From 83dc7ffb35f4e8378633aa5c8ddfc68caa096ac8 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 21 Nov 2022 03:53:31 -0800 Subject: [PATCH 1/4] Add complex number support to `log` --- .../array_api/elementwise_functions.py | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/spec/API_specification/array_api/elementwise_functions.py b/spec/API_specification/array_api/elementwise_functions.py index 78a60de9c..e008c8fab 100644 --- a/spec/API_specification/array_api/elementwise_functions.py +++ b/spec/API_specification/array_api/elementwise_functions.py @@ -904,12 +904,12 @@ def less_equal(x1: array, x2: array, /) -> array: """ def log(x: array, /) -> array: - """ - Calculates an implementation-dependent approximation to the natural (base ``e``) logarithm, having domain ``[0, +infinity]`` and codomain ``[-infinity, +infinity]``, for each element ``x_i`` of the input array ``x``. + r""" + Calculates an implementation-dependent approximation to the natural (base ``e``) logarithm for each element ``x_i`` of the input array ``x``. **Special cases** - For floating-point operands, + 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``. @@ -917,6 +917,36 @@ def log(x: array, /) -> array: - 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 ``-0`` and ``b`` is ``+0``, the result is ``-infinity + πj``. + - If ``a`` is ``+0`` and ``b`` is ``+0``, the result is ``-infinity + 0j``. + - If ``a`` is a 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 + π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``. + + .. note:: + The natural logarithm of a complex number :math:`z` with polar coordinates :math:`(r,\theta)` equals :math:`\ln r + (θ+ 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:`[-i\pi, +i\pi]` along the imaginary axis and mathematically unbounded along the real axis. + + *Note: branch cuts have provisional status* (see :ref:`branch-cuts`). + Parameters ---------- x: array From be87641c4f4e9e05d03327db4e77a5a84653e13c Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 21 Nov 2022 03:55:32 -0800 Subject: [PATCH 2/4] Update accepted dtypes --- spec/API_specification/array_api/elementwise_functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/API_specification/array_api/elementwise_functions.py b/spec/API_specification/array_api/elementwise_functions.py index e008c8fab..d5fe60492 100644 --- a/spec/API_specification/array_api/elementwise_functions.py +++ b/spec/API_specification/array_api/elementwise_functions.py @@ -950,12 +950,12 @@ def log(x: array, /) -> array: Parameters ---------- x: array - input array. Should have a real-valued floating-point data type. + 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 real-valued floating-point data type determined by :ref:`type-promotion`. + 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: From 062832dd7981b06ac178da25a3f722c92918448d Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 21 Nov 2022 03:59:53 -0800 Subject: [PATCH 3/4] Update note --- spec/API_specification/array_api/elementwise_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/API_specification/array_api/elementwise_functions.py b/spec/API_specification/array_api/elementwise_functions.py index d5fe60492..e68a77abf 100644 --- a/spec/API_specification/array_api/elementwise_functions.py +++ b/spec/API_specification/array_api/elementwise_functions.py @@ -943,7 +943,7 @@ def log(x: array, /) -> array: 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:`[-i\pi, +i\pi]` along the imaginary axis and mathematically unbounded along the real axis. + 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`). From d0a8ec501712ad7adfb270be60506b333668028c Mon Sep 17 00:00:00 2001 From: Athan Date: Thu, 1 Dec 2022 00:44:57 -0800 Subject: [PATCH 4/4] Fix equation Co-authored-by: Aaron Meurer --- spec/API_specification/array_api/elementwise_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/API_specification/array_api/elementwise_functions.py b/spec/API_specification/array_api/elementwise_functions.py index 120ab0b3a..2fd5dce6a 100644 --- a/spec/API_specification/array_api/elementwise_functions.py +++ b/spec/API_specification/array_api/elementwise_functions.py @@ -933,7 +933,7 @@ def log(x: array, /) -> array: - If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``. .. note:: - The natural logarithm of a complex number :math:`z` with polar coordinates :math:`(r,\theta)` equals :math:`\ln r + (θ+ 2n\pi)j` with principal value :math:`\ln r + \theta j`. + 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))``.