From 9c11e7222d7f338e4e5ade49734ee25229dbff9c Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Tue, 14 Dec 2021 12:19:56 -0500 Subject: [PATCH 01/10] Convert array_object.md to rst --- spec/API_specification/array_object.md | 1351 ----------------- spec/API_specification/array_object.rst | 311 ++++ spec/API_specification/signatures/_types.py | 3 +- .../signatures/array_object.py | 942 ++++++++++++ 4 files changed, 1255 insertions(+), 1352 deletions(-) delete mode 100644 spec/API_specification/array_object.md create mode 100644 spec/API_specification/array_object.rst create mode 100644 spec/API_specification/signatures/array_object.py diff --git a/spec/API_specification/array_object.md b/spec/API_specification/array_object.md deleted file mode 100644 index e950643b4..000000000 --- a/spec/API_specification/array_object.md +++ /dev/null @@ -1,1351 +0,0 @@ -(array-object)= - -# Array object - -> Array API specification for array object attributes and methods. - -A conforming implementation of the array API standard must provide and support an array object having the following attributes and methods adhering to the following conventions. - -- Positional parameters must be [positional-only](https://www.python.org/dev/peps/pep-0570/) parameters. Positional-only parameters have no externally-usable name. When a method accepting positional-only parameters is called, positional arguments are mapped to these parameters based solely on their order. -- Optional parameters must be [keyword-only](https://www.python.org/dev/peps/pep-3102/) arguments. -- Broadcasting semantics must follow the semantics defined in {ref}`broadcasting`. -- Unless stated otherwise, methods must support the data types defined in {ref}`data-types`. -- Unless stated otherwise, methods must adhere to the type promotion rules defined in {ref}`type-promotion`. -- Unless stated otherwise, floating-point operations must adhere to IEEE 754-2019. - -Furthermore, a conforming implementation of the array API standard must support array objects of arbitrary rank `N` (i.e., number of dimensions), where `N` is greater than or equal to zero. - -```{note} -Conforming implementations must support zero-dimensional arrays. - -Apart from array object attributes, such as `ndim`, `device`, and `dtype`, all operations in this standard return arrays (or tuples of arrays), including those operations, such as `mean`, `var`, and `std`, from which some common array libraries (e.g., NumPy) return scalar values. - -_Rationale: always returning arrays is necessary to (1) support accelerator libraries where non-array return values could force device synchronization and (2) support delayed execution models where an array represents a future value._ -``` - -* * * - -(operators)= - -## Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following Python operators. - -### Arithmetic Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following Python arithmetic operators. - -- `+x`: [`__pos__(x)`](#__pos__self-) - - - [`operator.pos(x)`](https://docs.python.org/3/library/operator.html#operator.pos) - - [`operator.__pos__(x)`](https://docs.python.org/3/library/operator.html#operator.__pos__) - -- `-x`: [`__neg__(x)`](#__neg__self-) - - - [`operator.neg(x)`](https://docs.python.org/3/library/operator.html#operator.neg) - - [`operator.__neg__(x)`](https://docs.python.org/3/library/operator.html#operator.__neg__) - -- `x1 + x2`: [`__add__(x1, x2)`](#__add__self-other-) - - - [`operator.add(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.add) - - [`operator.__add__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__add__) - -- `x1 - x2`: [`__sub__(x1, x2)`](#__sub__self-other-) - - - [`operator.sub(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.sub) - - [`operator.__sub__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__sub__) - -- `x1 * x2`: [`__mul__(x1, x2)`](#__mul__self-other-) - - - [`operator.mul(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.mul) - - [`operator.__mul__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__mul__) - -- `x1 / x2`: [`__truediv__(x1, x2)`](#__truediv__self-other-) - - - [`operator.truediv(x1,x2)`](https://docs.python.org/3/library/operator.html#operator.truediv) - - [`operator.__truediv__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__truediv__) - -- `x1 // x2`: [`__floordiv__(x1, x2)`](#__floordiv__self-other-) - - - [`operator.floordiv(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.floordiv) - - [`operator.__floordiv__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__floordiv__) - -- `x1 % x2`: [`__mod__(x1, x2)`](#__mod__self-other-) - - - [`operator.mod(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.mod) - - [`operator.__mod__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__mod__) - -- `x1 ** x2`: [`__pow__(x1, x2)`](#__pow__self-other-) - - - [`operator.pow(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.pow) - - [`operator.__pow__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__pow__) - -Arithmetic operators should be defined for arrays having numeric data types. - -### Array Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following Python array operators. - -- `x1 @ x2`: [`__matmul__(x1, x2)`](#__matmul__self-other-) - - - [`operator.matmul(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.matmul) - - [`operator.__matmul__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__matmul__) - -The matmul `@` operator should be defined for arrays having numeric data types. - -### Bitwise Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following Python bitwise operators. - -- `~x`: [`__invert__(x)`](#__invert__self-) - - - [`operator.inv(x)`](https://docs.python.org/3/library/operator.html#operator.inv) - - [`operator.invert(x)`](https://docs.python.org/3/library/operator.html#operator.invert) - - [`operator.__inv__(x)`](https://docs.python.org/3/library/operator.html#operator.__inv__) - - [`operator.__invert__(x)`](https://docs.python.org/3/library/operator.html#operator.__invert__) - -- `x1 & x2`: [`__and__(x1, x2)`](#__and__self-other-) - - - [`operator.and(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.and) - - [`operator.__and__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__and__) - -- `x1 | x2`: [`__or__(x1, x2)`](#__or__self-other-) - - - [`operator.or(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.or) - - [`operator.__or__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__or__) - -- `x1 ^ x2`: [`__xor__(x1, x2)`](#__xor__self-other-) - - - [`operator.xor(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.xor) - - [`operator.__xor__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__xor__) - -- `x1 << x2`: [`__lshift__(x1, x2)`](#__lshift__self-other-) - - - [`operator.lshift(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.lshift) - - [`operator.__lshift__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__lshift__) - -- `x1 >> x2`: [`__rshift__(x1, x2)`](#__rshift__self-other-) - - - [`operator.rshift(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.rshift) - - [`operator.__rshift__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__rshift__) - -Bitwise operators should be defined for arrays having integer and boolean data types. - -### Comparison Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following Python comparison operators. - -- `x1 < x2`: [`__lt__(x1, x2)`](#__lt__self-other-) - - - [`operator.lt(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.lt) - - [`operator.__lt__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__lt__) - -- `x1 <= x2`: [`__le__(x1, x2)`](#__le__self-other-) - - - [`operator.le(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.le) - - [`operator.__le__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__le__) - -- `x1 > x2`: [`__gt__(x1, x2)`](#__gt__self-other-) - - - [`operator.gt(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.gt) - - [`operator.__gt__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__gt__) - -- `x1 >= x2`: [`__ge__(x1, x2)`](#__ge__self-other-) - - - [`operator.ge(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.ge) - - [`operator.__ge__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__ge__) - -- `x1 == x2`: [`__eq__(x1, x2)`](#__eq__self-other-) - - - [`operator.eq(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.eq) - - [`operator.__eq__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__eq__) - -- `x1 != x2`: [`__ne__(x1, x2)`](#__ne__self-other-) - - - [`operator.ne(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.ne) - - [`operator.__ne__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__ne__) - -Comparison operators should be defined for arrays having any data type. - -### In-place Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following in-place Python operators. - -An in-place operation must not change the data type or shape of the in-place array as a result of {ref}`type-promotion` or {ref}`broadcasting`. - -An in-place operation must have the same behavior (including special cases) as its respective binary (i.e., two operand, non-assignment) operation. For example, after in-place addition `x1 += x2`, the modified array `x1` must always equal the result of the equivalent binary arithmetic operation `x1 = x1 + x2`. - -```{note} -In-place operators must be supported as discussed in {ref}`copyview-mutability`. -``` - -#### Arithmetic Operators - -- `+=`. May be implemented via `__iadd__`. -- `-=`. May be implemented via `__isub__`. -- `*=`. May be implemented via `__imul__`. -- `/=`. May be implemented via `__itruediv__`. -- `//=`. May be implemented via `__ifloordiv__`. -- `**=`. May be implemented via `__ipow__`. -- `%=`. May be implemented via `__imod__`. - -#### Array Operators - -- `@=`. May be implemented via `__imatmul__`. - -#### Bitwise Operators - -- `&=`. May be implemented via `__iand__`. -- `|=`. May be implemented via `__ior__`. -- `^=`. May be implemented via `__ixor__`. -- `<<=`. May be implemented via `__ilshift__`. -- `>>=`. May be implemented via `__irshift__`. - -### Reflected Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following reflected operators. - -The results of applying reflected operators must match their non-reflected equivalents. - -```{note} -All operators for which `array scalar` is implemented must have an equivalent reflected operator implementation. -``` - -#### Arithmetic Operators - -- `__radd__` -- `__rsub__` -- `__rmul__` -- `__rtruediv__` -- `__rfloordiv__` -- `__rpow__` -- `__rmod__` - -#### Array Operators - -- `__rmatmul__` - -#### Bitwise Operators - -- `__rand__` -- `__ror__` -- `__rxor__` -- `__rlshift__` -- `__rrshift__` - -* * * - -## Attributes - - - -(attribute-dtype)= -### dtype - -Data type of the array elements. - -#### Returns - -- **out**: _<dtype>_ - - - array data type. - -(attribute-device)= -### device - -Hardware device the array data resides on. - -#### Returns - -- **out**: _<device>_ - - - a `device` object (see {ref}`device-support`). - -(attribute-mT)= -### mT - -Transpose of a matrix (or a stack of matrices). - -If an array instance has fewer than two dimensions, an error should be raised. - -#### Returns - -- **out**: _<array>_ - - - array whose last two dimensions (axes) are permuted in reverse order relative to original array (i.e., for an array instance having shape `(..., M, N)`, the returned array must have shape `(..., N, M)`). The returned array must have the same data type as the original array. - -(attribute-ndim)= -### ndim - -Number of array dimensions (axes). - -#### Returns - -- **out**: _int_ - - - number of array dimensions (axes). - -(attribute-shape)= -### shape - -Array dimensions. - -#### Returns - -- **out**: _Tuple\[ Optional\[ int ], ... ]_ - - - array dimensions. An array dimension must be `None` if and only if a dimension is unknown. - -```{note} -For array libraries having graph-based computational models, array dimensions may be unknown due to data-dependent operations (e.g., boolean indexing; `A[:, B > 0]`) and thus cannot be statically resolved without knowing array contents. -``` - -```{note} -The returned value should be a tuple; however, where warranted, an array library may choose to return a custom shape object. If an array library returns a custom shape object, the object must be immutable, must support indexing for dimension retrieval, and must behave similarly to a tuple. -``` - -(attribute-size)= -### size - -Number of elements in an array. - -```{note} -This must equal the product of the array's dimensions. -``` - -#### Returns - -- **out**: _Optional\[ int ]_ - - - number of elements in an array. The returned value must be `None` if and only if one or more array dimensions are unknown. - -```{note} -For array libraries having graph-based computational models, an array may have unknown dimensions due to data-dependent operations. -``` - -(attribute-T)= -### T - -Transpose of the array. - -The array instance must be two-dimensional. If the array instance is not two-dimensional, an error should be raised. - -```{note} -Limiting the transpose to two-dimensional arrays (matrices) deviates from the NumPy et al practice of reversing all axes for arrays having more than two-dimensions. This is intentional, as reversing all axes was found to be problematic (e.g., conflicting with the mathematical definition of a transpose which is limited to matrices; not operating on batches of matrices; et cetera). In order to reverse all axes, one is recommended to use the functional `permute_dims` interface found in this specification. -``` - -#### Returns - -- **out**: _<array>_ - - - two-dimensional array whose first and last dimensions (axes) are permuted in reverse order relative to original array. The returned array must have the same data type as the original array. - -* * * - -## Methods - - - -(method-__abs__)= -### \_\_abs\_\_(self, /) - -Calculates the absolute value for each element of an array instance (i.e., the element-wise result has the same magnitude as the respective element but has positive sign). - -```{note} -For signed integer data types, the absolute value of the minimum representable integer is implementation-dependent. -``` - -#### Special Cases - -For floating-point operands, let `self` equal `x`. - -- If `x_i` is `NaN`, the result is `NaN`. -- If `x_i` is `-0`, the result is `+0`. -- If `x_i` is `-infinity`, the result is `+infinity`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise absolute value. The returned array must have the same data type as `self`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`abs(x)`](elementwise_functions.md#absx-). -``` - -(method-__add__)= -### \_\_add\_\_(self, other, /) - -Calculates the sum for each element of an array instance with the respective element of the array `other`. - -#### Special Cases - -For floating-point operands, let `self` equal `x1` and `other` equal `x2`. - -- If either `x1_i` or `x2_i` is `NaN`, the result is `NaN`. -- If `x1_i` is `+infinity` and `x2_i` is `-infinity`, the result is `NaN`. -- If `x1_i` is `-infinity` and `x2_i` is `+infinity`, the result is `NaN`. -- If `x1_i` is `+infinity` and `x2_i` is `+infinity`, the result is `+infinity`. -- If `x1_i` is `-infinity` and `x2_i` is `-infinity`, the result is `-infinity`. -- If `x1_i` is `+infinity` and `x2_i` is a finite number, the result is `+infinity`. -- If `x1_i` is `-infinity` and `x2_i` is a finite number, the result is `-infinity`. -- If `x1_i` is a finite number and `x2_i` is `+infinity`, the result is `+infinity`. -- If `x1_i` is a finite number and `x2_i` is `-infinity`, the result is `-infinity`. -- If `x1_i` is `-0` and `x2_i` is `-0`, the result is `-0`. -- If `x1_i` is `-0` and `x2_i` is `+0`, the result is `+0`. -- If `x1_i` is `+0` and `x2_i` is `-0`, the result is `+0`. -- If `x1_i` is `+0` and `x2_i` is `+0`, the result is `+0`. -- If `x1_i` is either `+0` or `-0` and `x2_i` is a nonzero finite number, the result is `x2_i`. -- If `x1_i` is a nonzero finite number and `x2_i` is either `+0` or `-0`, the result is `x1_i`. -- If `x1_i` is a nonzero finite number and `x2_i` is `-x1_i`, the result is `+0`. -- In the remaining cases, when neither `infinity`, `+0`, `-0`, nor a `NaN` is involved, and the operands have the same mathematical sign or have different magnitudes, the sum must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported round mode. If the magnitude is too large to represent, the operation overflows and the result is an `infinity` of appropriate mathematical sign. - -```{note} -Floating-point addition is a commutative operation, but not always associative. -``` - -#### Parameters - -- **self**: _<array>_ - - - array instance (augend array). Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - addend array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise sums. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`add(x1, x2)`](elementwise_functions.md#addx1-x2-). -``` - -(method-__and__)= -### \_\_and\_\_(self, other, /) - -Evaluates `self_i & other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer or boolean data type. - -- **other**: _Union\[ int, bool, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have an integer or boolean data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_and(x1, x2)`](elementwise_functions.md#logical_andx1-x2-). -``` - - -(method-__array_namespace__)= -### \_\_array_namespace\_\_(self, /, *, api_version=None) - -Returns an object that has all the array API functions on it. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -- **api_version**: _<Optional\[str\]>_ - - - string representing the version of the array API specification to be returned, in `'YYYY.MM'` form, for example, `'2020.10'`. If it is `None`, it should return the namespace corresponding to latest version of the array API specification. If the given version is invalid or not implemented for the given module, an error should be raised. Default: `None`. - -#### Returns - -- **out**: _<object>_ - - - an object representing the array API namespace. It should have every top-level function defined in the specification as an attribute. It may contain other public names as well, but it is recommended to only include those names that are part of the specification. - - -(method-__bool__)= -### \_\_bool\_\_(self, /) - -Converts a zero-dimensional boolean array to a Python `bool` object. - -#### Parameters - -- **self**: _<array>_ - - - zero-dimensional array instance. Must have a boolean data type. - -#### Returns - -- **out**: _<bool>_ - - - a Python `bool` object representing the single element of the array. - - -(method-__dlpack__)= -### \_\_dlpack\_\_(self, /, *, stream=None) - -Exports the array for consumption by {ref}`function-from_dlpack` as a DLPack capsule. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -- **stream**: _Optional\[ Union\[ int, Any ]]_ - - - for CUDA and ROCm, a Python integer representing a pointer to a stream, on devices that support streams. `stream` is provided by the consumer to the producer to instruct the producer to ensure that operations can safely be performed on the array (e.g., by inserting a dependency between streams via "wait for event"). The pointer must be a positive integer or `-1`. If `stream` is `-1`, the value may be used by the consumer to signal "producer must not perform any synchronization". The ownership of the stream stays with the consumer. - - On CPU and other device types without streams, only `None` is accepted. - - For other device types which do have a stream, queue or similar synchronization mechanism, the most appropriate type to use for `stream` is not yet determined. E.g., for SYCL one may want to use an object containing an in-order `cl::sycl::queue`. This is allowed when libraries agree on such a convention, and may be standardized in a future version of this API standard. - - ```{note} - Support for a `stream` value other than `None` is optional and implementation-dependent. - ``` - - Device-specific notes: - - :::{admonition} CUDA - - `None`: producer must assume the legacy default stream (default). - - `1`: the legacy default stream. - - `2`: the per-thread default stream. - - `> 2`: stream number represented as a Python integer. - - `0` is disallowed due to its ambiguity: `0` could mean either `None`, `1`, or `2`. - ::: - - :::{admonition} ROCm - - `None`: producer must assume the legacy default stream (default). - - `0`: the default stream. - - `> 2`: stream number represented as a Python integer. - - Using `1` and `2` is not supported. - ::: - - ```{tip} - It is recommended that implementers explicitly handle streams. If - they use the legacy default stream, specifying `1` (CUDA) or `0` - (ROCm) is preferred. `None` is a safe default for developers who do - not want to think about stream handling at all, potentially at the - cost of more synchronization than necessary. - ``` - -#### Returns - -- **capsule**: _<PyCapsule>_ - - - a DLPack capsule for the array. See {ref}`data-interchange` for details. - - -(method-__dlpack_device__)= -### \_\_dlpack\_device\_\_(self, /) - -Returns device type and device ID in DLPack format. Meant for use within {ref}`function-from_dlpack`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -#### Returns - -- **device**: _Tuple\[enum.IntEnum, int\]_ - - - a tuple `(device_type, device_id)` in DLPack format. Valid device type enum members are: - - ``` - CPU = 1 - CUDA = 2 - CPU_PINNED = 3 - OPENCL = 4 - VULKAN = 7 - METAL = 8 - VPI = 9 - ROCM = 10 - ``` - -(method-__eq__)= -### \_\_eq\_\_(self, other, /) - -Computes the truth value of `self_i == other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. May have any data type. - -- **other**: _Union\[ int, float, bool, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). May have any data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`equal(x1, x2)`](elementwise_functions.md#equalx1-x2-). -``` - -(method-__float__)= -### \_\_float\_\_(self, /) - -Converts a zero-dimensional floating-point array to a Python `float` object. - -#### Parameters - -- **self**: _<array>_ - - - zero-dimensional array instance. Must have a floating-point data type. - -#### Returns - -- **out**: _<float>_ - - - a Python `float` object representing the single element of the array instance. - -(method-__floordiv__)= -### \_\_floordiv\_\_(self, other, /) - -Evaluates `self_i // other_i` for each element of an array instance with the respective element of the array `other`. - -```{note} -For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. -``` - -#### Special Cases - -```{note} -Floor division was introduced in Python via [PEP 238](https://www.python.org/dev/peps/pep-0238/) with the goal to disambiguate "true division" (i.e., computing an approximation to the mathematical operation of division) from "floor division" (i.e., rounding the result of division toward negative infinity). The former was computed when one of the operands was a `float`, while the latter was computed when both operands were `int`s. Overloading the `/` operator to support both behaviors led to subtle numerical bugs when integers are possible, but not expected. - -To resolve this ambiguity, `/` was designated for true division, and `//` was designated for floor division. Semantically, floor division was [defined](https://www.python.org/dev/peps/pep-0238/#semantics-of-floor-division) as equivalent to `a // b == floor(a/b)`; however, special floating-point cases were left ill-defined. - -Accordingly, floor division is not implemented consistently across array libraries for some of the special cases documented below. Namely, when one of the operands is `infinity`, libraries may diverge with some choosing to strictly follow `floor(a/b)` and others choosing to pair `//` with `%` according to the relation `b = a % b + b * (a // b)`. The special cases leading to divergent behavior are documented below. - -This specification prefers floor division to match `floor(divide(x1, x2))` in order to avoid surprising and unexpected results; however, array libraries may choose to more strictly follow Python behavior. -``` - -For floating-point operands, let `self` equal `x1` and `other` equal `x2`. - -- If either `x1_i` or `x2_i` is `NaN`, the result is `NaN`. -- If `x1_i` is either `+infinity` or `-infinity` and `x2_i` is either `+infinity` or `-infinity`, the result is `NaN`. -- If `x1_i` is either `+0` or `-0` and `x2_i` is either `+0` or `-0`, the result is `NaN`. -- If `x1_i` is `+0` and `x2_i` is greater than `0`, the result is `+0`. -- If `x1_i` is `-0` and `x2_i` is greater than `0`, the result is `-0`. -- If `x1_i` is `+0` and `x2_i` is less than `0`, the result is `-0`. -- If `x1_i` is `-0` and `x2_i` is less than `0`, the result is `+0`. -- If `x1_i` is greater than `0` and `x2_i` is `+0`, the result is `+infinity`. -- If `x1_i` is greater than `0` and `x2_i` is `-0`, the result is `-infinity`. -- If `x1_i` is less than `0` and `x2_i` is `+0`, the result is `-infinity`. -- If `x1_i` is less than `0` and `x2_i` is `-0`, the result is `+infinity`. -- If `x1_i` is `+infinity` and `x2_i` is a positive (i.e., greater than `0`) finite number, the result is `+infinity`. (**note**: libraries may return `NaN` to match Python behavior.) -- If `x1_i` is `+infinity` and `x2_i` is a negative (i.e., less than `0`) finite number, the result is `-infinity`. (**note**: libraries may return `NaN` to match Python behavior.) -- If `x1_i` is `-infinity` and `x2_i` is a positive (i.e., greater than `0`) finite number, the result is `-infinity`. (**note**: libraries may return `NaN` to match Python behavior.) -- If `x1_i` is `-infinity` and `x2_i` is a negative (i.e., less than `0`) finite number, the result is `+infinity`. (**note**: libraries may return `NaN` to match Python behavior.) -- If `x1_i` is a positive (i.e., greater than `0`) finite number and `x2_i` is `+infinity`, the result is `+0`. -- If `x1_i` is a positive (i.e., greater than `0`) finite number and `x2_i` is `-infinity`, the result is `-0`. (**note**: libraries may return `-1.0` to match Python behavior.) -- If `x1_i` is a negative (i.e., less than `0`) finite number and `x2_i` is `+infinity`, the result is `-0`. (**note**: libraries may return `-1.0` to match Python behavior.) -- If `x1_i` is a negative (i.e., less than `0`) finite number and `x2_i` is `-infinity`, the result is `+0`. -- If `x1_i` and `x2_i` have the same mathematical sign and are both nonzero finite numbers, the result has a positive mathematical sign. -- If `x1_i` and `x2_i` have different mathematical signs and are both nonzero finite numbers, the result has a negative mathematical sign. -- In the remaining cases, where neither `-infinity`, `+0`, `-0`, nor `NaN` is involved, the quotient must be computed and rounded to the greatest (i.e., closest to `+infinity`) representable integer-value number that is not greater than the division result. If the magnitude is too large to represent, the operation overflows and the result is an `infinity` of appropriate mathematical sign. If the magnitude is too small to represent, the operation underflows and the result is a zero of appropriate mathematical sign. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`floor_divide(x1, x2)`](elementwise_functions.md#floor_dividex1-x2-). -``` - -(method-__ge__)= -### \_\_ge\_\_(self, other, /) - -Computes the truth value of `self_i >= other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`greater_equal(x1, x2)`](elementwise_functions.md#greater_equalx1-x2-). -``` - -(method-__getitem__)= -### \_\_getitem\_\_(self, key, /) - -Returns `self[key]`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -- **key**: _Union\[ int, slice, ellipsis, Tuple\[ Union\[ int, slice, ellipsis ], ... ], <array> ]_ - - - index key. - -#### Returns - -- **out**: _<array>_ - - - an array containing the accessed value(s). The returned array must have the same data type as `self`. - -(method-__gt__)= -### \_\_gt\_\_(self, other, /) - -Computes the truth value of `self_i > other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`greater(x1, x2)`](elementwise_functions.md#greaterx1-x2-). -``` - -(method-__index__)= -### \_\_index\_\_(self, /) - -Converts a zero-dimensional integer array to a Python `int` object. - -```{note} -This method is called to implement [`operator.index()`](https://docs.python.org/3/reference/datamodel.html#object.__index__). See also [PEP 357](https://www.python.org/dev/peps/pep-0357/). -``` - -#### Parameters - -- **self**: _<array>_ - - - zero-dimensional array instance. Must have an integer data type. - -#### Returns - -- **out**: _<int>_ - - - a Python `int` object representing the single element of the array instance. - -(method-__int__)= -### \_\_int\_\_(self, /) - -Converts a zero-dimensional integer array to a Python `int` object. - -#### Parameters - -- **self**: _<array>_ - - - zero-dimensional array instance. Must have an integer data type. - -#### Returns - -- **out**: _<int>_ - - - a Python `int` object representing the single element of the array instance. - -(method-__invert__)= -### \_\_invert\_\_(self, /) - -Evaluates `~self_i` for each element of an array instance. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer or boolean data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have the same data type as `self`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_invert(x)`](elementwise_functions.md#bitwise_invertx-). -``` - -(method-__le__)= -### \_\_le\_\_(self, other, /) - -Computes the truth value of `self_i <= other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`less_equal(x1, x2)`](elementwise_functions.md#less_equalx1-x2-). -``` - -(method-__lshift__)= -### \_\_lshift\_\_(self, other, /) - -Evaluates `self_i << other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer data type. - -- **other**: _Union\[ int, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have an integer data type. Each element must be greater than or equal to `0`. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have the same data type as `self`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_left_shift(x1, x2)`](elementwise_functions.md#bitwise_left_shiftx1-x2-). -``` - -(method-__lt__)= -### \_\_lt\_\_(self, other, /) - -Computes the truth value of `self_i < other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`less(x1, x2)`](elementwise_functions.md#lessx1-x2-). -``` - -(method-__matmul__)= -### \_\_matmul\_\_(self, other, /) - -Computes the matrix product. - -```{note} -The `matmul` function must implement the same semantics as the built-in `@` operator (see [PEP 465](https://www.python.org/dev/peps/pep-0465)). -``` - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. Must have at least one dimension. If `self` is one-dimensional having shape `(M,)` and `other` has more than one dimension, `self` must be promoted to a two-dimensional array by prepending `1` to its dimensions (i.e., must have shape `(1, M)`). After matrix multiplication, the prepended dimensions in the returned array must be removed. If `self` has more than one dimension (including after vector-to-matrix promotion), `shape(self)[:-2]` must be compatible with `shape(other)[:-2]` (after vector-to-matrix promotion) (see {ref}`broadcasting`). If `self` has shape `(..., M, K)`, the innermost two dimensions form matrices on which to perform matrix multiplication. - -- **other**: _<array>_ - - - other array. Should have a numeric data type. Must have at least one dimension. If `other` is one-dimensional having shape `(N,)` and `self` has more than one dimension, `other` must be promoted to a two-dimensional array by appending `1` to its dimensions (i.e., must have shape `(N, 1)`). After matrix multiplication, the appended dimensions in the returned array must be removed. If `other` has more than one dimension (including after vector-to-matrix promotion), `shape(other)[:-2]` must be compatible with `shape(self)[:-2]` (after vector-to-matrix promotion) (see {ref}`broadcasting`). If `other` has shape `(..., K, N)`, the innermost two dimensions form matrices on which to perform matrix multiplication. - -#### Returns - -- **out**: _<array>_ - - - if both `self` and `other` are one-dimensional arrays having shape `(N,)`, a zero-dimensional array containing the inner product as its only element. - - if `self` is a two-dimensional array having shape `(M, K)` and `other` is a two-dimensional array having shape `(K, N)`, a two-dimensional array containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication) and having shape `(M, N)`. - - if `self` is a one-dimensional array having shape `(K,)` and `other` is an array having shape `(..., K, N)`, an array having shape `(..., N)` (i.e., prepended dimensions during vector-to-matrix promotion must be removed) and containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication). - - if `self` is an array having shape `(..., M, K)` and `other` is a one-dimensional array having shape `(K,)`, an array having shape `(..., M)` (i.e., appended dimensions during vector-to-matrix promotion must be removed) and containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication). - - if `self` is a two-dimensional array having shape `(M, K)` and `other` is an array having shape `(..., K, N)`, an array having shape `(..., M, N)` and containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication) for each stacked matrix. - - if `self` is an array having shape `(..., M, K)` and `other` is a two-dimensional array having shape `(K, N)`, an array having shape `(..., M, N)` and containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication) for each stacked matrix. - - if either `self` or `other` has more than two dimensions, an array having a shape determined by {ref}`broadcasting` `shape(self)[:-2]` against `shape(other)[:-2]` and containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication) for each stacked matrix. - - The returned array must have a data type determined by {ref}`type-promotion`. - - ```{note} - Results must equal the results returned by the equivalent function [`matmul(x1, x2)`](linear_algebra_functions.md#matmulx1-x2-). - ``` - -#### Raises - -- if either `self` or `other` is a zero-dimensional array. -- if `self` is a one-dimensional array having shape `(K,)`, `other` is a one-dimensional array having shape `(L,)`, and `K != L`. -- if `self` is a one-dimensional array having shape `(K,)`, `other` is an array having shape `(..., L, N)`, and `K != L`. -- if `self` is an array having shape `(..., M, K)`, `other` is a one-dimensional array having shape `(L,)`, and `K != L`. -- if `self` is an array having shape `(..., M, K)`, `other` is an array having shape `(..., L, N)`, and `K != L`. - -(method-__mod__)= -### \_\_mod\_\_(self, other, /) - -Evaluates `self_i % other_i` for each element of an array instance with the respective element of the array `other`. - -```{note} -For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. -``` - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. Each element-wise result must have the same sign as the respective element `other_i`. The returned array must have a floating-point data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`remainder(x1, x2)`](elementwise_functions.md#remainderx1-x2-). -``` - -(method-__mul__)= -### \_\_mul\_\_(self, other, /) - -Calculates the product for each element of an array instance with the respective element of the array `other`. - -#### Special Cases - -For floating-point operands, let `self` equal `x1` and `other` equal `x2`. - -- If either `x1_i` or `x2_i` is `NaN`, the result is `NaN`. -- If `x1_i` is either `+infinity` or `-infinity` and `x2_i` is either `+0` or `-0`, the result is `NaN`. -- If `x1_i` is either `+0` or `-0` and `x2_i` is either `+infinity` or `-infinity`, the result is `NaN`. -- If `x1_i` and `x2_i` have the same mathematical sign, the result has a positive mathematical sign, unless the result is `NaN`. If the result is `NaN`, the "sign" of `NaN` is implementation-defined. -- If `x1_i` and `x2_i` have different mathematical signs, the result has a negative mathematical sign, unless the result is `NaN`. If the result is `NaN`, the "sign" of `NaN` is implementation-defined. -- If `x1_i` is either `+infinity` or `-infinity` and `x2_i` is either `+infinity` or `-infinity`, the result is a signed infinity with the mathematical sign determined by the rule already stated above. -- If `x1_i` is either `+infinity` or `-infinity` and `x2_i` is a nonzero finite number, the result is a signed infinity with the mathematical sign determined by the rule already stated above. -- If `x1_i` is a nonzero finite number and `x2_i` is either `+infinity` or `-infinity`, the result is a signed infinity with the mathematical sign determined by the rule already stated above. -- In the remaining cases, where neither `infinity` nor `NaN` is involved, the product must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported rounding mode. If the magnitude is too large to represent, the result is an `infinity` of appropriate mathematical sign. If the magnitude is too small to represent, the result is a zero of appropriate mathematical sign. - -```{note} -Floating-point multiplication is not always associative due to finite precision. -``` - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise products. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`multiply(x1, x2)`](elementwise_functions.md#multiplyx1-x2-). -``` - -(method-__ne__)= -### \_\_ne\_\_(self, other, /) - -Computes the truth value of `self_i != other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. May have any data type. - -- **other**: _Union\[ int, float, bool, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). May have any data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool` (i.e., must be a boolean array). - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`not_equal(x1, x2)`](elementwise_functions.md#not_equalx1-x2-). -``` - -(method-__neg__)= -### \_\_neg\_\_(self, /) - -Evaluates `-self_i` for each element of an array instance. - -```{note} -For signed integer data types, the numerical negative of the minimum representable integer is implementation-dependent. -``` - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the evaluated result for each element in `self`. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`negative(x)`](elementwise_functions.md#negativex-). -``` - -(method-__or__)= -### \_\_or\_\_(self, other, /) - -Evaluates `self_i | other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer or boolean data type. - -- **other**: _Union\[ int, bool, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have an integer or boolean data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_or(x1, x2)`](elementwise_functions.md#bitwise_orx1-x2-). -``` - -(method-__pos__)= -### \_\_pos\_\_(self, /) - -Evaluates `+self_i` for each element of an array instance. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the evaluated result for each element. The returned array must have the same data type as `self`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`positive(x)`](elementwise_functions.md#positivex-). -``` - -(method-__pow__)= -### \_\_pow\_\_(self, other, /) - -Calculates an implementation-dependent approximation of exponentiation by raising each element (the base) of an array instance to the power of `other_i` (the exponent), where `other_i` is the corresponding element of the array `other`. - -```{note} -If both `self` and `other` have integer data types, the result of `__pow__` when `other_i` is negative (i.e., less than zero) is unspecified and thus implementation-dependent. - -If `self` has an integer data type and `other` has a floating-point data type, behavior is implementation-dependent (type promotion between data type "kinds" (integer versus floating-point) is unspecified). -``` - -#### Special Cases - -For floating-point operands, let `self` equal `x1` and `other` equal `x2`. - -- If `x1_i` is not equal to `1` and `x2_i` is `NaN`, the result is `NaN`. -- If `x2_i` is `+0`, the result is `1`, even if `x1_i` is `NaN`. -- If `x2_i` is `-0`, the result is `1`, even if `x1_i` is `NaN`. -- If `x1_i` is `NaN` and `x2_i` is not equal to `0`, the result is `NaN`. -- If `abs(x1_i)` is greater than `1` and `x2_i` is `+infinity`, the result is `+infinity`. -- If `abs(x1_i)` is greater than `1` and `x2_i` is `-infinity`, the result is `+0`. -- If `abs(x1_i)` is `1` and `x2_i` is `+infinity`, the result is `1`. -- If `abs(x1_i)` is `1` and `x2_i` is `-infinity`, the result is `1`. -- If `x1_i` is `1` and `x2_i` is not `NaN`, the result is `1`. -- If `abs(x1_i)` is less than `1` and `x2_i` is `+infinity`, the result is `+0`. -- If `abs(x1_i)` is less than `1` and `x2_i` is `-infinity`, the result is `+infinity`. -- If `x1_i` is `+infinity` and `x2_i` is greater than `0`, the result is `+infinity`. -- If `x1_i` is `+infinity` and `x2_i` is less than `0`, the result is `+0`. -- If `x1_i` is `-infinity`, `x2_i` is greater than `0`, and `x2_i` is an odd integer value, the result is `-infinity`. -- If `x1_i` is `-infinity`, `x2_i` is greater than `0`, and `x2_i` is not an odd integer value, the result is `+infinity`. -- If `x1_i` is `-infinity`, `x2_i` is less than `0`, and `x2_i` is an odd integer value, the result is `-0`. -- If `x1_i` is `-infinity`, `x2_i` is less than `0`, and `x2_i` is not an odd integer value, the result is `+0`. -- If `x1_i` is `+0` and `x2_i` is greater than `0`, the result is `+0`. -- If `x1_i` is `+0` and `x2_i` is less than `0`, the result is `+infinity`. -- If `x1_i` is `-0`, `x2_i` is greater than `0`, and `x2_i` is an odd integer value, the result is `-0`. -- If `x1_i` is `-0`, `x2_i` is greater than `0`, and `x2_i` is not an odd integer value, the result is `+0`. -- If `x1_i` is `-0`, `x2_i` is less than `0`, and `x2_i` is an odd integer value, the result is `-infinity`. -- If `x1_i` is `-0`, `x2_i` is less than `0`, and `x2_i` is not an odd integer value, the result is `+infinity`. -- If `x1_i` is less than `0`, `x1_i` is a finite number, `x2_i` is a finite number, and `x2_i` is not an integer value, the result is `NaN`. - -#### Parameters - -- **self**: _<array>_ - - - array instance whose elements correspond to the exponentiation base. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array whose elements correspond to the exponentiation exponent. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`pow(x1, x2)`](elementwise_functions.md#powx1-x2-). -``` - -(method-__rshift__)= -### \_\_rshift\_\_(self, other, /) - -Evaluates `self_i >> other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer data type. - -- **other**: _Union\[ int, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have an integer data type. Each element must be greater than or equal to `0`. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have the same data type as `self`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_right_shift(x1, x2)`](elementwise_functions.md#bitwise_right_shiftx1-x2-). -``` - -(method-__setitem__)= -### \_\_setitem\_\_(self, key, value, /) - -Sets `self[key]` to `value`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -- **key**: _Union\[ int, slice, ellipsis, Tuple\[ Union\[ int, slice, ellipsis ], ... ], <array> ]_ - - - index key. - -- **value**: _Union\[ int, float, bool, <array> ]_ - - - value(s) to set. Must be compatible with `self[key]` (see {ref}`broadcasting`). - -```{note} -Setting array values must not affect the data type of `self`. - -When `value` is a Python scalar (i.e., `int`, `float`, `bool`), behavior must follow specification guidance on mixing arrays with Python scalars (see {ref}`type-promotion`). - -When `value` is an `array` of a different data type than `self`, how values are cast to the data type of `self` is implementation defined. -``` - -(method-__sub__)= -### \_\_sub\_\_(self, other, /) - -Calculates the difference for each element of an array instance with the respective element of the array `other`. The result of `self_i - other_i` must be the same as `self_i + (-other_i)` and must be governed by the same floating-point rules as addition (see [`__add__()`](#__add__self-other-)). - -#### Parameters - -- **self**: _<array>_ - - - array instance (minuend array). Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - subtrahend array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise differences. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`subtract(x1, x2)`](elementwise_functions.md#subtractx1-x2-). -``` - -(method-__truediv__)= -### \_\_truediv\_\_(self, other, /) - -Evaluates `self_i / other_i` for each element of an array instance with the respective element of the array `other`. - -#### Special Cases - -For floating-point operands, let `self` equal `x1` and `other` equal `x2`. - -- If either `x1_i` or `x2_i` is `NaN`, the result is `NaN`. -- If `x1_i` is either `+infinity` or `-infinity` and `x2_i` is either `+infinity` or `-infinity`, the result is `NaN`. -- If `x1_i` is either `+0` or `-0` and `x2_i` is either `+0` or `-0`, the result is `NaN`. -- If `x1_i` is `+0` and `x2_i` is greater than `0`, the result is `+0`. -- If `x1_i` is `-0` and `x2_i` is greater than `0`, the result is `-0`. -- If `x1_i` is `+0` and `x2_i` is less than `0`, the result is `-0`. -- If `x1_i` is `-0` and `x2_i` is less than `0`, the result is `+0`. -- If `x1_i` is greater than `0` and `x2_i` is `+0`, the result is `+infinity`. -- If `x1_i` is greater than `0` and `x2_i` is `-0`, the result is `-infinity`. -- If `x1_i` is less than `0` and `x2_i` is `+0`, the result is `-infinity`. -- If `x1_i` is less than `0` and `x2_i` is `-0`, the result is `+infinity`. -- If `x1_i` is `+infinity` and `x2_i` is a positive (i.e., greater than `0`) finite number, the result is `+infinity`. -- If `x1_i` is `+infinity` and `x2_i` is a negative (i.e., less than `0`) finite number, the result is `-infinity`. -- If `x1_i` is `-infinity` and `x2_i` is a positive (i.e., greater than `0`) finite number, the result is `-infinity`. -- If `x1_i` is `-infinity` and `x2_i` is a negative (i.e., less than `0`) finite number, the result is `+infinity`. -- If `x1_i` is a positive (i.e., greater than `0`) finite number and `x2_i` is `+infinity`, the result is `+0`. -- If `x1_i` is a positive (i.e., greater than `0`) finite number and `x2_i` is `-infinity`, the result is `-0`. -- If `x1_i` is a negative (i.e., less than `0`) finite number and `x2_i` is `+infinity`, the result is `-0`. -- If `x1_i` is a negative (i.e., less than `0`) finite number and `x2_i` is `-infinity`, the result is `+0`. -- If `x1_i` and `x2_i` have the same mathematical sign and are both nonzero finite numbers, the result has a positive mathematical sign. -- If `x1_i` and `x2_i` have different mathematical signs and are both nonzero finite numbers, the result has a negative mathematical sign. -- In the remaining cases, where neither `-infinity`, `+0`, `-0`, nor `NaN` is involved, the quotient must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported rounding mode. If the magnitude is too large to represent, the operation overflows and the result is an `infinity` of appropriate mathematical sign. If the magnitude is too small to represent, the operation underflows and the result is a zero of appropriate mathematical sign. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array should have a floating-point data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`divide(x1, x2)`](elementwise_functions.md#dividex1-x2-). -``` - -(method-__xor__)= -### \_\_xor\_\_(self, other, /) - -Evaluates `self_i ^ other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer or boolean data type. - -- **other**: _Union\[ int, bool, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have an integer or boolean data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_xor(x1, x2)`](elementwise_functions.md#bitwise_xorx1-x2-). -``` - -(method-to_device)= -### to\_device(self, device, /, *, stream=None) - -Copy the array from the device on which it currently resides to the specified `device`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -- **device**: _<device>_ - - - a `device` object (see {ref}`device-support`). - -- **stream**: _Optional\[ Union\[ int, Any ]]_ - - - stream object to use during copy. In addition to the types supported in {ref}`method-__dlpack__`, implementations may choose to support any library-specific stream object with the caveat that any code using such an object would not be portable. - -#### Returns - -- **out**: _<array>_ - - - an array with the same data and data type as `self` and located on the specified `device`. - -```{note} -If `stream` is given, the copy operation should be enqueued on the provided `stream`; otherwise, the copy operation should be enqueued on the default stream/queue. Whether the copy is performed synchronously or asynchronously is implementation-dependent. Accordingly, if synchronization is required to guarantee data safety, this must be clearly explained in a conforming library's documentation. -``` diff --git a/spec/API_specification/array_object.rst b/spec/API_specification/array_object.rst new file mode 100644 index 000000000..33a6e9e86 --- /dev/null +++ b/spec/API_specification/array_object.rst @@ -0,0 +1,311 @@ +.. _array-object: + +Array object +============ + + Array API specification for array object attributes and methods. + +A conforming implementation of the array API standard must provide and support an array object having the following attributes and methods adhering to the following conventions. + +* Positional parameters must be `positional-only `_ parameters. Positional-only parameters have no externally-usable name. When a method accepting positional-only parameters is called, positional arguments are mapped to these parameters based solely on their order. +* Optional parameters must be `keyword-only `_ arguments. +* Broadcasting semantics must follow the semantics defined in :ref:`broadcasting`. +* Unless stated otherwise, methods must support the data types defined in :ref:`data-types`. +* Unless stated otherwise, methods must adhere to the type promotion rules defined in :ref:`type-promotion`. +* Unless stated otherwise, floating-point operations must adhere to IEEE 754-2019. + +Furthermore, a conforming implementation of the array API standard must support array objects of arbitrary rank ``N`` (i.e., number of dimensions), where ``N`` is greater than or equal to zero. + +.. note:: + Conforming implementations must support zero-dimensional arrays. + + Apart from array object attributes, such as ``ndim``, ``device``, and ``dtype``, all operations in this standard return arrays (or tuples of arrays), including those operations, such as ``mean``, ``var``, and ``std``, from which some common array libraries (e.g., NumPy) return scalar values. + + *Rationale: always returning arrays is necessary to (1) support accelerator libraries where non-array return values could force device synchronization and (2) support delayed execution models where an array represents a future value.* + +------------------------------------------------- + +.. _operators: + +Operators +--------- + +A conforming implementation of the array API standard must provide and support an array object supporting the following Python operators. + +Arithmetic Operators +~~~~~~~~~~~~~~~~~~~~ + +A conforming implementation of the array API standard must provide and support an array object supporting the following Python arithmetic operators. + +- ``+x``: :meth:`array.__pos__` + + - `operator.pos(x) `_ + - `operator.__pos__(x) `_ + +- `-x`: :meth:`array.__neg__` + + - `operator.neg(x) `_ + - `operator.__neg__(x) `_ + +- `x1 + x2`: :meth:`array.__add__` + + - `operator.add(x1, x2) `_ + - `operator.__add__(x1, x2) `_ + +- `x1 - x2`: :meth:`array.__sub__` + + - `operator.sub(x1, x2) `_ + - `operator.__sub__(x1, x2) `_ + +- `x1 * x2`: :meth:`array.__mul__` + + - `operator.mul(x1, x2) `_ + - `operator.__mul__(x1, x2) `_ + +- `x1 / x2`: :meth:`array.__truediv__` + + - `operator.truediv(x1,x2) `_ + - `operator.__truediv__(x1, x2) `_ + +- `x1 // x2`: :meth:`array.__floordiv__` + + - `operator.floordiv(x1, x2) `_ + - `operator.__floordiv__(x1, x2) `_ + +- `x1 % x2`: :meth:`array.__mod__` + + - `operator.mod(x1, x2) `_ + - `operator.__mod__(x1, x2) `_ + +- `x1 ** x2`: :meth:`array.__pow__` + + - `operator.pow(x1, x2) `_ + - `operator.__pow__(x1, x2) `_ + +Arithmetic operators should be defined for arrays having numeric data types. + +Array Operators +~~~~~~~~~~~~~~~ + +A conforming implementation of the array API standard must provide and support an array object supporting the following Python array operators. + +- `x1 @ x2`: :meth:`array.__matmul__` + + - `operator.matmul(x1, x2) `_ + - `operator.__matmul__(x1, x2) `_ + +The matmul ``@`` operator should be defined for arrays having numeric data types. + +Bitwise Operators +~~~~~~~~~~~~~~~~~ + +A conforming implementation of the array API standard must provide and support an array object supporting the following Python bitwise operators. + +- `~x`: :meth:`array.__invert__` + + - `operator.inv(x) `_ + - `operator.invert(x) `_ + - `operator.__inv__(x) `_ + - `operator.__invert__(x) `_ + +- `x1 & x2`: :meth:`array.__and__` + + - `operator.and(x1, x2) `_ + - `operator.__and__(x1, x2) `_ + +- `x1 | x2`: :meth:`array.__or__` + + - `operator.or(x1, x2) `_ + - `operator.__or__(x1, x2) `_ + +- `x1 ^ x2`: :meth:`array.__xor__` + + - `operator.xor(x1, x2) `_ + - `operator.__xor__(x1, x2) `_ + +- `x1 << x2`: :meth:`array.__lshift__` + + - `operator.lshift(x1, x2) `_ + - `operator.__lshift__(x1, x2) `_ + +- `x1 >> x2`: :meth:`array.__rshift__` + + - `operator.rshift(x1, x2) `_ + - `operator.__rshift__(x1, x2) `_ + +Bitwise operators should be defined for arrays having integer and boolean data types. + +Comparison Operators +~~~~~~~~~~~~~~~~~~~~ + +A conforming implementation of the array API standard must provide and support an array object supporting the following Python comparison operators. + +- `x1 < x2`: :meth:`array.__lt__` + + - `operator.lt(x1, x2) `_ + - `operator.__lt__(x1, x2) `_ + +- `x1 <= x2`: :meth:`array.__le__` + + - `operator.le(x1, x2) `_ + - `operator.__le__(x1, x2) `_ + +- `x1 > x2`: :meth:`array.__gt__` + + - `operator.gt(x1, x2) `_ + - `operator.__gt__(x1, x2) `_ + +- `x1 >= x2`: :meth:`array.__ge__` + + - `operator.ge(x1, x2) `_ + - `operator.__ge__(x1, x2) `_ + +- `x1 == x2`: :meth:`array.__eq__` + + - `operator.eq(x1, x2) `_ + - `operator.__eq__(x1, x2) `_ + +- `x1 != x2`: :meth:`array.__ne__` + + - `operator.ne(x1, x2) `_ + - `operator.__ne__(x1, x2) `_ + +Comparison operators should be defined for arrays having any data type. + +In-place Operators +~~~~~~~~~~~~~~~~~~ + +A conforming implementation of the array API standard must provide and support an array object supporting the following in-place Python operators. + +An in-place operation must not change the data type or shape of the in-place array as a result of :ref:`type-promotion` or :ref:`broadcasting`. + +An in-place operation must have the same behavior (including special cases) as its respective binary (i.e., two operand, non-assignment) operation. For example, after in-place addition ``x1 += x2``, the modified array ``x1`` must always equal the result of the equivalent binary arithmetic operation ``x1 = x1 + x2``. + +.. note:: +In-place operators must be supported as discussed in :ref:`copyview-mutability`. + +Arithmetic Operators +"""""""""""""""""""" + +- ``+=``. May be implemented via ``__iadd__``. +- ``-=``. May be implemented via ``__isub__``. +- ``*=``. May be implemented via ``__imul__``. +- ``/=``. May be implemented via ``__itruediv__``. +- ``//=``. May be implemented via ``__ifloordiv__``. +- ``**=``. May be implemented via ``__ipow__``. +- ``%=``. May be implemented via ``__imod__``. + +Array Operators +""""""""""""""" + +- ``@=``. May be implemented via ``__imatmul__``. + +Bitwise Operators +""""""""""""""""" + +- ``&=``. May be implemented via ``__iand__``. +- ``|=``. May be implemented via ``__ior__``. +- ``^=``. May be implemented via ``__ixor__``. +- ``<<=``. May be implemented via ``__ilshift__``. +- ``>>=``. May be implemented via ``__irshift__``. + +Reflected Operators +~~~~~~~~~~~~~~~~~~~ + +A conforming implementation of the array API standard must provide and support an array object supporting the following reflected operators. + +The results of applying reflected operators must match their non-reflected equivalents. + +.. note:: +All operators for which ``array scalar`` is implemented must have an equivalent reflected operator implementation. + +Arithmetic Operators +"""""""""""""""""""" + +- ``__radd__`` +- ``__rsub__`` +- ``__rmul__`` +- ``__rtruediv__`` +- ``__rfloordiv__`` +- ``__rpow__`` +- ``__rmod__`` + +Array Operators +""""""""""""""" + +- ``__rmatmul__`` + +Bitwise Operators +""""""""""""""""" + +- ``__rand__`` +- ``__ror__`` +- ``__rxor__`` +- ``__rlshift__`` +- ``__rrshift__`` + +------------------------------------------------- + +.. currentmodule:: signatures.array_object + +Attributes +---------- +.. + NOTE: please keep the attributes in alphabetical order + + +.. autosummary:: + :toctree: generated + + array.dtype + array.device + array.mT + array.ndim + array.shape + array.size + array.T + +------------------------------------------------- + +Methods +------- +.. + NOTE: please keep the methods in alphabetical order + + +.. autosummary:: + :toctree: generated + + array.__abs__ + array.__add__ + array.__and__ + array.__array_namespace__ + array.__bool__ + array.__dlpack__ + array.__dlpack_device__ + array.__eq__ + array.__float__ + array.__floordiv__ + array.__ge__ + array.__getitem__ + array.__gt__ + array.__index__ + array.__int__ + array.__invert__ + array.__le__ + array.__lshift__ + array.__lt__ + array.__matmul__ + array.__mod__ + array.__mul__ + array.__ne__ + array.__neg__ + array.__or__ + array.__pos__ + array.__pow__ + array.__rshift__ + array.__setitem__ + array.__sub__ + array.__truediv__ + array.__xor__ + array.to_device diff --git a/spec/API_specification/signatures/_types.py b/spec/API_specification/signatures/_types.py index 6c0b5b85a..6e624d542 100644 --- a/spec/API_specification/signatures/_types.py +++ b/spec/API_specification/signatures/_types.py @@ -7,6 +7,7 @@ from dataclasses import dataclass from typing import Any, List, Literal, Optional, Sequence, Tuple, TypeVar, Union +from enum import Enum array = TypeVar('array') device = TypeVar('device') @@ -37,4 +38,4 @@ class iinfo_object: __all__ = ['Any', 'List', 'Literal', 'NestedSequence', 'Optional', 'PyCapsule', 'SupportsBufferProtocol', 'SupportsDLPack', 'Tuple', 'Union', -'array', 'device', 'dtype', 'ellipsis', 'finfo_object', 'iinfo_object'] \ No newline at end of file +'array', 'device', 'dtype', 'ellipsis', 'finfo_object', 'iinfo_object', 'Enum'] \ No newline at end of file diff --git a/spec/API_specification/signatures/array_object.py b/spec/API_specification/signatures/array_object.py new file mode 100644 index 000000000..0562a90b3 --- /dev/null +++ b/spec/API_specification/signatures/array_object.py @@ -0,0 +1,942 @@ +from ._types import array, dtype, device, Optional, Tuple, Union, Any, PyCapsule, Enum, ellipsis + +class array(): + def __init__(self) -> None: + """ + Initialize the attributes for the array object class. + """ + + self.dtype = None + """ + Data type of the array elements. + + Returns + ------- + out: dtype + array data type. + """ + + self.device = None + """ + Hardware device the array data resides on. + + Returns + ------- + out: device + a ``device`` object (see :ref:`device-support`). + """ + + self.mT = None + """ + Transpose of a matrix (or a stack of matrices). + + If an array instance has fewer than two dimensions, an error should be raised. + + Returns + ------- + out: array + array whose last two dimensions (axes) are permuted in reverse order relative to original array (i.e., for an array instance having shape ``(..., M, N)``, the returned array must have shape ``(..., N, M)``). The returned array must have the same data type as the original array. + """ + + self.ndim = None + """ + Number of array dimensions (axes). + + Returns + ------- + out: int + number of array dimensions (axes). + """ + + self.shape = None + """ + Array dimensions. + + Returns + ------- + out: Tuple[Optional[int], ...] + array dimensions. An array dimension must be ``None`` if and only if a dimension is unknown. + + Notes + ----- + - For array libraries having graph-based computational models, array dimensions may be unknown due to data-dependent operations (e.g., boolean indexing; ``A[:, B > 0]``) and thus cannot be statically resolved without knowing array contents. + + - The returned value should be a tuple; however, where warranted, an array library may choose to return a custom shape object. If an array library returns a custom shape object, the object must be immutable, must support indexing for dimension retrieval, and must behave similarly to a tuple. + """ + + self.size = None + """ + Number of elements in an array. + + Returns + ------- + out: Optional[int] + number of elements in an array. The returned value must be ``None`` if and only if one or more array dimensions are unknown. + + Notes + ----- + - This must equal the product of the array's dimensions. + + - For array libraries having graph-based computational models, an array may have unknown dimensions due to data-dependent operations. + """ + + self.T = None + """ + Transpose of the array. + + The array instance must be two-dimensional. If the array instance is not two-dimensional, an error should be raised. + + Returns + ------- + out: array + two-dimensional array whose first and last dimensions (axes) are permuted in reverse order relative to original array. The returned array must have the same data type as the original array.two-dimensional array whose first and last dimensions (axes) are permuted in reverse order relative to original array. The returned array must have the same data type as the original array. + + Notes + ----- + - Limiting the transpose to two-dimensional arrays (matrices) deviates from the NumPy et al practice of reversing all axes for arrays having more than two-dimensions. This is intentional, as reversing all axes was found to be problematic (e.g., conflicting with the mathematical definition of a transpose which is limited to matrices; not operating on batches of matrices; et cetera). In order to reverse all axes, one is recommended to use the functional ``permute_dims`` interface found in this specification. + """ + + def __abs__(self: array, /) -> array: + """ + Calculates the absolute value for each element of an array instance (i.e., the element-wise result has the same magnitude as the respective element but has positive sign). + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise absolute value. The returned array must have the same data type as ``self``. + + Notes + ----- + - For signed integer data types, the absolute value of the minimum representable integer is implementation-dependent. + + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-abs`. + + **Special cases** + + For floating-point operands, let ``self`` equal ``x``. + + - If ``x_i`` is ``NaN``, the result is ``NaN``. + - If ``x_i`` is ``-0``, the result is ``+0``. + - If ``x_i`` is ``-infinity``, the result is ``+infinity``. + """ + + def __add__(self: array, other: Union[int, float, array], /) -> array: + """ + Calculates the sum for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance (augend array). Should have a numeric data type. + other: Union[int, float, array] + addend array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise sums. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + - Floating-point addition is a commutative operation, but not always associative. + + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-add`. + + **Special cases** + + For floating-point operands, let ``self`` equal ``x1`` and ``other`` equal ``x2``. + + - If either ``x1_i`` or ``x2_i`` is ``NaN``, the result is ``NaN``. + - If ``x1_i`` is ``+infinity`` and ``x2_i`` is ``-infinity``, the result is ``NaN``. + - If ``x1_i`` is ``-infinity`` and ``x2_i`` is ``+infinity``, the result is ``NaN``. + - If ``x1_i`` is ``+infinity`` and ``x2_i`` is ``+infinity``, the result is ``+infinity``. + - If ``x1_i`` is ``-infinity`` and ``x2_i`` is ``-infinity``, the result is ``-infinity``. + - If ``x1_i`` is ``+infinity`` and ``x2_i`` is a finite number, the result is ``+infinity``. + - If ``x1_i`` is ``-infinity`` and ``x2_i`` is a finite number, the result is ``-infinity``. + - If ``x1_i`` is a finite number and ``x2_i`` is ``+infinity``, the result is ``+infinity``. + - If ``x1_i`` is a finite number and ``x2_i`` is ``-infinity``, the result is ``-infinity``. + - If ``x1_i`` is ``-0`` and ``x2_i`` is ``-0``, the result is ``-0``. + - If ``x1_i`` is ``-0`` and ``x2_i`` is ``+0``, the result is ``+0``. + - If ``x1_i`` is ``+0`` and ``x2_i`` is ``-0``, the result is ``+0``. + - If ``x1_i`` is ``+0`` and ``x2_i`` is ``+0``, the result is ``+0``. + - If ``x1_i`` is either ``+0`` or ``-0`` and ``x2_i`` is a nonzero finite number, the result is ``x2_i``. + - If ``x1_i`` is a nonzero finite number and ``x2_i`` is either ``+0`` or ``-0``, the result is ``x1_i``. + - If ``x1_i`` is a nonzero finite number and ``x2_i`` is ``-x1_i``, the result is ``+0``. + - In the remaining cases, when neither ``infinity``, ``+0``, ``-0``, nor a ``NaN`` is involved, and the operands have the same mathematical sign or have different magnitudes, the sum must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported round mode. If the magnitude is too large to represent, the operation overflows and the result is an ``infinity`` of appropriate mathematical sign. + """ + + def __and__(self: array, other: Union[int, bool, array], /) -> array: + """ + Evaluates ``self_i & other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have an integer or boolean data type. + other: Union[int, bool, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have an integer or boolean data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_and`. + """ + + def __array_namespace__(self: array, /, *, api_version: Optional[str] = None) -> object: + """ + Returns an object that has all the array API functions on it. + + Parameters + ---------- + self: array + array instance. + api_version: Optional[str] + string representing the version of the array API specification to be returned, in ``'YYYY.MM'`` form, for example, ``'2020.10'``. If it is ``None``, it should return the namespace corresponding to latest version of the array API specification. If the given version is invalid or not implemented for the given module, an error should be raised. Default: ``None``. + + Returns + ------- + out: object + an object representing the array API namespace. It should have every top-level function defined in the specification as an attribute. It may contain other public names as well, but it is recommended to only include those names that are part of the specification. + """ + + def __bool__(self: array, /) -> bool: + """ + Converts a zero-dimensional boolean array to a Python ``bool`` object. + + Parameters + ---------- + self: array + zero-dimensional array instance. Must have a boolean data type. + + Returns + ------- + out: bool + a Python ``bool`` object representing the single element of the array. + """ + + def __dlpack__(self: array, /, *, stream: Optional[Union[int, Any]] = None) -> PyCapsule: + """ + Exports the array for consumption by :ref:`function-from_dlpack` as a DLPack capsule. + + Parameters + ---------- + self: array + array instance. + stream: Optional[Union[int, Any]] + for CUDA and ROCm, a Python integer representing a pointer to a stream, on devices that support streams. ``stream`` is provided by the consumer to the producer to instruct the producer to ensure that operations can safely be performed on the array (e.g., by inserting a dependency between streams via "wait for event"). The pointer must be a positive integer or ``-1``. If ``stream`` is ``-1``, the value may be used by the consumer to signal "producer must not perform any synchronization". The ownership of the stream stays with the consumer. + On CPU and other device types without streams, only ``None`` is accepted. + + For other device types which do have a stream, queue or similar synchronization mechanism, the most appropriate type to use for `stream` is not yet determined. E.g., for SYCL one may want to use an object containing an in-order ``cl::sycl::queue``. This is allowed when libraries agree on such a convention, and may be standardized in a future version of this API standard. + + **Note** + + Support for a ``stream`` value other than ``None`` is optional and implementation-dependent. + + Device-specific notes: + + **CUDA** + + - ``None``: producer must assume the legacy default stream (default). + - ``1``: the legacy default stream. + - ``2``: the per-thread default stream. + - ``> 2``: stream number represented as a Python integer. + + ``0`` is disallowed due to its ambiguity: ``0`` could mean either ``None``, ``1``, or ``2``. + + **ROCm** + + - ``None``: producer must assume the legacy default stream (default). + - ``0``: the default stream. + - ``> 2``: stream number represented as a Python integer. + + Using ``1`` and ``2`` is not supported. + + **Tip** + + It is recommended that implementers explicitly handle streams. If + they use the legacy default stream, specifying ``1`` (CUDA) or ``0`` + (ROCm) is preferred. ``None`` is a safe default for developers who do + not want to think about stream handling at all, potentially at the + cost of more synchronization than necessary. + + Returns + ------- + capsule: PyCapsule + a DLPack capsule for the array. See :ref:`data-interchange` for details. + """ + + def __dlpack_device__(self: array, /) -> Tuple[Enum, int]: + """ + Returns device type and device ID in DLPack format. Meant for use within :ref:`function-from_dlpack`. + + Parameters + ---------- + self: array + array instance. + + Returns + ------- + device: Tuple[Enum, int] + a tuple ``(device_type, device_id)`` in DLPack format. Valid device type enum members are: + + - ``CPU = 1`` + - ``CUDA = 2`` + - ``CPU_PINNED = 3`` + - ``OPENCL = 4`` + - ``VULKAN = 7`` + - ``METAL = 8`` + - ``VPI = 9`` + - ``ROCM = 10`` + """ + + def __eq__(self: array, other: Union[int, float, bool, array], /) -> array: + """ + Computes the truth value of ``self_i == other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. May have any data type. + other: Union[int, float, bool, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). May have any data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type of ``bool``. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-equal`. + """ + + def __float__(self: array, /) -> float: + """ + Converts a zero-dimensional floating-point array to a Python ``float`` object. + + Parameters + ---------- + self: array + zero-dimensional array instance. Must have a floating-point data type. + + Returns + ------- + out: float + a Python ``float`` object representing the single element of the array instance. + """ + + def __floordiv__(self: array, other: Union[int, float, array], /) -> array: + """ + Evaluates ``self_i // other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + - For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-floor_divide`. + - Floor division was introduced in Python via `PEP 238 `_ with the goal to disambiguate "true division" (i.e., computing an approximation to the mathematical operation of division) from "floor division" (i.e., rounding the result of division toward negative infinity). The former was computed when one of the operands was a ``float``, while the latter was computed when both operands were ``int``s. Overloading the ``/`` operator to support both behaviors led to subtle numerical bugs when integers are possible, but not expected. To resolve this ambiguity, ``/`` was designated for true division, and ``//`` was designated for floor division. Semantically, floor division was `defined `_ as equivalent to ``a // b == floor(a/b)``; however, special floating-point cases were left ill-defined. Accordingly, floor division is not implemented consistently across array libraries for some of the special cases documented below. Namely, when one of the operands is ``infinity``, libraries may diverge with some choosing to strictly follow ``floor(a/b)`` and others choosing to pair ``//`` with ``%`` according to the relation ``b = a % b + b * (a // b)``. The special cases leading to divergent behavior are documented below. This specification prefers floor division to match ``floor(divide(x1, x2))`` in order to avoid surprising and unexpected results; however, array libraries may choose to more strictly follow Python behavior. + + **Special cases** + + For floating-point operands, let ``self`` equal ``x1`` and ``other`` equal ``x2``. + + - If either ``x1_i`` or ``x2_i`` is ``NaN``, the result is ``NaN``. + - If ``x1_i`` is either ``+infinity`` or ``-infinity`` and ``x2_i`` is either ``+infinity`` or ``-infinity``, the result is ``NaN``. + - If ``x1_i`` is either ``+0`` or ``-0`` and ``x2_i`` is either ``+0`` or ``-0``, the result is ``NaN``. + - If ``x1_i`` is ``+0`` and ``x2_i`` is greater than ``0``, the result is ``+0``. + - If ``x1_i`` is ``-0`` and ``x2_i`` is greater than ``0``, the result is ``-0``. + - If ``x1_i`` is ``+0`` and ``x2_i`` is less than ``0``, the result is ``-0``. + - If ``x1_i`` is ``-0`` and ``x2_i`` is less than ``0``, the result is ``+0``. + - If ``x1_i`` is greater than ``0`` and ``x2_i`` is ``+0``, the result is ``+infinity``. + - If ``x1_i`` is greater than ``0`` and ``x2_i`` is ``-0``, the result is ``-infinity``. + - If ``x1_i`` is less than ``0`` and ``x2_i`` is ``+0``, the result is ``-infinity``. + - If ``x1_i`` is less than ``0`` and ``x2_i`` is ``-0``, the result is ``+infinity``. + - If ``x1_i`` is ``+infinity`` and ``x2_i`` is a positive (i.e., greater than ``0``) finite number, the result is ``+infinity``. (**note**: libraries may return ``NaN`` to match Python behavior.) + - If ``x1_i`` is ``+infinity`` and ``x2_i`` is a negative (i.e., less than ``0``) finite number, the result is ``-infinity``. (**note**: libraries may return ``NaN`` to match Python behavior.) + - If ``x1_i`` is ``-infinity`` and ``x2_i`` is a positive (i.e., greater than ``0``) finite number, the result is ``-infinity``. (**note**: libraries may return ``NaN`` to match Python behavior.) + - If ``x1_i`` is ``-infinity`` and ``x2_i`` is a negative (i.e., less than ``0``) finite number, the result is ``+infinity``. (**note**: libraries may return ``NaN`` to match Python behavior.) + - If ``x1_i`` is a positive (i.e., greater than ``0``) finite number and ``x2_i`` is ``+infinity``, the result is ``+0``. + - If ``x1_i`` is a positive (i.e., greater than ``0``) finite number and ``x2_i`` is ``-infinity``, the result is ``-0``. (**note**: libraries may return ``-1.0`` to match Python behavior.) + - If ``x1_i`` is a negative (i.e., less than ``0``) finite number and ``x2_i`` is ``+infinity``, the result is ``-0``. (**note**: libraries may return ``-1.0`` to match Python behavior.) + - If ``x1_i`` is a negative (i.e., less than ``0``) finite number and ``x2_i`` is ``-infinity``, the result is ``+0``. + - If ``x1_i`` and ``x2_i`` have the same mathematical sign and are both nonzero finite numbers, the result has a positive mathematical sign. + - If ``x1_i`` and ``x2_i`` have different mathematical signs and are both nonzero finite numbers, the result has a negative mathematical sign. + - In the remaining cases, where neither ``-infinity``, ``+0``, ``-0``, nor ``NaN`` is involved, the quotient must be computed and rounded to the greatest (i.e., closest to ``+infinity``) representable integer-value number that is not greater than the division result. If the magnitude is too large to represent, the operation overflows and the result is an ``infinity`` of appropriate mathematical sign. If the magnitude is too small to represent, the operation underflows and the result is a zero of appropriate mathematical sign. + """ + + def __ge__(self: array, other: Union[int, float, array], /) -> array: + """ + Computes the truth value of ``self_i >= other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type of ``bool``. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-greater_equal`. + """ + + def __getitem__(self: array, key: Union[int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], array], /) -> array: + """ + Returns ``self[key]``. + + Parameters + ---------- + self: array + array instance. + key: Union[int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], array] + index key. + + Returns + ------- + out: array + an array containing the accessed value(s). The returned array must have the same data type as ``self``. + """ + + def __gt__(self: array, other: Union[int, float, array], /) -> array: + """ + Computes the truth value of ``self_i > other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type of ``bool``. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-greater`. + """ + + def __index__(self: array, /) -> int: + """ + Converts a zero-dimensional integer array to a Python ``int`` object. + + Parameters + ---------- + self: array + zero-dimensional array instance. Must have an integer data type. + + Returns + ------- + out: int + a Python ``int`` object representing the single element of the array instance. + + Notes + ----- + - This method is called to implement `operator.index() `_. See also `PEP 357 `_. + """ + + def __int__(self: array, /) -> int: + """ + Converts a zero-dimensional integer array to a Python ``int`` object. + + Parameters + ---------- + self: array + zero-dimensional array instance. Must have an integer data type. + + Returns + ------- + out: int + a Python ``int`` object representing the single element of the array instance. + """ + + def __invert__(self: array, /) -> array: + """ + Evaluates ``~self_i`` for each element of an array instance. + + Parameters + ---------- + self: array + array instance. Should have an integer or boolean data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have the same data type as `self`. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_invert`. + """ + + def __le__(self: array, other: Union[int, float, array], /) -> array: + """ + Computes the truth value of ``self_i <= other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type of ``bool``. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-less_equal`. + """ + + def __lshift__(self: array, other: Union[int, array], /) -> array: + """ + Evaluates ``self_i << other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have an integer data type. + other: Union[int, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have an integer data type. Each element must be greater than or equal to ``0``. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have the same data type as ``self``. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_left_shift`. + """ + + def __lt__(self: array, other: Union[int, float, array], /) -> array: + """ + Computes the truth value of ``self_i < other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type of ``bool``. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-less`. + """ + + def __matmul__(self: array, other: array, /) -> array: + """ + Computes the matrix product. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. Must have at least one dimension. If ``self`` is one-dimensional having shape ``(M,)`` and ``other`` has more than one dimension, ``self`` must be promoted to a two-dimensional array by prepending ``1`` to its dimensions (i.e., must have shape ``(1, M)``). After matrix multiplication, the prepended dimensions in the returned array must be removed. If ``self`` has more than one dimension (including after vector-to-matrix promotion), ``shape(self)[:-2]`` must be compatible with ``shape(other)[:-2]`` (after vector-to-matrix promotion) (see :ref:`broadcasting`). If ``self`` has shape ``(..., M, K)``, the innermost two dimensions form matrices on which to perform matrix multiplication. + other: array + other array. Should have a numeric data type. Must have at least one dimension. If ``other`` is one-dimensional having shape ``(N,)`` and ``self`` has more than one dimension, ``other`` must be promoted to a two-dimensional array by appending ``1`` to its dimensions (i.e., must have shape ``(N, 1)``). After matrix multiplication, the appended dimensions in the returned array must be removed. If ``other`` has more than one dimension (including after vector-to-matrix promotion), ``shape(other)[:-2]`` must be compatible with ``shape(self)[:-2]`` (after vector-to-matrix promotion) (see :ref:`broadcasting`). If ``other`` has shape ``(..., K, N)``, the innermost two dimensions form matrices on which to perform matrix multiplication. + + Returns + ------- + out: array + - if both ``self`` and ``other`` are one-dimensional arrays having shape ``(N,)``, a zero-dimensional array containing the inner product as its only element. + - if ``self`` is a two-dimensional array having shape ``(M, K)`` and ``other`` is a two-dimensional array having shape ``(K, N)``, a two-dimensional array containing the `conventional matrix product `_ and having shape ``(M, N)``. + - if ``self`` is a one-dimensional array having shape ``(K,)`` and ``other`` is an array having shape ``(..., K, N)``, an array having shape ``(..., N)`` (i.e., prepended dimensions during vector-to-matrix promotion must be removed) and containing the `conventional matrix product `_. + - if ``self`` is an array having shape ``(..., M, K)`` and ``other`` is a one-dimensional array having shape ``(K,)``, an array having shape ``(..., M)`` (i.e., appended dimensions during vector-to-matrix promotion must be removed) and containing the `conventional matrix product `_. + - if ``self`` is a two-dimensional array having shape ``(M, K)`` and ``other`` is an array having shape ``(..., K, N)``, an array having shape ``(..., M, N)`` and containing the `conventional matrix product `_ for each stacked matrix. + - if ``self`` is an array having shape ``(..., M, K)`` and ``other`` is a two-dimensional array having shape ``(K, N)``, an array having shape ``(..., M, N)`` and containing the `conventional matrix product `_ for each stacked matrix. + - if either ``self`` or ``other`` has more than two dimensions, an array having a shape determined by :ref:`broadcasting` ``shape(self)[:-2]`` against ``shape(other)[:-2]`` and containing the `conventional matrix product `_ for each stacked matrix. + - The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + - The ``matmul`` function must implement the same semantics as the built-in ``@`` operator (see `PEP 465 `_). + - Results must equal the results returned by the equivalent function :ref:`function-matmul`. + + **Raises** + + - if either ``self`` or ``other`` is a zero-dimensional array. + - if ``self`` is a one-dimensional array having shape ``(K,)``, ``other`` is a one-dimensional array having shape ``(L,)``, and ``K != L``. + - if ``self`` is a one-dimensional array having shape ``(K,)``, ``other`` is an array having shape ``(..., L, N)``, and ``K != L``. + - if ``self`` is an array having shape ``(..., M, K)``, ``other`` is a one-dimensional array having shape ``(L,)``, and ``K != L``. + - if ``self`` is an array having shape ``(..., M, K)``, ``other`` is an array having shape ``(..., L, N)``, and ``K != L``. + """ + + def __mod__(self: array, other: Union[int, float, array], /) -> array: + """ + Evaluates ``self_i % other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. Each element-wise result must have the same sign as the respective element ``other_i``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + - For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-remainder`. + """ + + def __mul__(self: array, other: Union[int, float, array], /) -> array: + """ + Calculates the product for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise products. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + - Floating-point multiplication is not always associative due to finite precision. + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-multiply`. + + **Special cases** + + For floating-point operands, let ``self`` equal ``x1`` and ``other`` equal ``x2``. + + - If either ``x1_i`` or ``x2_i`` is ``NaN``, the result is ``NaN``. + - If ``x1_i`` is either ``+infinity`` or ``-infinity`` and ``x2_i`` is either ``+0`` or ``-0``, the result is ``NaN``. + - If ``x1_i`` is either ``+0`` or ``-0`` and ``x2_i`` is either ``+infinity`` or ``-infinity``, the result is ``NaN``. + - If ``x1_i`` and ``x2_i`` have the same mathematical sign, the result has a positive mathematical sign, unless the result is ``NaN``. If the result is ``NaN``, the "sign" of ``NaN`` is implementation-defined. + - If ``x1_i`` and ``x2_i`` have different mathematical signs, the result has a negative mathematical sign, unless the result is ``NaN``. If the result is ``NaN``, the "sign" of ``NaN`` is implementation-defined. + - If ``x1_i`` is either ``+infinity`` or ``-infinity`` and ``x2_i`` is either ``+infinity`` or ``-infinity``, the result is a signed infinity with the mathematical sign determined by the rule already stated above. + - If ``x1_i`` is either ``+infinity`` or ``-infinity`` and ``x2_i`` is a nonzero finite number, the result is a signed infinity with the mathematical sign determined by the rule already stated above. + - If ``x1_i`` is a nonzero finite number and ``x2_i`` is either ``+infinity`` or ``-infinity``, the result is a signed infinity with the mathematical sign determined by the rule already stated above. + - In the remaining cases, where neither ``infinity`` nor `NaN` is involved, the product must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported rounding mode. If the magnitude is too large to represent, the result is an ``infinity`` of appropriate mathematical sign. If the magnitude is too small to represent, the result is a zero of appropriate mathematical sign. + """ + + def __ne__(self: array, other: Union[int, float, bool, array], /) -> array: + """ + Computes the truth value of ``self_i != other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. May have any data type. + other: Union[int, float, bool, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). May have any data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type of ``bool`` (i.e., must be a boolean array). + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-not_equal`. + """ + + def __neg__(self: array, /) -> array: + """ + Evaluates ``-self_i`` for each element of an array instance. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + + Returns + ------- + out: array + an array containing the evaluated result for each element in ``self``. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + - For signed integer data types, the numerical negative of the minimum representable integer is implementation-dependent. + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-negative`. + """ + + def __or__(self: array, other: Union[int, bool, array], /) -> array: + """ + Evaluates ``self_i | other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have an integer or boolean data type. + other: Union[int, bool, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have an integer or boolean data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_or`. + """ + + def __pos__(self: array, /) -> array: + """ + Evaluates ``+self_i`` for each element of an array instance. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + + Returns + ------- + out: array + an array containing the evaluated result for each element. The returned array must have the same data type as ``self``. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-positive`. + """ + + def __pow__(self: array, other: Union[int, float, array], /) -> array: + """ + Calculates an implementation-dependent approximation of exponentiation by raising each element (the base) of an array instance to the power of ``other_i`` (the exponent), where ``other_i`` is the corresponding element of the array ``other``. + + Parameters + ---------- + self: array + array instance whose elements correspond to the exponentiation base. Should have a numeric data type. + other: Union[int, float, array] + other array whose elements correspond to the exponentiation exponent. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + - If both ``self`` and ``other`` have integer data types, the result of ``__pow__`` when `other_i` is negative (i.e., less than zero) is unspecified and thus implementation-dependent. + - If ``self`` has an integer data type and ``other`` has a floating-point data type, behavior is implementation-dependent (type promotion between data type "kinds" (integer versus floating-point) is unspecified). + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-pow`. + + **Special cases** + + For floating-point operands, let ``self`` equal ``x1`` and ``other`` equal ``x2``. + + - If ``x1_i`` is not equal to ``1`` and ``x2_i`` is ``NaN``, the result is ``NaN``. + - If ``x2_i`` is ``+0``, the result is ``1``, even if ``x1_i`` is ``NaN``. + - If ``x2_i`` is ``-0``, the result is `1`, even if ``x1_i`` is ``NaN``. + - If ``x1_i`` is ``NaN`` and ``x2_i`` is not equal to ``0``, the result is ``NaN``. + - If ``abs(x1_i)`` is greater than ``1`` and ``x2_i`` is ``+infinity``, the result is ``+infinity``. + - If ``abs(x1_i)`` is greater than ``1`` and ``x2_i`` is ``-infinity``, the result is ``+0``. + - If ``abs(x1_i)`` is ``1`` and ``x2_i`` is ``+infinity``, the result is ``1``. + - If ``abs(x1_i)`` is ``1`` and ``x2_i`` is ``-infinity``, the result is ``1``. + - If ``x1_i`` is ``1`` and ``x2_i`` is not ``NaN``, the result is ``1``. + - If ``abs(x1_i)`` is less than ``1`` and ``x2_i`` is ``+infinity``, the result is ``+0``. + - If ``abs(x1_i)`` is less than ``1`` and ``x2_i`` is ``-infinity``, the result is ``+infinity``. + - If ``x1_i`` is ``+infinity`` and ``x2_i`` is greater than ``0``, the result is ``+infinity``. + - If ``x1_i`` is ``+infinity`` and ``x2_i`` is less than ``0``, the result is ``+0``. + - If ``x1_i`` is ``-infinity``, ``x2_i`` is greater than ``0``, and ``x2_i`` is an odd integer value, the result is ``-infinity``. + - If ``x1_i`` is ``-infinity``, ``x2_i`` is greater than ``0``, and ``x2_i`` is not an odd integer value, the result is ``+infinity``. + - If ``x1_i`` is ``-infinity``, ``x2_i`` is less than ``0``, and ``x2_i`` is an odd integer value, the result is ``-0``. + - If ``x1_i`` is ``-infinity``, ``x2_i`` is less than ``0``, and ``x2_i`` is not an odd integer value, the result is ``+0``. + - If ``x1_i`` is ``+0`` and ``x2_i`` is greater than ``0``, the result is ``+0``. + - If ``x1_i`` is ``+0`` and ``x2_i`` is less than ``0``, the result is ``+infinity``. + - If ``x1_i`` is ``-0``, ``x2_i`` is greater than ``0``, and ``x2_i`` is an odd integer value, the result is ``-0``. + - If ``x1_i`` is ``-0``, ``x2_i`` is greater than ``0``, and ``x2_i`` is not an odd integer value, the result is ``+0``. + - If ``x1_i`` is ``-0``, ``x2_i`` is less than ``0``, and ``x2_i`` is an odd integer value, the result is ``-infinity``. + - If ``x1_i`` is ``-0``, ``x2_i`` is less than ``0``, and ``x2_i`` is not an odd integer value, the result is ``+infinity``. + - If ``x1_i`` is less than ``0``, ``x1_i`` is a finite number, ``x2_i`` is a finite number, and ``x2_i`` is not an integer value, the result is ``NaN``. + """ + + def __rshift__(self: array, other: Union[int, array], /) -> array: + """ + Evaluates ``self_i >> other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have an integer data type. + other: Union[int, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have an integer data type. Each element must be greater than or equal to ``0``. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have the same data type as ``self``. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_right_shift`. + """ + + def __setitem__(self: array, key: Union[int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], array], value: Union[int, float, bool, array], /) -> None: + """ + Sets ``self[key]`` to ``value``. + + Parameters + ---------- + self: array + array instance. + key: Union[int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], array] + index key. + value: Union[int, float, bool, array] + value(s) to set. Must be compatible with ``self[key]`` (see :ref:`broadcasting`). + + Notes + ----- + - Setting array values must not affect the data type of ``self``. + - When ``value`` is a Python scalar (i.e., ``int``, ``float``, ``bool``), behavior must follow specification guidance on mixing arrays with Python scalars (see :ref:`type-promotion`). + - When ``value`` is an ``array`` of a different data type than ``self``, how values are cast to the data type of ``self`` is implementation defined. + """ + + def __sub__(self: array, other: Union[int, float, array], /) -> array: + """ + Calculates the difference for each element of an array instance with the respective element of the array ``other``. The result of ``self_i - other_i`` must be the same as ``self_i + (-other_i)`` and must be governed by the same floating-point rules as addition (see :meth:`array.__add__`). + + Parameters + ---------- + self: array + array instance (minuend array). Should have a numeric data type. + other: Union[int, float, array] + subtrahend array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise differences. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-subtract`. + """ + + def __truediv__(self: array, other: Union[int, float, array], /) -> array: + """ + Evaluates ``self_i / other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array should have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-divide`. + + **Special cases** + + For floating-point operands, let ``self`` equal ``x1`` and ``other`` equal ``x2``. + + - If either ``x1_i`` or ``x2_i`` is ``NaN``, the result is ``NaN``. + - If ``x1_i`` is either ``+infinity`` or ``-infinity`` and ``x2_i`` is either ``+infinity`` or ``-infinity``, the result is `NaN`. + - If ``x1_i`` is either ``+0`` or ``-0`` and ``x2_i`` is either ``+0`` or ``-0``, the result is ``NaN``. + - If ``x1_i`` is ``+0`` and ``x2_i`` is greater than ``0``, the result is ``+0``. + - If ``x1_i`` is ``-0`` and ``x2_i`` is greater than ``0``, the result is ``-0``. + - If ``x1_i`` is ``+0`` and ``x2_i`` is less than ``0``, the result is ``-0``. + - If ``x1_i`` is ``-0`` and ``x2_i`` is less than ``0``, the result is ``+0``. + - If ``x1_i`` is greater than ``0`` and ``x2_i`` is ``+0``, the result is ``+infinity``. + - If ``x1_i`` is greater than ``0`` and ``x2_i`` is ``-0``, the result is ``-infinity``. + - If ``x1_i`` is less than ``0`` and ``x2_i`` is ``+0``, the result is ``-infinity``. + - If ``x1_i`` is less than ``0`` and ``x2_i`` is ``-0``, the result is ``+infinity``. + - If ``x1_i`` is ``+infinity`` and ``x2_i`` is a positive (i.e., greater than ``0``) finite number, the result is ``+infinity``. + - If ``x1_i`` is ``+infinity`` and ``x2_i`` is a negative (i.e., less than ``0``) finite number, the result is ``-infinity``. + - If ``x1_i`` is ``-infinity`` and ``x2_i`` is a positive (i.e., greater than ``0``) finite number, the result is ``-infinity``. + - If ``x1_i`` is ``-infinity`` and ``x2_i`` is a negative (i.e., less than ``0``) finite number, the result is ``+infinity``. + - If ``x1_i`` is a positive (i.e., greater than ``0``) finite number and ``x2_i`` is ``+infinity``, the result is ``+0``. + - If ``x1_i`` is a positive (i.e., greater than ``0``) finite number and ``x2_i`` is ``-infinity``, the result is ``-0``. + - If ``x1_i`` is a negative (i.e., less than ``0``) finite number and ``x2_i`` is ``+infinity``, the result is ``-0``. + - If ``x1_i`` is a negative (i.e., less than ``0``) finite number and ``x2_i`` is ``-infinity``, the result is ``+0``. + - If ``x1_i`` and ``x2_i`` have the same mathematical sign and are both nonzero finite numbers, the result has a positive mathematical sign. + - If ``x1_i`` and ``x2_i`` have different mathematical signs and are both nonzero finite numbers, the result has a negative mathematical sign. + - In the remaining cases, where neither ``-infinity``, ``+0``, ``-0``, nor ``NaN`` is involved, the quotient must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported rounding mode. If the magnitude is too large to represent, the operation overflows and the result is an ``infinity`` of appropriate mathematical sign. If the magnitude is too small to represent, the operation underflows and the result is a zero of appropriate mathematical sign. + """ + + def __xor__(self: array, other: Union[int, bool, array], /) -> array: + """ + Evaluates ``self_i ^ other_i`` for each element of an array instance with the respective element of the array ``other``. + + Parameters + ---------- + self: array + array instance. Should have an integer or boolean data type. + other: Union[int, bool, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have an integer or boolean data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_xor`. + """ + + def to_device(self: array, device: device, /, *, stream: Optional[Union[int, Any]] = None) -> array: + """ + Copy the array from the device on which it currently resides to the specified ``device``. + + Parameters + ---------- + self: array + array instance. + device: device + a ``device`` object (see :ref:`device-support`). + stream: Optional[Union[int, Any]] + stream object to use during copy. In addition to the types supported in :meth:`array.__dlpack__`, implementations may choose to support any library-specific stream object with the caveat that any code using such an object would not be portable. + + Returns + ------- + out: array + an array with the same data and data type as ``self`` and located on the specified ``device``. + + Notes + ----- + - If ``stream`` is given, the copy operation should be enqueued on the provided ``stream``; otherwise, the copy operation should be enqueued on the default stream/queue. Whether the copy is performed synchronously or asynchronously is implementation-dependent. Accordingly, if synchronization is required to guarantee data safety, this must be clearly explained in a conforming library's documentation. + """ \ No newline at end of file From 9bf66d6767a74320fe09189b3f1ce4737f01a195 Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Tue, 14 Dec 2021 12:27:51 -0500 Subject: [PATCH 02/10] Remove warnings --- spec/API_specification/array_object.rst | 4 ++-- spec/purpose_and_scope.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/API_specification/array_object.rst b/spec/API_specification/array_object.rst index 33a6e9e86..8062ecd1c 100644 --- a/spec/API_specification/array_object.rst +++ b/spec/API_specification/array_object.rst @@ -182,7 +182,7 @@ An in-place operation must not change the data type or shape of the in-place arr An in-place operation must have the same behavior (including special cases) as its respective binary (i.e., two operand, non-assignment) operation. For example, after in-place addition ``x1 += x2``, the modified array ``x1`` must always equal the result of the equivalent binary arithmetic operation ``x1 = x1 + x2``. .. note:: -In-place operators must be supported as discussed in :ref:`copyview-mutability`. + In-place operators must be supported as discussed in :ref:`copyview-mutability`. Arithmetic Operators """""""""""""""""""" @@ -217,7 +217,7 @@ A conforming implementation of the array API standard must provide and support a The results of applying reflected operators must match their non-reflected equivalents. .. note:: -All operators for which ``array scalar`` is implemented must have an equivalent reflected operator implementation. + All operators for which ``array scalar`` is implemented must have an equivalent reflected operator implementation. Arithmetic Operators """""""""""""""""""" diff --git a/spec/purpose_and_scope.md b/spec/purpose_and_scope.md index a34208cff..6e19c02ea 100644 --- a/spec/purpose_and_scope.md +++ b/spec/purpose_and_scope.md @@ -318,7 +318,7 @@ namespace (e.g. `import package_name.array_api`). This has two issues though: To address both issues, a uniform way must be provided by a conforming implementation to access the API namespace, namely a [method on the array -object](method-__array_namespace__): +object](array.__array_namespace__): ``` xp = x.__array_namespace__() From a6daf310b0e78cb2398ea89d521a2dae1b765558 Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Tue, 14 Dec 2021 15:07:17 -0500 Subject: [PATCH 03/10] Change redirecting github action --- .github/workflows/preview.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index cdb310fe4..4ca25be0e 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -14,6 +14,3 @@ jobs: artifact-path: 0/build/latest/index.html circleci-jobs: build_page job-title: Check the rendered docs here! - - name: Array API preview - run: | - curl --fail ${{ steps.step1.outputs.url }} | grep $GITHUB_SHA From d81ebe2787afe893cc1d576655ce8cc53ea1811a Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Tue, 14 Dec 2021 15:25:00 -0500 Subject: [PATCH 04/10] Revert changes --- .github/workflows/preview.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 4ca25be0e..d15d99107 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -14,3 +14,6 @@ jobs: artifact-path: 0/build/latest/index.html circleci-jobs: build_page job-title: Check the rendered docs here! + - name: Array API preview + run: | + curl --fail ${{ steps.step1.outputs.url }} | grep $GITHUB_SHA \ No newline at end of file From 8faf1a6983e136db6e7f193813570685fab110a4 Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Tue, 21 Dec 2021 19:09:40 -0500 Subject: [PATCH 05/10] Add missing template to toctree --- spec/API_specification/array_object.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/API_specification/array_object.rst b/spec/API_specification/array_object.rst index 8062ecd1c..ecbd91861 100644 --- a/spec/API_specification/array_object.rst +++ b/spec/API_specification/array_object.rst @@ -256,6 +256,7 @@ Attributes .. autosummary:: :toctree: generated + :template: method.rst array.dtype array.device @@ -275,6 +276,7 @@ Methods .. autosummary:: :toctree: generated + :template: method.rst array.__abs__ array.__add__ From 503cf825ea0e768ad395d3774f5fd82bd84bfff2 Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Tue, 21 Dec 2021 19:13:51 -0500 Subject: [PATCH 06/10] Fix warnings --- spec/API_specification/array_object.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/API_specification/array_object.rst b/spec/API_specification/array_object.rst index ecbd91861..8062ecd1c 100644 --- a/spec/API_specification/array_object.rst +++ b/spec/API_specification/array_object.rst @@ -256,7 +256,6 @@ Attributes .. autosummary:: :toctree: generated - :template: method.rst array.dtype array.device @@ -276,7 +275,6 @@ Methods .. autosummary:: :toctree: generated - :template: method.rst array.__abs__ array.__add__ From c1e942b9fe9f4d4937b85077da5e391906841b60 Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Mon, 10 Jan 2022 11:05:20 -0500 Subject: [PATCH 07/10] Add review changes --- .../signatures/array_object.py | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/spec/API_specification/signatures/array_object.py b/spec/API_specification/signatures/array_object.py index 0562a90b3..53d87333b 100644 --- a/spec/API_specification/signatures/array_object.py +++ b/spec/API_specification/signatures/array_object.py @@ -6,7 +6,8 @@ def __init__(self) -> None: Initialize the attributes for the array object class. """ - self.dtype = None + @property + def dtype() -> dtype: """ Data type of the array elements. @@ -16,7 +17,8 @@ def __init__(self) -> None: array data type. """ - self.device = None + @property + def device() -> device: """ Hardware device the array data resides on. @@ -26,7 +28,8 @@ def __init__(self) -> None: a ``device`` object (see :ref:`device-support`). """ - self.mT = None + @property + def mT() -> array: """ Transpose of a matrix (or a stack of matrices). @@ -38,7 +41,8 @@ def __init__(self) -> None: array whose last two dimensions (axes) are permuted in reverse order relative to original array (i.e., for an array instance having shape ``(..., M, N)``, the returned array must have shape ``(..., N, M)``). The returned array must have the same data type as the original array. """ - self.ndim = None + @property + def ndim() -> int: """ Number of array dimensions (axes). @@ -48,7 +52,8 @@ def __init__(self) -> None: number of array dimensions (axes). """ - self.shape = None + @property + def shape() -> Tuple[Optional[int], ...]: """ Array dimensions. @@ -64,7 +69,8 @@ def __init__(self) -> None: - The returned value should be a tuple; however, where warranted, an array library may choose to return a custom shape object. If an array library returns a custom shape object, the object must be immutable, must support indexing for dimension retrieval, and must behave similarly to a tuple. """ - self.size = None + @property + def size() -> Optional[int]: """ Number of elements in an array. @@ -80,7 +86,8 @@ def __init__(self) -> None: - For array libraries having graph-based computational models, an array may have unknown dimensions due to data-dependent operations. """ - self.T = None + @property + def T() -> array: """ Transpose of the array. @@ -939,4 +946,4 @@ def to_device(self: array, device: device, /, *, stream: Optional[Union[int, Any Notes ----- - If ``stream`` is given, the copy operation should be enqueued on the provided ``stream``; otherwise, the copy operation should be enqueued on the default stream/queue. Whether the copy is performed synchronously or asynchronously is implementation-dependent. Accordingly, if synchronization is required to guarantee data safety, this must be clearly explained in a conforming library's documentation. - """ \ No newline at end of file + """ From cef078e66f4a445b49c02c2748a7444107c05402 Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Wed, 12 Jan 2022 17:47:06 -0500 Subject: [PATCH 08/10] Fix notes and device type override --- .../signatures/array_object.py | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/spec/API_specification/signatures/array_object.py b/spec/API_specification/signatures/array_object.py index 62fbb8feb..9484650b5 100644 --- a/spec/API_specification/signatures/array_object.py +++ b/spec/API_specification/signatures/array_object.py @@ -1,4 +1,5 @@ -from ._types import array, dtype, device, Optional, Tuple, Union, Any, PyCapsule, Enum, ellipsis +from ._types import array, dtype, Optional, Tuple, Union, Any, PyCapsule, Enum, ellipsis +from ._types import device as Device class array(): def __init__(self) -> None: @@ -18,7 +19,7 @@ def dtype() -> dtype: """ @property - def device() -> device: + def device() -> Device: """ Hardware device the array data resides on. @@ -244,13 +245,25 @@ def __dlpack__(self: array, /, *, stream: Optional[Union[int, Any]] = None) -> P For other device types which do have a stream, queue or similar synchronization mechanism, the most appropriate type to use for `stream` is not yet determined. E.g., for SYCL one may want to use an object containing an in-order ``cl::sycl::queue``. This is allowed when libraries agree on such a convention, and may be standardized in a future version of this API standard. - **Note** + **Tip** - Support for a ``stream`` value other than ``None`` is optional and implementation-dependent. + It is recommended that implementers explicitly handle streams. If + they use the legacy default stream, specifying ``1`` (CUDA) or ``0`` + (ROCm) is preferred. ``None`` is a safe default for developers who do + not want to think about stream handling at all, potentially at the + cost of more synchronization than necessary. - Device-specific notes: + Returns + ------- + capsule: PyCapsule + a DLPack capsule for the array. See :ref:`data-interchange` for details. + + Notes + ----- + - Support for a ``stream`` value other than ``None`` is optional and implementation-dependent. + - Device-specific notes: - **CUDA** + **CUDA** - ``None``: producer must assume the legacy default stream (default). - ``1``: the legacy default stream. @@ -259,26 +272,13 @@ def __dlpack__(self: array, /, *, stream: Optional[Union[int, Any]] = None) -> P ``0`` is disallowed due to its ambiguity: ``0`` could mean either ``None``, ``1``, or ``2``. - **ROCm** + **ROCm** - ``None``: producer must assume the legacy default stream (default). - ``0``: the default stream. - ``> 2``: stream number represented as a Python integer. Using ``1`` and ``2`` is not supported. - - **Tip** - - It is recommended that implementers explicitly handle streams. If - they use the legacy default stream, specifying ``1`` (CUDA) or ``0`` - (ROCm) is preferred. ``None`` is a safe default for developers who do - not want to think about stream handling at all, potentially at the - cost of more synchronization than necessary. - - Returns - ------- - capsule: PyCapsule - a DLPack capsule for the array. See :ref:`data-interchange` for details. """ def __dlpack_device__(self: array, /) -> Tuple[Enum, int]: @@ -925,7 +925,7 @@ def __xor__(self: array, other: Union[int, bool, array], /) -> array: - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_xor`. """ - def to_device(self: array, device: device, /, *, stream: Optional[Union[int, Any]] = None) -> array: + def to_device(self: array, device: Device, /, *, stream: Optional[Union[int, Any]] = None) -> array: """ Copy the array from the device on which it currently resides to the specified ``device``. From 993423daa0ada4054f69f20c57894d3c947debc0 Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Mon, 17 Jan 2022 14:39:00 -0500 Subject: [PATCH 09/10] Delete extra file --- spec/API_specification/array_object.md | 1357 ------------------------ 1 file changed, 1357 deletions(-) delete mode 100644 spec/API_specification/array_object.md diff --git a/spec/API_specification/array_object.md b/spec/API_specification/array_object.md deleted file mode 100644 index 46ba3648e..000000000 --- a/spec/API_specification/array_object.md +++ /dev/null @@ -1,1357 +0,0 @@ -(array-object)= - -# Array object - -> Array API specification for array object attributes and methods. - -A conforming implementation of the array API standard must provide and support an array object having the following attributes and methods adhering to the following conventions. - -- Positional parameters must be [positional-only](https://www.python.org/dev/peps/pep-0570/) parameters. Positional-only parameters have no externally-usable name. When a method accepting positional-only parameters is called, positional arguments are mapped to these parameters based solely on their order. -- Optional parameters must be [keyword-only](https://www.python.org/dev/peps/pep-3102/) arguments. -- Broadcasting semantics must follow the semantics defined in {ref}`broadcasting`. -- Unless stated otherwise, methods must support the data types defined in {ref}`data-types`. -- Unless stated otherwise, methods must adhere to the type promotion rules defined in {ref}`type-promotion`. -- Unless stated otherwise, floating-point operations must adhere to IEEE 754-2019. - -Furthermore, a conforming implementation of the array API standard must support array objects of arbitrary rank `N` (i.e., number of dimensions), where `N` is greater than or equal to zero. - -```{note} -Conforming implementations must support zero-dimensional arrays. - -Apart from array object attributes, such as `ndim`, `device`, and `dtype`, all operations in this standard return arrays (or tuples of arrays), including those operations, such as `mean`, `var`, and `std`, from which some common array libraries (e.g., NumPy) return scalar values. - -_Rationale: always returning arrays is necessary to (1) support accelerator libraries where non-array return values could force device synchronization and (2) support delayed execution models where an array represents a future value._ -``` - -* * * - -(operators)= - -## Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following Python operators. - -### Arithmetic Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following Python arithmetic operators. - -- `+x`: [`__pos__(x)`](#__pos__self-) - - - [`operator.pos(x)`](https://docs.python.org/3/library/operator.html#operator.pos) - - [`operator.__pos__(x)`](https://docs.python.org/3/library/operator.html#operator.__pos__) - -- `-x`: [`__neg__(x)`](#__neg__self-) - - - [`operator.neg(x)`](https://docs.python.org/3/library/operator.html#operator.neg) - - [`operator.__neg__(x)`](https://docs.python.org/3/library/operator.html#operator.__neg__) - -- `x1 + x2`: [`__add__(x1, x2)`](#__add__self-other-) - - - [`operator.add(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.add) - - [`operator.__add__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__add__) - -- `x1 - x2`: [`__sub__(x1, x2)`](#__sub__self-other-) - - - [`operator.sub(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.sub) - - [`operator.__sub__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__sub__) - -- `x1 * x2`: [`__mul__(x1, x2)`](#__mul__self-other-) - - - [`operator.mul(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.mul) - - [`operator.__mul__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__mul__) - -- `x1 / x2`: [`__truediv__(x1, x2)`](#__truediv__self-other-) - - - [`operator.truediv(x1,x2)`](https://docs.python.org/3/library/operator.html#operator.truediv) - - [`operator.__truediv__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__truediv__) - -- `x1 // x2`: [`__floordiv__(x1, x2)`](#__floordiv__self-other-) - - - [`operator.floordiv(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.floordiv) - - [`operator.__floordiv__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__floordiv__) - -- `x1 % x2`: [`__mod__(x1, x2)`](#__mod__self-other-) - - - [`operator.mod(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.mod) - - [`operator.__mod__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__mod__) - -- `x1 ** x2`: [`__pow__(x1, x2)`](#__pow__self-other-) - - - [`operator.pow(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.pow) - - [`operator.__pow__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__pow__) - -Arithmetic operators should be defined for arrays having numeric data types. - -### Array Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following Python array operators. - -- `x1 @ x2`: [`__matmul__(x1, x2)`](#__matmul__self-other-) - - - [`operator.matmul(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.matmul) - - [`operator.__matmul__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__matmul__) - -The matmul `@` operator should be defined for arrays having numeric data types. - -### Bitwise Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following Python bitwise operators. - -- `~x`: [`__invert__(x)`](#__invert__self-) - - - [`operator.inv(x)`](https://docs.python.org/3/library/operator.html#operator.inv) - - [`operator.invert(x)`](https://docs.python.org/3/library/operator.html#operator.invert) - - [`operator.__inv__(x)`](https://docs.python.org/3/library/operator.html#operator.__inv__) - - [`operator.__invert__(x)`](https://docs.python.org/3/library/operator.html#operator.__invert__) - -- `x1 & x2`: [`__and__(x1, x2)`](#__and__self-other-) - - - [`operator.and(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.and) - - [`operator.__and__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__and__) - -- `x1 | x2`: [`__or__(x1, x2)`](#__or__self-other-) - - - [`operator.or(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.or) - - [`operator.__or__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__or__) - -- `x1 ^ x2`: [`__xor__(x1, x2)`](#__xor__self-other-) - - - [`operator.xor(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.xor) - - [`operator.__xor__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__xor__) - -- `x1 << x2`: [`__lshift__(x1, x2)`](#__lshift__self-other-) - - - [`operator.lshift(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.lshift) - - [`operator.__lshift__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__lshift__) - -- `x1 >> x2`: [`__rshift__(x1, x2)`](#__rshift__self-other-) - - - [`operator.rshift(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.rshift) - - [`operator.__rshift__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__rshift__) - -Bitwise operators should be defined for arrays having integer and boolean data types. - -### Comparison Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following Python comparison operators. - -- `x1 < x2`: [`__lt__(x1, x2)`](#__lt__self-other-) - - - [`operator.lt(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.lt) - - [`operator.__lt__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__lt__) - -- `x1 <= x2`: [`__le__(x1, x2)`](#__le__self-other-) - - - [`operator.le(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.le) - - [`operator.__le__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__le__) - -- `x1 > x2`: [`__gt__(x1, x2)`](#__gt__self-other-) - - - [`operator.gt(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.gt) - - [`operator.__gt__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__gt__) - -- `x1 >= x2`: [`__ge__(x1, x2)`](#__ge__self-other-) - - - [`operator.ge(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.ge) - - [`operator.__ge__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__ge__) - -- `x1 == x2`: [`__eq__(x1, x2)`](#__eq__self-other-) - - - [`operator.eq(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.eq) - - [`operator.__eq__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__eq__) - -- `x1 != x2`: [`__ne__(x1, x2)`](#__ne__self-other-) - - - [`operator.ne(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.ne) - - [`operator.__ne__(x1, x2)`](https://docs.python.org/3/library/operator.html#operator.__ne__) - -Comparison operators should be defined for arrays having any data type. - -### In-place Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following in-place Python operators. - -An in-place operation must not change the data type or shape of the in-place array as a result of {ref}`type-promotion` or {ref}`broadcasting`. - -An in-place operation must have the same behavior (including special cases) as its respective binary (i.e., two operand, non-assignment) operation. For example, after in-place addition `x1 += x2`, the modified array `x1` must always equal the result of the equivalent binary arithmetic operation `x1 = x1 + x2`. - -```{note} -In-place operators must be supported as discussed in {ref}`copyview-mutability`. -``` - -#### Arithmetic Operators - -- `+=`. May be implemented via `__iadd__`. -- `-=`. May be implemented via `__isub__`. -- `*=`. May be implemented via `__imul__`. -- `/=`. May be implemented via `__itruediv__`. -- `//=`. May be implemented via `__ifloordiv__`. -- `**=`. May be implemented via `__ipow__`. -- `%=`. May be implemented via `__imod__`. - -#### Array Operators - -- `@=`. May be implemented via `__imatmul__`. - -#### Bitwise Operators - -- `&=`. May be implemented via `__iand__`. -- `|=`. May be implemented via `__ior__`. -- `^=`. May be implemented via `__ixor__`. -- `<<=`. May be implemented via `__ilshift__`. -- `>>=`. May be implemented via `__irshift__`. - -### Reflected Operators - -A conforming implementation of the array API standard must provide and support an array object supporting the following reflected operators. - -The results of applying reflected operators must match their non-reflected equivalents. - -```{note} -All operators for which `array scalar` is implemented must have an equivalent reflected operator implementation. -``` - -#### Arithmetic Operators - -- `__radd__` -- `__rsub__` -- `__rmul__` -- `__rtruediv__` -- `__rfloordiv__` -- `__rpow__` -- `__rmod__` - -#### Array Operators - -- `__rmatmul__` - -#### Bitwise Operators - -- `__rand__` -- `__ror__` -- `__rxor__` -- `__rlshift__` -- `__rrshift__` - -* * * - -## Attributes - - - -(attribute-dtype)= -### dtype - -Data type of the array elements. - -#### Returns - -- **out**: _<dtype>_ - - - array data type. - -(attribute-device)= -### device - -Hardware device the array data resides on. - -#### Returns - -- **out**: _<device>_ - - - a `device` object (see {ref}`device-support`). - -(attribute-mT)= -### mT - -Transpose of a matrix (or a stack of matrices). - -If an array instance has fewer than two dimensions, an error should be raised. - -#### Returns - -- **out**: _<array>_ - - - array whose last two dimensions (axes) are permuted in reverse order relative to original array (i.e., for an array instance having shape `(..., M, N)`, the returned array must have shape `(..., N, M)`). The returned array must have the same data type as the original array. - -(attribute-ndim)= -### ndim - -Number of array dimensions (axes). - -#### Returns - -- **out**: _int_ - - - number of array dimensions (axes). - -(attribute-shape)= -### shape - -Array dimensions. - -#### Returns - -- **out**: _Tuple\[ Optional\[ int ], ... ]_ - - - array dimensions. An array dimension must be `None` if and only if a dimension is unknown. - -```{note} -For array libraries having graph-based computational models, array dimensions may be unknown due to data-dependent operations (e.g., boolean indexing; `A[:, B > 0]`) and thus cannot be statically resolved without knowing array contents. -``` - -```{note} -The returned value should be a tuple; however, where warranted, an array library may choose to return a custom shape object. If an array library returns a custom shape object, the object must be immutable, must support indexing for dimension retrieval, and must behave similarly to a tuple. -``` - -(attribute-size)= -### size - -Number of elements in an array. - -```{note} -This must equal the product of the array's dimensions. -``` - -#### Returns - -- **out**: _Optional\[ int ]_ - - - number of elements in an array. The returned value must be `None` if and only if one or more array dimensions are unknown. - -```{note} -For array libraries having graph-based computational models, an array may have unknown dimensions due to data-dependent operations. -``` - -(attribute-T)= -### T - -Transpose of the array. - -The array instance must be two-dimensional. If the array instance is not two-dimensional, an error should be raised. - -```{note} -Limiting the transpose to two-dimensional arrays (matrices) deviates from the NumPy et al practice of reversing all axes for arrays having more than two-dimensions. This is intentional, as reversing all axes was found to be problematic (e.g., conflicting with the mathematical definition of a transpose which is limited to matrices; not operating on batches of matrices; et cetera). In order to reverse all axes, one is recommended to use the functional `permute_dims` interface found in this specification. -``` - -#### Returns - -- **out**: _<array>_ - - - two-dimensional array whose first and last dimensions (axes) are permuted in reverse order relative to original array. The returned array must have the same data type as the original array. - -* * * - -## Methods - - - -(method-__abs__)= -### \_\_abs\_\_(self, /) - -Calculates the absolute value for each element of an array instance (i.e., the element-wise result has the same magnitude as the respective element but has positive sign). - -```{note} -For signed integer data types, the absolute value of the minimum representable integer is implementation-dependent. -``` - -#### Special Cases - -For floating-point operands, let `self` equal `x`. - -- If `x_i` is `NaN`, the result is `NaN`. -- If `x_i` is `-0`, the result is `+0`. -- If `x_i` is `-infinity`, the result is `+infinity`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise absolute value. The returned array must have the same data type as `self`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`abs(x)`](elementwise_functions.md#absx-). -``` - -(method-__add__)= -### \_\_add\_\_(self, other, /) - -Calculates the sum for each element of an array instance with the respective element of the array `other`. - -#### Special Cases - -For floating-point operands, let `self` equal `x1` and `other` equal `x2`. - -- If either `x1_i` or `x2_i` is `NaN`, the result is `NaN`. -- If `x1_i` is `+infinity` and `x2_i` is `-infinity`, the result is `NaN`. -- If `x1_i` is `-infinity` and `x2_i` is `+infinity`, the result is `NaN`. -- If `x1_i` is `+infinity` and `x2_i` is `+infinity`, the result is `+infinity`. -- If `x1_i` is `-infinity` and `x2_i` is `-infinity`, the result is `-infinity`. -- If `x1_i` is `+infinity` and `x2_i` is a finite number, the result is `+infinity`. -- If `x1_i` is `-infinity` and `x2_i` is a finite number, the result is `-infinity`. -- If `x1_i` is a finite number and `x2_i` is `+infinity`, the result is `+infinity`. -- If `x1_i` is a finite number and `x2_i` is `-infinity`, the result is `-infinity`. -- If `x1_i` is `-0` and `x2_i` is `-0`, the result is `-0`. -- If `x1_i` is `-0` and `x2_i` is `+0`, the result is `+0`. -- If `x1_i` is `+0` and `x2_i` is `-0`, the result is `+0`. -- If `x1_i` is `+0` and `x2_i` is `+0`, the result is `+0`. -- If `x1_i` is either `+0` or `-0` and `x2_i` is a nonzero finite number, the result is `x2_i`. -- If `x1_i` is a nonzero finite number and `x2_i` is either `+0` or `-0`, the result is `x1_i`. -- If `x1_i` is a nonzero finite number and `x2_i` is `-x1_i`, the result is `+0`. -- In the remaining cases, when neither `infinity`, `+0`, `-0`, nor a `NaN` is involved, and the operands have the same mathematical sign or have different magnitudes, the sum must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported round mode. If the magnitude is too large to represent, the operation overflows and the result is an `infinity` of appropriate mathematical sign. - -```{note} -Floating-point addition is a commutative operation, but not always associative. -``` - -#### Parameters - -- **self**: _<array>_ - - - array instance (augend array). Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - addend array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise sums. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`add(x1, x2)`](elementwise_functions.md#addx1-x2-). -``` - -(method-__and__)= -### \_\_and\_\_(self, other, /) - -Evaluates `self_i & other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer or boolean data type. - -- **other**: _Union\[ int, bool, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have an integer or boolean data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_and(x1, x2)`](elementwise_functions.md#logical_andx1-x2-). -``` - - -(method-__array_namespace__)= -### \_\_array_namespace\_\_(self, /, *, api_version=None) - -Returns an object that has all the array API functions on it. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -- **api_version**: _<Optional\[str\]>_ - - - string representing the version of the array API specification to be returned, in `'YYYY.MM'` form, for example, `'2020.10'`. If it is `None`, it should return the namespace corresponding to latest version of the array API specification. If the given version is invalid or not implemented for the given module, an error should be raised. Default: `None`. - -#### Returns - -- **out**: _<Any>_ - - - an object representing the array API namespace. It should have every top-level function defined in the specification as an attribute. It may contain other public names as well, but it is recommended to only include those names that are part of the specification. - - -(method-__bool__)= -### \_\_bool\_\_(self, /) - -Converts a zero-dimensional boolean array to a Python `bool` object. - -#### Parameters - -- **self**: _<array>_ - - - zero-dimensional array instance. Must have a boolean data type. - -#### Returns - -- **out**: _<bool>_ - - - a Python `bool` object representing the single element of the array. - - -(method-__dlpack__)= -### \_\_dlpack\_\_(self, /, *, stream=None) - -Exports the array for consumption by {ref}`function-from_dlpack` as a DLPack capsule. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -- **stream**: _Optional\[ Union\[ int, Any ]]_ - - - for CUDA and ROCm, a Python integer representing a pointer to a stream, on devices that support streams. `stream` is provided by the consumer to the producer to instruct the producer to ensure that operations can safely be performed on the array (e.g., by inserting a dependency between streams via "wait for event"). The pointer must be a positive integer or `-1`. If `stream` is `-1`, the value may be used by the consumer to signal "producer must not perform any synchronization". The ownership of the stream stays with the consumer. - - On CPU and other device types without streams, only `None` is accepted. - - For other device types which do have a stream, queue or similar synchronization mechanism, the most appropriate type to use for `stream` is not yet determined. E.g., for SYCL one may want to use an object containing an in-order `cl::sycl::queue`. This is allowed when libraries agree on such a convention, and may be standardized in a future version of this API standard. - - ```{note} - Support for a `stream` value other than `None` is optional and implementation-dependent. - ``` - - Device-specific notes: - - :::{admonition} CUDA - - `None`: producer must assume the legacy default stream (default). - - `1`: the legacy default stream. - - `2`: the per-thread default stream. - - `> 2`: stream number represented as a Python integer. - - `0` is disallowed due to its ambiguity: `0` could mean either `None`, `1`, or `2`. - ::: - - :::{admonition} ROCm - - `None`: producer must assume the legacy default stream (default). - - `0`: the default stream. - - `> 2`: stream number represented as a Python integer. - - Using `1` and `2` is not supported. - ::: - - ```{tip} - It is recommended that implementers explicitly handle streams. If - they use the legacy default stream, specifying `1` (CUDA) or `0` - (ROCm) is preferred. `None` is a safe default for developers who do - not want to think about stream handling at all, potentially at the - cost of more synchronization than necessary. - ``` - -#### Returns - -- **capsule**: _<PyCapsule>_ - - - a DLPack capsule for the array. See {ref}`data-interchange` for details. - - -(method-__dlpack_device__)= -### \_\_dlpack\_device\_\_(self, /) - -Returns device type and device ID in DLPack format. Meant for use within {ref}`function-from_dlpack`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -#### Returns - -- **device**: _Tuple\[enum.IntEnum, int\]_ - - - a tuple `(device_type, device_id)` in DLPack format. Valid device type enum members are: - - ``` - CPU = 1 - CUDA = 2 - CPU_PINNED = 3 - OPENCL = 4 - VULKAN = 7 - METAL = 8 - VPI = 9 - ROCM = 10 - ``` - -(method-__eq__)= -### \_\_eq\_\_(self, other, /) - -Computes the truth value of `self_i == other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. May have any data type. - -- **other**: _Union\[ int, float, bool, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). May have any data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`equal(x1, x2)`](elementwise_functions.md#equalx1-x2-). -``` - -(method-__float__)= -### \_\_float\_\_(self, /) - -Converts a zero-dimensional floating-point array to a Python `float` object. - -#### Parameters - -- **self**: _<array>_ - - - zero-dimensional array instance. Must have a floating-point data type. - -#### Returns - -- **out**: _<float>_ - - - a Python `float` object representing the single element of the array instance. - -(method-__floordiv__)= -### \_\_floordiv\_\_(self, other, /) - -Evaluates `self_i // other_i` for each element of an array instance with the respective element of the array `other`. - -```{note} -For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. -``` - -#### Special Cases - -```{note} -Floor division was introduced in Python via [PEP 238](https://www.python.org/dev/peps/pep-0238/) with the goal to disambiguate "true division" (i.e., computing an approximation to the mathematical operation of division) from "floor division" (i.e., rounding the result of division toward negative infinity). The former was computed when one of the operands was a `float`, while the latter was computed when both operands were `int`s. Overloading the `/` operator to support both behaviors led to subtle numerical bugs when integers are possible, but not expected. - -To resolve this ambiguity, `/` was designated for true division, and `//` was designated for floor division. Semantically, floor division was [defined](https://www.python.org/dev/peps/pep-0238/#semantics-of-floor-division) as equivalent to `a // b == floor(a/b)`; however, special floating-point cases were left ill-defined. - -Accordingly, floor division is not implemented consistently across array libraries for some of the special cases documented below. Namely, when one of the operands is `infinity`, libraries may diverge with some choosing to strictly follow `floor(a/b)` and others choosing to pair `//` with `%` according to the relation `b = a % b + b * (a // b)`. The special cases leading to divergent behavior are documented below. - -This specification prefers floor division to match `floor(divide(x1, x2))` in order to avoid surprising and unexpected results; however, array libraries may choose to more strictly follow Python behavior. -``` - -For floating-point operands, let `self` equal `x1` and `other` equal `x2`. - -- If either `x1_i` or `x2_i` is `NaN`, the result is `NaN`. -- If `x1_i` is either `+infinity` or `-infinity` and `x2_i` is either `+infinity` or `-infinity`, the result is `NaN`. -- If `x1_i` is either `+0` or `-0` and `x2_i` is either `+0` or `-0`, the result is `NaN`. -- If `x1_i` is `+0` and `x2_i` is greater than `0`, the result is `+0`. -- If `x1_i` is `-0` and `x2_i` is greater than `0`, the result is `-0`. -- If `x1_i` is `+0` and `x2_i` is less than `0`, the result is `-0`. -- If `x1_i` is `-0` and `x2_i` is less than `0`, the result is `+0`. -- If `x1_i` is greater than `0` and `x2_i` is `+0`, the result is `+infinity`. -- If `x1_i` is greater than `0` and `x2_i` is `-0`, the result is `-infinity`. -- If `x1_i` is less than `0` and `x2_i` is `+0`, the result is `-infinity`. -- If `x1_i` is less than `0` and `x2_i` is `-0`, the result is `+infinity`. -- If `x1_i` is `+infinity` and `x2_i` is a positive (i.e., greater than `0`) finite number, the result is `+infinity`. (**note**: libraries may return `NaN` to match Python behavior.) -- If `x1_i` is `+infinity` and `x2_i` is a negative (i.e., less than `0`) finite number, the result is `-infinity`. (**note**: libraries may return `NaN` to match Python behavior.) -- If `x1_i` is `-infinity` and `x2_i` is a positive (i.e., greater than `0`) finite number, the result is `-infinity`. (**note**: libraries may return `NaN` to match Python behavior.) -- If `x1_i` is `-infinity` and `x2_i` is a negative (i.e., less than `0`) finite number, the result is `+infinity`. (**note**: libraries may return `NaN` to match Python behavior.) -- If `x1_i` is a positive (i.e., greater than `0`) finite number and `x2_i` is `+infinity`, the result is `+0`. -- If `x1_i` is a positive (i.e., greater than `0`) finite number and `x2_i` is `-infinity`, the result is `-0`. (**note**: libraries may return `-1.0` to match Python behavior.) -- If `x1_i` is a negative (i.e., less than `0`) finite number and `x2_i` is `+infinity`, the result is `-0`. (**note**: libraries may return `-1.0` to match Python behavior.) -- If `x1_i` is a negative (i.e., less than `0`) finite number and `x2_i` is `-infinity`, the result is `+0`. -- If `x1_i` and `x2_i` have the same mathematical sign and are both nonzero finite numbers, the result has a positive mathematical sign. -- If `x1_i` and `x2_i` have different mathematical signs and are both nonzero finite numbers, the result has a negative mathematical sign. -- In the remaining cases, where neither `-infinity`, `+0`, `-0`, nor `NaN` is involved, the quotient must be computed and rounded to the greatest (i.e., closest to `+infinity`) representable integer-value number that is not greater than the division result. If the magnitude is too large to represent, the operation overflows and the result is an `infinity` of appropriate mathematical sign. If the magnitude is too small to represent, the operation underflows and the result is a zero of appropriate mathematical sign. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`floor_divide(x1, x2)`](elementwise_functions.md#floor_dividex1-x2-). -``` - -(method-__ge__)= -### \_\_ge\_\_(self, other, /) - -Computes the truth value of `self_i >= other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`greater_equal(x1, x2)`](elementwise_functions.md#greater_equalx1-x2-). -``` - -(method-__getitem__)= -### \_\_getitem\_\_(self, key, /) - -Returns `self[key]`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -- **key**: _Union\[ int, slice, ellipsis, Tuple\[ Union\[ int, slice, ellipsis ], ... ], <array> ]_ - - - index key. - -#### Returns - -- **out**: _<array>_ - - - an array containing the accessed value(s). The returned array must have the same data type as `self`. - -(method-__gt__)= -### \_\_gt\_\_(self, other, /) - -Computes the truth value of `self_i > other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`greater(x1, x2)`](elementwise_functions.md#greaterx1-x2-). -``` - -(method-__index__)= -### \_\_index\_\_(self, /) - -Converts a zero-dimensional integer array to a Python `int` object. - -```{note} -This method is called to implement [`operator.index()`](https://docs.python.org/3/reference/datamodel.html#object.__index__). See also [PEP 357](https://www.python.org/dev/peps/pep-0357/). -``` - -#### Parameters - -- **self**: _<array>_ - - - zero-dimensional array instance. Must have an integer data type. - -#### Returns - -- **out**: _<int>_ - - - a Python `int` object representing the single element of the array instance. - -(method-__int__)= -### \_\_int\_\_(self, /) - -Converts a zero-dimensional integer array to a Python `int` object. - -#### Parameters - -- **self**: _<array>_ - - - zero-dimensional array instance. Must have an integer data type. - -#### Returns - -- **out**: _<int>_ - - - a Python `int` object representing the single element of the array instance. - -(method-__invert__)= -### \_\_invert\_\_(self, /) - -Evaluates `~self_i` for each element of an array instance. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer or boolean data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have the same data type as `self`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_invert(x)`](elementwise_functions.md#bitwise_invertx-). -``` - -(method-__le__)= -### \_\_le\_\_(self, other, /) - -Computes the truth value of `self_i <= other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`less_equal(x1, x2)`](elementwise_functions.md#less_equalx1-x2-). -``` - -(method-__lshift__)= -### \_\_lshift\_\_(self, other, /) - -Evaluates `self_i << other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer data type. - -- **other**: _Union\[ int, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have an integer data type. Each element must be greater than or equal to `0`. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have the same data type as `self`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_left_shift(x1, x2)`](elementwise_functions.md#bitwise_left_shiftx1-x2-). -``` - -(method-__lt__)= -### \_\_lt\_\_(self, other, /) - -Computes the truth value of `self_i < other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`less(x1, x2)`](elementwise_functions.md#lessx1-x2-). -``` - -(method-__matmul__)= -### \_\_matmul\_\_(self, other, /) - -Computes the matrix product. - -```{note} -The `matmul` function must implement the same semantics as the built-in `@` operator (see [PEP 465](https://www.python.org/dev/peps/pep-0465)). -``` - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. Must have at least one dimension. If `self` is one-dimensional having shape `(M,)` and `other` has more than one dimension, `self` must be promoted to a two-dimensional array by prepending `1` to its dimensions (i.e., must have shape `(1, M)`). After matrix multiplication, the prepended dimensions in the returned array must be removed. If `self` has more than one dimension (including after vector-to-matrix promotion), `shape(self)[:-2]` must be compatible with `shape(other)[:-2]` (after vector-to-matrix promotion) (see {ref}`broadcasting`). If `self` has shape `(..., M, K)`, the innermost two dimensions form matrices on which to perform matrix multiplication. - -- **other**: _<array>_ - - - other array. Should have a numeric data type. Must have at least one dimension. If `other` is one-dimensional having shape `(N,)` and `self` has more than one dimension, `other` must be promoted to a two-dimensional array by appending `1` to its dimensions (i.e., must have shape `(N, 1)`). After matrix multiplication, the appended dimensions in the returned array must be removed. If `other` has more than one dimension (including after vector-to-matrix promotion), `shape(other)[:-2]` must be compatible with `shape(self)[:-2]` (after vector-to-matrix promotion) (see {ref}`broadcasting`). If `other` has shape `(..., K, N)`, the innermost two dimensions form matrices on which to perform matrix multiplication. - -#### Returns - -- **out**: _<array>_ - - - if both `self` and `other` are one-dimensional arrays having shape `(N,)`, a zero-dimensional array containing the inner product as its only element. - - if `self` is a two-dimensional array having shape `(M, K)` and `other` is a two-dimensional array having shape `(K, N)`, a two-dimensional array containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication) and having shape `(M, N)`. - - if `self` is a one-dimensional array having shape `(K,)` and `other` is an array having shape `(..., K, N)`, an array having shape `(..., N)` (i.e., prepended dimensions during vector-to-matrix promotion must be removed) and containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication). - - if `self` is an array having shape `(..., M, K)` and `other` is a one-dimensional array having shape `(K,)`, an array having shape `(..., M)` (i.e., appended dimensions during vector-to-matrix promotion must be removed) and containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication). - - if `self` is a two-dimensional array having shape `(M, K)` and `other` is an array having shape `(..., K, N)`, an array having shape `(..., M, N)` and containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication) for each stacked matrix. - - if `self` is an array having shape `(..., M, K)` and `other` is a two-dimensional array having shape `(K, N)`, an array having shape `(..., M, N)` and containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication) for each stacked matrix. - - if either `self` or `other` has more than two dimensions, an array having a shape determined by {ref}`broadcasting` `shape(self)[:-2]` against `shape(other)[:-2]` and containing the [conventional matrix product](https://en.wikipedia.org/wiki/Matrix_multiplication) for each stacked matrix. - - The returned array must have a data type determined by {ref}`type-promotion`. - - ```{note} - Results must equal the results returned by the equivalent function [`matmul(x1, x2)`](linear_algebra_functions.md#matmulx1-x2-). - ``` - -#### Raises - -- if either `self` or `other` is a zero-dimensional array. -- if `self` is a one-dimensional array having shape `(K,)`, `other` is a one-dimensional array having shape `(L,)`, and `K != L`. -- if `self` is a one-dimensional array having shape `(K,)`, `other` is an array having shape `(..., L, N)`, and `K != L`. -- if `self` is an array having shape `(..., M, K)`, `other` is a one-dimensional array having shape `(L,)`, and `K != L`. -- if `self` is an array having shape `(..., M, K)`, `other` is an array having shape `(..., L, N)`, and `K != L`. - -(method-__mod__)= -### \_\_mod\_\_(self, other, /) - -Evaluates `self_i % other_i` for each element of an array instance with the respective element of the array `other`. - -```{note} -For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. -``` - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. Each element-wise result must have the same sign as the respective element `other_i`. The returned array must have a floating-point data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`remainder(x1, x2)`](elementwise_functions.md#remainderx1-x2-). -``` - -(method-__mul__)= -### \_\_mul\_\_(self, other, /) - -Calculates the product for each element of an array instance with the respective element of the array `other`. - -#### Special Cases - -For floating-point operands, let `self` equal `x1` and `other` equal `x2`. - -- If either `x1_i` or `x2_i` is `NaN`, the result is `NaN`. -- If `x1_i` is either `+infinity` or `-infinity` and `x2_i` is either `+0` or `-0`, the result is `NaN`. -- If `x1_i` is either `+0` or `-0` and `x2_i` is either `+infinity` or `-infinity`, the result is `NaN`. -- If `x1_i` and `x2_i` have the same mathematical sign, the result has a positive mathematical sign, unless the result is `NaN`. If the result is `NaN`, the "sign" of `NaN` is implementation-defined. -- If `x1_i` and `x2_i` have different mathematical signs, the result has a negative mathematical sign, unless the result is `NaN`. If the result is `NaN`, the "sign" of `NaN` is implementation-defined. -- If `x1_i` is either `+infinity` or `-infinity` and `x2_i` is either `+infinity` or `-infinity`, the result is a signed infinity with the mathematical sign determined by the rule already stated above. -- If `x1_i` is either `+infinity` or `-infinity` and `x2_i` is a nonzero finite number, the result is a signed infinity with the mathematical sign determined by the rule already stated above. -- If `x1_i` is a nonzero finite number and `x2_i` is either `+infinity` or `-infinity`, the result is a signed infinity with the mathematical sign determined by the rule already stated above. -- In the remaining cases, where neither `infinity` nor `NaN` is involved, the product must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported rounding mode. If the magnitude is too large to represent, the result is an `infinity` of appropriate mathematical sign. If the magnitude is too small to represent, the result is a zero of appropriate mathematical sign. - -```{note} -Floating-point multiplication is not always associative due to finite precision. -``` - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise products. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`multiply(x1, x2)`](elementwise_functions.md#multiplyx1-x2-). -``` - -(method-__ne__)= -### \_\_ne\_\_(self, other, /) - -Computes the truth value of `self_i != other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. May have any data type. - -- **other**: _Union\[ int, float, bool, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). May have any data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type of `bool` (i.e., must be a boolean array). - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`not_equal(x1, x2)`](elementwise_functions.md#not_equalx1-x2-). -``` - -(method-__neg__)= -### \_\_neg\_\_(self, /) - -Evaluates `-self_i` for each element of an array instance. - -```{note} -For signed integer data types, the numerical negative of the minimum representable integer is implementation-dependent. -``` - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the evaluated result for each element in `self`. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`negative(x)`](elementwise_functions.md#negativex-). -``` - -(method-__or__)= -### \_\_or\_\_(self, other, /) - -Evaluates `self_i | other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer or boolean data type. - -- **other**: _Union\[ int, bool, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have an integer or boolean data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_or(x1, x2)`](elementwise_functions.md#bitwise_orx1-x2-). -``` - -(method-__pos__)= -### \_\_pos\_\_(self, /) - -Evaluates `+self_i` for each element of an array instance. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the evaluated result for each element. The returned array must have the same data type as `self`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`positive(x)`](elementwise_functions.md#positivex-). -``` - -(method-__pow__)= -### \_\_pow\_\_(self, other, /) - -Calculates an implementation-dependent approximation of exponentiation by raising each element (the base) of an array instance to the power of `other_i` (the exponent), where `other_i` is the corresponding element of the array `other`. - -```{note} -If both `self` and `other` have integer data types, the result of `__pow__` when `other_i` is negative (i.e., less than zero) is unspecified and thus implementation-dependent. - -If `self` has an integer data type and `other` has a floating-point data type, behavior is implementation-dependent, as type promotion between data type "kinds" (e.g., integer versus floating-point) is unspecified. -``` - -#### Special Cases - -For floating-point operands, let `self` equal `x1` and `other` equal `x2`. - -- If `x1_i` is not equal to `1` and `x2_i` is `NaN`, the result is `NaN`. -- If `x2_i` is `+0`, the result is `1`, even if `x1_i` is `NaN`. -- If `x2_i` is `-0`, the result is `1`, even if `x1_i` is `NaN`. -- If `x1_i` is `NaN` and `x2_i` is not equal to `0`, the result is `NaN`. -- If `abs(x1_i)` is greater than `1` and `x2_i` is `+infinity`, the result is `+infinity`. -- If `abs(x1_i)` is greater than `1` and `x2_i` is `-infinity`, the result is `+0`. -- If `abs(x1_i)` is `1` and `x2_i` is `+infinity`, the result is `1`. -- If `abs(x1_i)` is `1` and `x2_i` is `-infinity`, the result is `1`. -- If `x1_i` is `1` and `x2_i` is not `NaN`, the result is `1`. -- If `abs(x1_i)` is less than `1` and `x2_i` is `+infinity`, the result is `+0`. -- If `abs(x1_i)` is less than `1` and `x2_i` is `-infinity`, the result is `+infinity`. -- If `x1_i` is `+infinity` and `x2_i` is greater than `0`, the result is `+infinity`. -- If `x1_i` is `+infinity` and `x2_i` is less than `0`, the result is `+0`. -- If `x1_i` is `-infinity`, `x2_i` is greater than `0`, and `x2_i` is an odd integer value, the result is `-infinity`. -- If `x1_i` is `-infinity`, `x2_i` is greater than `0`, and `x2_i` is not an odd integer value, the result is `+infinity`. -- If `x1_i` is `-infinity`, `x2_i` is less than `0`, and `x2_i` is an odd integer value, the result is `-0`. -- If `x1_i` is `-infinity`, `x2_i` is less than `0`, and `x2_i` is not an odd integer value, the result is `+0`. -- If `x1_i` is `+0` and `x2_i` is greater than `0`, the result is `+0`. -- If `x1_i` is `+0` and `x2_i` is less than `0`, the result is `+infinity`. -- If `x1_i` is `-0`, `x2_i` is greater than `0`, and `x2_i` is an odd integer value, the result is `-0`. -- If `x1_i` is `-0`, `x2_i` is greater than `0`, and `x2_i` is not an odd integer value, the result is `+0`. -- If `x1_i` is `-0`, `x2_i` is less than `0`, and `x2_i` is an odd integer value, the result is `-infinity`. -- If `x1_i` is `-0`, `x2_i` is less than `0`, and `x2_i` is not an odd integer value, the result is `+infinity`. -- If `x1_i` is less than `0`, `x1_i` is a finite number, `x2_i` is a finite number, and `x2_i` is not an integer value, the result is `NaN`. - -#### Parameters - -- **self**: _<array>_ - - - array instance whose elements correspond to the exponentiation base. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array whose elements correspond to the exponentiation exponent. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`pow(x1, x2)`](elementwise_functions.md#powx1-x2-). -``` - -(method-__rshift__)= -### \_\_rshift\_\_(self, other, /) - -Evaluates `self_i >> other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer data type. - -- **other**: _Union\[ int, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have an integer data type. Each element must be greater than or equal to `0`. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have the same data type as `self`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_right_shift(x1, x2)`](elementwise_functions.md#bitwise_right_shiftx1-x2-). -``` - -(method-__setitem__)= -### \_\_setitem\_\_(self, key, value, /) - -Sets `self[key]` to `value`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -- **key**: _Union\[ int, slice, ellipsis, Tuple\[ Union\[ int, slice, ellipsis ], ... ], <array> ]_ - - - index key. - -- **value**: _Union\[ int, float, bool, <array> ]_ - - - value(s) to set. Must be compatible with `self[key]` (see {ref}`broadcasting`). - -```{note} -Setting array values must not affect the data type of `self`. - -When `value` is a Python scalar (i.e., `int`, `float`, `bool`), behavior must follow specification guidance on mixing arrays with Python scalars (see {ref}`type-promotion`). - -When `value` is an `array` of a different data type than `self`, how values are cast to the data type of `self` is implementation defined. -``` - -(method-__sub__)= -### \_\_sub\_\_(self, other, /) - -Calculates the difference for each element of an array instance with the respective element of the array `other`. The result of `self_i - other_i` must be the same as `self_i + (-other_i)` and must be governed by the same floating-point rules as addition (see [`__add__()`](#__add__self-other-)). - -#### Parameters - -- **self**: _<array>_ - - - array instance (minuend array). Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - subtrahend array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise differences. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`subtract(x1, x2)`](elementwise_functions.md#subtractx1-x2-). -``` - -(method-__truediv__)= -### \_\_truediv\_\_(self, other, /) - -Evaluates `self_i / other_i` for each element of an array instance with the respective element of the array `other`. - -```{note} -If one or both of `self` and `other` have integer data types, the result is implementation-dependent, as type promotion between data type "kinds" (e.g., integer versus floating-point) is unspecified. - -Specification-compliant libraries may choose to raise an error or return an array containing the element-wise results. If an array is returned, the array must have a floating-point data type. -``` - -#### Special Cases - -For floating-point operands, let `self` equal `x1` and `other` equal `x2`. - -- If either `x1_i` or `x2_i` is `NaN`, the result is `NaN`. -- If `x1_i` is either `+infinity` or `-infinity` and `x2_i` is either `+infinity` or `-infinity`, the result is `NaN`. -- If `x1_i` is either `+0` or `-0` and `x2_i` is either `+0` or `-0`, the result is `NaN`. -- If `x1_i` is `+0` and `x2_i` is greater than `0`, the result is `+0`. -- If `x1_i` is `-0` and `x2_i` is greater than `0`, the result is `-0`. -- If `x1_i` is `+0` and `x2_i` is less than `0`, the result is `-0`. -- If `x1_i` is `-0` and `x2_i` is less than `0`, the result is `+0`. -- If `x1_i` is greater than `0` and `x2_i` is `+0`, the result is `+infinity`. -- If `x1_i` is greater than `0` and `x2_i` is `-0`, the result is `-infinity`. -- If `x1_i` is less than `0` and `x2_i` is `+0`, the result is `-infinity`. -- If `x1_i` is less than `0` and `x2_i` is `-0`, the result is `+infinity`. -- If `x1_i` is `+infinity` and `x2_i` is a positive (i.e., greater than `0`) finite number, the result is `+infinity`. -- If `x1_i` is `+infinity` and `x2_i` is a negative (i.e., less than `0`) finite number, the result is `-infinity`. -- If `x1_i` is `-infinity` and `x2_i` is a positive (i.e., greater than `0`) finite number, the result is `-infinity`. -- If `x1_i` is `-infinity` and `x2_i` is a negative (i.e., less than `0`) finite number, the result is `+infinity`. -- If `x1_i` is a positive (i.e., greater than `0`) finite number and `x2_i` is `+infinity`, the result is `+0`. -- If `x1_i` is a positive (i.e., greater than `0`) finite number and `x2_i` is `-infinity`, the result is `-0`. -- If `x1_i` is a negative (i.e., less than `0`) finite number and `x2_i` is `+infinity`, the result is `-0`. -- If `x1_i` is a negative (i.e., less than `0`) finite number and `x2_i` is `-infinity`, the result is `+0`. -- If `x1_i` and `x2_i` have the same mathematical sign and are both nonzero finite numbers, the result has a positive mathematical sign. -- If `x1_i` and `x2_i` have different mathematical signs and are both nonzero finite numbers, the result has a negative mathematical sign. -- In the remaining cases, where neither `-infinity`, `+0`, `-0`, nor `NaN` is involved, the quotient must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported rounding mode. If the magnitude is too large to represent, the operation overflows and the result is an `infinity` of appropriate mathematical sign. If the magnitude is too small to represent, the operation underflows and the result is a zero of appropriate mathematical sign. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have a numeric data type. - -- **other**: _Union\[ int, float, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have a numeric data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array should have a floating-point data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`divide(x1, x2)`](elementwise_functions.md#dividex1-x2-). -``` - -(method-__xor__)= -### \_\_xor\_\_(self, other, /) - -Evaluates `self_i ^ other_i` for each element of an array instance with the respective element of the array `other`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. Should have an integer or boolean data type. - -- **other**: _Union\[ int, bool, <array> ]_ - - - other array. Must be compatible with `self` (see {ref}`broadcasting`). Should have an integer or boolean data type. - -#### Returns - -- **out**: _<array>_ - - - an array containing the element-wise results. The returned array must have a data type determined by {ref}`type-promotion`. - -```{note} -Element-wise results must equal the results returned by the equivalent element-wise function [`bitwise_xor(x1, x2)`](elementwise_functions.md#bitwise_xorx1-x2-). -``` - -(method-to_device)= -### to\_device(self, device, /, *, stream=None) - -Copy the array from the device on which it currently resides to the specified `device`. - -#### Parameters - -- **self**: _<array>_ - - - array instance. - -- **device**: _<device>_ - - - a `device` object (see {ref}`device-support`). - -- **stream**: _Optional\[ Union\[ int, Any ]]_ - - - stream object to use during copy. In addition to the types supported in {ref}`method-__dlpack__`, implementations may choose to support any library-specific stream object with the caveat that any code using such an object would not be portable. - -#### Returns - -- **out**: _<array>_ - - - an array with the same data and data type as `self` and located on the specified `device`. - -```{note} -If `stream` is given, the copy operation should be enqueued on the provided `stream`; otherwise, the copy operation should be enqueued on the default stream/queue. Whether the copy is performed synchronously or asynchronously is implementation-dependent. Accordingly, if synchronization is required to guarantee data safety, this must be clearly explained in a conforming library's documentation. -``` From fe93f2fbe672d7b45ac7b10478dfb0b44529412b Mon Sep 17 00:00:00 2001 From: Stephannie Jimenez Date: Thu, 20 Jan 2022 15:34:28 -0500 Subject: [PATCH 10/10] Fix notes and admonitions --- .../signatures/array_object.py | 448 ++++++++++-------- 1 file changed, 243 insertions(+), 205 deletions(-) diff --git a/spec/API_specification/signatures/array_object.py b/spec/API_specification/signatures/array_object.py index 89bb72902..f726bd914 100644 --- a/spec/API_specification/signatures/array_object.py +++ b/spec/API_specification/signatures/array_object.py @@ -63,11 +63,12 @@ def shape() -> Tuple[Optional[int], ...]: out: Tuple[Optional[int], ...] array dimensions. An array dimension must be ``None`` if and only if a dimension is unknown. - Notes - ----- - - For array libraries having graph-based computational models, array dimensions may be unknown due to data-dependent operations (e.g., boolean indexing; ``A[:, B > 0]``) and thus cannot be statically resolved without knowing array contents. - - The returned value should be a tuple; however, where warranted, an array library may choose to return a custom shape object. If an array library returns a custom shape object, the object must be immutable, must support indexing for dimension retrieval, and must behave similarly to a tuple. + .. note:: + For array libraries having graph-based computational models, array dimensions may be unknown due to data-dependent operations (e.g., boolean indexing; ``A[:, B > 0]``) and thus cannot be statically resolved without knowing array contents. + + .. note:: + The returned value should be a tuple; however, where warranted, an array library may choose to return a custom shape object. If an array library returns a custom shape object, the object must be immutable, must support indexing for dimension retrieval, and must behave similarly to a tuple. """ @property @@ -75,16 +76,17 @@ def size() -> Optional[int]: """ Number of elements in an array. + .. note:: + This must equal the product of the array's dimensions. + Returns ------- out: Optional[int] number of elements in an array. The returned value must be ``None`` if and only if one or more array dimensions are unknown. - Notes - ----- - - This must equal the product of the array's dimensions. - - For array libraries having graph-based computational models, an array may have unknown dimensions due to data-dependent operations. + .. note:: + For array libraries having graph-based computational models, an array may have unknown dimensions due to data-dependent operations. """ @property @@ -99,30 +101,17 @@ def T() -> array: out: array two-dimensional array whose first and last dimensions (axes) are permuted in reverse order relative to original array. The returned array must have the same data type as the original array.two-dimensional array whose first and last dimensions (axes) are permuted in reverse order relative to original array. The returned array must have the same data type as the original array. - Notes - ----- - - Limiting the transpose to two-dimensional arrays (matrices) deviates from the NumPy et al practice of reversing all axes for arrays having more than two-dimensions. This is intentional, as reversing all axes was found to be problematic (e.g., conflicting with the mathematical definition of a transpose which is limited to matrices; not operating on batches of matrices; et cetera). In order to reverse all axes, one is recommended to use the functional ``permute_dims`` interface found in this specification. + + .. note:: + Limiting the transpose to two-dimensional arrays (matrices) deviates from the NumPy et al practice of reversing all axes for arrays having more than two-dimensions. This is intentional, as reversing all axes was found to be problematic (e.g., conflicting with the mathematical definition of a transpose which is limited to matrices; not operating on batches of matrices; et cetera). In order to reverse all axes, one is recommended to use the functional ``permute_dims`` interface found in this specification. """ def __abs__(self: array, /) -> array: """ Calculates the absolute value for each element of an array instance (i.e., the element-wise result has the same magnitude as the respective element but has positive sign). - Parameters - ---------- - self: array - array instance. Should have a numeric data type. - - Returns - ------- - out: array - an array containing the element-wise absolute value. The returned array must have the same data type as ``self``. - - Notes - ----- - - For signed integer data types, the absolute value of the minimum representable integer is implementation-dependent. - - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-abs`. + .. note:: + For signed integer data types, the absolute value of the minimum representable integer is implementation-dependent. **Special cases** @@ -131,29 +120,25 @@ def __abs__(self: array, /) -> array: - If ``x_i`` is ``NaN``, the result is ``NaN``. - If ``x_i`` is ``-0``, the result is ``+0``. - If ``x_i`` is ``-infinity``, the result is ``+infinity``. - """ - - def __add__(self: array, other: Union[int, float, array], /) -> array: - """ - Calculates the sum for each element of an array instance with the respective element of the array ``other``. Parameters ---------- self: array - array instance (augend array). Should have a numeric data type. - other: Union[int, float, array] - addend array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + array instance. Should have a numeric data type. Returns ------- out: array - an array containing the element-wise sums. The returned array must have a data type determined by :ref:`type-promotion`. + an array containing the element-wise absolute value. The returned array must have the same data type as ``self``. - Notes - ----- - - Floating-point addition is a commutative operation, but not always associative. - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-add`. + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-abs`. + """ + + def __add__(self: array, other: Union[int, float, array], /) -> array: + """ + Calculates the sum for each element of an array instance with the respective element of the array ``other``. **Special cases** @@ -176,6 +161,25 @@ def __add__(self: array, other: Union[int, float, array], /) -> array: - If ``x1_i`` is a nonzero finite number and ``x2_i`` is either ``+0`` or ``-0``, the result is ``x1_i``. - If ``x1_i`` is a nonzero finite number and ``x2_i`` is ``-x1_i``, the result is ``+0``. - In the remaining cases, when neither ``infinity``, ``+0``, ``-0``, nor a ``NaN`` is involved, and the operands have the same mathematical sign or have different magnitudes, the sum must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported round mode. If the magnitude is too large to represent, the operation overflows and the result is an ``infinity`` of appropriate mathematical sign. + + .. note:: + Floating-point addition is a commutative operation, but not always associative. + + Parameters + ---------- + self: array + array instance (augend array). Should have a numeric data type. + other: Union[int, float, array] + addend array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise sums. The returned array must have a data type determined by :ref:`type-promotion`. + + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-add`. """ def __and__(self: array, other: Union[int, bool, array], /) -> array: @@ -194,9 +198,9 @@ def __and__(self: array, other: Union[int, bool, array], /) -> array: out: array an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_and`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_and`. """ def __array_namespace__(self: array, /, *, api_version: Optional[str] = None) -> Any: @@ -240,12 +244,39 @@ def __dlpack__(self: array, /, *, stream: Optional[Union[int, Any]] = None) -> P self: array array instance. stream: Optional[Union[int, Any]] - for CUDA and ROCm, a Python integer representing a pointer to a stream, on devices that support streams. ``stream`` is provided by the consumer to the producer to instruct the producer to ensure that operations can safely be performed on the array (e.g., by inserting a dependency between streams via "wait for event"). The pointer must be a positive integer or ``-1``. If ``stream`` is ``-1``, the value may be used by the consumer to signal "producer must not perform any synchronization". The ownership of the stream stays with the consumer. - On CPU and other device types without streams, only ``None`` is accepted. + for CUDA and ROCm, a Python integer representing a pointer to a stream, on devices that support streams. ``stream`` is provided by the consumer to the producer to instruct the producer to ensure that operations can safely be performed on the array (e.g., by inserting a dependency between streams via "wait for event"). The pointer must be a positive integer or ``-1``. If ``stream`` is ``-1``, the value may be used by the consumer to signal "producer must not perform any synchronization". The ownership of the stream stays with the consumer. On CPU and other device types without streams, only ``None`` is accepted. + + For other device types which do have a stream, queue or similar synchronization mechanism, the most appropriate type to use for ``stream`` is not yet determined. E.g., for SYCL one may want to use an object containing an in-order ``cl::sycl::queue``. This is allowed when libraries agree on such a convention, and may be standardized in a future version of this API standard. + + + .. note:: + Support for a ``stream`` value other than ``None`` is optional and implementation-dependent. + - For other device types which do have a stream, queue or similar synchronization mechanism, the most appropriate type to use for `stream` is not yet determined. E.g., for SYCL one may want to use an object containing an in-order ``cl::sycl::queue``. This is allowed when libraries agree on such a convention, and may be standardized in a future version of this API standard. + Device-specific notes: - **Tip** + + .. admonition:: CUDA + :class: note + + - ``None``: producer must assume the legacy default stream (default). + - ``1``: the legacy default stream. + - ``2``: the per-thread default stream. + - ``> 2``: stream number represented as a Python integer. + - ``0`` is disallowed due to its ambiguity: ``0`` could mean either ``None``, ``1``, or ``2``. + + + .. admonition:: ROCm + :class: note + + - ``None``: producer must assume the legacy default stream (default). + - ``0``: the default stream. + - ``> 2``: stream number represented as a Python integer. + - Using ``1`` and ``2`` is not supported. + + + .. admonition:: Tip + :class: important It is recommended that implementers explicitly handle streams. If they use the legacy default stream, specifying ``1`` (CUDA) or ``0`` @@ -257,28 +288,6 @@ def __dlpack__(self: array, /, *, stream: Optional[Union[int, Any]] = None) -> P ------- capsule: PyCapsule a DLPack capsule for the array. See :ref:`data-interchange` for details. - - Notes - ----- - - Support for a ``stream`` value other than ``None`` is optional and implementation-dependent. - - Device-specific notes: - - **CUDA** - - - ``None``: producer must assume the legacy default stream (default). - - ``1``: the legacy default stream. - - ``2``: the per-thread default stream. - - ``> 2``: stream number represented as a Python integer. - - ``0`` is disallowed due to its ambiguity: ``0`` could mean either ``None``, ``1``, or ``2``. - - **ROCm** - - - ``None``: producer must assume the legacy default stream (default). - - ``0``: the default stream. - - ``> 2``: stream number represented as a Python integer. - - Using ``1`` and ``2`` is not supported. """ def __dlpack_device__(self: array, /) -> Tuple[Enum, int]: @@ -295,14 +304,16 @@ def __dlpack_device__(self: array, /) -> Tuple[Enum, int]: device: Tuple[Enum, int] a tuple ``(device_type, device_id)`` in DLPack format. Valid device type enum members are: - - ``CPU = 1`` - - ``CUDA = 2`` - - ``CPU_PINNED = 3`` - - ``OPENCL = 4`` - - ``VULKAN = 7`` - - ``METAL = 8`` - - ``VPI = 9`` - - ``ROCM = 10`` + :: + + CPU = 1 + CUDA = 2 + CPU_PINNED = 3 + OPENCL = 4 + VULKAN = 7 + METAL = 8 + VPI = 9 + ROCM = 10 """ def __eq__(self: array, other: Union[int, float, bool, array], /) -> array: @@ -321,9 +332,9 @@ def __eq__(self: array, other: Union[int, float, bool, array], /) -> array: out: array an array containing the element-wise results. The returned array must have a data type of ``bool``. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-equal`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-equal`. """ def __float__(self: array, /) -> float: @@ -345,25 +356,19 @@ def __floordiv__(self: array, other: Union[int, float, array], /) -> array: """ Evaluates ``self_i // other_i`` for each element of an array instance with the respective element of the array ``other``. - Parameters - ---------- - self: array - array instance. Should have a numeric data type. - other: Union[int, float, array] - other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + .. note:: + For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. - Returns - ------- - out: array - an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. + **Special cases** - Notes - ----- - - For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-floor_divide`. - - Floor division was introduced in Python via `PEP 238 `_ with the goal to disambiguate "true division" (i.e., computing an approximation to the mathematical operation of division) from "floor division" (i.e., rounding the result of division toward negative infinity). The former was computed when one of the operands was a ``float``, while the latter was computed when both operands were ``int``s. Overloading the ``/`` operator to support both behaviors led to subtle numerical bugs when integers are possible, but not expected. To resolve this ambiguity, ``/`` was designated for true division, and ``//`` was designated for floor division. Semantically, floor division was `defined `_ as equivalent to ``a // b == floor(a/b)``; however, special floating-point cases were left ill-defined. Accordingly, floor division is not implemented consistently across array libraries for some of the special cases documented below. Namely, when one of the operands is ``infinity``, libraries may diverge with some choosing to strictly follow ``floor(a/b)`` and others choosing to pair ``//`` with ``%`` according to the relation ``b = a % b + b * (a // b)``. The special cases leading to divergent behavior are documented below. This specification prefers floor division to match ``floor(divide(x1, x2))`` in order to avoid surprising and unexpected results; however, array libraries may choose to more strictly follow Python behavior. + .. note:: + Floor division was introduced in Python via `PEP 238 `_ with the goal to disambiguate "true division" (i.e., computing an approximation to the mathematical operation of division) from "floor division" (i.e., rounding the result of division toward negative infinity). The former was computed when one of the operands was a ``float``, while the latter was computed when both operands were ``int``s. Overloading the ``/`` operator to support both behaviors led to subtle numerical bugs when integers are possible, but not expected. - **Special cases** + To resolve this ambiguity, ``/`` was designated for true division, and ``//`` was designated for floor division. Semantically, floor division was `defined `_ as equivalent to ``a // b == floor(a/b)``; however, special floating-point cases were left ill-defined. + + Accordingly, floor division is not implemented consistently across array libraries for some of the special cases documented below. Namely, when one of the operands is ``infinity``, libraries may diverge with some choosing to strictly follow ``floor(a/b)`` and others choosing to pair ``//`` with ``%`` according to the relation ``b = a % b + b * (a // b)``. The special cases leading to divergent behavior are documented below. + + This specification prefers floor division to match ``floor(divide(x1, x2))`` in order to avoid surprising and unexpected results; however, array libraries may choose to more strictly follow Python behavior. For floating-point operands, let ``self`` equal ``x1`` and ``other`` equal ``x2``. @@ -389,6 +394,22 @@ def __floordiv__(self: array, other: Union[int, float, array], /) -> array: - If ``x1_i`` and ``x2_i`` have the same mathematical sign and are both nonzero finite numbers, the result has a positive mathematical sign. - If ``x1_i`` and ``x2_i`` have different mathematical signs and are both nonzero finite numbers, the result has a negative mathematical sign. - In the remaining cases, where neither ``-infinity``, ``+0``, ``-0``, nor ``NaN`` is involved, the quotient must be computed and rounded to the greatest (i.e., closest to ``+infinity``) representable integer-value number that is not greater than the division result. If the magnitude is too large to represent, the operation overflows and the result is an ``infinity`` of appropriate mathematical sign. If the magnitude is too small to represent, the operation underflows and the result is a zero of appropriate mathematical sign. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. + + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-floor_divide`. """ def __ge__(self: array, other: Union[int, float, array], /) -> array: @@ -407,10 +428,10 @@ def __ge__(self: array, other: Union[int, float, array], /) -> array: out: array an array containing the element-wise results. The returned array must have a data type of ``bool``. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-greater_equal`. - """ + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-greater_equal`. + """ def __getitem__(self: array, key: Union[int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], array], /) -> array: """ @@ -445,15 +466,18 @@ def __gt__(self: array, other: Union[int, float, array], /) -> array: out: array an array containing the element-wise results. The returned array must have a data type of ``bool``. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-greater`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-greater`. """ def __index__(self: array, /) -> int: """ Converts a zero-dimensional integer array to a Python ``int`` object. + .. note:: + This method is called to implement `operator.index() `_. See also `PEP 357 `_. + Parameters ---------- self: array @@ -463,10 +487,6 @@ def __index__(self: array, /) -> int: ------- out: int a Python ``int`` object representing the single element of the array instance. - - Notes - ----- - - This method is called to implement `operator.index() `_. See also `PEP 357 `_. """ def __int__(self: array, /) -> int: @@ -498,9 +518,9 @@ def __invert__(self: array, /) -> array: out: array an array containing the element-wise results. The returned array must have the same data type as `self`. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_invert`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_invert`. """ def __le__(self: array, other: Union[int, float, array], /) -> array: @@ -519,9 +539,9 @@ def __le__(self: array, other: Union[int, float, array], /) -> array: out: array an array containing the element-wise results. The returned array must have a data type of ``bool``. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-less_equal`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-less_equal`. """ def __lshift__(self: array, other: Union[int, array], /) -> array: @@ -540,9 +560,9 @@ def __lshift__(self: array, other: Union[int, array], /) -> array: out: array an array containing the element-wise results. The returned array must have the same data type as ``self``. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_left_shift`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_left_shift`. """ def __lt__(self: array, other: Union[int, float, array], /) -> array: @@ -561,15 +581,18 @@ def __lt__(self: array, other: Union[int, float, array], /) -> array: out: array an array containing the element-wise results. The returned array must have a data type of ``bool``. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-less`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-less`. """ def __matmul__(self: array, other: array, /) -> array: """ Computes the matrix product. + .. note:: + The ``matmul`` function must implement the same semantics as the built-in ``@`` operator (see `PEP 465 `_). + Parameters ---------- self: array @@ -589,10 +612,9 @@ def __matmul__(self: array, other: array, /) -> array: - if either ``self`` or ``other`` has more than two dimensions, an array having a shape determined by :ref:`broadcasting` ``shape(self)[:-2]`` against ``shape(other)[:-2]`` and containing the `conventional matrix product `_ for each stacked matrix. - The returned array must have a data type determined by :ref:`type-promotion`. - Notes - ----- - - The ``matmul`` function must implement the same semantics as the built-in ``@`` operator (see `PEP 465 `_). - - Results must equal the results returned by the equivalent function :ref:`function-matmul`. + + .. note:: + Results must equal the results returned by the equivalent function :ref:`function-matmul`. **Raises** @@ -607,6 +629,9 @@ def __mod__(self: array, other: Union[int, float, array], /) -> array: """ Evaluates ``self_i % other_i`` for each element of an array instance with the respective element of the array ``other``. + .. note:: + For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. + Parameters ---------- self: array @@ -619,33 +644,15 @@ def __mod__(self: array, other: Union[int, float, array], /) -> array: out: array an array containing the element-wise results. Each element-wise result must have the same sign as the respective element ``other_i``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - Notes - ----- - - For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-remainder`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-remainder`. """ def __mul__(self: array, other: Union[int, float, array], /) -> array: """ Calculates the product for each element of an array instance with the respective element of the array ``other``. - Parameters - ---------- - self: array - array instance. Should have a numeric data type. - other: Union[int, float, array] - other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. - - Returns - ------- - out: array - an array containing the element-wise products. The returned array must have a data type determined by :ref:`type-promotion`. - - Notes - ----- - - Floating-point multiplication is not always associative due to finite precision. - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-multiply`. - **Special cases** For floating-point operands, let ``self`` equal ``x1`` and ``other`` equal ``x2``. @@ -659,6 +666,26 @@ def __mul__(self: array, other: Union[int, float, array], /) -> array: - If ``x1_i`` is either ``+infinity`` or ``-infinity`` and ``x2_i`` is a nonzero finite number, the result is a signed infinity with the mathematical sign determined by the rule already stated above. - If ``x1_i`` is a nonzero finite number and ``x2_i`` is either ``+infinity`` or ``-infinity``, the result is a signed infinity with the mathematical sign determined by the rule already stated above. - In the remaining cases, where neither ``infinity`` nor `NaN` is involved, the product must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported rounding mode. If the magnitude is too large to represent, the result is an ``infinity`` of appropriate mathematical sign. If the magnitude is too small to represent, the result is a zero of appropriate mathematical sign. + + + .. note:: + Floating-point multiplication is not always associative due to finite precision. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise products. The returned array must have a data type determined by :ref:`type-promotion`. + + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-multiply`. """ def __ne__(self: array, other: Union[int, float, bool, array], /) -> array: @@ -677,15 +704,18 @@ def __ne__(self: array, other: Union[int, float, bool, array], /) -> array: out: array an array containing the element-wise results. The returned array must have a data type of ``bool`` (i.e., must be a boolean array). - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-not_equal`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-not_equal`. """ def __neg__(self: array, /) -> array: """ Evaluates ``-self_i`` for each element of an array instance. + .. note:: + For signed integer data types, the numerical negative of the minimum representable integer is implementation-dependent. + Parameters ---------- self: array @@ -696,10 +726,9 @@ def __neg__(self: array, /) -> array: out: array an array containing the evaluated result for each element in ``self``. The returned array must have a data type determined by :ref:`type-promotion`. - Notes - ----- - - For signed integer data types, the numerical negative of the minimum representable integer is implementation-dependent. - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-negative`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-negative`. """ def __or__(self: array, other: Union[int, bool, array], /) -> array: @@ -718,9 +747,9 @@ def __or__(self: array, other: Union[int, bool, array], /) -> array: out: array an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_or`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_or`. """ def __pos__(self: array, /) -> array: @@ -737,32 +766,19 @@ def __pos__(self: array, /) -> array: out: array an array containing the evaluated result for each element. The returned array must have the same data type as ``self``. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-positive`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-positive`. """ def __pow__(self: array, other: Union[int, float, array], /) -> array: """ Calculates an implementation-dependent approximation of exponentiation by raising each element (the base) of an array instance to the power of ``other_i`` (the exponent), where ``other_i`` is the corresponding element of the array ``other``. - Parameters - ---------- - self: array - array instance whose elements correspond to the exponentiation base. Should have a numeric data type. - other: Union[int, float, array] - other array whose elements correspond to the exponentiation exponent. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + .. note:: + If both ``self`` and ``other`` have integer data types, the result of ``__pow__`` when `other_i` is negative (i.e., less than zero) is unspecified and thus implementation-dependent. - Returns - ------- - out: array - an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. - - Notes - ----- - - If both ``self`` and ``other`` have integer data types, the result of ``__pow__`` when `other_i` is negative (i.e., less than zero) is unspecified and thus implementation-dependent. - - If ``self`` has an integer data type and ``other`` has a floating-point data type, behavior is implementation-dependent, as type promotion between data type "kinds" (e.g., integer versus floating-point) is unspecified. - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-pow`. + If ``self`` has an integer data type and ``other`` has a floating-point data type, behavior is implementation-dependent, as type promotion between data type "kinds" (e.g., integer versus floating-point) is unspecified. **Special cases** @@ -792,6 +808,22 @@ def __pow__(self: array, other: Union[int, float, array], /) -> array: - If ``x1_i`` is ``-0``, ``x2_i`` is less than ``0``, and ``x2_i`` is an odd integer value, the result is ``-infinity``. - If ``x1_i`` is ``-0``, ``x2_i`` is less than ``0``, and ``x2_i`` is not an odd integer value, the result is ``+infinity``. - If ``x1_i`` is less than ``0``, ``x1_i`` is a finite number, ``x2_i`` is a finite number, and ``x2_i`` is not an integer value, the result is ``NaN``. + + Parameters + ---------- + self: array + array instance whose elements correspond to the exponentiation base. Should have a numeric data type. + other: Union[int, float, array] + other array whose elements correspond to the exponentiation exponent. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. + + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-pow`. """ def __rshift__(self: array, other: Union[int, array], /) -> array: @@ -810,9 +842,9 @@ def __rshift__(self: array, other: Union[int, array], /) -> array: out: array an array containing the element-wise results. The returned array must have the same data type as ``self``. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_right_shift`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_right_shift`. """ def __setitem__(self: array, key: Union[int, slice, ellipsis, Tuple[Union[int, slice, ellipsis], ...], array], value: Union[int, float, bool, array], /) -> None: @@ -828,11 +860,14 @@ def __setitem__(self: array, key: Union[int, slice, ellipsis, Tuple[Union[int, s value: Union[int, float, bool, array] value(s) to set. Must be compatible with ``self[key]`` (see :ref:`broadcasting`). - Notes - ----- - - Setting array values must not affect the data type of ``self``. - - When ``value`` is a Python scalar (i.e., ``int``, ``float``, ``bool``), behavior must follow specification guidance on mixing arrays with Python scalars (see :ref:`type-promotion`). - - When ``value`` is an ``array`` of a different data type than ``self``, how values are cast to the data type of ``self`` is implementation defined. + + .. note:: + + Setting array values must not affect the data type of ``self``. + + When ``value`` is a Python scalar (i.e., ``int``, ``float``, ``bool``), behavior must follow specification guidance on mixing arrays with Python scalars (see :ref:`type-promotion`). + + When ``value`` is an ``array`` of a different data type than ``self``, how values are cast to the data type of ``self`` is implementation defined. """ def __sub__(self: array, other: Union[int, float, array], /) -> array: @@ -851,32 +886,19 @@ def __sub__(self: array, other: Union[int, float, array], /) -> array: out: array an array containing the element-wise differences. The returned array must have a data type determined by :ref:`type-promotion`. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-subtract`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-subtract`. """ def __truediv__(self: array, other: Union[int, float, array], /) -> array: """ Evaluates ``self_i / other_i`` for each element of an array instance with the respective element of the array ``other``. - Parameters - ---------- - self: array - array instance. Should have a numeric data type. - other: Union[int, float, array] - other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. - - Returns - ------- - out: array - an array containing the element-wise results. The returned array should have a floating-point data type determined by :ref:`type-promotion`. + .. note:: + If one or both of ``self`` and ``other`` have integer data types, the result is implementation-dependent, as type promotion between data type "kinds" (e.g., integer versus floating-point) is unspecified. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-divide`. - - If one or both of ``self`` and ``other`` have integer data types, the result is implementation-dependent, as type promotion between data type "kinds" (e.g., integer versus floating-point) is unspecified. - - Specification-compliant libraries may choose to raise an error or return an array containing the element-wise results. If an array is returned, the array must have a floating-point data type. + Specification-compliant libraries may choose to raise an error or return an array containing the element-wise results. If an array is returned, the array must have a floating-point data type. **Special cases** @@ -904,6 +926,22 @@ def __truediv__(self: array, other: Union[int, float, array], /) -> array: - If ``x1_i`` and ``x2_i`` have the same mathematical sign and are both nonzero finite numbers, the result has a positive mathematical sign. - If ``x1_i`` and ``x2_i`` have different mathematical signs and are both nonzero finite numbers, the result has a negative mathematical sign. - In the remaining cases, where neither ``-infinity``, ``+0``, ``-0``, nor ``NaN`` is involved, the quotient must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported rounding mode. If the magnitude is too large to represent, the operation overflows and the result is an ``infinity`` of appropriate mathematical sign. If the magnitude is too small to represent, the operation underflows and the result is a zero of appropriate mathematical sign. + + Parameters + ---------- + self: array + array instance. Should have a numeric data type. + other: Union[int, float, array] + other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type. + + Returns + ------- + out: array + an array containing the element-wise results. The returned array should have a floating-point data type determined by :ref:`type-promotion`. + + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-divide`. """ def __xor__(self: array, other: Union[int, bool, array], /) -> array: @@ -922,9 +960,9 @@ def __xor__(self: array, other: Union[int, bool, array], /) -> array: out: array an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. - Notes - ----- - - Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_xor`. + + .. note:: + Element-wise results must equal the results returned by the equivalent element-wise function :ref:`function-bitwise_xor`. """ def to_device(self: array, device: Device, /, *, stream: Optional[Union[int, Any]] = None) -> array: @@ -945,7 +983,7 @@ def to_device(self: array, device: Device, /, *, stream: Optional[Union[int, Any out: array an array with the same data and data type as ``self`` and located on the specified ``device``. - Notes - ----- - - If ``stream`` is given, the copy operation should be enqueued on the provided ``stream``; otherwise, the copy operation should be enqueued on the default stream/queue. Whether the copy is performed synchronously or asynchronously is implementation-dependent. Accordingly, if synchronization is required to guarantee data safety, this must be clearly explained in a conforming library's documentation. + + .. note:: + If ``stream`` is given, the copy operation should be enqueued on the provided ``stream``; otherwise, the copy operation should be enqueued on the default stream/queue. Whether the copy is performed synchronously or asynchronously is implementation-dependent. Accordingly, if synchronization is required to guarantee data safety, this must be clearly explained in a conforming library's documentation. """