Extend ldexp to handle complex inputs

Currently, [ldexp](https://numpy.org/doc/stable/reference/generated/numpy.ldexp.html) throws a TypeError on a complex input: ```python3 import numpy as np def naive_ldexp(x, n): return x * 2**n def new_ldexp(x, n): if np.iscomplex(x): y = np.empty_like(x) y.real = np.ldexp(x.real, n) y.imag = np.ldexp(x.imag, n) return y else: return np.ldexp(x, n) def main(): x = 2.2 + 3.3j n = 3 print(naive_ldexp(x, n)) print(new_ldexp(x, n)) print(np.ldexp(x, n)) if __name__ == "__main__": main() ``` ``` (17.6+26.4j) (17.6+26.4j) Traceback (most recent call last): File "test.py", line 34, in <module> main() File "test.py", line 30, in main print(np.ldexp(x, n)) ^^^^^^^^^^^^^^ TypeError: ufunc 'ldexp' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe'' ``` This can easily be solved by applying ldexp to the real and imaginary parts of the input, as shown in the function new_ldexp above.

Probably good to think first what the inverse function, np.frexp, should do for complex numbers. I guess the choices are: 1. Remove the largest exponent of real/imaginary, and give a complex mantissa, in which only one of the real or imaginary components is guaranteed to have its absolute value be in the interval [0.5, 1) (but for both the claim in the np.frexp docstring that they are in the interval (-1, 1) would continue to hold). 2. Do real, imaginary separately. 3. Insists on 0.5 < |z| < 1. The first option seems the most sensible, in which case the suggested extension for ldexp makes sense. -- Marten "Carlos Martin" <cgmartin@andrew.cmu.edu> writes:

Probably good to think first what the inverse function, np.frexp, should do for complex numbers. I guess the choices are: 1. Remove the largest exponent of real/imaginary, and give a complex mantissa, in which only one of the real or imaginary components is guaranteed to have its absolute value be in the interval [0.5, 1) (but for both the claim in the np.frexp docstring that they are in the interval (-1, 1) would continue to hold). 2. Do real, imaginary separately. 3. Insists on 0.5 < |z| < 1. The first option seems the most sensible, in which case the suggested extension for ldexp makes sense. -- Marten "Carlos Martin" <cgmartin@andrew.cmu.edu> writes:
participants (2)
-
Carlos Martin
-
Marten van Kerkwijk