|
| 1 | +.. _array-object: |
| 2 | + |
| 3 | +Array object |
| 4 | +============ |
| 5 | + |
| 6 | + Array API specification for array object attributes and methods. |
| 7 | + |
| 8 | +A conforming implementation of the array API standard must provide and support an array object having the following attributes and methods. |
| 9 | + |
| 10 | +Furthermore, a conforming implementation of the array API standard must support, at minimum, array objects of rank (i.e., number of dimensions) ``0``, ``1``, ``2``, ``3``, and ``4`` and must explicitly document their maximum supported rank ``N``. |
| 11 | + |
| 12 | +.. note:: |
| 13 | + Conforming implementations must support zero-dimensional arrays. |
| 14 | + |
| 15 | + 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. |
| 16 | + |
| 17 | + *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.* |
| 18 | + |
| 19 | +------------------------------------------------- |
| 20 | + |
| 21 | +.. _operators: |
| 22 | + |
| 23 | +Operators |
| 24 | +--------- |
| 25 | + |
| 26 | +A conforming implementation of the array API standard must provide and support an array object supporting the following Python operators. |
| 27 | + |
| 28 | +Arithmetic Operators |
| 29 | +~~~~~~~~~~~~~~~~~~~~ |
| 30 | + |
| 31 | +A conforming implementation of the array API standard must provide and support an array object supporting the following Python arithmetic operators. |
| 32 | + |
| 33 | +- ``+x``: :meth:`.array.__pos__` |
| 34 | + |
| 35 | + - `operator.pos(x) <https://docs.python.org/3/library/operator.html#operator.pos>`_ |
| 36 | + - `operator.__pos__(x) <https://docs.python.org/3/library/operator.html#operator.__pos__>`_ |
| 37 | + |
| 38 | +- `-x`: :meth:`.array.__neg__` |
| 39 | + |
| 40 | + - `operator.neg(x) <https://docs.python.org/3/library/operator.html#operator.neg>`_ |
| 41 | + - `operator.__neg__(x) <https://docs.python.org/3/library/operator.html#operator.__neg__>`_ |
| 42 | + |
| 43 | +- `x1 + x2`: :meth:`.array.__add__` |
| 44 | + |
| 45 | + - `operator.add(x1, x2) <https://docs.python.org/3/library/operator.html#operator.add>`_ |
| 46 | + - `operator.__add__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__add__>`_ |
| 47 | + |
| 48 | +- `x1 - x2`: :meth:`.array.__sub__` |
| 49 | + |
| 50 | + - `operator.sub(x1, x2) <https://docs.python.org/3/library/operator.html#operator.sub>`_ |
| 51 | + - `operator.__sub__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__sub__>`_ |
| 52 | + |
| 53 | +- `x1 * x2`: :meth:`.array.__mul__` |
| 54 | + |
| 55 | + - `operator.mul(x1, x2) <https://docs.python.org/3/library/operator.html#operator.mul>`_ |
| 56 | + - `operator.__mul__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__mul__>`_ |
| 57 | + |
| 58 | +- `x1 / x2`: :meth:`.array.__truediv__` |
| 59 | + |
| 60 | + - `operator.truediv(x1,x2) <https://docs.python.org/3/library/operator.html#operator.truediv>`_ |
| 61 | + - `operator.__truediv__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__truediv__>`_ |
| 62 | + |
| 63 | +- `x1 // x2`: :meth:`.array.__floordiv__` |
| 64 | + |
| 65 | + - `operator.floordiv(x1, x2) <https://docs.python.org/3/library/operator.html#operator.floordiv>`_ |
| 66 | + - `operator.__floordiv__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__floordiv__>`_ |
| 67 | + |
| 68 | +- `x1 % x2`: :meth:`.array.__mod__` |
| 69 | + |
| 70 | + - `operator.mod(x1, x2) <https://docs.python.org/3/library/operator.html#operator.mod>`_ |
| 71 | + - `operator.__mod__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__mod__>`_ |
| 72 | + |
| 73 | +- `x1 ** x2`: :meth:`.array.__pow__` |
| 74 | + |
| 75 | + - `operator.pow(x1, x2) <https://docs.python.org/3/library/operator.html#operator.pow>`_ |
| 76 | + - `operator.__pow__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__pow__>`_ |
| 77 | + |
| 78 | +Arithmetic operators should be defined for arrays having real-valued data types. |
| 79 | + |
| 80 | +Array Operators |
| 81 | +~~~~~~~~~~~~~~~ |
| 82 | + |
| 83 | +A conforming implementation of the array API standard must provide and support an array object supporting the following Python array operators. |
| 84 | + |
| 85 | +- `x1 @ x2`: :meth:`.array.__matmul__` |
| 86 | + |
| 87 | + - `operator.matmul(x1, x2) <https://docs.python.org/3/library/operator.html#operator.matmul>`_ |
| 88 | + - `operator.__matmul__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__matmul__>`_ |
| 89 | + |
| 90 | +The matmul ``@`` operator should be defined for arrays having numeric data types. |
| 91 | + |
| 92 | +Bitwise Operators |
| 93 | +~~~~~~~~~~~~~~~~~ |
| 94 | + |
| 95 | +A conforming implementation of the array API standard must provide and support an array object supporting the following Python bitwise operators. |
| 96 | + |
| 97 | +- `~x`: :meth:`.array.__invert__` |
| 98 | + |
| 99 | + - `operator.inv(x) <https://docs.python.org/3/library/operator.html#operator.inv>`_ |
| 100 | + - `operator.invert(x) <https://docs.python.org/3/library/operator.html#operator.invert>`_ |
| 101 | + - `operator.__inv__(x) <https://docs.python.org/3/library/operator.html#operator.__inv__>`_ |
| 102 | + - `operator.__invert__(x) <https://docs.python.org/3/library/operator.html#operator.__invert__>`_ |
| 103 | + |
| 104 | +- `x1 & x2`: :meth:`.array.__and__` |
| 105 | + |
| 106 | + - `operator.and(x1, x2) <https://docs.python.org/3/library/operator.html#operator.and>`_ |
| 107 | + - `operator.__and__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__and__>`_ |
| 108 | + |
| 109 | +- `x1 | x2`: :meth:`.array.__or__` |
| 110 | + |
| 111 | + - `operator.or(x1, x2) <https://docs.python.org/3/library/operator.html#operator.or>`_ |
| 112 | + - `operator.__or__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__or__>`_ |
| 113 | + |
| 114 | +- `x1 ^ x2`: :meth:`.array.__xor__` |
| 115 | + |
| 116 | + - `operator.xor(x1, x2) <https://docs.python.org/3/library/operator.html#operator.xor>`_ |
| 117 | + - `operator.__xor__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__xor__>`_ |
| 118 | + |
| 119 | +- `x1 << x2`: :meth:`.array.__lshift__` |
| 120 | + |
| 121 | + - `operator.lshift(x1, x2) <https://docs.python.org/3/library/operator.html#operator.lshift>`_ |
| 122 | + - `operator.__lshift__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__lshift__>`_ |
| 123 | + |
| 124 | +- `x1 >> x2`: :meth:`.array.__rshift__` |
| 125 | + |
| 126 | + - `operator.rshift(x1, x2) <https://docs.python.org/3/library/operator.html#operator.rshift>`_ |
| 127 | + - `operator.__rshift__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__rshift__>`_ |
| 128 | + |
| 129 | +Bitwise operators should be defined for arrays having integer and boolean data types. |
| 130 | + |
| 131 | +Comparison Operators |
| 132 | +~~~~~~~~~~~~~~~~~~~~ |
| 133 | + |
| 134 | +A conforming implementation of the array API standard must provide and support an array object supporting the following Python comparison operators. |
| 135 | + |
| 136 | +- `x1 < x2`: :meth:`.array.__lt__` |
| 137 | + |
| 138 | + - `operator.lt(x1, x2) <https://docs.python.org/3/library/operator.html#operator.lt>`_ |
| 139 | + - `operator.__lt__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__lt__>`_ |
| 140 | + |
| 141 | +- `x1 <= x2`: :meth:`.array.__le__` |
| 142 | + |
| 143 | + - `operator.le(x1, x2) <https://docs.python.org/3/library/operator.html#operator.le>`_ |
| 144 | + - `operator.__le__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__le__>`_ |
| 145 | + |
| 146 | +- `x1 > x2`: :meth:`.array.__gt__` |
| 147 | + |
| 148 | + - `operator.gt(x1, x2) <https://docs.python.org/3/library/operator.html#operator.gt>`_ |
| 149 | + - `operator.__gt__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__gt__>`_ |
| 150 | + |
| 151 | +- `x1 >= x2`: :meth:`.array.__ge__` |
| 152 | + |
| 153 | + - `operator.ge(x1, x2) <https://docs.python.org/3/library/operator.html#operator.ge>`_ |
| 154 | + - `operator.__ge__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__ge__>`_ |
| 155 | + |
| 156 | +- `x1 == x2`: :meth:`.array.__eq__` |
| 157 | + |
| 158 | + - `operator.eq(x1, x2) <https://docs.python.org/3/library/operator.html#operator.eq>`_ |
| 159 | + - `operator.__eq__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__eq__>`_ |
| 160 | + |
| 161 | +- `x1 != x2`: :meth:`.array.__ne__` |
| 162 | + |
| 163 | + - `operator.ne(x1, x2) <https://docs.python.org/3/library/operator.html#operator.ne>`_ |
| 164 | + - `operator.__ne__(x1, x2) <https://docs.python.org/3/library/operator.html#operator.__ne__>`_ |
| 165 | + |
| 166 | +:meth:`.array.__lt__`, :meth:`.array.__le__`, :meth:`.array.__gt__`, :meth:`.array.__ge__` are only defined for arrays having real-valued data types. Other comparison operators should be defined for arrays having any data type. |
| 167 | +For backward compatibility, conforming implementations may support complex numbers; however, inequality comparison of complex numbers is unspecified and thus implementation-dependent (see :ref:`complex-number-ordering`). |
| 168 | + |
| 169 | +In-place Operators |
| 170 | +~~~~~~~~~~~~~~~~~~ |
| 171 | + |
| 172 | +.. note:: |
| 173 | + In-place operations must be supported as discussed in :ref:`copyview-mutability`. |
| 174 | + |
| 175 | +A conforming implementation of the array API standard must provide and support an array object supporting the following "in-place" Python operators. |
| 176 | + |
| 177 | +.. note:: |
| 178 | + This specification refers to the following operators as "in-place" as that is what these operators are called in `Python <https://docs.python.org/3/library/operator.html#in-place-operators>`. However, conforming array libraries which do not support array mutation may choose to not explicitly implement in-place Python operators. When a library does not implement a method corresponding to an in-place Python operator, Python falls back to the equivalent method for the corresponding binary arithmetic operation. |
| 179 | + |
| 180 | +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`. |
| 181 | + |
| 182 | +Let ``x1 += x2`` be a representative in-place operation. If, after applying type promotion (see :ref:`type-promotion`) to in-place operands ``x1`` and ``x2``, the resulting data type is equal to the data type of the array on the left-hand side of the operation (i.e., ``x1``), then an in-place operation must have the same behavior (including special cases) as the respective binary (i.e., two operand, non-assignment) operation. In this case, for the in-place addition ``x1 += x2``, the modified array ``x1`` must always equal the result of the equivalent binary arithmetic operation ``x1[...] = x1 + x2``. |
| 183 | + |
| 184 | +If, however, after applying type promotion (see :ref:`type-promotion`) to in-place operands, the resulting data type is not equal to the data type of the array on the left-hand side of the operation, then a conforming implementation may return results which differ from the respective binary operation due to casting behavior and selection of the operation's intermediate precision. The choice of casting behavior and intermediate precision is unspecified and thus implementation-defined. |
| 185 | + |
| 186 | +.. note:: |
| 187 | + Let ``x1`` be the operand on the left-hand side and ``x2`` be the operand on the right-hand side of an in-place operation. Consumers of the array API standard are advised of the following considerations when using in-place operations: |
| 188 | + |
| 189 | + 1. In-place operations do not guarantee in-place mutation. A conforming library may or may not support in-place mutation. |
| 190 | + 2. If, after applying broadcasting (see :ref:`broadcasting`) to in-place operands, the resulting shape is not equal to the shape of ``x1``, in-place operators may raise an exception. |
| 191 | + 3. If, after applying type promotion (see :ref:`type-promotion`) to in-place operands, the resulting data type is not equal to the data type of ``x1``, the resulting data type may not equal the data type of ``x1`` and the operation's intermediate precision may be that of ``x1``, even if the promoted data type between ``x1`` and ``x2`` would have higher precision. |
| 192 | + |
| 193 | + In general, for in-place operations, consumers of the array API standard are advised to ensure operands have the same data type and broadcast to the shape of the operand on the left-hand side of the operation in order to maximize portability. |
| 194 | + |
| 195 | +Arithmetic Operators |
| 196 | +"""""""""""""""""""" |
| 197 | + |
| 198 | +- ``+=``. May be implemented via ``__iadd__``. |
| 199 | +- ``-=``. May be implemented via ``__isub__``. |
| 200 | +- ``*=``. May be implemented via ``__imul__``. |
| 201 | +- ``/=``. May be implemented via ``__itruediv__``. |
| 202 | +- ``//=``. May be implemented via ``__ifloordiv__``. |
| 203 | +- ``**=``. May be implemented via ``__ipow__``. |
| 204 | +- ``%=``. May be implemented via ``__imod__``. |
| 205 | + |
| 206 | +Array Operators |
| 207 | +""""""""""""""" |
| 208 | + |
| 209 | +- ``@=``. May be implemented via ``__imatmul__``. |
| 210 | + |
| 211 | +Bitwise Operators |
| 212 | +""""""""""""""""" |
| 213 | + |
| 214 | +- ``&=``. May be implemented via ``__iand__``. |
| 215 | +- ``|=``. May be implemented via ``__ior__``. |
| 216 | +- ``^=``. May be implemented via ``__ixor__``. |
| 217 | +- ``<<=``. May be implemented via ``__ilshift__``. |
| 218 | +- ``>>=``. May be implemented via ``__irshift__``. |
| 219 | + |
| 220 | +Reflected Operators |
| 221 | +~~~~~~~~~~~~~~~~~~~ |
| 222 | + |
| 223 | +A conforming implementation of the array API standard must provide and support an array object supporting the following reflected operators. |
| 224 | + |
| 225 | +The results of applying reflected operators must match their non-reflected equivalents. |
| 226 | + |
| 227 | +.. note:: |
| 228 | + All operators for which ``array <op> scalar`` is implemented must have an equivalent reflected operator implementation. |
| 229 | + |
| 230 | +Arithmetic Operators |
| 231 | +"""""""""""""""""""" |
| 232 | + |
| 233 | +- ``__radd__`` |
| 234 | +- ``__rsub__`` |
| 235 | +- ``__rmul__`` |
| 236 | +- ``__rtruediv__`` |
| 237 | +- ``__rfloordiv__`` |
| 238 | +- ``__rpow__`` |
| 239 | +- ``__rmod__`` |
| 240 | + |
| 241 | +Array Operators |
| 242 | +""""""""""""""" |
| 243 | + |
| 244 | +- ``__rmatmul__`` |
| 245 | + |
| 246 | +Bitwise Operators |
| 247 | +""""""""""""""""" |
| 248 | + |
| 249 | +- ``__rand__`` |
| 250 | +- ``__ror__`` |
| 251 | +- ``__rxor__`` |
| 252 | +- ``__rlshift__`` |
| 253 | +- ``__rrshift__`` |
| 254 | + |
| 255 | +------------------------------------------------- |
| 256 | + |
| 257 | +.. currentmodule:: array_api |
| 258 | + |
| 259 | +Attributes |
| 260 | +---------- |
| 261 | +.. |
| 262 | + NOTE: please keep the attributes in alphabetical order |
| 263 | +
|
| 264 | + |
| 265 | +.. autosummary:: |
| 266 | + :toctree: generated |
| 267 | + :template: property.rst |
| 268 | + |
| 269 | + array.dtype |
| 270 | + array.device |
| 271 | + array.mT |
| 272 | + array.ndim |
| 273 | + array.shape |
| 274 | + array.size |
| 275 | + array.T |
| 276 | + |
| 277 | +------------------------------------------------- |
| 278 | + |
| 279 | +Methods |
| 280 | +------- |
| 281 | +.. |
| 282 | + NOTE: please keep the methods in alphabetical order |
| 283 | +
|
| 284 | + |
| 285 | +.. autosummary:: |
| 286 | + :toctree: generated |
| 287 | + :template: property.rst |
| 288 | + |
| 289 | + array.__abs__ |
| 290 | + array.__add__ |
| 291 | + array.__and__ |
| 292 | + array.__array_namespace__ |
| 293 | + array.__bool__ |
| 294 | + array.__complex__ |
| 295 | + array.__dlpack__ |
| 296 | + array.__dlpack_device__ |
| 297 | + array.__eq__ |
| 298 | + array.__float__ |
| 299 | + array.__floordiv__ |
| 300 | + array.__ge__ |
| 301 | + array.__getitem__ |
| 302 | + array.__gt__ |
| 303 | + array.__index__ |
| 304 | + array.__int__ |
| 305 | + array.__invert__ |
| 306 | + array.__le__ |
| 307 | + array.__lshift__ |
| 308 | + array.__lt__ |
| 309 | + array.__matmul__ |
| 310 | + array.__mod__ |
| 311 | + array.__mul__ |
| 312 | + array.__ne__ |
| 313 | + array.__neg__ |
| 314 | + array.__or__ |
| 315 | + array.__pos__ |
| 316 | + array.__pow__ |
| 317 | + array.__rshift__ |
| 318 | + array.__setitem__ |
| 319 | + array.__sub__ |
| 320 | + array.__truediv__ |
| 321 | + array.__xor__ |
| 322 | + array.to_device |
0 commit comments