diff options
Diffstat (limited to 'numpy/core/tests/test_scalarmath.py')
-rw-r--r-- | numpy/core/tests/test_scalarmath.py | 82 |
1 files changed, 60 insertions, 22 deletions
diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py index e3dc52c48..c737099c1 100644 --- a/numpy/core/tests/test_scalarmath.py +++ b/numpy/core/tests/test_scalarmath.py @@ -4,7 +4,7 @@ import warnings import itertools import operator import platform -from numpy.compat import _pep440 +from numpy._utils import _pep440 import pytest from hypothesis import given, settings from hypothesis.strategies import sampled_from @@ -14,7 +14,7 @@ import numpy as np from numpy.testing import ( assert_, assert_equal, assert_raises, assert_almost_equal, assert_array_equal, IS_PYPY, suppress_warnings, _gen_alignment_data, - assert_warns, + assert_warns, _SUPPORTS_SVE, ) types = [np.bool_, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, @@ -75,17 +75,7 @@ class TestTypes: np.add(1, 1) -@pytest.mark.slow -@settings(max_examples=10000, deadline=2000) -@given(sampled_from(reasonable_operators_for_scalars), - hynp.arrays(dtype=hynp.scalar_dtypes(), shape=()), - hynp.arrays(dtype=hynp.scalar_dtypes(), shape=())) -def test_array_scalar_ufunc_equivalence(op, arr1, arr2): - """ - This is a thorough test attempting to cover important promotion paths - and ensuring that arrays and scalars stay as aligned as possible. - However, if it creates troubles, it should maybe just be removed. - """ +def check_ufunc_scalar_equivalence(op, arr1, arr2): scalar1 = arr1[()] scalar2 = arr2[()] assert isinstance(scalar1, np.generic) @@ -95,6 +85,11 @@ def test_array_scalar_ufunc_equivalence(op, arr1, arr2): comp_ops = {operator.ge, operator.gt, operator.le, operator.lt} if op in comp_ops and (np.isnan(scalar1) or np.isnan(scalar2)): pytest.xfail("complex comp ufuncs use sort-order, scalars do not.") + if op == operator.pow and arr2.item() in [-1, 0, 0.5, 1, 2]: + # array**scalar special case can have different result dtype + # (Other powers may have issues also, but are not hit here.) + # TODO: It would be nice to resolve this issue. + pytest.skip("array**2 can have incorrect/weird result dtype") # ignore fpe's since they may just mismatch for integers anyway. with warnings.catch_warnings(), np.errstate(all="ignore"): @@ -107,10 +102,51 @@ def test_array_scalar_ufunc_equivalence(op, arr1, arr2): op(scalar1, scalar2) else: scalar_res = op(scalar1, scalar2) - assert_array_equal(scalar_res, res) + assert_array_equal(scalar_res, res, strict=True) + + +@pytest.mark.slow +@settings(max_examples=10000, deadline=2000) +@given(sampled_from(reasonable_operators_for_scalars), + hynp.arrays(dtype=hynp.scalar_dtypes(), shape=()), + hynp.arrays(dtype=hynp.scalar_dtypes(), shape=())) +def test_array_scalar_ufunc_equivalence(op, arr1, arr2): + """ + This is a thorough test attempting to cover important promotion paths + and ensuring that arrays and scalars stay as aligned as possible. + However, if it creates troubles, it should maybe just be removed. + """ + check_ufunc_scalar_equivalence(op, arr1, arr2) + + +@pytest.mark.slow +@given(sampled_from(reasonable_operators_for_scalars), + hynp.scalar_dtypes(), hynp.scalar_dtypes()) +def test_array_scalar_ufunc_dtypes(op, dt1, dt2): + # Same as above, but don't worry about sampling weird values so that we + # do not have to sample as much + arr1 = np.array(2, dtype=dt1) + arr2 = np.array(3, dtype=dt2) # some power do weird things. + + check_ufunc_scalar_equivalence(op, arr1, arr2) + + +@pytest.mark.parametrize("fscalar", [np.float16, np.float32]) +def test_int_float_promotion_truediv(fscalar): + # Promotion for mixed int and float32/float16 must not go to float64 + i = np.int8(1) + f = fscalar(1) + expected = np.result_type(i, f) + assert (i / f).dtype == expected + assert (f / i).dtype == expected + # But normal int / int true division goes to float64: + assert (i / i).dtype == np.dtype("float64") + # For int16, result has to be ast least float32 (takes ufunc path): + assert (np.int16(1) / f).dtype == np.dtype("float32") class TestBaseMath: + @pytest.mark.xfail(_SUPPORTS_SVE, reason="gh-22982") def test_blocked(self): # test alignments offsets for simd instructions # alignments for vz + 2 * (vs - 1) + 1 @@ -860,27 +896,29 @@ def test_operator_scalars(op, type1, type2): @pytest.mark.parametrize("op", reasonable_operators_for_scalars) -def test_longdouble_inf_loop(op): +@pytest.mark.parametrize("val", [None, 2**64]) +def test_longdouble_inf_loop(op, val): + # Note: The 2**64 value will pass once NEP 50 is adopted. try: - op(np.longdouble(3), None) + op(np.longdouble(3), val) except TypeError: pass try: - op(None, np.longdouble(3)) + op(val, np.longdouble(3)) except TypeError: pass @pytest.mark.parametrize("op", reasonable_operators_for_scalars) -def test_clongdouble_inf_loop(op): - if op in {operator.mod} and False: - pytest.xfail("The modulo operator is known to be broken") +@pytest.mark.parametrize("val", [None, 2**64]) +def test_clongdouble_inf_loop(op, val): + # Note: The 2**64 value will pass once NEP 50 is adopted. try: - op(np.clongdouble(3), None) + op(np.clongdouble(3), val) except TypeError: pass try: - op(None, np.longdouble(3)) + op(val, np.longdouble(3)) except TypeError: pass |