[Jython-checkins] jython: Fix float.__mod__ to conform to spec.
jeff.allen
jython-checkins at python.org
Wed Dec 31 02:41:07 CET 2014
https://hg.python.org/jython/rev/2472ea52bc76
changeset: 7479:2472ea52bc76
user: Jeff Allen <ja.py at farowl.co.uk>
date: Wed Dec 17 21:24:56 2014 +0000
summary:
Fix float.__mod__ to conform to spec.
Fixes test failures in test_float by re-implementing using Java % and tweaks.
files:
Lib/test/test_float.py | 9 ++---
src/org/python/core/PyFloat.java | 32 +++++++++++++++-----
2 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py
--- a/Lib/test/test_float.py
+++ b/Lib/test/test_float.py
@@ -217,10 +217,9 @@
# In particular, check signs of zeros.
mod = operator.mod
- #FIXME: Jython fails some mod edge cases.
- #self.assertEqualAndEqualSign(mod(-1.0, 1.0), 0.0)
+ self.assertEqualAndEqualSign(mod(-1.0, 1.0), 0.0)
self.assertEqualAndEqualSign(mod(-1e-100, 1.0), 1.0)
- #self.assertEqualAndEqualSign(mod(-0.0, 1.0), 0.0)
+ self.assertEqualAndEqualSign(mod(-0.0, 1.0), 0.0)
self.assertEqualAndEqualSign(mod(0.0, 1.0), 0.0)
self.assertEqualAndEqualSign(mod(1e-100, 1.0), 1e-100)
self.assertEqualAndEqualSign(mod(1.0, 1.0), 0.0)
@@ -228,9 +227,9 @@
self.assertEqualAndEqualSign(mod(-1.0, -1.0), -0.0)
self.assertEqualAndEqualSign(mod(-1e-100, -1.0), -1e-100)
self.assertEqualAndEqualSign(mod(-0.0, -1.0), -0.0)
- #self.assertEqualAndEqualSign(mod(0.0, -1.0), -0.0)
+ self.assertEqualAndEqualSign(mod(0.0, -1.0), -0.0)
self.assertEqualAndEqualSign(mod(1e-100, -1.0), -1.0)
- #self.assertEqualAndEqualSign(mod(1.0, -1.0), -0.0)
+ self.assertEqualAndEqualSign(mod(1.0, -1.0), -0.0)
@requires_IEEE_754
def test_float_pow(self):
diff --git a/src/org/python/core/PyFloat.java b/src/org/python/core/PyFloat.java
--- a/src/org/python/core/PyFloat.java
+++ b/src/org/python/core/PyFloat.java
@@ -625,15 +625,30 @@
return new PyFloat(leftv / getValue());
}
+ /**
+ * Python % operator: y = n*x + z. The modulo operator always yields a result with the same sign
+ * as its second operand (or zero). (Compare <code>java.Math.IEEEremainder</code>)
+ *
+ * @param x dividend
+ * @param y divisor
+ * @return <code>x % y</code>
+ */
private static double modulo(double x, double y) {
- if (y == 0) {
+ if (y == 0.0) {
throw Py.ZeroDivisionError("float modulo");
+ } else {
+ double z = x % y;
+ if (z == 0.0) {
+ // Has to be same sign as y (even when zero).
+ return Math.copySign(z, y);
+ } else if ((z > 0.0) == (y > 0.0)) {
+ // z has same sign as y, as it must.
+ return z;
+ } else {
+ // Note abs(z) < abs(y) and opposite sign.
+ return z + y;
+ }
}
- double z = Math.IEEEremainder(x, y);
- if (z * y < 0) {
- z += y;
- }
- return z;
}
@Override
@@ -934,8 +949,9 @@
}
/**
- * Common code for PyFloat, {@link PyInteger} and {@link PyLong} to prepare a {@link FloatFormatter} from a parsed specification.
- * The object returned has format method {@link FloatFormatter#format(double)}.
+ * Common code for PyFloat, {@link PyInteger} and {@link PyLong} to prepare a
+ * {@link FloatFormatter} from a parsed specification. The object returned has format method
+ * {@link FloatFormatter#format(double)}.
*
* @param spec a parsed PEP-3101 format specification.
* @return a formatter ready to use, or null if the type is not a floating point format type.
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list