ZhengyangZhang commited on
Commit
b9918be
·
verified ·
1 Parent(s): 466722c

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/numpy/_core/__init__.py +4 -0
  2. lib/python3.12/site-packages/numpy/_core/__init__.pyi +0 -0
  3. lib/python3.12/site-packages/numpy/_core/__pycache__/__init__.cpython-312.pyc +0 -0
  4. lib/python3.12/site-packages/numpy/_core/__pycache__/_dtype.cpython-312.pyc +0 -0
  5. lib/python3.12/site-packages/numpy/_core/__pycache__/_dtype_ctypes.cpython-312.pyc +0 -0
  6. lib/python3.12/site-packages/numpy/_core/__pycache__/_internal.cpython-312.pyc +0 -0
  7. lib/python3.12/site-packages/numpy/_core/__pycache__/_multiarray_umath.cpython-312.pyc +0 -0
  8. lib/python3.12/site-packages/numpy/_core/__pycache__/multiarray.cpython-312.pyc +0 -0
  9. lib/python3.12/site-packages/numpy/_core/__pycache__/umath.cpython-312.pyc +0 -0
  10. lib/python3.12/site-packages/numpy/_core/_dtype.py +6 -0
  11. lib/python3.12/site-packages/numpy/_core/_dtype_ctypes.py +6 -0
  12. lib/python3.12/site-packages/numpy/_core/_internal.py +6 -0
  13. lib/python3.12/site-packages/numpy/_core/_multiarray_umath.py +6 -0
  14. lib/python3.12/site-packages/numpy/_core/multiarray.py +6 -0
  15. lib/python3.12/site-packages/numpy/_core/umath.py +6 -0
  16. lib/python3.12/site-packages/numpy/array_api/__init__.py +387 -0
  17. lib/python3.12/site-packages/numpy/array_api/__pycache__/_data_type_functions.cpython-312.pyc +0 -0
  18. lib/python3.12/site-packages/numpy/array_api/__pycache__/_elementwise_functions.cpython-312.pyc +0 -0
  19. lib/python3.12/site-packages/numpy/array_api/__pycache__/_indexing_functions.cpython-312.pyc +0 -0
  20. lib/python3.12/site-packages/numpy/array_api/__pycache__/_manipulation_functions.cpython-312.pyc +0 -0
  21. lib/python3.12/site-packages/numpy/array_api/__pycache__/_searching_functions.cpython-312.pyc +0 -0
  22. lib/python3.12/site-packages/numpy/array_api/__pycache__/linalg.cpython-312.pyc +0 -0
  23. lib/python3.12/site-packages/numpy/array_api/_array_object.py +1133 -0
  24. lib/python3.12/site-packages/numpy/array_api/_constants.py +7 -0
  25. lib/python3.12/site-packages/numpy/array_api/_creation_functions.py +351 -0
  26. lib/python3.12/site-packages/numpy/array_api/_data_type_functions.py +197 -0
  27. lib/python3.12/site-packages/numpy/array_api/_dtypes.py +180 -0
  28. lib/python3.12/site-packages/numpy/array_api/_elementwise_functions.py +765 -0
  29. lib/python3.12/site-packages/numpy/array_api/_indexing_functions.py +20 -0
  30. lib/python3.12/site-packages/numpy/array_api/_manipulation_functions.py +112 -0
  31. lib/python3.12/site-packages/numpy/array_api/_searching_functions.py +51 -0
  32. lib/python3.12/site-packages/numpy/array_api/_set_functions.py +106 -0
  33. lib/python3.12/site-packages/numpy/array_api/_sorting_functions.py +54 -0
  34. lib/python3.12/site-packages/numpy/array_api/_statistical_functions.py +122 -0
  35. lib/python3.12/site-packages/numpy/array_api/_typing.py +76 -0
  36. lib/python3.12/site-packages/numpy/array_api/_utility_functions.py +37 -0
  37. lib/python3.12/site-packages/numpy/array_api/linalg.py +466 -0
  38. lib/python3.12/site-packages/numpy/array_api/setup.py +12 -0
  39. lib/python3.12/site-packages/numpy/array_api/tests/__init__.py +7 -0
  40. lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/__init__.cpython-312.pyc +0 -0
  41. lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_array_object.cpython-312.pyc +0 -0
  42. lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_creation_functions.cpython-312.pyc +0 -0
  43. lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_data_type_functions.cpython-312.pyc +0 -0
  44. lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_elementwise_functions.cpython-312.pyc +0 -0
  45. lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_indexing_functions.cpython-312.pyc +0 -0
  46. lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_manipulation_functions.cpython-312.pyc +0 -0
  47. lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_set_functions.cpython-312.pyc +0 -0
  48. lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_sorting_functions.cpython-312.pyc +0 -0
  49. lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_validation.cpython-312.pyc +0 -0
  50. lib/python3.12/site-packages/numpy/array_api/tests/test_array_object.py +395 -0
lib/python3.12/site-packages/numpy/_core/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ """
2
+ This private module only contains stubs for interoperability with
3
+ NumPy 2.0 pickled arrays. It may not be used by the end user.
4
+ """
lib/python3.12/site-packages/numpy/_core/__init__.pyi ADDED
File without changes
lib/python3.12/site-packages/numpy/_core/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (336 Bytes). View file
 
lib/python3.12/site-packages/numpy/_core/__pycache__/_dtype.cpython-312.pyc ADDED
Binary file (399 Bytes). View file
 
lib/python3.12/site-packages/numpy/_core/__pycache__/_dtype_ctypes.cpython-312.pyc ADDED
Binary file (415 Bytes). View file
 
lib/python3.12/site-packages/numpy/_core/__pycache__/_internal.cpython-312.pyc ADDED
Binary file (407 Bytes). View file
 
lib/python3.12/site-packages/numpy/_core/__pycache__/_multiarray_umath.cpython-312.pyc ADDED
Binary file (425 Bytes). View file
 
lib/python3.12/site-packages/numpy/_core/__pycache__/multiarray.cpython-312.pyc ADDED
Binary file (409 Bytes). View file
 
lib/python3.12/site-packages/numpy/_core/__pycache__/umath.cpython-312.pyc ADDED
Binary file (396 Bytes). View file
 
lib/python3.12/site-packages/numpy/_core/_dtype.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from numpy.core import _dtype
2
+
3
+ _globals = globals()
4
+
5
+ for item in _dtype.__dir__():
6
+ _globals[item] = getattr(_dtype, item)
lib/python3.12/site-packages/numpy/_core/_dtype_ctypes.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from numpy.core import _dtype_ctypes
2
+
3
+ _globals = globals()
4
+
5
+ for item in _dtype_ctypes.__dir__():
6
+ _globals[item] = getattr(_dtype_ctypes, item)
lib/python3.12/site-packages/numpy/_core/_internal.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from numpy.core import _internal
2
+
3
+ _globals = globals()
4
+
5
+ for item in _internal.__dir__():
6
+ _globals[item] = getattr(_internal, item)
lib/python3.12/site-packages/numpy/_core/_multiarray_umath.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from numpy.core import _multiarray_umath
2
+
3
+ _globals = globals()
4
+
5
+ for item in _multiarray_umath.__dir__():
6
+ _globals[item] = getattr(_multiarray_umath, item)
lib/python3.12/site-packages/numpy/_core/multiarray.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from numpy.core import multiarray
2
+
3
+ _globals = globals()
4
+
5
+ for item in multiarray.__dir__():
6
+ _globals[item] = getattr(multiarray, item)
lib/python3.12/site-packages/numpy/_core/umath.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from numpy.core import umath
2
+
3
+ _globals = globals()
4
+
5
+ for item in umath.__dir__():
6
+ _globals[item] = getattr(umath, item)
lib/python3.12/site-packages/numpy/array_api/__init__.py ADDED
@@ -0,0 +1,387 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ A NumPy sub-namespace that conforms to the Python array API standard.
3
+
4
+ This submodule accompanies NEP 47, which proposes its inclusion in NumPy. It
5
+ is still considered experimental, and will issue a warning when imported.
6
+
7
+ This is a proof-of-concept namespace that wraps the corresponding NumPy
8
+ functions to give a conforming implementation of the Python array API standard
9
+ (https://data-apis.github.io/array-api/latest/). The standard is currently in
10
+ an RFC phase and comments on it are both welcome and encouraged. Comments
11
+ should be made either at https://github.com/data-apis/array-api or at
12
+ https://github.com/data-apis/consortium-feedback/discussions.
13
+
14
+ NumPy already follows the proposed spec for the most part, so this module
15
+ serves mostly as a thin wrapper around it. However, NumPy also implements a
16
+ lot of behavior that is not included in the spec, so this serves as a
17
+ restricted subset of the API. Only those functions that are part of the spec
18
+ are included in this namespace, and all functions are given with the exact
19
+ signature given in the spec, including the use of position-only arguments, and
20
+ omitting any extra keyword arguments implemented by NumPy but not part of the
21
+ spec. The behavior of some functions is also modified from the NumPy behavior
22
+ to conform to the standard. Note that the underlying array object itself is
23
+ wrapped in a wrapper Array() class, but is otherwise unchanged. This submodule
24
+ is implemented in pure Python with no C extensions.
25
+
26
+ The array API spec is designed as a "minimal API subset" and explicitly allows
27
+ libraries to include behaviors not specified by it. But users of this module
28
+ that intend to write portable code should be aware that only those behaviors
29
+ that are listed in the spec are guaranteed to be implemented across libraries.
30
+ Consequently, the NumPy implementation was chosen to be both conforming and
31
+ minimal, so that users can use this implementation of the array API namespace
32
+ and be sure that behaviors that it defines will be available in conforming
33
+ namespaces from other libraries.
34
+
35
+ A few notes about the current state of this submodule:
36
+
37
+ - There is a test suite that tests modules against the array API standard at
38
+ https://github.com/data-apis/array-api-tests. The test suite is still a work
39
+ in progress, but the existing tests pass on this module, with a few
40
+ exceptions:
41
+
42
+ - DLPack support (see https://github.com/data-apis/array-api/pull/106) is
43
+ not included here, as it requires a full implementation in NumPy proper
44
+ first.
45
+
46
+ The test suite is not yet complete, and even the tests that exist are not
47
+ guaranteed to give a comprehensive coverage of the spec. Therefore, when
48
+ reviewing and using this submodule, you should refer to the standard
49
+ documents themselves. There are some tests in numpy.array_api.tests, but
50
+ they primarily focus on things that are not tested by the official array API
51
+ test suite.
52
+
53
+ - There is a custom array object, numpy.array_api.Array, which is returned by
54
+ all functions in this module. All functions in the array API namespace
55
+ implicitly assume that they will only receive this object as input. The only
56
+ way to create instances of this object is to use one of the array creation
57
+ functions. It does not have a public constructor on the object itself. The
58
+ object is a small wrapper class around numpy.ndarray. The main purpose of it
59
+ is to restrict the namespace of the array object to only those dtypes and
60
+ only those methods that are required by the spec, as well as to limit/change
61
+ certain behavior that differs in the spec. In particular:
62
+
63
+ - The array API namespace does not have scalar objects, only 0-D arrays.
64
+ Operations on Array that would create a scalar in NumPy create a 0-D
65
+ array.
66
+
67
+ - Indexing: Only a subset of indices supported by NumPy are required by the
68
+ spec. The Array object restricts indexing to only allow those types of
69
+ indices that are required by the spec. See the docstring of the
70
+ numpy.array_api.Array._validate_indices helper function for more
71
+ information.
72
+
73
+ - Type promotion: Some type promotion rules are different in the spec. In
74
+ particular, the spec does not have any value-based casting. The spec also
75
+ does not require cross-kind casting, like integer -> floating-point. Only
76
+ those promotions that are explicitly required by the array API
77
+ specification are allowed in this module. See NEP 47 for more info.
78
+
79
+ - Functions do not automatically call asarray() on their input, and will not
80
+ work if the input type is not Array. The exception is array creation
81
+ functions, and Python operators on the Array object, which accept Python
82
+ scalars of the same type as the array dtype.
83
+
84
+ - All functions include type annotations, corresponding to those given in the
85
+ spec (see _typing.py for definitions of some custom types). These do not
86
+ currently fully pass mypy due to some limitations in mypy.
87
+
88
+ - Dtype objects are just the NumPy dtype objects, e.g., float64 =
89
+ np.dtype('float64'). The spec does not require any behavior on these dtype
90
+ objects other than that they be accessible by name and be comparable by
91
+ equality, but it was considered too much extra complexity to create custom
92
+ objects to represent dtypes.
93
+
94
+ - All places where the implementations in this submodule are known to deviate
95
+ from their corresponding functions in NumPy are marked with "# Note:"
96
+ comments.
97
+
98
+ Still TODO in this module are:
99
+
100
+ - DLPack support for numpy.ndarray is still in progress. See
101
+ https://github.com/numpy/numpy/pull/19083.
102
+
103
+ - The copy=False keyword argument to asarray() is not yet implemented. This
104
+ requires support in numpy.asarray() first.
105
+
106
+ - Some functions are not yet fully tested in the array API test suite, and may
107
+ require updates that are not yet known until the tests are written.
108
+
109
+ - The spec is still in an RFC phase and may still have minor updates, which
110
+ will need to be reflected here.
111
+
112
+ - Complex number support in array API spec is planned but not yet finalized,
113
+ as are the fft extension and certain linear algebra functions such as eig
114
+ that require complex dtypes.
115
+
116
+ """
117
+
118
+ import warnings
119
+
120
+ warnings.warn(
121
+ "The numpy.array_api submodule is still experimental. See NEP 47.", stacklevel=2
122
+ )
123
+
124
+ __array_api_version__ = "2022.12"
125
+
126
+ __all__ = ["__array_api_version__"]
127
+
128
+ from ._constants import e, inf, nan, pi, newaxis
129
+
130
+ __all__ += ["e", "inf", "nan", "pi", "newaxis"]
131
+
132
+ from ._creation_functions import (
133
+ asarray,
134
+ arange,
135
+ empty,
136
+ empty_like,
137
+ eye,
138
+ from_dlpack,
139
+ full,
140
+ full_like,
141
+ linspace,
142
+ meshgrid,
143
+ ones,
144
+ ones_like,
145
+ tril,
146
+ triu,
147
+ zeros,
148
+ zeros_like,
149
+ )
150
+
151
+ __all__ += [
152
+ "asarray",
153
+ "arange",
154
+ "empty",
155
+ "empty_like",
156
+ "eye",
157
+ "from_dlpack",
158
+ "full",
159
+ "full_like",
160
+ "linspace",
161
+ "meshgrid",
162
+ "ones",
163
+ "ones_like",
164
+ "tril",
165
+ "triu",
166
+ "zeros",
167
+ "zeros_like",
168
+ ]
169
+
170
+ from ._data_type_functions import (
171
+ astype,
172
+ broadcast_arrays,
173
+ broadcast_to,
174
+ can_cast,
175
+ finfo,
176
+ isdtype,
177
+ iinfo,
178
+ result_type,
179
+ )
180
+
181
+ __all__ += [
182
+ "astype",
183
+ "broadcast_arrays",
184
+ "broadcast_to",
185
+ "can_cast",
186
+ "finfo",
187
+ "iinfo",
188
+ "result_type",
189
+ ]
190
+
191
+ from ._dtypes import (
192
+ int8,
193
+ int16,
194
+ int32,
195
+ int64,
196
+ uint8,
197
+ uint16,
198
+ uint32,
199
+ uint64,
200
+ float32,
201
+ float64,
202
+ complex64,
203
+ complex128,
204
+ bool,
205
+ )
206
+
207
+ __all__ += [
208
+ "int8",
209
+ "int16",
210
+ "int32",
211
+ "int64",
212
+ "uint8",
213
+ "uint16",
214
+ "uint32",
215
+ "uint64",
216
+ "float32",
217
+ "float64",
218
+ "bool",
219
+ ]
220
+
221
+ from ._elementwise_functions import (
222
+ abs,
223
+ acos,
224
+ acosh,
225
+ add,
226
+ asin,
227
+ asinh,
228
+ atan,
229
+ atan2,
230
+ atanh,
231
+ bitwise_and,
232
+ bitwise_left_shift,
233
+ bitwise_invert,
234
+ bitwise_or,
235
+ bitwise_right_shift,
236
+ bitwise_xor,
237
+ ceil,
238
+ conj,
239
+ cos,
240
+ cosh,
241
+ divide,
242
+ equal,
243
+ exp,
244
+ expm1,
245
+ floor,
246
+ floor_divide,
247
+ greater,
248
+ greater_equal,
249
+ imag,
250
+ isfinite,
251
+ isinf,
252
+ isnan,
253
+ less,
254
+ less_equal,
255
+ log,
256
+ log1p,
257
+ log2,
258
+ log10,
259
+ logaddexp,
260
+ logical_and,
261
+ logical_not,
262
+ logical_or,
263
+ logical_xor,
264
+ multiply,
265
+ negative,
266
+ not_equal,
267
+ positive,
268
+ pow,
269
+ real,
270
+ remainder,
271
+ round,
272
+ sign,
273
+ sin,
274
+ sinh,
275
+ square,
276
+ sqrt,
277
+ subtract,
278
+ tan,
279
+ tanh,
280
+ trunc,
281
+ )
282
+
283
+ __all__ += [
284
+ "abs",
285
+ "acos",
286
+ "acosh",
287
+ "add",
288
+ "asin",
289
+ "asinh",
290
+ "atan",
291
+ "atan2",
292
+ "atanh",
293
+ "bitwise_and",
294
+ "bitwise_left_shift",
295
+ "bitwise_invert",
296
+ "bitwise_or",
297
+ "bitwise_right_shift",
298
+ "bitwise_xor",
299
+ "ceil",
300
+ "cos",
301
+ "cosh",
302
+ "divide",
303
+ "equal",
304
+ "exp",
305
+ "expm1",
306
+ "floor",
307
+ "floor_divide",
308
+ "greater",
309
+ "greater_equal",
310
+ "isfinite",
311
+ "isinf",
312
+ "isnan",
313
+ "less",
314
+ "less_equal",
315
+ "log",
316
+ "log1p",
317
+ "log2",
318
+ "log10",
319
+ "logaddexp",
320
+ "logical_and",
321
+ "logical_not",
322
+ "logical_or",
323
+ "logical_xor",
324
+ "multiply",
325
+ "negative",
326
+ "not_equal",
327
+ "positive",
328
+ "pow",
329
+ "remainder",
330
+ "round",
331
+ "sign",
332
+ "sin",
333
+ "sinh",
334
+ "square",
335
+ "sqrt",
336
+ "subtract",
337
+ "tan",
338
+ "tanh",
339
+ "trunc",
340
+ ]
341
+
342
+ from ._indexing_functions import take
343
+
344
+ __all__ += ["take"]
345
+
346
+ # linalg is an extension in the array API spec, which is a sub-namespace. Only
347
+ # a subset of functions in it are imported into the top-level namespace.
348
+ from . import linalg
349
+
350
+ __all__ += ["linalg"]
351
+
352
+ from .linalg import matmul, tensordot, matrix_transpose, vecdot
353
+
354
+ __all__ += ["matmul", "tensordot", "matrix_transpose", "vecdot"]
355
+
356
+ from ._manipulation_functions import (
357
+ concat,
358
+ expand_dims,
359
+ flip,
360
+ permute_dims,
361
+ reshape,
362
+ roll,
363
+ squeeze,
364
+ stack,
365
+ )
366
+
367
+ __all__ += ["concat", "expand_dims", "flip", "permute_dims", "reshape", "roll", "squeeze", "stack"]
368
+
369
+ from ._searching_functions import argmax, argmin, nonzero, where
370
+
371
+ __all__ += ["argmax", "argmin", "nonzero", "where"]
372
+
373
+ from ._set_functions import unique_all, unique_counts, unique_inverse, unique_values
374
+
375
+ __all__ += ["unique_all", "unique_counts", "unique_inverse", "unique_values"]
376
+
377
+ from ._sorting_functions import argsort, sort
378
+
379
+ __all__ += ["argsort", "sort"]
380
+
381
+ from ._statistical_functions import max, mean, min, prod, std, sum, var
382
+
383
+ __all__ += ["max", "mean", "min", "prod", "std", "sum", "var"]
384
+
385
+ from ._utility_functions import all, any
386
+
387
+ __all__ += ["all", "any"]
lib/python3.12/site-packages/numpy/array_api/__pycache__/_data_type_functions.cpython-312.pyc ADDED
Binary file (7.82 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/__pycache__/_elementwise_functions.cpython-312.pyc ADDED
Binary file (35.8 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/__pycache__/_indexing_functions.cpython-312.pyc ADDED
Binary file (1.28 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/__pycache__/_manipulation_functions.cpython-312.pyc ADDED
Binary file (5.04 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/__pycache__/_searching_functions.cpython-312.pyc ADDED
Binary file (3.01 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/__pycache__/linalg.cpython-312.pyc ADDED
Binary file (21.1 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/_array_object.py ADDED
@@ -0,0 +1,1133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Wrapper class around the ndarray object for the array API standard.
3
+
4
+ The array API standard defines some behaviors differently than ndarray, in
5
+ particular, type promotion rules are different (the standard has no
6
+ value-based casting). The standard also specifies a more limited subset of
7
+ array methods and functionalities than are implemented on ndarray. Since the
8
+ goal of the array_api namespace is to be a minimal implementation of the array
9
+ API standard, we need to define a separate wrapper class for the array_api
10
+ namespace.
11
+
12
+ The standard compliant class is only a wrapper class. It is *not* a subclass
13
+ of ndarray.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import operator
19
+ from enum import IntEnum
20
+ from ._creation_functions import asarray
21
+ from ._dtypes import (
22
+ _all_dtypes,
23
+ _boolean_dtypes,
24
+ _integer_dtypes,
25
+ _integer_or_boolean_dtypes,
26
+ _floating_dtypes,
27
+ _complex_floating_dtypes,
28
+ _numeric_dtypes,
29
+ _result_type,
30
+ _dtype_categories,
31
+ )
32
+
33
+ from typing import TYPE_CHECKING, Optional, Tuple, Union, Any, SupportsIndex
34
+ import types
35
+
36
+ if TYPE_CHECKING:
37
+ from ._typing import Any, PyCapsule, Device, Dtype
38
+ import numpy.typing as npt
39
+
40
+ import numpy as np
41
+
42
+ from numpy import array_api
43
+
44
+
45
+ class Array:
46
+ """
47
+ n-d array object for the array API namespace.
48
+
49
+ See the docstring of :py:obj:`np.ndarray <numpy.ndarray>` for more
50
+ information.
51
+
52
+ This is a wrapper around numpy.ndarray that restricts the usage to only
53
+ those things that are required by the array API namespace. Note,
54
+ attributes on this object that start with a single underscore are not part
55
+ of the API specification and should only be used internally. This object
56
+ should not be constructed directly. Rather, use one of the creation
57
+ functions, such as asarray().
58
+
59
+ """
60
+ _array: np.ndarray[Any, Any]
61
+
62
+ # Use a custom constructor instead of __init__, as manually initializing
63
+ # this class is not supported API.
64
+ @classmethod
65
+ def _new(cls, x, /):
66
+ """
67
+ This is a private method for initializing the array API Array
68
+ object.
69
+
70
+ Functions outside of the array_api submodule should not use this
71
+ method. Use one of the creation functions instead, such as
72
+ ``asarray``.
73
+
74
+ """
75
+ obj = super().__new__(cls)
76
+ # Note: The spec does not have array scalars, only 0-D arrays.
77
+ if isinstance(x, np.generic):
78
+ # Convert the array scalar to a 0-D array
79
+ x = np.asarray(x)
80
+ if x.dtype not in _all_dtypes:
81
+ raise TypeError(
82
+ f"The array_api namespace does not support the dtype '{x.dtype}'"
83
+ )
84
+ obj._array = x
85
+ return obj
86
+
87
+ # Prevent Array() from working
88
+ def __new__(cls, *args, **kwargs):
89
+ raise TypeError(
90
+ "The array_api Array object should not be instantiated directly. Use an array creation function, such as asarray(), instead."
91
+ )
92
+
93
+ # These functions are not required by the spec, but are implemented for
94
+ # the sake of usability.
95
+
96
+ def __str__(self: Array, /) -> str:
97
+ """
98
+ Performs the operation __str__.
99
+ """
100
+ return self._array.__str__().replace("array", "Array")
101
+
102
+ def __repr__(self: Array, /) -> str:
103
+ """
104
+ Performs the operation __repr__.
105
+ """
106
+ suffix = f", dtype={self.dtype.name})"
107
+ if 0 in self.shape:
108
+ prefix = "empty("
109
+ mid = str(self.shape)
110
+ else:
111
+ prefix = "Array("
112
+ mid = np.array2string(self._array, separator=', ', prefix=prefix, suffix=suffix)
113
+ return prefix + mid + suffix
114
+
115
+ # This function is not required by the spec, but we implement it here for
116
+ # convenience so that np.asarray(np.array_api.Array) will work.
117
+ def __array__(self, dtype: None | np.dtype[Any] = None) -> npt.NDArray[Any]:
118
+ """
119
+ Warning: this method is NOT part of the array API spec. Implementers
120
+ of other libraries need not include it, and users should not assume it
121
+ will be present in other implementations.
122
+
123
+ """
124
+ return np.asarray(self._array, dtype=dtype)
125
+
126
+ # These are various helper functions to make the array behavior match the
127
+ # spec in places where it either deviates from or is more strict than
128
+ # NumPy behavior
129
+
130
+ def _check_allowed_dtypes(self, other: bool | int | float | Array, dtype_category: str, op: str) -> Array:
131
+ """
132
+ Helper function for operators to only allow specific input dtypes
133
+
134
+ Use like
135
+
136
+ other = self._check_allowed_dtypes(other, 'numeric', '__add__')
137
+ if other is NotImplemented:
138
+ return other
139
+ """
140
+
141
+ if self.dtype not in _dtype_categories[dtype_category]:
142
+ raise TypeError(f"Only {dtype_category} dtypes are allowed in {op}")
143
+ if isinstance(other, (int, complex, float, bool)):
144
+ other = self._promote_scalar(other)
145
+ elif isinstance(other, Array):
146
+ if other.dtype not in _dtype_categories[dtype_category]:
147
+ raise TypeError(f"Only {dtype_category} dtypes are allowed in {op}")
148
+ else:
149
+ return NotImplemented
150
+
151
+ # This will raise TypeError for type combinations that are not allowed
152
+ # to promote in the spec (even if the NumPy array operator would
153
+ # promote them).
154
+ res_dtype = _result_type(self.dtype, other.dtype)
155
+ if op.startswith("__i"):
156
+ # Note: NumPy will allow in-place operators in some cases where
157
+ # the type promoted operator does not match the left-hand side
158
+ # operand. For example,
159
+
160
+ # >>> a = np.array(1, dtype=np.int8)
161
+ # >>> a += np.array(1, dtype=np.int16)
162
+
163
+ # The spec explicitly disallows this.
164
+ if res_dtype != self.dtype:
165
+ raise TypeError(
166
+ f"Cannot perform {op} with dtypes {self.dtype} and {other.dtype}"
167
+ )
168
+
169
+ return other
170
+
171
+ # Helper function to match the type promotion rules in the spec
172
+ def _promote_scalar(self, scalar):
173
+ """
174
+ Returns a promoted version of a Python scalar appropriate for use with
175
+ operations on self.
176
+
177
+ This may raise an OverflowError in cases where the scalar is an
178
+ integer that is too large to fit in a NumPy integer dtype, or
179
+ TypeError when the scalar type is incompatible with the dtype of self.
180
+ """
181
+ # Note: Only Python scalar types that match the array dtype are
182
+ # allowed.
183
+ if isinstance(scalar, bool):
184
+ if self.dtype not in _boolean_dtypes:
185
+ raise TypeError(
186
+ "Python bool scalars can only be promoted with bool arrays"
187
+ )
188
+ elif isinstance(scalar, int):
189
+ if self.dtype in _boolean_dtypes:
190
+ raise TypeError(
191
+ "Python int scalars cannot be promoted with bool arrays"
192
+ )
193
+ if self.dtype in _integer_dtypes:
194
+ info = np.iinfo(self.dtype)
195
+ if not (info.min <= scalar <= info.max):
196
+ raise OverflowError(
197
+ "Python int scalars must be within the bounds of the dtype for integer arrays"
198
+ )
199
+ # int + array(floating) is allowed
200
+ elif isinstance(scalar, float):
201
+ if self.dtype not in _floating_dtypes:
202
+ raise TypeError(
203
+ "Python float scalars can only be promoted with floating-point arrays."
204
+ )
205
+ elif isinstance(scalar, complex):
206
+ if self.dtype not in _complex_floating_dtypes:
207
+ raise TypeError(
208
+ "Python complex scalars can only be promoted with complex floating-point arrays."
209
+ )
210
+ else:
211
+ raise TypeError("'scalar' must be a Python scalar")
212
+
213
+ # Note: scalars are unconditionally cast to the same dtype as the
214
+ # array.
215
+
216
+ # Note: the spec only specifies integer-dtype/int promotion
217
+ # behavior for integers within the bounds of the integer dtype.
218
+ # Outside of those bounds we use the default NumPy behavior (either
219
+ # cast or raise OverflowError).
220
+ return Array._new(np.array(scalar, self.dtype))
221
+
222
+ @staticmethod
223
+ def _normalize_two_args(x1, x2) -> Tuple[Array, Array]:
224
+ """
225
+ Normalize inputs to two arg functions to fix type promotion rules
226
+
227
+ NumPy deviates from the spec type promotion rules in cases where one
228
+ argument is 0-dimensional and the other is not. For example:
229
+
230
+ >>> import numpy as np
231
+ >>> a = np.array([1.0], dtype=np.float32)
232
+ >>> b = np.array(1.0, dtype=np.float64)
233
+ >>> np.add(a, b) # The spec says this should be float64
234
+ array([2.], dtype=float32)
235
+
236
+ To fix this, we add a dimension to the 0-dimension array before passing it
237
+ through. This works because a dimension would be added anyway from
238
+ broadcasting, so the resulting shape is the same, but this prevents NumPy
239
+ from not promoting the dtype.
240
+ """
241
+ # Another option would be to use signature=(x1.dtype, x2.dtype, None),
242
+ # but that only works for ufuncs, so we would have to call the ufuncs
243
+ # directly in the operator methods. One should also note that this
244
+ # sort of trick wouldn't work for functions like searchsorted, which
245
+ # don't do normal broadcasting, but there aren't any functions like
246
+ # that in the array API namespace.
247
+ if x1.ndim == 0 and x2.ndim != 0:
248
+ # The _array[None] workaround was chosen because it is relatively
249
+ # performant. broadcast_to(x1._array, x2.shape) is much slower. We
250
+ # could also manually type promote x2, but that is more complicated
251
+ # and about the same performance as this.
252
+ x1 = Array._new(x1._array[None])
253
+ elif x2.ndim == 0 and x1.ndim != 0:
254
+ x2 = Array._new(x2._array[None])
255
+ return (x1, x2)
256
+
257
+ # Note: A large fraction of allowed indices are disallowed here (see the
258
+ # docstring below)
259
+ def _validate_index(self, key):
260
+ """
261
+ Validate an index according to the array API.
262
+
263
+ The array API specification only requires a subset of indices that are
264
+ supported by NumPy. This function will reject any index that is
265
+ allowed by NumPy but not required by the array API specification. We
266
+ always raise ``IndexError`` on such indices (the spec does not require
267
+ any specific behavior on them, but this makes the NumPy array API
268
+ namespace a minimal implementation of the spec). See
269
+ https://data-apis.org/array-api/latest/API_specification/indexing.html
270
+ for the full list of required indexing behavior
271
+
272
+ This function raises IndexError if the index ``key`` is invalid. It
273
+ only raises ``IndexError`` on indices that are not already rejected by
274
+ NumPy, as NumPy will already raise the appropriate error on such
275
+ indices. ``shape`` may be None, in which case, only cases that are
276
+ independent of the array shape are checked.
277
+
278
+ The following cases are allowed by NumPy, but not specified by the array
279
+ API specification:
280
+
281
+ - Indices to not include an implicit ellipsis at the end. That is,
282
+ every axis of an array must be explicitly indexed or an ellipsis
283
+ included. This behaviour is sometimes referred to as flat indexing.
284
+
285
+ - The start and stop of a slice may not be out of bounds. In
286
+ particular, for a slice ``i:j:k`` on an axis of size ``n``, only the
287
+ following are allowed:
288
+
289
+ - ``i`` or ``j`` omitted (``None``).
290
+ - ``-n <= i <= max(0, n - 1)``.
291
+ - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``.
292
+ - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``.
293
+
294
+ - Boolean array indices are not allowed as part of a larger tuple
295
+ index.
296
+
297
+ - Integer array indices are not allowed (with the exception of 0-D
298
+ arrays, which are treated the same as scalars).
299
+
300
+ Additionally, it should be noted that indices that would return a
301
+ scalar in NumPy will return a 0-D array. Array scalars are not allowed
302
+ in the specification, only 0-D arrays. This is done in the
303
+ ``Array._new`` constructor, not this function.
304
+
305
+ """
306
+ _key = key if isinstance(key, tuple) else (key,)
307
+ for i in _key:
308
+ if isinstance(i, bool) or not (
309
+ isinstance(i, SupportsIndex) # i.e. ints
310
+ or isinstance(i, slice)
311
+ or i == Ellipsis
312
+ or i is None
313
+ or isinstance(i, Array)
314
+ or isinstance(i, np.ndarray)
315
+ ):
316
+ raise IndexError(
317
+ f"Single-axes index {i} has {type(i)=}, but only "
318
+ "integers, slices (:), ellipsis (...), newaxis (None), "
319
+ "zero-dimensional integer arrays and boolean arrays "
320
+ "are specified in the Array API."
321
+ )
322
+
323
+ nonexpanding_key = []
324
+ single_axes = []
325
+ n_ellipsis = 0
326
+ key_has_mask = False
327
+ for i in _key:
328
+ if i is not None:
329
+ nonexpanding_key.append(i)
330
+ if isinstance(i, Array) or isinstance(i, np.ndarray):
331
+ if i.dtype in _boolean_dtypes:
332
+ key_has_mask = True
333
+ single_axes.append(i)
334
+ else:
335
+ # i must not be an array here, to avoid elementwise equals
336
+ if i == Ellipsis:
337
+ n_ellipsis += 1
338
+ else:
339
+ single_axes.append(i)
340
+
341
+ n_single_axes = len(single_axes)
342
+ if n_ellipsis > 1:
343
+ return # handled by ndarray
344
+ elif n_ellipsis == 0:
345
+ # Note boolean masks must be the sole index, which we check for
346
+ # later on.
347
+ if not key_has_mask and n_single_axes < self.ndim:
348
+ raise IndexError(
349
+ f"{self.ndim=}, but the multi-axes index only specifies "
350
+ f"{n_single_axes} dimensions. If this was intentional, "
351
+ "add a trailing ellipsis (...) which expands into as many "
352
+ "slices (:) as necessary - this is what np.ndarray arrays "
353
+ "implicitly do, but such flat indexing behaviour is not "
354
+ "specified in the Array API."
355
+ )
356
+
357
+ if n_ellipsis == 0:
358
+ indexed_shape = self.shape
359
+ else:
360
+ ellipsis_start = None
361
+ for pos, i in enumerate(nonexpanding_key):
362
+ if not (isinstance(i, Array) or isinstance(i, np.ndarray)):
363
+ if i == Ellipsis:
364
+ ellipsis_start = pos
365
+ break
366
+ assert ellipsis_start is not None # sanity check
367
+ ellipsis_end = self.ndim - (n_single_axes - ellipsis_start)
368
+ indexed_shape = (
369
+ self.shape[:ellipsis_start] + self.shape[ellipsis_end:]
370
+ )
371
+ for i, side in zip(single_axes, indexed_shape):
372
+ if isinstance(i, slice):
373
+ if side == 0:
374
+ f_range = "0 (or None)"
375
+ else:
376
+ f_range = f"between -{side} and {side - 1} (or None)"
377
+ if i.start is not None:
378
+ try:
379
+ start = operator.index(i.start)
380
+ except TypeError:
381
+ pass # handled by ndarray
382
+ else:
383
+ if not (-side <= start <= side):
384
+ raise IndexError(
385
+ f"Slice {i} contains {start=}, but should be "
386
+ f"{f_range} for an axis of size {side} "
387
+ "(out-of-bounds starts are not specified in "
388
+ "the Array API)"
389
+ )
390
+ if i.stop is not None:
391
+ try:
392
+ stop = operator.index(i.stop)
393
+ except TypeError:
394
+ pass # handled by ndarray
395
+ else:
396
+ if not (-side <= stop <= side):
397
+ raise IndexError(
398
+ f"Slice {i} contains {stop=}, but should be "
399
+ f"{f_range} for an axis of size {side} "
400
+ "(out-of-bounds stops are not specified in "
401
+ "the Array API)"
402
+ )
403
+ elif isinstance(i, Array):
404
+ if i.dtype in _boolean_dtypes and len(_key) != 1:
405
+ assert isinstance(key, tuple) # sanity check
406
+ raise IndexError(
407
+ f"Single-axes index {i} is a boolean array and "
408
+ f"{len(key)=}, but masking is only specified in the "
409
+ "Array API when the array is the sole index."
410
+ )
411
+ elif i.dtype in _integer_dtypes and i.ndim != 0:
412
+ raise IndexError(
413
+ f"Single-axes index {i} is a non-zero-dimensional "
414
+ "integer array, but advanced integer indexing is not "
415
+ "specified in the Array API."
416
+ )
417
+ elif isinstance(i, tuple):
418
+ raise IndexError(
419
+ f"Single-axes index {i} is a tuple, but nested tuple "
420
+ "indices are not specified in the Array API."
421
+ )
422
+
423
+ # Everything below this line is required by the spec.
424
+
425
+ def __abs__(self: Array, /) -> Array:
426
+ """
427
+ Performs the operation __abs__.
428
+ """
429
+ if self.dtype not in _numeric_dtypes:
430
+ raise TypeError("Only numeric dtypes are allowed in __abs__")
431
+ res = self._array.__abs__()
432
+ return self.__class__._new(res)
433
+
434
+ def __add__(self: Array, other: Union[int, float, Array], /) -> Array:
435
+ """
436
+ Performs the operation __add__.
437
+ """
438
+ other = self._check_allowed_dtypes(other, "numeric", "__add__")
439
+ if other is NotImplemented:
440
+ return other
441
+ self, other = self._normalize_two_args(self, other)
442
+ res = self._array.__add__(other._array)
443
+ return self.__class__._new(res)
444
+
445
+ def __and__(self: Array, other: Union[int, bool, Array], /) -> Array:
446
+ """
447
+ Performs the operation __and__.
448
+ """
449
+ other = self._check_allowed_dtypes(other, "integer or boolean", "__and__")
450
+ if other is NotImplemented:
451
+ return other
452
+ self, other = self._normalize_two_args(self, other)
453
+ res = self._array.__and__(other._array)
454
+ return self.__class__._new(res)
455
+
456
+ def __array_namespace__(
457
+ self: Array, /, *, api_version: Optional[str] = None
458
+ ) -> types.ModuleType:
459
+ if api_version is not None and not api_version.startswith("2021."):
460
+ raise ValueError(f"Unrecognized array API version: {api_version!r}")
461
+ return array_api
462
+
463
+ def __bool__(self: Array, /) -> bool:
464
+ """
465
+ Performs the operation __bool__.
466
+ """
467
+ # Note: This is an error here.
468
+ if self._array.ndim != 0:
469
+ raise TypeError("bool is only allowed on arrays with 0 dimensions")
470
+ res = self._array.__bool__()
471
+ return res
472
+
473
+ def __complex__(self: Array, /) -> complex:
474
+ """
475
+ Performs the operation __complex__.
476
+ """
477
+ # Note: This is an error here.
478
+ if self._array.ndim != 0:
479
+ raise TypeError("complex is only allowed on arrays with 0 dimensions")
480
+ res = self._array.__complex__()
481
+ return res
482
+
483
+ def __dlpack__(self: Array, /, *, stream: None = None) -> PyCapsule:
484
+ """
485
+ Performs the operation __dlpack__.
486
+ """
487
+ return self._array.__dlpack__(stream=stream)
488
+
489
+ def __dlpack_device__(self: Array, /) -> Tuple[IntEnum, int]:
490
+ """
491
+ Performs the operation __dlpack_device__.
492
+ """
493
+ # Note: device support is required for this
494
+ return self._array.__dlpack_device__()
495
+
496
+ def __eq__(self: Array, other: Union[int, float, bool, Array], /) -> Array:
497
+ """
498
+ Performs the operation __eq__.
499
+ """
500
+ # Even though "all" dtypes are allowed, we still require them to be
501
+ # promotable with each other.
502
+ other = self._check_allowed_dtypes(other, "all", "__eq__")
503
+ if other is NotImplemented:
504
+ return other
505
+ self, other = self._normalize_two_args(self, other)
506
+ res = self._array.__eq__(other._array)
507
+ return self.__class__._new(res)
508
+
509
+ def __float__(self: Array, /) -> float:
510
+ """
511
+ Performs the operation __float__.
512
+ """
513
+ # Note: This is an error here.
514
+ if self._array.ndim != 0:
515
+ raise TypeError("float is only allowed on arrays with 0 dimensions")
516
+ if self.dtype in _complex_floating_dtypes:
517
+ raise TypeError("float is not allowed on complex floating-point arrays")
518
+ res = self._array.__float__()
519
+ return res
520
+
521
+ def __floordiv__(self: Array, other: Union[int, float, Array], /) -> Array:
522
+ """
523
+ Performs the operation __floordiv__.
524
+ """
525
+ other = self._check_allowed_dtypes(other, "real numeric", "__floordiv__")
526
+ if other is NotImplemented:
527
+ return other
528
+ self, other = self._normalize_two_args(self, other)
529
+ res = self._array.__floordiv__(other._array)
530
+ return self.__class__._new(res)
531
+
532
+ def __ge__(self: Array, other: Union[int, float, Array], /) -> Array:
533
+ """
534
+ Performs the operation __ge__.
535
+ """
536
+ other = self._check_allowed_dtypes(other, "real numeric", "__ge__")
537
+ if other is NotImplemented:
538
+ return other
539
+ self, other = self._normalize_two_args(self, other)
540
+ res = self._array.__ge__(other._array)
541
+ return self.__class__._new(res)
542
+
543
+ def __getitem__(
544
+ self: Array,
545
+ key: Union[
546
+ int,
547
+ slice,
548
+ ellipsis,
549
+ Tuple[Union[int, slice, ellipsis, None], ...],
550
+ Array,
551
+ ],
552
+ /,
553
+ ) -> Array:
554
+ """
555
+ Performs the operation __getitem__.
556
+ """
557
+ # Note: Only indices required by the spec are allowed. See the
558
+ # docstring of _validate_index
559
+ self._validate_index(key)
560
+ if isinstance(key, Array):
561
+ # Indexing self._array with array_api arrays can be erroneous
562
+ key = key._array
563
+ res = self._array.__getitem__(key)
564
+ return self._new(res)
565
+
566
+ def __gt__(self: Array, other: Union[int, float, Array], /) -> Array:
567
+ """
568
+ Performs the operation __gt__.
569
+ """
570
+ other = self._check_allowed_dtypes(other, "real numeric", "__gt__")
571
+ if other is NotImplemented:
572
+ return other
573
+ self, other = self._normalize_two_args(self, other)
574
+ res = self._array.__gt__(other._array)
575
+ return self.__class__._new(res)
576
+
577
+ def __int__(self: Array, /) -> int:
578
+ """
579
+ Performs the operation __int__.
580
+ """
581
+ # Note: This is an error here.
582
+ if self._array.ndim != 0:
583
+ raise TypeError("int is only allowed on arrays with 0 dimensions")
584
+ if self.dtype in _complex_floating_dtypes:
585
+ raise TypeError("int is not allowed on complex floating-point arrays")
586
+ res = self._array.__int__()
587
+ return res
588
+
589
+ def __index__(self: Array, /) -> int:
590
+ """
591
+ Performs the operation __index__.
592
+ """
593
+ res = self._array.__index__()
594
+ return res
595
+
596
+ def __invert__(self: Array, /) -> Array:
597
+ """
598
+ Performs the operation __invert__.
599
+ """
600
+ if self.dtype not in _integer_or_boolean_dtypes:
601
+ raise TypeError("Only integer or boolean dtypes are allowed in __invert__")
602
+ res = self._array.__invert__()
603
+ return self.__class__._new(res)
604
+
605
+ def __le__(self: Array, other: Union[int, float, Array], /) -> Array:
606
+ """
607
+ Performs the operation __le__.
608
+ """
609
+ other = self._check_allowed_dtypes(other, "real numeric", "__le__")
610
+ if other is NotImplemented:
611
+ return other
612
+ self, other = self._normalize_two_args(self, other)
613
+ res = self._array.__le__(other._array)
614
+ return self.__class__._new(res)
615
+
616
+ def __lshift__(self: Array, other: Union[int, Array], /) -> Array:
617
+ """
618
+ Performs the operation __lshift__.
619
+ """
620
+ other = self._check_allowed_dtypes(other, "integer", "__lshift__")
621
+ if other is NotImplemented:
622
+ return other
623
+ self, other = self._normalize_two_args(self, other)
624
+ res = self._array.__lshift__(other._array)
625
+ return self.__class__._new(res)
626
+
627
+ def __lt__(self: Array, other: Union[int, float, Array], /) -> Array:
628
+ """
629
+ Performs the operation __lt__.
630
+ """
631
+ other = self._check_allowed_dtypes(other, "real numeric", "__lt__")
632
+ if other is NotImplemented:
633
+ return other
634
+ self, other = self._normalize_two_args(self, other)
635
+ res = self._array.__lt__(other._array)
636
+ return self.__class__._new(res)
637
+
638
+ def __matmul__(self: Array, other: Array, /) -> Array:
639
+ """
640
+ Performs the operation __matmul__.
641
+ """
642
+ # matmul is not defined for scalars, but without this, we may get
643
+ # the wrong error message from asarray.
644
+ other = self._check_allowed_dtypes(other, "numeric", "__matmul__")
645
+ if other is NotImplemented:
646
+ return other
647
+ res = self._array.__matmul__(other._array)
648
+ return self.__class__._new(res)
649
+
650
+ def __mod__(self: Array, other: Union[int, float, Array], /) -> Array:
651
+ """
652
+ Performs the operation __mod__.
653
+ """
654
+ other = self._check_allowed_dtypes(other, "real numeric", "__mod__")
655
+ if other is NotImplemented:
656
+ return other
657
+ self, other = self._normalize_two_args(self, other)
658
+ res = self._array.__mod__(other._array)
659
+ return self.__class__._new(res)
660
+
661
+ def __mul__(self: Array, other: Union[int, float, Array], /) -> Array:
662
+ """
663
+ Performs the operation __mul__.
664
+ """
665
+ other = self._check_allowed_dtypes(other, "numeric", "__mul__")
666
+ if other is NotImplemented:
667
+ return other
668
+ self, other = self._normalize_two_args(self, other)
669
+ res = self._array.__mul__(other._array)
670
+ return self.__class__._new(res)
671
+
672
+ def __ne__(self: Array, other: Union[int, float, bool, Array], /) -> Array:
673
+ """
674
+ Performs the operation __ne__.
675
+ """
676
+ other = self._check_allowed_dtypes(other, "all", "__ne__")
677
+ if other is NotImplemented:
678
+ return other
679
+ self, other = self._normalize_two_args(self, other)
680
+ res = self._array.__ne__(other._array)
681
+ return self.__class__._new(res)
682
+
683
+ def __neg__(self: Array, /) -> Array:
684
+ """
685
+ Performs the operation __neg__.
686
+ """
687
+ if self.dtype not in _numeric_dtypes:
688
+ raise TypeError("Only numeric dtypes are allowed in __neg__")
689
+ res = self._array.__neg__()
690
+ return self.__class__._new(res)
691
+
692
+ def __or__(self: Array, other: Union[int, bool, Array], /) -> Array:
693
+ """
694
+ Performs the operation __or__.
695
+ """
696
+ other = self._check_allowed_dtypes(other, "integer or boolean", "__or__")
697
+ if other is NotImplemented:
698
+ return other
699
+ self, other = self._normalize_two_args(self, other)
700
+ res = self._array.__or__(other._array)
701
+ return self.__class__._new(res)
702
+
703
+ def __pos__(self: Array, /) -> Array:
704
+ """
705
+ Performs the operation __pos__.
706
+ """
707
+ if self.dtype not in _numeric_dtypes:
708
+ raise TypeError("Only numeric dtypes are allowed in __pos__")
709
+ res = self._array.__pos__()
710
+ return self.__class__._new(res)
711
+
712
+ def __pow__(self: Array, other: Union[int, float, Array], /) -> Array:
713
+ """
714
+ Performs the operation __pow__.
715
+ """
716
+ from ._elementwise_functions import pow
717
+
718
+ other = self._check_allowed_dtypes(other, "numeric", "__pow__")
719
+ if other is NotImplemented:
720
+ return other
721
+ # Note: NumPy's __pow__ does not follow type promotion rules for 0-d
722
+ # arrays, so we use pow() here instead.
723
+ return pow(self, other)
724
+
725
+ def __rshift__(self: Array, other: Union[int, Array], /) -> Array:
726
+ """
727
+ Performs the operation __rshift__.
728
+ """
729
+ other = self._check_allowed_dtypes(other, "integer", "__rshift__")
730
+ if other is NotImplemented:
731
+ return other
732
+ self, other = self._normalize_two_args(self, other)
733
+ res = self._array.__rshift__(other._array)
734
+ return self.__class__._new(res)
735
+
736
+ def __setitem__(
737
+ self,
738
+ key: Union[
739
+ int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], Array
740
+ ],
741
+ value: Union[int, float, bool, Array],
742
+ /,
743
+ ) -> None:
744
+ """
745
+ Performs the operation __setitem__.
746
+ """
747
+ # Note: Only indices required by the spec are allowed. See the
748
+ # docstring of _validate_index
749
+ self._validate_index(key)
750
+ if isinstance(key, Array):
751
+ # Indexing self._array with array_api arrays can be erroneous
752
+ key = key._array
753
+ self._array.__setitem__(key, asarray(value)._array)
754
+
755
+ def __sub__(self: Array, other: Union[int, float, Array], /) -> Array:
756
+ """
757
+ Performs the operation __sub__.
758
+ """
759
+ other = self._check_allowed_dtypes(other, "numeric", "__sub__")
760
+ if other is NotImplemented:
761
+ return other
762
+ self, other = self._normalize_two_args(self, other)
763
+ res = self._array.__sub__(other._array)
764
+ return self.__class__._new(res)
765
+
766
+ # PEP 484 requires int to be a subtype of float, but __truediv__ should
767
+ # not accept int.
768
+ def __truediv__(self: Array, other: Union[float, Array], /) -> Array:
769
+ """
770
+ Performs the operation __truediv__.
771
+ """
772
+ other = self._check_allowed_dtypes(other, "floating-point", "__truediv__")
773
+ if other is NotImplemented:
774
+ return other
775
+ self, other = self._normalize_two_args(self, other)
776
+ res = self._array.__truediv__(other._array)
777
+ return self.__class__._new(res)
778
+
779
+ def __xor__(self: Array, other: Union[int, bool, Array], /) -> Array:
780
+ """
781
+ Performs the operation __xor__.
782
+ """
783
+ other = self._check_allowed_dtypes(other, "integer or boolean", "__xor__")
784
+ if other is NotImplemented:
785
+ return other
786
+ self, other = self._normalize_two_args(self, other)
787
+ res = self._array.__xor__(other._array)
788
+ return self.__class__._new(res)
789
+
790
+ def __iadd__(self: Array, other: Union[int, float, Array], /) -> Array:
791
+ """
792
+ Performs the operation __iadd__.
793
+ """
794
+ other = self._check_allowed_dtypes(other, "numeric", "__iadd__")
795
+ if other is NotImplemented:
796
+ return other
797
+ self._array.__iadd__(other._array)
798
+ return self
799
+
800
+ def __radd__(self: Array, other: Union[int, float, Array], /) -> Array:
801
+ """
802
+ Performs the operation __radd__.
803
+ """
804
+ other = self._check_allowed_dtypes(other, "numeric", "__radd__")
805
+ if other is NotImplemented:
806
+ return other
807
+ self, other = self._normalize_two_args(self, other)
808
+ res = self._array.__radd__(other._array)
809
+ return self.__class__._new(res)
810
+
811
+ def __iand__(self: Array, other: Union[int, bool, Array], /) -> Array:
812
+ """
813
+ Performs the operation __iand__.
814
+ """
815
+ other = self._check_allowed_dtypes(other, "integer or boolean", "__iand__")
816
+ if other is NotImplemented:
817
+ return other
818
+ self._array.__iand__(other._array)
819
+ return self
820
+
821
+ def __rand__(self: Array, other: Union[int, bool, Array], /) -> Array:
822
+ """
823
+ Performs the operation __rand__.
824
+ """
825
+ other = self._check_allowed_dtypes(other, "integer or boolean", "__rand__")
826
+ if other is NotImplemented:
827
+ return other
828
+ self, other = self._normalize_two_args(self, other)
829
+ res = self._array.__rand__(other._array)
830
+ return self.__class__._new(res)
831
+
832
+ def __ifloordiv__(self: Array, other: Union[int, float, Array], /) -> Array:
833
+ """
834
+ Performs the operation __ifloordiv__.
835
+ """
836
+ other = self._check_allowed_dtypes(other, "real numeric", "__ifloordiv__")
837
+ if other is NotImplemented:
838
+ return other
839
+ self._array.__ifloordiv__(other._array)
840
+ return self
841
+
842
+ def __rfloordiv__(self: Array, other: Union[int, float, Array], /) -> Array:
843
+ """
844
+ Performs the operation __rfloordiv__.
845
+ """
846
+ other = self._check_allowed_dtypes(other, "real numeric", "__rfloordiv__")
847
+ if other is NotImplemented:
848
+ return other
849
+ self, other = self._normalize_two_args(self, other)
850
+ res = self._array.__rfloordiv__(other._array)
851
+ return self.__class__._new(res)
852
+
853
+ def __ilshift__(self: Array, other: Union[int, Array], /) -> Array:
854
+ """
855
+ Performs the operation __ilshift__.
856
+ """
857
+ other = self._check_allowed_dtypes(other, "integer", "__ilshift__")
858
+ if other is NotImplemented:
859
+ return other
860
+ self._array.__ilshift__(other._array)
861
+ return self
862
+
863
+ def __rlshift__(self: Array, other: Union[int, Array], /) -> Array:
864
+ """
865
+ Performs the operation __rlshift__.
866
+ """
867
+ other = self._check_allowed_dtypes(other, "integer", "__rlshift__")
868
+ if other is NotImplemented:
869
+ return other
870
+ self, other = self._normalize_two_args(self, other)
871
+ res = self._array.__rlshift__(other._array)
872
+ return self.__class__._new(res)
873
+
874
+ def __imatmul__(self: Array, other: Array, /) -> Array:
875
+ """
876
+ Performs the operation __imatmul__.
877
+ """
878
+ # matmul is not defined for scalars, but without this, we may get
879
+ # the wrong error message from asarray.
880
+ other = self._check_allowed_dtypes(other, "numeric", "__imatmul__")
881
+ if other is NotImplemented:
882
+ return other
883
+ res = self._array.__imatmul__(other._array)
884
+ return self.__class__._new(res)
885
+
886
+ def __rmatmul__(self: Array, other: Array, /) -> Array:
887
+ """
888
+ Performs the operation __rmatmul__.
889
+ """
890
+ # matmul is not defined for scalars, but without this, we may get
891
+ # the wrong error message from asarray.
892
+ other = self._check_allowed_dtypes(other, "numeric", "__rmatmul__")
893
+ if other is NotImplemented:
894
+ return other
895
+ res = self._array.__rmatmul__(other._array)
896
+ return self.__class__._new(res)
897
+
898
+ def __imod__(self: Array, other: Union[int, float, Array], /) -> Array:
899
+ """
900
+ Performs the operation __imod__.
901
+ """
902
+ other = self._check_allowed_dtypes(other, "real numeric", "__imod__")
903
+ if other is NotImplemented:
904
+ return other
905
+ self._array.__imod__(other._array)
906
+ return self
907
+
908
+ def __rmod__(self: Array, other: Union[int, float, Array], /) -> Array:
909
+ """
910
+ Performs the operation __rmod__.
911
+ """
912
+ other = self._check_allowed_dtypes(other, "real numeric", "__rmod__")
913
+ if other is NotImplemented:
914
+ return other
915
+ self, other = self._normalize_two_args(self, other)
916
+ res = self._array.__rmod__(other._array)
917
+ return self.__class__._new(res)
918
+
919
+ def __imul__(self: Array, other: Union[int, float, Array], /) -> Array:
920
+ """
921
+ Performs the operation __imul__.
922
+ """
923
+ other = self._check_allowed_dtypes(other, "numeric", "__imul__")
924
+ if other is NotImplemented:
925
+ return other
926
+ self._array.__imul__(other._array)
927
+ return self
928
+
929
+ def __rmul__(self: Array, other: Union[int, float, Array], /) -> Array:
930
+ """
931
+ Performs the operation __rmul__.
932
+ """
933
+ other = self._check_allowed_dtypes(other, "numeric", "__rmul__")
934
+ if other is NotImplemented:
935
+ return other
936
+ self, other = self._normalize_two_args(self, other)
937
+ res = self._array.__rmul__(other._array)
938
+ return self.__class__._new(res)
939
+
940
+ def __ior__(self: Array, other: Union[int, bool, Array], /) -> Array:
941
+ """
942
+ Performs the operation __ior__.
943
+ """
944
+ other = self._check_allowed_dtypes(other, "integer or boolean", "__ior__")
945
+ if other is NotImplemented:
946
+ return other
947
+ self._array.__ior__(other._array)
948
+ return self
949
+
950
+ def __ror__(self: Array, other: Union[int, bool, Array], /) -> Array:
951
+ """
952
+ Performs the operation __ror__.
953
+ """
954
+ other = self._check_allowed_dtypes(other, "integer or boolean", "__ror__")
955
+ if other is NotImplemented:
956
+ return other
957
+ self, other = self._normalize_two_args(self, other)
958
+ res = self._array.__ror__(other._array)
959
+ return self.__class__._new(res)
960
+
961
+ def __ipow__(self: Array, other: Union[int, float, Array], /) -> Array:
962
+ """
963
+ Performs the operation __ipow__.
964
+ """
965
+ other = self._check_allowed_dtypes(other, "numeric", "__ipow__")
966
+ if other is NotImplemented:
967
+ return other
968
+ self._array.__ipow__(other._array)
969
+ return self
970
+
971
+ def __rpow__(self: Array, other: Union[int, float, Array], /) -> Array:
972
+ """
973
+ Performs the operation __rpow__.
974
+ """
975
+ from ._elementwise_functions import pow
976
+
977
+ other = self._check_allowed_dtypes(other, "numeric", "__rpow__")
978
+ if other is NotImplemented:
979
+ return other
980
+ # Note: NumPy's __pow__ does not follow the spec type promotion rules
981
+ # for 0-d arrays, so we use pow() here instead.
982
+ return pow(other, self)
983
+
984
+ def __irshift__(self: Array, other: Union[int, Array], /) -> Array:
985
+ """
986
+ Performs the operation __irshift__.
987
+ """
988
+ other = self._check_allowed_dtypes(other, "integer", "__irshift__")
989
+ if other is NotImplemented:
990
+ return other
991
+ self._array.__irshift__(other._array)
992
+ return self
993
+
994
+ def __rrshift__(self: Array, other: Union[int, Array], /) -> Array:
995
+ """
996
+ Performs the operation __rrshift__.
997
+ """
998
+ other = self._check_allowed_dtypes(other, "integer", "__rrshift__")
999
+ if other is NotImplemented:
1000
+ return other
1001
+ self, other = self._normalize_two_args(self, other)
1002
+ res = self._array.__rrshift__(other._array)
1003
+ return self.__class__._new(res)
1004
+
1005
+ def __isub__(self: Array, other: Union[int, float, Array], /) -> Array:
1006
+ """
1007
+ Performs the operation __isub__.
1008
+ """
1009
+ other = self._check_allowed_dtypes(other, "numeric", "__isub__")
1010
+ if other is NotImplemented:
1011
+ return other
1012
+ self._array.__isub__(other._array)
1013
+ return self
1014
+
1015
+ def __rsub__(self: Array, other: Union[int, float, Array], /) -> Array:
1016
+ """
1017
+ Performs the operation __rsub__.
1018
+ """
1019
+ other = self._check_allowed_dtypes(other, "numeric", "__rsub__")
1020
+ if other is NotImplemented:
1021
+ return other
1022
+ self, other = self._normalize_two_args(self, other)
1023
+ res = self._array.__rsub__(other._array)
1024
+ return self.__class__._new(res)
1025
+
1026
+ def __itruediv__(self: Array, other: Union[float, Array], /) -> Array:
1027
+ """
1028
+ Performs the operation __itruediv__.
1029
+ """
1030
+ other = self._check_allowed_dtypes(other, "floating-point", "__itruediv__")
1031
+ if other is NotImplemented:
1032
+ return other
1033
+ self._array.__itruediv__(other._array)
1034
+ return self
1035
+
1036
+ def __rtruediv__(self: Array, other: Union[float, Array], /) -> Array:
1037
+ """
1038
+ Performs the operation __rtruediv__.
1039
+ """
1040
+ other = self._check_allowed_dtypes(other, "floating-point", "__rtruediv__")
1041
+ if other is NotImplemented:
1042
+ return other
1043
+ self, other = self._normalize_two_args(self, other)
1044
+ res = self._array.__rtruediv__(other._array)
1045
+ return self.__class__._new(res)
1046
+
1047
+ def __ixor__(self: Array, other: Union[int, bool, Array], /) -> Array:
1048
+ """
1049
+ Performs the operation __ixor__.
1050
+ """
1051
+ other = self._check_allowed_dtypes(other, "integer or boolean", "__ixor__")
1052
+ if other is NotImplemented:
1053
+ return other
1054
+ self._array.__ixor__(other._array)
1055
+ return self
1056
+
1057
+ def __rxor__(self: Array, other: Union[int, bool, Array], /) -> Array:
1058
+ """
1059
+ Performs the operation __rxor__.
1060
+ """
1061
+ other = self._check_allowed_dtypes(other, "integer or boolean", "__rxor__")
1062
+ if other is NotImplemented:
1063
+ return other
1064
+ self, other = self._normalize_two_args(self, other)
1065
+ res = self._array.__rxor__(other._array)
1066
+ return self.__class__._new(res)
1067
+
1068
+ def to_device(self: Array, device: Device, /, stream: None = None) -> Array:
1069
+ if stream is not None:
1070
+ raise ValueError("The stream argument to to_device() is not supported")
1071
+ if device == 'cpu':
1072
+ return self
1073
+ raise ValueError(f"Unsupported device {device!r}")
1074
+
1075
+ @property
1076
+ def dtype(self) -> Dtype:
1077
+ """
1078
+ Array API compatible wrapper for :py:meth:`np.ndarray.dtype <numpy.ndarray.dtype>`.
1079
+
1080
+ See its docstring for more information.
1081
+ """
1082
+ return self._array.dtype
1083
+
1084
+ @property
1085
+ def device(self) -> Device:
1086
+ return "cpu"
1087
+
1088
+ # Note: mT is new in array API spec (see matrix_transpose)
1089
+ @property
1090
+ def mT(self) -> Array:
1091
+ from .linalg import matrix_transpose
1092
+ return matrix_transpose(self)
1093
+
1094
+ @property
1095
+ def ndim(self) -> int:
1096
+ """
1097
+ Array API compatible wrapper for :py:meth:`np.ndarray.ndim <numpy.ndarray.ndim>`.
1098
+
1099
+ See its docstring for more information.
1100
+ """
1101
+ return self._array.ndim
1102
+
1103
+ @property
1104
+ def shape(self) -> Tuple[int, ...]:
1105
+ """
1106
+ Array API compatible wrapper for :py:meth:`np.ndarray.shape <numpy.ndarray.shape>`.
1107
+
1108
+ See its docstring for more information.
1109
+ """
1110
+ return self._array.shape
1111
+
1112
+ @property
1113
+ def size(self) -> int:
1114
+ """
1115
+ Array API compatible wrapper for :py:meth:`np.ndarray.size <numpy.ndarray.size>`.
1116
+
1117
+ See its docstring for more information.
1118
+ """
1119
+ return self._array.size
1120
+
1121
+ @property
1122
+ def T(self) -> Array:
1123
+ """
1124
+ Array API compatible wrapper for :py:meth:`np.ndarray.T <numpy.ndarray.T>`.
1125
+
1126
+ See its docstring for more information.
1127
+ """
1128
+ # Note: T only works on 2-dimensional arrays. See the corresponding
1129
+ # note in the specification:
1130
+ # https://data-apis.org/array-api/latest/API_specification/array_object.html#t
1131
+ if self.ndim != 2:
1132
+ raise ValueError("x.T requires x to have 2 dimensions. Use x.mT to transpose stacks of matrices and permute_dims() to permute dimensions.")
1133
+ return self.__class__._new(self._array.T)
lib/python3.12/site-packages/numpy/array_api/_constants.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ e = np.e
4
+ inf = np.inf
5
+ nan = np.nan
6
+ pi = np.pi
7
+ newaxis = np.newaxis
lib/python3.12/site-packages/numpy/array_api/_creation_functions.py ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+
4
+ from typing import TYPE_CHECKING, List, Optional, Tuple, Union
5
+
6
+ if TYPE_CHECKING:
7
+ from ._typing import (
8
+ Array,
9
+ Device,
10
+ Dtype,
11
+ NestedSequence,
12
+ SupportsBufferProtocol,
13
+ )
14
+ from collections.abc import Sequence
15
+ from ._dtypes import _all_dtypes
16
+
17
+ import numpy as np
18
+
19
+
20
+ def _check_valid_dtype(dtype):
21
+ # Note: Only spelling dtypes as the dtype objects is supported.
22
+
23
+ # We use this instead of "dtype in _all_dtypes" because the dtype objects
24
+ # define equality with the sorts of things we want to disallow.
25
+ for d in (None,) + _all_dtypes:
26
+ if dtype is d:
27
+ return
28
+ raise ValueError("dtype must be one of the supported dtypes")
29
+
30
+
31
+ def asarray(
32
+ obj: Union[
33
+ Array,
34
+ bool,
35
+ int,
36
+ float,
37
+ NestedSequence[bool | int | float],
38
+ SupportsBufferProtocol,
39
+ ],
40
+ /,
41
+ *,
42
+ dtype: Optional[Dtype] = None,
43
+ device: Optional[Device] = None,
44
+ copy: Optional[Union[bool, np._CopyMode]] = None,
45
+ ) -> Array:
46
+ """
47
+ Array API compatible wrapper for :py:func:`np.asarray <numpy.asarray>`.
48
+
49
+ See its docstring for more information.
50
+ """
51
+ # _array_object imports in this file are inside the functions to avoid
52
+ # circular imports
53
+ from ._array_object import Array
54
+
55
+ _check_valid_dtype(dtype)
56
+ if device not in ["cpu", None]:
57
+ raise ValueError(f"Unsupported device {device!r}")
58
+ if copy in (False, np._CopyMode.IF_NEEDED):
59
+ # Note: copy=False is not yet implemented in np.asarray
60
+ raise NotImplementedError("copy=False is not yet implemented")
61
+ if isinstance(obj, Array):
62
+ if dtype is not None and obj.dtype != dtype:
63
+ copy = True
64
+ if copy in (True, np._CopyMode.ALWAYS):
65
+ return Array._new(np.array(obj._array, copy=True, dtype=dtype))
66
+ return obj
67
+ if dtype is None and isinstance(obj, int) and (obj > 2 ** 64 or obj < -(2 ** 63)):
68
+ # Give a better error message in this case. NumPy would convert this
69
+ # to an object array. TODO: This won't handle large integers in lists.
70
+ raise OverflowError("Integer out of bounds for array dtypes")
71
+ res = np.asarray(obj, dtype=dtype)
72
+ return Array._new(res)
73
+
74
+
75
+ def arange(
76
+ start: Union[int, float],
77
+ /,
78
+ stop: Optional[Union[int, float]] = None,
79
+ step: Union[int, float] = 1,
80
+ *,
81
+ dtype: Optional[Dtype] = None,
82
+ device: Optional[Device] = None,
83
+ ) -> Array:
84
+ """
85
+ Array API compatible wrapper for :py:func:`np.arange <numpy.arange>`.
86
+
87
+ See its docstring for more information.
88
+ """
89
+ from ._array_object import Array
90
+
91
+ _check_valid_dtype(dtype)
92
+ if device not in ["cpu", None]:
93
+ raise ValueError(f"Unsupported device {device!r}")
94
+ return Array._new(np.arange(start, stop=stop, step=step, dtype=dtype))
95
+
96
+
97
+ def empty(
98
+ shape: Union[int, Tuple[int, ...]],
99
+ *,
100
+ dtype: Optional[Dtype] = None,
101
+ device: Optional[Device] = None,
102
+ ) -> Array:
103
+ """
104
+ Array API compatible wrapper for :py:func:`np.empty <numpy.empty>`.
105
+
106
+ See its docstring for more information.
107
+ """
108
+ from ._array_object import Array
109
+
110
+ _check_valid_dtype(dtype)
111
+ if device not in ["cpu", None]:
112
+ raise ValueError(f"Unsupported device {device!r}")
113
+ return Array._new(np.empty(shape, dtype=dtype))
114
+
115
+
116
+ def empty_like(
117
+ x: Array, /, *, dtype: Optional[Dtype] = None, device: Optional[Device] = None
118
+ ) -> Array:
119
+ """
120
+ Array API compatible wrapper for :py:func:`np.empty_like <numpy.empty_like>`.
121
+
122
+ See its docstring for more information.
123
+ """
124
+ from ._array_object import Array
125
+
126
+ _check_valid_dtype(dtype)
127
+ if device not in ["cpu", None]:
128
+ raise ValueError(f"Unsupported device {device!r}")
129
+ return Array._new(np.empty_like(x._array, dtype=dtype))
130
+
131
+
132
+ def eye(
133
+ n_rows: int,
134
+ n_cols: Optional[int] = None,
135
+ /,
136
+ *,
137
+ k: int = 0,
138
+ dtype: Optional[Dtype] = None,
139
+ device: Optional[Device] = None,
140
+ ) -> Array:
141
+ """
142
+ Array API compatible wrapper for :py:func:`np.eye <numpy.eye>`.
143
+
144
+ See its docstring for more information.
145
+ """
146
+ from ._array_object import Array
147
+
148
+ _check_valid_dtype(dtype)
149
+ if device not in ["cpu", None]:
150
+ raise ValueError(f"Unsupported device {device!r}")
151
+ return Array._new(np.eye(n_rows, M=n_cols, k=k, dtype=dtype))
152
+
153
+
154
+ def from_dlpack(x: object, /) -> Array:
155
+ from ._array_object import Array
156
+
157
+ return Array._new(np.from_dlpack(x))
158
+
159
+
160
+ def full(
161
+ shape: Union[int, Tuple[int, ...]],
162
+ fill_value: Union[int, float],
163
+ *,
164
+ dtype: Optional[Dtype] = None,
165
+ device: Optional[Device] = None,
166
+ ) -> Array:
167
+ """
168
+ Array API compatible wrapper for :py:func:`np.full <numpy.full>`.
169
+
170
+ See its docstring for more information.
171
+ """
172
+ from ._array_object import Array
173
+
174
+ _check_valid_dtype(dtype)
175
+ if device not in ["cpu", None]:
176
+ raise ValueError(f"Unsupported device {device!r}")
177
+ if isinstance(fill_value, Array) and fill_value.ndim == 0:
178
+ fill_value = fill_value._array
179
+ res = np.full(shape, fill_value, dtype=dtype)
180
+ if res.dtype not in _all_dtypes:
181
+ # This will happen if the fill value is not something that NumPy
182
+ # coerces to one of the acceptable dtypes.
183
+ raise TypeError("Invalid input to full")
184
+ return Array._new(res)
185
+
186
+
187
+ def full_like(
188
+ x: Array,
189
+ /,
190
+ fill_value: Union[int, float],
191
+ *,
192
+ dtype: Optional[Dtype] = None,
193
+ device: Optional[Device] = None,
194
+ ) -> Array:
195
+ """
196
+ Array API compatible wrapper for :py:func:`np.full_like <numpy.full_like>`.
197
+
198
+ See its docstring for more information.
199
+ """
200
+ from ._array_object import Array
201
+
202
+ _check_valid_dtype(dtype)
203
+ if device not in ["cpu", None]:
204
+ raise ValueError(f"Unsupported device {device!r}")
205
+ res = np.full_like(x._array, fill_value, dtype=dtype)
206
+ if res.dtype not in _all_dtypes:
207
+ # This will happen if the fill value is not something that NumPy
208
+ # coerces to one of the acceptable dtypes.
209
+ raise TypeError("Invalid input to full_like")
210
+ return Array._new(res)
211
+
212
+
213
+ def linspace(
214
+ start: Union[int, float],
215
+ stop: Union[int, float],
216
+ /,
217
+ num: int,
218
+ *,
219
+ dtype: Optional[Dtype] = None,
220
+ device: Optional[Device] = None,
221
+ endpoint: bool = True,
222
+ ) -> Array:
223
+ """
224
+ Array API compatible wrapper for :py:func:`np.linspace <numpy.linspace>`.
225
+
226
+ See its docstring for more information.
227
+ """
228
+ from ._array_object import Array
229
+
230
+ _check_valid_dtype(dtype)
231
+ if device not in ["cpu", None]:
232
+ raise ValueError(f"Unsupported device {device!r}")
233
+ return Array._new(np.linspace(start, stop, num, dtype=dtype, endpoint=endpoint))
234
+
235
+
236
+ def meshgrid(*arrays: Array, indexing: str = "xy") -> List[Array]:
237
+ """
238
+ Array API compatible wrapper for :py:func:`np.meshgrid <numpy.meshgrid>`.
239
+
240
+ See its docstring for more information.
241
+ """
242
+ from ._array_object import Array
243
+
244
+ # Note: unlike np.meshgrid, only inputs with all the same dtype are
245
+ # allowed
246
+
247
+ if len({a.dtype for a in arrays}) > 1:
248
+ raise ValueError("meshgrid inputs must all have the same dtype")
249
+
250
+ return [
251
+ Array._new(array)
252
+ for array in np.meshgrid(*[a._array for a in arrays], indexing=indexing)
253
+ ]
254
+
255
+
256
+ def ones(
257
+ shape: Union[int, Tuple[int, ...]],
258
+ *,
259
+ dtype: Optional[Dtype] = None,
260
+ device: Optional[Device] = None,
261
+ ) -> Array:
262
+ """
263
+ Array API compatible wrapper for :py:func:`np.ones <numpy.ones>`.
264
+
265
+ See its docstring for more information.
266
+ """
267
+ from ._array_object import Array
268
+
269
+ _check_valid_dtype(dtype)
270
+ if device not in ["cpu", None]:
271
+ raise ValueError(f"Unsupported device {device!r}")
272
+ return Array._new(np.ones(shape, dtype=dtype))
273
+
274
+
275
+ def ones_like(
276
+ x: Array, /, *, dtype: Optional[Dtype] = None, device: Optional[Device] = None
277
+ ) -> Array:
278
+ """
279
+ Array API compatible wrapper for :py:func:`np.ones_like <numpy.ones_like>`.
280
+
281
+ See its docstring for more information.
282
+ """
283
+ from ._array_object import Array
284
+
285
+ _check_valid_dtype(dtype)
286
+ if device not in ["cpu", None]:
287
+ raise ValueError(f"Unsupported device {device!r}")
288
+ return Array._new(np.ones_like(x._array, dtype=dtype))
289
+
290
+
291
+ def tril(x: Array, /, *, k: int = 0) -> Array:
292
+ """
293
+ Array API compatible wrapper for :py:func:`np.tril <numpy.tril>`.
294
+
295
+ See its docstring for more information.
296
+ """
297
+ from ._array_object import Array
298
+
299
+ if x.ndim < 2:
300
+ # Note: Unlike np.tril, x must be at least 2-D
301
+ raise ValueError("x must be at least 2-dimensional for tril")
302
+ return Array._new(np.tril(x._array, k=k))
303
+
304
+
305
+ def triu(x: Array, /, *, k: int = 0) -> Array:
306
+ """
307
+ Array API compatible wrapper for :py:func:`np.triu <numpy.triu>`.
308
+
309
+ See its docstring for more information.
310
+ """
311
+ from ._array_object import Array
312
+
313
+ if x.ndim < 2:
314
+ # Note: Unlike np.triu, x must be at least 2-D
315
+ raise ValueError("x must be at least 2-dimensional for triu")
316
+ return Array._new(np.triu(x._array, k=k))
317
+
318
+
319
+ def zeros(
320
+ shape: Union[int, Tuple[int, ...]],
321
+ *,
322
+ dtype: Optional[Dtype] = None,
323
+ device: Optional[Device] = None,
324
+ ) -> Array:
325
+ """
326
+ Array API compatible wrapper for :py:func:`np.zeros <numpy.zeros>`.
327
+
328
+ See its docstring for more information.
329
+ """
330
+ from ._array_object import Array
331
+
332
+ _check_valid_dtype(dtype)
333
+ if device not in ["cpu", None]:
334
+ raise ValueError(f"Unsupported device {device!r}")
335
+ return Array._new(np.zeros(shape, dtype=dtype))
336
+
337
+
338
+ def zeros_like(
339
+ x: Array, /, *, dtype: Optional[Dtype] = None, device: Optional[Device] = None
340
+ ) -> Array:
341
+ """
342
+ Array API compatible wrapper for :py:func:`np.zeros_like <numpy.zeros_like>`.
343
+
344
+ See its docstring for more information.
345
+ """
346
+ from ._array_object import Array
347
+
348
+ _check_valid_dtype(dtype)
349
+ if device not in ["cpu", None]:
350
+ raise ValueError(f"Unsupported device {device!r}")
351
+ return Array._new(np.zeros_like(x._array, dtype=dtype))
lib/python3.12/site-packages/numpy/array_api/_data_type_functions.py ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ._array_object import Array
4
+ from ._dtypes import (
5
+ _all_dtypes,
6
+ _boolean_dtypes,
7
+ _signed_integer_dtypes,
8
+ _unsigned_integer_dtypes,
9
+ _integer_dtypes,
10
+ _real_floating_dtypes,
11
+ _complex_floating_dtypes,
12
+ _numeric_dtypes,
13
+ _result_type,
14
+ )
15
+
16
+ from dataclasses import dataclass
17
+ from typing import TYPE_CHECKING, List, Tuple, Union
18
+
19
+ if TYPE_CHECKING:
20
+ from ._typing import Dtype
21
+ from collections.abc import Sequence
22
+
23
+ import numpy as np
24
+
25
+
26
+ # Note: astype is a function, not an array method as in NumPy.
27
+ def astype(x: Array, dtype: Dtype, /, *, copy: bool = True) -> Array:
28
+ if not copy and dtype == x.dtype:
29
+ return x
30
+ return Array._new(x._array.astype(dtype=dtype, copy=copy))
31
+
32
+
33
+ def broadcast_arrays(*arrays: Array) -> List[Array]:
34
+ """
35
+ Array API compatible wrapper for :py:func:`np.broadcast_arrays <numpy.broadcast_arrays>`.
36
+
37
+ See its docstring for more information.
38
+ """
39
+ from ._array_object import Array
40
+
41
+ return [
42
+ Array._new(array) for array in np.broadcast_arrays(*[a._array for a in arrays])
43
+ ]
44
+
45
+
46
+ def broadcast_to(x: Array, /, shape: Tuple[int, ...]) -> Array:
47
+ """
48
+ Array API compatible wrapper for :py:func:`np.broadcast_to <numpy.broadcast_to>`.
49
+
50
+ See its docstring for more information.
51
+ """
52
+ from ._array_object import Array
53
+
54
+ return Array._new(np.broadcast_to(x._array, shape))
55
+
56
+
57
+ def can_cast(from_: Union[Dtype, Array], to: Dtype, /) -> bool:
58
+ """
59
+ Array API compatible wrapper for :py:func:`np.can_cast <numpy.can_cast>`.
60
+
61
+ See its docstring for more information.
62
+ """
63
+ if isinstance(from_, Array):
64
+ from_ = from_.dtype
65
+ elif from_ not in _all_dtypes:
66
+ raise TypeError(f"{from_=}, but should be an array_api array or dtype")
67
+ if to not in _all_dtypes:
68
+ raise TypeError(f"{to=}, but should be a dtype")
69
+ # Note: We avoid np.can_cast() as it has discrepancies with the array API,
70
+ # since NumPy allows cross-kind casting (e.g., NumPy allows bool -> int8).
71
+ # See https://github.com/numpy/numpy/issues/20870
72
+ try:
73
+ # We promote `from_` and `to` together. We then check if the promoted
74
+ # dtype is `to`, which indicates if `from_` can (up)cast to `to`.
75
+ dtype = _result_type(from_, to)
76
+ return to == dtype
77
+ except TypeError:
78
+ # _result_type() raises if the dtypes don't promote together
79
+ return False
80
+
81
+
82
+ # These are internal objects for the return types of finfo and iinfo, since
83
+ # the NumPy versions contain extra data that isn't part of the spec.
84
+ @dataclass
85
+ class finfo_object:
86
+ bits: int
87
+ # Note: The types of the float data here are float, whereas in NumPy they
88
+ # are scalars of the corresponding float dtype.
89
+ eps: float
90
+ max: float
91
+ min: float
92
+ smallest_normal: float
93
+ dtype: Dtype
94
+
95
+
96
+ @dataclass
97
+ class iinfo_object:
98
+ bits: int
99
+ max: int
100
+ min: int
101
+ dtype: Dtype
102
+
103
+
104
+ def finfo(type: Union[Dtype, Array], /) -> finfo_object:
105
+ """
106
+ Array API compatible wrapper for :py:func:`np.finfo <numpy.finfo>`.
107
+
108
+ See its docstring for more information.
109
+ """
110
+ fi = np.finfo(type)
111
+ # Note: The types of the float data here are float, whereas in NumPy they
112
+ # are scalars of the corresponding float dtype.
113
+ return finfo_object(
114
+ fi.bits,
115
+ float(fi.eps),
116
+ float(fi.max),
117
+ float(fi.min),
118
+ float(fi.smallest_normal),
119
+ fi.dtype,
120
+ )
121
+
122
+
123
+ def iinfo(type: Union[Dtype, Array], /) -> iinfo_object:
124
+ """
125
+ Array API compatible wrapper for :py:func:`np.iinfo <numpy.iinfo>`.
126
+
127
+ See its docstring for more information.
128
+ """
129
+ ii = np.iinfo(type)
130
+ return iinfo_object(ii.bits, ii.max, ii.min, ii.dtype)
131
+
132
+
133
+ # Note: isdtype is a new function from the 2022.12 array API specification.
134
+ def isdtype(
135
+ dtype: Dtype, kind: Union[Dtype, str, Tuple[Union[Dtype, str], ...]]
136
+ ) -> bool:
137
+ """
138
+ Returns a boolean indicating whether a provided dtype is of a specified data type ``kind``.
139
+
140
+ See
141
+ https://data-apis.org/array-api/latest/API_specification/generated/array_api.isdtype.html
142
+ for more details
143
+ """
144
+ if isinstance(kind, tuple):
145
+ # Disallow nested tuples
146
+ if any(isinstance(k, tuple) for k in kind):
147
+ raise TypeError("'kind' must be a dtype, str, or tuple of dtypes and strs")
148
+ return any(isdtype(dtype, k) for k in kind)
149
+ elif isinstance(kind, str):
150
+ if kind == 'bool':
151
+ return dtype in _boolean_dtypes
152
+ elif kind == 'signed integer':
153
+ return dtype in _signed_integer_dtypes
154
+ elif kind == 'unsigned integer':
155
+ return dtype in _unsigned_integer_dtypes
156
+ elif kind == 'integral':
157
+ return dtype in _integer_dtypes
158
+ elif kind == 'real floating':
159
+ return dtype in _real_floating_dtypes
160
+ elif kind == 'complex floating':
161
+ return dtype in _complex_floating_dtypes
162
+ elif kind == 'numeric':
163
+ return dtype in _numeric_dtypes
164
+ else:
165
+ raise ValueError(f"Unrecognized data type kind: {kind!r}")
166
+ elif kind in _all_dtypes:
167
+ return dtype == kind
168
+ else:
169
+ raise TypeError(f"'kind' must be a dtype, str, or tuple of dtypes and strs, not {type(kind).__name__}")
170
+
171
+ def result_type(*arrays_and_dtypes: Union[Array, Dtype]) -> Dtype:
172
+ """
173
+ Array API compatible wrapper for :py:func:`np.result_type <numpy.result_type>`.
174
+
175
+ See its docstring for more information.
176
+ """
177
+ # Note: we use a custom implementation that gives only the type promotions
178
+ # required by the spec rather than using np.result_type. NumPy implements
179
+ # too many extra type promotions like int64 + uint64 -> float64, and does
180
+ # value-based casting on scalar arrays.
181
+ A = []
182
+ for a in arrays_and_dtypes:
183
+ if isinstance(a, Array):
184
+ a = a.dtype
185
+ elif isinstance(a, np.ndarray) or a not in _all_dtypes:
186
+ raise TypeError("result_type() inputs must be array_api arrays or dtypes")
187
+ A.append(a)
188
+
189
+ if len(A) == 0:
190
+ raise ValueError("at least one array or dtype is required")
191
+ elif len(A) == 1:
192
+ return A[0]
193
+ else:
194
+ t = A[0]
195
+ for t2 in A[1:]:
196
+ t = _result_type(t, t2)
197
+ return t
lib/python3.12/site-packages/numpy/array_api/_dtypes.py ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ # Note: we use dtype objects instead of dtype classes. The spec does not
4
+ # require any behavior on dtypes other than equality.
5
+ int8 = np.dtype("int8")
6
+ int16 = np.dtype("int16")
7
+ int32 = np.dtype("int32")
8
+ int64 = np.dtype("int64")
9
+ uint8 = np.dtype("uint8")
10
+ uint16 = np.dtype("uint16")
11
+ uint32 = np.dtype("uint32")
12
+ uint64 = np.dtype("uint64")
13
+ float32 = np.dtype("float32")
14
+ float64 = np.dtype("float64")
15
+ complex64 = np.dtype("complex64")
16
+ complex128 = np.dtype("complex128")
17
+ # Note: This name is changed
18
+ bool = np.dtype("bool")
19
+
20
+ _all_dtypes = (
21
+ int8,
22
+ int16,
23
+ int32,
24
+ int64,
25
+ uint8,
26
+ uint16,
27
+ uint32,
28
+ uint64,
29
+ float32,
30
+ float64,
31
+ complex64,
32
+ complex128,
33
+ bool,
34
+ )
35
+ _boolean_dtypes = (bool,)
36
+ _real_floating_dtypes = (float32, float64)
37
+ _floating_dtypes = (float32, float64, complex64, complex128)
38
+ _complex_floating_dtypes = (complex64, complex128)
39
+ _integer_dtypes = (int8, int16, int32, int64, uint8, uint16, uint32, uint64)
40
+ _signed_integer_dtypes = (int8, int16, int32, int64)
41
+ _unsigned_integer_dtypes = (uint8, uint16, uint32, uint64)
42
+ _integer_or_boolean_dtypes = (
43
+ bool,
44
+ int8,
45
+ int16,
46
+ int32,
47
+ int64,
48
+ uint8,
49
+ uint16,
50
+ uint32,
51
+ uint64,
52
+ )
53
+ _real_numeric_dtypes = (
54
+ float32,
55
+ float64,
56
+ int8,
57
+ int16,
58
+ int32,
59
+ int64,
60
+ uint8,
61
+ uint16,
62
+ uint32,
63
+ uint64,
64
+ )
65
+ _numeric_dtypes = (
66
+ float32,
67
+ float64,
68
+ complex64,
69
+ complex128,
70
+ int8,
71
+ int16,
72
+ int32,
73
+ int64,
74
+ uint8,
75
+ uint16,
76
+ uint32,
77
+ uint64,
78
+ )
79
+
80
+ _dtype_categories = {
81
+ "all": _all_dtypes,
82
+ "real numeric": _real_numeric_dtypes,
83
+ "numeric": _numeric_dtypes,
84
+ "integer": _integer_dtypes,
85
+ "integer or boolean": _integer_or_boolean_dtypes,
86
+ "boolean": _boolean_dtypes,
87
+ "real floating-point": _floating_dtypes,
88
+ "complex floating-point": _complex_floating_dtypes,
89
+ "floating-point": _floating_dtypes,
90
+ }
91
+
92
+
93
+ # Note: the spec defines a restricted type promotion table compared to NumPy.
94
+ # In particular, cross-kind promotions like integer + float or boolean +
95
+ # integer are not allowed, even for functions that accept both kinds.
96
+ # Additionally, NumPy promotes signed integer + uint64 to float64, but this
97
+ # promotion is not allowed here. To be clear, Python scalar int objects are
98
+ # allowed to promote to floating-point dtypes, but only in array operators
99
+ # (see Array._promote_scalar) method in _array_object.py.
100
+ _promotion_table = {
101
+ (int8, int8): int8,
102
+ (int8, int16): int16,
103
+ (int8, int32): int32,
104
+ (int8, int64): int64,
105
+ (int16, int8): int16,
106
+ (int16, int16): int16,
107
+ (int16, int32): int32,
108
+ (int16, int64): int64,
109
+ (int32, int8): int32,
110
+ (int32, int16): int32,
111
+ (int32, int32): int32,
112
+ (int32, int64): int64,
113
+ (int64, int8): int64,
114
+ (int64, int16): int64,
115
+ (int64, int32): int64,
116
+ (int64, int64): int64,
117
+ (uint8, uint8): uint8,
118
+ (uint8, uint16): uint16,
119
+ (uint8, uint32): uint32,
120
+ (uint8, uint64): uint64,
121
+ (uint16, uint8): uint16,
122
+ (uint16, uint16): uint16,
123
+ (uint16, uint32): uint32,
124
+ (uint16, uint64): uint64,
125
+ (uint32, uint8): uint32,
126
+ (uint32, uint16): uint32,
127
+ (uint32, uint32): uint32,
128
+ (uint32, uint64): uint64,
129
+ (uint64, uint8): uint64,
130
+ (uint64, uint16): uint64,
131
+ (uint64, uint32): uint64,
132
+ (uint64, uint64): uint64,
133
+ (int8, uint8): int16,
134
+ (int8, uint16): int32,
135
+ (int8, uint32): int64,
136
+ (int16, uint8): int16,
137
+ (int16, uint16): int32,
138
+ (int16, uint32): int64,
139
+ (int32, uint8): int32,
140
+ (int32, uint16): int32,
141
+ (int32, uint32): int64,
142
+ (int64, uint8): int64,
143
+ (int64, uint16): int64,
144
+ (int64, uint32): int64,
145
+ (uint8, int8): int16,
146
+ (uint16, int8): int32,
147
+ (uint32, int8): int64,
148
+ (uint8, int16): int16,
149
+ (uint16, int16): int32,
150
+ (uint32, int16): int64,
151
+ (uint8, int32): int32,
152
+ (uint16, int32): int32,
153
+ (uint32, int32): int64,
154
+ (uint8, int64): int64,
155
+ (uint16, int64): int64,
156
+ (uint32, int64): int64,
157
+ (float32, float32): float32,
158
+ (float32, float64): float64,
159
+ (float64, float32): float64,
160
+ (float64, float64): float64,
161
+ (complex64, complex64): complex64,
162
+ (complex64, complex128): complex128,
163
+ (complex128, complex64): complex128,
164
+ (complex128, complex128): complex128,
165
+ (float32, complex64): complex64,
166
+ (float32, complex128): complex128,
167
+ (float64, complex64): complex128,
168
+ (float64, complex128): complex128,
169
+ (complex64, float32): complex64,
170
+ (complex64, float64): complex128,
171
+ (complex128, float32): complex128,
172
+ (complex128, float64): complex128,
173
+ (bool, bool): bool,
174
+ }
175
+
176
+
177
+ def _result_type(type1, type2):
178
+ if (type1, type2) in _promotion_table:
179
+ return _promotion_table[type1, type2]
180
+ raise TypeError(f"{type1} and {type2} cannot be type promoted together")
lib/python3.12/site-packages/numpy/array_api/_elementwise_functions.py ADDED
@@ -0,0 +1,765 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ._dtypes import (
4
+ _boolean_dtypes,
5
+ _floating_dtypes,
6
+ _real_floating_dtypes,
7
+ _complex_floating_dtypes,
8
+ _integer_dtypes,
9
+ _integer_or_boolean_dtypes,
10
+ _real_numeric_dtypes,
11
+ _numeric_dtypes,
12
+ _result_type,
13
+ )
14
+ from ._array_object import Array
15
+
16
+ import numpy as np
17
+
18
+
19
+ def abs(x: Array, /) -> Array:
20
+ """
21
+ Array API compatible wrapper for :py:func:`np.abs <numpy.abs>`.
22
+
23
+ See its docstring for more information.
24
+ """
25
+ if x.dtype not in _numeric_dtypes:
26
+ raise TypeError("Only numeric dtypes are allowed in abs")
27
+ return Array._new(np.abs(x._array))
28
+
29
+
30
+ # Note: the function name is different here
31
+ def acos(x: Array, /) -> Array:
32
+ """
33
+ Array API compatible wrapper for :py:func:`np.arccos <numpy.arccos>`.
34
+
35
+ See its docstring for more information.
36
+ """
37
+ if x.dtype not in _floating_dtypes:
38
+ raise TypeError("Only floating-point dtypes are allowed in acos")
39
+ return Array._new(np.arccos(x._array))
40
+
41
+
42
+ # Note: the function name is different here
43
+ def acosh(x: Array, /) -> Array:
44
+ """
45
+ Array API compatible wrapper for :py:func:`np.arccosh <numpy.arccosh>`.
46
+
47
+ See its docstring for more information.
48
+ """
49
+ if x.dtype not in _floating_dtypes:
50
+ raise TypeError("Only floating-point dtypes are allowed in acosh")
51
+ return Array._new(np.arccosh(x._array))
52
+
53
+
54
+ def add(x1: Array, x2: Array, /) -> Array:
55
+ """
56
+ Array API compatible wrapper for :py:func:`np.add <numpy.add>`.
57
+
58
+ See its docstring for more information.
59
+ """
60
+ if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
61
+ raise TypeError("Only numeric dtypes are allowed in add")
62
+ # Call result type here just to raise on disallowed type combinations
63
+ _result_type(x1.dtype, x2.dtype)
64
+ x1, x2 = Array._normalize_two_args(x1, x2)
65
+ return Array._new(np.add(x1._array, x2._array))
66
+
67
+
68
+ # Note: the function name is different here
69
+ def asin(x: Array, /) -> Array:
70
+ """
71
+ Array API compatible wrapper for :py:func:`np.arcsin <numpy.arcsin>`.
72
+
73
+ See its docstring for more information.
74
+ """
75
+ if x.dtype not in _floating_dtypes:
76
+ raise TypeError("Only floating-point dtypes are allowed in asin")
77
+ return Array._new(np.arcsin(x._array))
78
+
79
+
80
+ # Note: the function name is different here
81
+ def asinh(x: Array, /) -> Array:
82
+ """
83
+ Array API compatible wrapper for :py:func:`np.arcsinh <numpy.arcsinh>`.
84
+
85
+ See its docstring for more information.
86
+ """
87
+ if x.dtype not in _floating_dtypes:
88
+ raise TypeError("Only floating-point dtypes are allowed in asinh")
89
+ return Array._new(np.arcsinh(x._array))
90
+
91
+
92
+ # Note: the function name is different here
93
+ def atan(x: Array, /) -> Array:
94
+ """
95
+ Array API compatible wrapper for :py:func:`np.arctan <numpy.arctan>`.
96
+
97
+ See its docstring for more information.
98
+ """
99
+ if x.dtype not in _floating_dtypes:
100
+ raise TypeError("Only floating-point dtypes are allowed in atan")
101
+ return Array._new(np.arctan(x._array))
102
+
103
+
104
+ # Note: the function name is different here
105
+ def atan2(x1: Array, x2: Array, /) -> Array:
106
+ """
107
+ Array API compatible wrapper for :py:func:`np.arctan2 <numpy.arctan2>`.
108
+
109
+ See its docstring for more information.
110
+ """
111
+ if x1.dtype not in _real_floating_dtypes or x2.dtype not in _real_floating_dtypes:
112
+ raise TypeError("Only real floating-point dtypes are allowed in atan2")
113
+ # Call result type here just to raise on disallowed type combinations
114
+ _result_type(x1.dtype, x2.dtype)
115
+ x1, x2 = Array._normalize_two_args(x1, x2)
116
+ return Array._new(np.arctan2(x1._array, x2._array))
117
+
118
+
119
+ # Note: the function name is different here
120
+ def atanh(x: Array, /) -> Array:
121
+ """
122
+ Array API compatible wrapper for :py:func:`np.arctanh <numpy.arctanh>`.
123
+
124
+ See its docstring for more information.
125
+ """
126
+ if x.dtype not in _floating_dtypes:
127
+ raise TypeError("Only floating-point dtypes are allowed in atanh")
128
+ return Array._new(np.arctanh(x._array))
129
+
130
+
131
+ def bitwise_and(x1: Array, x2: Array, /) -> Array:
132
+ """
133
+ Array API compatible wrapper for :py:func:`np.bitwise_and <numpy.bitwise_and>`.
134
+
135
+ See its docstring for more information.
136
+ """
137
+ if (
138
+ x1.dtype not in _integer_or_boolean_dtypes
139
+ or x2.dtype not in _integer_or_boolean_dtypes
140
+ ):
141
+ raise TypeError("Only integer or boolean dtypes are allowed in bitwise_and")
142
+ # Call result type here just to raise on disallowed type combinations
143
+ _result_type(x1.dtype, x2.dtype)
144
+ x1, x2 = Array._normalize_two_args(x1, x2)
145
+ return Array._new(np.bitwise_and(x1._array, x2._array))
146
+
147
+
148
+ # Note: the function name is different here
149
+ def bitwise_left_shift(x1: Array, x2: Array, /) -> Array:
150
+ """
151
+ Array API compatible wrapper for :py:func:`np.left_shift <numpy.left_shift>`.
152
+
153
+ See its docstring for more information.
154
+ """
155
+ if x1.dtype not in _integer_dtypes or x2.dtype not in _integer_dtypes:
156
+ raise TypeError("Only integer dtypes are allowed in bitwise_left_shift")
157
+ # Call result type here just to raise on disallowed type combinations
158
+ _result_type(x1.dtype, x2.dtype)
159
+ x1, x2 = Array._normalize_two_args(x1, x2)
160
+ # Note: bitwise_left_shift is only defined for x2 nonnegative.
161
+ if np.any(x2._array < 0):
162
+ raise ValueError("bitwise_left_shift(x1, x2) is only defined for x2 >= 0")
163
+ return Array._new(np.left_shift(x1._array, x2._array))
164
+
165
+
166
+ # Note: the function name is different here
167
+ def bitwise_invert(x: Array, /) -> Array:
168
+ """
169
+ Array API compatible wrapper for :py:func:`np.invert <numpy.invert>`.
170
+
171
+ See its docstring for more information.
172
+ """
173
+ if x.dtype not in _integer_or_boolean_dtypes:
174
+ raise TypeError("Only integer or boolean dtypes are allowed in bitwise_invert")
175
+ return Array._new(np.invert(x._array))
176
+
177
+
178
+ def bitwise_or(x1: Array, x2: Array, /) -> Array:
179
+ """
180
+ Array API compatible wrapper for :py:func:`np.bitwise_or <numpy.bitwise_or>`.
181
+
182
+ See its docstring for more information.
183
+ """
184
+ if (
185
+ x1.dtype not in _integer_or_boolean_dtypes
186
+ or x2.dtype not in _integer_or_boolean_dtypes
187
+ ):
188
+ raise TypeError("Only integer or boolean dtypes are allowed in bitwise_or")
189
+ # Call result type here just to raise on disallowed type combinations
190
+ _result_type(x1.dtype, x2.dtype)
191
+ x1, x2 = Array._normalize_two_args(x1, x2)
192
+ return Array._new(np.bitwise_or(x1._array, x2._array))
193
+
194
+
195
+ # Note: the function name is different here
196
+ def bitwise_right_shift(x1: Array, x2: Array, /) -> Array:
197
+ """
198
+ Array API compatible wrapper for :py:func:`np.right_shift <numpy.right_shift>`.
199
+
200
+ See its docstring for more information.
201
+ """
202
+ if x1.dtype not in _integer_dtypes or x2.dtype not in _integer_dtypes:
203
+ raise TypeError("Only integer dtypes are allowed in bitwise_right_shift")
204
+ # Call result type here just to raise on disallowed type combinations
205
+ _result_type(x1.dtype, x2.dtype)
206
+ x1, x2 = Array._normalize_two_args(x1, x2)
207
+ # Note: bitwise_right_shift is only defined for x2 nonnegative.
208
+ if np.any(x2._array < 0):
209
+ raise ValueError("bitwise_right_shift(x1, x2) is only defined for x2 >= 0")
210
+ return Array._new(np.right_shift(x1._array, x2._array))
211
+
212
+
213
+ def bitwise_xor(x1: Array, x2: Array, /) -> Array:
214
+ """
215
+ Array API compatible wrapper for :py:func:`np.bitwise_xor <numpy.bitwise_xor>`.
216
+
217
+ See its docstring for more information.
218
+ """
219
+ if (
220
+ x1.dtype not in _integer_or_boolean_dtypes
221
+ or x2.dtype not in _integer_or_boolean_dtypes
222
+ ):
223
+ raise TypeError("Only integer or boolean dtypes are allowed in bitwise_xor")
224
+ # Call result type here just to raise on disallowed type combinations
225
+ _result_type(x1.dtype, x2.dtype)
226
+ x1, x2 = Array._normalize_two_args(x1, x2)
227
+ return Array._new(np.bitwise_xor(x1._array, x2._array))
228
+
229
+
230
+ def ceil(x: Array, /) -> Array:
231
+ """
232
+ Array API compatible wrapper for :py:func:`np.ceil <numpy.ceil>`.
233
+
234
+ See its docstring for more information.
235
+ """
236
+ if x.dtype not in _real_numeric_dtypes:
237
+ raise TypeError("Only real numeric dtypes are allowed in ceil")
238
+ if x.dtype in _integer_dtypes:
239
+ # Note: The return dtype of ceil is the same as the input
240
+ return x
241
+ return Array._new(np.ceil(x._array))
242
+
243
+
244
+ def conj(x: Array, /) -> Array:
245
+ """
246
+ Array API compatible wrapper for :py:func:`np.conj <numpy.conj>`.
247
+
248
+ See its docstring for more information.
249
+ """
250
+ if x.dtype not in _complex_floating_dtypes:
251
+ raise TypeError("Only complex floating-point dtypes are allowed in conj")
252
+ return Array._new(np.conj(x))
253
+
254
+
255
+ def cos(x: Array, /) -> Array:
256
+ """
257
+ Array API compatible wrapper for :py:func:`np.cos <numpy.cos>`.
258
+
259
+ See its docstring for more information.
260
+ """
261
+ if x.dtype not in _floating_dtypes:
262
+ raise TypeError("Only floating-point dtypes are allowed in cos")
263
+ return Array._new(np.cos(x._array))
264
+
265
+
266
+ def cosh(x: Array, /) -> Array:
267
+ """
268
+ Array API compatible wrapper for :py:func:`np.cosh <numpy.cosh>`.
269
+
270
+ See its docstring for more information.
271
+ """
272
+ if x.dtype not in _floating_dtypes:
273
+ raise TypeError("Only floating-point dtypes are allowed in cosh")
274
+ return Array._new(np.cosh(x._array))
275
+
276
+
277
+ def divide(x1: Array, x2: Array, /) -> Array:
278
+ """
279
+ Array API compatible wrapper for :py:func:`np.divide <numpy.divide>`.
280
+
281
+ See its docstring for more information.
282
+ """
283
+ if x1.dtype not in _floating_dtypes or x2.dtype not in _floating_dtypes:
284
+ raise TypeError("Only floating-point dtypes are allowed in divide")
285
+ # Call result type here just to raise on disallowed type combinations
286
+ _result_type(x1.dtype, x2.dtype)
287
+ x1, x2 = Array._normalize_two_args(x1, x2)
288
+ return Array._new(np.divide(x1._array, x2._array))
289
+
290
+
291
+ def equal(x1: Array, x2: Array, /) -> Array:
292
+ """
293
+ Array API compatible wrapper for :py:func:`np.equal <numpy.equal>`.
294
+
295
+ See its docstring for more information.
296
+ """
297
+ # Call result type here just to raise on disallowed type combinations
298
+ _result_type(x1.dtype, x2.dtype)
299
+ x1, x2 = Array._normalize_two_args(x1, x2)
300
+ return Array._new(np.equal(x1._array, x2._array))
301
+
302
+
303
+ def exp(x: Array, /) -> Array:
304
+ """
305
+ Array API compatible wrapper for :py:func:`np.exp <numpy.exp>`.
306
+
307
+ See its docstring for more information.
308
+ """
309
+ if x.dtype not in _floating_dtypes:
310
+ raise TypeError("Only floating-point dtypes are allowed in exp")
311
+ return Array._new(np.exp(x._array))
312
+
313
+
314
+ def expm1(x: Array, /) -> Array:
315
+ """
316
+ Array API compatible wrapper for :py:func:`np.expm1 <numpy.expm1>`.
317
+
318
+ See its docstring for more information.
319
+ """
320
+ if x.dtype not in _floating_dtypes:
321
+ raise TypeError("Only floating-point dtypes are allowed in expm1")
322
+ return Array._new(np.expm1(x._array))
323
+
324
+
325
+ def floor(x: Array, /) -> Array:
326
+ """
327
+ Array API compatible wrapper for :py:func:`np.floor <numpy.floor>`.
328
+
329
+ See its docstring for more information.
330
+ """
331
+ if x.dtype not in _real_numeric_dtypes:
332
+ raise TypeError("Only real numeric dtypes are allowed in floor")
333
+ if x.dtype in _integer_dtypes:
334
+ # Note: The return dtype of floor is the same as the input
335
+ return x
336
+ return Array._new(np.floor(x._array))
337
+
338
+
339
+ def floor_divide(x1: Array, x2: Array, /) -> Array:
340
+ """
341
+ Array API compatible wrapper for :py:func:`np.floor_divide <numpy.floor_divide>`.
342
+
343
+ See its docstring for more information.
344
+ """
345
+ if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
346
+ raise TypeError("Only real numeric dtypes are allowed in floor_divide")
347
+ # Call result type here just to raise on disallowed type combinations
348
+ _result_type(x1.dtype, x2.dtype)
349
+ x1, x2 = Array._normalize_two_args(x1, x2)
350
+ return Array._new(np.floor_divide(x1._array, x2._array))
351
+
352
+
353
+ def greater(x1: Array, x2: Array, /) -> Array:
354
+ """
355
+ Array API compatible wrapper for :py:func:`np.greater <numpy.greater>`.
356
+
357
+ See its docstring for more information.
358
+ """
359
+ if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
360
+ raise TypeError("Only real numeric dtypes are allowed in greater")
361
+ # Call result type here just to raise on disallowed type combinations
362
+ _result_type(x1.dtype, x2.dtype)
363
+ x1, x2 = Array._normalize_two_args(x1, x2)
364
+ return Array._new(np.greater(x1._array, x2._array))
365
+
366
+
367
+ def greater_equal(x1: Array, x2: Array, /) -> Array:
368
+ """
369
+ Array API compatible wrapper for :py:func:`np.greater_equal <numpy.greater_equal>`.
370
+
371
+ See its docstring for more information.
372
+ """
373
+ if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
374
+ raise TypeError("Only real numeric dtypes are allowed in greater_equal")
375
+ # Call result type here just to raise on disallowed type combinations
376
+ _result_type(x1.dtype, x2.dtype)
377
+ x1, x2 = Array._normalize_two_args(x1, x2)
378
+ return Array._new(np.greater_equal(x1._array, x2._array))
379
+
380
+
381
+ def imag(x: Array, /) -> Array:
382
+ """
383
+ Array API compatible wrapper for :py:func:`np.imag <numpy.imag>`.
384
+
385
+ See its docstring for more information.
386
+ """
387
+ if x.dtype not in _complex_floating_dtypes:
388
+ raise TypeError("Only complex floating-point dtypes are allowed in imag")
389
+ return Array._new(np.imag(x))
390
+
391
+
392
+ def isfinite(x: Array, /) -> Array:
393
+ """
394
+ Array API compatible wrapper for :py:func:`np.isfinite <numpy.isfinite>`.
395
+
396
+ See its docstring for more information.
397
+ """
398
+ if x.dtype not in _numeric_dtypes:
399
+ raise TypeError("Only numeric dtypes are allowed in isfinite")
400
+ return Array._new(np.isfinite(x._array))
401
+
402
+
403
+ def isinf(x: Array, /) -> Array:
404
+ """
405
+ Array API compatible wrapper for :py:func:`np.isinf <numpy.isinf>`.
406
+
407
+ See its docstring for more information.
408
+ """
409
+ if x.dtype not in _numeric_dtypes:
410
+ raise TypeError("Only numeric dtypes are allowed in isinf")
411
+ return Array._new(np.isinf(x._array))
412
+
413
+
414
+ def isnan(x: Array, /) -> Array:
415
+ """
416
+ Array API compatible wrapper for :py:func:`np.isnan <numpy.isnan>`.
417
+
418
+ See its docstring for more information.
419
+ """
420
+ if x.dtype not in _numeric_dtypes:
421
+ raise TypeError("Only numeric dtypes are allowed in isnan")
422
+ return Array._new(np.isnan(x._array))
423
+
424
+
425
+ def less(x1: Array, x2: Array, /) -> Array:
426
+ """
427
+ Array API compatible wrapper for :py:func:`np.less <numpy.less>`.
428
+
429
+ See its docstring for more information.
430
+ """
431
+ if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
432
+ raise TypeError("Only real numeric dtypes are allowed in less")
433
+ # Call result type here just to raise on disallowed type combinations
434
+ _result_type(x1.dtype, x2.dtype)
435
+ x1, x2 = Array._normalize_two_args(x1, x2)
436
+ return Array._new(np.less(x1._array, x2._array))
437
+
438
+
439
+ def less_equal(x1: Array, x2: Array, /) -> Array:
440
+ """
441
+ Array API compatible wrapper for :py:func:`np.less_equal <numpy.less_equal>`.
442
+
443
+ See its docstring for more information.
444
+ """
445
+ if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
446
+ raise TypeError("Only real numeric dtypes are allowed in less_equal")
447
+ # Call result type here just to raise on disallowed type combinations
448
+ _result_type(x1.dtype, x2.dtype)
449
+ x1, x2 = Array._normalize_two_args(x1, x2)
450
+ return Array._new(np.less_equal(x1._array, x2._array))
451
+
452
+
453
+ def log(x: Array, /) -> Array:
454
+ """
455
+ Array API compatible wrapper for :py:func:`np.log <numpy.log>`.
456
+
457
+ See its docstring for more information.
458
+ """
459
+ if x.dtype not in _floating_dtypes:
460
+ raise TypeError("Only floating-point dtypes are allowed in log")
461
+ return Array._new(np.log(x._array))
462
+
463
+
464
+ def log1p(x: Array, /) -> Array:
465
+ """
466
+ Array API compatible wrapper for :py:func:`np.log1p <numpy.log1p>`.
467
+
468
+ See its docstring for more information.
469
+ """
470
+ if x.dtype not in _floating_dtypes:
471
+ raise TypeError("Only floating-point dtypes are allowed in log1p")
472
+ return Array._new(np.log1p(x._array))
473
+
474
+
475
+ def log2(x: Array, /) -> Array:
476
+ """
477
+ Array API compatible wrapper for :py:func:`np.log2 <numpy.log2>`.
478
+
479
+ See its docstring for more information.
480
+ """
481
+ if x.dtype not in _floating_dtypes:
482
+ raise TypeError("Only floating-point dtypes are allowed in log2")
483
+ return Array._new(np.log2(x._array))
484
+
485
+
486
+ def log10(x: Array, /) -> Array:
487
+ """
488
+ Array API compatible wrapper for :py:func:`np.log10 <numpy.log10>`.
489
+
490
+ See its docstring for more information.
491
+ """
492
+ if x.dtype not in _floating_dtypes:
493
+ raise TypeError("Only floating-point dtypes are allowed in log10")
494
+ return Array._new(np.log10(x._array))
495
+
496
+
497
+ def logaddexp(x1: Array, x2: Array) -> Array:
498
+ """
499
+ Array API compatible wrapper for :py:func:`np.logaddexp <numpy.logaddexp>`.
500
+
501
+ See its docstring for more information.
502
+ """
503
+ if x1.dtype not in _real_floating_dtypes or x2.dtype not in _real_floating_dtypes:
504
+ raise TypeError("Only real floating-point dtypes are allowed in logaddexp")
505
+ # Call result type here just to raise on disallowed type combinations
506
+ _result_type(x1.dtype, x2.dtype)
507
+ x1, x2 = Array._normalize_two_args(x1, x2)
508
+ return Array._new(np.logaddexp(x1._array, x2._array))
509
+
510
+
511
+ def logical_and(x1: Array, x2: Array, /) -> Array:
512
+ """
513
+ Array API compatible wrapper for :py:func:`np.logical_and <numpy.logical_and>`.
514
+
515
+ See its docstring for more information.
516
+ """
517
+ if x1.dtype not in _boolean_dtypes or x2.dtype not in _boolean_dtypes:
518
+ raise TypeError("Only boolean dtypes are allowed in logical_and")
519
+ # Call result type here just to raise on disallowed type combinations
520
+ _result_type(x1.dtype, x2.dtype)
521
+ x1, x2 = Array._normalize_two_args(x1, x2)
522
+ return Array._new(np.logical_and(x1._array, x2._array))
523
+
524
+
525
+ def logical_not(x: Array, /) -> Array:
526
+ """
527
+ Array API compatible wrapper for :py:func:`np.logical_not <numpy.logical_not>`.
528
+
529
+ See its docstring for more information.
530
+ """
531
+ if x.dtype not in _boolean_dtypes:
532
+ raise TypeError("Only boolean dtypes are allowed in logical_not")
533
+ return Array._new(np.logical_not(x._array))
534
+
535
+
536
+ def logical_or(x1: Array, x2: Array, /) -> Array:
537
+ """
538
+ Array API compatible wrapper for :py:func:`np.logical_or <numpy.logical_or>`.
539
+
540
+ See its docstring for more information.
541
+ """
542
+ if x1.dtype not in _boolean_dtypes or x2.dtype not in _boolean_dtypes:
543
+ raise TypeError("Only boolean dtypes are allowed in logical_or")
544
+ # Call result type here just to raise on disallowed type combinations
545
+ _result_type(x1.dtype, x2.dtype)
546
+ x1, x2 = Array._normalize_two_args(x1, x2)
547
+ return Array._new(np.logical_or(x1._array, x2._array))
548
+
549
+
550
+ def logical_xor(x1: Array, x2: Array, /) -> Array:
551
+ """
552
+ Array API compatible wrapper for :py:func:`np.logical_xor <numpy.logical_xor>`.
553
+
554
+ See its docstring for more information.
555
+ """
556
+ if x1.dtype not in _boolean_dtypes or x2.dtype not in _boolean_dtypes:
557
+ raise TypeError("Only boolean dtypes are allowed in logical_xor")
558
+ # Call result type here just to raise on disallowed type combinations
559
+ _result_type(x1.dtype, x2.dtype)
560
+ x1, x2 = Array._normalize_two_args(x1, x2)
561
+ return Array._new(np.logical_xor(x1._array, x2._array))
562
+
563
+
564
+ def multiply(x1: Array, x2: Array, /) -> Array:
565
+ """
566
+ Array API compatible wrapper for :py:func:`np.multiply <numpy.multiply>`.
567
+
568
+ See its docstring for more information.
569
+ """
570
+ if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
571
+ raise TypeError("Only numeric dtypes are allowed in multiply")
572
+ # Call result type here just to raise on disallowed type combinations
573
+ _result_type(x1.dtype, x2.dtype)
574
+ x1, x2 = Array._normalize_two_args(x1, x2)
575
+ return Array._new(np.multiply(x1._array, x2._array))
576
+
577
+
578
+ def negative(x: Array, /) -> Array:
579
+ """
580
+ Array API compatible wrapper for :py:func:`np.negative <numpy.negative>`.
581
+
582
+ See its docstring for more information.
583
+ """
584
+ if x.dtype not in _numeric_dtypes:
585
+ raise TypeError("Only numeric dtypes are allowed in negative")
586
+ return Array._new(np.negative(x._array))
587
+
588
+
589
+ def not_equal(x1: Array, x2: Array, /) -> Array:
590
+ """
591
+ Array API compatible wrapper for :py:func:`np.not_equal <numpy.not_equal>`.
592
+
593
+ See its docstring for more information.
594
+ """
595
+ # Call result type here just to raise on disallowed type combinations
596
+ _result_type(x1.dtype, x2.dtype)
597
+ x1, x2 = Array._normalize_two_args(x1, x2)
598
+ return Array._new(np.not_equal(x1._array, x2._array))
599
+
600
+
601
+ def positive(x: Array, /) -> Array:
602
+ """
603
+ Array API compatible wrapper for :py:func:`np.positive <numpy.positive>`.
604
+
605
+ See its docstring for more information.
606
+ """
607
+ if x.dtype not in _numeric_dtypes:
608
+ raise TypeError("Only numeric dtypes are allowed in positive")
609
+ return Array._new(np.positive(x._array))
610
+
611
+
612
+ # Note: the function name is different here
613
+ def pow(x1: Array, x2: Array, /) -> Array:
614
+ """
615
+ Array API compatible wrapper for :py:func:`np.power <numpy.power>`.
616
+
617
+ See its docstring for more information.
618
+ """
619
+ if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
620
+ raise TypeError("Only numeric dtypes are allowed in pow")
621
+ # Call result type here just to raise on disallowed type combinations
622
+ _result_type(x1.dtype, x2.dtype)
623
+ x1, x2 = Array._normalize_two_args(x1, x2)
624
+ return Array._new(np.power(x1._array, x2._array))
625
+
626
+
627
+ def real(x: Array, /) -> Array:
628
+ """
629
+ Array API compatible wrapper for :py:func:`np.real <numpy.real>`.
630
+
631
+ See its docstring for more information.
632
+ """
633
+ if x.dtype not in _complex_floating_dtypes:
634
+ raise TypeError("Only complex floating-point dtypes are allowed in real")
635
+ return Array._new(np.real(x))
636
+
637
+
638
+ def remainder(x1: Array, x2: Array, /) -> Array:
639
+ """
640
+ Array API compatible wrapper for :py:func:`np.remainder <numpy.remainder>`.
641
+
642
+ See its docstring for more information.
643
+ """
644
+ if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
645
+ raise TypeError("Only real numeric dtypes are allowed in remainder")
646
+ # Call result type here just to raise on disallowed type combinations
647
+ _result_type(x1.dtype, x2.dtype)
648
+ x1, x2 = Array._normalize_two_args(x1, x2)
649
+ return Array._new(np.remainder(x1._array, x2._array))
650
+
651
+
652
+ def round(x: Array, /) -> Array:
653
+ """
654
+ Array API compatible wrapper for :py:func:`np.round <numpy.round>`.
655
+
656
+ See its docstring for more information.
657
+ """
658
+ if x.dtype not in _numeric_dtypes:
659
+ raise TypeError("Only numeric dtypes are allowed in round")
660
+ return Array._new(np.round(x._array))
661
+
662
+
663
+ def sign(x: Array, /) -> Array:
664
+ """
665
+ Array API compatible wrapper for :py:func:`np.sign <numpy.sign>`.
666
+
667
+ See its docstring for more information.
668
+ """
669
+ if x.dtype not in _numeric_dtypes:
670
+ raise TypeError("Only numeric dtypes are allowed in sign")
671
+ return Array._new(np.sign(x._array))
672
+
673
+
674
+ def sin(x: Array, /) -> Array:
675
+ """
676
+ Array API compatible wrapper for :py:func:`np.sin <numpy.sin>`.
677
+
678
+ See its docstring for more information.
679
+ """
680
+ if x.dtype not in _floating_dtypes:
681
+ raise TypeError("Only floating-point dtypes are allowed in sin")
682
+ return Array._new(np.sin(x._array))
683
+
684
+
685
+ def sinh(x: Array, /) -> Array:
686
+ """
687
+ Array API compatible wrapper for :py:func:`np.sinh <numpy.sinh>`.
688
+
689
+ See its docstring for more information.
690
+ """
691
+ if x.dtype not in _floating_dtypes:
692
+ raise TypeError("Only floating-point dtypes are allowed in sinh")
693
+ return Array._new(np.sinh(x._array))
694
+
695
+
696
+ def square(x: Array, /) -> Array:
697
+ """
698
+ Array API compatible wrapper for :py:func:`np.square <numpy.square>`.
699
+
700
+ See its docstring for more information.
701
+ """
702
+ if x.dtype not in _numeric_dtypes:
703
+ raise TypeError("Only numeric dtypes are allowed in square")
704
+ return Array._new(np.square(x._array))
705
+
706
+
707
+ def sqrt(x: Array, /) -> Array:
708
+ """
709
+ Array API compatible wrapper for :py:func:`np.sqrt <numpy.sqrt>`.
710
+
711
+ See its docstring for more information.
712
+ """
713
+ if x.dtype not in _floating_dtypes:
714
+ raise TypeError("Only floating-point dtypes are allowed in sqrt")
715
+ return Array._new(np.sqrt(x._array))
716
+
717
+
718
+ def subtract(x1: Array, x2: Array, /) -> Array:
719
+ """
720
+ Array API compatible wrapper for :py:func:`np.subtract <numpy.subtract>`.
721
+
722
+ See its docstring for more information.
723
+ """
724
+ if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
725
+ raise TypeError("Only numeric dtypes are allowed in subtract")
726
+ # Call result type here just to raise on disallowed type combinations
727
+ _result_type(x1.dtype, x2.dtype)
728
+ x1, x2 = Array._normalize_two_args(x1, x2)
729
+ return Array._new(np.subtract(x1._array, x2._array))
730
+
731
+
732
+ def tan(x: Array, /) -> Array:
733
+ """
734
+ Array API compatible wrapper for :py:func:`np.tan <numpy.tan>`.
735
+
736
+ See its docstring for more information.
737
+ """
738
+ if x.dtype not in _floating_dtypes:
739
+ raise TypeError("Only floating-point dtypes are allowed in tan")
740
+ return Array._new(np.tan(x._array))
741
+
742
+
743
+ def tanh(x: Array, /) -> Array:
744
+ """
745
+ Array API compatible wrapper for :py:func:`np.tanh <numpy.tanh>`.
746
+
747
+ See its docstring for more information.
748
+ """
749
+ if x.dtype not in _floating_dtypes:
750
+ raise TypeError("Only floating-point dtypes are allowed in tanh")
751
+ return Array._new(np.tanh(x._array))
752
+
753
+
754
+ def trunc(x: Array, /) -> Array:
755
+ """
756
+ Array API compatible wrapper for :py:func:`np.trunc <numpy.trunc>`.
757
+
758
+ See its docstring for more information.
759
+ """
760
+ if x.dtype not in _real_numeric_dtypes:
761
+ raise TypeError("Only real numeric dtypes are allowed in trunc")
762
+ if x.dtype in _integer_dtypes:
763
+ # Note: The return dtype of trunc is the same as the input
764
+ return x
765
+ return Array._new(np.trunc(x._array))
lib/python3.12/site-packages/numpy/array_api/_indexing_functions.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ._array_object import Array
4
+ from ._dtypes import _integer_dtypes
5
+
6
+ import numpy as np
7
+
8
+ def take(x: Array, indices: Array, /, *, axis: Optional[int] = None) -> Array:
9
+ """
10
+ Array API compatible wrapper for :py:func:`np.take <numpy.take>`.
11
+
12
+ See its docstring for more information.
13
+ """
14
+ if axis is None and x.ndim != 1:
15
+ raise ValueError("axis must be specified when ndim > 1")
16
+ if indices.dtype not in _integer_dtypes:
17
+ raise TypeError("Only integer dtypes are allowed in indexing")
18
+ if indices.ndim != 1:
19
+ raise ValueError("Only 1-dim indices array is supported")
20
+ return Array._new(np.take(x._array, indices._array, axis=axis))
lib/python3.12/site-packages/numpy/array_api/_manipulation_functions.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ._array_object import Array
4
+ from ._data_type_functions import result_type
5
+
6
+ from typing import List, Optional, Tuple, Union
7
+
8
+ import numpy as np
9
+
10
+ # Note: the function name is different here
11
+ def concat(
12
+ arrays: Union[Tuple[Array, ...], List[Array]], /, *, axis: Optional[int] = 0
13
+ ) -> Array:
14
+ """
15
+ Array API compatible wrapper for :py:func:`np.concatenate <numpy.concatenate>`.
16
+
17
+ See its docstring for more information.
18
+ """
19
+ # Note: Casting rules here are different from the np.concatenate default
20
+ # (no for scalars with axis=None, no cross-kind casting)
21
+ dtype = result_type(*arrays)
22
+ arrays = tuple(a._array for a in arrays)
23
+ return Array._new(np.concatenate(arrays, axis=axis, dtype=dtype))
24
+
25
+
26
+ def expand_dims(x: Array, /, *, axis: int) -> Array:
27
+ """
28
+ Array API compatible wrapper for :py:func:`np.expand_dims <numpy.expand_dims>`.
29
+
30
+ See its docstring for more information.
31
+ """
32
+ return Array._new(np.expand_dims(x._array, axis))
33
+
34
+
35
+ def flip(x: Array, /, *, axis: Optional[Union[int, Tuple[int, ...]]] = None) -> Array:
36
+ """
37
+ Array API compatible wrapper for :py:func:`np.flip <numpy.flip>`.
38
+
39
+ See its docstring for more information.
40
+ """
41
+ return Array._new(np.flip(x._array, axis=axis))
42
+
43
+
44
+ # Note: The function name is different here (see also matrix_transpose).
45
+ # Unlike transpose(), the axes argument is required.
46
+ def permute_dims(x: Array, /, axes: Tuple[int, ...]) -> Array:
47
+ """
48
+ Array API compatible wrapper for :py:func:`np.transpose <numpy.transpose>`.
49
+
50
+ See its docstring for more information.
51
+ """
52
+ return Array._new(np.transpose(x._array, axes))
53
+
54
+
55
+ # Note: the optional argument is called 'shape', not 'newshape'
56
+ def reshape(x: Array,
57
+ /,
58
+ shape: Tuple[int, ...],
59
+ *,
60
+ copy: Optional[Bool] = None) -> Array:
61
+ """
62
+ Array API compatible wrapper for :py:func:`np.reshape <numpy.reshape>`.
63
+
64
+ See its docstring for more information.
65
+ """
66
+
67
+ data = x._array
68
+ if copy:
69
+ data = np.copy(data)
70
+
71
+ reshaped = np.reshape(data, shape)
72
+
73
+ if copy is False and not np.shares_memory(data, reshaped):
74
+ raise AttributeError("Incompatible shape for in-place modification.")
75
+
76
+ return Array._new(reshaped)
77
+
78
+
79
+ def roll(
80
+ x: Array,
81
+ /,
82
+ shift: Union[int, Tuple[int, ...]],
83
+ *,
84
+ axis: Optional[Union[int, Tuple[int, ...]]] = None,
85
+ ) -> Array:
86
+ """
87
+ Array API compatible wrapper for :py:func:`np.roll <numpy.roll>`.
88
+
89
+ See its docstring for more information.
90
+ """
91
+ return Array._new(np.roll(x._array, shift, axis=axis))
92
+
93
+
94
+ def squeeze(x: Array, /, axis: Union[int, Tuple[int, ...]]) -> Array:
95
+ """
96
+ Array API compatible wrapper for :py:func:`np.squeeze <numpy.squeeze>`.
97
+
98
+ See its docstring for more information.
99
+ """
100
+ return Array._new(np.squeeze(x._array, axis=axis))
101
+
102
+
103
+ def stack(arrays: Union[Tuple[Array, ...], List[Array]], /, *, axis: int = 0) -> Array:
104
+ """
105
+ Array API compatible wrapper for :py:func:`np.stack <numpy.stack>`.
106
+
107
+ See its docstring for more information.
108
+ """
109
+ # Call result type here just to raise on disallowed type combinations
110
+ result_type(*arrays)
111
+ arrays = tuple(a._array for a in arrays)
112
+ return Array._new(np.stack(arrays, axis=axis))
lib/python3.12/site-packages/numpy/array_api/_searching_functions.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ._array_object import Array
4
+ from ._dtypes import _result_type, _real_numeric_dtypes
5
+
6
+ from typing import Optional, Tuple
7
+
8
+ import numpy as np
9
+
10
+
11
+ def argmax(x: Array, /, *, axis: Optional[int] = None, keepdims: bool = False) -> Array:
12
+ """
13
+ Array API compatible wrapper for :py:func:`np.argmax <numpy.argmax>`.
14
+
15
+ See its docstring for more information.
16
+ """
17
+ if x.dtype not in _real_numeric_dtypes:
18
+ raise TypeError("Only real numeric dtypes are allowed in argmax")
19
+ return Array._new(np.asarray(np.argmax(x._array, axis=axis, keepdims=keepdims)))
20
+
21
+
22
+ def argmin(x: Array, /, *, axis: Optional[int] = None, keepdims: bool = False) -> Array:
23
+ """
24
+ Array API compatible wrapper for :py:func:`np.argmin <numpy.argmin>`.
25
+
26
+ See its docstring for more information.
27
+ """
28
+ if x.dtype not in _real_numeric_dtypes:
29
+ raise TypeError("Only real numeric dtypes are allowed in argmin")
30
+ return Array._new(np.asarray(np.argmin(x._array, axis=axis, keepdims=keepdims)))
31
+
32
+
33
+ def nonzero(x: Array, /) -> Tuple[Array, ...]:
34
+ """
35
+ Array API compatible wrapper for :py:func:`np.nonzero <numpy.nonzero>`.
36
+
37
+ See its docstring for more information.
38
+ """
39
+ return tuple(Array._new(i) for i in np.nonzero(x._array))
40
+
41
+
42
+ def where(condition: Array, x1: Array, x2: Array, /) -> Array:
43
+ """
44
+ Array API compatible wrapper for :py:func:`np.where <numpy.where>`.
45
+
46
+ See its docstring for more information.
47
+ """
48
+ # Call result type here just to raise on disallowed type combinations
49
+ _result_type(x1.dtype, x2.dtype)
50
+ x1, x2 = Array._normalize_two_args(x1, x2)
51
+ return Array._new(np.where(condition._array, x1._array, x2._array))
lib/python3.12/site-packages/numpy/array_api/_set_functions.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ._array_object import Array
4
+
5
+ from typing import NamedTuple
6
+
7
+ import numpy as np
8
+
9
+ # Note: np.unique() is split into four functions in the array API:
10
+ # unique_all, unique_counts, unique_inverse, and unique_values (this is done
11
+ # to remove polymorphic return types).
12
+
13
+ # Note: The various unique() functions are supposed to return multiple NaNs.
14
+ # This does not match the NumPy behavior, however, this is currently left as a
15
+ # TODO in this implementation as this behavior may be reverted in np.unique().
16
+ # See https://github.com/numpy/numpy/issues/20326.
17
+
18
+ # Note: The functions here return a namedtuple (np.unique() returns a normal
19
+ # tuple).
20
+
21
+ class UniqueAllResult(NamedTuple):
22
+ values: Array
23
+ indices: Array
24
+ inverse_indices: Array
25
+ counts: Array
26
+
27
+
28
+ class UniqueCountsResult(NamedTuple):
29
+ values: Array
30
+ counts: Array
31
+
32
+
33
+ class UniqueInverseResult(NamedTuple):
34
+ values: Array
35
+ inverse_indices: Array
36
+
37
+
38
+ def unique_all(x: Array, /) -> UniqueAllResult:
39
+ """
40
+ Array API compatible wrapper for :py:func:`np.unique <numpy.unique>`.
41
+
42
+ See its docstring for more information.
43
+ """
44
+ values, indices, inverse_indices, counts = np.unique(
45
+ x._array,
46
+ return_counts=True,
47
+ return_index=True,
48
+ return_inverse=True,
49
+ equal_nan=False,
50
+ )
51
+ # np.unique() flattens inverse indices, but they need to share x's shape
52
+ # See https://github.com/numpy/numpy/issues/20638
53
+ inverse_indices = inverse_indices.reshape(x.shape)
54
+ return UniqueAllResult(
55
+ Array._new(values),
56
+ Array._new(indices),
57
+ Array._new(inverse_indices),
58
+ Array._new(counts),
59
+ )
60
+
61
+
62
+ def unique_counts(x: Array, /) -> UniqueCountsResult:
63
+ res = np.unique(
64
+ x._array,
65
+ return_counts=True,
66
+ return_index=False,
67
+ return_inverse=False,
68
+ equal_nan=False,
69
+ )
70
+
71
+ return UniqueCountsResult(*[Array._new(i) for i in res])
72
+
73
+
74
+ def unique_inverse(x: Array, /) -> UniqueInverseResult:
75
+ """
76
+ Array API compatible wrapper for :py:func:`np.unique <numpy.unique>`.
77
+
78
+ See its docstring for more information.
79
+ """
80
+ values, inverse_indices = np.unique(
81
+ x._array,
82
+ return_counts=False,
83
+ return_index=False,
84
+ return_inverse=True,
85
+ equal_nan=False,
86
+ )
87
+ # np.unique() flattens inverse indices, but they need to share x's shape
88
+ # See https://github.com/numpy/numpy/issues/20638
89
+ inverse_indices = inverse_indices.reshape(x.shape)
90
+ return UniqueInverseResult(Array._new(values), Array._new(inverse_indices))
91
+
92
+
93
+ def unique_values(x: Array, /) -> Array:
94
+ """
95
+ Array API compatible wrapper for :py:func:`np.unique <numpy.unique>`.
96
+
97
+ See its docstring for more information.
98
+ """
99
+ res = np.unique(
100
+ x._array,
101
+ return_counts=False,
102
+ return_index=False,
103
+ return_inverse=False,
104
+ equal_nan=False,
105
+ )
106
+ return Array._new(res)
lib/python3.12/site-packages/numpy/array_api/_sorting_functions.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ._array_object import Array
4
+ from ._dtypes import _real_numeric_dtypes
5
+
6
+ import numpy as np
7
+
8
+
9
+ # Note: the descending keyword argument is new in this function
10
+ def argsort(
11
+ x: Array, /, *, axis: int = -1, descending: bool = False, stable: bool = True
12
+ ) -> Array:
13
+ """
14
+ Array API compatible wrapper for :py:func:`np.argsort <numpy.argsort>`.
15
+
16
+ See its docstring for more information.
17
+ """
18
+ if x.dtype not in _real_numeric_dtypes:
19
+ raise TypeError("Only real numeric dtypes are allowed in argsort")
20
+ # Note: this keyword argument is different, and the default is different.
21
+ kind = "stable" if stable else "quicksort"
22
+ if not descending:
23
+ res = np.argsort(x._array, axis=axis, kind=kind)
24
+ else:
25
+ # As NumPy has no native descending sort, we imitate it here. Note that
26
+ # simply flipping the results of np.argsort(x._array, ...) would not
27
+ # respect the relative order like it would in native descending sorts.
28
+ res = np.flip(
29
+ np.argsort(np.flip(x._array, axis=axis), axis=axis, kind=kind),
30
+ axis=axis,
31
+ )
32
+ # Rely on flip()/argsort() to validate axis
33
+ normalised_axis = axis if axis >= 0 else x.ndim + axis
34
+ max_i = x.shape[normalised_axis] - 1
35
+ res = max_i - res
36
+ return Array._new(res)
37
+
38
+ # Note: the descending keyword argument is new in this function
39
+ def sort(
40
+ x: Array, /, *, axis: int = -1, descending: bool = False, stable: bool = True
41
+ ) -> Array:
42
+ """
43
+ Array API compatible wrapper for :py:func:`np.sort <numpy.sort>`.
44
+
45
+ See its docstring for more information.
46
+ """
47
+ if x.dtype not in _real_numeric_dtypes:
48
+ raise TypeError("Only real numeric dtypes are allowed in sort")
49
+ # Note: this keyword argument is different, and the default is different.
50
+ kind = "stable" if stable else "quicksort"
51
+ res = np.sort(x._array, axis=axis, kind=kind)
52
+ if descending:
53
+ res = np.flip(res, axis=axis)
54
+ return Array._new(res)
lib/python3.12/site-packages/numpy/array_api/_statistical_functions.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ._dtypes import (
4
+ _real_floating_dtypes,
5
+ _real_numeric_dtypes,
6
+ _numeric_dtypes,
7
+ )
8
+ from ._array_object import Array
9
+ from ._dtypes import float32, float64, complex64, complex128
10
+
11
+ from typing import TYPE_CHECKING, Optional, Tuple, Union
12
+
13
+ if TYPE_CHECKING:
14
+ from ._typing import Dtype
15
+
16
+ import numpy as np
17
+
18
+
19
+ def max(
20
+ x: Array,
21
+ /,
22
+ *,
23
+ axis: Optional[Union[int, Tuple[int, ...]]] = None,
24
+ keepdims: bool = False,
25
+ ) -> Array:
26
+ if x.dtype not in _real_numeric_dtypes:
27
+ raise TypeError("Only real numeric dtypes are allowed in max")
28
+ return Array._new(np.max(x._array, axis=axis, keepdims=keepdims))
29
+
30
+
31
+ def mean(
32
+ x: Array,
33
+ /,
34
+ *,
35
+ axis: Optional[Union[int, Tuple[int, ...]]] = None,
36
+ keepdims: bool = False,
37
+ ) -> Array:
38
+ if x.dtype not in _real_floating_dtypes:
39
+ raise TypeError("Only real floating-point dtypes are allowed in mean")
40
+ return Array._new(np.mean(x._array, axis=axis, keepdims=keepdims))
41
+
42
+
43
+ def min(
44
+ x: Array,
45
+ /,
46
+ *,
47
+ axis: Optional[Union[int, Tuple[int, ...]]] = None,
48
+ keepdims: bool = False,
49
+ ) -> Array:
50
+ if x.dtype not in _real_numeric_dtypes:
51
+ raise TypeError("Only real numeric dtypes are allowed in min")
52
+ return Array._new(np.min(x._array, axis=axis, keepdims=keepdims))
53
+
54
+
55
+ def prod(
56
+ x: Array,
57
+ /,
58
+ *,
59
+ axis: Optional[Union[int, Tuple[int, ...]]] = None,
60
+ dtype: Optional[Dtype] = None,
61
+ keepdims: bool = False,
62
+ ) -> Array:
63
+ if x.dtype not in _numeric_dtypes:
64
+ raise TypeError("Only numeric dtypes are allowed in prod")
65
+ # Note: sum() and prod() always upcast for dtype=None. `np.prod` does that
66
+ # for integers, but not for float32 or complex64, so we need to
67
+ # special-case it here
68
+ if dtype is None:
69
+ if x.dtype == float32:
70
+ dtype = float64
71
+ elif x.dtype == complex64:
72
+ dtype = complex128
73
+ return Array._new(np.prod(x._array, dtype=dtype, axis=axis, keepdims=keepdims))
74
+
75
+
76
+ def std(
77
+ x: Array,
78
+ /,
79
+ *,
80
+ axis: Optional[Union[int, Tuple[int, ...]]] = None,
81
+ correction: Union[int, float] = 0.0,
82
+ keepdims: bool = False,
83
+ ) -> Array:
84
+ # Note: the keyword argument correction is different here
85
+ if x.dtype not in _real_floating_dtypes:
86
+ raise TypeError("Only real floating-point dtypes are allowed in std")
87
+ return Array._new(np.std(x._array, axis=axis, ddof=correction, keepdims=keepdims))
88
+
89
+
90
+ def sum(
91
+ x: Array,
92
+ /,
93
+ *,
94
+ axis: Optional[Union[int, Tuple[int, ...]]] = None,
95
+ dtype: Optional[Dtype] = None,
96
+ keepdims: bool = False,
97
+ ) -> Array:
98
+ if x.dtype not in _numeric_dtypes:
99
+ raise TypeError("Only numeric dtypes are allowed in sum")
100
+ # Note: sum() and prod() always upcast for dtype=None. `np.sum` does that
101
+ # for integers, but not for float32 or complex64, so we need to
102
+ # special-case it here
103
+ if dtype is None:
104
+ if x.dtype == float32:
105
+ dtype = float64
106
+ elif x.dtype == complex64:
107
+ dtype = complex128
108
+ return Array._new(np.sum(x._array, axis=axis, dtype=dtype, keepdims=keepdims))
109
+
110
+
111
+ def var(
112
+ x: Array,
113
+ /,
114
+ *,
115
+ axis: Optional[Union[int, Tuple[int, ...]]] = None,
116
+ correction: Union[int, float] = 0.0,
117
+ keepdims: bool = False,
118
+ ) -> Array:
119
+ # Note: the keyword argument correction is different here
120
+ if x.dtype not in _real_floating_dtypes:
121
+ raise TypeError("Only real floating-point dtypes are allowed in var")
122
+ return Array._new(np.var(x._array, axis=axis, ddof=correction, keepdims=keepdims))
lib/python3.12/site-packages/numpy/array_api/_typing.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This file defines the types for type annotations.
3
+
4
+ These names aren't part of the module namespace, but they are used in the
5
+ annotations in the function signatures. The functions in the module are only
6
+ valid for inputs that match the given type annotations.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ __all__ = [
12
+ "Array",
13
+ "Device",
14
+ "Dtype",
15
+ "SupportsDLPack",
16
+ "SupportsBufferProtocol",
17
+ "PyCapsule",
18
+ ]
19
+
20
+ import sys
21
+
22
+ from typing import (
23
+ Any,
24
+ Literal,
25
+ Sequence,
26
+ Type,
27
+ Union,
28
+ TypeVar,
29
+ Protocol,
30
+ )
31
+
32
+ from ._array_object import Array
33
+ from numpy import (
34
+ dtype,
35
+ int8,
36
+ int16,
37
+ int32,
38
+ int64,
39
+ uint8,
40
+ uint16,
41
+ uint32,
42
+ uint64,
43
+ float32,
44
+ float64,
45
+ )
46
+
47
+ _T_co = TypeVar("_T_co", covariant=True)
48
+
49
+ class NestedSequence(Protocol[_T_co]):
50
+ def __getitem__(self, key: int, /) -> _T_co | NestedSequence[_T_co]: ...
51
+ def __len__(self, /) -> int: ...
52
+
53
+ Device = Literal["cpu"]
54
+
55
+ Dtype = dtype[Union[
56
+ int8,
57
+ int16,
58
+ int32,
59
+ int64,
60
+ uint8,
61
+ uint16,
62
+ uint32,
63
+ uint64,
64
+ float32,
65
+ float64,
66
+ ]]
67
+
68
+ if sys.version_info >= (3, 12):
69
+ from collections.abc import Buffer as SupportsBufferProtocol
70
+ else:
71
+ SupportsBufferProtocol = Any
72
+
73
+ PyCapsule = Any
74
+
75
+ class SupportsDLPack(Protocol):
76
+ def __dlpack__(self, /, *, stream: None = ...) -> PyCapsule: ...
lib/python3.12/site-packages/numpy/array_api/_utility_functions.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ._array_object import Array
4
+
5
+ from typing import Optional, Tuple, Union
6
+
7
+ import numpy as np
8
+
9
+
10
+ def all(
11
+ x: Array,
12
+ /,
13
+ *,
14
+ axis: Optional[Union[int, Tuple[int, ...]]] = None,
15
+ keepdims: bool = False,
16
+ ) -> Array:
17
+ """
18
+ Array API compatible wrapper for :py:func:`np.all <numpy.all>`.
19
+
20
+ See its docstring for more information.
21
+ """
22
+ return Array._new(np.asarray(np.all(x._array, axis=axis, keepdims=keepdims)))
23
+
24
+
25
+ def any(
26
+ x: Array,
27
+ /,
28
+ *,
29
+ axis: Optional[Union[int, Tuple[int, ...]]] = None,
30
+ keepdims: bool = False,
31
+ ) -> Array:
32
+ """
33
+ Array API compatible wrapper for :py:func:`np.any <numpy.any>`.
34
+
35
+ See its docstring for more information.
36
+ """
37
+ return Array._new(np.asarray(np.any(x._array, axis=axis, keepdims=keepdims)))
lib/python3.12/site-packages/numpy/array_api/linalg.py ADDED
@@ -0,0 +1,466 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from ._dtypes import (
4
+ _floating_dtypes,
5
+ _numeric_dtypes,
6
+ float32,
7
+ float64,
8
+ complex64,
9
+ complex128
10
+ )
11
+ from ._manipulation_functions import reshape
12
+ from ._elementwise_functions import conj
13
+ from ._array_object import Array
14
+
15
+ from ..core.numeric import normalize_axis_tuple
16
+
17
+ from typing import TYPE_CHECKING
18
+ if TYPE_CHECKING:
19
+ from ._typing import Literal, Optional, Sequence, Tuple, Union, Dtype
20
+
21
+ from typing import NamedTuple
22
+
23
+ import numpy.linalg
24
+ import numpy as np
25
+
26
+ class EighResult(NamedTuple):
27
+ eigenvalues: Array
28
+ eigenvectors: Array
29
+
30
+ class QRResult(NamedTuple):
31
+ Q: Array
32
+ R: Array
33
+
34
+ class SlogdetResult(NamedTuple):
35
+ sign: Array
36
+ logabsdet: Array
37
+
38
+ class SVDResult(NamedTuple):
39
+ U: Array
40
+ S: Array
41
+ Vh: Array
42
+
43
+ # Note: the inclusion of the upper keyword is different from
44
+ # np.linalg.cholesky, which does not have it.
45
+ def cholesky(x: Array, /, *, upper: bool = False) -> Array:
46
+ """
47
+ Array API compatible wrapper for :py:func:`np.linalg.cholesky <numpy.linalg.cholesky>`.
48
+
49
+ See its docstring for more information.
50
+ """
51
+ # Note: the restriction to floating-point dtypes only is different from
52
+ # np.linalg.cholesky.
53
+ if x.dtype not in _floating_dtypes:
54
+ raise TypeError('Only floating-point dtypes are allowed in cholesky')
55
+ L = np.linalg.cholesky(x._array)
56
+ if upper:
57
+ U = Array._new(L).mT
58
+ if U.dtype in [complex64, complex128]:
59
+ U = conj(U)
60
+ return U
61
+ return Array._new(L)
62
+
63
+ # Note: cross is the numpy top-level namespace, not np.linalg
64
+ def cross(x1: Array, x2: Array, /, *, axis: int = -1) -> Array:
65
+ """
66
+ Array API compatible wrapper for :py:func:`np.cross <numpy.cross>`.
67
+
68
+ See its docstring for more information.
69
+ """
70
+ if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
71
+ raise TypeError('Only numeric dtypes are allowed in cross')
72
+ # Note: this is different from np.cross(), which broadcasts
73
+ if x1.shape != x2.shape:
74
+ raise ValueError('x1 and x2 must have the same shape')
75
+ if x1.ndim == 0:
76
+ raise ValueError('cross() requires arrays of dimension at least 1')
77
+ # Note: this is different from np.cross(), which allows dimension 2
78
+ if x1.shape[axis] != 3:
79
+ raise ValueError('cross() dimension must equal 3')
80
+ return Array._new(np.cross(x1._array, x2._array, axis=axis))
81
+
82
+ def det(x: Array, /) -> Array:
83
+ """
84
+ Array API compatible wrapper for :py:func:`np.linalg.det <numpy.linalg.det>`.
85
+
86
+ See its docstring for more information.
87
+ """
88
+ # Note: the restriction to floating-point dtypes only is different from
89
+ # np.linalg.det.
90
+ if x.dtype not in _floating_dtypes:
91
+ raise TypeError('Only floating-point dtypes are allowed in det')
92
+ return Array._new(np.linalg.det(x._array))
93
+
94
+ # Note: diagonal is the numpy top-level namespace, not np.linalg
95
+ def diagonal(x: Array, /, *, offset: int = 0) -> Array:
96
+ """
97
+ Array API compatible wrapper for :py:func:`np.diagonal <numpy.diagonal>`.
98
+
99
+ See its docstring for more information.
100
+ """
101
+ # Note: diagonal always operates on the last two axes, whereas np.diagonal
102
+ # operates on the first two axes by default
103
+ return Array._new(np.diagonal(x._array, offset=offset, axis1=-2, axis2=-1))
104
+
105
+
106
+ def eigh(x: Array, /) -> EighResult:
107
+ """
108
+ Array API compatible wrapper for :py:func:`np.linalg.eigh <numpy.linalg.eigh>`.
109
+
110
+ See its docstring for more information.
111
+ """
112
+ # Note: the restriction to floating-point dtypes only is different from
113
+ # np.linalg.eigh.
114
+ if x.dtype not in _floating_dtypes:
115
+ raise TypeError('Only floating-point dtypes are allowed in eigh')
116
+
117
+ # Note: the return type here is a namedtuple, which is different from
118
+ # np.eigh, which only returns a tuple.
119
+ return EighResult(*map(Array._new, np.linalg.eigh(x._array)))
120
+
121
+
122
+ def eigvalsh(x: Array, /) -> Array:
123
+ """
124
+ Array API compatible wrapper for :py:func:`np.linalg.eigvalsh <numpy.linalg.eigvalsh>`.
125
+
126
+ See its docstring for more information.
127
+ """
128
+ # Note: the restriction to floating-point dtypes only is different from
129
+ # np.linalg.eigvalsh.
130
+ if x.dtype not in _floating_dtypes:
131
+ raise TypeError('Only floating-point dtypes are allowed in eigvalsh')
132
+
133
+ return Array._new(np.linalg.eigvalsh(x._array))
134
+
135
+ def inv(x: Array, /) -> Array:
136
+ """
137
+ Array API compatible wrapper for :py:func:`np.linalg.inv <numpy.linalg.inv>`.
138
+
139
+ See its docstring for more information.
140
+ """
141
+ # Note: the restriction to floating-point dtypes only is different from
142
+ # np.linalg.inv.
143
+ if x.dtype not in _floating_dtypes:
144
+ raise TypeError('Only floating-point dtypes are allowed in inv')
145
+
146
+ return Array._new(np.linalg.inv(x._array))
147
+
148
+
149
+ # Note: matmul is the numpy top-level namespace but not in np.linalg
150
+ def matmul(x1: Array, x2: Array, /) -> Array:
151
+ """
152
+ Array API compatible wrapper for :py:func:`np.matmul <numpy.matmul>`.
153
+
154
+ See its docstring for more information.
155
+ """
156
+ # Note: the restriction to numeric dtypes only is different from
157
+ # np.matmul.
158
+ if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
159
+ raise TypeError('Only numeric dtypes are allowed in matmul')
160
+
161
+ return Array._new(np.matmul(x1._array, x2._array))
162
+
163
+
164
+ # Note: the name here is different from norm(). The array API norm is split
165
+ # into matrix_norm and vector_norm().
166
+
167
+ # The type for ord should be Optional[Union[int, float, Literal[np.inf,
168
+ # -np.inf, 'fro', 'nuc']]], but Literal does not support floating-point
169
+ # literals.
170
+ def matrix_norm(x: Array, /, *, keepdims: bool = False, ord: Optional[Union[int, float, Literal['fro', 'nuc']]] = 'fro') -> Array:
171
+ """
172
+ Array API compatible wrapper for :py:func:`np.linalg.norm <numpy.linalg.norm>`.
173
+
174
+ See its docstring for more information.
175
+ """
176
+ # Note: the restriction to floating-point dtypes only is different from
177
+ # np.linalg.norm.
178
+ if x.dtype not in _floating_dtypes:
179
+ raise TypeError('Only floating-point dtypes are allowed in matrix_norm')
180
+
181
+ return Array._new(np.linalg.norm(x._array, axis=(-2, -1), keepdims=keepdims, ord=ord))
182
+
183
+
184
+ def matrix_power(x: Array, n: int, /) -> Array:
185
+ """
186
+ Array API compatible wrapper for :py:func:`np.matrix_power <numpy.matrix_power>`.
187
+
188
+ See its docstring for more information.
189
+ """
190
+ # Note: the restriction to floating-point dtypes only is different from
191
+ # np.linalg.matrix_power.
192
+ if x.dtype not in _floating_dtypes:
193
+ raise TypeError('Only floating-point dtypes are allowed for the first argument of matrix_power')
194
+
195
+ # np.matrix_power already checks if n is an integer
196
+ return Array._new(np.linalg.matrix_power(x._array, n))
197
+
198
+ # Note: the keyword argument name rtol is different from np.linalg.matrix_rank
199
+ def matrix_rank(x: Array, /, *, rtol: Optional[Union[float, Array]] = None) -> Array:
200
+ """
201
+ Array API compatible wrapper for :py:func:`np.matrix_rank <numpy.matrix_rank>`.
202
+
203
+ See its docstring for more information.
204
+ """
205
+ # Note: this is different from np.linalg.matrix_rank, which supports 1
206
+ # dimensional arrays.
207
+ if x.ndim < 2:
208
+ raise np.linalg.LinAlgError("1-dimensional array given. Array must be at least two-dimensional")
209
+ S = np.linalg.svd(x._array, compute_uv=False)
210
+ if rtol is None:
211
+ tol = S.max(axis=-1, keepdims=True) * max(x.shape[-2:]) * np.finfo(S.dtype).eps
212
+ else:
213
+ if isinstance(rtol, Array):
214
+ rtol = rtol._array
215
+ # Note: this is different from np.linalg.matrix_rank, which does not multiply
216
+ # the tolerance by the largest singular value.
217
+ tol = S.max(axis=-1, keepdims=True)*np.asarray(rtol)[..., np.newaxis]
218
+ return Array._new(np.count_nonzero(S > tol, axis=-1))
219
+
220
+
221
+ # Note: this function is new in the array API spec. Unlike transpose, it only
222
+ # transposes the last two axes.
223
+ def matrix_transpose(x: Array, /) -> Array:
224
+ if x.ndim < 2:
225
+ raise ValueError("x must be at least 2-dimensional for matrix_transpose")
226
+ return Array._new(np.swapaxes(x._array, -1, -2))
227
+
228
+ # Note: outer is the numpy top-level namespace, not np.linalg
229
+ def outer(x1: Array, x2: Array, /) -> Array:
230
+ """
231
+ Array API compatible wrapper for :py:func:`np.outer <numpy.outer>`.
232
+
233
+ See its docstring for more information.
234
+ """
235
+ # Note: the restriction to numeric dtypes only is different from
236
+ # np.outer.
237
+ if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
238
+ raise TypeError('Only numeric dtypes are allowed in outer')
239
+
240
+ # Note: the restriction to only 1-dim arrays is different from np.outer
241
+ if x1.ndim != 1 or x2.ndim != 1:
242
+ raise ValueError('The input arrays to outer must be 1-dimensional')
243
+
244
+ return Array._new(np.outer(x1._array, x2._array))
245
+
246
+ # Note: the keyword argument name rtol is different from np.linalg.pinv
247
+ def pinv(x: Array, /, *, rtol: Optional[Union[float, Array]] = None) -> Array:
248
+ """
249
+ Array API compatible wrapper for :py:func:`np.linalg.pinv <numpy.linalg.pinv>`.
250
+
251
+ See its docstring for more information.
252
+ """
253
+ # Note: the restriction to floating-point dtypes only is different from
254
+ # np.linalg.pinv.
255
+ if x.dtype not in _floating_dtypes:
256
+ raise TypeError('Only floating-point dtypes are allowed in pinv')
257
+
258
+ # Note: this is different from np.linalg.pinv, which does not multiply the
259
+ # default tolerance by max(M, N).
260
+ if rtol is None:
261
+ rtol = max(x.shape[-2:]) * np.finfo(x.dtype).eps
262
+ return Array._new(np.linalg.pinv(x._array, rcond=rtol))
263
+
264
+ def qr(x: Array, /, *, mode: Literal['reduced', 'complete'] = 'reduced') -> QRResult:
265
+ """
266
+ Array API compatible wrapper for :py:func:`np.linalg.qr <numpy.linalg.qr>`.
267
+
268
+ See its docstring for more information.
269
+ """
270
+ # Note: the restriction to floating-point dtypes only is different from
271
+ # np.linalg.qr.
272
+ if x.dtype not in _floating_dtypes:
273
+ raise TypeError('Only floating-point dtypes are allowed in qr')
274
+
275
+ # Note: the return type here is a namedtuple, which is different from
276
+ # np.linalg.qr, which only returns a tuple.
277
+ return QRResult(*map(Array._new, np.linalg.qr(x._array, mode=mode)))
278
+
279
+ def slogdet(x: Array, /) -> SlogdetResult:
280
+ """
281
+ Array API compatible wrapper for :py:func:`np.linalg.slogdet <numpy.linalg.slogdet>`.
282
+
283
+ See its docstring for more information.
284
+ """
285
+ # Note: the restriction to floating-point dtypes only is different from
286
+ # np.linalg.slogdet.
287
+ if x.dtype not in _floating_dtypes:
288
+ raise TypeError('Only floating-point dtypes are allowed in slogdet')
289
+
290
+ # Note: the return type here is a namedtuple, which is different from
291
+ # np.linalg.slogdet, which only returns a tuple.
292
+ return SlogdetResult(*map(Array._new, np.linalg.slogdet(x._array)))
293
+
294
+ # Note: unlike np.linalg.solve, the array API solve() only accepts x2 as a
295
+ # vector when it is exactly 1-dimensional. All other cases treat x2 as a stack
296
+ # of matrices. The np.linalg.solve behavior of allowing stacks of both
297
+ # matrices and vectors is ambiguous c.f.
298
+ # https://github.com/numpy/numpy/issues/15349 and
299
+ # https://github.com/data-apis/array-api/issues/285.
300
+
301
+ # To workaround this, the below is the code from np.linalg.solve except
302
+ # only calling solve1 in the exactly 1D case.
303
+ def _solve(a, b):
304
+ from ..linalg.linalg import (_makearray, _assert_stacked_2d,
305
+ _assert_stacked_square, _commonType,
306
+ isComplexType, get_linalg_error_extobj,
307
+ _raise_linalgerror_singular)
308
+ from ..linalg import _umath_linalg
309
+
310
+ a, _ = _makearray(a)
311
+ _assert_stacked_2d(a)
312
+ _assert_stacked_square(a)
313
+ b, wrap = _makearray(b)
314
+ t, result_t = _commonType(a, b)
315
+
316
+ # This part is different from np.linalg.solve
317
+ if b.ndim == 1:
318
+ gufunc = _umath_linalg.solve1
319
+ else:
320
+ gufunc = _umath_linalg.solve
321
+
322
+ # This does nothing currently but is left in because it will be relevant
323
+ # when complex dtype support is added to the spec in 2022.
324
+ signature = 'DD->D' if isComplexType(t) else 'dd->d'
325
+ with np.errstate(call=_raise_linalgerror_singular, invalid='call',
326
+ over='ignore', divide='ignore', under='ignore'):
327
+ r = gufunc(a, b, signature=signature)
328
+
329
+ return wrap(r.astype(result_t, copy=False))
330
+
331
+ def solve(x1: Array, x2: Array, /) -> Array:
332
+ """
333
+ Array API compatible wrapper for :py:func:`np.linalg.solve <numpy.linalg.solve>`.
334
+
335
+ See its docstring for more information.
336
+ """
337
+ # Note: the restriction to floating-point dtypes only is different from
338
+ # np.linalg.solve.
339
+ if x1.dtype not in _floating_dtypes or x2.dtype not in _floating_dtypes:
340
+ raise TypeError('Only floating-point dtypes are allowed in solve')
341
+
342
+ return Array._new(_solve(x1._array, x2._array))
343
+
344
+ def svd(x: Array, /, *, full_matrices: bool = True) -> SVDResult:
345
+ """
346
+ Array API compatible wrapper for :py:func:`np.linalg.svd <numpy.linalg.svd>`.
347
+
348
+ See its docstring for more information.
349
+ """
350
+ # Note: the restriction to floating-point dtypes only is different from
351
+ # np.linalg.svd.
352
+ if x.dtype not in _floating_dtypes:
353
+ raise TypeError('Only floating-point dtypes are allowed in svd')
354
+
355
+ # Note: the return type here is a namedtuple, which is different from
356
+ # np.svd, which only returns a tuple.
357
+ return SVDResult(*map(Array._new, np.linalg.svd(x._array, full_matrices=full_matrices)))
358
+
359
+ # Note: svdvals is not in NumPy (but it is in SciPy). It is equivalent to
360
+ # np.linalg.svd(compute_uv=False).
361
+ def svdvals(x: Array, /) -> Union[Array, Tuple[Array, ...]]:
362
+ if x.dtype not in _floating_dtypes:
363
+ raise TypeError('Only floating-point dtypes are allowed in svdvals')
364
+ return Array._new(np.linalg.svd(x._array, compute_uv=False))
365
+
366
+ # Note: tensordot is the numpy top-level namespace but not in np.linalg
367
+
368
+ # Note: axes must be a tuple, unlike np.tensordot where it can be an array or array-like.
369
+ def tensordot(x1: Array, x2: Array, /, *, axes: Union[int, Tuple[Sequence[int], Sequence[int]]] = 2) -> Array:
370
+ # Note: the restriction to numeric dtypes only is different from
371
+ # np.tensordot.
372
+ if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
373
+ raise TypeError('Only numeric dtypes are allowed in tensordot')
374
+
375
+ return Array._new(np.tensordot(x1._array, x2._array, axes=axes))
376
+
377
+ # Note: trace is the numpy top-level namespace, not np.linalg
378
+ def trace(x: Array, /, *, offset: int = 0, dtype: Optional[Dtype] = None) -> Array:
379
+ """
380
+ Array API compatible wrapper for :py:func:`np.trace <numpy.trace>`.
381
+
382
+ See its docstring for more information.
383
+ """
384
+ if x.dtype not in _numeric_dtypes:
385
+ raise TypeError('Only numeric dtypes are allowed in trace')
386
+
387
+ # Note: trace() works the same as sum() and prod() (see
388
+ # _statistical_functions.py)
389
+ if dtype is None:
390
+ if x.dtype == float32:
391
+ dtype = float64
392
+ elif x.dtype == complex64:
393
+ dtype = complex128
394
+ # Note: trace always operates on the last two axes, whereas np.trace
395
+ # operates on the first two axes by default
396
+ return Array._new(np.asarray(np.trace(x._array, offset=offset, axis1=-2, axis2=-1, dtype=dtype)))
397
+
398
+ # Note: vecdot is not in NumPy
399
+ def vecdot(x1: Array, x2: Array, /, *, axis: int = -1) -> Array:
400
+ if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
401
+ raise TypeError('Only numeric dtypes are allowed in vecdot')
402
+ ndim = max(x1.ndim, x2.ndim)
403
+ x1_shape = (1,)*(ndim - x1.ndim) + tuple(x1.shape)
404
+ x2_shape = (1,)*(ndim - x2.ndim) + tuple(x2.shape)
405
+ if x1_shape[axis] != x2_shape[axis]:
406
+ raise ValueError("x1 and x2 must have the same size along the given axis")
407
+
408
+ x1_, x2_ = np.broadcast_arrays(x1._array, x2._array)
409
+ x1_ = np.moveaxis(x1_, axis, -1)
410
+ x2_ = np.moveaxis(x2_, axis, -1)
411
+
412
+ res = x1_[..., None, :] @ x2_[..., None]
413
+ return Array._new(res[..., 0, 0])
414
+
415
+
416
+ # Note: the name here is different from norm(). The array API norm is split
417
+ # into matrix_norm and vector_norm().
418
+
419
+ # The type for ord should be Optional[Union[int, float, Literal[np.inf,
420
+ # -np.inf]]] but Literal does not support floating-point literals.
421
+ def vector_norm(x: Array, /, *, axis: Optional[Union[int, Tuple[int, ...]]] = None, keepdims: bool = False, ord: Optional[Union[int, float]] = 2) -> Array:
422
+ """
423
+ Array API compatible wrapper for :py:func:`np.linalg.norm <numpy.linalg.norm>`.
424
+
425
+ See its docstring for more information.
426
+ """
427
+ # Note: the restriction to floating-point dtypes only is different from
428
+ # np.linalg.norm.
429
+ if x.dtype not in _floating_dtypes:
430
+ raise TypeError('Only floating-point dtypes are allowed in norm')
431
+
432
+ # np.linalg.norm tries to do a matrix norm whenever axis is a 2-tuple or
433
+ # when axis=None and the input is 2-D, so to force a vector norm, we make
434
+ # it so the input is 1-D (for axis=None), or reshape so that norm is done
435
+ # on a single dimension.
436
+ a = x._array
437
+ if axis is None:
438
+ # Note: np.linalg.norm() doesn't handle 0-D arrays
439
+ a = a.ravel()
440
+ _axis = 0
441
+ elif isinstance(axis, tuple):
442
+ # Note: The axis argument supports any number of axes, whereas
443
+ # np.linalg.norm() only supports a single axis for vector norm.
444
+ normalized_axis = normalize_axis_tuple(axis, x.ndim)
445
+ rest = tuple(i for i in range(a.ndim) if i not in normalized_axis)
446
+ newshape = axis + rest
447
+ a = np.transpose(a, newshape).reshape(
448
+ (np.prod([a.shape[i] for i in axis], dtype=int), *[a.shape[i] for i in rest]))
449
+ _axis = 0
450
+ else:
451
+ _axis = axis
452
+
453
+ res = Array._new(np.linalg.norm(a, axis=_axis, ord=ord))
454
+
455
+ if keepdims:
456
+ # We can't reuse np.linalg.norm(keepdims) because of the reshape hacks
457
+ # above to avoid matrix norm logic.
458
+ shape = list(x.shape)
459
+ _axis = normalize_axis_tuple(range(x.ndim) if axis is None else axis, x.ndim)
460
+ for i in _axis:
461
+ shape[i] = 1
462
+ res = reshape(res, tuple(shape))
463
+
464
+ return res
465
+
466
+ __all__ = ['cholesky', 'cross', 'det', 'diagonal', 'eigh', 'eigvalsh', 'inv', 'matmul', 'matrix_norm', 'matrix_power', 'matrix_rank', 'matrix_transpose', 'outer', 'pinv', 'qr', 'slogdet', 'solve', 'svd', 'svdvals', 'tensordot', 'trace', 'vecdot', 'vector_norm']
lib/python3.12/site-packages/numpy/array_api/setup.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def configuration(parent_package="", top_path=None):
2
+ from numpy.distutils.misc_util import Configuration
3
+
4
+ config = Configuration("array_api", parent_package, top_path)
5
+ config.add_subpackage("tests")
6
+ return config
7
+
8
+
9
+ if __name__ == "__main__":
10
+ from numpy.distutils.core import setup
11
+
12
+ setup(configuration=configuration)
lib/python3.12/site-packages/numpy/array_api/tests/__init__.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ """
2
+ Tests for the array API namespace.
3
+
4
+ Note, full compliance with the array API can be tested with the official array API test
5
+ suite https://github.com/data-apis/array-api-tests. This test suite primarily
6
+ focuses on those things that are not tested by the official test suite.
7
+ """
lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (495 Bytes). View file
 
lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_array_object.cpython-312.pyc ADDED
Binary file (28.3 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_creation_functions.cpython-312.pyc ADDED
Binary file (13.6 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_data_type_functions.cpython-312.pyc ADDED
Binary file (2.35 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_elementwise_functions.cpython-312.pyc ADDED
Binary file (4.6 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_indexing_functions.cpython-312.pyc ADDED
Binary file (1.27 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_manipulation_functions.cpython-312.pyc ADDED
Binary file (2.68 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_set_functions.cpython-312.pyc ADDED
Binary file (1.23 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_sorting_functions.cpython-312.pyc ADDED
Binary file (1.23 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/tests/__pycache__/test_validation.cpython-312.pyc ADDED
Binary file (1.68 kB). View file
 
lib/python3.12/site-packages/numpy/array_api/tests/test_array_object.py ADDED
@@ -0,0 +1,395 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import operator
2
+
3
+ from numpy.testing import assert_raises, suppress_warnings
4
+ import numpy as np
5
+ import pytest
6
+
7
+ from .. import ones, asarray, reshape, result_type, all, equal
8
+ from .._array_object import Array
9
+ from .._dtypes import (
10
+ _all_dtypes,
11
+ _boolean_dtypes,
12
+ _real_floating_dtypes,
13
+ _floating_dtypes,
14
+ _complex_floating_dtypes,
15
+ _integer_dtypes,
16
+ _integer_or_boolean_dtypes,
17
+ _real_numeric_dtypes,
18
+ _numeric_dtypes,
19
+ int8,
20
+ int16,
21
+ int32,
22
+ int64,
23
+ uint64,
24
+ bool as bool_,
25
+ )
26
+
27
+
28
+ def test_validate_index():
29
+ # The indexing tests in the official array API test suite test that the
30
+ # array object correctly handles the subset of indices that are required
31
+ # by the spec. But the NumPy array API implementation specifically
32
+ # disallows any index not required by the spec, via Array._validate_index.
33
+ # This test focuses on testing that non-valid indices are correctly
34
+ # rejected. See
35
+ # https://data-apis.org/array-api/latest/API_specification/indexing.html
36
+ # and the docstring of Array._validate_index for the exact indexing
37
+ # behavior that should be allowed. This does not test indices that are
38
+ # already invalid in NumPy itself because Array will generally just pass
39
+ # such indices directly to the underlying np.ndarray.
40
+
41
+ a = ones((3, 4))
42
+
43
+ # Out of bounds slices are not allowed
44
+ assert_raises(IndexError, lambda: a[:4])
45
+ assert_raises(IndexError, lambda: a[:-4])
46
+ assert_raises(IndexError, lambda: a[:3:-1])
47
+ assert_raises(IndexError, lambda: a[:-5:-1])
48
+ assert_raises(IndexError, lambda: a[4:])
49
+ assert_raises(IndexError, lambda: a[-4:])
50
+ assert_raises(IndexError, lambda: a[4::-1])
51
+ assert_raises(IndexError, lambda: a[-4::-1])
52
+
53
+ assert_raises(IndexError, lambda: a[...,:5])
54
+ assert_raises(IndexError, lambda: a[...,:-5])
55
+ assert_raises(IndexError, lambda: a[...,:5:-1])
56
+ assert_raises(IndexError, lambda: a[...,:-6:-1])
57
+ assert_raises(IndexError, lambda: a[...,5:])
58
+ assert_raises(IndexError, lambda: a[...,-5:])
59
+ assert_raises(IndexError, lambda: a[...,5::-1])
60
+ assert_raises(IndexError, lambda: a[...,-5::-1])
61
+
62
+ # Boolean indices cannot be part of a larger tuple index
63
+ assert_raises(IndexError, lambda: a[a[:,0]==1,0])
64
+ assert_raises(IndexError, lambda: a[a[:,0]==1,...])
65
+ assert_raises(IndexError, lambda: a[..., a[0]==1])
66
+ assert_raises(IndexError, lambda: a[[True, True, True]])
67
+ assert_raises(IndexError, lambda: a[(True, True, True),])
68
+
69
+ # Integer array indices are not allowed (except for 0-D)
70
+ idx = asarray([[0, 1]])
71
+ assert_raises(IndexError, lambda: a[idx])
72
+ assert_raises(IndexError, lambda: a[idx,])
73
+ assert_raises(IndexError, lambda: a[[0, 1]])
74
+ assert_raises(IndexError, lambda: a[(0, 1), (0, 1)])
75
+ assert_raises(IndexError, lambda: a[[0, 1]])
76
+ assert_raises(IndexError, lambda: a[np.array([[0, 1]])])
77
+
78
+ # Multiaxis indices must contain exactly as many indices as dimensions
79
+ assert_raises(IndexError, lambda: a[()])
80
+ assert_raises(IndexError, lambda: a[0,])
81
+ assert_raises(IndexError, lambda: a[0])
82
+ assert_raises(IndexError, lambda: a[:])
83
+
84
+ def test_operators():
85
+ # For every operator, we test that it works for the required type
86
+ # combinations and raises TypeError otherwise
87
+ binary_op_dtypes = {
88
+ "__add__": "numeric",
89
+ "__and__": "integer_or_boolean",
90
+ "__eq__": "all",
91
+ "__floordiv__": "real numeric",
92
+ "__ge__": "real numeric",
93
+ "__gt__": "real numeric",
94
+ "__le__": "real numeric",
95
+ "__lshift__": "integer",
96
+ "__lt__": "real numeric",
97
+ "__mod__": "real numeric",
98
+ "__mul__": "numeric",
99
+ "__ne__": "all",
100
+ "__or__": "integer_or_boolean",
101
+ "__pow__": "numeric",
102
+ "__rshift__": "integer",
103
+ "__sub__": "numeric",
104
+ "__truediv__": "floating",
105
+ "__xor__": "integer_or_boolean",
106
+ }
107
+ # Recompute each time because of in-place ops
108
+ def _array_vals():
109
+ for d in _integer_dtypes:
110
+ yield asarray(1, dtype=d)
111
+ for d in _boolean_dtypes:
112
+ yield asarray(False, dtype=d)
113
+ for d in _floating_dtypes:
114
+ yield asarray(1.0, dtype=d)
115
+
116
+
117
+ BIG_INT = int(1e30)
118
+ for op, dtypes in binary_op_dtypes.items():
119
+ ops = [op]
120
+ if op not in ["__eq__", "__ne__", "__le__", "__ge__", "__lt__", "__gt__"]:
121
+ rop = "__r" + op[2:]
122
+ iop = "__i" + op[2:]
123
+ ops += [rop, iop]
124
+ for s in [1, 1.0, 1j, BIG_INT, False]:
125
+ for _op in ops:
126
+ for a in _array_vals():
127
+ # Test array op scalar. From the spec, the following combinations
128
+ # are supported:
129
+
130
+ # - Python bool for a bool array dtype,
131
+ # - a Python int within the bounds of the given dtype for integer array dtypes,
132
+ # - a Python int or float for real floating-point array dtypes
133
+ # - a Python int, float, or complex for complex floating-point array dtypes
134
+
135
+ if ((dtypes == "all"
136
+ or dtypes == "numeric" and a.dtype in _numeric_dtypes
137
+ or dtypes == "real numeric" and a.dtype in _real_numeric_dtypes
138
+ or dtypes == "integer" and a.dtype in _integer_dtypes
139
+ or dtypes == "integer_or_boolean" and a.dtype in _integer_or_boolean_dtypes
140
+ or dtypes == "boolean" and a.dtype in _boolean_dtypes
141
+ or dtypes == "floating" and a.dtype in _floating_dtypes
142
+ )
143
+ # bool is a subtype of int, which is why we avoid
144
+ # isinstance here.
145
+ and (a.dtype in _boolean_dtypes and type(s) == bool
146
+ or a.dtype in _integer_dtypes and type(s) == int
147
+ or a.dtype in _real_floating_dtypes and type(s) in [float, int]
148
+ or a.dtype in _complex_floating_dtypes and type(s) in [complex, float, int]
149
+ )):
150
+ if a.dtype in _integer_dtypes and s == BIG_INT:
151
+ assert_raises(OverflowError, lambda: getattr(a, _op)(s))
152
+ else:
153
+ # Only test for no error
154
+ with suppress_warnings() as sup:
155
+ # ignore warnings from pow(BIG_INT)
156
+ sup.filter(RuntimeWarning,
157
+ "invalid value encountered in power")
158
+ getattr(a, _op)(s)
159
+ else:
160
+ assert_raises(TypeError, lambda: getattr(a, _op)(s))
161
+
162
+ # Test array op array.
163
+ for _op in ops:
164
+ for x in _array_vals():
165
+ for y in _array_vals():
166
+ # See the promotion table in NEP 47 or the array
167
+ # API spec page on type promotion. Mixed kind
168
+ # promotion is not defined.
169
+ if (x.dtype == uint64 and y.dtype in [int8, int16, int32, int64]
170
+ or y.dtype == uint64 and x.dtype in [int8, int16, int32, int64]
171
+ or x.dtype in _integer_dtypes and y.dtype not in _integer_dtypes
172
+ or y.dtype in _integer_dtypes and x.dtype not in _integer_dtypes
173
+ or x.dtype in _boolean_dtypes and y.dtype not in _boolean_dtypes
174
+ or y.dtype in _boolean_dtypes and x.dtype not in _boolean_dtypes
175
+ or x.dtype in _floating_dtypes and y.dtype not in _floating_dtypes
176
+ or y.dtype in _floating_dtypes and x.dtype not in _floating_dtypes
177
+ ):
178
+ assert_raises(TypeError, lambda: getattr(x, _op)(y))
179
+ # Ensure in-place operators only promote to the same dtype as the left operand.
180
+ elif (
181
+ _op.startswith("__i")
182
+ and result_type(x.dtype, y.dtype) != x.dtype
183
+ ):
184
+ assert_raises(TypeError, lambda: getattr(x, _op)(y))
185
+ # Ensure only those dtypes that are required for every operator are allowed.
186
+ elif (dtypes == "all" and (x.dtype in _boolean_dtypes and y.dtype in _boolean_dtypes
187
+ or x.dtype in _numeric_dtypes and y.dtype in _numeric_dtypes)
188
+ or (dtypes == "real numeric" and x.dtype in _real_numeric_dtypes and y.dtype in _real_numeric_dtypes)
189
+ or (dtypes == "numeric" and x.dtype in _numeric_dtypes and y.dtype in _numeric_dtypes)
190
+ or dtypes == "integer" and x.dtype in _integer_dtypes and y.dtype in _integer_dtypes
191
+ or dtypes == "integer_or_boolean" and (x.dtype in _integer_dtypes and y.dtype in _integer_dtypes
192
+ or x.dtype in _boolean_dtypes and y.dtype in _boolean_dtypes)
193
+ or dtypes == "boolean" and x.dtype in _boolean_dtypes and y.dtype in _boolean_dtypes
194
+ or dtypes == "floating" and x.dtype in _floating_dtypes and y.dtype in _floating_dtypes
195
+ ):
196
+ getattr(x, _op)(y)
197
+ else:
198
+ assert_raises(TypeError, lambda: getattr(x, _op)(y))
199
+
200
+ unary_op_dtypes = {
201
+ "__abs__": "numeric",
202
+ "__invert__": "integer_or_boolean",
203
+ "__neg__": "numeric",
204
+ "__pos__": "numeric",
205
+ }
206
+ for op, dtypes in unary_op_dtypes.items():
207
+ for a in _array_vals():
208
+ if (
209
+ dtypes == "numeric"
210
+ and a.dtype in _numeric_dtypes
211
+ or dtypes == "integer_or_boolean"
212
+ and a.dtype in _integer_or_boolean_dtypes
213
+ ):
214
+ # Only test for no error
215
+ getattr(a, op)()
216
+ else:
217
+ assert_raises(TypeError, lambda: getattr(a, op)())
218
+
219
+ # Finally, matmul() must be tested separately, because it works a bit
220
+ # different from the other operations.
221
+ def _matmul_array_vals():
222
+ for a in _array_vals():
223
+ yield a
224
+ for d in _all_dtypes:
225
+ yield ones((3, 4), dtype=d)
226
+ yield ones((4, 2), dtype=d)
227
+ yield ones((4, 4), dtype=d)
228
+
229
+ # Scalars always error
230
+ for _op in ["__matmul__", "__rmatmul__", "__imatmul__"]:
231
+ for s in [1, 1.0, False]:
232
+ for a in _matmul_array_vals():
233
+ if (type(s) in [float, int] and a.dtype in _floating_dtypes
234
+ or type(s) == int and a.dtype in _integer_dtypes):
235
+ # Type promotion is valid, but @ is not allowed on 0-D
236
+ # inputs, so the error is a ValueError
237
+ assert_raises(ValueError, lambda: getattr(a, _op)(s))
238
+ else:
239
+ assert_raises(TypeError, lambda: getattr(a, _op)(s))
240
+
241
+ for x in _matmul_array_vals():
242
+ for y in _matmul_array_vals():
243
+ if (x.dtype == uint64 and y.dtype in [int8, int16, int32, int64]
244
+ or y.dtype == uint64 and x.dtype in [int8, int16, int32, int64]
245
+ or x.dtype in _integer_dtypes and y.dtype not in _integer_dtypes
246
+ or y.dtype in _integer_dtypes and x.dtype not in _integer_dtypes
247
+ or x.dtype in _floating_dtypes and y.dtype not in _floating_dtypes
248
+ or y.dtype in _floating_dtypes and x.dtype not in _floating_dtypes
249
+ or x.dtype in _boolean_dtypes
250
+ or y.dtype in _boolean_dtypes
251
+ ):
252
+ assert_raises(TypeError, lambda: x.__matmul__(y))
253
+ assert_raises(TypeError, lambda: y.__rmatmul__(x))
254
+ assert_raises(TypeError, lambda: x.__imatmul__(y))
255
+ elif x.shape == () or y.shape == () or x.shape[1] != y.shape[0]:
256
+ assert_raises(ValueError, lambda: x.__matmul__(y))
257
+ assert_raises(ValueError, lambda: y.__rmatmul__(x))
258
+ if result_type(x.dtype, y.dtype) != x.dtype:
259
+ assert_raises(TypeError, lambda: x.__imatmul__(y))
260
+ else:
261
+ assert_raises(ValueError, lambda: x.__imatmul__(y))
262
+ else:
263
+ x.__matmul__(y)
264
+ y.__rmatmul__(x)
265
+ if result_type(x.dtype, y.dtype) != x.dtype:
266
+ assert_raises(TypeError, lambda: x.__imatmul__(y))
267
+ elif y.shape[0] != y.shape[1]:
268
+ # This one fails because x @ y has a different shape from x
269
+ assert_raises(ValueError, lambda: x.__imatmul__(y))
270
+ else:
271
+ x.__imatmul__(y)
272
+
273
+
274
+ def test_python_scalar_construtors():
275
+ b = asarray(False)
276
+ i = asarray(0)
277
+ f = asarray(0.0)
278
+ c = asarray(0j)
279
+
280
+ assert bool(b) == False
281
+ assert int(i) == 0
282
+ assert float(f) == 0.0
283
+ assert operator.index(i) == 0
284
+
285
+ # bool/int/float/complex should only be allowed on 0-D arrays.
286
+ assert_raises(TypeError, lambda: bool(asarray([False])))
287
+ assert_raises(TypeError, lambda: int(asarray([0])))
288
+ assert_raises(TypeError, lambda: float(asarray([0.0])))
289
+ assert_raises(TypeError, lambda: complex(asarray([0j])))
290
+ assert_raises(TypeError, lambda: operator.index(asarray([0])))
291
+
292
+ # bool should work on all types of arrays
293
+ assert bool(b) is bool(i) is bool(f) is bool(c) is False
294
+
295
+ # int should fail on complex arrays
296
+ assert int(b) == int(i) == int(f) == 0
297
+ assert_raises(TypeError, lambda: int(c))
298
+
299
+ # float should fail on complex arrays
300
+ assert float(b) == float(i) == float(f) == 0.0
301
+ assert_raises(TypeError, lambda: float(c))
302
+
303
+ # complex should work on all types of arrays
304
+ assert complex(b) == complex(i) == complex(f) == complex(c) == 0j
305
+
306
+ # index should only work on integer arrays
307
+ assert operator.index(i) == 0
308
+ assert_raises(TypeError, lambda: operator.index(b))
309
+ assert_raises(TypeError, lambda: operator.index(f))
310
+ assert_raises(TypeError, lambda: operator.index(c))
311
+
312
+
313
+ def test_device_property():
314
+ a = ones((3, 4))
315
+ assert a.device == 'cpu'
316
+
317
+ assert all(equal(a.to_device('cpu'), a))
318
+ assert_raises(ValueError, lambda: a.to_device('gpu'))
319
+
320
+ assert all(equal(asarray(a, device='cpu'), a))
321
+ assert_raises(ValueError, lambda: asarray(a, device='gpu'))
322
+
323
+ def test_array_properties():
324
+ a = ones((1, 2, 3))
325
+ b = ones((2, 3))
326
+ assert_raises(ValueError, lambda: a.T)
327
+
328
+ assert isinstance(b.T, Array)
329
+ assert b.T.shape == (3, 2)
330
+
331
+ assert isinstance(a.mT, Array)
332
+ assert a.mT.shape == (1, 3, 2)
333
+ assert isinstance(b.mT, Array)
334
+ assert b.mT.shape == (3, 2)
335
+
336
+ def test___array__():
337
+ a = ones((2, 3), dtype=int16)
338
+ assert np.asarray(a) is a._array
339
+ b = np.asarray(a, dtype=np.float64)
340
+ assert np.all(np.equal(b, np.ones((2, 3), dtype=np.float64)))
341
+ assert b.dtype == np.float64
342
+
343
+ def test_allow_newaxis():
344
+ a = ones(5)
345
+ indexed_a = a[None, :]
346
+ assert indexed_a.shape == (1, 5)
347
+
348
+ def test_disallow_flat_indexing_with_newaxis():
349
+ a = ones((3, 3, 3))
350
+ with pytest.raises(IndexError):
351
+ a[None, 0, 0]
352
+
353
+ def test_disallow_mask_with_newaxis():
354
+ a = ones((3, 3, 3))
355
+ with pytest.raises(IndexError):
356
+ a[None, asarray(True)]
357
+
358
+ @pytest.mark.parametrize("shape", [(), (5,), (3, 3, 3)])
359
+ @pytest.mark.parametrize("index", ["string", False, True])
360
+ def test_error_on_invalid_index(shape, index):
361
+ a = ones(shape)
362
+ with pytest.raises(IndexError):
363
+ a[index]
364
+
365
+ def test_mask_0d_array_without_errors():
366
+ a = ones(())
367
+ a[asarray(True)]
368
+
369
+ @pytest.mark.parametrize(
370
+ "i", [slice(5), slice(5, 0), asarray(True), asarray([0, 1])]
371
+ )
372
+ def test_error_on_invalid_index_with_ellipsis(i):
373
+ a = ones((3, 3, 3))
374
+ with pytest.raises(IndexError):
375
+ a[..., i]
376
+ with pytest.raises(IndexError):
377
+ a[i, ...]
378
+
379
+ def test_array_keys_use_private_array():
380
+ """
381
+ Indexing operations convert array keys before indexing the internal array
382
+
383
+ Fails when array_api array keys are not converted into NumPy-proper arrays
384
+ in __getitem__(). This is achieved by passing array_api arrays with 0-sized
385
+ dimensions, which NumPy-proper treats erroneously - not sure why!
386
+
387
+ TODO: Find and use appropriate __setitem__() case.
388
+ """
389
+ a = ones((0, 0), dtype=bool_)
390
+ assert a[a].shape == (0,)
391
+
392
+ a = ones((0,), dtype=bool_)
393
+ key = ones((0, 0), dtype=bool_)
394
+ with pytest.raises(IndexError):
395
+ a[key]