about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/numpy/array_api/tests
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/numpy/array_api/tests
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/numpy/array_api/tests')
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/array_api/tests/__init__.py7
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_array_object.py395
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_creation_functions.py142
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_data_type_functions.py31
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_elementwise_functions.py114
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_indexing_functions.py24
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_manipulation_functions.py37
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_set_functions.py19
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_sorting_functions.py23
-rw-r--r--.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_validation.py27
10 files changed, 819 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/numpy/array_api/tests/__init__.py b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/__init__.py
new file mode 100644
index 00000000..536062e3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/__init__.py
@@ -0,0 +1,7 @@
+"""
+Tests for the array API namespace.
+
+Note, full compliance with the array API can be tested with the official array API test
+suite https://github.com/data-apis/array-api-tests. This test suite primarily
+focuses on those things that are not tested by the official test suite.
+"""
diff --git a/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_array_object.py b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_array_object.py
new file mode 100644
index 00000000..0feb72c4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_array_object.py
@@ -0,0 +1,395 @@
+import operator
+
+from numpy.testing import assert_raises, suppress_warnings
+import numpy as np
+import pytest
+
+from .. import ones, asarray, reshape, result_type, all, equal
+from .._array_object import Array
+from .._dtypes import (
+    _all_dtypes,
+    _boolean_dtypes,
+    _real_floating_dtypes,
+    _floating_dtypes,
+    _complex_floating_dtypes,
+    _integer_dtypes,
+    _integer_or_boolean_dtypes,
+    _real_numeric_dtypes,
+    _numeric_dtypes,
+    int8,
+    int16,
+    int32,
+    int64,
+    uint64,
+    bool as bool_,
+)
+
+
+def test_validate_index():
+    # The indexing tests in the official array API test suite test that the
+    # array object correctly handles the subset of indices that are required
+    # by the spec. But the NumPy array API implementation specifically
+    # disallows any index not required by the spec, via Array._validate_index.
+    # This test focuses on testing that non-valid indices are correctly
+    # rejected. See
+    # https://data-apis.org/array-api/latest/API_specification/indexing.html
+    # and the docstring of Array._validate_index for the exact indexing
+    # behavior that should be allowed. This does not test indices that are
+    # already invalid in NumPy itself because Array will generally just pass
+    # such indices directly to the underlying np.ndarray.
+
+    a = ones((3, 4))
+
+    # Out of bounds slices are not allowed
+    assert_raises(IndexError, lambda: a[:4])
+    assert_raises(IndexError, lambda: a[:-4])
+    assert_raises(IndexError, lambda: a[:3:-1])
+    assert_raises(IndexError, lambda: a[:-5:-1])
+    assert_raises(IndexError, lambda: a[4:])
+    assert_raises(IndexError, lambda: a[-4:])
+    assert_raises(IndexError, lambda: a[4::-1])
+    assert_raises(IndexError, lambda: a[-4::-1])
+
+    assert_raises(IndexError, lambda: a[...,:5])
+    assert_raises(IndexError, lambda: a[...,:-5])
+    assert_raises(IndexError, lambda: a[...,:5:-1])
+    assert_raises(IndexError, lambda: a[...,:-6:-1])
+    assert_raises(IndexError, lambda: a[...,5:])
+    assert_raises(IndexError, lambda: a[...,-5:])
+    assert_raises(IndexError, lambda: a[...,5::-1])
+    assert_raises(IndexError, lambda: a[...,-5::-1])
+
+    # Boolean indices cannot be part of a larger tuple index
+    assert_raises(IndexError, lambda: a[a[:,0]==1,0])
+    assert_raises(IndexError, lambda: a[a[:,0]==1,...])
+    assert_raises(IndexError, lambda: a[..., a[0]==1])
+    assert_raises(IndexError, lambda: a[[True, True, True]])
+    assert_raises(IndexError, lambda: a[(True, True, True),])
+
+    # Integer array indices are not allowed (except for 0-D)
+    idx = asarray([[0, 1]])
+    assert_raises(IndexError, lambda: a[idx])
+    assert_raises(IndexError, lambda: a[idx,])
+    assert_raises(IndexError, lambda: a[[0, 1]])
+    assert_raises(IndexError, lambda: a[(0, 1), (0, 1)])
+    assert_raises(IndexError, lambda: a[[0, 1]])
+    assert_raises(IndexError, lambda: a[np.array([[0, 1]])])
+
+    # Multiaxis indices must contain exactly as many indices as dimensions
+    assert_raises(IndexError, lambda: a[()])
+    assert_raises(IndexError, lambda: a[0,])
+    assert_raises(IndexError, lambda: a[0])
+    assert_raises(IndexError, lambda: a[:])
+
+def test_operators():
+    # For every operator, we test that it works for the required type
+    # combinations and raises TypeError otherwise
+    binary_op_dtypes = {
+        "__add__": "numeric",
+        "__and__": "integer_or_boolean",
+        "__eq__": "all",
+        "__floordiv__": "real numeric",
+        "__ge__": "real numeric",
+        "__gt__": "real numeric",
+        "__le__": "real numeric",
+        "__lshift__": "integer",
+        "__lt__": "real numeric",
+        "__mod__": "real numeric",
+        "__mul__": "numeric",
+        "__ne__": "all",
+        "__or__": "integer_or_boolean",
+        "__pow__": "numeric",
+        "__rshift__": "integer",
+        "__sub__": "numeric",
+        "__truediv__": "floating",
+        "__xor__": "integer_or_boolean",
+    }
+    # Recompute each time because of in-place ops
+    def _array_vals():
+        for d in _integer_dtypes:
+            yield asarray(1, dtype=d)
+        for d in _boolean_dtypes:
+            yield asarray(False, dtype=d)
+        for d in _floating_dtypes:
+            yield asarray(1.0, dtype=d)
+
+
+    BIG_INT = int(1e30)
+    for op, dtypes in binary_op_dtypes.items():
+        ops = [op]
+        if op not in ["__eq__", "__ne__", "__le__", "__ge__", "__lt__", "__gt__"]:
+            rop = "__r" + op[2:]
+            iop = "__i" + op[2:]
+            ops += [rop, iop]
+        for s in [1, 1.0, 1j, BIG_INT, False]:
+            for _op in ops:
+                for a in _array_vals():
+                    # Test array op scalar. From the spec, the following combinations
+                    # are supported:
+
+                    # - Python bool for a bool array dtype,
+                    # - a Python int within the bounds of the given dtype for integer array dtypes,
+                    # - a Python int or float for real floating-point array dtypes
+                    # - a Python int, float, or complex for complex floating-point array dtypes
+
+                    if ((dtypes == "all"
+                         or dtypes == "numeric" and a.dtype in _numeric_dtypes
+                         or dtypes == "real numeric" and a.dtype in _real_numeric_dtypes
+                         or dtypes == "integer" and a.dtype in _integer_dtypes
+                         or dtypes == "integer_or_boolean" and a.dtype in _integer_or_boolean_dtypes
+                         or dtypes == "boolean" and a.dtype in _boolean_dtypes
+                         or dtypes == "floating" and a.dtype in _floating_dtypes
+                        )
+                        # bool is a subtype of int, which is why we avoid
+                        # isinstance here.
+                        and (a.dtype in _boolean_dtypes and type(s) == bool
+                             or a.dtype in _integer_dtypes and type(s) == int
+                             or a.dtype in _real_floating_dtypes and type(s) in [float, int]
+                             or a.dtype in _complex_floating_dtypes and type(s) in [complex, float, int]
+                        )):
+                        if a.dtype in _integer_dtypes and s == BIG_INT:
+                            assert_raises(OverflowError, lambda: getattr(a, _op)(s))
+                        else:
+                            # Only test for no error
+                            with suppress_warnings() as sup:
+                                # ignore warnings from pow(BIG_INT)
+                                sup.filter(RuntimeWarning,
+                                           "invalid value encountered in power")
+                                getattr(a, _op)(s)
+                    else:
+                        assert_raises(TypeError, lambda: getattr(a, _op)(s))
+
+                # Test array op array.
+                for _op in ops:
+                    for x in _array_vals():
+                        for y in _array_vals():
+                            # See the promotion table in NEP 47 or the array
+                            # API spec page on type promotion. Mixed kind
+                            # promotion is not defined.
+                            if (x.dtype == uint64 and y.dtype in [int8, int16, int32, int64]
+                                or y.dtype == uint64 and x.dtype in [int8, int16, int32, int64]
+                                or x.dtype in _integer_dtypes and y.dtype not in _integer_dtypes
+                                or y.dtype in _integer_dtypes and x.dtype not in _integer_dtypes
+                                or x.dtype in _boolean_dtypes and y.dtype not in _boolean_dtypes
+                                or y.dtype in _boolean_dtypes and x.dtype not in _boolean_dtypes
+                                or x.dtype in _floating_dtypes and y.dtype not in _floating_dtypes
+                                or y.dtype in _floating_dtypes and x.dtype not in _floating_dtypes
+                                ):
+                                assert_raises(TypeError, lambda: getattr(x, _op)(y))
+                            # Ensure in-place operators only promote to the same dtype as the left operand.
+                            elif (
+                                _op.startswith("__i")
+                                and result_type(x.dtype, y.dtype) != x.dtype
+                            ):
+                                assert_raises(TypeError, lambda: getattr(x, _op)(y))
+                            # Ensure only those dtypes that are required for every operator are allowed.
+                            elif (dtypes == "all" and (x.dtype in _boolean_dtypes and y.dtype in _boolean_dtypes
+                                                      or x.dtype in _numeric_dtypes and y.dtype in _numeric_dtypes)
+                                or (dtypes == "real numeric" and x.dtype in _real_numeric_dtypes and y.dtype in _real_numeric_dtypes)
+                                or (dtypes == "numeric" and x.dtype in _numeric_dtypes and y.dtype in _numeric_dtypes)
+                                or dtypes == "integer" and x.dtype in _integer_dtypes and y.dtype in _integer_dtypes
+                                or dtypes == "integer_or_boolean" and (x.dtype in _integer_dtypes and y.dtype in _integer_dtypes
+                                                                       or x.dtype in _boolean_dtypes and y.dtype in _boolean_dtypes)
+                                or dtypes == "boolean" and x.dtype in _boolean_dtypes and y.dtype in _boolean_dtypes
+                                or dtypes == "floating" and x.dtype in _floating_dtypes and y.dtype in _floating_dtypes
+                            ):
+                                getattr(x, _op)(y)
+                            else:
+                                assert_raises(TypeError, lambda: getattr(x, _op)(y))
+
+    unary_op_dtypes = {
+        "__abs__": "numeric",
+        "__invert__": "integer_or_boolean",
+        "__neg__": "numeric",
+        "__pos__": "numeric",
+    }
+    for op, dtypes in unary_op_dtypes.items():
+        for a in _array_vals():
+            if (
+                dtypes == "numeric"
+                and a.dtype in _numeric_dtypes
+                or dtypes == "integer_or_boolean"
+                and a.dtype in _integer_or_boolean_dtypes
+            ):
+                # Only test for no error
+                getattr(a, op)()
+            else:
+                assert_raises(TypeError, lambda: getattr(a, op)())
+
+    # Finally, matmul() must be tested separately, because it works a bit
+    # different from the other operations.
+    def _matmul_array_vals():
+        for a in _array_vals():
+            yield a
+        for d in _all_dtypes:
+            yield ones((3, 4), dtype=d)
+            yield ones((4, 2), dtype=d)
+            yield ones((4, 4), dtype=d)
+
+    # Scalars always error
+    for _op in ["__matmul__", "__rmatmul__", "__imatmul__"]:
+        for s in [1, 1.0, False]:
+            for a in _matmul_array_vals():
+                if (type(s) in [float, int] and a.dtype in _floating_dtypes
+                    or type(s) == int and a.dtype in _integer_dtypes):
+                    # Type promotion is valid, but @ is not allowed on 0-D
+                    # inputs, so the error is a ValueError
+                    assert_raises(ValueError, lambda: getattr(a, _op)(s))
+                else:
+                    assert_raises(TypeError, lambda: getattr(a, _op)(s))
+
+    for x in _matmul_array_vals():
+        for y in _matmul_array_vals():
+            if (x.dtype == uint64 and y.dtype in [int8, int16, int32, int64]
+                or y.dtype == uint64 and x.dtype in [int8, int16, int32, int64]
+                or x.dtype in _integer_dtypes and y.dtype not in _integer_dtypes
+                or y.dtype in _integer_dtypes and x.dtype not in _integer_dtypes
+                or x.dtype in _floating_dtypes and y.dtype not in _floating_dtypes
+                or y.dtype in _floating_dtypes and x.dtype not in _floating_dtypes
+                or x.dtype in _boolean_dtypes
+                or y.dtype in _boolean_dtypes
+                ):
+                assert_raises(TypeError, lambda: x.__matmul__(y))
+                assert_raises(TypeError, lambda: y.__rmatmul__(x))
+                assert_raises(TypeError, lambda: x.__imatmul__(y))
+            elif x.shape == () or y.shape == () or x.shape[1] != y.shape[0]:
+                assert_raises(ValueError, lambda: x.__matmul__(y))
+                assert_raises(ValueError, lambda: y.__rmatmul__(x))
+                if result_type(x.dtype, y.dtype) != x.dtype:
+                    assert_raises(TypeError, lambda: x.__imatmul__(y))
+                else:
+                    assert_raises(ValueError, lambda: x.__imatmul__(y))
+            else:
+                x.__matmul__(y)
+                y.__rmatmul__(x)
+                if result_type(x.dtype, y.dtype) != x.dtype:
+                    assert_raises(TypeError, lambda: x.__imatmul__(y))
+                elif y.shape[0] != y.shape[1]:
+                    # This one fails because x @ y has a different shape from x
+                    assert_raises(ValueError, lambda: x.__imatmul__(y))
+                else:
+                    x.__imatmul__(y)
+
+
+def test_python_scalar_construtors():
+    b = asarray(False)
+    i = asarray(0)
+    f = asarray(0.0)
+    c = asarray(0j)
+
+    assert bool(b) == False
+    assert int(i) == 0
+    assert float(f) == 0.0
+    assert operator.index(i) == 0
+
+    # bool/int/float/complex should only be allowed on 0-D arrays.
+    assert_raises(TypeError, lambda: bool(asarray([False])))
+    assert_raises(TypeError, lambda: int(asarray([0])))
+    assert_raises(TypeError, lambda: float(asarray([0.0])))
+    assert_raises(TypeError, lambda: complex(asarray([0j])))
+    assert_raises(TypeError, lambda: operator.index(asarray([0])))
+
+    # bool should work on all types of arrays
+    assert bool(b) is bool(i) is bool(f) is bool(c) is False
+
+    # int should fail on complex arrays
+    assert int(b) == int(i) == int(f) == 0
+    assert_raises(TypeError, lambda: int(c))
+
+    # float should fail on complex arrays
+    assert float(b) == float(i) == float(f) == 0.0
+    assert_raises(TypeError, lambda: float(c))
+
+    # complex should work on all types of arrays
+    assert complex(b) == complex(i) == complex(f) == complex(c) == 0j
+
+    # index should only work on integer arrays
+    assert operator.index(i) == 0
+    assert_raises(TypeError, lambda: operator.index(b))
+    assert_raises(TypeError, lambda: operator.index(f))
+    assert_raises(TypeError, lambda: operator.index(c))
+
+
+def test_device_property():
+    a = ones((3, 4))
+    assert a.device == 'cpu'
+
+    assert all(equal(a.to_device('cpu'), a))
+    assert_raises(ValueError, lambda: a.to_device('gpu'))
+
+    assert all(equal(asarray(a, device='cpu'), a))
+    assert_raises(ValueError, lambda: asarray(a, device='gpu'))
+
+def test_array_properties():
+    a = ones((1, 2, 3))
+    b = ones((2, 3))
+    assert_raises(ValueError, lambda: a.T)
+
+    assert isinstance(b.T, Array)
+    assert b.T.shape == (3, 2)
+
+    assert isinstance(a.mT, Array)
+    assert a.mT.shape == (1, 3, 2)
+    assert isinstance(b.mT, Array)
+    assert b.mT.shape == (3, 2)
+
+def test___array__():
+    a = ones((2, 3), dtype=int16)
+    assert np.asarray(a) is a._array
+    b = np.asarray(a, dtype=np.float64)
+    assert np.all(np.equal(b, np.ones((2, 3), dtype=np.float64)))
+    assert b.dtype == np.float64
+
+def test_allow_newaxis():
+    a = ones(5)
+    indexed_a = a[None, :]
+    assert indexed_a.shape == (1, 5)
+
+def test_disallow_flat_indexing_with_newaxis():
+    a = ones((3, 3, 3))
+    with pytest.raises(IndexError):
+        a[None, 0, 0]
+
+def test_disallow_mask_with_newaxis():
+    a = ones((3, 3, 3))
+    with pytest.raises(IndexError):
+        a[None, asarray(True)]
+
+@pytest.mark.parametrize("shape", [(), (5,), (3, 3, 3)])
+@pytest.mark.parametrize("index", ["string", False, True])
+def test_error_on_invalid_index(shape, index):
+    a = ones(shape)
+    with pytest.raises(IndexError):
+        a[index]
+
+def test_mask_0d_array_without_errors():
+    a = ones(())
+    a[asarray(True)]
+
+@pytest.mark.parametrize(
+    "i", [slice(5), slice(5, 0), asarray(True), asarray([0, 1])]
+)
+def test_error_on_invalid_index_with_ellipsis(i):
+    a = ones((3, 3, 3))
+    with pytest.raises(IndexError):
+        a[..., i]
+    with pytest.raises(IndexError):
+        a[i, ...]
+
+def test_array_keys_use_private_array():
+    """
+    Indexing operations convert array keys before indexing the internal array
+
+    Fails when array_api array keys are not converted into NumPy-proper arrays
+    in __getitem__(). This is achieved by passing array_api arrays with 0-sized
+    dimensions, which NumPy-proper treats erroneously - not sure why!
+
+    TODO: Find and use appropriate __setitem__() case.
+    """
+    a = ones((0, 0), dtype=bool_)
+    assert a[a].shape == (0,)
+
+    a = ones((0,), dtype=bool_)
+    key = ones((0, 0), dtype=bool_)
+    with pytest.raises(IndexError):
+        a[key]
diff --git a/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_creation_functions.py b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_creation_functions.py
new file mode 100644
index 00000000..be9eaa38
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_creation_functions.py
@@ -0,0 +1,142 @@
+from numpy.testing import assert_raises
+import numpy as np
+
+from .. import all
+from .._creation_functions import (
+    asarray,
+    arange,
+    empty,
+    empty_like,
+    eye,
+    full,
+    full_like,
+    linspace,
+    meshgrid,
+    ones,
+    ones_like,
+    zeros,
+    zeros_like,
+)
+from .._dtypes import float32, float64
+from .._array_object import Array
+
+
+def test_asarray_errors():
+    # Test various protections against incorrect usage
+    assert_raises(TypeError, lambda: Array([1]))
+    assert_raises(TypeError, lambda: asarray(["a"]))
+    assert_raises(ValueError, lambda: asarray([1.0], dtype=np.float16))
+    assert_raises(OverflowError, lambda: asarray(2**100))
+    # Preferably this would be OverflowError
+    # assert_raises(OverflowError, lambda: asarray([2**100]))
+    assert_raises(TypeError, lambda: asarray([2**100]))
+    asarray([1], device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: asarray([1], device="gpu"))
+
+    assert_raises(ValueError, lambda: asarray([1], dtype=int))
+    assert_raises(ValueError, lambda: asarray([1], dtype="i"))
+
+
+def test_asarray_copy():
+    a = asarray([1])
+    b = asarray(a, copy=True)
+    a[0] = 0
+    assert all(b[0] == 1)
+    assert all(a[0] == 0)
+    a = asarray([1])
+    b = asarray(a, copy=np._CopyMode.ALWAYS)
+    a[0] = 0
+    assert all(b[0] == 1)
+    assert all(a[0] == 0)
+    a = asarray([1])
+    b = asarray(a, copy=np._CopyMode.NEVER)
+    a[0] = 0
+    assert all(b[0] == 0)
+    assert_raises(NotImplementedError, lambda: asarray(a, copy=False))
+    assert_raises(NotImplementedError,
+                  lambda: asarray(a, copy=np._CopyMode.IF_NEEDED))
+
+
+def test_arange_errors():
+    arange(1, device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: arange(1, device="gpu"))
+    assert_raises(ValueError, lambda: arange(1, dtype=int))
+    assert_raises(ValueError, lambda: arange(1, dtype="i"))
+
+
+def test_empty_errors():
+    empty((1,), device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: empty((1,), device="gpu"))
+    assert_raises(ValueError, lambda: empty((1,), dtype=int))
+    assert_raises(ValueError, lambda: empty((1,), dtype="i"))
+
+
+def test_empty_like_errors():
+    empty_like(asarray(1), device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: empty_like(asarray(1), device="gpu"))
+    assert_raises(ValueError, lambda: empty_like(asarray(1), dtype=int))
+    assert_raises(ValueError, lambda: empty_like(asarray(1), dtype="i"))
+
+
+def test_eye_errors():
+    eye(1, device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: eye(1, device="gpu"))
+    assert_raises(ValueError, lambda: eye(1, dtype=int))
+    assert_raises(ValueError, lambda: eye(1, dtype="i"))
+
+
+def test_full_errors():
+    full((1,), 0, device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: full((1,), 0, device="gpu"))
+    assert_raises(ValueError, lambda: full((1,), 0, dtype=int))
+    assert_raises(ValueError, lambda: full((1,), 0, dtype="i"))
+
+
+def test_full_like_errors():
+    full_like(asarray(1), 0, device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: full_like(asarray(1), 0, device="gpu"))
+    assert_raises(ValueError, lambda: full_like(asarray(1), 0, dtype=int))
+    assert_raises(ValueError, lambda: full_like(asarray(1), 0, dtype="i"))
+
+
+def test_linspace_errors():
+    linspace(0, 1, 10, device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: linspace(0, 1, 10, device="gpu"))
+    assert_raises(ValueError, lambda: linspace(0, 1, 10, dtype=float))
+    assert_raises(ValueError, lambda: linspace(0, 1, 10, dtype="f"))
+
+
+def test_ones_errors():
+    ones((1,), device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: ones((1,), device="gpu"))
+    assert_raises(ValueError, lambda: ones((1,), dtype=int))
+    assert_raises(ValueError, lambda: ones((1,), dtype="i"))
+
+
+def test_ones_like_errors():
+    ones_like(asarray(1), device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: ones_like(asarray(1), device="gpu"))
+    assert_raises(ValueError, lambda: ones_like(asarray(1), dtype=int))
+    assert_raises(ValueError, lambda: ones_like(asarray(1), dtype="i"))
+
+
+def test_zeros_errors():
+    zeros((1,), device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: zeros((1,), device="gpu"))
+    assert_raises(ValueError, lambda: zeros((1,), dtype=int))
+    assert_raises(ValueError, lambda: zeros((1,), dtype="i"))
+
+
+def test_zeros_like_errors():
+    zeros_like(asarray(1), device="cpu")  # Doesn't error
+    assert_raises(ValueError, lambda: zeros_like(asarray(1), device="gpu"))
+    assert_raises(ValueError, lambda: zeros_like(asarray(1), dtype=int))
+    assert_raises(ValueError, lambda: zeros_like(asarray(1), dtype="i"))
+
+def test_meshgrid_dtype_errors():
+    # Doesn't raise
+    meshgrid()
+    meshgrid(asarray([1.], dtype=float32))
+    meshgrid(asarray([1.], dtype=float32), asarray([1.], dtype=float32))
+
+    assert_raises(ValueError, lambda: meshgrid(asarray([1.], dtype=float32), asarray([1.], dtype=float64)))
diff --git a/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_data_type_functions.py b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_data_type_functions.py
new file mode 100644
index 00000000..61d56ca4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_data_type_functions.py
@@ -0,0 +1,31 @@
+import pytest
+
+from numpy.testing import assert_raises
+from numpy import array_api as xp
+import numpy as np
+
+@pytest.mark.parametrize(
+    "from_, to, expected",
+    [
+        (xp.int8, xp.int16, True),
+        (xp.int16, xp.int8, False),
+        (xp.bool, xp.int8, False),
+        (xp.asarray(0, dtype=xp.uint8), xp.int8, False),
+    ],
+)
+def test_can_cast(from_, to, expected):
+    """
+    can_cast() returns correct result
+    """
+    assert xp.can_cast(from_, to) == expected
+
+def test_isdtype_strictness():
+    assert_raises(TypeError, lambda: xp.isdtype(xp.float64, 64))
+    assert_raises(ValueError, lambda: xp.isdtype(xp.float64, 'f8'))
+
+    assert_raises(TypeError, lambda: xp.isdtype(xp.float64, (('integral',),)))
+    assert_raises(TypeError, lambda: xp.isdtype(xp.float64, np.object_))
+
+    # TODO: These will require https://github.com/numpy/numpy/issues/23883
+    # assert_raises(TypeError, lambda: xp.isdtype(xp.float64, None))
+    # assert_raises(TypeError, lambda: xp.isdtype(xp.float64, np.float64))
diff --git a/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_elementwise_functions.py b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_elementwise_functions.py
new file mode 100644
index 00000000..1228d0af
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_elementwise_functions.py
@@ -0,0 +1,114 @@
+from inspect import getfullargspec
+
+from numpy.testing import assert_raises
+
+from .. import asarray, _elementwise_functions
+from .._elementwise_functions import bitwise_left_shift, bitwise_right_shift
+from .._dtypes import (
+    _dtype_categories,
+    _boolean_dtypes,
+    _floating_dtypes,
+    _integer_dtypes,
+)
+
+
+def nargs(func):
+    return len(getfullargspec(func).args)
+
+
+def test_function_types():
+    # Test that every function accepts only the required input types. We only
+    # test the negative cases here (error). The positive cases are tested in
+    # the array API test suite.
+
+    elementwise_function_input_types = {
+        "abs": "numeric",
+        "acos": "floating-point",
+        "acosh": "floating-point",
+        "add": "numeric",
+        "asin": "floating-point",
+        "asinh": "floating-point",
+        "atan": "floating-point",
+        "atan2": "real floating-point",
+        "atanh": "floating-point",
+        "bitwise_and": "integer or boolean",
+        "bitwise_invert": "integer or boolean",
+        "bitwise_left_shift": "integer",
+        "bitwise_or": "integer or boolean",
+        "bitwise_right_shift": "integer",
+        "bitwise_xor": "integer or boolean",
+        "ceil": "real numeric",
+        "conj": "complex floating-point",
+        "cos": "floating-point",
+        "cosh": "floating-point",
+        "divide": "floating-point",
+        "equal": "all",
+        "exp": "floating-point",
+        "expm1": "floating-point",
+        "floor": "real numeric",
+        "floor_divide": "real numeric",
+        "greater": "real numeric",
+        "greater_equal": "real numeric",
+        "imag": "complex floating-point",
+        "isfinite": "numeric",
+        "isinf": "numeric",
+        "isnan": "numeric",
+        "less": "real numeric",
+        "less_equal": "real numeric",
+        "log": "floating-point",
+        "logaddexp": "real floating-point",
+        "log10": "floating-point",
+        "log1p": "floating-point",
+        "log2": "floating-point",
+        "logical_and": "boolean",
+        "logical_not": "boolean",
+        "logical_or": "boolean",
+        "logical_xor": "boolean",
+        "multiply": "numeric",
+        "negative": "numeric",
+        "not_equal": "all",
+        "positive": "numeric",
+        "pow": "numeric",
+        "real": "complex floating-point",
+        "remainder": "real numeric",
+        "round": "numeric",
+        "sign": "numeric",
+        "sin": "floating-point",
+        "sinh": "floating-point",
+        "sqrt": "floating-point",
+        "square": "numeric",
+        "subtract": "numeric",
+        "tan": "floating-point",
+        "tanh": "floating-point",
+        "trunc": "real numeric",
+    }
+
+    def _array_vals():
+        for d in _integer_dtypes:
+            yield asarray(1, dtype=d)
+        for d in _boolean_dtypes:
+            yield asarray(False, dtype=d)
+        for d in _floating_dtypes:
+            yield asarray(1.0, dtype=d)
+
+    for x in _array_vals():
+        for func_name, types in elementwise_function_input_types.items():
+            dtypes = _dtype_categories[types]
+            func = getattr(_elementwise_functions, func_name)
+            if nargs(func) == 2:
+                for y in _array_vals():
+                    if x.dtype not in dtypes or y.dtype not in dtypes:
+                        assert_raises(TypeError, lambda: func(x, y))
+            else:
+                if x.dtype not in dtypes:
+                    assert_raises(TypeError, lambda: func(x))
+
+
+def test_bitwise_shift_error():
+    # bitwise shift functions should raise when the second argument is negative
+    assert_raises(
+        ValueError, lambda: bitwise_left_shift(asarray([1, 1]), asarray([1, -1]))
+    )
+    assert_raises(
+        ValueError, lambda: bitwise_right_shift(asarray([1, 1]), asarray([1, -1]))
+    )
diff --git a/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_indexing_functions.py b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_indexing_functions.py
new file mode 100644
index 00000000..9e05c638
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_indexing_functions.py
@@ -0,0 +1,24 @@
+import pytest
+
+from numpy import array_api as xp
+
+
+@pytest.mark.parametrize(
+    "x, indices, axis, expected",
+    [
+        ([2, 3], [1, 1, 0], 0,  [3, 3, 2]),
+        ([2, 3], [1, 1, 0], -1, [3, 3, 2]),
+        ([[2, 3]], [1], -1, [[3]]),
+        ([[2, 3]], [0, 0], 0, [[2, 3], [2, 3]]),
+    ],
+)
+def test_take_function(x, indices, axis, expected):
+    """
+    Indices respect relative order of a descending stable-sort
+
+    See https://github.com/numpy/numpy/issues/20778
+    """
+    x = xp.asarray(x)
+    indices = xp.asarray(indices)
+    out = xp.take(x, indices, axis=axis)
+    assert xp.all(out == xp.asarray(expected))
diff --git a/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_manipulation_functions.py b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_manipulation_functions.py
new file mode 100644
index 00000000..aec57c38
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_manipulation_functions.py
@@ -0,0 +1,37 @@
+from numpy.testing import assert_raises
+import numpy as np
+
+from .. import all
+from .._creation_functions import asarray
+from .._dtypes import float64, int8
+from .._manipulation_functions import (
+        concat,
+        reshape,
+        stack
+)
+
+
+def test_concat_errors():
+    assert_raises(TypeError, lambda: concat((1, 1), axis=None))
+    assert_raises(TypeError, lambda: concat([asarray([1], dtype=int8),
+                                             asarray([1], dtype=float64)]))
+
+
+def test_stack_errors():
+    assert_raises(TypeError, lambda: stack([asarray([1, 1], dtype=int8),
+                                            asarray([2, 2], dtype=float64)]))
+
+
+def test_reshape_copy():
+    a = asarray(np.ones((2, 3)))
+    b = reshape(a, (3, 2), copy=True)
+    assert not np.shares_memory(a._array, b._array)
+    
+    a = asarray(np.ones((2, 3)))
+    b = reshape(a, (3, 2), copy=False)
+    assert np.shares_memory(a._array, b._array)
+
+    a = asarray(np.ones((2, 3)).T)
+    b = reshape(a, (3, 2), copy=True)
+    assert_raises(AttributeError, lambda: reshape(a, (2, 3), copy=False))
+
diff --git a/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_set_functions.py b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_set_functions.py
new file mode 100644
index 00000000..b8eb65d4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_set_functions.py
@@ -0,0 +1,19 @@
+import pytest
+from hypothesis import given
+from hypothesis.extra.array_api import make_strategies_namespace
+
+from numpy import array_api as xp
+
+xps = make_strategies_namespace(xp)
+
+
+@pytest.mark.parametrize("func", [xp.unique_all, xp.unique_inverse])
+@given(xps.arrays(dtype=xps.scalar_dtypes(), shape=xps.array_shapes()))
+def test_inverse_indices_shape(func, x):
+    """
+    Inverse indices share shape of input array
+
+    See https://github.com/numpy/numpy/issues/20638
+    """
+    out = func(x)
+    assert out.inverse_indices.shape == x.shape
diff --git a/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_sorting_functions.py b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_sorting_functions.py
new file mode 100644
index 00000000..9848bbfe
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_sorting_functions.py
@@ -0,0 +1,23 @@
+import pytest
+
+from numpy import array_api as xp
+
+
+@pytest.mark.parametrize(
+    "obj, axis, expected",
+    [
+        ([0, 0], -1, [0, 1]),
+        ([0, 1, 0], -1, [1, 0, 2]),
+        ([[0, 1], [1, 1]], 0, [[1, 0], [0, 1]]),
+        ([[0, 1], [1, 1]], 1, [[1, 0], [0, 1]]),
+    ],
+)
+def test_stable_desc_argsort(obj, axis, expected):
+    """
+    Indices respect relative order of a descending stable-sort
+
+    See https://github.com/numpy/numpy/issues/20778
+    """
+    x = xp.asarray(obj)
+    out = xp.argsort(x, axis=axis, stable=True, descending=True)
+    assert xp.all(out == xp.asarray(expected))
diff --git a/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_validation.py b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_validation.py
new file mode 100644
index 00000000..0dd100d1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/numpy/array_api/tests/test_validation.py
@@ -0,0 +1,27 @@
+from typing import Callable
+
+import pytest
+
+from numpy import array_api as xp
+
+
+def p(func: Callable, *args, **kwargs):
+    f_sig = ", ".join(
+        [str(a) for a in args] + [f"{k}={v}" for k, v in kwargs.items()]
+    )
+    id_ = f"{func.__name__}({f_sig})"
+    return pytest.param(func, args, kwargs, id=id_)
+
+
+@pytest.mark.parametrize(
+    "func, args, kwargs",
+    [
+        p(xp.can_cast, 42, xp.int8),
+        p(xp.can_cast, xp.int8, 42),
+        p(xp.result_type, 42),
+    ],
+)
+def test_raises_on_invalid_types(func, args, kwargs):
+    """Function raises TypeError when passed invalidly-typed inputs"""
+    with pytest.raises(TypeError):
+        func(*args, **kwargs)