diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index efd8af45dbd2..eb0c38b0b6fe 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -2153,6 +2153,41 @@ def identity(n, dtype=None): from numpy import eye return eye(n, dtype=dtype) +def _allclose_points(a, b, rtol=1.e-5, atol=1.e-8): + """ + This is the point-wise inner calculation of 'allclose', which is subtly + different from 'isclose'. Provided as a comparison routine for use in + testing.assert_allclose. + See those routines for further details. + + """ + x = array(a, copy=False, ndmin=1) + y = array(b, copy=False, ndmin=1) + + # make sure y is an inexact type to avoid abs(MIN_INT); will cause + # casting of x later. + dtype = multiarray.result_type(y, 1.) + y = array(y, dtype=dtype, copy=False) + + xinf = isinf(x) + yinf = isinf(y) + if any(xinf) or any(yinf): + # Check that x and y have inf's only in the same positions + if not all(xinf == yinf): + return False + # Check that sign of inf's in x and y is the same + if not all(x[xinf] == y[xinf]): + return False + + x = x[~xinf] + y = y[~xinf] + + # ignore invalid fpe's + with errstate(invalid='ignore'): + r = less_equal(abs(x - y), atol + rtol * abs(y)) + + return r + def allclose(a, b, rtol=1.e-5, atol=1.e-8): """ Returns True if two arrays are element-wise equal within a tolerance. @@ -2208,32 +2243,7 @@ def allclose(a, b, rtol=1.e-5, atol=1.e-8): False """ - x = array(a, copy=False, ndmin=1) - y = array(b, copy=False, ndmin=1) - - # make sure y is an inexact type to avoid abs(MIN_INT); will cause - # casting of x later. - dtype = multiarray.result_type(y, 1.) - y = array(y, dtype=dtype, copy=False) - - xinf = isinf(x) - yinf = isinf(y) - if any(xinf) or any(yinf): - # Check that x and y have inf's only in the same positions - if not all(xinf == yinf): - return False - # Check that sign of inf's in x and y is the same - if not all(x[xinf] == y[xinf]): - return False - - x = x[~xinf] - y = y[~xinf] - - # ignore invalid fpe's - with errstate(invalid='ignore'): - r = all(less_equal(abs(x - y), atol + rtol * abs(y))) - - return r + return all(_allclose_points(a, b, rtol=rtol, atol=atol)) def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False): """ diff --git a/numpy/testing/tests/test_utils.py b/numpy/testing/tests/test_utils.py index aa0a2669fd7d..5189f7e633f4 100644 --- a/numpy/testing/tests/test_utils.py +++ b/numpy/testing/tests/test_utils.py @@ -449,6 +449,15 @@ def test_min_int(self): # Should not raise: assert_allclose(a, a) + def test_report_fail_percentage(self): + a = np.array([1, 1, 1, 1]) + b = np.array([1, 1, 1, 2]) + try: + assert_allclose(a, b) + msg = '' + except AssertionError as exc: + msg = exc.args[0] + self.assertTrue("mismatch 25.0%" in msg) class TestArrayAlmostEqualNulp(unittest.TestCase): @dec.knownfailureif(True, "Github issue #347") diff --git a/numpy/testing/utils.py b/numpy/testing/utils.py index bd184d922041..71c7145f9c51 100644 --- a/numpy/testing/utils.py +++ b/numpy/testing/utils.py @@ -1289,7 +1289,7 @@ def assert_allclose(actual, desired, rtol=1e-7, atol=0, """ import numpy as np def compare(x, y): - return np.allclose(x, y, rtol=rtol, atol=atol) + return np.core.numeric._allclose_points(x, y, rtol=rtol, atol=atol) actual, desired = np.asanyarray(actual), np.asanyarray(desired) header = 'Not equal to tolerance rtol=%g, atol=%g' % (rtol, atol)