array-api-strict 2.2__py3-none-any.whl → 2.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. array_api_strict/__init__.py +10 -7
  2. array_api_strict/_array_object.py +31 -19
  3. array_api_strict/_creation_functions.py +2 -0
  4. array_api_strict/_data_type_functions.py +34 -3
  5. array_api_strict/_dtypes.py +1 -0
  6. array_api_strict/_elementwise_functions.py +140 -471
  7. array_api_strict/_fft.py +31 -5
  8. array_api_strict/_flags.py +10 -8
  9. array_api_strict/_helpers.py +37 -0
  10. array_api_strict/_linear_algebra_functions.py +1 -1
  11. array_api_strict/_manipulation_functions.py +5 -0
  12. array_api_strict/_searching_functions.py +44 -5
  13. array_api_strict/_statistical_functions.py +42 -5
  14. array_api_strict/_version.py +16 -16
  15. array_api_strict/tests/test_array_object.py +146 -74
  16. array_api_strict/tests/test_creation_functions.py +7 -0
  17. array_api_strict/tests/test_data_type_functions.py +24 -4
  18. array_api_strict/tests/test_elementwise_functions.py +66 -8
  19. array_api_strict/tests/test_flags.py +29 -18
  20. array_api_strict/tests/test_manipulation_functions.py +1 -1
  21. array_api_strict/tests/test_searching_functions.py +24 -0
  22. array_api_strict/tests/test_statistical_functions.py +19 -1
  23. array_api_strict/tests/test_validation.py +1 -1
  24. array_api_strict-2.3.dist-info/METADATA +68 -0
  25. array_api_strict-2.3.dist-info/RECORD +43 -0
  26. {array_api_strict-2.2.dist-info → array_api_strict-2.3.dist-info}/WHEEL +1 -1
  27. array_api_strict-2.2.dist-info/METADATA +0 -37
  28. array_api_strict-2.2.dist-info/RECORD +0 -41
  29. {array_api_strict-2.2.dist-info → array_api_strict-2.3.dist-info}/LICENSE +0 -0
  30. {array_api_strict-2.2.dist-info → array_api_strict-2.3.dist-info}/top_level.txt +0 -0
@@ -10,17 +10,152 @@ from ._dtypes import (
10
10
  _real_numeric_dtypes,
11
11
  _numeric_dtypes,
12
12
  _result_type,
13
+ _dtype_categories,
13
14
  )
14
15
  from ._array_object import Array
15
16
  from ._flags import requires_api_version
16
17
  from ._creation_functions import asarray
17
18
  from ._data_type_functions import broadcast_to, iinfo
19
+ from ._helpers import _maybe_normalize_py_scalars
18
20
 
19
21
  from typing import Optional, Union
20
22
 
21
23
  import numpy as np
22
24
 
23
25
 
26
+ def _binary_ufunc_proto(x1, x2, dtype_category, func_name, np_func):
27
+ """Base implementation of a binary function, `func_name`, defined for
28
+ dtypes from `dtype_category`
29
+ """
30
+ x1, x2 = _maybe_normalize_py_scalars(x1, x2, dtype_category, func_name)
31
+
32
+ if x1.device != x2.device:
33
+ raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
34
+ # Call result type here just to raise on disallowed type combinations
35
+ _result_type(x1.dtype, x2.dtype)
36
+ x1, x2 = Array._normalize_two_args(x1, x2)
37
+ return Array._new(np_func(x1._array, x2._array), device=x1.device)
38
+
39
+
40
+ _binary_docstring_template=\
41
+ """
42
+ Array API compatible wrapper for :py:func:`np.%s <numpy.%s>`.
43
+
44
+ See its docstring for more information.
45
+ """
46
+
47
+
48
+ def create_binary_func(func_name, dtype_category, np_func):
49
+ def inner(x1, x2, /) -> Array:
50
+ return _binary_ufunc_proto(x1, x2, dtype_category, func_name, np_func)
51
+ return inner
52
+
53
+
54
+ # static type annotation for ArrayOrPythonScalar arguments given a category
55
+ # NB: keep the keys in sync with the _dtype_categories dict
56
+ _annotations = {
57
+ "all": "bool | int | float | complex | Array",
58
+ "real numeric": "int | float | Array",
59
+ "numeric": "int | float | complex | Array",
60
+ "integer": "int | Array",
61
+ "integer or boolean": "int | bool | Array",
62
+ "boolean": "bool | Array",
63
+ "real floating-point": "float | Array",
64
+ "complex floating-point": "complex | Array",
65
+ "floating-point": "float | complex | Array",
66
+ }
67
+
68
+
69
+ # func_name: dtype_category (must match that from _dtypes.py)
70
+ _binary_funcs = {
71
+ "add": "numeric",
72
+ "atan2": "real floating-point",
73
+ "bitwise_and": "integer or boolean",
74
+ "bitwise_or": "integer or boolean",
75
+ "bitwise_xor": "integer or boolean",
76
+ "_bitwise_left_shift": "integer", # leading underscore deliberate
77
+ "_bitwise_right_shift": "integer",
78
+ # XXX: copysign: real fp or numeric?
79
+ "copysign": "real floating-point",
80
+ "divide": "floating-point",
81
+ "equal": "all",
82
+ "greater": "real numeric",
83
+ "greater_equal": "real numeric",
84
+ "less": "real numeric",
85
+ "less_equal": "real numeric",
86
+ "not_equal": "all",
87
+ "floor_divide": "real numeric",
88
+ "hypot": "real floating-point",
89
+ "logaddexp": "real floating-point",
90
+ "logical_and": "boolean",
91
+ "logical_or": "boolean",
92
+ "logical_xor": "boolean",
93
+ "maximum": "real numeric",
94
+ "minimum": "real numeric",
95
+ "multiply": "numeric",
96
+ "nextafter": "real floating-point",
97
+ "pow": "numeric",
98
+ "remainder": "real numeric",
99
+ "subtract": "numeric",
100
+ }
101
+
102
+
103
+ # map array-api-name : numpy-name
104
+ _numpy_renames = {
105
+ "atan2": "arctan2",
106
+ "_bitwise_left_shift": "left_shift",
107
+ "_bitwise_right_shift": "right_shift",
108
+ "pow": "power"
109
+ }
110
+
111
+
112
+ # create and attach functions to the module
113
+ for func_name, dtype_category in _binary_funcs.items():
114
+ # sanity check
115
+ assert dtype_category in _dtype_categories
116
+
117
+ numpy_name = _numpy_renames.get(func_name, func_name)
118
+ np_func = getattr(np, numpy_name)
119
+
120
+ func = create_binary_func(func_name, dtype_category, np_func)
121
+ func.__name__ = func_name
122
+
123
+ func.__doc__ = _binary_docstring_template % (numpy_name, numpy_name)
124
+ func.__annotations__['x1'] = _annotations[dtype_category]
125
+ func.__annotations__['x2'] = _annotations[dtype_category]
126
+
127
+ vars()[func_name] = func
128
+
129
+
130
+ copysign = requires_api_version('2023.12')(copysign) # noqa: F821
131
+ hypot = requires_api_version('2023.12')(hypot) # noqa: F821
132
+ maximum = requires_api_version('2023.12')(maximum) # noqa: F821
133
+ minimum = requires_api_version('2023.12')(minimum) # noqa: F821
134
+ nextafter = requires_api_version('2024.12')(nextafter) # noqa: F821
135
+
136
+
137
+ def bitwise_left_shift(x1: int | Array, x2: int | Array, /) -> Array:
138
+ is_negative = np.any(x2._array < 0) if isinstance(x2, Array) else x2 < 0
139
+ if is_negative:
140
+ raise ValueError("bitwise_left_shift(x1, x2) is only defined for x2 >= 0")
141
+ return _bitwise_left_shift(x1, x2) # noqa: F821
142
+ if _bitwise_left_shift.__doc__: # noqa: F821
143
+ bitwise_left_shift.__doc__ = _bitwise_left_shift.__doc__ # noqa: F821
144
+
145
+
146
+ def bitwise_right_shift(x1: int | Array, x2: int | Array, /) -> Array:
147
+ is_negative = np.any(x2._array < 0) if isinstance(x2, Array) else x2 < 0
148
+ if is_negative:
149
+ raise ValueError("bitwise_left_shift(x1, x2) is only defined for x2 >= 0")
150
+ return _bitwise_right_shift(x1, x2) # noqa: F821
151
+ if _bitwise_right_shift.__doc__: # noqa: F821
152
+ bitwise_right_shift.__doc__ = _bitwise_right_shift.__doc__ # noqa: F821
153
+
154
+
155
+ # clean up to not pollute the namespace
156
+ del func, create_binary_func
157
+
158
+
24
159
  def abs(x: Array, /) -> Array:
25
160
  """
26
161
  Array API compatible wrapper for :py:func:`np.abs <numpy.abs>`.
@@ -56,23 +191,6 @@ def acosh(x: Array, /) -> Array:
56
191
  return Array._new(np.arccosh(x._array), device=x.device)
57
192
 
58
193
 
59
- def add(x1: Array, x2: Array, /) -> Array:
60
- """
61
- Array API compatible wrapper for :py:func:`np.add <numpy.add>`.
62
-
63
- See its docstring for more information.
64
- """
65
- if x1.device != x2.device:
66
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
67
-
68
- if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
69
- raise TypeError("Only numeric dtypes are allowed in add")
70
- # Call result type here just to raise on disallowed type combinations
71
- _result_type(x1.dtype, x2.dtype)
72
- x1, x2 = Array._normalize_two_args(x1, x2)
73
- return Array._new(np.add(x1._array, x2._array), device=x1.device)
74
-
75
-
76
194
  # Note: the function name is different here
77
195
  def asin(x: Array, /) -> Array:
78
196
  """
@@ -109,23 +227,6 @@ def atan(x: Array, /) -> Array:
109
227
  return Array._new(np.arctan(x._array), device=x.device)
110
228
 
111
229
 
112
- # Note: the function name is different here
113
- def atan2(x1: Array, x2: Array, /) -> Array:
114
- """
115
- Array API compatible wrapper for :py:func:`np.arctan2 <numpy.arctan2>`.
116
-
117
- See its docstring for more information.
118
- """
119
- if x1.device != x2.device:
120
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
121
- if x1.dtype not in _real_floating_dtypes or x2.dtype not in _real_floating_dtypes:
122
- raise TypeError("Only real floating-point dtypes are allowed in atan2")
123
- # Call result type here just to raise on disallowed type combinations
124
- _result_type(x1.dtype, x2.dtype)
125
- x1, x2 = Array._normalize_two_args(x1, x2)
126
- return Array._new(np.arctan2(x1._array, x2._array), device=x1.device)
127
-
128
-
129
230
  # Note: the function name is different here
130
231
  def atanh(x: Array, /) -> Array:
131
232
  """
@@ -138,47 +239,6 @@ def atanh(x: Array, /) -> Array:
138
239
  return Array._new(np.arctanh(x._array), device=x.device)
139
240
 
140
241
 
141
- def bitwise_and(x1: Array, x2: Array, /) -> Array:
142
- """
143
- Array API compatible wrapper for :py:func:`np.bitwise_and <numpy.bitwise_and>`.
144
-
145
- See its docstring for more information.
146
- """
147
- if x1.device != x2.device:
148
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
149
-
150
- if (
151
- x1.dtype not in _integer_or_boolean_dtypes
152
- or x2.dtype not in _integer_or_boolean_dtypes
153
- ):
154
- raise TypeError("Only integer or boolean dtypes are allowed in bitwise_and")
155
- # Call result type here just to raise on disallowed type combinations
156
- _result_type(x1.dtype, x2.dtype)
157
- x1, x2 = Array._normalize_two_args(x1, x2)
158
- return Array._new(np.bitwise_and(x1._array, x2._array), device=x1.device)
159
-
160
-
161
- # Note: the function name is different here
162
- def bitwise_left_shift(x1: Array, x2: Array, /) -> Array:
163
- """
164
- Array API compatible wrapper for :py:func:`np.left_shift <numpy.left_shift>`.
165
-
166
- See its docstring for more information.
167
- """
168
- if x1.device != x2.device:
169
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
170
-
171
- if x1.dtype not in _integer_dtypes or x2.dtype not in _integer_dtypes:
172
- raise TypeError("Only integer dtypes are allowed in bitwise_left_shift")
173
- # Call result type here just to raise on disallowed type combinations
174
- _result_type(x1.dtype, x2.dtype)
175
- x1, x2 = Array._normalize_two_args(x1, x2)
176
- # Note: bitwise_left_shift is only defined for x2 nonnegative.
177
- if np.any(x2._array < 0):
178
- raise ValueError("bitwise_left_shift(x1, x2) is only defined for x2 >= 0")
179
- return Array._new(np.left_shift(x1._array, x2._array), device=x1.device)
180
-
181
-
182
242
  # Note: the function name is different here
183
243
  def bitwise_invert(x: Array, /) -> Array:
184
244
  """
@@ -191,67 +251,6 @@ def bitwise_invert(x: Array, /) -> Array:
191
251
  return Array._new(np.invert(x._array), device=x.device)
192
252
 
193
253
 
194
- def bitwise_or(x1: Array, x2: Array, /) -> Array:
195
- """
196
- Array API compatible wrapper for :py:func:`np.bitwise_or <numpy.bitwise_or>`.
197
-
198
- See its docstring for more information.
199
- """
200
- if x1.device != x2.device:
201
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
202
-
203
- if (
204
- x1.dtype not in _integer_or_boolean_dtypes
205
- or x2.dtype not in _integer_or_boolean_dtypes
206
- ):
207
- raise TypeError("Only integer or boolean dtypes are allowed in bitwise_or")
208
- # Call result type here just to raise on disallowed type combinations
209
- _result_type(x1.dtype, x2.dtype)
210
- x1, x2 = Array._normalize_two_args(x1, x2)
211
- return Array._new(np.bitwise_or(x1._array, x2._array), device=x1.device)
212
-
213
-
214
- # Note: the function name is different here
215
- def bitwise_right_shift(x1: Array, x2: Array, /) -> Array:
216
- """
217
- Array API compatible wrapper for :py:func:`np.right_shift <numpy.right_shift>`.
218
-
219
- See its docstring for more information.
220
- """
221
- if x1.device != x2.device:
222
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
223
-
224
- if x1.dtype not in _integer_dtypes or x2.dtype not in _integer_dtypes:
225
- raise TypeError("Only integer dtypes are allowed in bitwise_right_shift")
226
- # Call result type here just to raise on disallowed type combinations
227
- _result_type(x1.dtype, x2.dtype)
228
- x1, x2 = Array._normalize_two_args(x1, x2)
229
- # Note: bitwise_right_shift is only defined for x2 nonnegative.
230
- if np.any(x2._array < 0):
231
- raise ValueError("bitwise_right_shift(x1, x2) is only defined for x2 >= 0")
232
- return Array._new(np.right_shift(x1._array, x2._array), device=x1.device)
233
-
234
-
235
- def bitwise_xor(x1: Array, x2: Array, /) -> Array:
236
- """
237
- Array API compatible wrapper for :py:func:`np.bitwise_xor <numpy.bitwise_xor>`.
238
-
239
- See its docstring for more information.
240
- """
241
- if x1.device != x2.device:
242
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
243
-
244
- if (
245
- x1.dtype not in _integer_or_boolean_dtypes
246
- or x2.dtype not in _integer_or_boolean_dtypes
247
- ):
248
- raise TypeError("Only integer or boolean dtypes are allowed in bitwise_xor")
249
- # Call result type here just to raise on disallowed type combinations
250
- _result_type(x1.dtype, x2.dtype)
251
- x1, x2 = Array._normalize_two_args(x1, x2)
252
- return Array._new(np.bitwise_xor(x1._array, x2._array), device=x1.device)
253
-
254
-
255
254
  def ceil(x: Array, /) -> Array:
256
255
  """
257
256
  Array API compatible wrapper for :py:func:`np.ceil <numpy.ceil>`.
@@ -372,32 +371,17 @@ def clip(
372
371
  out[ib] = b[ib]
373
372
  return Array._new(out, device=device)
374
373
 
374
+
375
375
  def conj(x: Array, /) -> Array:
376
376
  """
377
377
  Array API compatible wrapper for :py:func:`np.conj <numpy.conj>`.
378
378
 
379
379
  See its docstring for more information.
380
380
  """
381
- if x.dtype not in _complex_floating_dtypes:
382
- raise TypeError("Only complex floating-point dtypes are allowed in conj")
381
+ if x.dtype not in _numeric_dtypes:
382
+ raise TypeError("Only numeric dtypes are allowed in conj")
383
383
  return Array._new(np.conj(x._array), device=x.device)
384
384
 
385
- @requires_api_version('2023.12')
386
- def copysign(x1: Array, x2: Array, /) -> Array:
387
- """
388
- Array API compatible wrapper for :py:func:`np.copysign <numpy.copysign>`.
389
-
390
- See its docstring for more information.
391
- """
392
- if x1.device != x2.device:
393
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
394
-
395
- if x1.dtype not in _real_floating_dtypes or x2.dtype not in _real_floating_dtypes:
396
- raise TypeError("Only real numeric dtypes are allowed in copysign")
397
- # Call result type here just to raise on disallowed type combinations
398
- _result_type(x1.dtype, x2.dtype)
399
- x1, x2 = Array._normalize_two_args(x1, x2)
400
- return Array._new(np.copysign(x1._array, x2._array), device=x1.device)
401
385
 
402
386
  def cos(x: Array, /) -> Array:
403
387
  """
@@ -421,36 +405,6 @@ def cosh(x: Array, /) -> Array:
421
405
  return Array._new(np.cosh(x._array), device=x.device)
422
406
 
423
407
 
424
- def divide(x1: Array, x2: Array, /) -> Array:
425
- """
426
- Array API compatible wrapper for :py:func:`np.divide <numpy.divide>`.
427
-
428
- See its docstring for more information.
429
- """
430
- if x1.device != x2.device:
431
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
432
- if x1.dtype not in _floating_dtypes or x2.dtype not in _floating_dtypes:
433
- raise TypeError("Only floating-point dtypes are allowed in divide")
434
- # Call result type here just to raise on disallowed type combinations
435
- _result_type(x1.dtype, x2.dtype)
436
- x1, x2 = Array._normalize_two_args(x1, x2)
437
- return Array._new(np.divide(x1._array, x2._array), device=x1.device)
438
-
439
-
440
- def equal(x1: Array, x2: Array, /) -> Array:
441
- """
442
- Array API compatible wrapper for :py:func:`np.equal <numpy.equal>`.
443
-
444
- See its docstring for more information.
445
- """
446
- if x1.device != x2.device:
447
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
448
- # Call result type here just to raise on disallowed type combinations
449
- _result_type(x1.dtype, x2.dtype)
450
- x1, x2 = Array._normalize_two_args(x1, x2)
451
- return Array._new(np.equal(x1._array, x2._array), device=x1.device)
452
-
453
-
454
408
  def exp(x: Array, /) -> Array:
455
409
  """
456
410
  Array API compatible wrapper for :py:func:`np.exp <numpy.exp>`.
@@ -487,69 +441,6 @@ def floor(x: Array, /) -> Array:
487
441
  return Array._new(np.floor(x._array), device=x.device)
488
442
 
489
443
 
490
- def floor_divide(x1: Array, x2: Array, /) -> Array:
491
- """
492
- Array API compatible wrapper for :py:func:`np.floor_divide <numpy.floor_divide>`.
493
-
494
- See its docstring for more information.
495
- """
496
- if x1.device != x2.device:
497
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
498
- if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
499
- raise TypeError("Only real numeric dtypes are allowed in floor_divide")
500
- # Call result type here just to raise on disallowed type combinations
501
- _result_type(x1.dtype, x2.dtype)
502
- x1, x2 = Array._normalize_two_args(x1, x2)
503
- return Array._new(np.floor_divide(x1._array, x2._array), device=x1.device)
504
-
505
-
506
- def greater(x1: Array, x2: Array, /) -> Array:
507
- """
508
- Array API compatible wrapper for :py:func:`np.greater <numpy.greater>`.
509
-
510
- See its docstring for more information.
511
- """
512
- if x1.device != x2.device:
513
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
514
- if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
515
- raise TypeError("Only real numeric dtypes are allowed in greater")
516
- # Call result type here just to raise on disallowed type combinations
517
- _result_type(x1.dtype, x2.dtype)
518
- x1, x2 = Array._normalize_two_args(x1, x2)
519
- return Array._new(np.greater(x1._array, x2._array), device=x1.device)
520
-
521
-
522
- def greater_equal(x1: Array, x2: Array, /) -> Array:
523
- """
524
- Array API compatible wrapper for :py:func:`np.greater_equal <numpy.greater_equal>`.
525
-
526
- See its docstring for more information.
527
- """
528
- if x1.device != x2.device:
529
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
530
- if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
531
- raise TypeError("Only real numeric dtypes are allowed in greater_equal")
532
- # Call result type here just to raise on disallowed type combinations
533
- _result_type(x1.dtype, x2.dtype)
534
- x1, x2 = Array._normalize_two_args(x1, x2)
535
- return Array._new(np.greater_equal(x1._array, x2._array), device=x1.device)
536
-
537
- @requires_api_version('2023.12')
538
- def hypot(x1: Array, x2: Array, /) -> Array:
539
- """
540
- Array API compatible wrapper for :py:func:`np.hypot <numpy.hypot>`.
541
-
542
- See its docstring for more information.
543
- """
544
- if x1.device != x2.device:
545
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
546
- if x1.dtype not in _real_floating_dtypes or x2.dtype not in _real_floating_dtypes:
547
- raise TypeError("Only real floating-point dtypes are allowed in hypot")
548
- # Call result type here just to raise on disallowed type combinations
549
- _result_type(x1.dtype, x2.dtype)
550
- x1, x2 = Array._normalize_two_args(x1, x2)
551
- return Array._new(np.hypot(x1._array, x2._array), device=x1.device)
552
-
553
444
  def imag(x: Array, /) -> Array:
554
445
  """
555
446
  Array API compatible wrapper for :py:func:`np.imag <numpy.imag>`.
@@ -594,38 +485,6 @@ def isnan(x: Array, /) -> Array:
594
485
  return Array._new(np.isnan(x._array), device=x.device)
595
486
 
596
487
 
597
- def less(x1: Array, x2: Array, /) -> Array:
598
- """
599
- Array API compatible wrapper for :py:func:`np.less <numpy.less>`.
600
-
601
- See its docstring for more information.
602
- """
603
- if x1.device != x2.device:
604
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
605
- if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
606
- raise TypeError("Only real numeric dtypes are allowed in less")
607
- # Call result type here just to raise on disallowed type combinations
608
- _result_type(x1.dtype, x2.dtype)
609
- x1, x2 = Array._normalize_two_args(x1, x2)
610
- return Array._new(np.less(x1._array, x2._array), device=x1.device)
611
-
612
-
613
- def less_equal(x1: Array, x2: Array, /) -> Array:
614
- """
615
- Array API compatible wrapper for :py:func:`np.less_equal <numpy.less_equal>`.
616
-
617
- See its docstring for more information.
618
- """
619
- if x1.device != x2.device:
620
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
621
- if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
622
- raise TypeError("Only real numeric dtypes are allowed in less_equal")
623
- # Call result type here just to raise on disallowed type combinations
624
- _result_type(x1.dtype, x2.dtype)
625
- x1, x2 = Array._normalize_two_args(x1, x2)
626
- return Array._new(np.less_equal(x1._array, x2._array), device=x1.device)
627
-
628
-
629
488
  def log(x: Array, /) -> Array:
630
489
  """
631
490
  Array API compatible wrapper for :py:func:`np.log <numpy.log>`.
@@ -670,38 +529,6 @@ def log10(x: Array, /) -> Array:
670
529
  return Array._new(np.log10(x._array), device=x.device)
671
530
 
672
531
 
673
- def logaddexp(x1: Array, x2: Array, /) -> Array:
674
- """
675
- Array API compatible wrapper for :py:func:`np.logaddexp <numpy.logaddexp>`.
676
-
677
- See its docstring for more information.
678
- """
679
- if x1.device != x2.device:
680
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
681
- if x1.dtype not in _real_floating_dtypes or x2.dtype not in _real_floating_dtypes:
682
- raise TypeError("Only real floating-point dtypes are allowed in logaddexp")
683
- # Call result type here just to raise on disallowed type combinations
684
- _result_type(x1.dtype, x2.dtype)
685
- x1, x2 = Array._normalize_two_args(x1, x2)
686
- return Array._new(np.logaddexp(x1._array, x2._array), device=x1.device)
687
-
688
-
689
- def logical_and(x1: Array, x2: Array, /) -> Array:
690
- """
691
- Array API compatible wrapper for :py:func:`np.logical_and <numpy.logical_and>`.
692
-
693
- See its docstring for more information.
694
- """
695
- if x1.device != x2.device:
696
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
697
- if x1.dtype not in _boolean_dtypes or x2.dtype not in _boolean_dtypes:
698
- raise TypeError("Only boolean dtypes are allowed in logical_and")
699
- # Call result type here just to raise on disallowed type combinations
700
- _result_type(x1.dtype, x2.dtype)
701
- x1, x2 = Array._normalize_two_args(x1, x2)
702
- return Array._new(np.logical_and(x1._array, x2._array), device=x1.device)
703
-
704
-
705
532
  def logical_not(x: Array, /) -> Array:
706
533
  """
707
534
  Array API compatible wrapper for :py:func:`np.logical_not <numpy.logical_not>`.
@@ -713,87 +540,6 @@ def logical_not(x: Array, /) -> Array:
713
540
  return Array._new(np.logical_not(x._array), device=x.device)
714
541
 
715
542
 
716
- def logical_or(x1: Array, x2: Array, /) -> Array:
717
- """
718
- Array API compatible wrapper for :py:func:`np.logical_or <numpy.logical_or>`.
719
-
720
- See its docstring for more information.
721
- """
722
- if x1.device != x2.device:
723
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
724
- if x1.dtype not in _boolean_dtypes or x2.dtype not in _boolean_dtypes:
725
- raise TypeError("Only boolean dtypes are allowed in logical_or")
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.logical_or(x1._array, x2._array), device=x1.device)
730
-
731
-
732
- def logical_xor(x1: Array, x2: Array, /) -> Array:
733
- """
734
- Array API compatible wrapper for :py:func:`np.logical_xor <numpy.logical_xor>`.
735
-
736
- See its docstring for more information.
737
- """
738
- if x1.device != x2.device:
739
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
740
- if x1.dtype not in _boolean_dtypes or x2.dtype not in _boolean_dtypes:
741
- raise TypeError("Only boolean dtypes are allowed in logical_xor")
742
- # Call result type here just to raise on disallowed type combinations
743
- _result_type(x1.dtype, x2.dtype)
744
- x1, x2 = Array._normalize_two_args(x1, x2)
745
- return Array._new(np.logical_xor(x1._array, x2._array), device=x1.device)
746
-
747
- @requires_api_version('2023.12')
748
- def maximum(x1: Array, x2: Array, /) -> Array:
749
- """
750
- Array API compatible wrapper for :py:func:`np.maximum <numpy.maximum>`.
751
-
752
- See its docstring for more information.
753
- """
754
- if x1.device != x2.device:
755
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
756
- if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
757
- raise TypeError("Only real numeric dtypes are allowed in maximum")
758
- # Call result type here just to raise on disallowed type combinations
759
- _result_type(x1.dtype, x2.dtype)
760
- x1, x2 = Array._normalize_two_args(x1, x2)
761
- # TODO: maximum(-0., 0.) is unspecified. Should we issue a warning/error
762
- # in that case?
763
- return Array._new(np.maximum(x1._array, x2._array), device=x1.device)
764
-
765
- @requires_api_version('2023.12')
766
- def minimum(x1: Array, x2: Array, /) -> Array:
767
- """
768
- Array API compatible wrapper for :py:func:`np.minimum <numpy.minimum>`.
769
-
770
- See its docstring for more information.
771
- """
772
- if x1.device != x2.device:
773
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
774
- if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
775
- raise TypeError("Only real numeric dtypes are allowed in minimum")
776
- # Call result type here just to raise on disallowed type combinations
777
- _result_type(x1.dtype, x2.dtype)
778
- x1, x2 = Array._normalize_two_args(x1, x2)
779
- return Array._new(np.minimum(x1._array, x2._array), device=x1.device)
780
-
781
- def multiply(x1: Array, x2: Array, /) -> Array:
782
- """
783
- Array API compatible wrapper for :py:func:`np.multiply <numpy.multiply>`.
784
-
785
- See its docstring for more information.
786
- """
787
- if x1.device != x2.device:
788
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
789
- if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
790
- raise TypeError("Only numeric dtypes are allowed in multiply")
791
- # Call result type here just to raise on disallowed type combinations
792
- _result_type(x1.dtype, x2.dtype)
793
- x1, x2 = Array._normalize_two_args(x1, x2)
794
- return Array._new(np.multiply(x1._array, x2._array), device=x1.device)
795
-
796
-
797
543
  def negative(x: Array, /) -> Array:
798
544
  """
799
545
  Array API compatible wrapper for :py:func:`np.negative <numpy.negative>`.
@@ -805,34 +551,6 @@ def negative(x: Array, /) -> Array:
805
551
  return Array._new(np.negative(x._array), device=x.device)
806
552
 
807
553
 
808
- @requires_api_version('2024.12')
809
- def nextafter(x1: Array, x2: Array, /) -> Array:
810
- """
811
- Array API compatible wrapper for :py:func:`np.nextafter <numpy.nextafter>`.
812
-
813
- See its docstring for more information.
814
- """
815
- if x1.device != x2.device:
816
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
817
- if x1.dtype not in _real_floating_dtypes or x2.dtype not in _real_floating_dtypes:
818
- raise TypeError("Only real floating-point dtypes are allowed in nextafter")
819
- x1, x2 = Array._normalize_two_args(x1, x2)
820
- return Array._new(np.nextafter(x1._array, x2._array), device=x1.device)
821
-
822
- def not_equal(x1: Array, x2: Array, /) -> Array:
823
- """
824
- Array API compatible wrapper for :py:func:`np.not_equal <numpy.not_equal>`.
825
-
826
- See its docstring for more information.
827
- """
828
- if x1.device != x2.device:
829
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
830
- # Call result type here just to raise on disallowed type combinations
831
- _result_type(x1.dtype, x2.dtype)
832
- x1, x2 = Array._normalize_two_args(x1, x2)
833
- return Array._new(np.not_equal(x1._array, x2._array), device=x1.device)
834
-
835
-
836
554
  def positive(x: Array, /) -> Array:
837
555
  """
838
556
  Array API compatible wrapper for :py:func:`np.positive <numpy.positive>`.
@@ -844,31 +562,14 @@ def positive(x: Array, /) -> Array:
844
562
  return Array._new(np.positive(x._array), device=x.device)
845
563
 
846
564
 
847
- # Note: the function name is different here
848
- def pow(x1: Array, x2: Array, /) -> Array:
849
- """
850
- Array API compatible wrapper for :py:func:`np.power <numpy.power>`.
851
-
852
- See its docstring for more information.
853
- """
854
- if x1.device != x2.device:
855
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
856
- if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
857
- raise TypeError("Only numeric dtypes are allowed in pow")
858
- # Call result type here just to raise on disallowed type combinations
859
- _result_type(x1.dtype, x2.dtype)
860
- x1, x2 = Array._normalize_two_args(x1, x2)
861
- return Array._new(np.power(x1._array, x2._array), device=x1.device)
862
-
863
-
864
565
  def real(x: Array, /) -> Array:
865
566
  """
866
567
  Array API compatible wrapper for :py:func:`np.real <numpy.real>`.
867
568
 
868
569
  See its docstring for more information.
869
570
  """
870
- if x.dtype not in _complex_floating_dtypes:
871
- raise TypeError("Only complex floating-point dtypes are allowed in real")
571
+ if x.dtype not in _numeric_dtypes:
572
+ raise TypeError("Only numeric dtypes are allowed in real")
872
573
  return Array._new(np.real(x._array), device=x.device)
873
574
 
874
575
 
@@ -883,22 +584,6 @@ def reciprocal(x: Array, /) -> Array:
883
584
  raise TypeError("Only floating-point dtypes are allowed in reciprocal")
884
585
  return Array._new(np.reciprocal(x._array), device=x.device)
885
586
 
886
- def remainder(x1: Array, x2: Array, /) -> Array:
887
- """
888
- Array API compatible wrapper for :py:func:`np.remainder <numpy.remainder>`.
889
-
890
- See its docstring for more information.
891
- """
892
- if x1.device != x2.device:
893
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
894
- if x1.dtype not in _real_numeric_dtypes or x2.dtype not in _real_numeric_dtypes:
895
- raise TypeError("Only real numeric dtypes are allowed in remainder")
896
- # Call result type here just to raise on disallowed type combinations
897
- _result_type(x1.dtype, x2.dtype)
898
- x1, x2 = Array._normalize_two_args(x1, x2)
899
- return Array._new(np.remainder(x1._array, x2._array), device=x1.device)
900
-
901
-
902
587
  def round(x: Array, /) -> Array:
903
588
  """
904
589
  Array API compatible wrapper for :py:func:`np.round <numpy.round>`.
@@ -979,22 +664,6 @@ def sqrt(x: Array, /) -> Array:
979
664
  return Array._new(np.sqrt(x._array), device=x.device)
980
665
 
981
666
 
982
- def subtract(x1: Array, x2: Array, /) -> Array:
983
- """
984
- Array API compatible wrapper for :py:func:`np.subtract <numpy.subtract>`.
985
-
986
- See its docstring for more information.
987
- """
988
- if x1.device != x2.device:
989
- raise ValueError(f"Arrays from two different devices ({x1.device} and {x2.device}) can not be combined.")
990
- if x1.dtype not in _numeric_dtypes or x2.dtype not in _numeric_dtypes:
991
- raise TypeError("Only numeric dtypes are allowed in subtract")
992
- # Call result type here just to raise on disallowed type combinations
993
- _result_type(x1.dtype, x2.dtype)
994
- x1, x2 = Array._normalize_two_args(x1, x2)
995
- return Array._new(np.subtract(x1._array, x2._array), device=x1.device)
996
-
997
-
998
667
  def tan(x: Array, /) -> Array:
999
668
  """
1000
669
  Array API compatible wrapper for :py:func:`np.tan <numpy.tan>`.