From bc2795f4ae941927cb2508c0559322011a0a34d0 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 6 Nov 2023 00:21:46 -0800 Subject: [PATCH 1/3] feat: add `hypot` specification for computing the square root of the sum of squares --- .../elementwise_functions.rst | 1 + .../_draft/elementwise_functions.py | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/spec/draft/API_specification/elementwise_functions.rst b/spec/draft/API_specification/elementwise_functions.rst index 8048eb38a..d8efcb729 100644 --- a/spec/draft/API_specification/elementwise_functions.rst +++ b/spec/draft/API_specification/elementwise_functions.rst @@ -45,6 +45,7 @@ Objects in API floor_divide greater greater_equal + hypot imag isfinite isinf diff --git a/src/array_api_stubs/_draft/elementwise_functions.py b/src/array_api_stubs/_draft/elementwise_functions.py index faaa9213b..58612d46d 100644 --- a/src/array_api_stubs/_draft/elementwise_functions.py +++ b/src/array_api_stubs/_draft/elementwise_functions.py @@ -27,6 +27,7 @@ "floor_divide", "greater", "greater_equal", + "hypot", "imag", "isfinite", "isinf", @@ -1331,6 +1332,48 @@ def greater_equal(x1: array, x2: array, /) -> array: """ +def hypot(x1: array, x2: array, /) -> array: + r""" + Computes the square root of the sum of squares for each element ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input array ``x2``. + + .. note:: + The value computed by this function may be interpreted as the length of the hypotenuse of a right-angled triangle with sides of length ``x1_i`` and ``x2_i``, the distance of a point ``(x1_i, x2_i)`` from the origin ``(0, 0)``, or the magnitude of a complex number ``x1_i + x2_i * 1j``. + + Parameters + ---------- + x1: array + first input array. Should have a real-valued floating-point data type. + x2: array + second input array. Must be compatible with ``x1`` (see :ref:`broadcasting`). Should have a real-valued floating-point data type. + + Returns + ------- + 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 real-valued floating-point operands, + + - If ``x1_i`` is ``+infinity`` or ``-infinity`` and ``x2_i`` is any value, including ``NaN``, the result is ``+infinity``. + - If ``x2_i`` is ``+infinity`` or ``-infinity`` and ``x1_i`` is any value, including ``NaN``, the result is ``+infinity``. + - If ``x1_i`` is either ``+0`` or ``-0``, the result is equivalent to ``abs(x2_i)``. + - If ``x2_i`` is either ``+0`` or ``-0``, the result is equivalent to ``abs(x1_i)``. + - If ``x1_i`` is a finite number or ``NaN`` and ``x2_i`` is ``NaN``, the result is ``NaN``. + - If ``x2_i`` is a finite number or ``NaN`` and ``x1_i`` is ``NaN``, the result is ``NaN``. + - Underflow may only occur when both arguments are subnormal and the correct result is also subnormal. + + .. note:: + For real-valued floating-point operands, ``hypot(x1, x2)`` must equal ``hypot(x2, x1)``, ``hypot(x1, -x2)``, ``hypot(-x1, x2)``, and ``hypot(-x1, -x2)``. + + .. note:: + The purpose of this function is to avoid underflow and overflow during intermediate stages of computation. Accordingly, conforming implementations should not use naive implementations. + """ + + def imag(x: array, /) -> array: """ Returns the imaginary component of a complex number for each element ``x_i`` of the input array ``x``. From d32ecb668343fdd091155e94221bc995b84d3690 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Tue, 20 Feb 2024 23:08:13 -0800 Subject: [PATCH 2/3] docs: add note concerning subnormal numbers --- src/array_api_stubs/_draft/elementwise_functions.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/array_api_stubs/_draft/elementwise_functions.py b/src/array_api_stubs/_draft/elementwise_functions.py index 58612d46d..282a70f31 100644 --- a/src/array_api_stubs/_draft/elementwise_functions.py +++ b/src/array_api_stubs/_draft/elementwise_functions.py @@ -1366,11 +1366,14 @@ def hypot(x1: array, x2: array, /) -> array: - If ``x2_i`` is a finite number or ``NaN`` and ``x1_i`` is ``NaN``, the result is ``NaN``. - Underflow may only occur when both arguments are subnormal and the correct result is also subnormal. - .. note:: - For real-valued floating-point operands, ``hypot(x1, x2)`` must equal ``hypot(x2, x1)``, ``hypot(x1, -x2)``, ``hypot(-x1, x2)``, and ``hypot(-x1, -x2)``. + For real-valued floating-point operands, ``hypot(x1, x2)`` must equal ``hypot(x2, x1)``, ``hypot(x1, -x2)``, ``hypot(-x1, x2)``, and ``hypot(-x1, -x2)``. + + The purpose of this function is to avoid underflow and overflow during intermediate stages of computation. Accordingly, conforming implementations should not use naive implementations. .. note:: - The purpose of this function is to avoid underflow and overflow during intermediate stages of computation. Accordingly, conforming implementations should not use naive implementations. + IEEE 754-2019 requires support for subnormal (a.k.a., denormal) numbers, which are useful for supporting gradual underflow. However, hardware support for subnormal numbers is not universal, and many platforms (e.g., accelerators) and compilers support toggling denormals-are-zero (DAZ) and/or flush-to-zero (FTZ) behavior to increase performance and to guard against timing attacks. + + Accordingly, conforming implementations may vary in their support for subnormal numbers. """ From 52cc4993036d99252c58f269669330bff48c7e8c Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Tue, 20 Feb 2024 23:09:30 -0800 Subject: [PATCH 3/3] docs: move note --- src/array_api_stubs/_draft/elementwise_functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/array_api_stubs/_draft/elementwise_functions.py b/src/array_api_stubs/_draft/elementwise_functions.py index 282a70f31..3dd1f1e30 100644 --- a/src/array_api_stubs/_draft/elementwise_functions.py +++ b/src/array_api_stubs/_draft/elementwise_functions.py @@ -1354,6 +1354,8 @@ def hypot(x1: array, x2: array, /) -> array: Notes ----- + The purpose of this function is to avoid underflow and overflow during intermediate stages of computation. Accordingly, conforming implementations should not use naive implementations. + **Special Cases** For real-valued floating-point operands, @@ -1368,8 +1370,6 @@ def hypot(x1: array, x2: array, /) -> array: For real-valued floating-point operands, ``hypot(x1, x2)`` must equal ``hypot(x2, x1)``, ``hypot(x1, -x2)``, ``hypot(-x1, x2)``, and ``hypot(-x1, -x2)``. - The purpose of this function is to avoid underflow and overflow during intermediate stages of computation. Accordingly, conforming implementations should not use naive implementations. - .. note:: IEEE 754-2019 requires support for subnormal (a.k.a., denormal) numbers, which are useful for supporting gradual underflow. However, hardware support for subnormal numbers is not universal, and many platforms (e.g., accelerators) and compilers support toggling denormals-are-zero (DAZ) and/or flush-to-zero (FTZ) behavior to increase performance and to guard against timing attacks.