[Python-modules-commits] [python-numpy] 01/04: BUG: Don't signal FP exceptions in np.absolute

Sandro Tosi morph at moszumanska.debian.org
Sun May 28 02:21:27 UTC 2017


This is an automated email from the git hooks/post-receive script.

morph pushed a commit to branch master
in repository python-numpy.

commit 285b463e037cd9aeaf37ccc90ccf3349cc84b88a
Author: James Cowgill <james410 at cowgill.org.uk>
Date:   Tue Mar 7 11:39:01 2017 +0000

    BUG: Don't signal FP exceptions in np.absolute
    
    Fixes #8686
    
    This PR centers around this piece of code in `numpy/core/src/umath/loops.c.src`:
    ```c
    UNARY_LOOP {
        const @type@ in1 = *(@type@ *)ip1;
        const @type@ tmp = in1 > 0 ? in1 : -in1;
        /* add 0 to clear -0.0 */
        *((@type@ *)op1) = tmp + 0;
    }
    ```
    
    If in1 is `NaN`, the C99 standard requires that the comparison `in1 > 0`
    signals `FE_INVALID`, but the usual semantics for the absolute function are
    that no FP exceptions should be generated (eg compare to C `fabs` and Python
    `abs`). This was probably never noticed due to a bug in GCC x86 where all
    floating point comparisons do not signal exceptions, however Clang on x86 and
    GCC on other architectures (including ARM and MIPS) do signal an FP exception
    here.
    
    Fix by clearing the floating point exceptions after the loop has
    finished. The alternative of rewriting the loop to use `npy_fabs`
    instead would also work but has performance issues because that function
    is not inlined. The `test_abs_neg_blocked` is adjusted not to ignore
    `FE_INVALID` errors because now both absolute and negate should never
    produce an FP exceptions.
---
 numpy/core/src/umath/loops.c.src |  1 +
 numpy/core/tests/test_umath.py   | 30 ++++++++++++++----------------
 2 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src
index 3c11908..7e683ab 100644
--- a/numpy/core/src/umath/loops.c.src
+++ b/numpy/core/src/umath/loops.c.src
@@ -1840,6 +1840,7 @@ NPY_NO_EXPORT void
             *((@type@ *)op1) = tmp + 0;
         }
     }
+    npy_clear_floatstatus();
 }
 
 NPY_NO_EXPORT void
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index 6fea832..fad75cd 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -1226,22 +1226,20 @@ class TestAbsoluteNegative(TestCase):
                 np.negative(inp, out=out)
                 assert_equal(out, tgt, err_msg=msg)
 
-                # will throw invalid flag depending on compiler optimizations
-                with np.errstate(invalid='ignore'):
-                    for v in [np.nan, -np.inf, np.inf]:
-                        for i in range(inp.size):
-                            d = np.arange(inp.size, dtype=dt)
-                            inp[:] = -d
-                            inp[i] = v
-                            d[i] = -v if v == -np.inf else v
-                            assert_array_equal(np.abs(inp), d, err_msg=msg)
-                            np.abs(inp, out=out)
-                            assert_array_equal(out, d, err_msg=msg)
-
-                            assert_array_equal(-inp, -1*inp, err_msg=msg)
-                            d = -1 * inp
-                            np.negative(inp, out=out)
-                            assert_array_equal(out, d, err_msg=msg)
+                for v in [np.nan, -np.inf, np.inf]:
+                    for i in range(inp.size):
+                        d = np.arange(inp.size, dtype=dt)
+                        inp[:] = -d
+                        inp[i] = v
+                        d[i] = -v if v == -np.inf else v
+                        assert_array_equal(np.abs(inp), d, err_msg=msg)
+                        np.abs(inp, out=out)
+                        assert_array_equal(out, d, err_msg=msg)
+
+                        assert_array_equal(-inp, -1*inp, err_msg=msg)
+                        d = -1 * inp
+                        np.negative(inp, out=out)
+                        assert_array_equal(out, d, err_msg=msg)
 
     def test_lower_align(self):
         # check data that is not aligned to element size

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-numpy.git



More information about the Python-modules-commits mailing list