diff --git a/doc/release/upcoming_changes/25086.new_feature.rst b/doc/release/upcoming_changes/25086.new_feature.rst new file mode 100644 index 000000000000..1cf012f95bb2 --- /dev/null +++ b/doc/release/upcoming_changes/25086.new_feature.rst @@ -0,0 +1,12 @@ +Array API compatible functions' aliases +--------------------------------------- + +13 aliases for existing functions were added to improve compatibility with the Array API standard: + +* Trigonometry: ``acos``, ``acosh``, ``asin``, ``asinh``, ``atan``, ``atanh``, ``atan2``. + +* Bitwise: ``bitwise_left_shift``, ``bitwise_invert``, ``bitwise_right_shift``. + +* Misc: ``concat``, ``permute_dims``, ``pow``. + +* linalg: ``tensordot``, ``matmul``. diff --git a/doc/source/reference/array_api.rst b/doc/source/reference/array_api.rst index 6f76e0633ef5..3bf946950762 100644 --- a/doc/source/reference/array_api.rst +++ b/doc/source/reference/array_api.rst @@ -71,66 +71,10 @@ The following functions are named differently in the array API * - Array API name - NumPy namespace name - Notes - * - ``acos`` - - ``arccos`` - - - * - ``acosh`` - - ``arccosh`` - - - * - ``asin`` - - ``arcsin`` - - - * - ``asinh`` - - ``arcsinh`` - - - * - ``atan`` - - ``arctan`` - - - * - ``atan2`` - - ``arctan2`` - - - * - ``atanh`` - - ``arctanh`` - - - * - ``bitwise_left_shift`` - - ``left_shift`` - - - * - ``bitwise_invert`` - - ``invert`` - - - * - ``bitwise_right_shift`` - - ``right_shift`` - - - * - ``bool`` - - ``bool_`` - - This is **breaking** because ``np.bool`` is currently a deprecated - alias for the built-in ``bool``. - * - ``concat`` - - ``concatenate`` - - * - ``matrix_norm`` and ``vector_norm`` - ``norm`` - ``matrix_norm`` and ``vector_norm`` each do a limited subset of what ``np.norm`` does. - * - ``permute_dims`` - - ``transpose`` - - Unlike ``np.transpose``, the ``axis`` keyword-argument to - ``permute_dims`` is required. - * - ``pow`` - - ``power`` - - - - -``linalg`` Namespace Differences -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -These functions are in the ``linalg`` sub-namespace in the array API, but are -only in the top-level namespace in NumPy: - -- ``matmul`` (*) -- ``tensordot`` (*) - -(*): These functions are also in the top-level namespace in the array API. Keyword Argument Renames ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/reference/routines.array-manipulation.rst b/doc/source/reference/routines.array-manipulation.rst index 559510599fcb..576f04fc6a23 100644 --- a/doc/source/reference/routines.array-manipulation.rst +++ b/doc/source/reference/routines.array-manipulation.rst @@ -32,6 +32,7 @@ Transpose-like operations swapaxes ndarray.T transpose + permute_dims Changing number of dimensions ============================= @@ -66,6 +67,7 @@ Joining arrays :toctree: generated/ concatenate + concat stack block vstack diff --git a/doc/source/reference/routines.bitwise.rst b/doc/source/reference/routines.bitwise.rst index 5bf61ed8abf5..293cb6722d04 100644 --- a/doc/source/reference/routines.bitwise.rst +++ b/doc/source/reference/routines.bitwise.rst @@ -12,8 +12,11 @@ Elementwise bit operations bitwise_or bitwise_xor invert + bitwise_invert left_shift + bitwise_left_shift right_shift + bitwise_right_shift Bit packing ----------- diff --git a/doc/source/reference/routines.linalg.rst b/doc/source/reference/routines.linalg.rst index 64a731d5168b..1cdb31a60b61 100644 --- a/doc/source/reference/routines.linalg.rst +++ b/doc/source/reference/routines.linalg.rst @@ -59,7 +59,9 @@ Matrix and vector products inner outer matmul + linalg.matmul (Array API compatible location) tensordot + linalg.tensordot (Array API compatible location) einsum einsum_path linalg.matrix_power diff --git a/doc/source/reference/routines.math.rst b/doc/source/reference/routines.math.rst index 8a5b3be26105..2c77b2cc1488 100644 --- a/doc/source/reference/routines.math.rst +++ b/doc/source/reference/routines.math.rst @@ -12,10 +12,14 @@ Trigonometric functions cos tan arcsin + asin arccos + acos arctan + atan hypot arctan2 + atan2 degrees radians unwrap @@ -31,8 +35,11 @@ Hyperbolic functions cosh tanh arcsinh + asinh arccosh + acosh arctanh + atanh Rounding -------- @@ -120,6 +127,7 @@ Arithmetic operations multiply divide power + pow subtract true_divide floor_divide diff --git a/numpy/__init__.py b/numpy/__init__.py index 5bf73f5abeba..f7934539f0d9 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -121,24 +121,25 @@ from . import _core from ._core import ( False_, ScalarType, True_, _get_promotion_state, _no_nep50_warning, - _set_promotion_state, abs, absolute, add, all, allclose, alltrue, - amax, amin, any, arange, arccos, arccosh, arcsin, arcsinh, arctan, - arctan2, arctanh, argmax, argmin, argpartition, argsort, argwhere, - around, array, array2string, array_equal, array_equiv, array_repr, - array_str, asanyarray, asarray, ascontiguousarray, asfortranarray, - astype, atleast_1d, atleast_2d, atleast_3d, base_repr, binary_repr, - bitwise_and, bitwise_count, bitwise_not, bitwise_or, bitwise_xor, - block, bool, bool_, broadcast, busday_count, busday_offset, - busdaycalendar, byte, bytes_, can_cast, cbrt, cdouble, ceil, - character, choose, clip, clongdouble, complex128, complex64, - complexfloating, compress, concatenate, conj, conjugate, convolve, - copysign, copyto, correlate, cos, cosh, count_nonzero, cross, csingle, - cumprod, cumproduct, cumsum, datetime64, datetime_as_string, - datetime_data, deg2rad, degrees, diagonal, divide, divmod, dot, - double, dtype, e, einsum, einsum_path, empty, empty_like, equal, - errstate, euler_gamma, exp, exp2, expm1, fabs, finfo, flatiter, - flatnonzero, flexible, float16, float32, float64, float_power, - floating, floor, floor_divide, fmax, fmin, fmod, + _set_promotion_state, abs, absolute, acos, acosh, add, all, allclose, + alltrue, amax, amin, any, arange, arccos, arccosh, arcsin, arcsinh, + arctan, arctan2, arctanh, argmax, argmin, argpartition, argsort, + argwhere, around, array, array2string, array_equal, array_equiv, + array_repr, array_str, asanyarray, asarray, ascontiguousarray, + asfortranarray, asin, asinh, atan, atanh, atan2, astype, atleast_1d, + atleast_2d, atleast_3d, base_repr, binary_repr, bitwise_and, + bitwise_count, bitwise_invert, bitwise_left_shift, bitwise_not, + bitwise_or, bitwise_right_shift, bitwise_xor, block, bool, bool_, + broadcast, busday_count, busday_offset, busdaycalendar, byte, bytes_, + can_cast, cbrt, cdouble, ceil, character, choose, clip, clongdouble, + complex128, complex64, complexfloating, compress, concat, concatenate, + conj, conjugate, convolve, copysign, copyto, correlate, cos, cosh, + count_nonzero, cross, csingle, cumprod, cumproduct, cumsum, + datetime64, datetime_as_string, datetime_data, deg2rad, degrees, + diagonal, divide, divmod, dot, double, dtype, e, einsum, einsum_path, + empty, empty_like, equal, errstate, euler_gamma, exp, exp2, expm1, + fabs, finfo, flatiter, flatnonzero, flexible, float16, float32, + float64, float_power, floating, floor, floor_divide, fmax, fmin, fmod, format_float_positional, format_float_scientific, frexp, from_dlpack, frombuffer, fromfile, fromfunction, fromiter, frompyfunc, fromstring, full, full_like, gcd, generic, geomspace, get_printoptions, @@ -153,18 +154,18 @@ may_share_memory, mean, memmap, min, min_scalar_type, minimum, mod, modf, moveaxis, multiply, nan, ndarray, ndim, nditer, negative, nested_iters, newaxis, nextafter, nonzero, not_equal, number, object_, - ones, ones_like, outer, partition, pi, positive, power, printoptions, - prod, product, promote_types, ptp, put, putmask, rad2deg, radians, - ravel, recarray, reciprocal, record, remainder, repeat, require, - reshape, resize, result_type, right_shift, rint, roll, rollaxis, - round, sctypeDict, searchsorted, set_printoptions, setbufsize, seterr, - seterrcall, shape, shares_memory, short, sign, signbit, signedinteger, - sin, single, sinh, size, sometrue, sort, spacing, sqrt, square, - squeeze, stack, std, str_, subtract, sum, swapaxes, take, tan, tanh, - tensordot, timedelta64, trace, transpose, true_divide, trunc, - typecodes, ubyte, ufunc, uint, uint16, uint32, uint64, uint8, uintc, - uintp, ulong, ulonglong, unsignedinteger, ushort, var, vdot, void, - vstack, where, zeros, zeros_like + ones, ones_like, outer, partition, permute_dims, pi, positive, pow, + power, printoptions, prod, product, promote_types, ptp, put, putmask, + rad2deg, radians, ravel, recarray, reciprocal, record, remainder, + repeat, require, reshape, resize, result_type, right_shift, rint, + roll, rollaxis, round, sctypeDict, searchsorted, set_printoptions, + setbufsize, seterr, seterrcall, shape, shares_memory, short, sign, + signbit, signedinteger, sin, single, sinh, size, sometrue, sort, + spacing, sqrt, square, squeeze, stack, std, str_, subtract, sum, + swapaxes, take, tan, tanh, tensordot, timedelta64, trace, transpose, + true_divide, trunc, typecodes, ubyte, ufunc, uint, uint16, uint32, + uint64, uint8, uintc, uintp, ulong, ulonglong, unsignedinteger, + ushort, var, vdot, void, vstack, where, zeros, zeros_like ) # NOTE: It's still under discussion whether these aliases diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index ac6143bfa055..13573d2d967c 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -3248,6 +3248,19 @@ true_divide: _UFunc_Nin2_Nout1[L['true_divide'], L[11], None] trunc: _UFunc_Nin1_Nout1[L['trunc'], L[7], None] abs = absolute +acos = arccos +acosh = arccosh +asin = arcsin +asinh = arcsinh +atan = arctan +atanh = arctanh +atan2 = arctan2 +concat = concatenate +bitwise_left_shift = left_shift +bitwise_invert = invert +bitwise_right_shift = right_shift +permute_dims = transpose +pow = power class _CopyMode(enum.Enum): ALWAYS: L[True] diff --git a/numpy/_core/__init__.py b/numpy/_core/__init__.py index 33fb1b52f9ea..4b90877138a3 100644 --- a/numpy/_core/__init__.py +++ b/numpy/_core/__init__.py @@ -101,7 +101,25 @@ from . import _dtype from . import _methods -__all__ = ['memmap', 'sctypeDict', 'record', 'recarray', 'abs'] +acos = numeric.arccos +acosh = numeric.arccosh +asin = numeric.arcsin +asinh = numeric.arcsinh +atan = numeric.arctan +atanh = numeric.arctanh +atan2 = numeric.arctan2 +concat = numeric.concatenate +bitwise_left_shift = numeric.left_shift +bitwise_invert = numeric.invert +bitwise_right_shift = numeric.right_shift +permute_dims = numeric.transpose +pow = numeric.power + +__all__ = [ + "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", "atan2", + "bitwise_invert", "bitwise_left_shift", "bitwise_right_shift", "concat", + "pow", "permute_dims", "memmap", "sctypeDict", "record", "recarray" +] __all__ += numeric.__all__ __all__ += function_base.__all__ __all__ += getlimits.__all__ diff --git a/numpy/linalg/__init__.py b/numpy/linalg/__init__.py index bfc65a08d14a..c1a95239a33c 100644 --- a/numpy/linalg/__init__.py +++ b/numpy/linalg/__init__.py @@ -29,6 +29,8 @@ cross multi_dot matrix_power + tensordot + matmul Decompositions -------------- diff --git a/numpy/linalg/__init__.pyi b/numpy/linalg/__init__.pyi index e2f9343eea8b..4ef877d2f663 100644 --- a/numpy/linalg/__init__.pyi +++ b/numpy/linalg/__init__.pyi @@ -21,11 +21,16 @@ from numpy.linalg._linalg import ( cond as cond, matrix_rank as matrix_rank, multi_dot as multi_dot, + matmul as matmul, trace as trace, diagonal as diagonal, cross as cross, ) +from numpy._core.numeric import ( + tensordot as tensordot, +) + from numpy._pytesttester import PytestTester __all__: list[str] diff --git a/numpy/linalg/_linalg.py b/numpy/linalg/_linalg.py index 5631294b364f..3cbcdff82c3e 100644 --- a/numpy/linalg/_linalg.py +++ b/numpy/linalg/_linalg.py @@ -13,7 +13,7 @@ 'cholesky', 'eigvals', 'eigvalsh', 'pinv', 'slogdet', 'det', 'svd', 'svdvals', 'eig', 'eigh', 'lstsq', 'norm', 'qr', 'cond', 'matrix_rank', 'LinAlgError', 'multi_dot', 'trace', 'diagonal', - 'cross', 'outer'] + 'cross', 'outer', 'tensordot', 'matmul'] import functools import operator @@ -28,7 +28,8 @@ amax, prod, abs, atleast_2d, intp, asanyarray, object_, matmul, swapaxes, divide, count_nonzero, isnan, sign, argsort, sort, reciprocal, overrides, diagonal as _core_diagonal, trace as _core_trace, - cross as _core_cross, outer as _core_outer + cross as _core_cross, outer as _core_outer, tensordot as _core_tensordot, + matmul as _core_matmul, ) from numpy.lib._twodim_base_impl import triu, eye from numpy.lib.array_utils import normalize_axis_index @@ -3129,3 +3130,61 @@ def cross(x1, x2, /, *, axis=-1): ) return _core_cross(x1, x2, axis=axis) + + +# matmul + +def _matmul_dispatcher(x1, x2, /): + return (x1, x2) + + +@array_function_dispatch(_matmul_dispatcher) +def matmul(x1, x2, /): + """ + Computes the matrix product. + + This function is Array API compatible, contrary to + :func:`numpy.matmul`. + + Parameters + ---------- + x1 : array_like + The first input array. + x2 : array_like + The second input array. + + Returns + ------- + out : ndarray + The matrix product of the inputs. + This is a scalar only when both ``x1``, ``x2`` are 1-d vectors. + + Raises + ------ + ValueError + If the last dimension of ``x1`` is not the same size as + the second-to-last dimension of ``x2``. + + If a scalar value is passed in. + + See Also + -------- + numpy.matmul + + """ + return _core_matmul(x1, x2) + + +# tensordot + +def _tensordot_dispatcher( + x1, x2, /, *, offset=None, dtype=None): + return (x1, x2) + + +@array_function_dispatch(_tensordot_dispatcher) +def tensordot(x1, x2, /, *, axes=2): + return _core_tensordot(x1, x2, axes=axes) + + +tensordot.__doc__ = _core_tensordot.__doc__ diff --git a/numpy/linalg/_linalg.pyi b/numpy/linalg/_linalg.pyi index 82b637f17957..4c25886b56b5 100644 --- a/numpy/linalg/_linalg.pyi +++ b/numpy/linalg/_linalg.pyi @@ -373,3 +373,24 @@ def cross( b: _ArrayLikeComplex_co, axis: int = ..., ) -> NDArray[complexfloating[Any, Any]]: ... + +@overload +def matmul( + x1: _ArrayLikeInt_co, + x2: _ArrayLikeInt_co, +) -> NDArray[signedinteger[Any]]: ... +@overload +def matmul( + x1: _ArrayLikeUInt_co, + x2: _ArrayLikeUInt_co, +) -> NDArray[unsignedinteger[Any]]: ... +@overload +def matmul( + x1: _ArrayLikeFloat_co, + x2: _ArrayLikeFloat_co, +) -> NDArray[floating[Any]]: ... +@overload +def matmul( + x1: _ArrayLikeComplex_co, + x2: _ArrayLikeComplex_co, +) -> NDArray[complexfloating[Any, Any]]: ... diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py index 2070918395e6..54ffb3ce1338 100644 --- a/numpy/linalg/tests/test_linalg.py +++ b/numpy/linalg/tests/test_linalg.py @@ -2254,7 +2254,6 @@ def test_trace(): def test_cross(): - x = np.arange(9).reshape((3, 3)) actual = np.linalg.cross(x, x + 1) expected = np.array([ @@ -2271,3 +2270,20 @@ def test_cross(): ): x_2dim = x[:, 1:] np.linalg.cross(x_2dim, x_2dim) + + +def test_tensordot(): + # np.linalg.tensordot is just an alias for np.tensordot + x = np.arange(6).reshape((2, 3)) + + assert np.linalg.tensordot(x, x) == 55 + + +def test_matmul(): + # np.linalg.matmul and np.matmul only differs in the number + # of arguments in the signature + x = np.arange(6).reshape((2, 3)) + actual = np.linalg.matmul(x, x.T) + expected = np.array([[5, 14], [14, 50]]) + + assert_equal(actual, expected) diff --git a/numpy/tests/test_public_api.py b/numpy/tests/test_public_api.py index 97078a4fe702..bbfac7748b28 100644 --- a/numpy/tests/test_public_api.py +++ b/numpy/tests/test_public_api.py @@ -613,10 +613,22 @@ def test_functions_single_location(): if ( member.__name__ in [ "absolute", # np.abs + "arccos", # np.acos + "arccosh", # np.acosh + "arcsin", # np.asin + "arcsinh", # np.asinh + "arctan", # np.atan + "arctan2", # np.atan2 + "arctanh", # np.atanh + "left_shift", # np.bitwise_left_shift + "right_shift", # np.bitwise_right_shift "conjugate", # np.conj - "invert", # np.bitwise_not + "invert", # np.bitwise_not & np.bitwise_invert "remainder", # np.mod "divide", # np.true_divide + "concatenate", # np.concat + "power", # np.pow + "transpose", # np.permute_dims ] and module.__name__ == "numpy" ): diff --git a/numpy/typing/tests/data/reveal/linalg.pyi b/numpy/typing/tests/data/reveal/linalg.pyi index f7508f4e6b8d..f3ddc4ce92d1 100644 --- a/numpy/typing/tests/data/reveal/linalg.pyi +++ b/numpy/typing/tests/data/reveal/linalg.pyi @@ -118,3 +118,7 @@ assert_type(np.linalg.multi_dot([AR_m, AR_m]), Any) assert_type(np.linalg.cross(AR_i8, AR_i8), npt.NDArray[np.signedinteger[Any]]) assert_type(np.linalg.cross(AR_f8, AR_f8), npt.NDArray[np.floating[Any]]) assert_type(np.linalg.cross(AR_c16, AR_c16), npt.NDArray[np.complexfloating[Any, Any]]) + +assert_type(np.linalg.matmul(AR_i8, AR_i8), npt.NDArray[np.signedinteger[Any]]) +assert_type(np.linalg.matmul(AR_f8, AR_f8), npt.NDArray[np.floating[Any]]) +assert_type(np.linalg.matmul(AR_c16, AR_c16), npt.NDArray[np.complexfloating[Any, Any]]) diff --git a/tools/ci/array-api-skips.txt b/tools/ci/array-api-skips.txt index c5e3f40acac3..695a7f9f1068 100644 --- a/tools/ci/array-api-skips.txt +++ b/tools/ci/array-api-skips.txt @@ -41,26 +41,11 @@ array_api_tests/test_data_type_functions.py::test_finfo[float32] array_api_tests/test_data_type_functions.py::test_isdtype # missing names -array_api_tests/test_has_names.py::test_has_names[linalg-matmul] array_api_tests/test_has_names.py::test_has_names[linalg-matrix_norm] array_api_tests/test_has_names.py::test_has_names[linalg-matrix_transpose] -array_api_tests/test_has_names.py::test_has_names[linalg-tensordot] array_api_tests/test_has_names.py::test_has_names[linalg-vecdot] array_api_tests/test_has_names.py::test_has_names[linalg-vector_norm] -array_api_tests/test_has_names.py::test_has_names[manipulation-concat] -array_api_tests/test_has_names.py::test_has_names[manipulation-permute_dims] array_api_tests/test_has_names.py::test_has_names[data_type-isdtype] -array_api_tests/test_has_names.py::test_has_names[elementwise-acos] -array_api_tests/test_has_names.py::test_has_names[elementwise-acosh] -array_api_tests/test_has_names.py::test_has_names[elementwise-asin] -array_api_tests/test_has_names.py::test_has_names[elementwise-asinh] -array_api_tests/test_has_names.py::test_has_names[elementwise-atan] -array_api_tests/test_has_names.py::test_has_names[elementwise-atan2] -array_api_tests/test_has_names.py::test_has_names[elementwise-atanh] -array_api_tests/test_has_names.py::test_has_names[elementwise-bitwise_left_shift] -array_api_tests/test_has_names.py::test_has_names[elementwise-bitwise_invert] -array_api_tests/test_has_names.py::test_has_names[elementwise-bitwise_right_shift] -array_api_tests/test_has_names.py::test_has_names[elementwise-pow] array_api_tests/test_has_names.py::test_has_names[linear_algebra-matrix_transpose] array_api_tests/test_has_names.py::test_has_names[linear_algebra-vecdot] array_api_tests/test_has_names.py::test_has_names[array_method-to_device] @@ -72,10 +57,6 @@ array_api_tests/test_linalg.py::test_matrix_transpose array_api_tests/test_linalg.py::test_pinv array_api_tests/test_linalg.py::test_vecdot -# missing names -array_api_tests/test_manipulation_functions.py::test_concat -array_api_tests/test_manipulation_functions.py::test_permute_dims - # a few misalignments array_api_tests/test_operators_and_elementwise_functions.py array_api_tests/test_signatures.py::test_func_signature[std] @@ -89,32 +70,17 @@ array_api_tests/test_signatures.py::test_func_signature[linspace] array_api_tests/test_signatures.py::test_func_signature[ones] array_api_tests/test_signatures.py::test_func_signature[ones_like] array_api_tests/test_signatures.py::test_func_signature[zeros_like] -array_api_tests/test_signatures.py::test_func_signature[concat] -array_api_tests/test_signatures.py::test_func_signature[permute_dims] array_api_tests/test_signatures.py::test_func_signature[reshape] array_api_tests/test_signatures.py::test_func_signature[argsort] array_api_tests/test_signatures.py::test_func_signature[sort] array_api_tests/test_signatures.py::test_func_signature[isdtype] -array_api_tests/test_signatures.py::test_func_signature[acos] -array_api_tests/test_signatures.py::test_func_signature[acosh] -array_api_tests/test_signatures.py::test_func_signature[asin] -array_api_tests/test_signatures.py::test_func_signature[asinh] -array_api_tests/test_signatures.py::test_func_signature[atan] -array_api_tests/test_signatures.py::test_func_signature[atan2] -array_api_tests/test_signatures.py::test_func_signature[atanh] -array_api_tests/test_signatures.py::test_func_signature[bitwise_left_shift] -array_api_tests/test_signatures.py::test_func_signature[bitwise_invert] -array_api_tests/test_signatures.py::test_func_signature[bitwise_right_shift] -array_api_tests/test_signatures.py::test_func_signature[pow] array_api_tests/test_signatures.py::test_func_signature[matrix_transpose] array_api_tests/test_signatures.py::test_func_signature[vecdot] -array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matmul] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.cholesky] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_norm] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_rank] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_transpose] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.pinv] -array_api_tests/test_signatures.py::test_extension_func_signature[linalg.tensordot] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.vecdot] array_api_tests/test_signatures.py::test_extension_func_signature[linalg.vector_norm] array_api_tests/test_signatures.py::test_array_method_signature[__array_namespace__]