[Numpy-discussion] Extend ldexp to handle complex inputs

2024-09-25 Thread Carlos Martin
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 
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.
___
NumPy-Discussion mailing list -- numpy-discussion@python.org
To unsubscribe send an email to numpy-discussion-le...@python.org
https://mail.python.org/mailman3/lists/numpy-discussion.python.org/
Member address: arch...@mail-archive.com


[Numpy-discussion] Re: Extend ldexp to handle complex inputs

2024-09-25 Thread Marten van Kerkwijk
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"  writes:

> 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 
> 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.
> ___
> NumPy-Discussion mailing list -- numpy-discussion@python.org
> To unsubscribe send an email to numpy-discussion-le...@python.org
> https://mail.python.org/mailman3/lists/numpy-discussion.python.org/
> Member address: m...@astro.utoronto.ca
___
NumPy-Discussion mailing list -- numpy-discussion@python.org
To unsubscribe send an email to numpy-discussion-le...@python.org
https://mail.python.org/mailman3/lists/numpy-discussion.python.org/
Member address: arch...@mail-archive.com