Author: Armin Rigo <[email protected]>
Branch: py3.5
Changeset: r87096:0523f9c54a03
Date: 2016-09-13 20:19 +0200
http://bitbucket.org/pypy/pypy/changeset/0523f9c54a03/

Log:    math.isclose()

diff --git a/pypy/module/math/__init__.py b/pypy/module/math/__init__.py
--- a/pypy/module/math/__init__.py
+++ b/pypy/module/math/__init__.py
@@ -52,5 +52,6 @@
        'erfc'           : 'interp_math.erfc',
        'gamma'          : 'interp_math.gamma',
        'lgamma'         : 'interp_math.lgamma',
+       'isclose'        : 'interp_math.isclose',
 }
 
diff --git a/pypy/module/math/interp_math.py b/pypy/module/math/interp_math.py
--- a/pypy/module/math/interp_math.py
+++ b/pypy/module/math/interp_math.py
@@ -3,6 +3,7 @@
 
 from rpython.rlib import rfloat
 from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
 
 class State:
     def __init__(self, space):
@@ -424,3 +425,53 @@
     """Compute the natural logarithm of the gamma function for x."""
     return math1(space, rfloat.lgamma, w_x)
 
+@unwrap_spec(w_rel_tol=WrappedDefault(1e-09), w_abs_tol=WrappedDefault(0.0))
+def isclose(space, w_a, w_b, __kwonly__, w_rel_tol, w_abs_tol):
+    """isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0) -> bool
+
+Determine whether two floating point numbers are close in value.
+
+   rel_tol
+       maximum difference for being considered "close", relative to the
+       magnitude of the input values
+   abs_tol
+       maximum difference for being considered "close", regardless of the
+       magnitude of the input values
+
+Return True if a is close in value to b, and False otherwise.
+
+For the values to be considered close, the difference between them
+must be smaller than at least one of the tolerances.
+
+-inf, inf and NaN behave similarly to the IEEE 754 Standard.  That
+is, NaN is not close to anything, even itself.  inf and -inf are
+only close to themselves."""
+    a = _get_double(space, w_a)
+    b = _get_double(space, w_b)
+    rel_tol = _get_double(space, w_rel_tol)
+    abs_tol = _get_double(space, w_abs_tol)
+    #
+    # sanity check on the inputs
+    if rel_tol < 0.0 or abs_tol < 0.0:
+        raise oefmt(space.w_ValueError, "tolerances must be non-negative")
+    #
+    # short circuit exact equality -- needed to catch two infinities of
+    # the same sign. And perhaps speeds things up a bit sometimes.
+    if a == b:
+        return space.w_True
+    #
+    # This catches the case of two infinities of opposite sign, or
+    # one infinity and one finite number. Two infinities of opposite
+    # sign would otherwise have an infinite relative tolerance.
+    # Two infinities of the same sign are caught by the equality check
+    # above.
+    if rfloat.isinf(a) or rfloat.isinf(b):
+        return space.w_False
+    #
+    # now do the regular computation
+    # this is essentially the "weak" test from the Boost library
+    diff = math.fabs(b - a)
+    result = ((diff <= math.fabs(rel_tol * b) or
+               diff <= math.fabs(rel_tol * a)) or
+              diff <= abs_tol)
+    return space.newbool(result)
diff --git a/pypy/module/math/test/test_math.py 
b/pypy/module/math/test/test_math.py
--- a/pypy/module/math/test/test_math.py
+++ b/pypy/module/math/test/test_math.py
@@ -343,3 +343,23 @@
         assert round(math.lgamma(6.0), 9) == round(math.log(120.0), 9)
         assert raises(ValueError, math.gamma, -1)
         assert round(math.lgamma(0.5), 9) == round(math.log(math.pi ** 0.5), 9)
+
+    def test_isclose(self):
+        import math
+        assert math.isclose(0, 1) is False
+        assert math.isclose(0, 0.0) is True
+        assert math.isclose(1000.1, 1000.2, abs_tol=0.2) is True
+        assert math.isclose(1000.1, 1000.2, rel_tol=1e-3) is True
+        assert math.isclose(1000.1, 1000.2, abs_tol=0.02) is False
+        assert math.isclose(1000.1, 1000.2, rel_tol=1e-5) is False
+        assert math.isclose(float("inf"), float("inf")) is True
+        assert math.isclose(float("-inf"), float("-inf")) is True
+        assert math.isclose(float("inf"), float("-inf")) is False
+        assert math.isclose(float("-inf"), float("inf")) is False
+        assert math.isclose(float("-inf"), 12.34) is False
+        assert math.isclose(float("-inf"), float("nan")) is False
+        assert math.isclose(float("nan"), 12.34) is False
+        assert math.isclose(float("nan"), float("nan")) is False
+        #
+        raises(TypeError, math.isclose, 0, 1, rel_tol=None)
+        raises(TypeError, math.isclose, 0, 1, abs_tol=None)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to