Skip to content

Add complex floating-point data types #418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions spec/API_specification/array_object.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ A conforming implementation of the array API standard must provide and support a
- `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.
Arithmetic operators should be defined for arrays having real-valued data types.

Array Operators
~~~~~~~~~~~~~~~
Expand All @@ -94,7 +94,7 @@ A conforming implementation of the array API standard must provide and support a
- `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.
The matmul ``@`` operator should be defined for arrays having real-valued data types.

Bitwise Operators
~~~~~~~~~~~~~~~~~
Expand Down
44 changes: 30 additions & 14 deletions spec/API_specification/data_types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,20 @@ float64

IEEE 754 double-precision (64-bit) binary floating-point number (see IEEE 754-2019).

.. note::
IEEE 754-2019 requires support for subnormal (a.k.a., denormal) numbers, which are useful for supporting gradual underflow. However, hardware support for subnormal numbers is not universal, and many platforms (e.g., accelerators) and compilers support toggling denormals-are-zero (DAZ) and/or flush-to-zero (FTZ) behavior to increase performance and to guard against timing attacks.
complex64
---------

Accordingly, subnormal behavior is left unspecified and, thus, implementation-defined. Conforming implementations may vary in their support for subnormal numbers.
Single-precision (64-bit) complex floating-point number whose real and imaginary components must be IEEE 754 single-precision (32-bit) binary floating-point numbers (see IEEE 754-2019).

.. admonition:: Future extension
:class: admonition tip
complex128
----------

``complex64`` and ``complex128`` data types are expected to be included in the next version of this standard and to have the following casting rules (will be added to :ref:`type-promotion`):
Double-precision (128-bit) complex floating-point number whose real and imaginary components must be IEEE 754 double-precision (64-bit) binary floating-point numbers (see IEEE 754-2019).

.. image:: /_static/images/dtype_promotion_complex.png
.. note::
IEEE 754-2019 requires support for subnormal (a.k.a., denormal) numbers, which are useful for supporting gradual underflow. However, hardware support for subnormal numbers is not universal, and many platforms (e.g., accelerators) and compilers support toggling denormals-are-zero (DAZ) and/or flush-to-zero (FTZ) behavior to increase performance and to guard against timing attacks.

See `array-api/issues/102 <https://github.com/data-apis/array-api/issues/102>`_ for more details
Accordingly, subnormal behavior is left unspecified and, thus, implementation-defined. Conforming implementations may vary in their support for subnormal numbers.

.. note::
A conforming implementation of the array API standard may provide and support additional data types beyond those described in this specification.
Expand Down Expand Up @@ -116,11 +117,14 @@ Default Data Types

A conforming implementation of the array API standard must define the following default data types.

- a default floating-point data type (either ``float32`` or ``float64``).
- a default real-valued floating-point data type (either ``float32`` or ``float64``).
- a default complex floating-point data type (either ``complex64`` or ``complex128``).
- a default integer data type (either ``int32`` or ``int64``).
- a default array index data type (either ``int32`` or ``int64``).

The default floating-point data type must be the same across platforms.
The default real-valued floating-point and complex floating-point data types must be the same across platforms.

The default complex floating-point point data type should match the default real-valued floating-point data type. For example, if the default real-valued floating-point data type is ``float32``, the default complex floating-point data type must be ``complex64``. If the default real-valued floating-point data type is ``float64``, the default complex floating-point data type must be ``complex128``.

The default integer data type should be the same across platforms, but the default may vary depending on whether Python is 32-bit or 64-bit.

Expand All @@ -139,14 +143,16 @@ For the purpose of organizing functions within this specification, the following
.. note::
Conforming libraries are not required to organize data types according to these categories. These categories are only intended for use within this specification.

.. note::
Future versions of the specification will include additional categories for complex data types.


Numeric Data Types
~~~~~~~~~~~~~~~~~~

``int8``, ``int16``, ``int32``, ``int64``, ``uint8``, ``uint16``, ``uint32``, ``uint64``, ``float32``, and ``float64`` (i.e., all data types except for ``bool``).
``int8``, ``int16``, ``int32``, ``int64``, ``uint8``, ``uint16``, ``uint32``, ``uint64``, ``float32``, ``float64``, ``complex64``, and ``complex128``.

Real-valued Data Types
~~~~~~~~~~~~~~~~~~~~~~

``int8``, ``int16``, ``int32``, ``int64``, ``uint8``, ``uint16``, ``uint32``, ``uint64``, ``float32``, and ``float64``.

Integer Data Types
~~~~~~~~~~~~~~~~~~
Expand All @@ -156,8 +162,18 @@ Integer Data Types
Floating-point Data Types
~~~~~~~~~~~~~~~~~~~~~~~~~

``float32``, ``float64``, ``complex64``, and ``complex128``.

Real-valued Floating-point Data Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``float32`` and ``float64``.

Complex Floating-point Data Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``complex64`` and ``complex128``.

Boolean Data Types
~~~~~~~~~~~~~~~~~~

Expand Down
64 changes: 32 additions & 32 deletions spec/API_specification/signatures/array_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def __abs__(self: array, /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.

Returns
-------
Expand Down Expand Up @@ -170,9 +170,9 @@ def __add__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance (augend array). Should have a numeric data type.
array instance (augend array). Should have a real-valued data type.
other: Union[int, float, array]
addend array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type.
addend array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued data type.

Returns
-------
Expand Down Expand Up @@ -346,7 +346,7 @@ def __float__(self: array, /) -> float:
Parameters
----------
self: array
zero-dimensional array instance. Must have a floating-point data type.
zero-dimensional array instance. Must have a real-valued floating-point data type.

Returns
-------
Expand Down Expand Up @@ -400,9 +400,9 @@ def __floordiv__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.
other: Union[int, float, array]
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type.
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued data type.

Returns
-------
Expand All @@ -421,9 +421,9 @@ def __ge__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.
other: Union[int, float, array]
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type.
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued data type.

Returns
-------
Expand Down Expand Up @@ -459,9 +459,9 @@ def __gt__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.
other: Union[int, float, array]
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type.
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued data type.

Returns
-------
Expand Down Expand Up @@ -532,9 +532,9 @@ def __le__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.
other: Union[int, float, array]
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type.
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued data type.

Returns
-------
Expand Down Expand Up @@ -574,9 +574,9 @@ def __lt__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.
other: Union[int, float, array]
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type.
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued data type.

Returns
-------
Expand All @@ -598,9 +598,9 @@ def __matmul__(self: array, other: array, /) -> array:
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.
array instance. Should have a real-valued 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.
other array. Should have a real-valued 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
-------
Expand Down Expand Up @@ -665,14 +665,14 @@ def __mod__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.
other: Union[int, float, array]
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type.
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued 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`.
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 real-valued floating-point data type determined by :ref:`type-promotion`.


.. note::
Expand Down Expand Up @@ -704,9 +704,9 @@ def __mul__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.
other: Union[int, float, array]
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type.
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued data type.

Returns
-------
Expand Down Expand Up @@ -749,7 +749,7 @@ def __neg__(self: array, /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.

Returns
-------
Expand Down Expand Up @@ -789,7 +789,7 @@ def __pos__(self: array, /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.

Returns
-------
Expand All @@ -808,7 +808,7 @@ def __pow__(self: array, other: Union[int, float, array], /) -> array:
.. 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.
If ``self`` has an integer data type and ``other`` has a real-valued 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**

Expand Down Expand Up @@ -842,9 +842,9 @@ def __pow__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance whose elements correspond to the exponentiation base. Should have a numeric data type.
array instance whose elements correspond to the exponentiation base. Should have a real-valued 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.
other array whose elements correspond to the exponentiation exponent. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued data type.

Returns
-------
Expand Down Expand Up @@ -907,9 +907,9 @@ def __sub__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance (minuend array). Should have a numeric data type.
array instance (minuend array). Should have a real-valued data type.
other: Union[int, float, array]
subtrahend array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type.
subtrahend array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued data type.

Returns
-------
Expand All @@ -928,7 +928,7 @@ def __truediv__(self: array, other: Union[int, float, array], /) -> array:
.. 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.
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 real-valued floating-point data type.

**Special cases**

Expand Down Expand Up @@ -960,14 +960,14 @@ def __truediv__(self: array, other: Union[int, float, array], /) -> array:
Parameters
----------
self: array
array instance. Should have a numeric data type.
array instance. Should have a real-valued data type.
other: Union[int, float, array]
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a numeric data type.
other array. Must be compatible with ``self`` (see :ref:`broadcasting`). Should have a real-valued 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`.
an array containing the element-wise results. The returned array should have a real-valued floating-point data type determined by :ref:`type-promotion`.


.. note::
Expand Down
Loading