summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/tests/test_simd.py11
-rw-r--r--numpy/core/tests/test_umath.py127
2 files changed, 107 insertions, 31 deletions
diff --git a/numpy/core/tests/test_simd.py b/numpy/core/tests/test_simd.py
index 3be28c3bb..ea5bbe103 100644
--- a/numpy/core/tests/test_simd.py
+++ b/numpy/core/tests/test_simd.py
@@ -1,6 +1,7 @@
# NOTE: Please avoid the use of numpy.testing since NPYV intrinsics
# may be involved in their functionality.
import pytest, math, re
+import itertools
from numpy.core._simd import targets
from numpy.core._multiarray_umath import __cpu_baseline__
@@ -820,8 +821,10 @@ class _SIMD_ALL(_Test_Utility):
def trunc_div(a, d):
"""
Divide towards zero works with large integers > 2^53,
- equivalent to int(a/d)
+ and wrap around overflow similar to what C does.
"""
+ if d == -1 and a == int_min:
+ return a
sign_a, sign_d = a < 0, d < 0
if a == 0 or sign_a == sign_d:
return a // d
@@ -833,9 +836,9 @@ class _SIMD_ALL(_Test_Utility):
0, 1, self.nlanes, int_max-self.nlanes,
int_min, int_min//2 + 1
)
- divisors = (1, 2, self.nlanes, int_min, int_max, int_max//2)
+ divisors = (1, 2, 9, 13, self.nlanes, int_min, int_max, int_max//2)
- for x, d in zip(rdata, divisors):
+ for x, d in itertools.product(rdata, divisors):
data = self._data(x)
vdata = self.load(data)
data_divc = [trunc_div(a, d) for a in data]
@@ -848,7 +851,7 @@ class _SIMD_ALL(_Test_Utility):
safe_neg = lambda x: -x-1 if -x > int_max else -x
# test round divison for signed integers
- for x, d in zip(rdata, divisors):
+ for x, d in itertools.product(rdata, divisors):
d_neg = safe_neg(d)
data = self._data(x)
data_neg = [safe_neg(a) for a in data]
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index 345aeb6c0..9d1b13b53 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -5,6 +5,7 @@ import itertools
import pytest
import sys
from fractions import Fraction
+from functools import reduce
import numpy.core.umath as ncu
from numpy.core import _umath_tests as ncu_tests
@@ -249,43 +250,115 @@ class TestDivision:
assert_equal(x // 100, [0, 0, 0, 1, -1, -1, -1, -1, -2])
assert_equal(x % 100, [5, 10, 90, 0, 95, 90, 10, 0, 80])
- @pytest.mark.parametrize("input_dtype",
- np.sctypes['int'] + np.sctypes['uint'])
- def test_division_int_boundary(self, input_dtype):
- iinfo = np.iinfo(input_dtype)
-
- # Unsigned:
- # Create list with 0, 25th, 50th, 75th percentile and max
- if iinfo.min == 0:
- lst = [0, iinfo.max//4, iinfo.max//2,
- int(iinfo.max/1.33), iinfo.max]
- divisors = [iinfo.max//4, iinfo.max//2,
- int(iinfo.max/1.33), iinfo.max]
- # Signed:
- # Create list with min, 25th percentile, 0, 75th percentile, max
- else:
- lst = [iinfo.min, iinfo.min//2, 0, iinfo.max//2, iinfo.max]
- divisors = [iinfo.min, iinfo.min//2, iinfo.max//2, iinfo.max]
- a = np.array(lst, dtype=input_dtype)
+ @pytest.mark.parametrize("dtype,ex_val", itertools.product(
+ np.sctypes['int'] + np.sctypes['uint'], (
+ (
+ # dividend
+ "np.arange(fo.max-lsize, fo.max, dtype=dtype),"
+ # divisors
+ "np.arange(lsize, dtype=dtype),"
+ # scalar divisors
+ "range(15)"
+ ),
+ (
+ # dividend
+ "np.arange(fo.min, fo.min+lsize, dtype=dtype),"
+ # divisors
+ "np.arange(lsize//-2, lsize//2, dtype=dtype),"
+ # scalar divisors
+ "range(fo.min, fo.min + 15)"
+ ), (
+ # dividend
+ "np.arange(fo.max-lsize, fo.max, dtype=dtype),"
+ # divisors
+ "np.arange(lsize, dtype=dtype),"
+ # scalar divisors
+ "[1,3,9,13,neg, fo.min+1, fo.min//2, fo.max//3, fo.max//4]"
+ )
+ )
+ ))
+ def test_division_int_boundary(self, dtype, ex_val):
+ fo = np.iinfo(dtype)
+ neg = -1 if fo.min < 0 else 1
+ # Large enough to test SIMD loops and remaind elements
+ lsize = 512 + 7
+ a, b, divisors = eval(ex_val)
+ a_lst, b_lst = a.tolist(), b.tolist()
+
+ c_div = lambda n, d: (
+ 0 if d == 0 or (n and n == fo.min and d == -1) else n//d
+ )
+ with np.errstate(divide='ignore'):
+ ac = a.copy()
+ ac //= b
+ div_ab = a // b
+ div_lst = [c_div(x, y) for x, y in zip(a_lst, b_lst)]
+
+ msg = "Integer arrays floor division check (//)"
+ assert all(div_ab == div_lst), msg
+ msg_eq = "Integer arrays floor division check (//=)"
+ assert all(ac == div_lst), msg_eq
for divisor in divisors:
- div_a = a // divisor
- b = a.copy(); b //= divisor
- div_lst = [i // divisor for i in lst]
+ ac = a.copy()
+ with np.errstate(divide='ignore'):
+ div_a = a // divisor
+ ac //= divisor
+ div_lst = [c_div(i, divisor) for i in a_lst]
- msg = "Integer arrays floor division check (//)"
assert all(div_a == div_lst), msg
-
- msg = "Integer arrays floor division check (//=)"
- assert all(div_a == b), msg
+ assert all(ac == div_lst), msg_eq
with np.errstate(divide='raise'):
+ if 0 in b or (fo.min and -1 in b and fo.min in a):
+ # Verify overflow case
+ with pytest.raises(FloatingPointError):
+ a // b
+ else:
+ a // b
+ if fo.min and fo.min in a:
+ with pytest.raises(FloatingPointError):
+ a // -1
+ elif fo.min:
+ a // -1
with pytest.raises(FloatingPointError):
a // 0
with pytest.raises(FloatingPointError):
- a //= 0
+ ac = a.copy()
+ ac //= 0
+
+ np.array([], dtype=dtype) // 0
+
+ @pytest.mark.parametrize("dtype,ex_val", itertools.product(
+ np.sctypes['int'] + np.sctypes['uint'], (
+ "np.array([fo.max, 1, 2, 1, 1, 2, 3], dtype=dtype)",
+ "np.array([fo.min, 1, -2, 1, 1, 2, -3], dtype=dtype)",
+ "np.arange(fo.min, fo.min+(100*10), 10, dtype=dtype)",
+ "np.arange(fo.max-(100*7), fo.max, 7, dtype=dtype)",
+ )
+ ))
+ def test_division_int_reduce(self, dtype, ex_val):
+ fo = np.iinfo(dtype)
+ a = eval(ex_val)
+ lst = a.tolist()
+ c_div = lambda n, d: (
+ 0 if d == 0 or (n and n == fo.min and d == -1) else n//d
+ )
+
+ with np.errstate(divide='ignore'):
+ div_a = np.floor_divide.reduce(a)
+ div_lst = reduce(c_div, lst)
+ msg = "Reduce floor integer division check"
+ assert div_a == div_lst, msg
- np.array([], dtype=input_dtype) // 0
+ with np.errstate(divide='raise'):
+ with pytest.raises(FloatingPointError):
+ np.floor_divide.reduce(np.arange(-100, 100, dtype=dtype))
+ if fo.min:
+ with pytest.raises(FloatingPointError):
+ np.floor_divide.reduce(
+ np.array([fo.min, 1, -1], dtype=dtype)
+ )
@pytest.mark.parametrize(
"dividend,divisor,quotient",