summaryrefslogtreecommitdiff
path: root/numpy/core/tests
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core/tests')
-rw-r--r--numpy/core/tests/test_api.py14
-rw-r--r--numpy/core/tests/test_argparse.py4
-rw-r--r--numpy/core/tests/test_array_coercion.py61
-rw-r--r--numpy/core/tests/test_arraymethod.py8
-rw-r--r--numpy/core/tests/test_arrayprint.py84
-rw-r--r--numpy/core/tests/test_cpu_features.py226
-rw-r--r--numpy/core/tests/test_custom_dtypes.py52
-rw-r--r--numpy/core/tests/test_datetime.py55
-rw-r--r--numpy/core/tests/test_defchararray.py88
-rw-r--r--numpy/core/tests/test_deprecations.py409
-rw-r--r--numpy/core/tests/test_dlpack.py3
-rw-r--r--numpy/core/tests/test_dtype.py88
-rw-r--r--numpy/core/tests/test_einsum.py143
-rw-r--r--numpy/core/tests/test_function_base.py37
-rw-r--r--numpy/core/tests/test_getlimits.py60
-rw-r--r--numpy/core/tests/test_indexing.py2
-rw-r--r--numpy/core/tests/test_item_selection.py79
-rw-r--r--numpy/core/tests/test_longdouble.py53
-rw-r--r--numpy/core/tests/test_mem_overlap.py2
-rw-r--r--numpy/core/tests/test_mem_policy.py1
-rw-r--r--numpy/core/tests/test_memmap.py4
-rw-r--r--numpy/core/tests/test_multiarray.py314
-rw-r--r--numpy/core/tests/test_nditer.py34
-rw-r--r--numpy/core/tests/test_nep50_promotions.py54
-rw-r--r--numpy/core/tests/test_numeric.py69
-rw-r--r--numpy/core/tests/test_numerictypes.py20
-rw-r--r--numpy/core/tests/test_overrides.py153
-rw-r--r--numpy/core/tests/test_print.py4
-rw-r--r--numpy/core/tests/test_regression.py57
-rw-r--r--numpy/core/tests/test_scalar_methods.py14
-rw-r--r--numpy/core/tests/test_scalarbuffer.py4
-rw-r--r--numpy/core/tests/test_scalarinherit.py8
-rw-r--r--numpy/core/tests/test_scalarmath.py80
-rw-r--r--numpy/core/tests/test_scalarprint.py6
-rw-r--r--numpy/core/tests/test_shape_base.py15
-rw-r--r--numpy/core/tests/test_simd.py354
-rw-r--r--numpy/core/tests/test_strings.py14
-rw-r--r--numpy/core/tests/test_ufunc.py217
-rw-r--r--numpy/core/tests/test_umath.py409
39 files changed, 2400 insertions, 899 deletions
diff --git a/numpy/core/tests/test_api.py b/numpy/core/tests/test_api.py
index 5006e77f2..b9f2f8ae9 100644
--- a/numpy/core/tests/test_api.py
+++ b/numpy/core/tests/test_api.py
@@ -102,6 +102,16 @@ def test_array_array():
assert_raises(ValueError, np.array, [nested], dtype=np.float64)
# Try with lists...
+ # float32
+ assert_equal(np.array([None] * 10, dtype=np.float32),
+ np.full((10,), np.nan, dtype=np.float32))
+ assert_equal(np.array([[None]] * 10, dtype=np.float32),
+ np.full((10, 1), np.nan, dtype=np.float32))
+ assert_equal(np.array([[None] * 10], dtype=np.float32),
+ np.full((1, 10), np.nan, dtype=np.float32))
+ assert_equal(np.array([[None] * 10] * 10, dtype=np.float32),
+ np.full((10, 10), np.nan, dtype=np.float32))
+ # float64
assert_equal(np.array([None] * 10, dtype=np.float64),
np.full((10,), np.nan, dtype=np.float64))
assert_equal(np.array([[None]] * 10, dtype=np.float64),
@@ -310,7 +320,7 @@ def test_array_astype_warning(t):
@pytest.mark.parametrize(["dtype", "out_dtype"],
[(np.bytes_, np.bool_),
- (np.unicode_, np.bool_),
+ (np.str_, np.bool_),
(np.dtype("S10,S9"), np.dtype("?,?"))])
def test_string_to_boolean_cast(dtype, out_dtype):
"""
@@ -324,7 +334,7 @@ def test_string_to_boolean_cast(dtype, out_dtype):
@pytest.mark.parametrize(["dtype", "out_dtype"],
[(np.bytes_, np.bool_),
- (np.unicode_, np.bool_),
+ (np.str_, np.bool_),
(np.dtype("S10,S9"), np.dtype("?,?"))])
def test_string_to_boolean_cast_errors(dtype, out_dtype):
"""
diff --git a/numpy/core/tests/test_argparse.py b/numpy/core/tests/test_argparse.py
index 63a01dee4..fae227027 100644
--- a/numpy/core/tests/test_argparse.py
+++ b/numpy/core/tests/test_argparse.py
@@ -53,8 +53,8 @@ def test_multiple_values():
def test_string_fallbacks():
# We can (currently?) use numpy strings to test the "slow" fallbacks
# that should normally not be taken due to string interning.
- arg2 = np.unicode_("arg2")
- missing_arg = np.unicode_("missing_arg")
+ arg2 = np.str_("arg2")
+ missing_arg = np.str_("missing_arg")
func(1, **{arg2: 3})
with pytest.raises(TypeError,
match="got an unexpected keyword argument 'missing_arg'"):
diff --git a/numpy/core/tests/test_array_coercion.py b/numpy/core/tests/test_array_coercion.py
index fade57292..d5373f642 100644
--- a/numpy/core/tests/test_array_coercion.py
+++ b/numpy/core/tests/test_array_coercion.py
@@ -1,6 +1,6 @@
"""
Tests for array coercion, mainly through testing `np.array` results directly.
-Note that other such tests exist e.g. in `test_api.py` and many corner-cases
+Note that other such tests exist, e.g., in `test_api.py` and many corner-cases
are tested (sometimes indirectly) elsewhere.
"""
@@ -20,8 +20,8 @@ from numpy.testing import (
def arraylikes():
"""
Generator for functions converting an array into various array-likes.
- If full is True (default) includes array-likes not capable of handling
- all dtypes
+ If full is True (default) it includes array-likes not capable of handling
+ all dtypes.
"""
# base array:
def ndarray(a):
@@ -39,9 +39,9 @@ def arraylikes():
yield subclass
class _SequenceLike():
- # We are giving a warning that array-like's were also expected to be
- # sequence-like in `np.array([array_like])`, this can be removed
- # when the deprecation exired (started NumPy 1.20)
+ # Older NumPy versions, sometimes cared whether a protocol array was
+ # also _SequenceLike. This shouldn't matter, but keep it for now
+ # for __array__ and not the others.
def __len__(self):
raise TypeError
@@ -62,7 +62,7 @@ def arraylikes():
yield param(memoryview, id="memoryview")
# Array-interface
- class ArrayInterface(_SequenceLike):
+ class ArrayInterface:
def __init__(self, a):
self.a = a # need to hold on to keep interface valid
self.__array_interface__ = a.__array_interface__
@@ -70,7 +70,7 @@ def arraylikes():
yield param(ArrayInterface, id="__array_interface__")
# Array-Struct
- class ArrayStruct(_SequenceLike):
+ class ArrayStruct:
def __init__(self, a):
self.a = a # need to hold on to keep struct valid
self.__array_struct__ = a.__array_struct__
@@ -130,7 +130,7 @@ def scalar_instances(times=True, extended_precision=True, user_dtype=True):
# Strings and unstructured void:
yield param(np.bytes_(b"1234"), id="bytes")
- yield param(np.unicode_("2345"), id="unicode")
+ yield param(np.str_("2345"), id="unicode")
yield param(np.void(b"4321"), id="unstructured_void")
@@ -161,8 +161,12 @@ class TestStringDiscovery:
# A nested array is also discovered correctly
arr = np.array(obj, dtype="O")
assert np.array(arr, dtype="S").dtype == expected
+ # Also if we use the dtype class
+ assert np.array(arr, dtype=type(expected)).dtype == expected
# Check that .astype() behaves identical
assert arr.astype("S").dtype == expected
+ # The DType class is accepted by `.astype()`
+ assert arr.astype(type(np.dtype("S"))).dtype == expected
@pytest.mark.parametrize("obj",
[object(), 1.2, 10**43, None, "string"],
@@ -257,7 +261,7 @@ class TestScalarDiscovery:
@pytest.mark.parametrize("scalar", scalar_instances())
def test_scalar_coercion(self, scalar):
# This tests various scalar coercion paths, mainly for the numerical
- # types. It includes some paths not directly related to `np.array`
+ # types. It includes some paths not directly related to `np.array`.
if isinstance(scalar, np.inexact):
# Ensure we have a full-precision number if available
scalar = type(scalar)((scalar * 2)**0.5)
@@ -292,7 +296,7 @@ class TestScalarDiscovery:
* `np.array(scalar, dtype=dtype)`
* `np.empty((), dtype=dtype)[()] = scalar`
* `np.array(scalar).astype(dtype)`
- should behave the same. The only exceptions are paramteric dtypes
+ should behave the same. The only exceptions are parametric dtypes
(mainly datetime/timedelta without unit) and void without fields.
"""
dtype = cast_to.dtype # use to parametrize only the target dtype
@@ -384,7 +388,7 @@ class TestScalarDiscovery:
"""
dtype = np.dtype(dtype)
- # This is a special case using casting logic. It warns for the NaN
+ # This is a special case using casting logic. It warns for the NaN
# but allows the cast (giving undefined behaviour).
with np.errstate(invalid="ignore"):
coerced = np.array(scalar, dtype=dtype)
@@ -650,6 +654,14 @@ class TestArrayLikes:
res = np.array([obj], dtype=object)
assert res[0] is obj
+ @pytest.mark.parametrize("arraylike", arraylikes())
+ @pytest.mark.parametrize("arr", [np.array(0.), np.arange(4)])
+ def test_object_assignment_special_case(self, arraylike, arr):
+ obj = arraylike(arr)
+ empty = np.arange(1, dtype=object)
+ empty[:] = [obj]
+ assert empty[0] is obj
+
def test_0d_generic_special_case(self):
class ArraySubclass(np.ndarray):
def __float__(self):
@@ -833,3 +845,28 @@ class TestSpecialAttributeLookupFailure:
np.array(self.WeirdArrayLike())
with pytest.raises(RuntimeError):
np.array(self.WeirdArrayInterface())
+
+
+def test_subarray_from_array_construction():
+ # Arrays are more complex, since they "broadcast" on success:
+ arr = np.array([1, 2])
+
+ res = arr.astype("(2)i,")
+ assert_array_equal(res, [[1, 1], [2, 2]])
+
+ res = np.array(arr, dtype="(2)i,")
+
+ assert_array_equal(res, [[1, 1], [2, 2]])
+
+ res = np.array([[(1,), (2,)], arr], dtype="(2)i,")
+ assert_array_equal(res, [[[1, 1], [2, 2]], [[1, 1], [2, 2]]])
+
+ # Also try a multi-dimensional example:
+ arr = np.arange(5 * 2).reshape(5, 2)
+ expected = np.broadcast_to(arr[:, :, np.newaxis, np.newaxis], (5, 2, 2, 2))
+
+ res = arr.astype("(2,2)f")
+ assert_array_equal(res, expected)
+
+ res = np.array(arr, dtype="(2,2)f")
+ assert_array_equal(res, expected)
diff --git a/numpy/core/tests/test_arraymethod.py b/numpy/core/tests/test_arraymethod.py
index 6b75d1921..4fd4d5558 100644
--- a/numpy/core/tests/test_arraymethod.py
+++ b/numpy/core/tests/test_arraymethod.py
@@ -64,7 +64,6 @@ class TestSimpleStridedCall:
self.method._simple_strided_call(*args)
-@pytest.mark.skipif(sys.version_info < (3, 9), reason="Requires python 3.9")
@pytest.mark.parametrize(
"cls", [np.ndarray, np.recarray, np.chararray, np.matrix, np.memmap]
)
@@ -84,10 +83,3 @@ class TestClassGetItem:
match = f"Too {'few' if arg_len == 0 else 'many'} arguments"
with pytest.raises(TypeError, match=match):
cls[arg_tup]
-
-
-@pytest.mark.skipif(sys.version_info >= (3, 9), reason="Requires python 3.8")
-def test_class_getitem_38() -> None:
- match = "Type subscription requires python >= 3.9"
- with pytest.raises(TypeError, match=match):
- np.ndarray[Any, Any]
diff --git a/numpy/core/tests/test_arrayprint.py b/numpy/core/tests/test_arrayprint.py
index f1883f703..6796b4077 100644
--- a/numpy/core/tests/test_arrayprint.py
+++ b/numpy/core/tests/test_arrayprint.py
@@ -9,6 +9,7 @@ from numpy.testing import (
assert_, assert_equal, assert_raises, assert_warns, HAS_REFCOUNT,
assert_raises_regex,
)
+from numpy.core.arrayprint import _typelessdata
import textwrap
class TestArrayRepr:
@@ -257,8 +258,7 @@ class TestArray2String:
assert_(np.array2string(s, formatter={'numpystr':lambda s: s*2}) ==
'[abcabc defdef]')
-
- def test_structure_format(self):
+ def test_structure_format_mixed(self):
dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])
x = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt)
assert_equal(np.array2string(x),
@@ -300,6 +300,7 @@ class TestArray2String:
( 'NaT',) ( 'NaT',) ( 'NaT',)]""")
)
+ def test_structure_format_int(self):
# See #8160
struct_int = np.array([([1, -1],), ([123, 1],)], dtype=[('B', 'i4', 2)])
assert_equal(np.array2string(struct_int),
@@ -309,6 +310,7 @@ class TestArray2String:
assert_equal(np.array2string(struct_2dint),
"[([[ 0, 1], [ 2, 3]],) ([[12, 0], [ 0, 0]],)]")
+ def test_structure_format_float(self):
# See #8172
array_scalar = np.array(
(1., 2.1234567890123456789, 3.), dtype=('f8,f8,f8'))
@@ -352,6 +354,33 @@ class TestArray2String:
' [ 501, 502, 503, ..., 999, 1000, 1001]])'
assert_equal(repr(A), reprA)
+ def test_summarize_structure(self):
+ A = (np.arange(2002, dtype="<i8").reshape(2, 1001)
+ .view([('i', "<i8", (1001,))]))
+ strA = ("[[([ 0, 1, 2, ..., 998, 999, 1000],)]\n"
+ " [([1001, 1002, 1003, ..., 1999, 2000, 2001],)]]")
+ assert_equal(str(A), strA)
+
+ reprA = ("array([[([ 0, 1, 2, ..., 998, 999, 1000],)],\n"
+ " [([1001, 1002, 1003, ..., 1999, 2000, 2001],)]],\n"
+ " dtype=[('i', '<i8', (1001,))])")
+ assert_equal(repr(A), reprA)
+
+ B = np.ones(2002, dtype=">i8").view([('i', ">i8", (2, 1001))])
+ strB = "[([[1, 1, 1, ..., 1, 1, 1], [1, 1, 1, ..., 1, 1, 1]],)]"
+ assert_equal(str(B), strB)
+
+ reprB = (
+ "array([([[1, 1, 1, ..., 1, 1, 1], [1, 1, 1, ..., 1, 1, 1]],)],\n"
+ " dtype=[('i', '>i8', (2, 1001))])"
+ )
+ assert_equal(repr(B), reprB)
+
+ C = (np.arange(22, dtype="<i8").reshape(2, 11)
+ .view([('i1', "<i8"), ('i10', "<i8", (10,))]))
+ strC = "[[( 0, [ 1, ..., 10])]\n [(11, [12, ..., 21])]]"
+ assert_equal(np.array2string(C, threshold=1, edgeitems=1), strC)
+
def test_linewidth(self):
a = np.full(6, 1)
@@ -796,6 +825,47 @@ class TestPrintOptions:
array(['1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'],
dtype='{}')""".format(styp)))
+ @pytest.mark.parametrize(
+ ['native'],
+ [
+ ('bool',),
+ ('uint8',),
+ ('uint16',),
+ ('uint32',),
+ ('uint64',),
+ ('int8',),
+ ('int16',),
+ ('int32',),
+ ('int64',),
+ ('float16',),
+ ('float32',),
+ ('float64',),
+ ('U1',), # 4-byte width string
+ ],
+ )
+ def test_dtype_endianness_repr(self, native):
+ '''
+ there was an issue where
+ repr(array([0], dtype='<u2')) and repr(array([0], dtype='>u2'))
+ both returned the same thing:
+ array([0], dtype=uint16)
+ even though their dtypes have different endianness.
+ '''
+ native_dtype = np.dtype(native)
+ non_native_dtype = native_dtype.newbyteorder()
+ non_native_repr = repr(np.array([1], non_native_dtype))
+ native_repr = repr(np.array([1], native_dtype))
+ # preserve the sensible default of only showing dtype if nonstandard
+ assert ('dtype' in native_repr) ^ (native_dtype in _typelessdata),\
+ ("an array's repr should show dtype if and only if the type "
+ 'of the array is NOT one of the standard types '
+ '(e.g., int32, bool, float64).')
+ if non_native_dtype.itemsize > 1:
+ # if the type is >1 byte, the non-native endian version
+ # must show endianness.
+ assert non_native_repr != native_repr
+ assert f"dtype='{non_native_dtype.byteorder}" in non_native_repr
+
def test_linewidth_repr(self):
a = np.full(7, fill_value=2)
np.set_printoptions(linewidth=17)
@@ -921,6 +991,16 @@ class TestPrintOptions:
[[ 0.]]]])""")
)
+ def test_edgeitems_structured(self):
+ np.set_printoptions(edgeitems=1, threshold=1)
+ A = np.arange(5*2*3, dtype="<i8").view([('i', "<i8", (5, 2, 3))])
+ reprA = (
+ "array([([[[ 0, ..., 2], [ 3, ..., 5]], ..., "
+ "[[24, ..., 26], [27, ..., 29]]],)],\n"
+ " dtype=[('i', '<i8', (5, 2, 3))])"
+ )
+ assert_equal(repr(A), reprA)
+
def test_bad_args(self):
assert_raises(ValueError, np.set_printoptions, threshold=float('nan'))
assert_raises(TypeError, np.set_printoptions, threshold='1')
diff --git a/numpy/core/tests/test_cpu_features.py b/numpy/core/tests/test_cpu_features.py
index 1a76897e2..2fad4dfd9 100644
--- a/numpy/core/tests/test_cpu_features.py
+++ b/numpy/core/tests/test_cpu_features.py
@@ -1,5 +1,14 @@
import sys, platform, re, pytest
-from numpy.core._multiarray_umath import __cpu_features__
+from numpy.core._multiarray_umath import (
+ __cpu_features__,
+ __cpu_baseline__,
+ __cpu_dispatch__,
+)
+import numpy as np
+import subprocess
+import pathlib
+import os
+import re
def assert_features_equal(actual, desired, fname):
__tracebackhide__ = True # Hide traceback for py.test
@@ -8,7 +17,7 @@ def assert_features_equal(actual, desired, fname):
return
detected = str(__cpu_features__).replace("'", "")
try:
- with open("/proc/cpuinfo", "r") as fd:
+ with open("/proc/cpuinfo") as fd:
cpuinfo = fd.read(2048)
except Exception as err:
cpuinfo = str(err)
@@ -48,6 +57,10 @@ def assert_features_equal(actual, desired, fname):
"%s"
) % (fname, actual, desired, error_report))
+def _text_to_list(txt):
+ out = txt.strip("][\n").replace("'", "").split(', ')
+ return None if out[0] == "" else out
+
class AbstractTest:
features = []
features_groups = {}
@@ -92,7 +105,6 @@ class AbstractTest:
return values
def load_flags_auxv(self):
- import subprocess
auxv = subprocess.check_output(['/bin/true'], env=dict(LD_SHOW_AUXV="1"))
for at in auxv.split(b'\n'):
if not at.startswith(b"AT_HWCAP"):
@@ -103,6 +115,208 @@ class AbstractTest:
hwcap_value[1].upper().decode().split()
)
+@pytest.mark.skipif(
+ sys.platform == 'emscripten',
+ reason= (
+ "The subprocess module is not available on WASM platforms and"
+ " therefore this test class cannot be properly executed."
+ ),
+)
+class TestEnvPrivation:
+ cwd = pathlib.Path(__file__).parent.resolve()
+ env = os.environ.copy()
+ _enable = os.environ.pop('NPY_ENABLE_CPU_FEATURES', None)
+ _disable = os.environ.pop('NPY_DISABLE_CPU_FEATURES', None)
+ SUBPROCESS_ARGS = dict(cwd=cwd, capture_output=True, text=True, check=True)
+ unavailable_feats = [
+ feat for feat in __cpu_dispatch__ if not __cpu_features__[feat]
+ ]
+ UNAVAILABLE_FEAT = (
+ None if len(unavailable_feats) == 0
+ else unavailable_feats[0]
+ )
+ BASELINE_FEAT = None if len(__cpu_baseline__) == 0 else __cpu_baseline__[0]
+ SCRIPT = """
+def main():
+ from numpy.core._multiarray_umath import __cpu_features__, __cpu_dispatch__
+
+ detected = [feat for feat in __cpu_dispatch__ if __cpu_features__[feat]]
+ print(detected)
+
+if __name__ == "__main__":
+ main()
+ """
+
+ @pytest.fixture(autouse=True)
+ def setup_class(self, tmp_path_factory):
+ file = tmp_path_factory.mktemp("runtime_test_script")
+ file /= "_runtime_detect.py"
+ file.write_text(self.SCRIPT)
+ self.file = file
+ return
+
+ def _run(self):
+ return subprocess.run(
+ [sys.executable, self.file],
+ env=self.env,
+ **self.SUBPROCESS_ARGS,
+ )
+
+ # Helper function mimicing pytest.raises for subprocess call
+ def _expect_error(
+ self,
+ msg,
+ err_type,
+ no_error_msg="Failed to generate error"
+ ):
+ try:
+ self._run()
+ except subprocess.CalledProcessError as e:
+ assertion_message = f"Expected: {msg}\nGot: {e.stderr}"
+ assert re.search(msg, e.stderr), assertion_message
+
+ assertion_message = (
+ f"Expected error of type: {err_type}; see full "
+ f"error:\n{e.stderr}"
+ )
+ assert re.search(err_type, e.stderr), assertion_message
+ else:
+ assert False, no_error_msg
+
+ def setup_method(self):
+ """Ensure that the environment is reset"""
+ self.env = os.environ.copy()
+ return
+
+ def test_runtime_feature_selection(self):
+ """
+ Ensure that when selecting `NPY_ENABLE_CPU_FEATURES`, only the
+ features exactly specified are dispatched.
+ """
+
+ # Capture runtime-enabled features
+ out = self._run()
+ non_baseline_features = _text_to_list(out.stdout)
+
+ if non_baseline_features is None:
+ pytest.skip(
+ "No dispatchable features outside of baseline detected."
+ )
+ feature = non_baseline_features[0]
+
+ # Capture runtime-enabled features when `NPY_ENABLE_CPU_FEATURES` is
+ # specified
+ self.env['NPY_ENABLE_CPU_FEATURES'] = feature
+ out = self._run()
+ enabled_features = _text_to_list(out.stdout)
+
+ # Ensure that only one feature is enabled, and it is exactly the one
+ # specified by `NPY_ENABLE_CPU_FEATURES`
+ assert set(enabled_features) == {feature}
+
+ if len(non_baseline_features) < 2:
+ pytest.skip("Only one non-baseline feature detected.")
+ # Capture runtime-enabled features when `NPY_ENABLE_CPU_FEATURES` is
+ # specified
+ self.env['NPY_ENABLE_CPU_FEATURES'] = ",".join(non_baseline_features)
+ out = self._run()
+ enabled_features = _text_to_list(out.stdout)
+
+ # Ensure that both features are enabled, and they are exactly the ones
+ # specified by `NPY_ENABLE_CPU_FEATURES`
+ assert set(enabled_features) == set(non_baseline_features)
+ return
+
+ @pytest.mark.parametrize("enabled, disabled",
+ [
+ ("feature", "feature"),
+ ("feature", "same"),
+ ])
+ def test_both_enable_disable_set(self, enabled, disabled):
+ """
+ Ensure that when both environment variables are set then an
+ ImportError is thrown
+ """
+ self.env['NPY_ENABLE_CPU_FEATURES'] = enabled
+ self.env['NPY_DISABLE_CPU_FEATURES'] = disabled
+ msg = "Both NPY_DISABLE_CPU_FEATURES and NPY_ENABLE_CPU_FEATURES"
+ err_type = "ImportError"
+ self._expect_error(msg, err_type)
+
+ @pytest.mark.skipif(
+ not __cpu_dispatch__,
+ reason=(
+ "NPY_*_CPU_FEATURES only parsed if "
+ "`__cpu_dispatch__` is non-empty"
+ )
+ )
+ @pytest.mark.parametrize("action", ["ENABLE", "DISABLE"])
+ def test_variable_too_long(self, action):
+ """
+ Test that an error is thrown if the environment variables are too long
+ to be processed. Current limit is 1024, but this may change later.
+ """
+ MAX_VAR_LENGTH = 1024
+ # Actual length is MAX_VAR_LENGTH + 1 due to null-termination
+ self.env[f'NPY_{action}_CPU_FEATURES'] = "t" * MAX_VAR_LENGTH
+ msg = (
+ f"Length of environment variable 'NPY_{action}_CPU_FEATURES' is "
+ f"{MAX_VAR_LENGTH + 1}, only {MAX_VAR_LENGTH} accepted"
+ )
+ err_type = "RuntimeError"
+ self._expect_error(msg, err_type)
+
+ @pytest.mark.skipif(
+ not __cpu_dispatch__,
+ reason=(
+ "NPY_*_CPU_FEATURES only parsed if "
+ "`__cpu_dispatch__` is non-empty"
+ )
+ )
+ def test_impossible_feature_disable(self):
+ """
+ Test that a RuntimeError is thrown if an impossible feature-disabling
+ request is made. This includes disabling a baseline feature.
+ """
+
+ if self.BASELINE_FEAT is None:
+ pytest.skip("There are no unavailable features to test with")
+ bad_feature = self.BASELINE_FEAT
+ self.env['NPY_DISABLE_CPU_FEATURES'] = bad_feature
+ msg = (
+ f"You cannot disable CPU feature '{bad_feature}', since it is "
+ "part of the baseline optimizations"
+ )
+ err_type = "RuntimeError"
+ self._expect_error(msg, err_type)
+
+ def test_impossible_feature_enable(self):
+ """
+ Test that a RuntimeError is thrown if an impossible feature-enabling
+ request is made. This includes enabling a feature not supported by the
+ machine, or disabling a baseline optimization.
+ """
+
+ if self.UNAVAILABLE_FEAT is None:
+ pytest.skip("There are no unavailable features to test with")
+ bad_feature = self.UNAVAILABLE_FEAT
+ self.env['NPY_ENABLE_CPU_FEATURES'] = bad_feature
+ msg = (
+ f"You cannot enable CPU features \\({bad_feature}\\), since "
+ "they are not supported by your machine."
+ )
+ err_type = "RuntimeError"
+ self._expect_error(msg, err_type)
+
+ # Ensure that only the bad feature gets reported
+ feats = f"{bad_feature}, {self.BASELINE_FEAT}"
+ self.env['NPY_ENABLE_CPU_FEATURES'] = feats
+ msg = (
+ f"You cannot enable CPU features \\({bad_feature}\\), since they "
+ "are not supported by your machine."
+ )
+ self._expect_error(msg, err_type)
+
is_linux = sys.platform.startswith('linux')
is_cygwin = sys.platform.startswith('cygwin')
machine = platform.machine()
@@ -116,7 +330,7 @@ class Test_X86_Features(AbstractTest):
"AVX", "F16C", "XOP", "FMA4", "FMA3", "AVX2", "AVX512F", "AVX512CD",
"AVX512ER", "AVX512PF", "AVX5124FMAPS", "AVX5124VNNIW", "AVX512VPOPCNTDQ",
"AVX512VL", "AVX512BW", "AVX512DQ", "AVX512VNNI", "AVX512IFMA",
- "AVX512VBMI", "AVX512VBMI2", "AVX512BITALG",
+ "AVX512VBMI", "AVX512VBMI2", "AVX512BITALG", "AVX512FP16",
]
features_groups = dict(
AVX512_KNL = ["AVX512F", "AVX512CD", "AVX512ER", "AVX512PF"],
@@ -128,6 +342,10 @@ class Test_X86_Features(AbstractTest):
"AVX512VBMI"],
AVX512_ICL = ["AVX512F", "AVX512CD", "AVX512BW", "AVX512DQ", "AVX512VL", "AVX512IFMA",
"AVX512VBMI", "AVX512VNNI", "AVX512VBMI2", "AVX512BITALG", "AVX512VPOPCNTDQ"],
+ AVX512_SPR = ["AVX512F", "AVX512CD", "AVX512BW", "AVX512DQ",
+ "AVX512VL", "AVX512IFMA", "AVX512VBMI", "AVX512VNNI",
+ "AVX512VBMI2", "AVX512BITALG", "AVX512VPOPCNTDQ",
+ "AVX512FP16"],
)
features_map = dict(
SSE3="PNI", SSE41="SSE4_1", SSE42="SSE4_2", FMA3="FMA",
diff --git a/numpy/core/tests/test_custom_dtypes.py b/numpy/core/tests/test_custom_dtypes.py
index 6bcc45d6b..da6a4bd50 100644
--- a/numpy/core/tests/test_custom_dtypes.py
+++ b/numpy/core/tests/test_custom_dtypes.py
@@ -45,6 +45,9 @@ class TestSFloat:
# Check the repr, mainly to cover the code paths:
assert repr(SF(scaling=1.)) == "_ScaledFloatTestDType(scaling=1.0)"
+ def test_dtype_name(self):
+ assert SF(1.).name == "_ScaledFloatTestDType64"
+
@pytest.mark.parametrize("scaling", [1., -1., 2.])
def test_sfloat_from_float(self, scaling):
a = np.array([1., 2., 3.]).astype(dtype=SF(scaling))
@@ -199,3 +202,52 @@ class TestSFloat:
# The output casting does not match the bool, bool -> bool loop:
with pytest.raises(TypeError):
ufunc(a, a, out=np.empty(a.shape, dtype=int), casting="equiv")
+
+ def test_wrapped_and_wrapped_reductions(self):
+ a = self._get_array(2.)
+ float_equiv = a.astype(float)
+
+ expected = np.hypot(float_equiv, float_equiv)
+ res = np.hypot(a, a)
+ assert res.dtype == a.dtype
+ res_float = res.view(np.float64) * 2
+ assert_array_equal(res_float, expected)
+
+ # Also check reduction (keepdims, due to incorrect getitem)
+ res = np.hypot.reduce(a, keepdims=True)
+ assert res.dtype == a.dtype
+ expected = np.hypot.reduce(float_equiv, keepdims=True)
+ assert res.view(np.float64) * 2 == expected
+
+ def test_astype_class(self):
+ # Very simple test that we accept `.astype()` also on the class.
+ # ScaledFloat always returns the default descriptor, but it does
+ # check the relevant code paths.
+ arr = np.array([1., 2., 3.], dtype=object)
+
+ res = arr.astype(SF) # passing the class class
+ expected = arr.astype(SF(1.)) # above will have discovered 1. scaling
+ assert_array_equal(res.view(np.float64), expected.view(np.float64))
+
+ def test_creation_class(self):
+ arr1 = np.array([1., 2., 3.], dtype=SF)
+ assert arr1.dtype == SF(1.)
+ arr2 = np.array([1., 2., 3.], dtype=SF(1.))
+ assert_array_equal(arr1.view(np.float64), arr2.view(np.float64))
+
+
+def test_type_pickle():
+ # can't actually unpickle, but we can pickle (if in namespace)
+ import pickle
+
+ np._ScaledFloatTestDType = SF
+
+ s = pickle.dumps(SF)
+ res = pickle.loads(s)
+ assert res is SF
+
+ del np._ScaledFloatTestDType
+
+
+def test_is_numeric():
+ assert SF._is_numeric
diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py
index 693eed0e2..547ebf9d6 100644
--- a/numpy/core/tests/test_datetime.py
+++ b/numpy/core/tests/test_datetime.py
@@ -719,8 +719,8 @@ class TestDateTime:
assert_equal(uni_a, uni_b)
# Datetime to long string - gh-9712
- assert_equal(str_a, dt_a.astype((np.string_, 128)))
- str_b = np.empty(str_a.shape, dtype=(np.string_, 128))
+ assert_equal(str_a, dt_a.astype((np.bytes_, 128)))
+ str_b = np.empty(str_a.shape, dtype=(np.bytes_, 128))
str_b[...] = dt_a
assert_equal(str_a, str_b)
@@ -1003,12 +1003,11 @@ class TestDateTime:
casting='unsafe'))
# Shouldn't be able to compare datetime and timedelta
- # TODO: Changing to 'same_kind' or 'safe' casting in the ufuncs by
- # default is needed to properly catch this kind of thing...
a = np.array('2012-12-21', dtype='M8[D]')
b = np.array(3, dtype='m8[D]')
- #assert_raises(TypeError, np.less, a, b)
- assert_raises(TypeError, np.less, a, b, casting='same_kind')
+ assert_raises(TypeError, np.less, a, b)
+ # not even if "unsafe"
+ assert_raises(TypeError, np.less, a, b, casting='unsafe')
def test_datetime_like(self):
a = np.array([3], dtype='m8[4D]')
@@ -2331,16 +2330,23 @@ class TestDateTime:
assert_equal(np.busday_count('2011-01-01', dates, busdaycal=bdd),
np.arange(366))
# Returns negative value when reversed
+ # -1 since the '2011-01-01' is not a busday
assert_equal(np.busday_count(dates, '2011-01-01', busdaycal=bdd),
- -np.arange(366))
+ -np.arange(366) - 1)
+ # 2011-12-31 is a saturday
dates = np.busday_offset('2011-12-31', -np.arange(366),
roll='forward', busdaycal=bdd)
+ # only the first generated date is in the future of 2011-12-31
+ expected = np.arange(366)
+ expected[0] = -1
assert_equal(np.busday_count(dates, '2011-12-31', busdaycal=bdd),
- np.arange(366))
+ expected)
# Returns negative value when reversed
+ expected = -np.arange(366)+1
+ expected[0] = 0
assert_equal(np.busday_count('2011-12-31', dates, busdaycal=bdd),
- -np.arange(366))
+ expected)
# Can't supply both a weekmask/holidays and busdaycal
assert_raises(ValueError, np.busday_offset, '2012-01-03', '2012-02-03',
@@ -2353,6 +2359,17 @@ class TestDateTime:
# Returns negative value when reversed
assert_equal(np.busday_count('2011-04', '2011-03', weekmask='Mon'), -4)
+ sunday = np.datetime64('2023-03-05')
+ monday = sunday + 1
+ friday = sunday + 5
+ saturday = sunday + 6
+ assert_equal(np.busday_count(sunday, monday), 0)
+ assert_equal(np.busday_count(monday, sunday), -1)
+
+ assert_equal(np.busday_count(friday, saturday), 1)
+ assert_equal(np.busday_count(saturday, friday), 0)
+
+
def test_datetime_is_busday(self):
holidays = ['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24',
'2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17',
@@ -2530,3 +2547,23 @@ class TestDateTimeData:
dt = np.datetime64('2000', '5μs')
assert np.datetime_data(dt.dtype) == ('us', 5)
+
+
+def test_comparisons_return_not_implemented():
+ # GH#17017
+
+ class custom:
+ __array_priority__ = 10000
+
+ obj = custom()
+
+ dt = np.datetime64('2000', 'ns')
+ td = dt - dt
+
+ for item in [dt, td]:
+ assert item.__eq__(obj) is NotImplemented
+ assert item.__ne__(obj) is NotImplemented
+ assert item.__le__(obj) is NotImplemented
+ assert item.__lt__(obj) is NotImplemented
+ assert item.__ge__(obj) is NotImplemented
+ assert item.__gt__(obj) is NotImplemented
diff --git a/numpy/core/tests/test_defchararray.py b/numpy/core/tests/test_defchararray.py
index 22296604e..39699f457 100644
--- a/numpy/core/tests/test_defchararray.py
+++ b/numpy/core/tests/test_defchararray.py
@@ -1,3 +1,5 @@
+import pytest
+
import numpy as np
from numpy.core.multiarray import _vec_string
from numpy.testing import (
@@ -29,7 +31,7 @@ class TestBasic:
def test_from_string_array(self):
A = np.array([[b'abc', b'foo'],
[b'long ', b'0123456789']])
- assert_equal(A.dtype.type, np.string_)
+ assert_equal(A.dtype.type, np.bytes_)
B = np.char.array(A)
assert_array_equal(B, A)
assert_equal(B.dtype, A.dtype)
@@ -46,7 +48,7 @@ class TestBasic:
def test_from_unicode_array(self):
A = np.array([['abc', 'Sigma \u03a3'],
['long ', '0123456789']])
- assert_equal(A.dtype.type, np.unicode_)
+ assert_equal(A.dtype.type, np.str_)
B = np.char.array(A)
assert_array_equal(B, A)
assert_equal(B.dtype, A.dtype)
@@ -64,40 +66,40 @@ class TestBasic:
def test_unicode_upconvert(self):
A = np.char.array(['abc'])
B = np.char.array(['\u03a3'])
- assert_(issubclass((A + B).dtype.type, np.unicode_))
+ assert_(issubclass((A + B).dtype.type, np.str_))
def test_from_string(self):
A = np.char.array(b'abc')
assert_equal(len(A), 1)
assert_equal(len(A[0]), 3)
- assert_(issubclass(A.dtype.type, np.string_))
+ assert_(issubclass(A.dtype.type, np.bytes_))
def test_from_unicode(self):
A = np.char.array('\u03a3')
assert_equal(len(A), 1)
assert_equal(len(A[0]), 1)
assert_equal(A.itemsize, 4)
- assert_(issubclass(A.dtype.type, np.unicode_))
+ assert_(issubclass(A.dtype.type, np.str_))
class TestVecString:
def test_non_existent_method(self):
def fail():
- _vec_string('a', np.string_, 'bogus')
+ _vec_string('a', np.bytes_, 'bogus')
assert_raises(AttributeError, fail)
def test_non_string_array(self):
def fail():
- _vec_string(1, np.string_, 'strip')
+ _vec_string(1, np.bytes_, 'strip')
assert_raises(TypeError, fail)
def test_invalid_args_tuple(self):
def fail():
- _vec_string(['a'], np.string_, 'strip', 1)
+ _vec_string(['a'], np.bytes_, 'strip', 1)
assert_raises(TypeError, fail)
@@ -111,7 +113,7 @@ class TestVecString:
def test_invalid_function_args(self):
def fail():
- _vec_string(['a'], np.string_, 'strip', (1,))
+ _vec_string(['a'], np.bytes_, 'strip', (1,))
assert_raises(TypeError, fail)
@@ -190,7 +192,7 @@ class TestComparisonsMixed1(TestComparisons):
def setup_method(self):
TestComparisons.setup_method(self)
self.B = np.array([['efg', '123 '],
- ['051', 'tuv']], np.unicode_).view(np.chararray)
+ ['051', 'tuv']], np.str_).view(np.chararray)
class TestComparisonsMixed2(TestComparisons):
"""Ticket #1276"""
@@ -198,7 +200,7 @@ class TestComparisonsMixed2(TestComparisons):
def setup_method(self):
TestComparisons.setup_method(self)
self.A = np.array([['abc', '123'],
- ['789', 'xyz']], np.unicode_).view(np.chararray)
+ ['789', 'xyz']], np.str_).view(np.chararray)
class TestInformation:
def setup_method(self):
@@ -320,17 +322,17 @@ class TestMethods:
tgt = [[b' abc ', b''],
[b'12345', b'Mixedcase'],
[b'123 \t 345 \0 ', b'Upper']]
- assert_(issubclass(self.A.capitalize().dtype.type, np.string_))
+ assert_(issubclass(self.A.capitalize().dtype.type, np.bytes_))
assert_array_equal(self.A.capitalize(), tgt)
tgt = [[' \u03c3 ', ''],
['12345', 'Mixedcase'],
['123 \t 345 \0 ', 'Upper']]
- assert_(issubclass(self.B.capitalize().dtype.type, np.unicode_))
+ assert_(issubclass(self.B.capitalize().dtype.type, np.str_))
assert_array_equal(self.B.capitalize(), tgt)
def test_center(self):
- assert_(issubclass(self.A.center(10).dtype.type, np.string_))
+ assert_(issubclass(self.A.center(10).dtype.type, np.bytes_))
C = self.A.center([10, 20])
assert_array_equal(np.char.str_len(C), [[10, 20], [10, 20], [12, 20]])
@@ -341,7 +343,7 @@ class TestMethods:
C = np.char.center(b'FOO', [[10, 20], [15, 8]])
tgt = [[b' FOO ', b' FOO '],
[b' FOO ', b' FOO ']]
- assert_(issubclass(C.dtype.type, np.string_))
+ assert_(issubclass(C.dtype.type, np.bytes_))
assert_array_equal(C, tgt)
def test_decode(self):
@@ -362,14 +364,14 @@ class TestMethods:
A0 = self.A.decode('ascii')
A = np.char.join([',', '#'], A0)
- assert_(issubclass(A.dtype.type, np.unicode_))
+ assert_(issubclass(A.dtype.type, np.str_))
tgt = np.array([[' ,a,b,c, ', ''],
['1,2,3,4,5', 'M#i#x#e#d#C#a#s#e'],
['1,2,3, ,\t, ,3,4,5, ,\x00, ', 'U#P#P#E#R']])
assert_array_equal(np.char.join([',', '#'], A0), tgt)
def test_ljust(self):
- assert_(issubclass(self.A.ljust(10).dtype.type, np.string_))
+ assert_(issubclass(self.A.ljust(10).dtype.type, np.bytes_))
C = self.A.ljust([10, 20])
assert_array_equal(np.char.str_len(C), [[10, 20], [10, 20], [12, 20]])
@@ -382,27 +384,27 @@ class TestMethods:
C = np.char.ljust(b'FOO', [[10, 20], [15, 8]])
tgt = [[b'FOO ', b'FOO '],
[b'FOO ', b'FOO ']]
- assert_(issubclass(C.dtype.type, np.string_))
+ assert_(issubclass(C.dtype.type, np.bytes_))
assert_array_equal(C, tgt)
def test_lower(self):
tgt = [[b' abc ', b''],
[b'12345', b'mixedcase'],
[b'123 \t 345 \0 ', b'upper']]
- assert_(issubclass(self.A.lower().dtype.type, np.string_))
+ assert_(issubclass(self.A.lower().dtype.type, np.bytes_))
assert_array_equal(self.A.lower(), tgt)
tgt = [[' \u03c3 ', ''],
['12345', 'mixedcase'],
['123 \t 345 \0 ', 'upper']]
- assert_(issubclass(self.B.lower().dtype.type, np.unicode_))
+ assert_(issubclass(self.B.lower().dtype.type, np.str_))
assert_array_equal(self.B.lower(), tgt)
def test_lstrip(self):
tgt = [[b'abc ', b''],
[b'12345', b'MixedCase'],
[b'123 \t 345 \0 ', b'UPPER']]
- assert_(issubclass(self.A.lstrip().dtype.type, np.string_))
+ assert_(issubclass(self.A.lstrip().dtype.type, np.bytes_))
assert_array_equal(self.A.lstrip(), tgt)
tgt = [[b' abc', b''],
@@ -413,7 +415,7 @@ class TestMethods:
tgt = [['\u03a3 ', ''],
['12345', 'MixedCase'],
['123 \t 345 \0 ', 'UPPER']]
- assert_(issubclass(self.B.lstrip().dtype.type, np.unicode_))
+ assert_(issubclass(self.B.lstrip().dtype.type, np.str_))
assert_array_equal(self.B.lstrip(), tgt)
def test_partition(self):
@@ -421,7 +423,7 @@ class TestMethods:
tgt = [[(b' abc ', b'', b''), (b'', b'', b'')],
[(b'12', b'3', b'45'), (b'', b'M', b'ixedCase')],
[(b'12', b'3', b' \t 345 \0 '), (b'UPPER', b'', b'')]]
- assert_(issubclass(P.dtype.type, np.string_))
+ assert_(issubclass(P.dtype.type, np.bytes_))
assert_array_equal(P, tgt)
def test_replace(self):
@@ -430,11 +432,11 @@ class TestMethods:
tgt = [[b' abc ', b''],
[b'12##########45', b'MixedC@se'],
[b'12########## \t ##########45 \x00', b'UPPER']]
- assert_(issubclass(R.dtype.type, np.string_))
+ assert_(issubclass(R.dtype.type, np.bytes_))
assert_array_equal(R, tgt)
def test_rjust(self):
- assert_(issubclass(self.A.rjust(10).dtype.type, np.string_))
+ assert_(issubclass(self.A.rjust(10).dtype.type, np.bytes_))
C = self.A.rjust([10, 20])
assert_array_equal(np.char.str_len(C), [[10, 20], [10, 20], [12, 20]])
@@ -447,7 +449,7 @@ class TestMethods:
C = np.char.rjust(b'FOO', [[10, 20], [15, 8]])
tgt = [[b' FOO', b' FOO'],
[b' FOO', b' FOO']]
- assert_(issubclass(C.dtype.type, np.string_))
+ assert_(issubclass(C.dtype.type, np.bytes_))
assert_array_equal(C, tgt)
def test_rpartition(self):
@@ -455,7 +457,7 @@ class TestMethods:
tgt = [[(b'', b'', b' abc '), (b'', b'', b'')],
[(b'12', b'3', b'45'), (b'', b'M', b'ixedCase')],
[(b'123 \t ', b'3', b'45 \0 '), (b'', b'', b'UPPER')]]
- assert_(issubclass(P.dtype.type, np.string_))
+ assert_(issubclass(P.dtype.type, np.bytes_))
assert_array_equal(P, tgt)
def test_rsplit(self):
@@ -467,7 +469,7 @@ class TestMethods:
assert_equal(A.tolist(), tgt)
def test_rstrip(self):
- assert_(issubclass(self.A.rstrip().dtype.type, np.string_))
+ assert_(issubclass(self.A.rstrip().dtype.type, np.bytes_))
tgt = [[b' abc', b''],
[b'12345', b'MixedCase'],
@@ -483,14 +485,14 @@ class TestMethods:
tgt = [[' \u03a3', ''],
['12345', 'MixedCase'],
['123 \t 345', 'UPPER']]
- assert_(issubclass(self.B.rstrip().dtype.type, np.unicode_))
+ assert_(issubclass(self.B.rstrip().dtype.type, np.str_))
assert_array_equal(self.B.rstrip(), tgt)
def test_strip(self):
tgt = [[b'abc', b''],
[b'12345', b'MixedCase'],
[b'123 \t 345', b'UPPER']]
- assert_(issubclass(self.A.strip().dtype.type, np.string_))
+ assert_(issubclass(self.A.strip().dtype.type, np.bytes_))
assert_array_equal(self.A.strip(), tgt)
tgt = [[b' abc ', b''],
@@ -501,7 +503,7 @@ class TestMethods:
tgt = [['\u03a3', ''],
['12345', 'MixedCase'],
['123 \t 345', 'UPPER']]
- assert_(issubclass(self.B.strip().dtype.type, np.unicode_))
+ assert_(issubclass(self.B.strip().dtype.type, np.str_))
assert_array_equal(self.B.strip(), tgt)
def test_split(self):
@@ -523,39 +525,39 @@ class TestMethods:
tgt = [[b' ABC ', b''],
[b'12345', b'mIXEDcASE'],
[b'123 \t 345 \0 ', b'upper']]
- assert_(issubclass(self.A.swapcase().dtype.type, np.string_))
+ assert_(issubclass(self.A.swapcase().dtype.type, np.bytes_))
assert_array_equal(self.A.swapcase(), tgt)
tgt = [[' \u03c3 ', ''],
['12345', 'mIXEDcASE'],
['123 \t 345 \0 ', 'upper']]
- assert_(issubclass(self.B.swapcase().dtype.type, np.unicode_))
+ assert_(issubclass(self.B.swapcase().dtype.type, np.str_))
assert_array_equal(self.B.swapcase(), tgt)
def test_title(self):
tgt = [[b' Abc ', b''],
[b'12345', b'Mixedcase'],
[b'123 \t 345 \0 ', b'Upper']]
- assert_(issubclass(self.A.title().dtype.type, np.string_))
+ assert_(issubclass(self.A.title().dtype.type, np.bytes_))
assert_array_equal(self.A.title(), tgt)
tgt = [[' \u03a3 ', ''],
['12345', 'Mixedcase'],
['123 \t 345 \0 ', 'Upper']]
- assert_(issubclass(self.B.title().dtype.type, np.unicode_))
+ assert_(issubclass(self.B.title().dtype.type, np.str_))
assert_array_equal(self.B.title(), tgt)
def test_upper(self):
tgt = [[b' ABC ', b''],
[b'12345', b'MIXEDCASE'],
[b'123 \t 345 \0 ', b'UPPER']]
- assert_(issubclass(self.A.upper().dtype.type, np.string_))
+ assert_(issubclass(self.A.upper().dtype.type, np.bytes_))
assert_array_equal(self.A.upper(), tgt)
tgt = [[' \u03a3 ', ''],
['12345', 'MIXEDCASE'],
['123 \t 345 \0 ', 'UPPER']]
- assert_(issubclass(self.B.upper().dtype.type, np.unicode_))
+ assert_(issubclass(self.B.upper().dtype.type, np.str_))
assert_array_equal(self.B.upper(), tgt)
def test_isnumeric(self):
@@ -670,3 +672,15 @@ def test_empty_indexing():
# empty chararray instead of a chararray with a single empty string in it.
s = np.chararray((4,))
assert_(s[[]].size == 0)
+
+
+@pytest.mark.parametrize(["dt1", "dt2"],
+ [("S", "U"), ("U", "S"), ("S", "O"), ("U", "O"),
+ ("S", "d"), ("S", "V")])
+def test_add_types(dt1, dt2):
+ arr1 = np.array([1234234], dtype=dt1)
+ # If the following fails, e.g. use a number and test "V" explicitly
+ arr2 = np.array([b"423"], dtype=dt2)
+ with pytest.raises(TypeError,
+ match=f".*same dtype kind.*{arr1.dtype}.*{arr2.dtype}"):
+ np.char.add(arr1, arr2)
diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py
index 4ec1f83d4..3ada39e90 100644
--- a/numpy/core/tests/test_deprecations.py
+++ b/numpy/core/tests/test_deprecations.py
@@ -310,12 +310,6 @@ class TestGeneratorSum(_DeprecationTestCase):
self.assert_deprecated(np.sum, args=((i for i in range(5)),))
-class TestPositiveOnNonNumerical(_DeprecationTestCase):
- # 2018-06-28, 1.16.0
- def test_positive_on_non_number(self):
- self.assert_deprecated(operator.pos, args=(np.array('foo'),))
-
-
class TestFromstring(_DeprecationTestCase):
# 2017-10-19, 1.14
def test_fromstring(self):
@@ -544,134 +538,6 @@ class FlatteningConcatenateUnsafeCast(_DeprecationTestCase):
casting="same_kind")
-class TestDeprecateSubarrayDTypeDuringArrayCoercion(_DeprecationTestCase):
- warning_cls = FutureWarning
- message = "(creating|casting) an array (with|to) a subarray dtype"
-
- def test_deprecated_array(self):
- # Arrays are more complex, since they "broadcast" on success:
- arr = np.array([1, 2])
-
- self.assert_deprecated(lambda: arr.astype("(2)i,"))
- with pytest.warns(FutureWarning):
- res = arr.astype("(2)i,")
-
- assert_array_equal(res, [[1, 2], [1, 2]])
-
- self.assert_deprecated(lambda: np.array(arr, dtype="(2)i,"))
- with pytest.warns(FutureWarning):
- res = np.array(arr, dtype="(2)i,")
-
- assert_array_equal(res, [[1, 2], [1, 2]])
-
- with pytest.warns(FutureWarning):
- res = np.array([[(1,), (2,)], arr], dtype="(2)i,")
-
- assert_array_equal(res, [[[1, 1], [2, 2]], [[1, 2], [1, 2]]])
-
- def test_deprecated_and_error(self):
- # These error paths do not give a warning, but will succeed in the
- # future.
- arr = np.arange(5 * 2).reshape(5, 2)
- def check():
- with pytest.raises(ValueError):
- arr.astype("(2,2)f")
-
- self.assert_deprecated(check)
-
- def check():
- with pytest.raises(ValueError):
- np.array(arr, dtype="(2,2)f")
-
- self.assert_deprecated(check)
-
-
-class TestFutureWarningArrayLikeNotIterable(_DeprecationTestCase):
- # Deprecated 2020-12-09, NumPy 1.20
- warning_cls = FutureWarning
- message = "The input object of type.*but not a sequence"
-
- @pytest.mark.parametrize("protocol",
- ["__array__", "__array_interface__", "__array_struct__"])
- def test_deprecated(self, protocol):
- """Test that these objects give a warning since they are not 0-D,
- not coerced at the top level `np.array(obj)`, but nested, and do
- *not* define the sequence protocol.
-
- NOTE: Tests for the versions including __len__ and __getitem__ exist
- in `test_array_coercion.py` and they can be modified or amended
- when this deprecation expired.
- """
- blueprint = np.arange(10)
- MyArr = type("MyArr", (), {protocol: getattr(blueprint, protocol)})
- self.assert_deprecated(lambda: np.array([MyArr()], dtype=object))
-
- @pytest.mark.parametrize("protocol",
- ["__array__", "__array_interface__", "__array_struct__"])
- def test_0d_not_deprecated(self, protocol):
- # 0-D always worked (albeit it would use __float__ or similar for the
- # conversion, which may not happen anymore)
- blueprint = np.array(1.)
- MyArr = type("MyArr", (), {protocol: getattr(blueprint, protocol)})
- myarr = MyArr()
-
- self.assert_not_deprecated(lambda: np.array([myarr], dtype=object))
- res = np.array([myarr], dtype=object)
- expected = np.empty(1, dtype=object)
- expected[0] = myarr
- assert_array_equal(res, expected)
-
- @pytest.mark.parametrize("protocol",
- ["__array__", "__array_interface__", "__array_struct__"])
- def test_unnested_not_deprecated(self, protocol):
- blueprint = np.arange(10)
- MyArr = type("MyArr", (), {protocol: getattr(blueprint, protocol)})
- myarr = MyArr()
-
- self.assert_not_deprecated(lambda: np.array(myarr))
- res = np.array(myarr)
- assert_array_equal(res, blueprint)
-
- @pytest.mark.parametrize("protocol",
- ["__array__", "__array_interface__", "__array_struct__"])
- def test_strange_dtype_handling(self, protocol):
- """The old code would actually use the dtype from the array, but
- then end up not using the array (for dimension discovery)
- """
- blueprint = np.arange(10).astype("f4")
- MyArr = type("MyArr", (), {protocol: getattr(blueprint, protocol),
- "__float__": lambda _: 0.5})
- myarr = MyArr()
-
- # Make sure we warn (and capture the FutureWarning)
- with pytest.warns(FutureWarning, match=self.message):
- res = np.array([[myarr]])
-
- assert res.shape == (1, 1)
- assert res.dtype == "f4"
- assert res[0, 0] == 0.5
-
- @pytest.mark.parametrize("protocol",
- ["__array__", "__array_interface__", "__array_struct__"])
- def test_assignment_not_deprecated(self, protocol):
- # If the result is dtype=object we do not unpack a nested array or
- # array-like, if it is nested at exactly the right depth.
- # NOTE: We actually do still call __array__, etc. but ignore the result
- # in the end. For `dtype=object` we could optimize that away.
- blueprint = np.arange(10).astype("f4")
- MyArr = type("MyArr", (), {protocol: getattr(blueprint, protocol),
- "__float__": lambda _: 0.5})
- myarr = MyArr()
-
- res = np.empty(3, dtype=object)
- def set():
- res[:] = [myarr, myarr, myarr]
- self.assert_not_deprecated(set)
- assert res[0] is myarr
- assert res[1] is myarr
- assert res[2] is myarr
-
-
class TestDeprecatedUnpickleObjectScalar(_DeprecationTestCase):
# Deprecated 2020-11-24, NumPy 1.20
"""
@@ -685,218 +551,6 @@ class TestDeprecatedUnpickleObjectScalar(_DeprecationTestCase):
ctor = np.core.multiarray.scalar
self.assert_deprecated(lambda: ctor(np.dtype("O"), 1))
-try:
- with warnings.catch_warnings():
- warnings.simplefilter("always")
- import nose # noqa: F401
-except ImportError:
- HAVE_NOSE = False
-else:
- HAVE_NOSE = True
-
-
-@pytest.mark.skipif(not HAVE_NOSE, reason="Needs nose")
-class TestNoseDecoratorsDeprecated(_DeprecationTestCase):
- class DidntSkipException(Exception):
- pass
-
- def test_slow(self):
- def _test_slow():
- @np.testing.dec.slow
- def slow_func(x, y, z):
- pass
-
- assert_(slow_func.slow)
- self.assert_deprecated(_test_slow)
-
- def test_setastest(self):
- def _test_setastest():
- @np.testing.dec.setastest()
- def f_default(a):
- pass
-
- @np.testing.dec.setastest(True)
- def f_istest(a):
- pass
-
- @np.testing.dec.setastest(False)
- def f_isnottest(a):
- pass
-
- assert_(f_default.__test__)
- assert_(f_istest.__test__)
- assert_(not f_isnottest.__test__)
- self.assert_deprecated(_test_setastest, num=3)
-
- def test_skip_functions_hardcoded(self):
- def _test_skip_functions_hardcoded():
- @np.testing.dec.skipif(True)
- def f1(x):
- raise self.DidntSkipException
-
- try:
- f1('a')
- except self.DidntSkipException:
- raise Exception('Failed to skip')
- except SkipTest().__class__:
- pass
-
- @np.testing.dec.skipif(False)
- def f2(x):
- raise self.DidntSkipException
-
- try:
- f2('a')
- except self.DidntSkipException:
- pass
- except SkipTest().__class__:
- raise Exception('Skipped when not expected to')
- self.assert_deprecated(_test_skip_functions_hardcoded, num=2)
-
- def test_skip_functions_callable(self):
- def _test_skip_functions_callable():
- def skip_tester():
- return skip_flag == 'skip me!'
-
- @np.testing.dec.skipif(skip_tester)
- def f1(x):
- raise self.DidntSkipException
-
- try:
- skip_flag = 'skip me!'
- f1('a')
- except self.DidntSkipException:
- raise Exception('Failed to skip')
- except SkipTest().__class__:
- pass
-
- @np.testing.dec.skipif(skip_tester)
- def f2(x):
- raise self.DidntSkipException
-
- try:
- skip_flag = 'five is right out!'
- f2('a')
- except self.DidntSkipException:
- pass
- except SkipTest().__class__:
- raise Exception('Skipped when not expected to')
- self.assert_deprecated(_test_skip_functions_callable, num=2)
-
- def test_skip_generators_hardcoded(self):
- def _test_skip_generators_hardcoded():
- @np.testing.dec.knownfailureif(True, "This test is known to fail")
- def g1(x):
- yield from range(x)
-
- try:
- for j in g1(10):
- pass
- except KnownFailureException().__class__:
- pass
- else:
- raise Exception('Failed to mark as known failure')
-
- @np.testing.dec.knownfailureif(False, "This test is NOT known to fail")
- def g2(x):
- yield from range(x)
- raise self.DidntSkipException('FAIL')
-
- try:
- for j in g2(10):
- pass
- except KnownFailureException().__class__:
- raise Exception('Marked incorrectly as known failure')
- except self.DidntSkipException:
- pass
- self.assert_deprecated(_test_skip_generators_hardcoded, num=2)
-
- def test_skip_generators_callable(self):
- def _test_skip_generators_callable():
- def skip_tester():
- return skip_flag == 'skip me!'
-
- @np.testing.dec.knownfailureif(skip_tester, "This test is known to fail")
- def g1(x):
- yield from range(x)
-
- try:
- skip_flag = 'skip me!'
- for j in g1(10):
- pass
- except KnownFailureException().__class__:
- pass
- else:
- raise Exception('Failed to mark as known failure')
-
- @np.testing.dec.knownfailureif(skip_tester, "This test is NOT known to fail")
- def g2(x):
- yield from range(x)
- raise self.DidntSkipException('FAIL')
-
- try:
- skip_flag = 'do not skip'
- for j in g2(10):
- pass
- except KnownFailureException().__class__:
- raise Exception('Marked incorrectly as known failure')
- except self.DidntSkipException:
- pass
- self.assert_deprecated(_test_skip_generators_callable, num=2)
-
- def test_deprecated(self):
- def _test_deprecated():
- @np.testing.dec.deprecated(True)
- def non_deprecated_func():
- pass
-
- @np.testing.dec.deprecated()
- def deprecated_func():
- import warnings
- warnings.warn("TEST: deprecated func", DeprecationWarning, stacklevel=1)
-
- @np.testing.dec.deprecated()
- def deprecated_func2():
- import warnings
- warnings.warn("AHHHH", stacklevel=1)
- raise ValueError
-
- @np.testing.dec.deprecated()
- def deprecated_func3():
- import warnings
- warnings.warn("AHHHH", stacklevel=1)
-
- # marked as deprecated, but does not raise DeprecationWarning
- assert_raises(AssertionError, non_deprecated_func)
- # should be silent
- deprecated_func()
- with warnings.catch_warnings(record=True):
- warnings.simplefilter("always") # do not propagate unrelated warnings
- # fails if deprecated decorator just disables test. See #1453.
- assert_raises(ValueError, deprecated_func2)
- # warning is not a DeprecationWarning
- assert_raises(AssertionError, deprecated_func3)
- self.assert_deprecated(_test_deprecated, num=4)
-
- def test_parametrize(self):
- def _test_parametrize():
- # dec.parametrize assumes that it is being run by nose. Because
- # we are running under pytest, we need to explicitly check the
- # results.
- @np.testing.dec.parametrize('base, power, expected',
- [(1, 1, 1),
- (2, 1, 2),
- (2, 2, 4)])
- def check_parametrize(base, power, expected):
- assert_(base**power == expected)
-
- count = 0
- for test in check_parametrize():
- test[0](*test[1:])
- count += 1
- assert_(count == 3)
- self.assert_deprecated(_test_parametrize)
-
class TestSingleElementSignature(_DeprecationTestCase):
# Deprecated 2021-04-01, NumPy 1.21
@@ -1040,6 +694,18 @@ class TestLoadtxtParseIntsViaFloat(_DeprecationTestCase):
assert isinstance(e.__cause__, DeprecationWarning)
+class TestScalarConversion(_DeprecationTestCase):
+ # 2023-01-02, 1.25.0
+ def test_float_conversion(self):
+ self.assert_deprecated(float, args=(np.array([3.14]),))
+
+ def test_behaviour(self):
+ b = np.array([[3.14]])
+ c = np.zeros(5)
+ with pytest.warns(DeprecationWarning):
+ c[0] = b
+
+
class TestPyIntConversion(_DeprecationTestCase):
message = r".*stop allowing conversion of out-of-bound.*"
@@ -1098,3 +764,54 @@ def test_future_scalar_attributes(name):
# Unfortunately, they are currently still valid via `np.dtype()`
np.dtype(name)
name in np.sctypeDict
+
+
+# Ignore the above future attribute warning for this test.
+@pytest.mark.filterwarnings("ignore:In the future:FutureWarning")
+class TestRemovedGlobals:
+ # Removed 2023-01-12, NumPy 1.24.0
+ # Not a deprecation, but the large error was added to aid those who missed
+ # the previous deprecation, and should be removed similarly to one
+ # (or faster).
+ @pytest.mark.parametrize("name",
+ ["object", "bool", "float", "complex", "str", "int"])
+ def test_attributeerror_includes_info(self, name):
+ msg = f".*\n`np.{name}` was a deprecated alias for the builtin"
+ with pytest.raises(AttributeError, match=msg):
+ getattr(np, name)
+
+
+class TestDeprecatedFinfo(_DeprecationTestCase):
+ # Deprecated in NumPy 1.25, 2023-01-16
+ def test_deprecated_none(self):
+ self.assert_deprecated(np.finfo, args=(None,))
+
+class TestFromnumeric(_DeprecationTestCase):
+ # 2023-02-28, 1.25.0
+ def test_round_(self):
+ self.assert_deprecated(lambda: np.round_(np.array([1.5, 2.5, 3.5])))
+
+ # 2023-03-02, 1.25.0
+ def test_cumproduct(self):
+ self.assert_deprecated(lambda: np.cumproduct(np.array([1, 2, 3])))
+
+ # 2023-03-02, 1.25.0
+ def test_product(self):
+ self.assert_deprecated(lambda: np.product(np.array([1, 2, 3])))
+
+ # 2023-03-02, 1.25.0
+ def test_sometrue(self):
+ self.assert_deprecated(lambda: np.sometrue(np.array([True, False])))
+
+ # 2023-03-02, 1.25.0
+ def test_alltrue(self):
+ self.assert_deprecated(lambda: np.alltrue(np.array([True, False])))
+
+
+class TestMathAlias(_DeprecationTestCase):
+ # Deprecated in Numpy 1.25, 2023-04-06
+ def test_deprecated_np_math(self):
+ self.assert_deprecated(lambda: np.math)
+
+ def test_deprecated_np_lib_math(self):
+ self.assert_deprecated(lambda: np.lib.math)
diff --git a/numpy/core/tests/test_dlpack.py b/numpy/core/tests/test_dlpack.py
index 278bdd12d..49249bc6a 100644
--- a/numpy/core/tests/test_dlpack.py
+++ b/numpy/core/tests/test_dlpack.py
@@ -38,13 +38,14 @@ class TestDLPack:
assert sys.getrefcount(x) == 2
@pytest.mark.parametrize("dtype", [
+ np.bool_,
np.int8, np.int16, np.int32, np.int64,
np.uint8, np.uint16, np.uint32, np.uint64,
np.float16, np.float32, np.float64,
np.complex64, np.complex128
])
def test_dtype_passthrough(self, dtype):
- x = np.arange(5, dtype=dtype)
+ x = np.arange(5).astype(dtype)
y = np.from_dlpack(x)
assert y.dtype == x.dtype
diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py
index 0a56483d6..57831f46f 100644
--- a/numpy/core/tests/test_dtype.py
+++ b/numpy/core/tests/test_dtype.py
@@ -7,6 +7,7 @@ import types
from typing import Any
import numpy as np
+import numpy.dtypes
from numpy.core._rational_tests import rational
from numpy.core._multiarray_tests import create_custom_field_dtype
from numpy.testing import (
@@ -195,6 +196,34 @@ class TestBuiltin:
# This is an safe cast (not equiv) due to the different names:
assert np.can_cast(x, y, casting="safe")
+ @pytest.mark.parametrize(
+ ["type_char", "char_size", "scalar_type"],
+ [["U", 4, np.str_],
+ ["S", 1, np.bytes_]])
+ def test_create_string_dtypes_directly(
+ self, type_char, char_size, scalar_type):
+ dtype_class = type(np.dtype(type_char))
+
+ dtype = dtype_class(8)
+ assert dtype.type is scalar_type
+ assert dtype.itemsize == 8*char_size
+
+ def test_create_invalid_string_errors(self):
+ one_too_big = np.iinfo(np.intc).max + 1
+ with pytest.raises(TypeError):
+ type(np.dtype("U"))(one_too_big // 4)
+
+ with pytest.raises(TypeError):
+ # Code coverage for very large numbers:
+ type(np.dtype("U"))(np.iinfo(np.intp).max // 4 + 1)
+
+ if one_too_big < sys.maxsize:
+ with pytest.raises(TypeError):
+ type(np.dtype("S"))(one_too_big)
+
+ with pytest.raises(ValueError):
+ type(np.dtype("U"))(-1)
+
class TestRecord:
def test_equivalent_record(self):
@@ -523,6 +552,14 @@ class TestRecord:
assert_equal(np.zeros((1, 2), dtype=[]) == a,
np.ones((1, 2), dtype=bool))
+ def test_nonstructured_with_object(self):
+ # See gh-23277, the dtype here thinks it contain objects, if the
+ # assert about that fails, the test becomes meaningless (which is OK)
+ arr = np.recarray((0,), dtype="O")
+ assert arr.dtype.names is None # no fields
+ assert arr.dtype.hasobject # but claims to contain objects
+ del arr # the deletion failed previously.
+
class TestSubarray:
def test_single_subarray(self):
@@ -1527,8 +1564,21 @@ class TestDTypeClasses:
dtype = np.dtype(dtype)
assert isinstance(dtype, np.dtype)
assert type(dtype) is not np.dtype
- assert type(dtype).__name__ == f"dtype[{dtype.type.__name__}]"
- assert type(dtype).__module__ == "numpy"
+ if dtype.type.__name__ != "rational":
+ dt_name = type(dtype).__name__.lower().removesuffix("dtype")
+ if dt_name == "uint" or dt_name == "int":
+ # The scalar names has a `c` attached because "int" is Python
+ # int and that is long...
+ dt_name += "c"
+ sc_name = dtype.type.__name__
+ assert dt_name == sc_name.strip("_")
+ assert type(dtype).__module__ == "numpy.dtypes"
+
+ assert getattr(numpy.dtypes, type(dtype).__name__) is type(dtype)
+ else:
+ assert type(dtype).__name__ == "dtype[rational]"
+ assert type(dtype).__module__ == "numpy"
+
assert not type(dtype)._abstract
# the flexible dtypes and datetime/timedelta have additional parameters
@@ -1551,6 +1601,32 @@ class TestDTypeClasses:
assert type(np.dtype).__module__ == "numpy"
assert np.dtype._abstract
+ def test_is_numeric(self):
+ all_codes = set(np.typecodes['All'])
+ numeric_codes = set(np.typecodes['AllInteger'] +
+ np.typecodes['AllFloat'] + '?')
+ non_numeric_codes = all_codes - numeric_codes
+
+ for code in numeric_codes:
+ assert type(np.dtype(code))._is_numeric
+
+ for code in non_numeric_codes:
+ assert not type(np.dtype(code))._is_numeric
+
+ @pytest.mark.parametrize("int_", ["UInt", "Int"])
+ @pytest.mark.parametrize("size", [8, 16, 32, 64])
+ def test_integer_alias_names(self, int_, size):
+ DType = getattr(numpy.dtypes, f"{int_}{size}DType")
+ sctype = getattr(numpy, f"{int_.lower()}{size}")
+ assert DType.type is sctype
+ assert DType.__name__.lower().removesuffix("dtype") == sctype.__name__
+
+ @pytest.mark.parametrize("name",
+ ["Half", "Float", "Double", "CFloat", "CDouble"])
+ def test_float_alias_names(self, name):
+ with pytest.raises(AttributeError):
+ getattr(numpy.dtypes, name + "DType") is numpy.dtypes.Float16DType
+
class TestFromCTypes:
@@ -1785,7 +1861,6 @@ class TestUserDType:
create_custom_field_dtype(blueprint, mytype, 2)
-@pytest.mark.skipif(sys.version_info < (3, 9), reason="Requires python 3.9")
class TestClassGetItem:
def test_dtype(self) -> None:
alias = np.dtype[Any]
@@ -1818,10 +1893,3 @@ def test_result_type_integers_and_unitless_timedelta64():
td = np.timedelta64(4)
result = np.result_type(0, td)
assert_dtype_equal(result, td.dtype)
-
-
-@pytest.mark.skipif(sys.version_info >= (3, 9), reason="Requires python 3.8")
-def test_class_getitem_38() -> None:
- match = "Type subscription requires python >= 3.9"
- with pytest.raises(TypeError, match=match):
- np.dtype[Any]
diff --git a/numpy/core/tests/test_einsum.py b/numpy/core/tests/test_einsum.py
index 7c0e8d97c..3a06d119f 100644
--- a/numpy/core/tests/test_einsum.py
+++ b/numpy/core/tests/test_einsum.py
@@ -100,6 +100,69 @@ class TestEinsum:
assert_raises(ValueError, np.einsum, "i->i", np.arange(6).reshape(-1, 1),
optimize=do_opt, order='d')
+ def test_einsum_object_errors(self):
+ # Exceptions created by object arithmetic should
+ # successfully propogate
+
+ class CustomException(Exception):
+ pass
+
+ class DestructoBox:
+
+ def __init__(self, value, destruct):
+ self._val = value
+ self._destruct = destruct
+
+ def __add__(self, other):
+ tmp = self._val + other._val
+ if tmp >= self._destruct:
+ raise CustomException
+ else:
+ self._val = tmp
+ return self
+
+ def __radd__(self, other):
+ if other == 0:
+ return self
+ else:
+ return self.__add__(other)
+
+ def __mul__(self, other):
+ tmp = self._val * other._val
+ if tmp >= self._destruct:
+ raise CustomException
+ else:
+ self._val = tmp
+ return self
+
+ def __rmul__(self, other):
+ if other == 0:
+ return self
+ else:
+ return self.__mul__(other)
+
+ a = np.array([DestructoBox(i, 5) for i in range(1, 10)],
+ dtype='object').reshape(3, 3)
+
+ # raised from unbuffered_loop_nop1_ndim2
+ assert_raises(CustomException, np.einsum, "ij->i", a)
+
+ # raised from unbuffered_loop_nop1_ndim3
+ b = np.array([DestructoBox(i, 100) for i in range(0, 27)],
+ dtype='object').reshape(3, 3, 3)
+ assert_raises(CustomException, np.einsum, "i...k->...", b)
+
+ # raised from unbuffered_loop_nop2_ndim2
+ b = np.array([DestructoBox(i, 55) for i in range(1, 4)],
+ dtype='object')
+ assert_raises(CustomException, np.einsum, "ij, j", a, b)
+
+ # raised from unbuffered_loop_nop2_ndim3
+ assert_raises(CustomException, np.einsum, "ij, jh", a, a)
+
+ # raised from PyArray_EinsteinSum
+ assert_raises(CustomException, np.einsum, "ij->", a)
+
def test_einsum_views(self):
# pass-through
for do_opt in [True, False]:
@@ -247,47 +310,50 @@ class TestEinsum:
# sum(a, axis=-1)
for n in range(1, 17):
a = np.arange(n, dtype=dtype)
- assert_equal(np.einsum("i->", a, optimize=do_opt),
- np.sum(a, axis=-1).astype(dtype))
- assert_equal(np.einsum(a, [0], [], optimize=do_opt),
- np.sum(a, axis=-1).astype(dtype))
+ b = np.sum(a, axis=-1)
+ if hasattr(b, 'astype'):
+ b = b.astype(dtype)
+ assert_equal(np.einsum("i->", a, optimize=do_opt), b)
+ assert_equal(np.einsum(a, [0], [], optimize=do_opt), b)
for n in range(1, 17):
a = np.arange(2*3*n, dtype=dtype).reshape(2, 3, n)
- assert_equal(np.einsum("...i->...", a, optimize=do_opt),
- np.sum(a, axis=-1).astype(dtype))
- assert_equal(np.einsum(a, [Ellipsis, 0], [Ellipsis], optimize=do_opt),
- np.sum(a, axis=-1).astype(dtype))
+ b = np.sum(a, axis=-1)
+ if hasattr(b, 'astype'):
+ b = b.astype(dtype)
+ assert_equal(np.einsum("...i->...", a, optimize=do_opt), b)
+ assert_equal(np.einsum(a, [Ellipsis, 0], [Ellipsis], optimize=do_opt), b)
# sum(a, axis=0)
for n in range(1, 17):
a = np.arange(2*n, dtype=dtype).reshape(2, n)
- assert_equal(np.einsum("i...->...", a, optimize=do_opt),
- np.sum(a, axis=0).astype(dtype))
- assert_equal(np.einsum(a, [0, Ellipsis], [Ellipsis], optimize=do_opt),
- np.sum(a, axis=0).astype(dtype))
+ b = np.sum(a, axis=0)
+ if hasattr(b, 'astype'):
+ b = b.astype(dtype)
+ assert_equal(np.einsum("i...->...", a, optimize=do_opt), b)
+ assert_equal(np.einsum(a, [0, Ellipsis], [Ellipsis], optimize=do_opt), b)
for n in range(1, 17):
a = np.arange(2*3*n, dtype=dtype).reshape(2, 3, n)
- assert_equal(np.einsum("i...->...", a, optimize=do_opt),
- np.sum(a, axis=0).astype(dtype))
- assert_equal(np.einsum(a, [0, Ellipsis], [Ellipsis], optimize=do_opt),
- np.sum(a, axis=0).astype(dtype))
+ b = np.sum(a, axis=0)
+ if hasattr(b, 'astype'):
+ b = b.astype(dtype)
+ assert_equal(np.einsum("i...->...", a, optimize=do_opt), b)
+ assert_equal(np.einsum(a, [0, Ellipsis], [Ellipsis], optimize=do_opt), b)
# trace(a)
for n in range(1, 17):
a = np.arange(n*n, dtype=dtype).reshape(n, n)
- assert_equal(np.einsum("ii", a, optimize=do_opt),
- np.trace(a).astype(dtype))
- assert_equal(np.einsum(a, [0, 0], optimize=do_opt),
- np.trace(a).astype(dtype))
+ b = np.trace(a)
+ if hasattr(b, 'astype'):
+ b = b.astype(dtype)
+ assert_equal(np.einsum("ii", a, optimize=do_opt), b)
+ assert_equal(np.einsum(a, [0, 0], optimize=do_opt), b)
# gh-15961: should accept numpy int64 type in subscript list
np_array = np.asarray([0, 0])
- assert_equal(np.einsum(a, np_array, optimize=do_opt),
- np.trace(a).astype(dtype))
- assert_equal(np.einsum(a, list(np_array), optimize=do_opt),
- np.trace(a).astype(dtype))
+ assert_equal(np.einsum(a, np_array, optimize=do_opt), b)
+ assert_equal(np.einsum(a, list(np_array), optimize=do_opt), b)
# multiply(a, b)
assert_equal(np.einsum("..., ...", 3, 4), 12) # scalar case
@@ -489,11 +555,15 @@ class TestEinsum:
b = np.einsum("i->", a, dtype=dtype, casting='unsafe')
assert_equal(b, np.sum(a))
- assert_equal(b.dtype, np.dtype(dtype))
+ if hasattr(b, "dtype"):
+ # Can be a python object when dtype is object
+ assert_equal(b.dtype, np.dtype(dtype))
b = np.einsum(a, [0], [], dtype=dtype, casting='unsafe')
assert_equal(b, np.sum(a))
- assert_equal(b.dtype, np.dtype(dtype))
+ if hasattr(b, "dtype"):
+ # Can be a python object when dtype is object
+ assert_equal(b.dtype, np.dtype(dtype))
# A case which was failing (ticket #1885)
p = np.arange(2) + 1
@@ -587,6 +657,10 @@ class TestEinsum:
def test_einsum_sums_clongdouble(self):
self.check_einsum_sums(np.clongdouble)
+ def test_einsum_sums_object(self):
+ self.check_einsum_sums('object')
+ self.check_einsum_sums('object', True)
+
def test_einsum_misc(self):
# This call used to crash because of a bug in
# PyArray_AssignZero
@@ -625,6 +699,21 @@ class TestEinsum:
# see issue gh-15776 and issue gh-15256
assert_equal(np.einsum('i,j', [1], [2], out=None), [[2]])
+ def test_object_loop(self):
+
+ class Mult:
+ def __mul__(self, other):
+ return 42
+
+ objMult = np.array([Mult()])
+ objNULL = np.ndarray(buffer = b'\0' * np.intp(0).itemsize, shape=1, dtype=object)
+
+ with pytest.raises(TypeError):
+ np.einsum("i,j", [1], objNULL)
+ with pytest.raises(TypeError):
+ np.einsum("i,j", objNULL, [1])
+ assert np.einsum("i,j", objMult, objMult) == 42
+
def test_subscript_range(self):
# Issue #7741, make sure that all letters of Latin alphabet (both uppercase & lowercase) can be used
# when creating a subscript from arrays
@@ -755,7 +844,7 @@ class TestEinsum:
# Test originally added to cover broken float16 path: gh-20305
# Likely most are covered elsewhere, at least partially.
dtype = np.dtype(dtype)
- # Simple test, designed to excersize most specialized code paths,
+ # Simple test, designed to exercise most specialized code paths,
# note the +0.5 for floats. This makes sure we use a float value
# where the results must be exact.
arr = (np.arange(7) + 0.5).astype(dtype)
diff --git a/numpy/core/tests/test_function_base.py b/numpy/core/tests/test_function_base.py
index dad7a5883..79f1ecfc9 100644
--- a/numpy/core/tests/test_function_base.py
+++ b/numpy/core/tests/test_function_base.py
@@ -1,3 +1,4 @@
+import pytest
from numpy import (
logspace, linspace, geomspace, dtype, array, sctypes, arange, isnan,
ndarray, sqrt, nextafter, stack, errstate
@@ -65,6 +66,33 @@ class TestLogspace:
t5 = logspace(start, stop, 6, axis=-1)
assert_equal(t5, t2.T)
+ @pytest.mark.parametrize("axis", [0, 1, -1])
+ def test_base_array(self, axis: int):
+ start = 1
+ stop = 2
+ num = 6
+ base = array([1, 2])
+ t1 = logspace(start, stop, num=num, base=base, axis=axis)
+ t2 = stack(
+ [logspace(start, stop, num=num, base=_base) for _base in base],
+ axis=(axis + 1) % t1.ndim,
+ )
+ assert_equal(t1, t2)
+
+ @pytest.mark.parametrize("axis", [0, 1, -1])
+ def test_stop_base_array(self, axis: int):
+ start = 1
+ stop = array([2, 3])
+ num = 6
+ base = array([1, 2])
+ t1 = logspace(start, stop, num=num, base=base, axis=axis)
+ t2 = stack(
+ [logspace(start, _stop, num=num, base=_base)
+ for _stop, _base in zip(stop, base)],
+ axis=(axis + 1) % t1.ndim,
+ )
+ assert_equal(t1, t2)
+
def test_dtype(self):
y = logspace(0, 6, dtype='float32')
assert_equal(y.dtype, dtype('float32'))
@@ -407,3 +435,12 @@ class TestLinspace:
y = linspace(-1, 3, num=8, dtype=int)
t = array([-1, -1, 0, 0, 1, 1, 2, 3], dtype=int)
assert_array_equal(y, t)
+
+ def test_any_step_zero_and_not_mult_inplace(self):
+ # any_step_zero is True, _mult_inplace is False
+ start = array([0.0, 1.0])
+ stop = array([2.0, 1.0])
+ y = linspace(start, stop, 3)
+ assert_array_equal(y, array([[0.0, 1.0], [1.0, 1.0], [2.0, 1.0]]))
+
+
diff --git a/numpy/core/tests/test_getlimits.py b/numpy/core/tests/test_getlimits.py
index b8aaba386..63217c38c 100644
--- a/numpy/core/tests/test_getlimits.py
+++ b/numpy/core/tests/test_getlimits.py
@@ -3,6 +3,7 @@
"""
import warnings
import numpy as np
+import pytest
from numpy.core import finfo, iinfo
from numpy import half, single, double, longdouble
from numpy.testing import assert_equal, assert_, assert_raises
@@ -40,20 +41,38 @@ class TestLongdouble:
ftype2 = finfo(longdouble)
assert_equal(id(ftype), id(ftype2))
+def assert_finfo_equal(f1, f2):
+ # assert two finfo instances have the same attributes
+ for attr in ('bits', 'eps', 'epsneg', 'iexp', 'machep',
+ 'max', 'maxexp', 'min', 'minexp', 'negep', 'nexp',
+ 'nmant', 'precision', 'resolution', 'tiny',
+ 'smallest_normal', 'smallest_subnormal'):
+ assert_equal(getattr(f1, attr), getattr(f2, attr),
+ f'finfo instances {f1} and {f2} differ on {attr}')
+
+def assert_iinfo_equal(i1, i2):
+ # assert two iinfo instances have the same attributes
+ for attr in ('bits', 'min', 'max'):
+ assert_equal(getattr(i1, attr), getattr(i2, attr),
+ f'iinfo instances {i1} and {i2} differ on {attr}')
+
class TestFinfo:
def test_basic(self):
dts = list(zip(['f2', 'f4', 'f8', 'c8', 'c16'],
[np.float16, np.float32, np.float64, np.complex64,
np.complex128]))
for dt1, dt2 in dts:
- for attr in ('bits', 'eps', 'epsneg', 'iexp', 'machep',
- 'max', 'maxexp', 'min', 'minexp', 'negep', 'nexp',
- 'nmant', 'precision', 'resolution', 'tiny',
- 'smallest_normal', 'smallest_subnormal'):
- assert_equal(getattr(finfo(dt1), attr),
- getattr(finfo(dt2), attr), attr)
+ assert_finfo_equal(finfo(dt1), finfo(dt2))
+
assert_raises(ValueError, finfo, 'i4')
+ def test_regression_gh23108(self):
+ # np.float32(1.0) and np.float64(1.0) have the same hash and are
+ # equal under the == operator
+ f1 = np.finfo(np.float32(1.0))
+ f2 = np.finfo(np.float64(1.0))
+ assert f1 != f2
+
class TestIinfo:
def test_basic(self):
dts = list(zip(['i1', 'i2', 'i4', 'i8',
@@ -61,9 +80,8 @@ class TestIinfo:
[np.int8, np.int16, np.int32, np.int64,
np.uint8, np.uint16, np.uint32, np.uint64]))
for dt1, dt2 in dts:
- for attr in ('bits', 'min', 'max'):
- assert_equal(getattr(iinfo(dt1), attr),
- getattr(iinfo(dt2), attr), attr)
+ assert_iinfo_equal(iinfo(dt1), iinfo(dt2))
+
assert_raises(ValueError, iinfo, 'f4')
def test_unsigned_max(self):
@@ -85,8 +103,28 @@ class TestRepr:
def test_instances():
- iinfo(10)
- finfo(3.0)
+ # Test the finfo and iinfo results on numeric instances agree with
+ # the results on the corresponding types
+
+ for c in [int, np.int16, np.int32, np.int64]:
+ class_iinfo = iinfo(c)
+ instance_iinfo = iinfo(c(12))
+
+ assert_iinfo_equal(class_iinfo, instance_iinfo)
+
+ for c in [float, np.float16, np.float32, np.float64]:
+ class_finfo = finfo(c)
+ instance_finfo = finfo(c(1.2))
+ assert_finfo_equal(class_finfo, instance_finfo)
+
+ with pytest.raises(ValueError):
+ iinfo(10.)
+
+ with pytest.raises(ValueError):
+ iinfo('hi')
+
+ with pytest.raises(ValueError):
+ finfo(np.int64(1))
def assert_ma_equal(discovered, ma_like):
diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py
index 74075639c..042936702 100644
--- a/numpy/core/tests/test_indexing.py
+++ b/numpy/core/tests/test_indexing.py
@@ -1062,7 +1062,7 @@ class TestMultiIndexingAutomated:
if np.any(_indx >= _size) or np.any(_indx < -_size):
raise IndexError
if len(indx[1:]) == len(orig_slice):
- if np.product(orig_slice) == 0:
+ if np.prod(orig_slice) == 0:
# Work around for a crash or IndexError with 'wrap'
# in some 0-sized cases.
try:
diff --git a/numpy/core/tests/test_item_selection.py b/numpy/core/tests/test_item_selection.py
index 3c35245a3..5660ef583 100644
--- a/numpy/core/tests/test_item_selection.py
+++ b/numpy/core/tests/test_item_selection.py
@@ -1,5 +1,7 @@
import sys
+import pytest
+
import numpy as np
from numpy.testing import (
assert_, assert_raises, assert_array_equal, HAS_REFCOUNT
@@ -84,3 +86,80 @@ class TestTake:
b = np.array([0, 1, 2, 3, 4, 5])
assert_array_equal(a, b)
+
+
+class TestPutMask:
+ @pytest.mark.parametrize("dtype", list(np.typecodes["All"]) + ["i,O"])
+ def test_simple(self, dtype):
+ if dtype.lower() == "m":
+ dtype += "8[ns]"
+
+ # putmask is weird and doesn't care about value length (even shorter)
+ vals = np.arange(1001).astype(dtype=dtype)
+
+ mask = np.random.randint(2, size=1000).astype(bool)
+ # Use vals.dtype in case of flexible dtype (i.e. string)
+ arr = np.zeros(1000, dtype=vals.dtype)
+ zeros = arr.copy()
+
+ np.putmask(arr, mask, vals)
+ assert_array_equal(arr[mask], vals[:len(mask)][mask])
+ assert_array_equal(arr[~mask], zeros[~mask])
+
+ @pytest.mark.parametrize("dtype", list(np.typecodes["All"])[1:] + ["i,O"])
+ @pytest.mark.parametrize("mode", ["raise", "wrap", "clip"])
+ def test_empty(self, dtype, mode):
+ arr = np.zeros(1000, dtype=dtype)
+ arr_copy = arr.copy()
+ mask = np.random.randint(2, size=1000).astype(bool)
+
+ # Allowing empty values like this is weird...
+ np.put(arr, mask, [])
+ assert_array_equal(arr, arr_copy)
+
+
+class TestPut:
+ @pytest.mark.parametrize("dtype", list(np.typecodes["All"])[1:] + ["i,O"])
+ @pytest.mark.parametrize("mode", ["raise", "wrap", "clip"])
+ def test_simple(self, dtype, mode):
+ if dtype.lower() == "m":
+ dtype += "8[ns]"
+
+ # put is weird and doesn't care about value length (even shorter)
+ vals = np.arange(1001).astype(dtype=dtype)
+
+ # Use vals.dtype in case of flexible dtype (i.e. string)
+ arr = np.zeros(1000, dtype=vals.dtype)
+ zeros = arr.copy()
+
+ if mode == "clip":
+ # Special because 0 and -1 value are "reserved" for clip test
+ indx = np.random.permutation(len(arr) - 2)[:-500] + 1
+
+ indx[-1] = 0
+ indx[-2] = len(arr) - 1
+ indx_put = indx.copy()
+ indx_put[-1] = -1389
+ indx_put[-2] = 1321
+ else:
+ # Avoid duplicates (for simplicity) and fill half only
+ indx = np.random.permutation(len(arr) - 3)[:-500]
+ indx_put = indx
+ if mode == "wrap":
+ indx_put = indx_put + len(arr)
+
+ np.put(arr, indx_put, vals, mode=mode)
+ assert_array_equal(arr[indx], vals[:len(indx)])
+ untouched = np.ones(len(arr), dtype=bool)
+ untouched[indx] = False
+ assert_array_equal(arr[untouched], zeros[:untouched.sum()])
+
+ @pytest.mark.parametrize("dtype", list(np.typecodes["All"])[1:] + ["i,O"])
+ @pytest.mark.parametrize("mode", ["raise", "wrap", "clip"])
+ def test_empty(self, dtype, mode):
+ arr = np.zeros(1000, dtype=dtype)
+ arr_copy = arr.copy()
+
+ # Allowing empty values like this is weird...
+ np.put(arr, [1, 2, 3], [])
+ assert_array_equal(arr, arr_copy)
diff --git a/numpy/core/tests/test_longdouble.py b/numpy/core/tests/test_longdouble.py
index 1a54e62d8..45721950c 100644
--- a/numpy/core/tests/test_longdouble.py
+++ b/numpy/core/tests/test_longdouble.py
@@ -1,10 +1,11 @@
import warnings
+import platform
import pytest
import numpy as np
from numpy.testing import (
assert_, assert_equal, assert_raises, assert_warns, assert_array_equal,
- temppath,
+ temppath, IS_MUSL
)
from numpy.core.tests._locales import CommaDecimalPointLocale
@@ -30,6 +31,10 @@ def test_scalar_extraction():
# 0.1 not exactly representable in base 2 floating point.
repr_precision = len(repr(np.longdouble(0.1)))
# +2 from macro block starting around line 842 in scalartypes.c.src.
+
+
+@pytest.mark.skipif(IS_MUSL,
+ reason="test flaky on musllinux")
@pytest.mark.skipif(LD_INFO.precision + 2 >= repr_precision,
reason="repr precision not enough to show eps")
def test_repr_roundtrip():
@@ -142,7 +147,7 @@ class TestFileBased:
def test_fromfile_bogus(self):
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write("1. 2. 3. flop 4.\n")
with assert_warns(DeprecationWarning):
@@ -153,7 +158,7 @@ class TestFileBased:
for ctype in ["complex", "cdouble", "cfloat"]:
# Check spacing between separator and only real component specified
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write("1, 2 , 3 ,4\n")
res = np.fromfile(path, dtype=ctype, sep=",")
@@ -161,7 +166,7 @@ class TestFileBased:
# Real component not specified
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write("1j, -2j, 3j, 4e1j\n")
res = np.fromfile(path, dtype=ctype, sep=",")
@@ -169,7 +174,7 @@ class TestFileBased:
# Both components specified
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write("1+1j,2-2j, -3+3j, -4e1+4j\n")
res = np.fromfile(path, dtype=ctype, sep=",")
@@ -177,7 +182,7 @@ class TestFileBased:
# Spaces at wrong places
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write("1+2 j,3\n")
with assert_warns(DeprecationWarning):
@@ -186,7 +191,7 @@ class TestFileBased:
# Spaces at wrong places
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write("1+ 2j,3\n")
with assert_warns(DeprecationWarning):
@@ -195,7 +200,7 @@ class TestFileBased:
# Spaces at wrong places
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write("1 +2j,3\n")
with assert_warns(DeprecationWarning):
@@ -204,7 +209,7 @@ class TestFileBased:
# Spaces at wrong places
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write("1+j\n")
with assert_warns(DeprecationWarning):
@@ -213,7 +218,7 @@ class TestFileBased:
# Spaces at wrong places
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write("1+\n")
with assert_warns(DeprecationWarning):
@@ -222,7 +227,7 @@ class TestFileBased:
# Spaces at wrong places
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write("1j+1\n")
with assert_warns(DeprecationWarning):
@@ -235,7 +240,7 @@ class TestFileBased:
reason="Need strtold_l")
def test_fromfile(self):
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write(self.out)
res = np.fromfile(path, dtype=np.longdouble, sep="\n")
assert_equal(res, self.tgt)
@@ -244,7 +249,7 @@ class TestFileBased:
reason="Need strtold_l")
def test_genfromtxt(self):
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write(self.out)
res = np.genfromtxt(path, dtype=np.longdouble)
assert_equal(res, self.tgt)
@@ -253,7 +258,7 @@ class TestFileBased:
reason="Need strtold_l")
def test_loadtxt(self):
with temppath() as path:
- with open(path, 'wt') as f:
+ with open(path, 'w') as f:
f.write(self.out)
res = np.loadtxt(path, dtype=np.longdouble)
assert_equal(res, self.tgt)
@@ -368,3 +373,23 @@ def test_longdouble_from_int(int_val):
True, False])
def test_longdouble_from_bool(bool_val):
assert np.longdouble(bool_val) == np.longdouble(int(bool_val))
+
+
+@pytest.mark.skipif(
+ not (IS_MUSL and platform.machine() == "x86_64"),
+ reason="only need to run on musllinux_x86_64"
+)
+def test_musllinux_x86_64_signature():
+ # this test may fail if you're emulating musllinux_x86_64 on a different
+ # architecture, but should pass natively.
+ known_sigs = [b'\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xfb\xbf']
+ sig = (np.longdouble(-1.0) / np.longdouble(10.0)
+ ).newbyteorder('<').tobytes()[:10]
+ assert sig in known_sigs
+
+
+def test_eps_positive():
+ # np.finfo('g').eps should be positive on all platforms. If this isn't true
+ # then something may have gone wrong with the MachArLike, e.g. if
+ # np.core.getlimits._discovered_machar didn't work properly
+ assert np.finfo(np.longdouble).eps > 0.
diff --git a/numpy/core/tests/test_mem_overlap.py b/numpy/core/tests/test_mem_overlap.py
index d66decfda..1fd4c4d41 100644
--- a/numpy/core/tests/test_mem_overlap.py
+++ b/numpy/core/tests/test_mem_overlap.py
@@ -55,7 +55,7 @@ def _indices(ndims):
def _check_assignment(srcidx, dstidx):
"""Check assignment arr[dstidx] = arr[srcidx] works."""
- arr = np.arange(np.product(shape)).reshape(shape)
+ arr = np.arange(np.prod(shape)).reshape(shape)
cpy = arr.copy()
diff --git a/numpy/core/tests/test_mem_policy.py b/numpy/core/tests/test_mem_policy.py
index d5dfbc38b..479f702ea 100644
--- a/numpy/core/tests/test_mem_policy.py
+++ b/numpy/core/tests/test_mem_policy.py
@@ -89,6 +89,7 @@ def get_module(tmp_path):
"""),
]
prologue = '''
+ #define NPY_TARGET_VERSION NPY_1_22_API_VERSION
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>
/*
diff --git a/numpy/core/tests/test_memmap.py b/numpy/core/tests/test_memmap.py
index 914f86f14..ad074b312 100644
--- a/numpy/core/tests/test_memmap.py
+++ b/numpy/core/tests/test_memmap.py
@@ -6,7 +6,7 @@ from pathlib import Path
from tempfile import NamedTemporaryFile, TemporaryFile
from numpy import (
- memmap, sum, average, product, ndarray, isscalar, add, subtract, multiply)
+ memmap, sum, average, prod, ndarray, isscalar, add, subtract, multiply)
from numpy import arange, allclose, asarray
from numpy.testing import (
@@ -153,7 +153,7 @@ class TestMemmap:
with suppress_warnings() as sup:
sup.filter(FutureWarning, "np.average currently does not preserve")
- for unary_op in [sum, average, product]:
+ for unary_op in [sum, average, prod]:
result = unary_op(fp)
assert_(isscalar(result))
assert_(result.__class__ is self.data[0, 0].__class__)
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 63ac32f20..196c2dc13 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
import collections.abc
import tempfile
import sys
@@ -28,11 +30,12 @@ from numpy.testing import (
assert_, assert_raises, assert_warns, assert_equal, assert_almost_equal,
assert_array_equal, assert_raises_regex, assert_array_almost_equal,
assert_allclose, IS_PYPY, IS_PYSTON, HAS_REFCOUNT, assert_array_less,
- runstring, temppath, suppress_warnings, break_cycles,
+ runstring, temppath, suppress_warnings, break_cycles, _SUPPORTS_SVE,
)
from numpy.testing._private.utils import requires_memory, _no_tracing
from numpy.core.tests._locales import CommaDecimalPointLocale
from numpy.lib.recfunctions import repack_fields
+from numpy.core.multiarray import _get_ndarray_c_version
# Need to test an object that does not fully implement math interface
from datetime import timedelta, datetime
@@ -403,6 +406,13 @@ class TestAttributes:
assert_array_equal(x['a'], [3.5, 3.5])
assert_array_equal(x['b'], [-2, -2])
+ def test_fill_readonly(self):
+ # gh-22922
+ a = np.zeros(11)
+ a.setflags(write=False)
+ with pytest.raises(ValueError, match=".*read-only"):
+ a.fill(0)
+
class TestArrayConstruction:
def test_array(self):
@@ -1186,6 +1196,17 @@ class TestCreation:
expected = expected * (arr.nbytes // len(expected))
assert arr.tobytes() == expected
+ @pytest.mark.parametrize("func", [
+ np.array, np.asarray, np.asanyarray, np.ascontiguousarray,
+ np.asfortranarray])
+ def test_creation_from_dtypemeta(self, func):
+ dtype = np.dtype('i')
+ arr1 = func([1, 2, 3], dtype=dtype)
+ arr2 = func([1, 2, 3], dtype=type(dtype))
+ assert_array_equal(arr1, arr2)
+ assert arr2.dtype == dtype
+
+
class TestStructured:
def test_subarray_field_access(self):
a = np.zeros((3, 5), dtype=[('a', ('i4', (2, 2)))])
@@ -1698,7 +1719,7 @@ class TestBool:
@pytest.mark.xfail(reason="See gh-9847")
def test_cast_from_unicode(self):
- self._test_cast_from_flexible(np.unicode_)
+ self._test_cast_from_flexible(np.str_)
@pytest.mark.xfail(reason="See gh-9847")
def test_cast_from_bytes(self):
@@ -1913,8 +1934,9 @@ class TestMethods:
assert_array_equal(a2.prod(axis=-1),
np.array([24, 1890, 600], ctype))
- def test_repeat(self):
- m = np.array([1, 2, 3, 4, 5, 6])
+ @pytest.mark.parametrize('dtype', [None, object])
+ def test_repeat(self, dtype):
+ m = np.array([1, 2, 3, 4, 5, 6], dtype=dtype)
m_rect = m.reshape((2, 3))
A = m.repeat([1, 3, 2, 1, 1, 2])
@@ -2080,7 +2102,7 @@ class TestMethods:
msg = 'byte-swapped complex sort, dtype={0}'.format(dt)
assert_equal(c, arr, msg)
- @pytest.mark.parametrize('dtype', [np.bytes_, np.unicode_])
+ @pytest.mark.parametrize('dtype', [np.bytes_, np.str_])
def test_sort_string(self, dtype):
# np.array will perform the encoding to bytes for us in the bytes test
a = np.array(['aaaaaaaa' + chr(i) for i in range(101)], dtype=dtype)
@@ -2108,19 +2130,26 @@ class TestMethods:
c.sort(kind=kind)
assert_equal(c, a, msg)
- def test_sort_structured(self):
+ @pytest.mark.parametrize("dt", [
+ np.dtype([('f', float), ('i', int)]),
+ np.dtype([('f', float), ('i', object)])])
+ @pytest.mark.parametrize("step", [1, 2])
+ def test_sort_structured(self, dt, step):
# test record array sorts.
- dt = np.dtype([('f', float), ('i', int)])
- a = np.array([(i, i) for i in range(101)], dtype=dt)
+ a = np.array([(i, i) for i in range(101*step)], dtype=dt)
b = a[::-1]
for kind in ['q', 'h', 'm']:
msg = "kind=%s" % kind
- c = a.copy()
+ c = a.copy()[::step]
+ indx = c.argsort(kind=kind)
c.sort(kind=kind)
- assert_equal(c, a, msg)
- c = b.copy()
+ assert_equal(c, a[::step], msg)
+ assert_equal(a[::step][indx], a[::step], msg)
+ c = b.copy()[::step]
+ indx = c.argsort(kind=kind)
c.sort(kind=kind)
- assert_equal(c, a, msg)
+ assert_equal(c, a[step-1::step], msg)
+ assert_equal(b[::step][indx], a[step-1::step], msg)
@pytest.mark.parametrize('dtype', ['datetime64[D]', 'timedelta64[D]'])
def test_sort_time(self, dtype):
@@ -2354,7 +2383,7 @@ class TestMethods:
# test unicode argsorts.
s = 'aaaaaaaa'
- a = np.array([s + chr(i) for i in range(101)], dtype=np.unicode_)
+ a = np.array([s + chr(i) for i in range(101)], dtype=np.str_)
b = a[::-1]
r = np.arange(101)
rr = r[::-1]
@@ -2437,7 +2466,7 @@ class TestMethods:
a = np.array(['aaaaaaaaa' for i in range(100)])
assert_equal(a.argsort(kind='m'), r)
# unicode
- a = np.array(['aaaaaaaaa' for i in range(100)], dtype=np.unicode_)
+ a = np.array(['aaaaaaaaa' for i in range(100)], dtype=np.str_)
assert_equal(a.argsort(kind='m'), r)
def test_sort_unicode_kind(self):
@@ -2581,7 +2610,7 @@ class TestMethods:
'P:\\20x_dapi_cy3\\20x_dapi_cy3_20100197_1',
'P:\\20x_dapi_cy3\\20x_dapi_cy3_20100198_1',
'P:\\20x_dapi_cy3\\20x_dapi_cy3_20100199_1'],
- dtype=np.unicode_)
+ dtype=np.str_)
ind = np.arange(len(a))
assert_equal([a.searchsorted(v, 'left') for v in a], ind)
assert_equal([a.searchsorted(v, 'right') for v in a], ind + 1)
@@ -3616,9 +3645,13 @@ class TestMethods:
msg = 'dtype: {0}'.format(dt)
ap = complex(a)
assert_equal(ap, a, msg)
- bp = complex(b)
+
+ with assert_warns(DeprecationWarning):
+ bp = complex(b)
assert_equal(bp, b, msg)
- cp = complex(c)
+
+ with assert_warns(DeprecationWarning):
+ cp = complex(c)
assert_equal(cp, c, msg)
def test__complex__should_not_work(self):
@@ -3641,7 +3674,8 @@ class TestMethods:
assert_raises(TypeError, complex, d)
e = np.array(['1+1j'], 'U')
- assert_raises(TypeError, complex, e)
+ with assert_warns(DeprecationWarning):
+ assert_raises(TypeError, complex, e)
class TestCequenceMethods:
def test_array_contains(self):
@@ -3703,7 +3737,7 @@ class TestBinop:
'and': (np.bitwise_and, True, int),
'xor': (np.bitwise_xor, True, int),
'or': (np.bitwise_or, True, int),
- 'matmul': (np.matmul, False, float),
+ 'matmul': (np.matmul, True, float),
# 'ge': (np.less_equal, False),
# 'gt': (np.less, False),
# 'le': (np.greater_equal, False),
@@ -4721,23 +4755,23 @@ class TestArgmax:
a = np.array([1, 2**7 - 1, -2**7], dtype=np.int8)
assert_equal(np.argmax(a), 1)
- a.repeat(129)
- assert_equal(np.argmax(a), 1)
+ a = a.repeat(129)
+ assert_equal(np.argmax(a), 129)
a = np.array([1, 2**15 - 1, -2**15], dtype=np.int16)
assert_equal(np.argmax(a), 1)
- a.repeat(129)
- assert_equal(np.argmax(a), 1)
+ a = a.repeat(129)
+ assert_equal(np.argmax(a), 129)
a = np.array([1, 2**31 - 1, -2**31], dtype=np.int32)
assert_equal(np.argmax(a), 1)
- a.repeat(129)
- assert_equal(np.argmax(a), 1)
+ a = a.repeat(129)
+ assert_equal(np.argmax(a), 129)
a = np.array([1, 2**63 - 1, -2**63], dtype=np.int64)
assert_equal(np.argmax(a), 1)
- a.repeat(129)
- assert_equal(np.argmax(a), 1)
+ a = a.repeat(129)
+ assert_equal(np.argmax(a), 129)
class TestArgmin:
usg_data = [
@@ -4863,23 +4897,23 @@ class TestArgmin:
a = np.array([1, -2**7, -2**7 + 1, 2**7 - 1], dtype=np.int8)
assert_equal(np.argmin(a), 1)
- a.repeat(129)
- assert_equal(np.argmin(a), 1)
+ a = a.repeat(129)
+ assert_equal(np.argmin(a), 129)
a = np.array([1, -2**15, -2**15 + 1, 2**15 - 1], dtype=np.int16)
assert_equal(np.argmin(a), 1)
- a.repeat(129)
- assert_equal(np.argmin(a), 1)
+ a = a.repeat(129)
+ assert_equal(np.argmin(a), 129)
a = np.array([1, -2**31, -2**31 + 1, 2**31 - 1], dtype=np.int32)
assert_equal(np.argmin(a), 1)
- a.repeat(129)
- assert_equal(np.argmin(a), 1)
+ a = a.repeat(129)
+ assert_equal(np.argmin(a), 129)
a = np.array([1, -2**63, -2**63 + 1, 2**63 - 1], dtype=np.int64)
assert_equal(np.argmin(a), 1)
- a.repeat(129)
- assert_equal(np.argmin(a), 1)
+ a = a.repeat(129)
+ assert_equal(np.argmin(a), 129)
class TestMinMax:
@@ -5077,6 +5111,22 @@ class TestPutmask:
with pytest.raises(ValueError):
np.putmask(a, a >= 2, 3)
+ def test_kwargs(self):
+ x = np.array([0, 0])
+ np.putmask(x, [0, 1], [-1, -2])
+ assert_array_equal(x, [0, -2])
+
+ x = np.array([0, 0])
+ np.putmask(x, mask=[0, 1], values=[-1, -2])
+ assert_array_equal(x, [0, -2])
+
+ x = np.array([0, 0])
+ np.putmask(x, values=[-1, -2], mask=[0, 1])
+ assert_array_equal(x, [0, -2])
+
+ with pytest.raises(TypeError):
+ np.putmask(a=x, values=[-1, -2], mask=[0, 1])
+
class TestTake:
def tst_basic(self, x):
@@ -5528,33 +5578,6 @@ class TestIO:
tmp_filename,
dtype='<f4')
- @pytest.mark.slow # takes > 1 minute on mechanical hard drive
- def test_big_binary(self):
- """Test workarounds for 32-bit limit for MSVC fwrite, fseek, and ftell
-
- These normally would hang doing something like this.
- See : https://github.com/numpy/numpy/issues/2256
- """
- if sys.platform != 'win32' or '[GCC ' in sys.version:
- return
- try:
- # before workarounds, only up to 2**32-1 worked
- fourgbplus = 2**32 + 2**16
- testbytes = np.arange(8, dtype=np.int8)
- n = len(testbytes)
- flike = tempfile.NamedTemporaryFile()
- f = flike.file
- np.tile(testbytes, fourgbplus // testbytes.nbytes).tofile(f)
- flike.seek(0)
- a = np.fromfile(f, dtype=np.int8)
- flike.close()
- assert_(len(a) == fourgbplus)
- # check only start and end for speed:
- assert_((a[:n] == testbytes).all())
- assert_((a[-n:] == testbytes).all())
- except (MemoryError, ValueError):
- pass
-
def test_string(self, tmp_filename):
self._check_from(b'1,2,3,4', [1., 2., 3., 4.], tmp_filename, sep=',')
@@ -6658,6 +6681,22 @@ class TestDot:
r = np.empty((1024, 32), dtype=int)
assert_raises(ValueError, dot, f, v, r)
+ def test_dot_out_result(self):
+ x = np.ones((), dtype=np.float16)
+ y = np.ones((5,), dtype=np.float16)
+ z = np.zeros((5,), dtype=np.float16)
+ res = x.dot(y, out=z)
+ assert np.array_equal(res, y)
+ assert np.array_equal(z, y)
+
+ def test_dot_out_aliasing(self):
+ x = np.ones((), dtype=np.float16)
+ y = np.ones((5,), dtype=np.float16)
+ z = np.zeros((5,), dtype=np.float16)
+ res = x.dot(y, out=z)
+ z[0] = 2
+ assert np.array_equal(res, z)
+
def test_dot_array_order(self):
a = np.array([[1, 2], [3, 4]], order='C')
b = np.array([[1, 2], [3, 4]], order='F')
@@ -7165,16 +7204,69 @@ class TestMatmulOperator(MatmulCommon):
assert_raises(TypeError, self.matmul, np.void(b'abc'), np.void(b'abc'))
assert_raises(TypeError, self.matmul, np.arange(10), np.void(b'abc'))
-def test_matmul_inplace():
- # It would be nice to support in-place matmul eventually, but for now
- # we don't have a working implementation, so better just to error out
- # and nudge people to writing "a = a @ b".
- a = np.eye(3)
- b = np.eye(3)
- assert_raises(TypeError, a.__imatmul__, b)
- import operator
- assert_raises(TypeError, operator.imatmul, a, b)
- assert_raises(TypeError, exec, "a @= b", globals(), locals())
+
+class TestMatmulInplace:
+ DTYPES = {}
+ for i in MatmulCommon.types:
+ for j in MatmulCommon.types:
+ if np.can_cast(j, i):
+ DTYPES[f"{i}-{j}"] = (np.dtype(i), np.dtype(j))
+
+ @pytest.mark.parametrize("dtype1,dtype2", DTYPES.values(), ids=DTYPES)
+ def test_basic(self, dtype1: np.dtype, dtype2: np.dtype) -> None:
+ a = np.arange(10).reshape(5, 2).astype(dtype1)
+ a_id = id(a)
+ b = np.ones((2, 2), dtype=dtype2)
+
+ ref = a @ b
+ a @= b
+
+ assert id(a) == a_id
+ assert a.dtype == dtype1
+ assert a.shape == (5, 2)
+ if dtype1.kind in "fc":
+ np.testing.assert_allclose(a, ref)
+ else:
+ np.testing.assert_array_equal(a, ref)
+
+ SHAPES = {
+ "2d_large": ((10**5, 10), (10, 10)),
+ "3d_large": ((10**4, 10, 10), (1, 10, 10)),
+ "1d": ((3,), (3,)),
+ "2d_1d": ((3, 3), (3,)),
+ "1d_2d": ((3,), (3, 3)),
+ "2d_broadcast": ((3, 3), (3, 1)),
+ "2d_broadcast_reverse": ((1, 3), (3, 3)),
+ "3d_broadcast1": ((3, 3, 3), (1, 3, 1)),
+ "3d_broadcast2": ((3, 3, 3), (1, 3, 3)),
+ "3d_broadcast3": ((3, 3, 3), (3, 3, 1)),
+ "3d_broadcast_reverse1": ((1, 3, 3), (3, 3, 3)),
+ "3d_broadcast_reverse2": ((3, 1, 3), (3, 3, 3)),
+ "3d_broadcast_reverse3": ((1, 1, 3), (3, 3, 3)),
+ }
+
+ @pytest.mark.parametrize("a_shape,b_shape", SHAPES.values(), ids=SHAPES)
+ def test_shapes(self, a_shape: tuple[int, ...], b_shape: tuple[int, ...]):
+ a_size = np.prod(a_shape)
+ a = np.arange(a_size).reshape(a_shape).astype(np.float64)
+ a_id = id(a)
+
+ b_size = np.prod(b_shape)
+ b = np.arange(b_size).reshape(b_shape)
+
+ ref = a @ b
+ if ref.shape != a_shape:
+ with pytest.raises(ValueError):
+ a @= b
+ return
+ else:
+ a @= b
+
+ assert id(a) == a_id
+ assert a.dtype.type == np.float64
+ assert a.shape == a_shape
+ np.testing.assert_allclose(a, ref)
+
def test_matmul_axes():
a = np.arange(3*4*5).reshape(3, 4, 5)
@@ -8670,14 +8762,16 @@ class TestConversion:
int_funcs = (int, lambda x: x.__int__())
for int_func in int_funcs:
assert_equal(int_func(np.array(0)), 0)
- assert_equal(int_func(np.array([1])), 1)
- assert_equal(int_func(np.array([[42]])), 42)
+ with assert_warns(DeprecationWarning):
+ assert_equal(int_func(np.array([1])), 1)
+ with assert_warns(DeprecationWarning):
+ assert_equal(int_func(np.array([[42]])), 42)
assert_raises(TypeError, int_func, np.array([1, 2]))
# gh-9972
assert_equal(4, int_func(np.array('4')))
assert_equal(5, int_func(np.bytes_(b'5')))
- assert_equal(6, int_func(np.unicode_('6')))
+ assert_equal(6, int_func(np.str_('6')))
# The delegation of int() to __trunc__ was deprecated in
# Python 3.11.
@@ -8686,7 +8780,8 @@ class TestConversion:
def __trunc__(self):
return 3
assert_equal(3, int_func(np.array(HasTrunc())))
- assert_equal(3, int_func(np.array([HasTrunc()])))
+ with assert_warns(DeprecationWarning):
+ assert_equal(3, int_func(np.array([HasTrunc()])))
else:
pass
@@ -8695,8 +8790,9 @@ class TestConversion:
raise NotImplementedError
assert_raises(NotImplementedError,
int_func, np.array(NotConvertible()))
- assert_raises(NotImplementedError,
- int_func, np.array([NotConvertible()]))
+ with assert_warns(DeprecationWarning):
+ assert_raises(NotImplementedError,
+ int_func, np.array([NotConvertible()]))
class TestWhere:
@@ -8863,6 +8959,11 @@ class TestWhere:
result = array.nonzero()
assert_array_equal(benchmark, result)
+ def test_kwargs(self):
+ a = np.zeros(1)
+ with assert_raises(TypeError):
+ np.where(a, x=a, y=a)
+
if not IS_PYPY:
# sys.getsizeof() is not valid on PyPy
@@ -9044,33 +9145,33 @@ class TestUnicodeEncoding:
def test_assign_scalar(self):
# gh-3258
l = np.array(['aa', 'bb'])
- l[:] = np.unicode_('cc')
+ l[:] = np.str_('cc')
assert_equal(l, ['cc', 'cc'])
def test_fill_scalar(self):
# gh-7227
l = np.array(['aa', 'bb'])
- l.fill(np.unicode_('cc'))
+ l.fill(np.str_('cc'))
assert_equal(l, ['cc', 'cc'])
class TestUnicodeArrayNonzero:
def test_empty_ustring_array_is_falsey(self):
- assert_(not np.array([''], dtype=np.unicode_))
+ assert_(not np.array([''], dtype=np.str_))
def test_whitespace_ustring_array_is_falsey(self):
- a = np.array(['eggs'], dtype=np.unicode_)
+ a = np.array(['eggs'], dtype=np.str_)
a[0] = ' \0\0'
assert_(not a)
def test_all_null_ustring_array_is_falsey(self):
- a = np.array(['eggs'], dtype=np.unicode_)
+ a = np.array(['eggs'], dtype=np.str_)
a[0] = '\0\0\0\0'
assert_(not a)
def test_null_inside_ustring_array_is_truthy(self):
- a = np.array(['eggs'], dtype=np.unicode_)
+ a = np.array(['eggs'], dtype=np.str_)
a[0] = ' \0 \0'
assert_(a)
@@ -9505,7 +9606,7 @@ def test_equal_override():
@pytest.mark.parametrize("op", [operator.eq, operator.ne])
@pytest.mark.parametrize(["dt1", "dt2"], [
- ([("f", "i")], [("f", "i")]), # structured comparison (successfull)
+ ([("f", "i")], [("f", "i")]), # structured comparison (successful)
("M8", "d"), # impossible comparison: result is all True or False
("d", "d"), # valid comparison
])
@@ -9828,40 +9929,50 @@ class TestViewDtype:
assert_array_equal(x.view('<i2'), expected)
+@pytest.mark.xfail(_SUPPORTS_SVE, reason="gh-22982")
# Test various array sizes that hit different code paths in quicksort-avx512
-@pytest.mark.parametrize("N", [8, 16, 24, 32, 48, 64, 96, 128, 151, 191,
- 256, 383, 512, 1023, 2047])
-def test_sort_float(N):
+@pytest.mark.parametrize("N", np.arange(1, 512))
+@pytest.mark.parametrize("dtype", ['e', 'f', 'd'])
+def test_sort_float(N, dtype):
# Regular data with nan sprinkled
np.random.seed(42)
- arr = -0.5 + np.random.sample(N).astype('f')
+ arr = -0.5 + np.random.sample(N).astype(dtype)
arr[np.random.choice(arr.shape[0], 3)] = np.nan
assert_equal(np.sort(arr, kind='quick'), np.sort(arr, kind='heap'))
# (2) with +INF
- infarr = np.inf*np.ones(N, dtype='f')
+ infarr = np.inf*np.ones(N, dtype=dtype)
infarr[np.random.choice(infarr.shape[0], 5)] = -1.0
assert_equal(np.sort(infarr, kind='quick'), np.sort(infarr, kind='heap'))
# (3) with -INF
- neginfarr = -np.inf*np.ones(N, dtype='f')
+ neginfarr = -np.inf*np.ones(N, dtype=dtype)
neginfarr[np.random.choice(neginfarr.shape[0], 5)] = 1.0
assert_equal(np.sort(neginfarr, kind='quick'),
np.sort(neginfarr, kind='heap'))
# (4) with +/-INF
- infarr = np.inf*np.ones(N, dtype='f')
+ infarr = np.inf*np.ones(N, dtype=dtype)
infarr[np.random.choice(infarr.shape[0], (int)(N/2))] = -np.inf
assert_equal(np.sort(infarr, kind='quick'), np.sort(infarr, kind='heap'))
-
-def test_sort_int():
- # Random data with NPY_MAX_INT32 and NPY_MIN_INT32 sprinkled
- rng = np.random.default_rng(42)
- N = 2047
- minv = np.iinfo(np.int32).min
- maxv = np.iinfo(np.int32).max
- arr = rng.integers(low=minv, high=maxv, size=N).astype('int32')
+def test_sort_float16():
+ arr = np.arange(65536, dtype=np.int16)
+ temp = np.frombuffer(arr.tobytes(), dtype=np.float16)
+ data = np.copy(temp)
+ np.random.shuffle(data)
+ data_backup = data
+ assert_equal(np.sort(data, kind='quick'),
+ np.sort(data_backup, kind='heap'))
+
+
+@pytest.mark.parametrize("N", np.arange(1, 512))
+@pytest.mark.parametrize("dtype", ['h', 'H', 'i', 'I', 'l', 'L'])
+def test_sort_int(N, dtype):
+ # Random data with MAX and MIN sprinkled
+ minv = np.iinfo(dtype).min
+ maxv = np.iinfo(dtype).max
+ arr = np.random.randint(low=minv, high=maxv-1, size=N, dtype=dtype)
arr[np.random.choice(arr.shape[0], 10)] = minv
arr[np.random.choice(arr.shape[0], 10)] = maxv
assert_equal(np.sort(arr, kind='quick'), np.sort(arr, kind='heap'))
@@ -9875,3 +9986,6 @@ def test_sort_uint():
arr = rng.integers(low=0, high=maxv, size=N).astype('uint32')
arr[np.random.choice(arr.shape[0], 10)] = maxv
assert_equal(np.sort(arr, kind='quick'), np.sort(arr, kind='heap'))
+
+def test_private_get_ndarray_c_version():
+ assert isinstance(_get_ndarray_c_version(), int)
diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py
index b88afdfa1..9f639c4c1 100644
--- a/numpy/core/tests/test_nditer.py
+++ b/numpy/core/tests/test_nditer.py
@@ -1457,6 +1457,38 @@ def test_iter_copy_casts_structured():
assert_array_equal(res2["b"][field], expected)
+def test_iter_copy_casts_structured2():
+ # Similar to the above, this is a fairly arcane test to cover internals
+ in_dtype = np.dtype([("a", np.dtype("O,O")),
+ ("b", np.dtype("(5)O,(3)O,(1,)O,(1,)i,(1,)O"))])
+ out_dtype = np.dtype([("a", np.dtype("O")),
+ ("b", np.dtype("O,(3)i,(4)O,(4)O,(4)i"))])
+
+ arr = np.ones(1, dtype=in_dtype)
+ it = np.nditer((arr,), ["buffered", "external_loop", "refs_ok"],
+ op_dtypes=[out_dtype], casting="unsafe")
+ it_copy = it.copy()
+
+ res1 = next(it)
+ del it
+ res2 = next(it_copy)
+ del it_copy
+
+ # Array of two structured scalars:
+ for res in res1, res2:
+ # Cast to tuple by getitem, which may be weird and changable?:
+ assert type(res["a"][0]) == tuple
+ assert res["a"][0] == (1, 1)
+
+ for res in res1, res2:
+ assert_array_equal(res["b"]["f0"][0], np.ones(5, dtype=object))
+ assert_array_equal(res["b"]["f1"], np.ones((1, 3), dtype="i"))
+ assert res["b"]["f2"].shape == (1, 4)
+ assert_array_equal(res["b"]["f2"][0], np.ones(4, dtype=object))
+ assert_array_equal(res["b"]["f3"][0], np.ones(4, dtype=object))
+ assert_array_equal(res["b"]["f3"][0], np.ones(4, dtype="i"))
+
+
def test_iter_allocate_output_simple():
# Check that the iterator will properly allocate outputs
@@ -2257,7 +2289,7 @@ def test_iter_buffering_string():
assert_equal(i[0], b'abc')
assert_equal(i[0].dtype, np.dtype('S6'))
- a = np.array(['abc', 'a', 'abcd'], dtype=np.unicode_)
+ a = np.array(['abc', 'a', 'abcd'], dtype=np.str_)
assert_equal(a.dtype, np.dtype('U4'))
assert_raises(TypeError, nditer, a, ['buffered'], ['readonly'],
op_dtypes='U2')
diff --git a/numpy/core/tests/test_nep50_promotions.py b/numpy/core/tests/test_nep50_promotions.py
index 3c0316960..7d52c5089 100644
--- a/numpy/core/tests/test_nep50_promotions.py
+++ b/numpy/core/tests/test_nep50_promotions.py
@@ -131,7 +131,7 @@ def test_nep50_weak_integers_with_inexact(dtype):
@pytest.mark.parametrize("op", [operator.add, operator.pow, operator.eq])
def test_weak_promotion_scalar_path(op):
- # Some additional paths excercising the weak scalars.
+ # Some additional paths exercising the weak scalars.
np._set_promotion_state("weak")
# Integer path:
@@ -180,3 +180,55 @@ def test_nep50_integer_regression():
arr = np.array(1)
assert (arr + 2**63).dtype == np.float64
assert (arr[()] + 2**63).dtype == np.float64
+
+
+def test_nep50_with_axisconcatenator():
+ # I promised that this will be an error in the future in the 1.25
+ # release notes; test this (NEP 50 opt-in makes the deprecation an error).
+ np._set_promotion_state("weak")
+
+ with pytest.raises(OverflowError):
+ np.r_[np.arange(5, dtype=np.int8), 255]
+
+
+@pytest.mark.parametrize("ufunc", [np.add, np.power])
+@pytest.mark.parametrize("state", ["weak", "weak_and_warn"])
+def test_nep50_huge_integers(ufunc, state):
+ # Very large integers are complicated, because they go to uint64 or
+ # object dtype. This tests covers a few possible paths (some of which
+ # cannot give the NEP 50 warnings).
+ np._set_promotion_state(state)
+
+ with pytest.raises(OverflowError):
+ ufunc(np.int64(0), 2**63) # 2**63 too large for int64
+
+ if state == "weak_and_warn":
+ with pytest.warns(UserWarning,
+ match="result dtype changed.*float64.*uint64"):
+ with pytest.raises(OverflowError):
+ ufunc(np.uint64(0), 2**64)
+ else:
+ with pytest.raises(OverflowError):
+ ufunc(np.uint64(0), 2**64) # 2**64 cannot be represented by uint64
+
+ # However, 2**63 can be represented by the uint64 (and that is used):
+ if state == "weak_and_warn":
+ with pytest.warns(UserWarning,
+ match="result dtype changed.*float64.*uint64"):
+ res = ufunc(np.uint64(1), 2**63)
+ else:
+ res = ufunc(np.uint64(1), 2**63)
+
+ assert res.dtype == np.uint64
+ assert res == ufunc(1, 2**63, dtype=object)
+
+ # The following paths fail to warn correctly about the change:
+ with pytest.raises(OverflowError):
+ ufunc(np.int64(1), 2**63) # np.array(2**63) would go to uint
+
+ with pytest.raises(OverflowError):
+ ufunc(np.int64(1), 2**100) # np.array(2**100) would go to object
+
+ # This would go to object and thus a Python float, not a NumPy one:
+ res = ufunc(1.0, 2**100)
+ assert isinstance(res, np.float64)
diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py
index 3cc168b34..832a47c92 100644
--- a/numpy/core/tests/test_numeric.py
+++ b/numpy/core/tests/test_numeric.py
@@ -114,7 +114,9 @@ class TestNonarrayArgs:
def test_cumproduct(self):
A = [[1, 2, 3], [4, 5, 6]]
- assert_(np.all(np.cumproduct(A) == np.array([1, 2, 6, 24, 120, 720])))
+ with assert_warns(DeprecationWarning):
+ expected = np.array([1, 2, 6, 24, 120, 720])
+ assert_(np.all(np.cumproduct(A) == expected))
def test_diagonal(self):
a = [[0, 1, 2, 3],
@@ -1193,8 +1195,8 @@ class TestFromiter:
expected = np.array(list(self.makegen()))
a = np.fromiter(self.makegen(), int)
a20 = np.fromiter(self.makegen(), int, 20)
- assert_(np.alltrue(a == expected, axis=0))
- assert_(np.alltrue(a20 == expected[:20], axis=0))
+ assert_(np.all(a == expected, axis=0))
+ assert_(np.all(a20 == expected[:20], axis=0))
def load_data(self, n, eindex):
# Utility method for the issue 2592 tests.
@@ -1822,20 +1824,11 @@ class TestClip:
self.nr = 5
self.nc = 3
- def fastclip(self, a, m, M, out=None, casting=None):
- if out is None:
- if casting is None:
- return a.clip(m, M)
- else:
- return a.clip(m, M, casting=casting)
- else:
- if casting is None:
- return a.clip(m, M, out)
- else:
- return a.clip(m, M, out, casting=casting)
+ def fastclip(self, a, m, M, out=None, **kwargs):
+ return a.clip(m, M, out=out, **kwargs)
def clip(self, a, m, M, out=None):
- # use slow-clip
+ # use a.choose to verify fastclip result
selector = np.less(a, m) + 2*np.greater(a, M)
return selector.choose((a, m, M), out=out)
@@ -1991,14 +1984,13 @@ class TestClip:
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
if casting is None:
- with assert_warns(DeprecationWarning):
- # NumPy 1.17.0, 2018-02-24 - casting is unsafe
+ with pytest.raises(TypeError):
self.fastclip(a, m, M, ac, casting=casting)
else:
# explicitly passing "unsafe" will silence warning
self.fastclip(a, m, M, ac, casting=casting)
- self.clip(a, m, M, act)
- assert_array_strict_equal(ac, act)
+ self.clip(a, m, M, act)
+ assert_array_strict_equal(ac, act)
def test_simple_int64_out(self):
# Test native int32 input with int32 scalar min/max and int64 out.
@@ -2018,9 +2010,7 @@ class TestClip:
M = np.float64(1)
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- with assert_warns(DeprecationWarning):
- # NumPy 1.17.0, 2018-02-24 - casting is unsafe
- self.fastclip(a, m, M, ac)
+ self.fastclip(a, m, M, out=ac, casting="unsafe")
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -2031,9 +2021,7 @@ class TestClip:
M = 2.0
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- with assert_warns(DeprecationWarning):
- # NumPy 1.17.0, 2018-02-24 - casting is unsafe
- self.fastclip(a, m, M, ac)
+ self.fastclip(a, m, M, out=ac, casting="unsafe")
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -2209,9 +2197,7 @@ class TestClip:
M = np.float64(2)
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- with assert_warns(DeprecationWarning):
- # NumPy 1.17.0, 2018-02-24 - casting is unsafe
- self.fastclip(a, m, M, ac)
+ self.fastclip(a, m, M, out=ac, casting="unsafe")
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -2233,9 +2219,7 @@ class TestClip:
M = np.float64(1)
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- with assert_warns(DeprecationWarning):
- # NumPy 1.17.0, 2018-02-24 - casting is unsafe
- self.fastclip(a, m, M, ac)
+ self.fastclip(a, m, M, out=ac, casting="unsafe")
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -2246,9 +2230,7 @@ class TestClip:
M = 2.0
ac = np.zeros(a.shape, dtype=np.int32)
act = ac.copy()
- with assert_warns(DeprecationWarning):
- # NumPy 1.17.0, 2018-02-24 - casting is unsafe
- self.fastclip(a, m, M, ac)
+ self.fastclip(a, m, M, out=ac, casting="unsafe")
self.clip(a, m, M, act)
assert_array_strict_equal(ac, act)
@@ -2301,16 +2283,11 @@ class TestClip:
def test_clip_nan(self):
d = np.arange(7.)
- with assert_warns(DeprecationWarning):
- assert_equal(d.clip(min=np.nan), d)
- with assert_warns(DeprecationWarning):
- assert_equal(d.clip(max=np.nan), d)
- with assert_warns(DeprecationWarning):
- assert_equal(d.clip(min=np.nan, max=np.nan), d)
- with assert_warns(DeprecationWarning):
- assert_equal(d.clip(min=-2, max=np.nan), d)
- with assert_warns(DeprecationWarning):
- assert_equal(d.clip(min=np.nan, max=10), d)
+ assert_equal(d.clip(min=np.nan), np.nan)
+ assert_equal(d.clip(max=np.nan), np.nan)
+ assert_equal(d.clip(min=np.nan, max=np.nan), np.nan)
+ assert_equal(d.clip(min=-2, max=np.nan), np.nan)
+ assert_equal(d.clip(min=np.nan, max=10), np.nan)
def test_object_clip(self):
a = np.arange(10, dtype=object)
@@ -2362,16 +2339,12 @@ class TestClip:
actual = np.clip(arr, amin, amax)
assert_equal(actual, exp)
- @pytest.mark.xfail(reason="no scalar nan propagation yet",
- raises=AssertionError,
- strict=True)
@pytest.mark.parametrize("arr, amin, amax", [
# problematic scalar nan case from hypothesis
(np.zeros(10, dtype=np.int64),
np.array(np.nan),
np.zeros(10, dtype=np.int32)),
])
- @pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_clip_scalar_nan_propagation(self, arr, amin, amax):
# enforcement of scalar nan propagation for comparisons
# called through clip()
diff --git a/numpy/core/tests/test_numerictypes.py b/numpy/core/tests/test_numerictypes.py
index 072cd65fe..bab5bf246 100644
--- a/numpy/core/tests/test_numerictypes.py
+++ b/numpy/core/tests/test_numerictypes.py
@@ -339,23 +339,28 @@ class TestEmptyField:
class TestCommonType:
def test_scalar_loses1(self):
- res = np.find_common_type(['f4', 'f4', 'i2'], ['f8'])
+ with pytest.warns(DeprecationWarning, match="np.find_common_type"):
+ res = np.find_common_type(['f4', 'f4', 'i2'], ['f8'])
assert_(res == 'f4')
def test_scalar_loses2(self):
- res = np.find_common_type(['f4', 'f4'], ['i8'])
+ with pytest.warns(DeprecationWarning, match="np.find_common_type"):
+ res = np.find_common_type(['f4', 'f4'], ['i8'])
assert_(res == 'f4')
def test_scalar_wins(self):
- res = np.find_common_type(['f4', 'f4', 'i2'], ['c8'])
+ with pytest.warns(DeprecationWarning, match="np.find_common_type"):
+ res = np.find_common_type(['f4', 'f4', 'i2'], ['c8'])
assert_(res == 'c8')
def test_scalar_wins2(self):
- res = np.find_common_type(['u4', 'i4', 'i4'], ['f4'])
+ with pytest.warns(DeprecationWarning, match="np.find_common_type"):
+ res = np.find_common_type(['u4', 'i4', 'i4'], ['f4'])
assert_(res == 'f8')
def test_scalar_wins3(self): # doesn't go up to 'f16' on purpose
- res = np.find_common_type(['u8', 'i8', 'i8'], ['f8'])
+ with pytest.warns(DeprecationWarning, match="np.find_common_type"):
+ res = np.find_common_type(['u8', 'i8', 'i8'], ['f8'])
assert_(res == 'f8')
class TestMultipleFields:
@@ -473,7 +478,8 @@ class TestMaximumSctype:
def test_complex(self, t):
assert_equal(np.maximum_sctype(t), np.sctypes['complex'][-1])
- @pytest.mark.parametrize('t', [np.bool_, np.object_, np.unicode_, np.bytes_, np.void])
+ @pytest.mark.parametrize('t', [np.bool_, np.object_, np.str_, np.bytes_,
+ np.void])
def test_other(self, t):
assert_equal(np.maximum_sctype(t), t)
@@ -485,7 +491,7 @@ class Test_sctype2char:
def test_scalar_type(self):
assert_equal(np.sctype2char(np.double), 'd')
assert_equal(np.sctype2char(np.int_), 'l')
- assert_equal(np.sctype2char(np.unicode_), 'U')
+ assert_equal(np.sctype2char(np.str_), 'U')
assert_equal(np.sctype2char(np.bytes_), 'S')
def test_other_type(self):
diff --git a/numpy/core/tests/test_overrides.py b/numpy/core/tests/test_overrides.py
index 63432ffa7..5924358ea 100644
--- a/numpy/core/tests/test_overrides.py
+++ b/numpy/core/tests/test_overrides.py
@@ -10,16 +10,11 @@ from numpy.testing import (
assert_, assert_equal, assert_raises, assert_raises_regex)
from numpy.core.overrides import (
_get_implementing_args, array_function_dispatch,
- verify_matching_signatures, ARRAY_FUNCTION_ENABLED)
+ verify_matching_signatures)
from numpy.compat import pickle
import pytest
-requires_array_function = pytest.mark.skipif(
- not ARRAY_FUNCTION_ENABLED,
- reason="__array_function__ dispatch not enabled.")
-
-
def _return_not_implemented(self, *args, **kwargs):
return NotImplemented
@@ -150,7 +145,6 @@ class TestGetImplementingArgs:
class TestNDArrayArrayFunction:
- @requires_array_function
def test_method(self):
class Other:
@@ -209,7 +203,6 @@ class TestNDArrayArrayFunction:
args=(array,), kwargs={})
-@requires_array_function
class TestArrayFunctionDispatch:
def test_pickle(self):
@@ -248,8 +241,20 @@ class TestArrayFunctionDispatch:
with assert_raises_regex(TypeError, 'no implementation found'):
dispatched_one_arg(array)
+ def test_where_dispatch(self):
+
+ class DuckArray:
+ def __array_function__(self, ufunc, method, *inputs, **kwargs):
+ return "overridden"
+
+ array = np.array(1)
+ duck_array = DuckArray()
+
+ result = np.std(array, where=duck_array)
+
+ assert_equal(result, "overridden")
+
-@requires_array_function
class TestVerifyMatchingSignatures:
def test_verify_matching_signatures(self):
@@ -302,7 +307,6 @@ def _new_duck_type_and_implements():
return (MyArray, implements)
-@requires_array_function
class TestArrayFunctionImplementation:
def test_one_arg(self):
@@ -355,6 +359,17 @@ class TestArrayFunctionImplementation:
TypeError, "no implementation found for 'my.func'"):
func(MyArray())
+ @pytest.mark.parametrize("name", ["concatenate", "mean", "asarray"])
+ def test_signature_error_message_simple(self, name):
+ func = getattr(np, name)
+ try:
+ # all of these functions need an argument:
+ func()
+ except TypeError as e:
+ exc = e
+
+ assert exc.args[0].startswith(f"{name}()")
+
def test_signature_error_message(self):
# The lambda function will be named "<lambda>", but the TypeError
# should show the name as "func"
@@ -366,7 +381,7 @@ class TestArrayFunctionImplementation:
pass
try:
- func(bad_arg=3)
+ func._implementation(bad_arg=3)
except TypeError as e:
expected_exception = e
@@ -374,6 +389,12 @@ class TestArrayFunctionImplementation:
func(bad_arg=3)
raise AssertionError("must fail")
except TypeError as exc:
+ if exc.args[0].startswith("_dispatcher"):
+ # We replace the qualname currently, but it used `__name__`
+ # (relevant functions have the same name and qualname anyway)
+ pytest.skip("Python version is not using __qualname__ for "
+ "TypeError formatting.")
+
assert exc.args == expected_exception.args
@pytest.mark.parametrize("value", [234, "this func is not replaced"])
@@ -394,6 +415,56 @@ class TestArrayFunctionImplementation:
except TypeError as exc:
assert exc is error # unmodified exception
+ def test_properties(self):
+ # Check that str and repr are sensible
+ func = dispatched_two_arg
+ assert str(func) == str(func._implementation)
+ repr_no_id = repr(func).split("at ")[0]
+ repr_no_id_impl = repr(func._implementation).split("at ")[0]
+ assert repr_no_id == repr_no_id_impl
+
+ @pytest.mark.parametrize("func", [
+ lambda x, y: 0, # no like argument
+ lambda like=None: 0, # not keyword only
+ lambda *, like=None, a=3: 0, # not last (not that it matters)
+ ])
+ def test_bad_like_sig(self, func):
+ # We sanity check the signature, and these should fail.
+ with pytest.raises(RuntimeError):
+ array_function_dispatch()(func)
+
+ def test_bad_like_passing(self):
+ # Cover internal sanity check for passing like as first positional arg
+ def func(*, like=None):
+ pass
+
+ func_with_like = array_function_dispatch()(func)
+ with pytest.raises(TypeError):
+ func_with_like()
+ with pytest.raises(TypeError):
+ func_with_like(like=234)
+
+ def test_too_many_args(self):
+ # Mainly a unit-test to increase coverage
+ objs = []
+ for i in range(40):
+ class MyArr:
+ def __array_function__(self, *args, **kwargs):
+ return NotImplemented
+
+ objs.append(MyArr())
+
+ def _dispatch(*args):
+ return args
+
+ @array_function_dispatch(_dispatch)
+ def func(*args):
+ pass
+
+ with pytest.raises(TypeError, match="maximum number"):
+ func(*objs)
+
+
class TestNDArrayMethods:
@@ -422,7 +493,6 @@ class TestNumPyFunctions:
signature = inspect.signature(np.sum)
assert_('axis' in signature.parameters)
- @requires_array_function
def test_override_sum(self):
MyArray, implements = _new_duck_type_and_implements()
@@ -432,7 +502,6 @@ class TestNumPyFunctions:
assert_equal(np.sum(MyArray()), 'yes')
- @requires_array_function
def test_sum_on_mock_array(self):
# We need a proxy for mocks because __array_function__ is only looked
@@ -453,7 +522,6 @@ class TestNumPyFunctions:
np.sum, (ArrayProxy,), (proxy,), {})
proxy.value.__array__.assert_not_called()
- @requires_array_function
def test_sum_forwarding_implementation(self):
class MyArray(np.ndarray):
@@ -505,7 +573,6 @@ class TestArrayLike:
def func_args(*args, **kwargs):
return args, kwargs
- @requires_array_function
def test_array_like_not_implemented(self):
self.add_method('array', self.MyArray)
@@ -538,7 +605,6 @@ class TestArrayLike:
@pytest.mark.parametrize('function, args, kwargs', _array_tests)
@pytest.mark.parametrize('numpy_ref', [True, False])
- @requires_array_function
def test_array_like(self, function, args, kwargs, numpy_ref):
self.add_method('array', self.MyArray)
self.add_method(function, self.MyArray)
@@ -571,7 +637,6 @@ class TestArrayLike:
@pytest.mark.parametrize('function, args, kwargs', _array_tests)
@pytest.mark.parametrize('ref', [1, [1], "MyNoArrayFunctionArray"])
- @requires_array_function
def test_no_array_function_like(self, function, args, kwargs, ref):
self.add_method('array', self.MyNoArrayFunctionArray)
self.add_method(function, self.MyNoArrayFunctionArray)
@@ -613,7 +678,6 @@ class TestArrayLike:
assert type(array_like) is self.MyArray
assert array_like.function is self.MyArray.fromfile
- @requires_array_function
def test_exception_handling(self):
self.add_method('array', self.MyArray, enable_value_error=True)
@@ -640,3 +704,56 @@ class TestArrayLike:
array_like.fill(1)
expected.fill(1)
assert_equal(array_like, expected)
+
+
+def test_function_like():
+ # We provide a `__get__` implementation, make sure it works
+ assert type(np.mean) is np.core._multiarray_umath._ArrayFunctionDispatcher
+
+ class MyClass:
+ def __array__(self):
+ # valid argument to mean:
+ return np.arange(3)
+
+ func1 = staticmethod(np.mean)
+ func2 = np.mean
+ func3 = classmethod(np.mean)
+
+ m = MyClass()
+ assert m.func1([10]) == 10
+ assert m.func2() == 1 # mean of the arange
+ with pytest.raises(TypeError, match="unsupported operand type"):
+ # Tries to operate on the class
+ m.func3()
+
+ # Manual binding also works (the above may shortcut):
+ bound = np.mean.__get__(m, MyClass)
+ assert bound() == 1
+
+ bound = np.mean.__get__(None, MyClass) # unbound actually
+ assert bound([10]) == 10
+
+ bound = np.mean.__get__(MyClass) # classmethod
+ with pytest.raises(TypeError, match="unsupported operand type"):
+ bound()
+
+
+def test_scipy_trapz_support_shim():
+ # SciPy 1.10 and earlier "clone" trapz in this way, so we have a
+ # support shim in place: https://github.com/scipy/scipy/issues/17811
+ # That should be removed eventually. This test copies what SciPy does.
+ # Hopefully removable 1 year after SciPy 1.11; shim added to NumPy 1.25.
+ import types
+ import functools
+
+ def _copy_func(f):
+ # Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)
+ g = types.FunctionType(f.__code__, f.__globals__, name=f.__name__,
+ argdefs=f.__defaults__, closure=f.__closure__)
+ g = functools.update_wrapper(g, f)
+ g.__kwdefaults__ = f.__kwdefaults__
+ return g
+
+ trapezoid = _copy_func(np.trapz)
+
+ assert np.trapz([1, 2]) == trapezoid([1, 2])
diff --git a/numpy/core/tests/test_print.py b/numpy/core/tests/test_print.py
index 89a8b48bf..162686ee0 100644
--- a/numpy/core/tests/test_print.py
+++ b/numpy/core/tests/test_print.py
@@ -3,7 +3,7 @@ import sys
import pytest
import numpy as np
-from numpy.testing import assert_, assert_equal
+from numpy.testing import assert_, assert_equal, IS_MUSL
from numpy.core.tests._locales import CommaDecimalPointLocale
@@ -196,5 +196,7 @@ class TestCommaDecimalPointLocale(CommaDecimalPointLocale):
def test_locale_double(self):
assert_equal(str(np.double(1.2)), str(float(1.2)))
+ @pytest.mark.skipif(IS_MUSL,
+ reason="test flaky on musllinux")
def test_locale_longdouble(self):
assert_equal(str(np.longdouble('1.2')), str(float(1.2)))
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index f638284de..841144790 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -292,7 +292,7 @@ class TestRegression:
def test_unicode_string_comparison(self):
# Ticket #190
- a = np.array('hello', np.unicode_)
+ a = np.array('hello', np.str_)
b = np.array('world')
a == b
@@ -455,7 +455,7 @@ class TestRegression:
test_data = [
# (original, py2_pickle)
- (np.unicode_('\u6f2c'),
+ (np.str_('\u6f2c'),
b"cnumpy.core.multiarray\nscalar\np0\n(cnumpy\ndtype\np1\n"
b"(S'U1'\np2\nI0\nI1\ntp3\nRp4\n(I3\nS'<'\np5\nNNNI4\nI4\n"
b"I0\ntp6\nbS',o\\x00\\x00'\np7\ntp8\nRp9\n."),
@@ -516,22 +516,15 @@ class TestRegression:
def test_method_args(self):
# Make sure methods and functions have same default axis
# keyword and arguments
- funcs1 = ['argmax', 'argmin', 'sum', ('product', 'prod'),
- ('sometrue', 'any'),
- ('alltrue', 'all'), 'cumsum', ('cumproduct', 'cumprod'),
- 'ptp', 'cumprod', 'prod', 'std', 'var', 'mean',
- 'round', 'min', 'max', 'argsort', 'sort']
+ funcs1 = ['argmax', 'argmin', 'sum', 'any', 'all', 'cumsum',
+ 'ptp', 'cumprod', 'prod', 'std', 'var', 'mean',
+ 'round', 'min', 'max', 'argsort', 'sort']
funcs2 = ['compress', 'take', 'repeat']
for func in funcs1:
arr = np.random.rand(8, 7)
arr2 = arr.copy()
- if isinstance(func, tuple):
- func_meth = func[1]
- func = func[0]
- else:
- func_meth = func
- res1 = getattr(arr, func_meth)()
+ res1 = getattr(arr, func)()
res2 = getattr(np, func)(arr2)
if res1 is None:
res1 = arr
@@ -1336,8 +1329,8 @@ class TestRegression:
# Ticket #1058
a = np.fromiter(list(range(10)), dtype='b')
b = np.fromiter(list(range(10)), dtype='B')
- assert_(np.alltrue(a == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])))
- assert_(np.alltrue(b == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])))
+ assert_(np.all(a == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])))
+ assert_(np.all(b == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])))
def test_array_from_sequence_scalar_array(self):
# Ticket #1078: segfaults when creating an array with a sequence of
@@ -1515,8 +1508,8 @@ class TestRegression:
def test_fromiter_comparison(self):
a = np.fromiter(list(range(10)), dtype='b')
b = np.fromiter(list(range(10)), dtype='B')
- assert_(np.alltrue(a == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])))
- assert_(np.alltrue(b == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])))
+ assert_(np.all(a == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])))
+ assert_(np.all(b == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])))
def test_fromstring_crash(self):
# Ticket #1345: the following should not cause a crash
@@ -1535,9 +1528,12 @@ class TestRegression:
for y in dtypes:
c = a.astype(y)
try:
- np.dot(b, c)
+ d = np.dot(b, c)
except TypeError:
failures.append((x, y))
+ else:
+ if d != 0:
+ failures.append((x, y))
if failures:
raise AssertionError("Failures: %r" % failures)
@@ -1671,7 +1667,9 @@ class TestRegression:
def test_find_common_type_boolean(self):
# Ticket #1695
- assert_(np.find_common_type([], ['?', '?']) == '?')
+ with pytest.warns(DeprecationWarning, match="np.find_common_type"):
+ res = np.find_common_type([], ['?', '?'])
+ assert res == '?'
def test_empty_mul(self):
a = np.array([1.])
@@ -1685,7 +1683,7 @@ class TestRegression:
# number 2, and the exception hung around until something checked
# PyErr_Occurred() and returned an error.
assert_equal(np.dtype('S10').itemsize, 10)
- np.array([['abc', 2], ['long ', '0123456789']], dtype=np.string_)
+ np.array([['abc', 2], ['long ', '0123456789']], dtype=np.bytes_)
assert_equal(np.dtype('S10').itemsize, 10)
def test_any_float(self):
@@ -1954,7 +1952,7 @@ class TestRegression:
# Python2 output for pickle.dumps(...)
datas = [
# (original, python2_pickle, koi8r_validity)
- (np.unicode_('\u6bd2'),
+ (np.str_('\u6bd2'),
(b"cnumpy.core.multiarray\nscalar\np0\n(cnumpy\ndtype\np1\n"
b"(S'U1'\np2\nI0\nI1\ntp3\nRp4\n(I3\nS'<'\np5\nNNNI4\nI4\nI0\n"
b"tp6\nbS'\\xd2k\\x00\\x00'\np7\ntp8\nRp9\n."),
@@ -2078,7 +2076,7 @@ class TestRegression:
# Ticket #1578, the mismatch only showed up when running
# python-debug for python versions >= 2.7, and then as
# a core dump and error message.
- a = np.array(['abc'], dtype=np.unicode_)[0]
+ a = np.array(['abc'], dtype=np.str_)[0]
del a
def test_refcount_error_in_clip(self):
@@ -2225,7 +2223,7 @@ class TestRegression:
def test_pickle_empty_string(self):
# gh-3926
for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
- test_string = np.string_('')
+ test_string = np.bytes_('')
assert_equal(pickle.loads(
pickle.dumps(test_string, protocol=proto)), test_string)
@@ -2346,7 +2344,7 @@ class TestRegression:
values = {
np.void: b"a",
np.bytes_: b"a",
- np.unicode_: "a",
+ np.str_: "a",
np.datetime64: "2017-08-25",
}
for sctype in scalar_types:
@@ -2553,3 +2551,14 @@ class TestRegression:
f"Unexpected types order of ufunc in {operation}"
f"for {order}. Possible fix: Use signed before unsigned"
"in generate_umath.py")
+
+ def test_nonbool_logical(self):
+ # gh-22845
+ # create two arrays with bit patterns that do not overlap.
+ # needs to be large enough to test both SIMD and scalar paths
+ size = 100
+ a = np.frombuffer(b'\x01' * size, dtype=np.bool_)
+ b = np.frombuffer(b'\x80' * size, dtype=np.bool_)
+ expected = np.ones(size, dtype=np.bool_)
+ assert_array_equal(np.logical_and(a, b), expected)
+
diff --git a/numpy/core/tests/test_scalar_methods.py b/numpy/core/tests/test_scalar_methods.py
index a53e47b19..18a7bc828 100644
--- a/numpy/core/tests/test_scalar_methods.py
+++ b/numpy/core/tests/test_scalar_methods.py
@@ -1,7 +1,6 @@
"""
Test the scalar constructors, which also do type-coercion
"""
-import sys
import fractions
import platform
import types
@@ -10,7 +9,7 @@ from typing import Any, Type
import pytest
import numpy as np
-from numpy.testing import assert_equal, assert_raises
+from numpy.testing import assert_equal, assert_raises, IS_MUSL
class TestAsIntegerRatio:
@@ -99,6 +98,8 @@ class TestAsIntegerRatio:
try:
nf = np.longdouble(n)
df = np.longdouble(d)
+ if not np.isfinite(df):
+ raise OverflowError
except (OverflowError, RuntimeWarning):
# the values may not fit in any float type
pytest.skip("longdouble too small on this platform")
@@ -132,7 +133,6 @@ class TestIsInteger:
assert not value.is_integer()
-@pytest.mark.skipif(sys.version_info < (3, 9), reason="Requires python 3.9")
class TestClassGetItem:
@pytest.mark.parametrize("cls", [
np.number,
@@ -186,14 +186,6 @@ class TestClassGetItem:
assert np.number[Any]
-@pytest.mark.skipif(sys.version_info >= (3, 9), reason="Requires python 3.8")
-@pytest.mark.parametrize("cls", [np.number, np.complexfloating, np.int64])
-def test_class_getitem_38(cls: Type[np.number]) -> None:
- match = "Type subscription requires python >= 3.9"
- with pytest.raises(TypeError, match=match):
- cls[Any]
-
-
class TestBitCount:
# derived in part from the cpython test "test_bit_count"
diff --git a/numpy/core/tests/test_scalarbuffer.py b/numpy/core/tests/test_scalarbuffer.py
index 0e6ab1015..31b0494cf 100644
--- a/numpy/core/tests/test_scalarbuffer.py
+++ b/numpy/core/tests/test_scalarbuffer.py
@@ -68,11 +68,11 @@ class TestScalarPEP3118:
get_buffer_info(x, ["WRITABLE"])
def test_void_scalar_structured_data(self):
- dt = np.dtype([('name', np.unicode_, 16), ('grades', np.float64, (2,))])
+ dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])
x = np.array(('ndarray_scalar', (1.2, 3.0)), dtype=dt)[()]
assert_(isinstance(x, np.void))
mv_x = memoryview(x)
- expected_size = 16 * np.dtype((np.unicode_, 1)).itemsize
+ expected_size = 16 * np.dtype((np.str_, 1)).itemsize
expected_size += 2 * np.dtype(np.float64).itemsize
assert_equal(mv_x.itemsize, expected_size)
assert_equal(mv_x.ndim, 0)
diff --git a/numpy/core/tests/test_scalarinherit.py b/numpy/core/tests/test_scalarinherit.py
index f697c3c81..f9c574d57 100644
--- a/numpy/core/tests/test_scalarinherit.py
+++ b/numpy/core/tests/test_scalarinherit.py
@@ -58,8 +58,8 @@ class TestInherit:
class TestCharacter:
def test_char_radd(self):
# GH issue 9620, reached gentype_add and raise TypeError
- np_s = np.string_('abc')
- np_u = np.unicode_('abc')
+ np_s = np.bytes_('abc')
+ np_u = np.str_('abc')
s = b'def'
u = 'def'
assert_(np_s.__radd__(np_s) is NotImplemented)
@@ -90,8 +90,8 @@ class TestCharacter:
assert ret == b"defabc"
def test_char_repeat(self):
- np_s = np.string_('abc')
- np_u = np.unicode_('abc')
+ np_s = np.bytes_('abc')
+ np_u = np.str_('abc')
res_s = b'abc' * 5
res_u = 'abc' * 5
assert_(np_s * 5 == res_s)
diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py
index 8de821340..c737099c1 100644
--- a/numpy/core/tests/test_scalarmath.py
+++ b/numpy/core/tests/test_scalarmath.py
@@ -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
diff --git a/numpy/core/tests/test_scalarprint.py b/numpy/core/tests/test_scalarprint.py
index 4deb5a0a4..98d1f4aa1 100644
--- a/numpy/core/tests/test_scalarprint.py
+++ b/numpy/core/tests/test_scalarprint.py
@@ -8,7 +8,7 @@ import sys
from tempfile import TemporaryFile
import numpy as np
-from numpy.testing import assert_, assert_equal, assert_raises
+from numpy.testing import assert_, assert_equal, assert_raises, IS_MUSL
class TestRealScalars:
def test_str(self):
@@ -260,10 +260,10 @@ class TestRealScalars:
assert_equal(fpos64('324', unique=False, precision=5,
fractional=False), "324.00")
-
def test_dragon4_interface(self):
tps = [np.float16, np.float32, np.float64]
- if hasattr(np, 'float128'):
+ # test is flaky for musllinux on np.float128
+ if hasattr(np, 'float128') and not IS_MUSL:
tps.append(np.float128)
fpos = np.format_float_positional
diff --git a/numpy/core/tests/test_shape_base.py b/numpy/core/tests/test_shape_base.py
index 570d006f5..0428b95a9 100644
--- a/numpy/core/tests/test_shape_base.py
+++ b/numpy/core/tests/test_shape_base.py
@@ -152,9 +152,9 @@ class TestHstack:
assert_array_equal(res, desired)
def test_generator(self):
- with assert_warns(FutureWarning):
+ with pytest.raises(TypeError, match="arrays to stack must be"):
hstack((np.arange(3) for _ in range(2)))
- with assert_warns(FutureWarning):
+ with pytest.raises(TypeError, match="arrays to stack must be"):
hstack(map(lambda x: x, np.ones((3, 2))))
def test_casting_and_dtype(self):
@@ -207,7 +207,7 @@ class TestVstack:
assert_array_equal(res, desired)
def test_generator(self):
- with assert_warns(FutureWarning):
+ with pytest.raises(TypeError, match="arrays to stack must be"):
vstack((np.arange(3) for _ in range(2)))
def test_casting_and_dtype(self):
@@ -472,10 +472,11 @@ def test_stack():
stack, [np.zeros((3, 3)), np.zeros(3)], axis=1)
assert_raises_regex(ValueError, 'must have the same shape',
stack, [np.arange(2), np.arange(3)])
- # generator is deprecated
- with assert_warns(FutureWarning):
- result = stack((x for x in range(3)))
- assert_array_equal(result, np.array([0, 1, 2]))
+
+ # do not accept generators
+ with pytest.raises(TypeError, match="arrays to stack must be"):
+ stack((x for x in range(3)))
+
#casting and dtype test
a = np.array([1, 2, 3])
b = np.array([2.5, 3.5, 4.5])
diff --git a/numpy/core/tests/test_simd.py b/numpy/core/tests/test_simd.py
index 264300621..92b567446 100644
--- a/numpy/core/tests/test_simd.py
+++ b/numpy/core/tests/test_simd.py
@@ -2,9 +2,24 @@
# may be involved in their functionality.
import pytest, math, re
import itertools
-from numpy.core._simd import targets
+import operator
+from numpy.core._simd import targets, clear_floatstatus, get_floatstatus
from numpy.core._multiarray_umath import __cpu_baseline__
+def check_floatstatus(divbyzero=False, overflow=False,
+ underflow=False, invalid=False,
+ all=False):
+ #define NPY_FPE_DIVIDEBYZERO 1
+ #define NPY_FPE_OVERFLOW 2
+ #define NPY_FPE_UNDERFLOW 4
+ #define NPY_FPE_INVALID 8
+ err = get_floatstatus()
+ ret = (all or divbyzero) and (err & 1) != 0
+ ret |= (all or overflow) and (err & 2) != 0
+ ret |= (all or underflow) and (err & 4) != 0
+ ret |= (all or invalid) and (err & 8) != 0
+ return ret
+
class _Test_Utility:
# submodule of the desired SIMD extension, e.g. targets["AVX512F"]
npyv = None
@@ -20,6 +35,9 @@ class _Test_Utility:
"""
return getattr(self.npyv, attr + "_" + self.sfx)
+ def _x2(self, intrin_name):
+ return getattr(self.npyv, f"{intrin_name}_{self.sfx}x2")
+
def _data(self, start=None, count=None, reverse=False):
"""
Create list of consecutive numbers according to number of vector's lanes.
@@ -365,6 +383,11 @@ class _SIMD_FP(_Test_Utility):
nfms = self.nmulsub(vdata_a, vdata_b, vdata_c)
data_nfms = self.mul(data_fma, self.setall(-1))
assert nfms == data_nfms
+ # multiply, add for odd elements and subtract even elements.
+ # (a * b) -+ c
+ fmas = list(self.muladdsub(vdata_a, vdata_b, vdata_c))
+ assert fmas[0::2] == list(data_fms)[0::2]
+ assert fmas[1::2] == list(data_fma)[1::2]
def test_abs(self):
pinf, ninf, nan = self._pinfinity(), self._ninfinity(), self._nan()
@@ -553,7 +576,16 @@ class _SIMD_FP(_Test_Utility):
nnan = self.notnan(self.setall(self._nan()))
assert nnan == [0]*self.nlanes
- import operator
+ @pytest.mark.parametrize("intrin_name", [
+ "rint", "trunc", "ceil", "floor"
+ ])
+ def test_unary_invalid_fpexception(self, intrin_name):
+ intrin = getattr(self, intrin_name)
+ for d in [float("nan"), float("inf"), -float("inf")]:
+ v = self.setall(d)
+ clear_floatstatus()
+ intrin(v)
+ assert check_floatstatus(invalid=True) == False
@pytest.mark.parametrize('py_comp,np_comp', [
(operator.lt, "cmplt"),
@@ -571,7 +603,8 @@ class _SIMD_FP(_Test_Utility):
return [lane == mask_true for lane in vector]
intrin = getattr(self, np_comp)
- cmp_cases = ((0, nan), (nan, 0), (nan, nan), (pinf, nan), (ninf, nan))
+ cmp_cases = ((0, nan), (nan, 0), (nan, nan), (pinf, nan),
+ (ninf, nan), (-0.0, +0.0))
for case_operand1, case_operand2 in cmp_cases:
data_a = [case_operand1]*self.nlanes
data_b = [case_operand2]*self.nlanes
@@ -653,25 +686,34 @@ class _SIMD_ALL(_Test_Utility):
assert store_h[:self.nlanes//2] == data[self.nlanes//2:]
assert store_h != vdata # detect overflow
- def test_memory_partial_load(self):
- if self.sfx in ("u8", "s8", "u16", "s16"):
+ @pytest.mark.parametrize("intrin, elsizes, scale, fill", [
+ ("self.load_tillz, self.load_till", (32, 64), 1, [0xffff]),
+ ("self.load2_tillz, self.load2_till", (32, 64), 2, [0xffff, 0x7fff]),
+ ])
+ def test_memory_partial_load(self, intrin, elsizes, scale, fill):
+ if self._scalar_size() not in elsizes:
return
-
+ npyv_load_tillz, npyv_load_till = eval(intrin)
data = self._data()
lanes = list(range(1, self.nlanes + 1))
lanes += [self.nlanes**2, self.nlanes**4] # test out of range
for n in lanes:
- load_till = self.load_till(data, n, 15)
- data_till = data[:n] + [15] * (self.nlanes-n)
+ load_till = npyv_load_till(data, n, *fill)
+ load_tillz = npyv_load_tillz(data, n)
+ n *= scale
+ data_till = data[:n] + fill * ((self.nlanes-n) // scale)
assert load_till == data_till
- load_tillz = self.load_tillz(data, n)
data_tillz = data[:n] + [0] * (self.nlanes-n)
assert load_tillz == data_tillz
- def test_memory_partial_store(self):
- if self.sfx in ("u8", "s8", "u16", "s16"):
+ @pytest.mark.parametrize("intrin, elsizes, scale", [
+ ("self.store_till", (32, 64), 1),
+ ("self.store2_till", (32, 64), 2),
+ ])
+ def test_memory_partial_store(self, intrin, elsizes, scale):
+ if self._scalar_size() not in elsizes:
return
-
+ npyv_store_till = eval(intrin)
data = self._data()
data_rev = self._data(reverse=True)
vdata = self.load(data)
@@ -679,105 +721,159 @@ class _SIMD_ALL(_Test_Utility):
lanes += [self.nlanes**2, self.nlanes**4]
for n in lanes:
data_till = data_rev.copy()
- data_till[:n] = data[:n]
+ data_till[:n*scale] = data[:n*scale]
store_till = self._data(reverse=True)
- self.store_till(store_till, n, vdata)
+ npyv_store_till(store_till, n, vdata)
assert store_till == data_till
- def test_memory_noncont_load(self):
- if self.sfx in ("u8", "s8", "u16", "s16"):
+ @pytest.mark.parametrize("intrin, elsizes, scale", [
+ ("self.loadn", (32, 64), 1),
+ ("self.loadn2", (32, 64), 2),
+ ])
+ def test_memory_noncont_load(self, intrin, elsizes, scale):
+ if self._scalar_size() not in elsizes:
return
-
- for stride in range(1, 64):
- data = self._data(count=stride*self.nlanes)
- data_stride = data[::stride]
- loadn = self.loadn(data, stride)
- assert loadn == data_stride
-
- for stride in range(-64, 0):
- data = self._data(stride, -stride*self.nlanes)
- data_stride = self.load(data[::stride]) # cast unsigned
- loadn = self.loadn(data, stride)
+ npyv_loadn = eval(intrin)
+ for stride in range(-64, 64):
+ if stride < 0:
+ data = self._data(stride, -stride*self.nlanes)
+ data_stride = list(itertools.chain(
+ *zip(*[data[-i::stride] for i in range(scale, 0, -1)])
+ ))
+ elif stride == 0:
+ data = self._data()
+ data_stride = data[0:scale] * (self.nlanes//scale)
+ else:
+ data = self._data(count=stride*self.nlanes)
+ data_stride = list(itertools.chain(
+ *zip(*[data[i::stride] for i in range(scale)]))
+ )
+ data_stride = self.load(data_stride) # cast unsigned
+ loadn = npyv_loadn(data, stride)
assert loadn == data_stride
- def test_memory_noncont_partial_load(self):
- if self.sfx in ("u8", "s8", "u16", "s16"):
+ @pytest.mark.parametrize("intrin, elsizes, scale, fill", [
+ ("self.loadn_tillz, self.loadn_till", (32, 64), 1, [0xffff]),
+ ("self.loadn2_tillz, self.loadn2_till", (32, 64), 2, [0xffff, 0x7fff]),
+ ])
+ def test_memory_noncont_partial_load(self, intrin, elsizes, scale, fill):
+ if self._scalar_size() not in elsizes:
return
-
+ npyv_loadn_tillz, npyv_loadn_till = eval(intrin)
lanes = list(range(1, self.nlanes + 1))
lanes += [self.nlanes**2, self.nlanes**4]
- for stride in range(1, 64):
- data = self._data(count=stride*self.nlanes)
- data_stride = data[::stride]
- for n in lanes:
- data_stride_till = data_stride[:n] + [15] * (self.nlanes-n)
- loadn_till = self.loadn_till(data, stride, n, 15)
- assert loadn_till == data_stride_till
- data_stride_tillz = data_stride[:n] + [0] * (self.nlanes-n)
- loadn_tillz = self.loadn_tillz(data, stride, n)
- assert loadn_tillz == data_stride_tillz
-
- for stride in range(-64, 0):
- data = self._data(stride, -stride*self.nlanes)
- data_stride = list(self.load(data[::stride])) # cast unsigned
+ for stride in range(-64, 64):
+ if stride < 0:
+ data = self._data(stride, -stride*self.nlanes)
+ data_stride = list(itertools.chain(
+ *zip(*[data[-i::stride] for i in range(scale, 0, -1)])
+ ))
+ elif stride == 0:
+ data = self._data()
+ data_stride = data[0:scale] * (self.nlanes//scale)
+ else:
+ data = self._data(count=stride*self.nlanes)
+ data_stride = list(itertools.chain(
+ *zip(*[data[i::stride] for i in range(scale)])
+ ))
+ data_stride = list(self.load(data_stride)) # cast unsigned
for n in lanes:
- data_stride_till = data_stride[:n] + [15] * (self.nlanes-n)
- loadn_till = self.loadn_till(data, stride, n, 15)
+ nscale = n * scale
+ llanes = self.nlanes - nscale
+ data_stride_till = (
+ data_stride[:nscale] + fill * (llanes//scale)
+ )
+ loadn_till = npyv_loadn_till(data, stride, n, *fill)
assert loadn_till == data_stride_till
- data_stride_tillz = data_stride[:n] + [0] * (self.nlanes-n)
- loadn_tillz = self.loadn_tillz(data, stride, n)
+ data_stride_tillz = data_stride[:nscale] + [0] * llanes
+ loadn_tillz = npyv_loadn_tillz(data, stride, n)
assert loadn_tillz == data_stride_tillz
- def test_memory_noncont_store(self):
- if self.sfx in ("u8", "s8", "u16", "s16"):
+ @pytest.mark.parametrize("intrin, elsizes, scale", [
+ ("self.storen", (32, 64), 1),
+ ("self.storen2", (32, 64), 2),
+ ])
+ def test_memory_noncont_store(self, intrin, elsizes, scale):
+ if self._scalar_size() not in elsizes:
return
-
- vdata = self.load(self._data())
+ npyv_storen = eval(intrin)
+ data = self._data()
+ vdata = self.load(data)
+ hlanes = self.nlanes // scale
for stride in range(1, 64):
- data = [15] * stride * self.nlanes
- data[::stride] = vdata
- storen = [15] * stride * self.nlanes
- storen += [127]*64
- self.storen(storen, stride, vdata)
- assert storen[:-64] == data
- assert storen[-64:] == [127]*64 # detect overflow
+ data_storen = [0xff] * stride * self.nlanes
+ for s in range(0, hlanes*stride, stride):
+ i = (s//stride)*scale
+ data_storen[s:s+scale] = data[i:i+scale]
+ storen = [0xff] * stride * self.nlanes
+ storen += [0x7f]*64
+ npyv_storen(storen, stride, vdata)
+ assert storen[:-64] == data_storen
+ assert storen[-64:] == [0x7f]*64 # detect overflow
for stride in range(-64, 0):
- data = [15] * -stride * self.nlanes
- data[::stride] = vdata
- storen = [127]*64
- storen += [15] * -stride * self.nlanes
- self.storen(storen, stride, vdata)
- assert storen[64:] == data
- assert storen[:64] == [127]*64 # detect overflow
-
- def test_memory_noncont_partial_store(self):
- if self.sfx in ("u8", "s8", "u16", "s16"):
+ data_storen = [0xff] * -stride * self.nlanes
+ for s in range(0, hlanes*stride, stride):
+ i = (s//stride)*scale
+ data_storen[s-scale:s or None] = data[i:i+scale]
+ storen = [0x7f]*64
+ storen += [0xff] * -stride * self.nlanes
+ npyv_storen(storen, stride, vdata)
+ assert storen[64:] == data_storen
+ assert storen[:64] == [0x7f]*64 # detect overflow
+ # stride 0
+ data_storen = [0x7f] * self.nlanes
+ storen = data_storen.copy()
+ data_storen[0:scale] = data[-scale:]
+ npyv_storen(storen, 0, vdata)
+ assert storen == data_storen
+
+ @pytest.mark.parametrize("intrin, elsizes, scale", [
+ ("self.storen_till", (32, 64), 1),
+ ("self.storen2_till", (32, 64), 2),
+ ])
+ def test_memory_noncont_partial_store(self, intrin, elsizes, scale):
+ if self._scalar_size() not in elsizes:
return
-
+ npyv_storen_till = eval(intrin)
data = self._data()
vdata = self.load(data)
lanes = list(range(1, self.nlanes + 1))
lanes += [self.nlanes**2, self.nlanes**4]
+ hlanes = self.nlanes // scale
for stride in range(1, 64):
for n in lanes:
- data_till = [15] * stride * self.nlanes
- data_till[::stride] = data[:n] + [15] * (self.nlanes-n)
- storen_till = [15] * stride * self.nlanes
- storen_till += [127]*64
- self.storen_till(storen_till, stride, n, vdata)
+ data_till = [0xff] * stride * self.nlanes
+ tdata = data[:n*scale] + [0xff] * (self.nlanes-n*scale)
+ for s in range(0, hlanes*stride, stride)[:n]:
+ i = (s//stride)*scale
+ data_till[s:s+scale] = tdata[i:i+scale]
+ storen_till = [0xff] * stride * self.nlanes
+ storen_till += [0x7f]*64
+ npyv_storen_till(storen_till, stride, n, vdata)
assert storen_till[:-64] == data_till
- assert storen_till[-64:] == [127]*64 # detect overflow
+ assert storen_till[-64:] == [0x7f]*64 # detect overflow
for stride in range(-64, 0):
for n in lanes:
- data_till = [15] * -stride * self.nlanes
- data_till[::stride] = data[:n] + [15] * (self.nlanes-n)
- storen_till = [127]*64
- storen_till += [15] * -stride * self.nlanes
- self.storen_till(storen_till, stride, n, vdata)
+ data_till = [0xff] * -stride * self.nlanes
+ tdata = data[:n*scale] + [0xff] * (self.nlanes-n*scale)
+ for s in range(0, hlanes*stride, stride)[:n]:
+ i = (s//stride)*scale
+ data_till[s-scale:s or None] = tdata[i:i+scale]
+ storen_till = [0x7f]*64
+ storen_till += [0xff] * -stride * self.nlanes
+ npyv_storen_till(storen_till, stride, n, vdata)
assert storen_till[64:] == data_till
- assert storen_till[:64] == [127]*64 # detect overflow
+ assert storen_till[:64] == [0x7f]*64 # detect overflow
+
+ # stride 0
+ for n in lanes:
+ data_till = [0x7f] * self.nlanes
+ storen_till = data_till.copy()
+ data_till[0:scale] = data[:n*scale][-scale:]
+ npyv_storen_till(storen_till, 0, n, vdata)
+ assert storen_till == data_till
@pytest.mark.parametrize("intrin, table_size, elsize", [
("self.lut32", 32, 32),
@@ -861,13 +957,27 @@ class _SIMD_ALL(_Test_Utility):
combineh = self.combineh(vdata_a, vdata_b)
assert combineh == data_a_hi + data_b_hi
# combine x2
- combine = self.combine(vdata_a, vdata_b)
+ combine = self.combine(vdata_a, vdata_b)
assert combine == (data_a_lo + data_b_lo, data_a_hi + data_b_hi)
+
# zip(interleave)
- data_zipl = [v for p in zip(data_a_lo, data_b_lo) for v in p]
- data_ziph = [v for p in zip(data_a_hi, data_b_hi) for v in p]
- vzip = self.zip(vdata_a, vdata_b)
+ data_zipl = self.load([
+ v for p in zip(data_a_lo, data_b_lo) for v in p
+ ])
+ data_ziph = self.load([
+ v for p in zip(data_a_hi, data_b_hi) for v in p
+ ])
+ vzip = self.zip(vdata_a, vdata_b)
assert vzip == (data_zipl, data_ziph)
+ vzip = [0]*self.nlanes*2
+ self._x2("store")(vzip, (vdata_a, vdata_b))
+ assert vzip == list(data_zipl) + list(data_ziph)
+
+ # unzip(deinterleave)
+ unzip = self.unzip(data_zipl, data_ziph)
+ assert unzip == (data_a, data_b)
+ unzip = self._x2("load")(list(data_zipl) + list(data_ziph))
+ assert unzip == (data_a, data_b)
def test_reorder_rev64(self):
# Reverse elements of each 64-bit lane
@@ -881,41 +991,51 @@ class _SIMD_ALL(_Test_Utility):
rev64 = self.rev64(self.load(range(self.nlanes)))
assert rev64 == data_rev64
- def test_operators_comparison(self):
+ def test_reorder_permi128(self):
+ """
+ Test permuting elements for each 128-bit lane.
+ npyv_permi128_##sfx
+ """
+ ssize = self._scalar_size()
+ if ssize < 32:
+ return
+ data = self.load(self._data())
+ permn = 128//ssize
+ permd = permn-1
+ nlane128 = self.nlanes//permn
+ shfl = [0, 1] if ssize == 64 else [0, 2, 4, 6]
+ for i in range(permn):
+ indices = [(i >> shf) & permd for shf in shfl]
+ vperm = self.permi128(data, *indices)
+ data_vperm = [
+ data[j + (e & -permn)]
+ for e, j in enumerate(indices*nlane128)
+ ]
+ assert vperm == data_vperm
+
+ @pytest.mark.parametrize('func, intrin', [
+ (operator.lt, "cmplt"),
+ (operator.le, "cmple"),
+ (operator.gt, "cmpgt"),
+ (operator.ge, "cmpge"),
+ (operator.eq, "cmpeq")
+ ])
+ def test_operators_comparison(self, func, intrin):
if self._is_fp():
data_a = self._data()
else:
data_a = self._data(self._int_max() - self.nlanes)
data_b = self._data(self._int_min(), reverse=True)
vdata_a, vdata_b = self.load(data_a), self.load(data_b)
+ intrin = getattr(self, intrin)
mask_true = self._true_mask()
def to_bool(vector):
return [lane == mask_true for lane in vector]
- # equal
- data_eq = [a == b for a, b in zip(data_a, data_b)]
- cmpeq = to_bool(self.cmpeq(vdata_a, vdata_b))
- assert cmpeq == data_eq
- # not equal
- data_neq = [a != b for a, b in zip(data_a, data_b)]
- cmpneq = to_bool(self.cmpneq(vdata_a, vdata_b))
- assert cmpneq == data_neq
- # greater than
- data_gt = [a > b for a, b in zip(data_a, data_b)]
- cmpgt = to_bool(self.cmpgt(vdata_a, vdata_b))
- assert cmpgt == data_gt
- # greater than and equal
- data_ge = [a >= b for a, b in zip(data_a, data_b)]
- cmpge = to_bool(self.cmpge(vdata_a, vdata_b))
- assert cmpge == data_ge
- # less than
- data_lt = [a < b for a, b in zip(data_a, data_b)]
- cmplt = to_bool(self.cmplt(vdata_a, vdata_b))
- assert cmplt == data_lt
- # less than and equal
- data_le = [a <= b for a, b in zip(data_a, data_b)]
- cmple = to_bool(self.cmple(vdata_a, vdata_b))
- assert cmple == data_le
+
+ data_cmp = [func(a, b) for a, b in zip(data_a, data_b)]
+ cmp = to_bool(intrin(vdata_a, vdata_b))
+ assert cmp == data_cmp
def test_operators_logical(self):
if self._is_fp():
@@ -1155,6 +1275,18 @@ class _SIMD_ALL(_Test_Utility):
ifadd = self.ifadd(false_mask, vdata_a, vdata_b, vdata_b)
assert ifadd == vdata_b
+ if not self._is_fp():
+ return
+ data_div = self.div(vdata_b, vdata_a)
+ ifdiv = self.ifdiv(true_mask, vdata_b, vdata_a, vdata_b)
+ assert ifdiv == data_div
+ ifdivz = self.ifdivz(true_mask, vdata_b, vdata_a)
+ assert ifdivz == data_div
+ ifdiv = self.ifdiv(false_mask, vdata_a, vdata_b, vdata_b)
+ assert ifdiv == vdata_b
+ ifdivz = self.ifdivz(false_mask, vdata_a, vdata_b)
+ assert ifdivz == self.zero()
+
bool_sfx = ("b8", "b16", "b32", "b64")
int_sfx = ("u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64")
fp_sfx = ("f32", "f64")
diff --git a/numpy/core/tests/test_strings.py b/numpy/core/tests/test_strings.py
index 2b87ed654..42f775e85 100644
--- a/numpy/core/tests/test_strings.py
+++ b/numpy/core/tests/test_strings.py
@@ -83,3 +83,17 @@ def test_string_comparisons_empty(op, ufunc, sym, dtypes):
assert_array_equal(op(arr, arr2), expected)
assert_array_equal(ufunc(arr, arr2), expected)
assert_array_equal(np.compare_chararrays(arr, arr2, sym, False), expected)
+
+
+@pytest.mark.parametrize("str_dt", ["S", "U"])
+@pytest.mark.parametrize("float_dt", np.typecodes["AllFloat"])
+def test_float_to_string_cast(str_dt, float_dt):
+ float_dt = np.dtype(float_dt)
+ fi = np.finfo(float_dt)
+ arr = np.array([np.nan, np.inf, -np.inf, fi.max, fi.min], dtype=float_dt)
+ expected = ["nan", "inf", "-inf", repr(fi.max), repr(fi.min)]
+ if float_dt.kind == 'c':
+ expected = [f"({r}+0j)" for r in expected]
+
+ res = arr.astype(str_dt)
+ assert_array_equal(res, np.array(expected, dtype=str_dt))
diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py
index 00aa48647..f716e2104 100644
--- a/numpy/core/tests/test_ufunc.py
+++ b/numpy/core/tests/test_ufunc.py
@@ -1650,6 +1650,19 @@ class TestUfunc:
a = a[1:, 1:, 1:]
self.check_identityless_reduction(a)
+ def test_reduce_identity_depends_on_loop(self):
+ """
+ The type of the result should always depend on the selected loop, not
+ necessarily the output (only relevant for object arrays).
+ """
+ # For an object loop, the default value 0 with type int is used:
+ assert type(np.add.reduce([], dtype=object)) is int
+ out = np.array(None, dtype=object)
+ # When the loop is float64 but `out` is object this does not happen,
+ # the result is float64 cast to object (which gives Python `float`).
+ np.add.reduce([], out=out, dtype=np.float64)
+ assert type(out[()]) is float
+
def test_initial_reduction(self):
# np.minimum.reduce is an identityless reduction
@@ -1670,6 +1683,9 @@ class TestUfunc:
# Check initial=None raises ValueError for both types of ufunc reductions
assert_raises(ValueError, np.minimum.reduce, [], initial=None)
assert_raises(ValueError, np.add.reduce, [], initial=None)
+ # Also in the somewhat special object case:
+ with pytest.raises(ValueError):
+ np.add.reduce([], initial=None, dtype=object)
# Check that np._NoValue gives default behavior.
assert_equal(np.add.reduce([], initial=np._NoValue), 0)
@@ -1679,6 +1695,23 @@ class TestUfunc:
res = np.add.reduce(a, initial=5)
assert_equal(res, 15)
+ def test_empty_reduction_and_idenity(self):
+ arr = np.zeros((0, 5))
+ # OK, since the reduction itself is *not* empty, the result is
+ assert np.true_divide.reduce(arr, axis=1).shape == (0,)
+ # Not OK, the reduction itself is empty and we have no idenity
+ with pytest.raises(ValueError):
+ np.true_divide.reduce(arr, axis=0)
+
+ # Test that an empty reduction fails also if the result is empty
+ arr = np.zeros((0, 0, 5))
+ with pytest.raises(ValueError):
+ np.true_divide.reduce(arr, axis=1)
+
+ # Division reduction makes sense with `initial=1` (empty or not):
+ res = np.true_divide.reduce(arr, axis=1, initial=1)
+ assert_array_equal(res, np.ones((0, 5)))
+
@pytest.mark.parametrize('axis', (0, 1, None))
@pytest.mark.parametrize('where', (np.array([False, True, True]),
np.array([[True], [False], [True]]),
@@ -1923,17 +1956,133 @@ class TestUfunc:
assert_(MyThing.rmul_count == 1, MyThing.rmul_count)
assert_(MyThing.getitem_count <= 2, MyThing.getitem_count)
- def test_inplace_fancy_indexing(self):
+ @pytest.mark.parametrize("a", (
+ np.arange(10, dtype=int),
+ np.arange(10, dtype=_rational_tests.rational),
+ ))
+ def test_ufunc_at_basic(self, a):
- a = np.arange(10)
- np.add.at(a, [2, 5, 2], 1)
- assert_equal(a, [0, 1, 4, 3, 4, 6, 6, 7, 8, 9])
+ aa = a.copy()
+ np.add.at(aa, [2, 5, 2], 1)
+ assert_equal(aa, [0, 1, 4, 3, 4, 6, 6, 7, 8, 9])
- a = np.arange(10)
+ with pytest.raises(ValueError):
+ # missing second operand
+ np.add.at(aa, [2, 5, 3])
+
+ aa = a.copy()
+ np.negative.at(aa, [2, 5, 3])
+ assert_equal(aa, [0, 1, -2, -3, 4, -5, 6, 7, 8, 9])
+
+ aa = a.copy()
b = np.array([100, 100, 100])
- np.add.at(a, [2, 5, 2], b)
- assert_equal(a, [0, 1, 202, 3, 4, 105, 6, 7, 8, 9])
+ np.add.at(aa, [2, 5, 2], b)
+ assert_equal(aa, [0, 1, 202, 3, 4, 105, 6, 7, 8, 9])
+
+ with pytest.raises(ValueError):
+ # extraneous second operand
+ np.negative.at(a, [2, 5, 3], [1, 2, 3])
+ with pytest.raises(ValueError):
+ # second operand cannot be converted to an array
+ np.add.at(a, [2, 5, 3], [[1, 2], 1])
+
+ # ufuncs with indexed loops for performance in ufunc.at
+ indexed_ufuncs = [np.add, np.subtract, np.multiply, np.floor_divide,
+ np.maximum, np.minimum, np.fmax, np.fmin]
+
+ @pytest.mark.parametrize(
+ "typecode", np.typecodes['AllInteger'] + np.typecodes['Float'])
+ @pytest.mark.parametrize("ufunc", indexed_ufuncs)
+ def test_ufunc_at_inner_loops(self, typecode, ufunc):
+ if ufunc is np.divide and typecode in np.typecodes['AllInteger']:
+ # Avoid divide-by-zero and inf for integer divide
+ a = np.ones(100, dtype=typecode)
+ indx = np.random.randint(100, size=30, dtype=np.intp)
+ vals = np.arange(1, 31, dtype=typecode)
+ else:
+ a = np.ones(1000, dtype=typecode)
+ indx = np.random.randint(1000, size=3000, dtype=np.intp)
+ vals = np.arange(3000, dtype=typecode)
+ atag = a.copy()
+ # Do the calculation twice and compare the answers
+ with warnings.catch_warnings(record=True) as w_at:
+ warnings.simplefilter('always')
+ ufunc.at(a, indx, vals)
+ with warnings.catch_warnings(record=True) as w_loop:
+ warnings.simplefilter('always')
+ for i, v in zip(indx, vals):
+ # Make sure all the work happens inside the ufunc
+ # in order to duplicate error/warning handling
+ ufunc(atag[i], v, out=atag[i:i+1], casting="unsafe")
+ assert_equal(atag, a)
+ # If w_loop warned, make sure w_at warned as well
+ if len(w_loop) > 0:
+ #
+ assert len(w_at) > 0
+ assert w_at[0].category == w_loop[0].category
+ assert str(w_at[0].message)[:10] == str(w_loop[0].message)[:10]
+
+ @pytest.mark.parametrize("typecode", np.typecodes['Complex'])
+ @pytest.mark.parametrize("ufunc", [np.add, np.subtract, np.multiply])
+ def test_ufunc_at_inner_loops_complex(self, typecode, ufunc):
+ a = np.ones(10, dtype=typecode)
+ indx = np.concatenate([np.ones(6, dtype=np.intp),
+ np.full(18, 4, dtype=np.intp)])
+ value = a.dtype.type(1j)
+ ufunc.at(a, indx, value)
+ expected = np.ones_like(a)
+ if ufunc is np.multiply:
+ expected[1] = expected[4] = -1
+ else:
+ expected[1] += 6 * (value if ufunc is np.add else -value)
+ expected[4] += 18 * (value if ufunc is np.add else -value)
+
+ assert_array_equal(a, expected)
+
+ def test_ufunc_at_ellipsis(self):
+ # Make sure the indexed loop check does not choke on iters
+ # with subspaces
+ arr = np.zeros(5)
+ np.add.at(arr, slice(None), np.ones(5))
+ assert_array_equal(arr, np.ones(5))
+
+ def test_ufunc_at_negative(self):
+ arr = np.ones(5, dtype=np.int32)
+ indx = np.arange(5)
+ umt.indexed_negative.at(arr, indx)
+ # If it is [-1, -1, -1, -100, 0] then the regular strided loop was used
+ assert np.all(arr == [-1, -1, -1, -200, -1])
+
+ def test_ufunc_at_large(self):
+ # issue gh-23457
+ indices = np.zeros(8195, dtype=np.int16)
+ b = np.zeros(8195, dtype=float)
+ b[0] = 10
+ b[1] = 5
+ b[8192:] = 100
+ a = np.zeros(1, dtype=float)
+ np.add.at(a, indices, b)
+ assert a[0] == b.sum()
+
+ def test_cast_index_fastpath(self):
+ arr = np.zeros(10)
+ values = np.ones(100000)
+ # index must be cast, which may be buffered in chunks:
+ index = np.zeros(len(values), dtype=np.uint8)
+ np.add.at(arr, index, values)
+ assert arr[0] == len(values)
+
+ @pytest.mark.parametrize("value", [
+ np.ones(1), np.ones(()), np.float64(1.), 1.])
+ def test_ufunc_at_scalar_value_fastpath(self, value):
+ arr = np.zeros(1000)
+ # index must be cast, which may be buffered in chunks:
+ index = np.repeat(np.arange(1000), 2)
+ np.add.at(arr, index, value)
+ assert_array_equal(arr, np.full_like(arr, 2 * value))
+
+ def test_ufunc_at_multiD(self):
a = np.arange(9).reshape(3, 3)
b = np.array([[100, 100, 100], [200, 200, 200], [300, 300, 300]])
np.add.at(a, (slice(None), [1, 2, 1]), b)
@@ -2013,11 +2162,7 @@ class TestUfunc:
[121, 222, 323],
[124, 225, 326]]])
- a = np.arange(10)
- np.negative.at(a, [2, 5, 2])
- assert_equal(a, [0, 1, 2, 3, 4, -5, 6, 7, 8, 9])
-
- # Test 0-dim array
+ def test_ufunc_at_0D(self):
a = np.array(0)
np.add.at(a, (), 1)
assert_equal(a, 1)
@@ -2025,11 +2170,13 @@ class TestUfunc:
assert_raises(IndexError, np.add.at, a, 0, 1)
assert_raises(IndexError, np.add.at, a, [], 1)
+ def test_ufunc_at_dtypes(self):
# Test mixed dtypes
a = np.arange(10)
np.power.at(a, [1, 2, 3, 2], 3.5)
assert_equal(a, np.array([0, 1, 4414, 46, 4, 5, 6, 7, 8, 9]))
+ def test_ufunc_at_boolean(self):
# Test boolean indexing and boolean ufuncs
a = np.arange(10)
index = a % 2 == 0
@@ -2041,6 +2188,7 @@ class TestUfunc:
np.invert.at(a, [2, 5, 2])
assert_equal(a, [0, 1, 2, 3, 4, 5 ^ 0xffffffff, 6, 7, 8, 9])
+ def test_ufunc_at_advanced(self):
# Test empty subspace
orig = np.arange(4)
a = orig[:, None][:, 0:0]
@@ -2064,7 +2212,7 @@ class TestUfunc:
# Test maximum
a = np.array([1, 2, 3])
np.maximum.at(a, [0], 0)
- assert_equal(np.array([1, 2, 3]), a)
+ assert_equal(a, np.array([1, 2, 3]))
def test_at_not_none_signature(self):
# Test ufuncs with non-trivial signature raise a TypeError
@@ -2075,6 +2223,23 @@ class TestUfunc:
a = np.array([[[1, 2], [3, 4]]])
assert_raises(TypeError, np.linalg._umath_linalg.det.at, a, [0])
+ def test_at_no_loop_for_op(self):
+ # str dtype does not have a ufunc loop for np.add
+ arr = np.ones(10, dtype=str)
+ with pytest.raises(np.core._exceptions._UFuncNoLoopError):
+ np.add.at(arr, [0, 1], [0, 1])
+
+ def test_at_output_casting(self):
+ arr = np.array([-1])
+ np.equal.at(arr, [0], [0])
+ assert arr[0] == 0
+
+ def test_at_broadcast_failure(self):
+ arr = np.arange(5)
+ with pytest.raises(ValueError):
+ np.add.at(arr, [0, 1], [1, 2, 3])
+
+
def test_reduce_arguments(self):
f = np.add.reduce
d = np.ones((5,2), dtype=int)
@@ -2580,7 +2745,9 @@ def test_reduce_casterrors(offset):
with pytest.raises(ValueError, match="invalid literal"):
# This is an unsafe cast, but we currently always allow that.
# Note that the double loop is picked, but the cast fails.
- np.add.reduce(arr, dtype=np.intp, out=out)
+ # `initial=None` disables the use of an identity here to test failures
+ # while copying the first values path (not used when identity exists).
+ np.add.reduce(arr, dtype=np.intp, out=out, initial=None)
assert count == sys.getrefcount(value)
# If an error occurred during casting, the operation is done at most until
# the error occurs (the result of which would be `value * offset`) and -1
@@ -2589,6 +2756,15 @@ def test_reduce_casterrors(offset):
assert out[()] < value * offset
+def test_object_reduce_cleanup_on_failure():
+ # Test cleanup, including of the initial value (manually provided or not)
+ with pytest.raises(TypeError):
+ np.add.reduce([1, 2, None], initial=4)
+
+ with pytest.raises(TypeError):
+ np.add.reduce([1, 2, None])
+
+
@pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
@pytest.mark.parametrize("method",
[np.add.accumulate, np.add.reduce,
@@ -2689,10 +2865,10 @@ class TestLowlevelAPIAccess:
r = np.equal.resolve_dtypes((S0, S0, None))
assert r == (S0, S0, np.dtype(bool))
- # Subarray dtypes are weird and only really exist nested, they need
- # the shift to full NEP 50 to be implemented nicely:
+ # Subarray dtypes are weird and may not work fully, we preserve them
+ # leading to a TypeError (currently no equal loop for void/structured)
dts = np.dtype("10i")
- with pytest.raises(NotImplementedError):
+ with pytest.raises(TypeError):
np.equal.resolve_dtypes((dts, dts, None))
def test_resolve_dtypes_reduction(self):
@@ -2791,3 +2967,10 @@ class TestLowlevelAPIAccess:
with pytest.raises(TypeError):
# cannot call it a second time:
np.negative._get_strided_loop(call_info)
+
+ def test_long_arrays(self):
+ t = np.zeros((1029, 917), dtype=np.single)
+ t[0][0] = 1
+ t[28][414] = 1
+ tc = np.cos(t)
+ assert_equal(tc[0][0], tc[28][414])
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index 88ab7e014..9e3fe387b 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -17,10 +17,26 @@ from numpy.testing import (
assert_, assert_equal, assert_raises, assert_raises_regex,
assert_array_equal, assert_almost_equal, assert_array_almost_equal,
assert_array_max_ulp, assert_allclose, assert_no_warnings, suppress_warnings,
- _gen_alignment_data, assert_array_almost_equal_nulp, IS_WASM
+ _gen_alignment_data, assert_array_almost_equal_nulp, IS_WASM, IS_MUSL
)
from numpy.testing._private.utils import _glibc_older_than
+UFUNCS = [obj for obj in np.core.umath.__dict__.values()
+ if isinstance(obj, np.ufunc)]
+
+UFUNCS_UNARY = [
+ uf for uf in UFUNCS if uf.nin == 1
+]
+UFUNCS_UNARY_FP = [
+ uf for uf in UFUNCS_UNARY if 'f->f' in uf.types
+]
+
+UFUNCS_BINARY = [
+ uf for uf in UFUNCS if uf.nin == 2
+]
+UFUNCS_BINARY_ACC = [
+ uf for uf in UFUNCS_BINARY if hasattr(uf, "accumulate") and uf.nout == 1
+]
def interesting_binop_operands(val1, val2, dtype):
"""
@@ -275,16 +291,16 @@ class TestComparisons:
b_lst = b.tolist()
# (Binary) Comparison (x1=array, x2=array)
- comp_b = np_comp(a, b)
- comp_b_list = [py_comp(x, y) for x, y in zip(a_lst, b_lst)]
+ comp_b = np_comp(a, b).view(np.uint8)
+ comp_b_list = [int(py_comp(x, y)) for x, y in zip(a_lst, b_lst)]
# (Scalar1) Comparison (x1=scalar, x2=array)
- comp_s1 = np_comp(np_scalar, b)
- comp_s1_list = [py_comp(scalar, x) for x in b_lst]
+ comp_s1 = np_comp(np_scalar, b).view(np.uint8)
+ comp_s1_list = [int(py_comp(scalar, x)) for x in b_lst]
# (Scalar2) Comparison (x1=array, x2=scalar)
- comp_s2 = np_comp(a, np_scalar)
- comp_s2_list = [py_comp(x, scalar) for x in a_lst]
+ comp_s2 = np_comp(a, np_scalar).view(np.uint8)
+ comp_s2_list = [int(py_comp(x, scalar)) for x in a_lst]
# Sequence: Binary, Scalar1 and Scalar2
assert_(comp_b.tolist() == comp_b_list,
@@ -353,6 +369,64 @@ class TestComparisons:
with pytest.raises(TypeError, match="No loop matching"):
np.equal(1, 1, sig=(None, None, "l"))
+ @pytest.mark.parametrize("dtypes", ["qQ", "Qq"])
+ @pytest.mark.parametrize('py_comp, np_comp', [
+ (operator.lt, np.less),
+ (operator.le, np.less_equal),
+ (operator.gt, np.greater),
+ (operator.ge, np.greater_equal),
+ (operator.eq, np.equal),
+ (operator.ne, np.not_equal)
+ ])
+ @pytest.mark.parametrize("vals", [(2**60, 2**60+1), (2**60+1, 2**60)])
+ def test_large_integer_direct_comparison(
+ self, dtypes, py_comp, np_comp, vals):
+ # Note that float(2**60) + 1 == float(2**60).
+ a1 = np.array([2**60], dtype=dtypes[0])
+ a2 = np.array([2**60 + 1], dtype=dtypes[1])
+ expected = py_comp(2**60, 2**60+1)
+
+ assert py_comp(a1, a2) == expected
+ assert np_comp(a1, a2) == expected
+ # Also check the scalars:
+ s1 = a1[0]
+ s2 = a2[0]
+ assert isinstance(s1, np.integer)
+ assert isinstance(s2, np.integer)
+ # The Python operator here is mainly interesting:
+ assert py_comp(s1, s2) == expected
+ assert np_comp(s1, s2) == expected
+
+ @pytest.mark.parametrize("dtype", np.typecodes['UnsignedInteger'])
+ @pytest.mark.parametrize('py_comp_func, np_comp_func', [
+ (operator.lt, np.less),
+ (operator.le, np.less_equal),
+ (operator.gt, np.greater),
+ (operator.ge, np.greater_equal),
+ (operator.eq, np.equal),
+ (operator.ne, np.not_equal)
+ ])
+ @pytest.mark.parametrize("flip", [True, False])
+ def test_unsigned_signed_direct_comparison(
+ self, dtype, py_comp_func, np_comp_func, flip):
+ if flip:
+ py_comp = lambda x, y: py_comp_func(y, x)
+ np_comp = lambda x, y: np_comp_func(y, x)
+ else:
+ py_comp = py_comp_func
+ np_comp = np_comp_func
+
+ arr = np.array([np.iinfo(dtype).max], dtype=dtype)
+ expected = py_comp(int(arr[0]), -1)
+
+ assert py_comp(arr, -1) == expected
+ assert np_comp(arr, -1) == expected
+ scalar = arr[0]
+ assert isinstance(scalar, np.integer)
+ # The Python operator here is mainly interesting:
+ assert py_comp(scalar, -1) == expected
+ assert np_comp(scalar, -1) == expected
+
class TestAdd:
def test_reduce_alignment(self):
@@ -408,7 +482,7 @@ class TestDivision:
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
+ # Large enough to test SIMD loops and remainder elements
lsize = 512 + 7
a, b, divisors = eval(ex_val)
a_lst, b_lst = a.tolist(), b.tolist()
@@ -573,6 +647,8 @@ class TestDivision:
assert_equal(np.signbit(x//1), 0)
assert_equal(np.signbit((-x)//1), 1)
+ @pytest.mark.skipif(hasattr(np.__config__, "blas_ssl2_info"),
+ reason="gh-22982")
@pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
@pytest.mark.parametrize('dtype', np.typecodes['Float'])
def test_floor_division_errors(self, dtype):
@@ -715,6 +791,8 @@ class TestRemainder:
# inf / 0 does not set any flags, only the modulo creates a NaN
np.divmod(finf, fzero)
+ @pytest.mark.skipif(hasattr(np.__config__, "blas_ssl2_info"),
+ reason="gh-22982")
@pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
@pytest.mark.xfail(sys.platform.startswith("darwin"),
reason="MacOS seems to not give the correct 'invalid' warning for "
@@ -1086,7 +1164,7 @@ class TestPower:
assert_complex_equal(np.power(zero, 1+1j), zero)
assert_complex_equal(np.power(zero, 1+0j), zero)
assert_complex_equal(np.power(zero, 1-1j), zero)
- #Complex powers will negative real part or 0 (provided imaginary
+ #Complex powers will negative real part or 0 (provided imaginary
# part is not zero) will generate a NAN and hence a RUNTIME warning
with pytest.warns(expected_warning=RuntimeWarning) as r:
assert_complex_equal(np.power(zero, -1+1j), cnan)
@@ -1276,9 +1354,20 @@ class TestLog:
# test log() of max for dtype does not raise
for dt in ['f', 'd', 'g']:
- with np.errstate(all='raise'):
- x = np.finfo(dt).max
- np.log(x)
+ try:
+ with np.errstate(all='raise'):
+ x = np.finfo(dt).max
+ np.log(x)
+ except FloatingPointError as exc:
+ if dt == 'g' and IS_MUSL:
+ # FloatingPointError is known to occur on longdouble
+ # for musllinux_x86_64 x is very large
+ pytest.skip(
+ "Overflow has occurred for"
+ " np.log(np.finfo(np.longdouble).max)"
+ )
+ else:
+ raise exc
def test_log_strides(self):
np.random.seed(42)
@@ -1395,23 +1484,50 @@ class TestSpecialFloats:
np.log(a)
@pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
- def test_sincos_values(self):
+ @pytest.mark.parametrize('dtype', ['e', 'f', 'd', 'g'])
+ def test_sincos_values(self, dtype):
with np.errstate(all='ignore'):
x = [np.nan, np.nan, np.nan, np.nan]
y = [np.nan, -np.nan, np.inf, -np.inf]
- for dt in ['e', 'f', 'd', 'g']:
- xf = np.array(x, dtype=dt)
- yf = np.array(y, dtype=dt)
- assert_equal(np.sin(yf), xf)
- assert_equal(np.cos(yf), xf)
+ xf = np.array(x, dtype=dtype)
+ yf = np.array(y, dtype=dtype)
+ assert_equal(np.sin(yf), xf)
+ assert_equal(np.cos(yf), xf)
+ @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
+ @pytest.mark.xfail(
+ sys.platform.startswith("darwin"),
+ reason="underflow is triggered for scalar 'sin'"
+ )
+ def test_sincos_underflow(self):
+ with np.errstate(under='raise'):
+ underflow_trigger = np.array(
+ float.fromhex("0x1.f37f47a03f82ap-511"),
+ dtype=np.float64
+ )
+ np.sin(underflow_trigger)
+ np.cos(underflow_trigger)
+ @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
+ @pytest.mark.parametrize('callable', [np.sin, np.cos])
+ @pytest.mark.parametrize('dtype', ['e', 'f', 'd'])
+ @pytest.mark.parametrize('value', [np.inf, -np.inf])
+ def test_sincos_errors(self, callable, dtype, value):
with np.errstate(invalid='raise'):
- for callable in [np.sin, np.cos]:
- for value in [np.inf, -np.inf]:
- for dt in ['e', 'f', 'd']:
- assert_raises(FloatingPointError, callable,
- np.array([value], dtype=dt))
+ assert_raises(FloatingPointError, callable,
+ np.array([value], dtype=dtype))
+
+ @pytest.mark.parametrize('callable', [np.sin, np.cos])
+ @pytest.mark.parametrize('dtype', ['f', 'd'])
+ @pytest.mark.parametrize('stride', [-1, 1, 2, 4, 5])
+ def test_sincos_overlaps(self, callable, dtype, stride):
+ N = 100
+ M = N // abs(stride)
+ rng = np.random.default_rng(42)
+ x = rng.standard_normal(N, dtype)
+ y = callable(x[::stride])
+ callable(x[::stride], out=x[:M])
+ assert_equal(x[:M], y)
@pytest.mark.parametrize('dt', ['e', 'f', 'd', 'g'])
def test_sqrt_values(self, dt):
@@ -1631,18 +1747,78 @@ class TestSpecialFloats:
np.array(value, dtype=dt))
# test to ensure no spurious FP exceptions are raised due to SIMD
- def test_spurious_fpexception(self):
- for dt in ['e', 'f', 'd']:
- arr = np.array([1.0, 2.0], dtype=dt)
- with assert_no_warnings():
- np.log(arr)
- np.log2(arr)
- np.log10(arr)
- np.arccosh(arr)
-
+ INF_INVALID_ERR = [
+ np.cos, np.sin, np.tan, np.arccos, np.arcsin, np.spacing, np.arctanh
+ ]
+ NEG_INVALID_ERR = [
+ np.log, np.log2, np.log10, np.log1p, np.sqrt, np.arccosh,
+ np.arctanh
+ ]
+ ONE_INVALID_ERR = [
+ np.arctanh,
+ ]
+ LTONE_INVALID_ERR = [
+ np.arccosh,
+ ]
+ BYZERO_ERR = [
+ np.log, np.log2, np.log10, np.reciprocal, np.arccosh
+ ]
+
+ @pytest.mark.parametrize("ufunc", UFUNCS_UNARY_FP)
+ @pytest.mark.parametrize("dtype", ('e', 'f', 'd'))
+ @pytest.mark.parametrize("data, escape", (
+ ([0.03], LTONE_INVALID_ERR),
+ ([0.03]*32, LTONE_INVALID_ERR),
+ # neg
+ ([-1.0], NEG_INVALID_ERR),
+ ([-1.0]*32, NEG_INVALID_ERR),
+ # flat
+ ([1.0], ONE_INVALID_ERR),
+ ([1.0]*32, ONE_INVALID_ERR),
+ # zero
+ ([0.0], BYZERO_ERR),
+ ([0.0]*32, BYZERO_ERR),
+ ([-0.0], BYZERO_ERR),
+ ([-0.0]*32, BYZERO_ERR),
+ # nan
+ ([0.5, 0.5, 0.5, np.nan], LTONE_INVALID_ERR),
+ ([0.5, 0.5, 0.5, np.nan]*32, LTONE_INVALID_ERR),
+ ([np.nan, 1.0, 1.0, 1.0], ONE_INVALID_ERR),
+ ([np.nan, 1.0, 1.0, 1.0]*32, ONE_INVALID_ERR),
+ ([np.nan], []),
+ ([np.nan]*32, []),
+ # inf
+ ([0.5, 0.5, 0.5, np.inf], INF_INVALID_ERR + LTONE_INVALID_ERR),
+ ([0.5, 0.5, 0.5, np.inf]*32, INF_INVALID_ERR + LTONE_INVALID_ERR),
+ ([np.inf, 1.0, 1.0, 1.0], INF_INVALID_ERR),
+ ([np.inf, 1.0, 1.0, 1.0]*32, INF_INVALID_ERR),
+ ([np.inf], INF_INVALID_ERR),
+ ([np.inf]*32, INF_INVALID_ERR),
+ # ninf
+ ([0.5, 0.5, 0.5, -np.inf],
+ NEG_INVALID_ERR + INF_INVALID_ERR + LTONE_INVALID_ERR),
+ ([0.5, 0.5, 0.5, -np.inf]*32,
+ NEG_INVALID_ERR + INF_INVALID_ERR + LTONE_INVALID_ERR),
+ ([-np.inf, 1.0, 1.0, 1.0], NEG_INVALID_ERR + INF_INVALID_ERR),
+ ([-np.inf, 1.0, 1.0, 1.0]*32, NEG_INVALID_ERR + INF_INVALID_ERR),
+ ([-np.inf], NEG_INVALID_ERR + INF_INVALID_ERR),
+ ([-np.inf]*32, NEG_INVALID_ERR + INF_INVALID_ERR),
+ ))
+ def test_unary_spurious_fpexception(self, ufunc, dtype, data, escape):
+ if escape and ufunc in escape:
+ return
+ # FIXME: NAN raises FP invalid exception:
+ # - ceil/float16 on MSVC:32-bit
+ # - spacing/float16 on almost all platforms
+ if ufunc in (np.spacing, np.ceil) and dtype == 'e':
+ return
+ array = np.array(data, dtype=dtype)
+ with assert_no_warnings():
+ ufunc(array)
class TestFPClass:
- @pytest.mark.parametrize("stride", [-4,-2,-1,1,2,4])
+ @pytest.mark.parametrize("stride", [-5, -4, -3, -2, -1, 1,
+ 2, 4, 5, 6, 7, 8, 9, 10])
def test_fpclass(self, stride):
arr_f64 = np.array([np.nan, -np.nan, np.inf, -np.inf, -1.0, 1.0, -0.0, 0.0, 2.2251e-308, -2.2251e-308], dtype='d')
arr_f32 = np.array([np.nan, -np.nan, np.inf, -np.inf, -1.0, 1.0, -0.0, 0.0, 1.4013e-045, -1.4013e-045], dtype='f')
@@ -1659,6 +1835,52 @@ class TestFPClass:
assert_equal(np.isfinite(arr_f32[::stride]), finite[::stride])
assert_equal(np.isfinite(arr_f64[::stride]), finite[::stride])
+ @pytest.mark.parametrize("dtype", ['d', 'f'])
+ def test_fp_noncontiguous(self, dtype):
+ data = np.array([np.nan, -np.nan, np.inf, -np.inf, -1.0,
+ 1.0, -0.0, 0.0, 2.2251e-308,
+ -2.2251e-308], dtype=dtype)
+ nan = np.array([True, True, False, False, False, False,
+ False, False, False, False])
+ inf = np.array([False, False, True, True, False, False,
+ False, False, False, False])
+ sign = np.array([False, True, False, True, True, False,
+ True, False, False, True])
+ finite = np.array([False, False, False, False, True, True,
+ True, True, True, True])
+ out = np.ndarray(data.shape, dtype='bool')
+ ncontig_in = data[1::3]
+ ncontig_out = out[1::3]
+ contig_in = np.array(ncontig_in)
+ assert_equal(ncontig_in.flags.c_contiguous, False)
+ assert_equal(ncontig_out.flags.c_contiguous, False)
+ assert_equal(contig_in.flags.c_contiguous, True)
+ # ncontig in, ncontig out
+ assert_equal(np.isnan(ncontig_in, out=ncontig_out), nan[1::3])
+ assert_equal(np.isinf(ncontig_in, out=ncontig_out), inf[1::3])
+ assert_equal(np.signbit(ncontig_in, out=ncontig_out), sign[1::3])
+ assert_equal(np.isfinite(ncontig_in, out=ncontig_out), finite[1::3])
+ # contig in, ncontig out
+ assert_equal(np.isnan(contig_in, out=ncontig_out), nan[1::3])
+ assert_equal(np.isinf(contig_in, out=ncontig_out), inf[1::3])
+ assert_equal(np.signbit(contig_in, out=ncontig_out), sign[1::3])
+ assert_equal(np.isfinite(contig_in, out=ncontig_out), finite[1::3])
+ # ncontig in, contig out
+ assert_equal(np.isnan(ncontig_in), nan[1::3])
+ assert_equal(np.isinf(ncontig_in), inf[1::3])
+ assert_equal(np.signbit(ncontig_in), sign[1::3])
+ assert_equal(np.isfinite(ncontig_in), finite[1::3])
+ # contig in, contig out, nd stride
+ data_split = np.array(np.array_split(data, 2))
+ nan_split = np.array(np.array_split(nan, 2))
+ inf_split = np.array(np.array_split(inf, 2))
+ sign_split = np.array(np.array_split(sign, 2))
+ finite_split = np.array(np.array_split(finite, 2))
+ assert_equal(np.isnan(data_split), nan_split)
+ assert_equal(np.isinf(data_split), inf_split)
+ assert_equal(np.signbit(data_split), sign_split)
+ assert_equal(np.isfinite(data_split), finite_split)
+
class TestLDExp:
@pytest.mark.parametrize("stride", [-4,-2,-1,1,2,4])
@pytest.mark.parametrize("dtype", ['f', 'd'])
@@ -1672,6 +1894,7 @@ class TestLDExp:
class TestFRExp:
@pytest.mark.parametrize("stride", [-4,-2,-1,1,2,4])
@pytest.mark.parametrize("dtype", ['f', 'd'])
+ @pytest.mark.xfail(IS_MUSL, reason="gh23048")
@pytest.mark.skipif(not sys.platform.startswith('linux'),
reason="np.frexp gives different answers for NAN/INF on windows and linux")
def test_frexp(self, dtype, stride):
@@ -3359,6 +3582,79 @@ class TestSpecialMethods:
assert_raises(ValueError, np.modf, a, out=('one', 'two', 'three'))
assert_raises(ValueError, np.modf, a, out=('one',))
+ def test_ufunc_override_where(self):
+
+ class OverriddenArrayOld(np.ndarray):
+
+ def _unwrap(self, objs):
+ cls = type(self)
+ result = []
+ for obj in objs:
+ if isinstance(obj, cls):
+ obj = np.array(obj)
+ elif type(obj) != np.ndarray:
+ return NotImplemented
+ result.append(obj)
+ return result
+
+ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
+
+ inputs = self._unwrap(inputs)
+ if inputs is NotImplemented:
+ return NotImplemented
+
+ kwargs = kwargs.copy()
+ if "out" in kwargs:
+ kwargs["out"] = self._unwrap(kwargs["out"])
+ if kwargs["out"] is NotImplemented:
+ return NotImplemented
+
+ r = super().__array_ufunc__(ufunc, method, *inputs, **kwargs)
+ if r is not NotImplemented:
+ r = r.view(type(self))
+
+ return r
+
+ class OverriddenArrayNew(OverriddenArrayOld):
+ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
+
+ kwargs = kwargs.copy()
+ if "where" in kwargs:
+ kwargs["where"] = self._unwrap((kwargs["where"], ))
+ if kwargs["where"] is NotImplemented:
+ return NotImplemented
+ else:
+ kwargs["where"] = kwargs["where"][0]
+
+ r = super().__array_ufunc__(ufunc, method, *inputs, **kwargs)
+ if r is not NotImplemented:
+ r = r.view(type(self))
+
+ return r
+
+ ufunc = np.negative
+
+ array = np.array([1, 2, 3])
+ where = np.array([True, False, True])
+ expected = ufunc(array, where=where)
+
+ with pytest.raises(TypeError):
+ ufunc(array, where=where.view(OverriddenArrayOld))
+
+ result_1 = ufunc(
+ array,
+ where=where.view(OverriddenArrayNew)
+ )
+ assert isinstance(result_1, OverriddenArrayNew)
+ assert np.all(np.array(result_1) == expected, where=where)
+
+ result_2 = ufunc(
+ array.view(OverriddenArrayNew),
+ where=where.view(OverriddenArrayNew)
+ )
+ assert isinstance(result_2, OverriddenArrayNew)
+ assert np.all(np.array(result_2) == expected, where=where)
+
def test_ufunc_override_exception(self):
class A:
@@ -3780,6 +4076,7 @@ class TestComplexFunctions:
assert_almost_equal(fz.real, fr, err_msg='real part %s' % f)
assert_almost_equal(fz.imag, 0., err_msg='imag part %s' % f)
+ @pytest.mark.xfail(IS_MUSL, reason="gh23049")
@pytest.mark.xfail(IS_WASM, reason="doesn't work")
def test_precisions_consistent(self):
z = 1 + 1j
@@ -3790,6 +4087,7 @@ class TestComplexFunctions:
assert_almost_equal(fcf, fcd, decimal=6, err_msg='fch-fcd %s' % f)
assert_almost_equal(fcl, fcd, decimal=15, err_msg='fch-fcl %s' % f)
+ @pytest.mark.xfail(IS_MUSL, reason="gh23049")
@pytest.mark.xfail(IS_WASM, reason="doesn't work")
def test_branch_cuts(self):
# check branch cuts and continuity on them
@@ -3816,6 +4114,7 @@ class TestComplexFunctions:
_check_branch_cut(np.arccosh, [0-2j, 2j, 2], [1, 1, 1j], 1, 1)
_check_branch_cut(np.arctanh, [0-2j, 2j, 0], [1, 1, 1j], 1, 1)
+ @pytest.mark.xfail(IS_MUSL, reason="gh23049")
@pytest.mark.xfail(IS_WASM, reason="doesn't work")
def test_branch_cuts_complex64(self):
# check branch cuts and continuity on them
@@ -3861,6 +4160,7 @@ class TestComplexFunctions:
b = cfunc(p)
assert_(abs(a - b) < atol, "%s %s: %s; cmath: %s" % (fname, p, a, b))
+ @pytest.mark.xfail(IS_MUSL, reason="gh23049")
@pytest.mark.xfail(IS_WASM, reason="doesn't work")
@pytest.mark.parametrize('dtype', [np.complex64, np.complex_, np.longcomplex])
def test_loss_of_precision(self, dtype):
@@ -3952,6 +4252,14 @@ class TestComplexFunctions:
check(func, pts, 1j)
check(func, pts, 1+1j)
+ @np.errstate(all="ignore")
+ def test_promotion_corner_cases(self):
+ for func in self.funcs:
+ assert func(np.float16(1)).dtype == np.float16
+ # Integer to low precision float promotion is a dubious choice:
+ assert func(np.uint8(1)).dtype == np.float16
+ assert func(np.int16(1)).dtype == np.float32
+
class TestAttributes:
def test_attributes(self):
@@ -4125,7 +4433,7 @@ def _test_spacing(t):
nan = t(np.nan)
inf = t(np.inf)
with np.errstate(invalid='ignore'):
- assert_(np.spacing(one) == eps)
+ assert_equal(np.spacing(one), eps)
assert_(np.isnan(np.spacing(nan)))
assert_(np.isnan(np.spacing(inf)))
assert_(np.isnan(np.spacing(-inf)))
@@ -4261,6 +4569,7 @@ def test_rint_big_int():
# Rint should not change the value
assert_equal(val, np.rint(val))
+
@pytest.mark.parametrize('ftype', [np.float32, np.float64])
def test_memoverlap_accumulate(ftype):
# Reproduces bug https://github.com/numpy/numpy/issues/15597
@@ -4270,6 +4579,38 @@ def test_memoverlap_accumulate(ftype):
assert_equal(np.maximum.accumulate(arr), out_max)
assert_equal(np.minimum.accumulate(arr), out_min)
+@pytest.mark.parametrize("ufunc, dtype", [
+ (ufunc, t[0])
+ for ufunc in UFUNCS_BINARY_ACC
+ for t in ufunc.types
+ if t[-1] == '?' and t[0] not in 'DFGMmO'
+])
+def test_memoverlap_accumulate_cmp(ufunc, dtype):
+ if ufunc.signature:
+ pytest.skip('For generic signatures only')
+ for size in (2, 8, 32, 64, 128, 256):
+ arr = np.array([0, 1, 1]*size, dtype=dtype)
+ acc = ufunc.accumulate(arr, dtype='?')
+ acc_u8 = acc.view(np.uint8)
+ exp = np.array(list(itertools.accumulate(arr, ufunc)), dtype=np.uint8)
+ assert_equal(exp, acc_u8)
+
+@pytest.mark.parametrize("ufunc, dtype", [
+ (ufunc, t[0])
+ for ufunc in UFUNCS_BINARY_ACC
+ for t in ufunc.types
+ if t[0] == t[1] and t[0] == t[-1] and t[0] not in 'DFGMmO?'
+])
+def test_memoverlap_accumulate_symmetric(ufunc, dtype):
+ if ufunc.signature:
+ pytest.skip('For generic signatures only')
+ with np.errstate(all='ignore'):
+ for size in (2, 8, 32, 64, 128, 256):
+ arr = np.array([0, 1, 2]*size).astype(dtype)
+ acc = ufunc.accumulate(arr, dtype=dtype)
+ exp = np.array(list(itertools.accumulate(arr, ufunc)), dtype=dtype)
+ assert_equal(exp, acc)
+
def test_signaling_nan_exceptions():
with assert_no_warnings():
a = np.ndarray(shape=(), dtype='float32', buffer=b'\x00\xe0\xbf\xff')