diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 8fd251e32..64a94ebe7 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,2 +1,7 @@ # Migrate code style to Black 162034b12711dad54589c5dc9e75942695a7957f + +# Move special cases to notes sections +816fba3b75c38cbb1bb6fe5b1342adc5eab694f3 +0a2fa71a32b924cc92718db29910a6cbbc5e9341 +931144e7d7d5c8b23393aa730ef28962a35b113b \ No newline at end of file diff --git a/spec/API_specification/array_api/array_object.py b/spec/API_specification/array_api/array_object.py index 7c92800d0..89e5ee1c3 100644 --- a/spec/API_specification/array_api/array_object.py +++ b/spec/API_specification/array_api/array_object.py @@ -126,32 +126,6 @@ def __abs__(self: array, /) -> array: .. note:: For signed integer data types, the absolute value of the minimum representable integer is implementation-dependent. - **Special cases** - - Let ``self`` equal ``x``. - - For real-valued floating-point operands, - - - 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``. - - For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - - - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is any value (including ``NaN``), the result is ``+infinity``. - - If ``a`` is any value (including ``NaN``) and ``b`` is either ``+infinity`` or ``-infinity``, the result is ``+infinity``. - - If ``a`` is either ``+0`` or ``-0``, the result is equal to ``abs(b)``. - - If ``b`` is either ``+0`` or ``-0``, the result is equal to ``abs(a)``. - - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN``. - - If ``a`` is a finite number and ``b`` is ``NaN``, the result is ``NaN``. - - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN``. - - .. note:: - For complex floating-point operands, conforming implementations should take care to avoid undue overflow or underflow during intermediate stages of computation. - - .. - TODO: once ``hypot`` is added to the specification, remove the special cases for complex floating-point operands and the note concerning guarding against undue overflow/underflow, and state that special cases must be handled as if implemented as ``hypot(real(x), imag(x))``. - Parameters ---------- self: array @@ -164,59 +138,13 @@ def __abs__(self: array, /) -> array: .. note:: - Element-wise results must equal the results returned by the equivalent element-wise function :func:`~array_api.abs`. + Element-wise results, including special cases, must equal the results returned by the equivalent element-wise function :func:`~array_api.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** - - Let ``self`` equal ``x1`` and ``other`` equal ``x2``. - - For real-valued floating-point operands, - - - 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. - - For complex floating-point operands, addition is defined according to the following table. For real components ``a`` and ``c`` and imaginary components ``b`` and ``d``, - - +------------+------------+------------+----------------+ - | | c | dj | c + dj | - +============+============+============+================+ - | **a** | a + c | a + dj | (a+c) + dj | - +------------+------------+------------+----------------+ - | **bj** | c + bj | (b+d)j | c + (b+d)j | - +------------+------------+------------+----------------+ - | **a + bj** | (a+c) + bj | a + (b+d)j | (a+c) + (b+d)j | - +------------+------------+------------+----------------+ - - For complex floating-point operands, real-valued floating-point special cases must independently apply to the real and imaginary component operations involving real numbers as described in the above table. For example, let ``a = real(x1_i)``, ``b = imag(x1_i)``, ``c = real(x2_i)``, ``d = imag(x2_i)``, and - - - If ``a`` is ``-0`` and ``c`` is ``-0``, the real component of the result is ``-0``. - - Similarly, if ``b`` is ``+0`` and ``d`` is ``-0``, the imaginary component of the result is ``+0``. - - Hence, if ``z1 = a + bj = -0 + 0j`` and ``z2 = c + dj = -0 - 0j``, the result of ``z1 + z2`` is ``-0 + 0j``. - Parameters ---------- self: array @@ -231,7 +159,7 @@ def __add__(self: array, other: Union[int, float, array], /) -> array: .. note:: - Element-wise results must equal the results returned by the equivalent element-wise function :func:`~array_api.add`. + Element-wise results, including special cases, must equal the results returned by the equivalent element-wise function :func:`~array_api.add`. """ def __and__(self: array, other: Union[int, bool, array], /) -> array: @@ -278,6 +206,19 @@ def __bool__(self: array, /) -> bool: """ Converts a zero-dimensional array to a Python ``bool`` object. + Parameters + ---------- + self: array + zero-dimensional array instance. + + Returns + ------- + out: bool + a Python ``bool`` object representing the single element of the array. + + Notes + ----- + **Special cases** For real-valued floating-point operands, @@ -287,6 +228,11 @@ def __bool__(self: array, /) -> bool: - If ``self`` is either ``+0`` or ``-0``, the result is ``False``. For complex floating-point operands, special cases must be handled as if the operation is implemented as the logical AND of ``bool(real(self))`` and ``bool(imag(self))``. + """ + + def __complex__(self: array, /) -> complex: + """ + Converts a zero-dimensional array to a Python ``complex`` object. Parameters ---------- @@ -295,13 +241,11 @@ def __bool__(self: array, /) -> bool: Returns ------- - out: bool - a Python ``bool`` object representing the single element of the array. - """ + out: complex + a Python ``complex`` object representing the single element of the array instance. - def __complex__(self: array, /) -> complex: - """ - Converts a zero-dimensional array to a Python ``complex`` object. + Notes + ----- **Special cases** @@ -316,16 +260,6 @@ def __complex__(self: array, /) -> complex: - If ``self`` is ``+infinity``, the result is ``+infinity + 0j``. - If ``self`` is ``-infinity``, the result is ``-infinity + 0j``. - If ``self`` is a finite number, the result is ``self + 0j``. - - Parameters - ---------- - self: array - zero-dimensional array instance. - - Returns - ------- - out: complex - a Python ``complex`` object representing the single element of the array instance. """ def __dlpack__( @@ -424,28 +358,6 @@ def __eq__(self: array, other: Union[int, float, bool, array], /) -> array: r""" Computes the truth value of ``self_i == other_i`` for each element of an array instance with the respective element of the array ``other``. - **Special Cases** - - Let ``self`` equal ``x1`` and ``other`` equal ``x2``. - - For real-valued floating-point operands, - - - If ``x1_i`` is ``NaN`` or ``x2_i`` is ``NaN``, the result is ``False``. - - If ``x1_i`` is ``+infinity`` and ``x2_i`` is ``+infinity``, the result is ``True``. - - If ``x1_i`` is ``-infinity`` and ``x2_i`` is ``-infinity``, the result is ``True``. - - If ``x1_i`` is ``-0`` and ``x2_i`` is either ``+0`` or ``-0``, the result is ``True``. - - If ``x1_i`` is ``+0`` and ``x2_i`` is either ``+0`` or ``-0``, the result is ``True``. - - If ``x1_i`` is a finite number, ``x2_i`` is a finite number, and ``x1_i`` equals ``x2_i``, the result is ``True``. - - In the remaining cases, the result is ``False``. - - For complex floating-point operands, let ``a = real(x1_i)``, ``b = imag(x1_i)``, ``c = real(x2_i)``, ``d = imag(x2_i)``, and - - - If ``a``, ``b``, ``c``, or ``d`` is ``NaN``, the result is ``False``. - - In the remaining cases, the result is the logical AND of the equality comparison between the real values ``a`` and ``c`` (real components) and between the real values ``b`` and ``d`` (imaginary components), as described above for real-valued floating-point operands (i.e., ``a == c AND b == d``). - - .. note:: - For discussion of complex number equality, see :ref:`complex-numbers`. - Parameters ---------- self: array @@ -460,7 +372,7 @@ def __eq__(self: array, other: Union[int, float, bool, array], /) -> array: .. note:: - Element-wise results must equal the results returned by the equivalent element-wise function :func:`~array_api.equal`. + Element-wise results, including special cases, must equal the results returned by the equivalent element-wise function :func:`~array_api.equal`. """ def __float__(self: array, /) -> float: @@ -470,13 +382,6 @@ def __float__(self: array, /) -> float: .. note:: Casting integer values outside the representable bounds of Python's float type is not specified and is implementation-dependent. - **Special cases** - - For boolean operands, - - - If ``self`` is ``True``, the result is ``1``. - - If ``self`` is ``False``, the result is ``0``. - Parameters ---------- self: array @@ -486,6 +391,16 @@ def __float__(self: array, /) -> float: ------- out: float a Python ``float`` object representing the single element of the array instance. + + Notes + ----- + + **Special cases** + + For boolean operands, + + - If ``self`` is ``True``, the result is ``1``. + - If ``self`` is ``False``, the result is ``0``. """ def __floordiv__(self: array, other: Union[int, float, array], /) -> array: @@ -495,42 +410,6 @@ def __floordiv__(self: array, other: Union[int, float, array], /) -> array: .. 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 `_ 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. - - 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 @@ -545,7 +424,7 @@ def __floordiv__(self: array, other: Union[int, float, array], /) -> array: .. note:: - Element-wise results must equal the results returned by the equivalent element-wise function :func:`~array_api.floor_divide`. + Element-wise results, including special cases, must equal the results returned by the equivalent element-wise function :func:`~array_api.floor_divide`. """ def __ge__(self: array, other: Union[int, float, array], /) -> array: @@ -641,6 +520,19 @@ def __int__(self: array, /) -> int: """ Converts a zero-dimensional array to a Python ``int`` object. + Parameters + ---------- + self: array + zero-dimensional array instance. Should have a real-valued or boolean data type. If ``self`` has a complex floating-point data type, the function must raise a ``TypeError``. + + Returns + ------- + out: int + a Python ``int`` object representing the single element of the array instance. + + Notes + ----- + **Special cases** For boolean operands, @@ -653,17 +545,6 @@ def __int__(self: array, /) -> int: - If ``self`` is a finite number, the result is the integer part of ``self``. - If ``self`` is ``-0``, the result is ``0``. - Parameters - ---------- - self: array - zero-dimensional array instance. Should have a real-valued or boolean data type. If ``self`` has a complex floating-point data type, the function must raise a ``TypeError``. - - Returns - ------- - out: int - a Python ``int`` object representing the single element of the array instance. - - **Raises** For floating-point operands, @@ -810,34 +691,6 @@ def __mod__(self: array, other: Union[int, float, array], /) -> array: .. 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:: - In general, this method is **not** recommended for floating-point operands as semantics do not follow IEEE 754. That this method is specified to accept floating-point operands is primarily for reasons of backward compatibility. - - 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 ``NaN``. - - If ``x1_i`` is greater than ``0`` and ``x2_i`` is ``-0``, the result is ``NaN``. - - If ``x1_i`` is less than ``0`` and ``x2_i`` is ``+0``, the result is ``NaN``. - - If ``x1_i`` is less than ``0`` and ``x2_i`` is ``-0``, the result is ``NaN``. - - If ``x1_i`` is ``+infinity`` and ``x2_i`` is a positive (i.e., greater than ``0``) finite number, the result is ``NaN``. - - If ``x1_i`` is ``+infinity`` and ``x2_i`` is a negative (i.e., less than ``0``) finite number, the result is ``NaN``. - - If ``x1_i`` is ``-infinity`` and ``x2_i`` is a positive (i.e., greater than ``0``) finite number, the result is ``NaN``. - - If ``x1_i`` is ``-infinity`` and ``x2_i`` is a negative (i.e., less than ``0``) finite number, the result is ``NaN``. - - If ``x1_i`` is a positive (i.e., greater than ``0``) finite number and ``x2_i`` is ``+infinity``, the result is ``x1_i``. (**note**: this result matches Python behavior.) - - If ``x1_i`` is a positive (i.e., greater than ``0``) finite number and ``x2_i`` is ``-infinity``, the result is ``x2_i``. (**note**: this result matches Python behavior.) - - If ``x1_i`` is a negative (i.e., less than ``0``) finite number and ``x2_i`` is ``+infinity``, the result is ``x2_i``. (**note**: this results matches Python behavior.) - - If ``x1_i`` is a negative (i.e., less than ``0``) finite number and ``x2_i`` is ``-infinity``, the result is ``x1_i``. (**note**: this result matches Python behavior.) - - In the remaining cases, the result must match that of the Python ``%`` operator. - Parameters ---------- self: array @@ -852,56 +705,13 @@ def __mod__(self: array, other: Union[int, float, array], /) -> array: .. note:: - Element-wise results must equal the results returned by the equivalent element-wise function :func:`~array_api.remainder`. + Element-wise results, including special cases, must equal the results returned by the equivalent element-wise function :func:`~array_api.remainder`. """ def __mul__(self: array, other: Union[int, float, array], /) -> array: r""" Calculates the product for each element of an array instance with the respective element of the array ``other``. - **Special cases** - - Let ``self`` equal ``x1`` and ``other`` equal ``x2``. - - For real-valued floating-point operands, - - - 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. - - For complex floating-point operands, multiplication is defined according to the following table. For real components ``a`` and ``c`` and imaginary components ``b`` and ``d``, - - +------------+----------------+-----------------+--------------------------+ - | | c | dj | c + dj | - +============+================+=================+==========================+ - | **a** | a * c | (a*d)j | (a*c) + (a*d)j | - +------------+----------------+-----------------+--------------------------+ - | **bj** | (b*c)j | -(b*d) | -(b*d) + (b*c)j | - +------------+----------------+-----------------+--------------------------+ - | **a + bj** | (a*c) + (b*c)j | -(b*d) + (a*d)j | special rules | - +------------+----------------+-----------------+--------------------------+ - - In general, for complex floating-point operands, real-valued floating-point special cases must independently apply to the real and imaginary component operations involving real numbers as described in the above table. - - When ``a``, ``b``, ``c``, or ``d`` are all finite numbers (i.e., a value other than ``NaN``, ``+infinity``, or ``-infinity``), multiplication of complex floating-point operands should be computed as if calculated according to the textbook formula for complex number multiplication - - .. math:: - (a + bj) \cdot (c + dj) = (ac - bd) + (bc + ad)j - - When at least one of ``a``, ``b``, ``c``, or ``d`` is ``NaN``, ``+infinity``, or ``-infinity``, - - - If ``a``, ``b``, ``c``, and ``d`` are all ``NaN``, the result is ``NaN + NaN j``. - - In the remaining cases, the result is implementation dependent. - - .. note:: - For complex floating-point operands, the results of special cases may be implementation dependent depending on how an implementation chooses to model complex numbers and complex infinity (e.g., complex plane versus Riemann sphere). For those implementations following C99 and its one-infinity model, when at least one component is infinite, even if the other component is ``NaN``, the complex value is infinite, and the usual arithmetic rules do not apply to complex-complex multiplication. In the interest of performance, other implementations may want to avoid the complex branching logic necessary to implement the one-infinity model and choose to implement all complex-complex multiplication according to the textbook formula. Accordingly, special case behavior is unlikely to be consistent across implementations. - .. note:: Floating-point multiplication is not always associative due to finite precision. @@ -919,33 +729,13 @@ def __mul__(self: array, other: Union[int, float, array], /) -> array: .. note:: - Element-wise results must equal the results returned by the equivalent element-wise function :func:`~array_api.multiply`. + Element-wise results, including special cases, must equal the results returned by the equivalent element-wise function :func:`~array_api.multiply`. """ 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``. - **Special Cases** - - Let ``self`` equal ``x1`` and ``other`` equal ``x2``. - - For real-valued floating-point operands, - - - If ``x1_i`` is ``NaN`` or ``x2_i`` is ``NaN``, the result is ``True``. - - If ``x1_i`` is ``+infinity`` and ``x2_i`` is ``-infinity``, the result is ``True``. - - If ``x1_i`` is ``-infinity`` and ``x2_i`` is ``+infinity``, the result is ``True``. - - If ``x1_i`` is a finite number, ``x2_i`` is a finite number, and ``x1_i`` does not equal ``x2_i``, the result is ``True``. - - In the remaining cases, the result is ``False``. - - For complex floating-point operands, let ``a = real(x1_i)``, ``b = imag(x1_i)``, ``c = real(x2_i)``, ``d = imag(x2_i)``, and - - - If ``a``, ``b``, ``c``, or ``d`` is ``NaN``, the result is ``True``. - - In the remaining cases, the result is the logical OR of the equality comparison between the real values ``a`` and ``c`` (real components) and between the real values ``b`` and ``d`` (imaginary components), as described above for real-valued floating-point operands (i.e., ``a != c OR b != d``). - - .. note:: - For discussion of complex number equality, see :ref:`complex-numbers`. - Parameters ---------- self: array @@ -960,7 +750,7 @@ def __ne__(self: array, other: Union[int, float, bool, array], /) -> array: .. note:: - Element-wise results must equal the results returned by the equivalent element-wise function :func:`~array_api.not_equal`. + Element-wise results, including special cases, must equal the results returned by the equivalent element-wise function :func:`~array_api.not_equal`. """ def __neg__(self: array, /) -> array: @@ -1037,49 +827,6 @@ def __pow__(self: array, other: Union[int, float, array], /) -> array: 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** - - Let ``self`` equal ``x1`` and ``other`` equal ``x2``. - - For real-valued floating-point operands, - - - 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``. - - For complex floating-point operands, special cases should be handled as if the operation is implemented as ``exp(x2*log(x1))``. - - .. note:: - Conforming implementations are allowed to treat special cases involving complex floating-point operands more carefully than as described in this specification. - - .. note:: - By convention, the branch cut of the natural logarithm is the negative real axis :math:`(-\infty, 0)`. - - The natural logarithm is a continuous function from above the branch cut, taking into account the sign of the imaginary component. As special cases involving complex floating-point operands should be handled according to ``exp(other*log(self))``, exponentiation has the same branch cut for ``self`` as the natural logarithm (see :func:`~array_api.log`). - - *Note: branch cuts have provisional status* (see :ref:`branch-cuts`). - Parameters ---------- self: array @@ -1094,7 +841,7 @@ def __pow__(self: array, other: Union[int, float, array], /) -> array: .. note:: - Element-wise results must equal the results returned by the equivalent element-wise function :func:`~array_api.pow`. + Element-wise results, including special cases, must equal the results returned by the equivalent element-wise function :func:`~array_api.pow`. """ def __rshift__(self: array, other: Union[int, array], /) -> array: @@ -1180,62 +927,6 @@ def __truediv__(self: array, other: Union[int, float, array], /) -> array: 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** - - Let ``self`` equal ``x1`` and ``other`` equal ``x2``. - - For floating-point operands, - - - 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. - - For complex floating-point operands, division is defined according to the following table. For real components ``a`` and ``c`` and imaginary components ``b`` and ``d``, - - +------------+----------------+-----------------+--------------------------+ - | | c | dj | c + dj | - +============+================+=================+==========================+ - | **a** | a / c | -(a/d)j | special rules | - +------------+----------------+-----------------+--------------------------+ - | **bj** | (b/c)j | b/d | special rules | - +------------+----------------+-----------------+--------------------------+ - | **a + bj** | (a/c) + (b/c)j | b/d - (a/d)j | special rules | - +------------+----------------+-----------------+--------------------------+ - - In general, for complex floating-point operands, real-valued floating-point special cases must independently apply to the real and imaginary component operations involving real numbers as described in the above table. - - When ``a``, ``b``, ``c``, or ``d`` are all finite numbers (i.e., a value other than ``NaN``, ``+infinity``, or ``-infinity``), division of complex floating-point operands should be computed as if calculated according to the textbook formula for complex number division - - .. math:: - \frac{a + bj}{c + dj} = \frac{(ac + bd) + (bc - ad)j}{c^2 + d^2} - - When at least one of ``a``, ``b``, ``c``, or ``d`` is ``NaN``, ``+infinity``, or ``-infinity``, - - - If ``a``, ``b``, ``c``, and ``d`` are all ``NaN``, the result is ``NaN + NaN j``. - - In the remaining cases, the result is implementation dependent. - - .. note:: - For complex floating-point operands, the results of special cases may be implementation dependent depending on how an implementation chooses to model complex numbers and complex infinity (e.g., complex plane versus Riemann sphere). For those implementations following C99 and its one-infinity model, when at least one component is infinite, even if the other component is ``NaN``, the complex value is infinite, and the usual arithmetic rules do not apply to complex-complex division. In the interest of performance, other implementations may want to avoid the complex branching logic necessary to implement the one-infinity model and choose to implement all complex-complex division according to the textbook formula. Accordingly, special case behavior is unlikely to be consistent across implementations. - Parameters ---------- self: array @@ -1250,7 +941,7 @@ def __truediv__(self: array, other: Union[int, float, array], /) -> array: .. note:: - Element-wise results must equal the results returned by the equivalent element-wise function :func:`~array_api.divide`. + Element-wise results, including special cases, must equal the results returned by the equivalent element-wise function :func:`~array_api.divide`. """ def __xor__(self: array, other: Union[int, bool, array], /) -> array: diff --git a/spec/API_specification/array_api/elementwise_functions.py b/spec/API_specification/array_api/elementwise_functions.py index 3a3743ba8..3fce08c94 100644 --- a/spec/API_specification/array_api/elementwise_functions.py +++ b/spec/API_specification/array_api/elementwise_functions.py @@ -16,6 +16,25 @@ def abs(x: array, /) -> array: .. math:: \operatorname{abs}(z) = \sqrt{a^2 + b^2} + .. note:: + For complex floating-point operands, conforming implementations should take care to avoid undue overflow or underflow during intermediate stages of computation. + + .. + TODO: once ``hypot`` is added to the specification, remove the special cases for complex floating-point operands and the note concerning guarding against undue overflow/underflow, and state that special cases must be handled as if implemented as ``hypot(real(x), imag(x))``. + + Parameters + ---------- + x: array + input array. Should have a numeric data type. + + Returns + ------- + out: array + an array containing the absolute value of each element in ``x``. If ``x`` has a real-valued data type, the returned array must have the same data type as ``x``. If ``x`` has a complex floating-point data type, the returned arrayed must have a real-valued floating-point data type whose precision matches the precision of ``x`` (e.g., if ``x`` is ``complex128``, then the returned array must have a ``float64`` data type). + + Notes + ----- + **Special Cases** For real-valued floating-point operands, @@ -33,22 +52,6 @@ def abs(x: array, /) -> array: - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN``. - If ``a`` is a finite number and ``b`` is ``NaN``, the result is ``NaN``. - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN``. - - .. note:: - For complex floating-point operands, conforming implementations should take care to avoid undue overflow or underflow during intermediate stages of computation. - - .. - TODO: once ``hypot`` is added to the specification, remove the special cases for complex floating-point operands and the note concerning guarding against undue overflow/underflow, and state that special cases must be handled as if implemented as ``hypot(real(x), imag(x))``. - - Parameters - ---------- - x: array - input array. Should have a numeric data type. - - Returns - ------- - out: array - an array containing the absolute value of each element in ``x``. If ``x`` has a real-valued data type, the returned array must have the same data type as ``x``. If ``x`` has a complex floating-point data type, the returned arrayed must have a real-valued floating-point data type whose precision matches the precision of ``x`` (e.g., if ``x`` is ``complex128``, then the returned array must have a ``float64`` data type). """ @@ -58,30 +61,6 @@ def acos(x: array, /) -> array: Each element-wise result is expressed in radians. - **Special cases** - - For real-valued floating-point operands, - - - If ``x_i`` is ``NaN``, the result is ``NaN``. - - If ``x_i`` is greater than ``1``, the result is ``NaN``. - - If ``x_i`` is less than ``-1``, the result is ``NaN``. - - If ``x_i`` is ``1``, the result is ``+0``. - - For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - - - If ``a`` is either ``+0`` or ``-0`` and ``b`` is ``+0``, the result is ``π/2 - 0j``. - - If ``a`` is either ``+0`` or ``-0`` and ``b`` is ``NaN``, the result is ``π/2 + NaN j``. - - If ``a`` is a finite number and ``b`` is ``+infinity``, the result is ``π/2 - infinity j``. - - If ``a`` is a nonzero finite number and ``b`` is ``NaN``, the result is ``NaN + NaN j``. - - If ``a`` is ``-infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``π - infinity j``. - - If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+0 - infinity j``. - - If ``a`` is ``-infinity`` and ``b`` is ``+infinity``, the result is ``3π/4 - infinity j``. - - If ``a`` is ``+infinity`` and ``b`` is ``+infinity``, the result is ``π/4 - infinity j``. - - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is ``NaN``, the result is ``NaN ± infinity j`` (sign of the imaginary component is unspecified). - - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN + NaN j``. - - If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``NaN - infinity j``. - - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. - .. note:: The principal value of the arc cosine of a complex number :math:`z` is @@ -112,36 +91,39 @@ def acos(x: array, /) -> array: ------- out: array an array containing the inverse cosine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - """ - -def acosh(x: array, /) -> array: - r""" - Calculates an implementation-dependent approximation to the inverse hyperbolic cosine for each element ``x_i`` of the input array ``x``. + Notes + ----- **Special cases** For real-valued floating-point operands, - If ``x_i`` is ``NaN``, the result is ``NaN``. - - If ``x_i`` is less than ``1``, the result is ``NaN``. + - If ``x_i`` is greater than ``1``, the result is ``NaN``. + - If ``x_i`` is less than ``-1``, the result is ``NaN``. - If ``x_i`` is ``1``, the result is ``+0``. - - If ``x_i`` is ``+infinity``, the result is ``+infinity``. For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - - If ``a`` is either ``+0`` or ``-0`` and ``b`` is ``+0``, the result is ``+0 + πj/2``. - - If ``a`` is a finite number and ``b`` is ``+infinity``, the result is ``+infinity + πj/2``. + - If ``a`` is either ``+0`` or ``-0`` and ``b`` is ``+0``, the result is ``π/2 - 0j``. + - If ``a`` is either ``+0`` or ``-0`` and ``b`` is ``NaN``, the result is ``π/2 + NaN j``. + - If ``a`` is a finite number and ``b`` is ``+infinity``, the result is ``π/2 - infinity j``. - If ``a`` is a nonzero finite number and ``b`` is ``NaN``, the result is ``NaN + NaN j``. - - If ``a`` is ``+0`` and ``b`` is ``NaN``, the result is ``NaN ± πj/2`` (sign of imaginary component is unspecified). - - If ``a`` is ``-infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+infinity + πj``. - - If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+infinity + 0j``. - - If ``a`` is ``-infinity`` and ``b`` is ``+infinity``, the result is ``+infinity + 3πj/4``. - - If ``a`` is ``+infinity`` and ``b`` is ``+infinity``, the result is ``+infinity + πj/4``. - - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is ``NaN``, the result is ``+infinity + NaN j``. + - If ``a`` is ``-infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``π - infinity j``. + - If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+0 - infinity j``. + - If ``a`` is ``-infinity`` and ``b`` is ``+infinity``, the result is ``3π/4 - infinity j``. + - If ``a`` is ``+infinity`` and ``b`` is ``+infinity``, the result is ``π/4 - infinity j``. + - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is ``NaN``, the result is ``NaN ± infinity j`` (sign of the imaginary component is unspecified). - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN + NaN j``. - - If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``+infinity + NaN j``. + - If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``NaN - infinity j``. - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. + """ + + +def acosh(x: array, /) -> array: + r""" + Calculates an implementation-dependent approximation to the inverse hyperbolic cosine for each element ``x_i`` of the input array ``x``. .. note:: The principal value of the inverse hyperbolic cosine of a complex number :math:`z` is @@ -180,6 +162,33 @@ def acosh(x: array, /) -> array: ------- out: array an array containing the inverse hyperbolic cosine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + + **Special cases** + + For real-valued floating-point operands, + + - If ``x_i`` is ``NaN``, the result is ``NaN``. + - If ``x_i`` is less than ``1``, the result is ``NaN``. + - If ``x_i`` is ``1``, the result is ``+0``. + - If ``x_i`` is ``+infinity``, the result is ``+infinity``. + + For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and + + - If ``a`` is either ``+0`` or ``-0`` and ``b`` is ``+0``, the result is ``+0 + πj/2``. + - If ``a`` is a finite number and ``b`` is ``+infinity``, the result is ``+infinity + πj/2``. + - If ``a`` is a nonzero finite number and ``b`` is ``NaN``, the result is ``NaN + NaN j``. + - If ``a`` is ``+0`` and ``b`` is ``NaN``, the result is ``NaN ± πj/2`` (sign of imaginary component is unspecified). + - If ``a`` is ``-infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+infinity + πj``. + - If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+infinity + 0j``. + - If ``a`` is ``-infinity`` and ``b`` is ``+infinity``, the result is ``+infinity + 3πj/4``. + - If ``a`` is ``+infinity`` and ``b`` is ``+infinity``, the result is ``+infinity + πj/4``. + - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is ``NaN``, the result is ``+infinity + NaN j``. + - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN + NaN j``. + - If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``+infinity + NaN j``. + - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. """ @@ -187,6 +196,21 @@ def add(x1: array, x2: array, /) -> array: """ Calculates the sum for each element ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input array ``x2``. + Parameters + ---------- + x1: array + first input array. Should have a numeric data type. + x2: array + second input array. Must be compatible with ``x1`` (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 + ----- + **Special cases** For real-valued floating-point operands, @@ -230,18 +254,6 @@ def add(x1: array, x2: array, /) -> array: - Similarly, if ``b`` is ``+0`` and ``d`` is ``-0``, the imaginary component of the result is ``+0``. Hence, if ``z1 = a + bj = -0 + 0j`` and ``z2 = c + dj = -0 - 0j``, the result of ``z1 + z2`` is ``-0 + 0j``. - - Parameters - ---------- - x1: array - first input array. Should have a numeric data type. - x2: array - second input array. Must be compatible with ``x1`` (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`. """ @@ -251,18 +263,6 @@ def asin(x: array, /) -> array: Each element-wise result is expressed in radians. - **Special cases** - - For real-valued floating-point operands, - - - If ``x_i`` is ``NaN``, the result is ``NaN``. - - If ``x_i`` is greater than ``1``, the result is ``NaN``. - - If ``x_i`` is less than ``-1``, the result is ``NaN``. - - If ``x_i`` is ``+0``, the result is ``+0``. - - If ``x_i`` is ``-0``, the result is ``-0``. - - For complex floating-point operands, special cases must be handled as if the operation is implemented as ``-1j * asinh(x*1j)``. - .. note:: The principal value of the arc sine of a complex number :math:`z` is @@ -293,34 +293,27 @@ def asin(x: array, /) -> array: ------- out: array an array containing the inverse sine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - """ - -def asinh(x: array, /) -> array: - r""" - Calculates an implementation-dependent approximation to the inverse hyperbolic sine for each element ``x_i`` in the input array ``x``. + Notes + ----- **Special cases** For real-valued floating-point operands, - If ``x_i`` is ``NaN``, the result is ``NaN``. + - If ``x_i`` is greater than ``1``, the result is ``NaN``. + - If ``x_i`` is less than ``-1``, the result is ``NaN``. - If ``x_i`` is ``+0``, the result is ``+0``. - If ``x_i`` is ``-0``, the result is ``-0``. - - If ``x_i`` is ``+infinity``, the result is ``+infinity``. - - If ``x_i`` is ``-infinity``, the result is ``-infinity``. - For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and + For complex floating-point operands, special cases must be handled as if the operation is implemented as ``-1j * asinh(x*1j)``. + """ - - If ``a`` is ``+0`` and ``b`` is ``+0``, the result is ``+0 + 0j``. - - If ``a`` is a positive (i.e., greater than ``0``) finite number and ``b`` is ``+infinity``, the result is ``+infinity + πj/2``. - - If ``a`` is a finite number and ``b`` is ``NaN``, the result is ``NaN + NaN j``. - - If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+infinity + 0j``. - - If ``a`` is ``+infinity`` and ``b`` is ``+infinity``, the result is ``+infinity + πj/4``. - - If ``a`` is ``NaN`` and ``b`` is ``+0``, the result is ``NaN + 0j``. - - If ``a`` is ``NaN`` and ``b`` is a nonzero finite number, the result is ``NaN + NaN j``. - - If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``±infinity + NaN j`` (sign of the real component is unspecified). - - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. + +def asinh(x: array, /) -> array: + r""" + Calculates an implementation-dependent approximation to the inverse hyperbolic sine for each element ``x_i`` in the input array ``x``. .. note:: The principal value of the inverse hyperbolic sine of a complex number :math:`z` is @@ -352,14 +345,9 @@ def asinh(x: array, /) -> array: ------- out: array an array containing the inverse hyperbolic sine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - """ - - -def atan(x: array, /) -> array: - r""" - Calculates an implementation-dependent approximation of the principal value of the inverse tangent for each element ``x_i`` of the input array ``x``. - Each element-wise result is expressed in radians. + Notes + ----- **Special cases** @@ -368,10 +356,28 @@ def atan(x: array, /) -> array: - If ``x_i`` is ``NaN``, the result is ``NaN``. - If ``x_i`` is ``+0``, the result is ``+0``. - If ``x_i`` is ``-0``, the result is ``-0``. - - If ``x_i`` is ``+infinity``, the result is an implementation-dependent approximation to ``+π/2``. - - If ``x_i`` is ``-infinity``, the result is an implementation-dependent approximation to ``-π/2``. + - If ``x_i`` is ``+infinity``, the result is ``+infinity``. + - If ``x_i`` is ``-infinity``, the result is ``-infinity``. - For complex floating-point operands, special cases must be handled as if the operation is implemented as ``-1j * atanh(x*1j)``. + For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and + + - If ``a`` is ``+0`` and ``b`` is ``+0``, the result is ``+0 + 0j``. + - If ``a`` is a positive (i.e., greater than ``0``) finite number and ``b`` is ``+infinity``, the result is ``+infinity + πj/2``. + - If ``a`` is a finite number and ``b`` is ``NaN``, the result is ``NaN + NaN j``. + - If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+infinity + 0j``. + - If ``a`` is ``+infinity`` and ``b`` is ``+infinity``, the result is ``+infinity + πj/4``. + - If ``a`` is ``NaN`` and ``b`` is ``+0``, the result is ``NaN + 0j``. + - If ``a`` is ``NaN`` and ``b`` is a nonzero finite number, the result is ``NaN + NaN j``. + - If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``±infinity + NaN j`` (sign of the real component is unspecified). + - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. + """ + + +def atan(x: array, /) -> array: + r""" + Calculates an implementation-dependent approximation of the principal value of the inverse tangent for each element ``x_i`` of the input array ``x``. + + Each element-wise result is expressed in radians. .. note:: The principal value of the inverse tangent of a complex number :math:`z` is @@ -398,6 +404,21 @@ def atan(x: array, /) -> array: ------- out: array an array containing the inverse tangent of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + + **Special cases** + + For real-valued floating-point operands, + + - If ``x_i`` is ``NaN``, the result is ``NaN``. + - If ``x_i`` is ``+0``, the result is ``+0``. + - If ``x_i`` is ``-0``, the result is ``-0``. + - If ``x_i`` is ``+infinity``, the result is an implementation-dependent approximation to ``+π/2``. + - If ``x_i`` is ``-infinity``, the result is an implementation-dependent approximation to ``-π/2``. + + For complex floating-point operands, special cases must be handled as if the operation is implemented as ``-1j * atanh(x*1j)``. """ @@ -412,6 +433,21 @@ def atan2(x1: array, x2: array, /) -> array: By IEEE 754 convention, the inverse tangent of the quotient ``x1/x2`` is defined for ``x2_i`` equal to positive or negative zero and for either or both of ``x1_i`` and ``x2_i`` equal to positive or negative ``infinity``. + Parameters + ---------- + x1: array + input array corresponding to the y-coordinates. Should have a real-valued floating-point data type. + x2: array + input array corresponding to the x-coordinates. Must be compatible with ``x1`` (see :ref:`broadcasting`). Should have a real-valued floating-point data type. + + Returns + ------- + out: array + an array containing the inverse tangent of the quotient ``x1/x2``. The returned array must have a real-valued floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + **Special cases** For floating-point operands, @@ -439,19 +475,6 @@ def atan2(x1: array, x2: array, /) -> array: - If ``x1_i`` is ``+infinity`` and ``x2_i`` is ``-infinity``, the result is an implementation-dependent approximation to ``+3π/4``. - If ``x1_i`` is ``-infinity`` and ``x2_i`` is ``+infinity``, the result is an implementation-dependent approximation to ``-π/4``. - If ``x1_i`` is ``-infinity`` and ``x2_i`` is ``-infinity``, the result is an implementation-dependent approximation to ``-3π/4``. - - Parameters - ---------- - x1: array - input array corresponding to the y-coordinates. Should have a real-valued floating-point data type. - x2: array - input array corresponding to the x-coordinates. Must be compatible with ``x1`` (see :ref:`broadcasting`). Should have a real-valued floating-point data type. - - Returns - ------- - out: array - an array containing the inverse tangent of the quotient ``x1/x2``. The returned array must have a real-valued floating-point data type determined by :ref:`type-promotion`. - """ @@ -459,32 +482,6 @@ def atanh(x: array, /) -> array: r""" Calculates an implementation-dependent approximation to the inverse hyperbolic tangent for each element ``x_i`` of the input array ``x``. - **Special cases** - - For real-valued floating-point operands, - - - If ``x_i`` is ``NaN``, the result is ``NaN``. - - If ``x_i`` is less than ``-1``, the result is ``NaN``. - - If ``x_i`` is greater than ``1``, the result is ``NaN``. - - If ``x_i`` is ``-1``, the result is ``-infinity``. - - If ``x_i`` is ``+1``, the result is ``+infinity``. - - If ``x_i`` is ``+0``, the result is ``+0``. - - If ``x_i`` is ``-0``, the result is ``-0``. - - For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - - - If ``a`` is ``+0`` and ``b`` is ``+0``, the result is ``+0 + 0j``. - - If ``a`` is ``+0`` and ``b`` is ``NaN``, the result is ``+0 + NaN j``. - - If ``a`` is ``1`` and ``b`` is ``+0``, the result is ``+infinity + 0j``. - - If ``a`` is a positive (i.e., greater than ``0``) finite number and ``b`` is ``+infinity``, the result is ``+0 + πj/2``. - - If ``a`` is a nonzero finite number and ``b`` is ``NaN``, the result is ``NaN + NaN j``. - - If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+0 + πj/2``. - - If ``a`` is ``+infinity`` and ``b`` is ``+infinity``, the result is ``+0 + πj/2``. - - If ``a`` is ``+infinity`` and ``b`` is ``NaN``, the result is ``+0 + NaN j``. - - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN + NaN j``. - - If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``±0 + πj/2`` (sign of the real component is unspecified). - - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. - .. note:: The principal value of the inverse hyperbolic tangent of a complex number :math:`z` is @@ -515,6 +512,35 @@ def atanh(x: array, /) -> array: ------- out: array an array containing the inverse hyperbolic tangent of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + + **Special cases** + + For real-valued floating-point operands, + + - If ``x_i`` is ``NaN``, the result is ``NaN``. + - If ``x_i`` is less than ``-1``, the result is ``NaN``. + - If ``x_i`` is greater than ``1``, the result is ``NaN``. + - If ``x_i`` is ``-1``, the result is ``-infinity``. + - If ``x_i`` is ``+1``, the result is ``+infinity``. + - If ``x_i`` is ``+0``, the result is ``+0``. + - If ``x_i`` is ``-0``, the result is ``-0``. + + For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and + + - If ``a`` is ``+0`` and ``b`` is ``+0``, the result is ``+0 + 0j``. + - If ``a`` is ``+0`` and ``b`` is ``NaN``, the result is ``+0 + NaN j``. + - If ``a`` is ``1`` and ``b`` is ``+0``, the result is ``+infinity + 0j``. + - If ``a`` is a positive (i.e., greater than ``0``) finite number and ``b`` is ``+infinity``, the result is ``+0 + πj/2``. + - If ``a`` is a nonzero finite number and ``b`` is ``NaN``, the result is ``NaN + NaN j``. + - If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+0 + πj/2``. + - If ``a`` is ``+infinity`` and ``b`` is ``+infinity``, the result is ``+0 + πj/2``. + - If ``a`` is ``+infinity`` and ``b`` is ``NaN``, the result is ``+0 + NaN j``. + - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN + NaN j``. + - If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``±0 + πj/2`` (sign of the real component is unspecified). + - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. """ @@ -631,6 +657,19 @@ def ceil(x: array, /) -> array: """ Rounds each element ``x_i`` of the input array ``x`` to the smallest (i.e., closest to ``-infinity``) integer-valued number that is not less than ``x_i``. + Parameters + ---------- + x: array + input array. Should have a real-valued data type. + + Returns + ------- + out: array + an array containing the rounded result for each element in ``x``. The returned array must have the same data type as ``x``. + + Notes + ----- + **Special cases** - If ``x_i`` is already integer-valued, the result is ``x_i``. @@ -642,16 +681,6 @@ def ceil(x: array, /) -> array: - If ``x_i`` is ``+0``, the result is ``+0``. - If ``x_i`` is ``-0``, the result is ``-0``. - If ``x_i`` is ``NaN``, the result is ``NaN``. - - Parameters - ---------- - x: array - input array. Should have a real-valued data type. - - Returns - ------- - out: array - an array containing the rounded result for each element in ``x``. The returned array must have the same data type as ``x``. """ @@ -689,18 +718,6 @@ def cos(x: array, /) -> array: Each element ``x_i`` is assumed to be expressed in radians. - **Special cases** - - For real-valued floating-point operands, - - - If ``x_i`` is ``NaN``, the result is ``NaN``. - - If ``x_i`` is ``+0``, the result is ``1``. - - If ``x_i`` is ``-0``, the result is ``1``. - - If ``x_i`` is ``+infinity``, the result is ``NaN``. - - If ``x_i`` is ``-infinity``, the result is ``NaN``. - - For complex floating-point operands, special cases must be handled as if the operation is implemented as ``cosh(x*1j)``. - .. note:: The cosine is an entire function on the complex plane and has no branch cuts. @@ -721,6 +738,21 @@ def cos(x: array, /) -> array: ------- out: array an array containing the cosine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + + **Special cases** + + For real-valued floating-point operands, + + - If ``x_i`` is ``NaN``, the result is ``NaN``. + - If ``x_i`` is ``+0``, the result is ``1``. + - If ``x_i`` is ``-0``, the result is ``1``. + - If ``x_i`` is ``+infinity``, the result is ``NaN``. + - If ``x_i`` is ``-infinity``, the result is ``NaN``. + + For complex floating-point operands, special cases must be handled as if the operation is implemented as ``cosh(x*1j)``. """ @@ -733,6 +765,22 @@ def cosh(x: array, /) -> array: .. math:: \operatorname{cosh}(x) = \frac{e^x + e^{-x}}{2} + .. note:: + The hyperbolic cosine is an entire function in the complex plane and has no branch cuts. The function is periodic, with period :math:`2\pi j`, with respect to the imaginary component. + + Parameters + ---------- + x: array + input array whose elements each represent a hyperbolic angle. Should have a floating-point data type. + + Returns + ------- + out: array + an array containing the hyperbolic cosine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + **Special cases** .. note:: @@ -765,19 +813,6 @@ def cosh(x: array, /) -> array: - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. where ``cis(v)`` is ``cos(v) + sin(v)*1j``. - - .. note:: - The hyperbolic cosine is an entire function in the complex plane and has no branch cuts. The function is periodic, with period :math:`2\pi j`, with respect to the imaginary component. - - Parameters - ---------- - x: array - input array whose elements each represent a hyperbolic angle. Should have a floating-point data type. - - Returns - ------- - out: array - an array containing the hyperbolic cosine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. """ @@ -790,6 +825,21 @@ def divide(x1: array, x2: array, /) -> array: 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. + Parameters + ---------- + x1: array + dividend input array. Should have a numeric data type. + x2: array + divisor input array. Must be compatible with ``x1`` (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 floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + **Special cases** For real-valued floating-point operands, @@ -843,24 +893,27 @@ def divide(x1: array, x2: array, /) -> array: .. note:: For complex floating-point operands, the results of special cases may be implementation dependent depending on how an implementation chooses to model complex numbers and complex infinity (e.g., complex plane versus Riemann sphere). For those implementations following C99 and its one-infinity model, when at least one component is infinite, even if the other component is ``NaN``, the complex value is infinite, and the usual arithmetic rules do not apply to complex-complex division. In the interest of performance, other implementations may want to avoid the complex branching logic necessary to implement the one-infinity model and choose to implement all complex-complex division according to the textbook formula. Accordingly, special case behavior is unlikely to be consistent across implementations. + """ + + +def equal(x1: array, x2: array, /) -> array: + r""" + Computes the truth value of ``x1_i == x2_i`` for each element ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input array ``x2``. Parameters ---------- x1: array - dividend input array. Should have a numeric data type. + first input array. May have any data type. x2: array - divisor input array. Must be compatible with ``x1`` (see :ref:`broadcasting`). Should have a numeric data type. + second input array. Must be compatible with ``x1`` (see :ref:`broadcasting`). May have any data type. Returns ------- out: array - an array containing the element-wise results. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - """ + an array containing the element-wise results. The returned array must have a data type of ``bool``. - -def equal(x1: array, x2: array, /) -> array: - r""" - Computes the truth value of ``x1_i == x2_i`` for each element ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input array ``x2``. + Notes + ----- **Special Cases** @@ -881,24 +934,31 @@ def equal(x1: array, x2: array, /) -> array: .. note:: For discussion of complex number equality, see :ref:`complex-numbers`. + """ + + +def exp(x: array, /) -> array: + """ + Calculates an implementation-dependent approximation to the exponential function for each element ``x_i`` of the input array ``x`` (``e`` raised to the power of ``x_i``, where ``e`` is the base of the natural logarithm). + + .. note:: + For complex floating-point operands, ``exp(conj(x))`` must equal ``conj(exp(x))``. + + .. note:: + The exponential function is an entire function in the complex plane and has no branch cuts. Parameters ---------- - x1: array - first input array. May have any data type. - x2: array - second input array. Must be compatible with ``x1`` (see :ref:`broadcasting`). May have any data type. + x: array + input array. Should have a floating-point data type. Returns ------- out: array - an array containing the element-wise results. The returned array must have a data type of ``bool``. - """ - + an array containing the evaluated exponential function result for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. -def exp(x: array, /) -> array: - """ - Calculates an implementation-dependent approximation to the exponential function for each element ``x_i`` of the input array ``x`` (``e`` raised to the power of ``x_i``, where ``e`` is the base of the natural logarithm). + Notes + ----- **Special cases** @@ -927,9 +987,18 @@ def exp(x: array, /) -> array: - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. where ``cis(v)`` is ``cos(v) + sin(v)*1j``. + """ + + +def expm1(x: array, /) -> array: + """ + Calculates an implementation-dependent approximation to ``exp(x)-1`` for each element ``x_i`` of the input array ``x``. .. note:: - For complex floating-point operands, ``exp(conj(x))`` must equal ``conj(exp(x))``. + The purpose of this function is to calculate ``exp(x)-1.0`` more accurately when `x` is close to zero. Accordingly, conforming implementations should avoid implementing this function as simply ``exp(x)-1.0``. See FDLIBM, or some other IEEE 754-2019 compliant mathematical library, for a potential reference implementation. + + .. note:: + For complex floating-point operands, ``expm1(conj(x))`` must equal ``conj(expm1(x))``. .. note:: The exponential function is an entire function in the complex plane and has no branch cuts. @@ -942,16 +1011,10 @@ def exp(x: array, /) -> array: Returns ------- out: array - an array containing the evaluated exponential function result for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - """ - - -def expm1(x: array, /) -> array: - """ - Calculates an implementation-dependent approximation to ``exp(x)-1`` for each element ``x_i`` of the input array ``x``. + an array containing the evaluated result for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - .. note:: - The purpose of this function is to calculate ``exp(x)-1.0`` more accurately when `x` is close to zero. Accordingly, conforming implementations should avoid implementing this function as simply ``exp(x)-1.0``. See FDLIBM, or some other IEEE 754-2019 compliant mathematical library, for a potential reference implementation. + Notes + ----- **Special cases** @@ -980,28 +1043,25 @@ def expm1(x: array, /) -> array: - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. where ``cis(v)`` is ``cos(v) + sin(v)*1j``. + """ - .. note:: - For complex floating-point operands, ``expm1(conj(x))`` must equal ``conj(expm1(x))``. - .. note:: - The exponential function is an entire function in the complex plane and has no branch cuts. +def floor(x: array, /) -> array: + """ + Rounds each element ``x_i`` of the input array ``x`` to the greatest (i.e., closest to ``+infinity``) integer-valued number that is not greater than ``x_i``. Parameters ---------- x: array - input array. Should have a floating-point data type. + input array. Should have a real-valued data type. Returns ------- out: array - an array containing the evaluated result for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - """ - + an array containing the rounded result for each element in ``x``. The returned array must have the same data type as ``x``. -def floor(x: array, /) -> array: - """ - Rounds each element ``x_i`` of the input array ``x`` to the greatest (i.e., closest to ``+infinity``) integer-valued number that is not greater than ``x_i``. + Notes + ----- **Special cases** @@ -1014,25 +1074,30 @@ def floor(x: array, /) -> array: - If ``x_i`` is ``+0``, the result is ``+0``. - If ``x_i`` is ``-0``, the result is ``-0``. - If ``x_i`` is ``NaN``, the result is ``NaN``. + """ + + +def floor_divide(x1: array, x2: array, /) -> array: + r""" + Rounds the result of dividing each element ``x1_i`` of the input array ``x1`` by the respective element ``x2_i`` of the input array ``x2`` to the greatest (i.e., closest to `+infinity`) integer-value number that is not greater than the division result. + + .. note:: + For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. Parameters ---------- - x: array - input array. Should have a real-valued data type. + x1: array + dividend input array. Should have a real-valued data type. + x2: array + divisor input array. Must be compatible with ``x1`` (see :ref:`broadcasting`). Should have a real-valued data type. Returns ------- out: array - an array containing the rounded result for each element in ``x``. The returned array must have the same data type as ``x``. - """ - - -def floor_divide(x1: array, x2: array, /) -> array: - r""" - Rounds the result of dividing each element ``x1_i`` of the input array ``x1`` by the respective element ``x2_i`` of the input array ``x2`` to the greatest (i.e., closest to `+infinity`) integer-value number that is not greater than the division result. + an array containing the element-wise results. The returned array must have a data type determined by :ref:`type-promotion`. - .. note:: - For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. + Notes + ----- **Special cases** @@ -1069,18 +1134,6 @@ def floor_divide(x1: array, x2: 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 - ---------- - x1: array - dividend input array. Should have a real-valued data type. - x2: array - divisor input array. Must be compatible with ``x1`` (see :ref:`broadcasting`). Should have a real-valued 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`. """ @@ -1146,6 +1199,19 @@ def isfinite(x: array, /) -> array: """ Tests each element ``x_i`` of the input array ``x`` to determine if finite. + Parameters + ---------- + x: array + input array. Should have a numeric data type. + + Returns + ------- + out: array + an array containing test results. The returned array must have a data type of ``bool``. + + Notes + ----- + **Special Cases** For real-valued floating-point operands, @@ -1160,6 +1226,12 @@ def isfinite(x: array, /) -> array: - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is any value, the result is ``False``. - If ``a`` is any value and ``b`` is either ``+infinity`` or ``-infinity``, the result is ``False``. - If ``a`` is a finite number and ``b`` is a finite number, the result is ``True``. + """ + + +def isinf(x: array, /) -> array: + """ + Tests each element ``x_i`` of the input array ``x`` to determine if equal to positive or negative infinity. Parameters ---------- @@ -1170,12 +1242,9 @@ def isfinite(x: array, /) -> array: ------- out: array an array containing test results. The returned array must have a data type of ``bool``. - """ - -def isinf(x: array, /) -> array: - """ - Tests each element ``x_i`` of the input array ``x`` to determine if equal to positive or negative infinity. + Notes + ----- **Special Cases** @@ -1189,6 +1258,12 @@ def isinf(x: array, /) -> array: - If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is any value (including ``NaN``), the result is ``True``. - If ``a`` is either a finite number or ``NaN`` and ``b`` is either ``+infinity`` or ``-infinity``, the result is ``True``. - In the remaining cases, the result is ``False``. + """ + + +def isnan(x: array, /) -> array: + """ + Tests each element ``x_i`` of the input array ``x`` to determine whether the element is ``NaN``. Parameters ---------- @@ -1198,13 +1273,10 @@ def isinf(x: array, /) -> array: Returns ------- out: array - an array containing test results. The returned array must have a data type of ``bool``. - """ - + an array containing test results. The returned array should have a data type of ``bool``. -def isnan(x: array, /) -> array: - """ - Tests each element ``x_i`` of the input array ``x`` to determine whether the element is ``NaN``. + Notes + ----- **Special Cases** @@ -1217,16 +1289,6 @@ def isnan(x: array, /) -> array: - If ``a`` or ``b`` is ``NaN``, the result is ``True``. - In the remaining cases, the result is ``False``. - - Parameters - ---------- - x: array - input array. Should have a numeric data type. - - Returns - ------- - out: array - an array containing test results. The returned array should have a data type of ``bool``. """ @@ -1276,6 +1338,34 @@ def log(x: array, /) -> array: r""" Calculates an implementation-dependent approximation to the natural (base ``e``) logarithm for each element ``x_i`` of the input array ``x``. + .. note:: + The natural logarithm of a complex number :math:`z` with polar coordinates :math:`(r,\theta)` equals :math:`\ln r + (\theta + 2n\pi)j` with principal value :math:`\ln r + \theta j`. + + .. note:: + For complex floating-point operands, ``log(conj(x))`` must equal ``conj(log(x))``. + + .. note:: + By convention, the branch cut of the natural logarithm is the negative real axis :math:`(-\infty, 0)`. + + The natural logarithm is a continuous function from above the branch cut, taking into account the sign of the imaginary component. + + Accordingly, for complex arguments, the function returns the natural logarithm in the range of a strip in the interval :math:`[-\pi j, +\pi j]` along the imaginary axis and mathematically unbounded along the real axis. + + *Note: branch cuts have provisional status* (see :ref:`branch-cuts`). + + Parameters + ---------- + x: array + input array. Should have a floating-point data type. + + Returns + ------- + out: array + an array containing the evaluated natural logarithm for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + **Special cases** For real-valued floating-point operands, @@ -1300,12 +1390,18 @@ def log(x: array, /) -> array: - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN + NaN j``. - If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``+infinity + NaN j``. - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. + """ + + +def log1p(x: array, /) -> array: + r""" + Calculates an implementation-dependent approximation to ``log(1+x)``, where ``log`` refers to the natural (base ``e``) logarithm, for each element ``x_i`` of the input array ``x``. .. note:: - The natural logarithm of a complex number :math:`z` with polar coordinates :math:`(r,\theta)` equals :math:`\ln r + (\theta + 2n\pi)j` with principal value :math:`\ln r + \theta j`. + The purpose of this function is to calculate ``log(1+x)`` more accurately when `x` is close to zero. Accordingly, conforming implementations should avoid implementing this function as simply ``log(1+x)``. See FDLIBM, or some other IEEE 754-2019 compliant mathematical library, for a potential reference implementation. .. note:: - For complex floating-point operands, ``log(conj(x))`` must equal ``conj(log(x))``. + For complex floating-point operands, ``log1p(conj(x))`` must equal ``conj(log1p(x))``. .. note:: By convention, the branch cut of the natural logarithm is the negative real axis :math:`(-\infty, 0)`. @@ -1324,16 +1420,10 @@ def log(x: array, /) -> array: Returns ------- out: array - an array containing the evaluated natural logarithm for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - """ - - -def log1p(x: array, /) -> array: - r""" - Calculates an implementation-dependent approximation to ``log(1+x)``, where ``log`` refers to the natural (base ``e``) logarithm, for each element ``x_i`` of the input array ``x``. + an array containing the evaluated result for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - .. note:: - The purpose of this function is to calculate ``log(1+x)`` more accurately when `x` is close to zero. Accordingly, conforming implementations should avoid implementing this function as simply ``log(1+x)``. See FDLIBM, or some other IEEE 754-2019 compliant mathematical library, for a potential reference implementation. + Notes + ----- **Special cases** @@ -1359,18 +1449,15 @@ def log1p(x: array, /) -> array: - If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN + NaN j``. - If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``+infinity + NaN j``. - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. + """ - .. note:: - For complex floating-point operands, ``log1p(conj(x))`` must equal ``conj(log1p(x))``. - - .. note:: - By convention, the branch cut of the natural logarithm is the negative real axis :math:`(-\infty, 0)`. - - The natural logarithm is a continuous function from above the branch cut, taking into account the sign of the imaginary component. - Accordingly, for complex arguments, the function returns the natural logarithm in the range of a strip in the interval :math:`[-\pi j, +\pi j]` along the imaginary axis and mathematically unbounded along the real axis. +def log2(x: array, /) -> array: + r""" + Calculates an implementation-dependent approximation to the base ``2`` logarithm for each element ``x_i`` of the input array ``x``. - *Note: branch cuts have provisional status* (see :ref:`branch-cuts`). + .. note:: + For complex floating-point operands, ``log2(conj(x))`` must equal ``conj(log2(x))``. Parameters ---------- @@ -1380,13 +1467,10 @@ def log1p(x: array, /) -> array: Returns ------- out: array - an array containing the evaluated result for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - """ - + an array containing the evaluated base ``2`` logarithm for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. -def log2(x: array, /) -> array: - r""" - Calculates an implementation-dependent approximation to the base ``2`` logarithm for each element ``x_i`` of the input array ``x``. + Notes + ----- **Special cases** @@ -1404,9 +1488,15 @@ def log2(x: array, /) -> array: \log_{2} x = \frac{\log_{e} x}{\log_{e} 2} where :math:`\log_{e}` is the natural logarithm, as implemented by :func:`~array_api.log`. + """ + + +def log10(x: array, /) -> array: + r""" + Calculates an implementation-dependent approximation to the base ``10`` logarithm for each element ``x_i`` of the input array ``x``. .. note:: - For complex floating-point operands, ``log2(conj(x))`` must equal ``conj(log2(x))``. + For complex floating-point operands, ``log10(conj(x))`` must equal ``conj(log10(x))``. Parameters ---------- @@ -1416,13 +1506,10 @@ def log2(x: array, /) -> array: Returns ------- out: array - an array containing the evaluated base ``2`` logarithm for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - """ - + an array containing the evaluated base ``10`` logarithm for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. -def log10(x: array, /) -> array: - r""" - Calculates an implementation-dependent approximation to the base ``10`` logarithm for each element ``x_i`` of the input array ``x``. + Notes + ----- **Special cases** @@ -1440,19 +1527,6 @@ def log10(x: array, /) -> array: \log_{10} x = \frac{\log_{e} x}{\log_{e} 10} where :math:`\log_{e}` is the natural logarithm, as implemented by :func:`~array_api.log`. - - .. note:: - For complex floating-point operands, ``log10(conj(x))`` must equal ``conj(log10(x))``. - - Parameters - ---------- - x: array - input array. Should have a floating-point data type. - - Returns - ------- - out: array - an array containing the evaluated base ``10`` logarithm for each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. """ @@ -1460,14 +1534,6 @@ def logaddexp(x1: array, x2: array, /) -> array: """ Calculates the logarithm of the sum of exponentiations ``log(exp(x1) + exp(x2))`` for each element ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input array ``x2``. - **Special cases** - - For floating-point operands, - - - If either ``x1_i`` or ``x2_i`` is ``NaN``, the result is ``NaN``. - - If ``x1_i`` is ``+infinity`` and ``x2_i`` is not ``NaN``, the result is ``+infinity``. - - If ``x1_i`` is not ``NaN`` and ``x2_i`` is ``+infinity``, the result is ``+infinity``. - Parameters ---------- x1: array @@ -1479,6 +1545,17 @@ def logaddexp(x1: array, x2: array, /) -> array: ------- out: array an array containing the element-wise results. The returned array must have a real-valued floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + + **Special cases** + + For floating-point operands, + + - If either ``x1_i`` or ``x2_i`` is ``NaN``, the result is ``NaN``. + - If ``x1_i`` is ``+infinity`` and ``x2_i`` is not ``NaN``, the result is ``+infinity``. + - If ``x1_i`` is not ``NaN`` and ``x2_i`` is ``+infinity``, the result is ``+infinity``. """ @@ -1568,6 +1645,24 @@ def multiply(x1: array, x2: array, /) -> array: r""" Calculates the product for each element ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input array ``x2``. + .. note:: + Floating-point multiplication is not always associative due to finite precision. + + Parameters + ---------- + x1: array + first input array. Should have a numeric data type. + x2: array + second input array. Must be compatible with ``x1`` (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 + ----- + **Special cases** For real-valued floating-point operands, @@ -1608,21 +1703,6 @@ def multiply(x1: array, x2: array, /) -> array: .. note:: For complex floating-point operands, the results of special cases may be implementation dependent depending on how an implementation chooses to model complex numbers and complex infinity (e.g., complex plane versus Riemann sphere). For those implementations following C99 and its one-infinity model, when at least one component is infinite, even if the other component is ``NaN``, the complex value is infinite, and the usual arithmetic rules do not apply to complex-complex multiplication. In the interest of performance, other implementations may want to avoid the complex branching logic necessary to implement the one-infinity model and choose to implement all complex-complex multiplication according to the textbook formula. Accordingly, special case behavior is unlikely to be consistent across implementations. - - .. note:: - Floating-point multiplication is not always associative due to finite precision. - - Parameters - ---------- - x1: array - first input array. Should have a numeric data type. - x2: array - second input array. Must be compatible with ``x1`` (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`. """ @@ -1652,6 +1732,21 @@ def not_equal(x1: array, x2: array, /) -> array: """ Computes the truth value of ``x1_i != x2_i`` for each element ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input array ``x2``. + Parameters + ---------- + x1: array + first input array. May have any data type. + x2: array + second input array. Must be compatible with ``x1`` (see :ref:`broadcasting`). + + Returns + ------- + out: array + an array containing the element-wise results. The returned array must have a data type of ``bool``. + + Notes + ----- + **Special Cases** For real-valued floating-point operands, @@ -1669,18 +1764,6 @@ def not_equal(x1: array, x2: array, /) -> array: .. note:: For discussion of complex number equality, see :ref:`complex-numbers`. - - Parameters - ---------- - x1: array - first input array. May have any data type. - x2: array - second input array. Must be compatible with ``x1`` (see :ref:`broadcasting`). - - Returns - ------- - out: array - an array containing the element-wise results. The returned array must have a data type of ``bool``. """ @@ -1707,7 +1790,29 @@ def pow(x1: array, x2: array, /) -> array: .. note:: If both ``x1`` and ``x2`` have integer data types, the result of ``pow`` when ``x2_i`` is negative (i.e., less than zero) is unspecified and thus implementation-dependent. - If ``x1`` has an integer data type and ``x2`` has a floating-point data type, behavior is implementation-dependent (type promotion between data type "kinds" (integer versus floating-point) is unspecified). + If ``x1`` has an integer data type and ``x2`` has a floating-point data type, behavior is implementation-dependent (type promotion between data type "kinds" (integer versus floating-point) is unspecified). + + .. note:: + By convention, the branch cut of the natural logarithm is the negative real axis :math:`(-\infty, 0)`. + + The natural logarithm is a continuous function from above the branch cut, taking into account the sign of the imaginary component. As special cases involving complex floating-point operands should be handled according to ``exp(x2*log(x1))``, exponentiation has the same branch cut for ``x1`` as the natural logarithm (see :func:`~array_api.log`). + + *Note: branch cuts have provisional status* (see :ref:`branch-cuts`). + + Parameters + ---------- + x1: array + first input array whose elements correspond to the exponentiation base. Should have a numeric data type. + x2: array + second input array whose elements correspond to the exponentiation exponent. Must be compatible with ``x1`` (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 + ----- **Special cases** @@ -1742,25 +1847,6 @@ def pow(x1: array, x2: array, /) -> array: .. note:: Conforming implementations are allowed to treat special cases involving complex floating-point operands more carefully than as described in this specification. - - .. note:: - By convention, the branch cut of the natural logarithm is the negative real axis :math:`(-\infty, 0)`. - - The natural logarithm is a continuous function from above the branch cut, taking into account the sign of the imaginary component. As special cases involving complex floating-point operands should be handled according to ``exp(x2*log(x1))``, exponentiation has the same branch cut for ``x1`` as the natural logarithm (see :func:`~array_api.log`). - - *Note: branch cuts have provisional status* (see :ref:`branch-cuts`). - - Parameters - ---------- - x1: array - first input array whose elements correspond to the exponentiation base. Should have a numeric data type. - x2: array - second input array whose elements correspond to the exponentiation exponent. Must be compatible with ``x1`` (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`. """ @@ -1790,6 +1876,21 @@ def remainder(x1: array, x2: array, /) -> array: .. note:: For input arrays which promote to an integer data type, the result of division by zero is unspecified and thus implementation-defined. + Parameters + ---------- + x1: array + dividend input array. Should have a real-valued data type. + x2: array + divisor input array. Must be compatible with ``x1`` (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 ``x2_i``. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + **Special cases** .. note:: @@ -1817,18 +1918,6 @@ def remainder(x1: array, x2: array, /) -> array: - If ``x1_i`` is a negative (i.e., less than ``0``) finite number and ``x2_i`` is ``+infinity``, the result is ``x2_i``. (**note**: this results matches Python behavior.) - If ``x1_i`` is a negative (i.e., less than ``0``) finite number and ``x2_i`` is ``-infinity``, the result is ``x1_i``. (**note**: this result matches Python behavior.) - In the remaining cases, the result must match that of the Python ``%`` operator. - - Parameters - ---------- - x1: array - dividend input array. Should have a real-valued data type. - x2: array - divisor input array. Must be compatible with ``x1`` (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 ``x2_i``. The returned array must have a data type determined by :ref:`type-promotion`. """ @@ -1841,6 +1930,19 @@ def round(x: array, /) -> array: Rounded real and imaginary components must be equal to their equivalent rounded real-valued floating-point counterparts (i.e., for complex-valued ``x``, ``real(round(x))`` must equal ``round(real(x)))`` and ``imag(round(x))`` must equal ``round(imag(x))``). + Parameters + ---------- + x: array + input array. Should have a numeric data type. + + Returns + ------- + out: array + an array containing the rounded result for each element in ``x``. The returned array must have the same data type as ``x``. + + Notes + ----- + **Special cases** .. note:: @@ -1856,16 +1958,6 @@ def round(x: array, /) -> array: - If ``x_i`` is ``-0``, the result is ``-0``. - If ``x_i`` is ``NaN``, the result is ``NaN``. - If two integers are equally close to ``x_i``, the result is the even integer closest to ``x_i``. - - Parameters - ---------- - x: array - input array. Should have a numeric data type. - - Returns - ------- - out: array - an array containing the rounded result for each element in ``x``. The returned array must have the same data type as ``x``. """ @@ -1883,6 +1975,19 @@ def sign(x: array, /) -> array: where :math:`|x_i|` is the absolute value of :math:`x_i`. + Parameters + ---------- + x: array + input array. Should have a numeric data type. + + Returns + ------- + out: array + an array containing the evaluated result for each element in ``x``. The returned array must have the same data type as ``x``. + + Notes + ----- + **Special cases** For real-valued operands, @@ -1897,16 +2002,6 @@ def sign(x: array, /) -> array: - If ``a`` is either ``-0`` or ``+0`` and ``b`` is either ``-0`` or ``+0``, the result is ``0 + 0j``. - If ``a`` is ``NaN`` or ``b`` is ``NaN``, the result is ``NaN + NaN j``. - In the remaining cases, special cases must be handled according to the rules of complex number division (see :func:`~array_api.divide`). - - Parameters - ---------- - x: array - input array. Should have a numeric data type. - - Returns - ------- - out: array - an array containing the evaluated result for each element in ``x``. The returned array must have the same data type as ``x``. """ @@ -1916,17 +2011,6 @@ def sin(x: array, /) -> array: Each element ``x_i`` is assumed to be expressed in radians. - **Special cases** - - For real-valued floating-point operands, - - - If ``x_i`` is ``NaN``, the result is ``NaN``. - - If ``x_i`` is ``+0``, the result is ``+0``. - - If ``x_i`` is ``-0``, the result is ``-0``. - - If ``x_i`` is either ``+infinity`` or ``-infinity``, the result is ``NaN``. - - For complex floating-point operands, special cases must be handled as if the operation is implemented as ``-1j * sinh(x*1j)``. - .. note:: The sine is an entire function on the complex plane and has no branch cuts. @@ -1947,6 +2031,20 @@ def sin(x: array, /) -> array: ------- out: array an array containing the sine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + + **Special cases** + + For real-valued floating-point operands, + + - If ``x_i`` is ``NaN``, the result is ``NaN``. + - If ``x_i`` is ``+0``, the result is ``+0``. + - If ``x_i`` is ``-0``, the result is ``-0``. + - If ``x_i`` is either ``+infinity`` or ``-infinity``, the result is ``NaN``. + + For complex floating-point operands, special cases must be handled as if the operation is implemented as ``-1j * sinh(x*1j)``. """ @@ -1959,6 +2057,22 @@ def sinh(x: array, /) -> array: .. math:: \operatorname{sinh}(x) = \frac{e^x - e^{-x}}{2} + .. note:: + The hyperbolic sine is an entire function in the complex plane and has no branch cuts. The function is periodic, with period :math:`2\pi j`, with respect to the imaginary component. + + Parameters + ---------- + x: array + input array whose elements each represent a hyperbolic angle. Should have a floating-point data type. + + Returns + ------- + out: array + an array containing the hyperbolic sine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + **Special cases** .. note:: @@ -1991,19 +2105,6 @@ def sinh(x: array, /) -> array: - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. where ``cis(v)`` is ``cos(v) + sin(v)*1j``. - - .. note:: - The hyperbolic sine is an entire function in the complex plane and has no branch cuts. The function is periodic, with period :math:`2\pi j`, with respect to the imaginary component. - - Parameters - ---------- - x: array - input array whose elements each represent a hyperbolic angle. Should have a floating-point data type. - - Returns - ------- - out: array - an array containing the hyperbolic sine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. """ @@ -2016,10 +2117,6 @@ def square(x: array, /) -> array: .. math:: x_i^2 = x_i \cdot x_i - **Special cases** - - For floating-point operands, special cases must be handled as if the operation is implemented as ``x * x`` (see :func:`~array_api.multiply`). - Parameters ---------- x: array @@ -2029,6 +2126,13 @@ def square(x: array, /) -> array: ------- out: array an array containing the evaluated result for each element in ``x``. The returned array must have a data type determined by :ref:`type-promotion`. + + Notes + ----- + + **Special cases** + + For floating-point operands, special cases must be handled as if the operation is implemented as ``x * x`` (see :func:`~array_api.multiply`). """ @@ -2039,28 +2143,6 @@ def sqrt(x: array, /) -> array: .. note:: After rounding, each result must be indistinguishable from the infinitely precise result (as required by IEEE 754). - **Special cases** - - For real-valued floating-point operands, - - - If ``x_i`` is ``NaN``, the result is ``NaN``. - - If ``x_i`` is less than ``0``, the result is ``NaN``. - - If ``x_i`` is ``+0``, the result is ``+0``. - - If ``x_i`` is ``-0``, the result is ``-0``. - - If ``x_i`` is ``+infinity``, the result is ``+infinity``. - - For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and - - - If ``a`` is either ``+0`` or ``-0`` and ``b`` is ``+0``, the result is ``+0 + 0j``. - - If ``a`` is any value (including ``NaN``) and ``b`` is ``+infinity``, the result is ``+infinity + infinity j``. - - If ``a`` is a finite number and ``b`` is ``NaN``, the result is ``NaN + NaN j``. - - If ``a`` ``-infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``NaN + NaN j``. - - If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+0 + infinity j``. - - If ``a`` is ``-infinity`` and ``b`` is ``NaN``, the result is ``NaN + infinity j`` (sign of the imaginary component is unspecified). - - If ``a`` is ``+infinity`` and ``b`` is ``NaN``, the result is ``+infinity + NaN j``. - - If ``a`` is ``NaN`` and ``b`` is any value, the result is ``NaN + NaN j``. - - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. - .. note:: For complex floating-point operands, ``sqrt(conj(x))`` must equal ``conj(sqrt(x))``. @@ -2082,6 +2164,31 @@ def sqrt(x: array, /) -> array: ------- out: array an array containing the square root of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + + **Special cases** + + For real-valued floating-point operands, + + - If ``x_i`` is ``NaN``, the result is ``NaN``. + - If ``x_i`` is less than ``0``, the result is ``NaN``. + - If ``x_i`` is ``+0``, the result is ``+0``. + - If ``x_i`` is ``-0``, the result is ``-0``. + - If ``x_i`` is ``+infinity``, the result is ``+infinity``. + + For complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and + + - If ``a`` is either ``+0`` or ``-0`` and ``b`` is ``+0``, the result is ``+0 + 0j``. + - If ``a`` is any value (including ``NaN``) and ``b`` is ``+infinity``, the result is ``+infinity + infinity j``. + - If ``a`` is a finite number and ``b`` is ``NaN``, the result is ``NaN + NaN j``. + - If ``a`` ``-infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``NaN + NaN j``. + - If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+0 + infinity j``. + - If ``a`` is ``-infinity`` and ``b`` is ``NaN``, the result is ``NaN + infinity j`` (sign of the imaginary component is unspecified). + - If ``a`` is ``+infinity`` and ``b`` is ``NaN``, the result is ``+infinity + NaN j``. + - If ``a`` is ``NaN`` and ``b`` is any value, the result is ``NaN + NaN j``. + - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. """ @@ -2111,17 +2218,6 @@ def tan(x: array, /) -> array: Each element ``x_i`` is assumed to be expressed in radians. - **Special cases** - - For real-valued floating-point operands, - - - If ``x_i`` is ``NaN``, the result is ``NaN``. - - If ``x_i`` is ``+0``, the result is ``+0``. - - If ``x_i`` is ``-0``, the result is ``-0``. - - If ``x_i`` is either ``+infinity`` or ``-infinity``, the result is ``NaN``. - - For complex floating-point operands, special cases must be handled as if the operation is implemented as ``-1j * tanh(x*1j)``. - .. note:: Tangent is an analytical function on the complex plane and has no branch cuts. The function is periodic, with period :math:`\pi j`, with respect to the real component and has first order poles along the real line at coordinates :math:`(\pi (\frac{1}{2} + n), 0)`. However, IEEE 754 binary floating-point representation cannot represent the value :math:`\pi / 2` exactly, and, thus, no argument value is possible for which a pole error occurs. @@ -2142,6 +2238,20 @@ def tan(x: array, /) -> array: ------- out: array an array containing the tangent of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + + **Special cases** + + For real-valued floating-point operands, + + - If ``x_i`` is ``NaN``, the result is ``NaN``. + - If ``x_i`` is ``+0``, the result is ``+0``. + - If ``x_i`` is ``-0``, the result is ``-0``. + - If ``x_i`` is either ``+infinity`` or ``-infinity``, the result is ``NaN``. + + For complex floating-point operands, special cases must be handled as if the operation is implemented as ``-1j * tanh(x*1j)``. """ @@ -2156,6 +2266,22 @@ def tanh(x: array, /) -> array: where :math:`\operatorname{sinh}(x)` is the hyperbolic sine and :math:`\operatorname{cosh}(x)` is the hyperbolic cosine. + .. note:: + The hyperbolic tangent is an analytical function on the complex plane and has no branch cuts. The function is periodic, with period :math:`\pi j`, with respect to the imaginary component and has first order poles along the imaginary line at coordinates :math:`(0, \pi (\frac{1}{2} + n))`. However, IEEE 754 binary floating-point representation cannot represent :math:`\pi / 2` exactly, and, thus, no argument value is possible such that a pole error occurs. + + Parameters + ---------- + x: array + input array whose elements each represent a hyperbolic angle. Should have a floating-point data type. + + Returns + ------- + out: array + an array containing the hyperbolic tangent of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. + + Notes + ----- + **Special cases** .. note:: @@ -2190,25 +2316,25 @@ def tanh(x: array, /) -> array: For historical reasons stemming from the C standard, array libraries may not return the expected result when ``a`` is ``+0`` and ``b`` is either ``+infinity`` or ``NaN``. The result should be ``+0 + NaN j`` in both cases; however, for libraries compiled against older C versions, the result may be ``NaN + NaN j``. Array libraries are not required to patch these older C versions, and, thus, users are advised that results may vary across array library implementations for these special cases. + """ - .. note:: - The hyperbolic tangent is an analytical function on the complex plane and has no branch cuts. The function is periodic, with period :math:`\pi j`, with respect to the imaginary component and has first order poles along the imaginary line at coordinates :math:`(0, \pi (\frac{1}{2} + n))`. However, IEEE 754 binary floating-point representation cannot represent :math:`\pi / 2` exactly, and, thus, no argument value is possible such that a pole error occurs. + +def trunc(x: array, /) -> array: + """ + Rounds each element ``x_i`` of the input array ``x`` to the nearest integer-valued number that is closer to zero than ``x_i``. Parameters ---------- x: array - input array whose elements each represent a hyperbolic angle. Should have a floating-point data type. + input array. Should have a real-valued data type. Returns ------- out: array - an array containing the hyperbolic tangent of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`. - """ - + an array containing the rounded result for each element in ``x``. The returned array must have the same data type as ``x``. -def trunc(x: array, /) -> array: - """ - Rounds each element ``x_i`` of the input array ``x`` to the nearest integer-valued number that is closer to zero than ``x_i``. + Notes + ----- **Special cases** @@ -2221,16 +2347,6 @@ def trunc(x: array, /) -> array: - If ``x_i`` is ``+0``, the result is ``+0``. - If ``x_i`` is ``-0``, the result is ``-0``. - If ``x_i`` is ``NaN``, the result is ``NaN``. - - Parameters - ---------- - x: array - input array. Should have a real-valued data type. - - Returns - ------- - out: array - an array containing the rounded result for each element in ``x``. The returned array must have the same data type as ``x``. """ diff --git a/spec/API_specification/array_api/linalg.py b/spec/API_specification/array_api/linalg.py index 65e25bc5e..b040251dd 100644 --- a/spec/API_specification/array_api/linalg.py +++ b/spec/API_specification/array_api/linalg.py @@ -606,14 +606,6 @@ def trace(x: array, /, *, offset: int = 0, dtype: Optional[dtype] = None) -> arr """ Returns the sum along the specified diagonals of a matrix (or a stack of matrices) ``x``. - **Special Cases** - - Let ``N`` equal the number of elements over which to compute the sum. - - - If ``N`` is ``0``, the sum is ``0`` (i.e., the empty sum). - - For both real-valued and complex floating-point operands, special cases must be handled as if the operation is implemented by successive application of :func:`~array_api.add`. - Parameters ---------- x: array @@ -650,6 +642,17 @@ def trace(x: array, /, *, offset: int = 0, dtype: Optional[dtype] = None) -> arr out[i, j, k, ..., l] = trace(a[i, j, k, ..., l, :, :]) The returned array must have a data type as described by the ``dtype`` parameter above. + + Notes + ----- + + **Special Cases** + + Let ``N`` equal the number of elements over which to compute the sum. + + - If ``N`` is ``0``, the sum is ``0`` (i.e., the empty sum). + + For both real-valued and complex floating-point operands, special cases must be handled as if the operation is implemented by successive application of :func:`~array_api.add`. """ diff --git a/spec/API_specification/array_api/statistical_functions.py b/spec/API_specification/array_api/statistical_functions.py index 24ef810af..787faeeb9 100644 --- a/spec/API_specification/array_api/statistical_functions.py +++ b/spec/API_specification/array_api/statistical_functions.py @@ -17,12 +17,6 @@ def max( .. note:: 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`). - **Special Cases** - - For floating-point operands, - - - If ``x_i`` is ``NaN``, the maximum value is ``NaN`` (i.e., ``NaN`` values propagate). - Parameters ---------- x: array @@ -36,6 +30,15 @@ def max( ------- out: array if the maximum value was computed over the entire array, a zero-dimensional array containing the maximum value; otherwise, a non-zero-dimensional array containing the maximum values. The returned array must have the same data type as ``x``. + + Notes + ----- + + **Special Cases** + + For floating-point operands, + + - If ``x_i`` is ``NaN``, the maximum value is ``NaN`` (i.e., ``NaN`` values propagate). """ @@ -49,13 +52,6 @@ def mean( """ Calculates the arithmetic mean of the input array ``x``. - **Special Cases** - - Let ``N`` equal the number of elements over which to compute the arithmetic mean. - - - If ``N`` is ``0``, the arithmetic mean is ``NaN``. - - If ``x_i`` is ``NaN``, the arithmetic mean is ``NaN`` (i.e., ``NaN`` values propagate). - Parameters ---------- x: array @@ -72,6 +68,16 @@ def mean( .. note:: While this specification recommends that this function only accept input arrays having a real-valued floating-point data type, specification-compliant array libraries may choose to accept input arrays having an integer data type. While mixed data type promotion is implementation-defined, if the input array ``x`` has an integer data type, the returned array must have the default real-valued floating-point data type. + + Notes + ----- + + **Special Cases** + + Let ``N`` equal the number of elements over which to compute the arithmetic mean. + + - If ``N`` is ``0``, the arithmetic mean is ``NaN``. + - If ``x_i`` is ``NaN``, the arithmetic mean is ``NaN`` (i.e., ``NaN`` values propagate). """ @@ -91,12 +97,6 @@ def min( .. note:: 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`). - **Special Cases** - - For floating-point operands, - - - If ``x_i`` is ``NaN``, the minimum value is ``NaN`` (i.e., ``NaN`` values propagate). - Parameters ---------- x: array @@ -110,6 +110,15 @@ def min( ------- out: array if the minimum value was computed over the entire array, a zero-dimensional array containing the minimum value; otherwise, a non-zero-dimensional array containing the minimum values. The returned array must have the same data type as ``x``. + + Notes + ----- + + **Special Cases** + + For floating-point operands, + + - If ``x_i`` is ``NaN``, the minimum value is ``NaN`` (i.e., ``NaN`` values propagate). """ @@ -124,14 +133,6 @@ def prod( """ Calculates the product of input array ``x`` elements. - **Special Cases** - - Let ``N`` equal the number of elements over which to compute the product. - - - If ``N`` is ``0``, the product is `1` (i.e., the empty product). - - For both real-valued and complex floating-point operands, special cases must be handled as if the operation is implemented by successive application of :func:`~array_api.multiply`. - Parameters ---------- x: array @@ -159,6 +160,17 @@ def prod( ------- out: array if the product was computed over the entire array, a zero-dimensional array containing the product; otherwise, a non-zero-dimensional array containing the products. The returned array must have a data type as described by the ``dtype`` parameter above. + + Notes + ----- + + **Special Cases** + + Let ``N`` equal the number of elements over which to compute the product. + + - If ``N`` is ``0``, the product is `1` (i.e., the empty product). + + For both real-valued and complex floating-point operands, special cases must be handled as if the operation is implemented by successive application of :func:`~array_api.multiply`. """ @@ -173,13 +185,6 @@ def std( """ Calculates the standard deviation of the input array ``x``. - **Special Cases** - - Let ``N`` equal the number of elements over which to compute the standard deviation. - - - If ``N - correction`` is less than or equal to ``0``, the standard deviation is ``NaN``. - - If ``x_i`` is ``NaN``, the standard deviation is ``NaN`` (i.e., ``NaN`` values propagate). - Parameters ---------- x: array @@ -198,6 +203,16 @@ def std( .. note:: While this specification recommends that this function only accept input arrays having a real-valued floating-point data type, specification-compliant array libraries may choose to accept input arrays having an integer data type. While mixed data type promotion is implementation-defined, if the input array ``x`` has an integer data type, the returned array must have the default real-valued floating-point data type. + + Notes + ----- + + **Special Cases** + + Let ``N`` equal the number of elements over which to compute the standard deviation. + + - If ``N - correction`` is less than or equal to ``0``, the standard deviation is ``NaN``. + - If ``x_i`` is ``NaN``, the standard deviation is ``NaN`` (i.e., ``NaN`` values propagate). """ @@ -212,14 +227,6 @@ def sum( """ Calculates the sum of the input array ``x``. - **Special Cases** - - Let ``N`` equal the number of elements over which to compute the sum. - - - If ``N`` is ``0``, the sum is ``0`` (i.e., the empty sum). - - For both real-valued and complex floating-point operands, special cases must be handled as if the operation is implemented by successive application of :func:`~array_api.add`. - Parameters ---------- x: array @@ -247,6 +254,17 @@ def sum( ------- out: array if the sum was computed over the entire array, a zero-dimensional array containing the sum; otherwise, an array containing the sums. The returned array must have a data type as described by the ``dtype`` parameter above. + + Notes + ----- + + **Special Cases** + + Let ``N`` equal the number of elements over which to compute the sum. + + - If ``N`` is ``0``, the sum is ``0`` (i.e., the empty sum). + + For both real-valued and complex floating-point operands, special cases must be handled as if the operation is implemented by successive application of :func:`~array_api.add`. """ @@ -261,13 +279,6 @@ def var( """ Calculates the variance of the input array ``x``. - **Special Cases** - - Let ``N`` equal the number of elements over which to compute the variance. - - - If ``N - correction`` is less than or equal to ``0``, the variance is ``NaN``. - - If ``x_i`` is ``NaN``, the variance is ``NaN`` (i.e., ``NaN`` values propagate). - Parameters ---------- x: array @@ -287,6 +298,16 @@ def var( .. note:: While this specification recommends that this function only accept input arrays having a real-valued floating-point data type, specification-compliant array libraries may choose to accept input arrays having an integer data type. While mixed data type promotion is implementation-defined, if the input array ``x`` has an integer data type, the returned array must have the default real-valued floating-point data type. + + Notes + ----- + + **Special Cases** + + Let ``N`` equal the number of elements over which to compute the variance. + + - If ``N - correction`` is less than or equal to ``0``, the variance is ``NaN``. + - If ``x_i`` is ``NaN``, the variance is ``NaN`` (i.e., ``NaN`` values propagate). """