Thanks to numba.vectorize in recent versions of numba, creating a numpy universal function for the task is very easy:
@numba.vectorize([numba.float64(numba.complex128),numba.float32(numba.complex64)])
def abs2(x):
return x.real**2 + x.imag**2
On my machine, I find a threefold speedup compared to a pure-numpy version that creates intermediate arrays:
>>> x = np.random.randn(10000).view('c16')
>>> y = abs2(x)
>>> np.all(y == x.real**2 + x.imag**2) # exactly equal, being the same operation
True
>>> %timeit np.abs(x)**2
10000 loops, best of 3: 81.4 µs per loop
>>> %timeit x.real**2 + x.imag**2
100000 loops, best of 3: 12.7 µs per loop
>>> %timeit abs2(x)
100000 loops, best of 3: 4.6 µs per loop
Answer from burnpanck on Stack OverflowThanks to numba.vectorize in recent versions of numba, creating a numpy universal function for the task is very easy:
@numba.vectorize([numba.float64(numba.complex128),numba.float32(numba.complex64)])
def abs2(x):
return x.real**2 + x.imag**2
On my machine, I find a threefold speedup compared to a pure-numpy version that creates intermediate arrays:
>>> x = np.random.randn(10000).view('c16')
>>> y = abs2(x)
>>> np.all(y == x.real**2 + x.imag**2) # exactly equal, being the same operation
True
>>> %timeit np.abs(x)**2
10000 loops, best of 3: 81.4 µs per loop
>>> %timeit x.real**2 + x.imag**2
100000 loops, best of 3: 12.7 µs per loop
>>> %timeit abs2(x)
100000 loops, best of 3: 4.6 µs per loop
EDIT: this solution has twice the minimum memory requirement, and is just marginally faster. The discussion in the comments is good for reference however.
Here's a faster solution, with the result stored in res:
import numpy as np
res = arr.conjugate()
np.multiply(arr,res,out=res)
where we exploited the property of the abs of a complex number, i.e. abs(z) = sqrt(z*z.conjugate), so that abs(z)**2 = z*z.conjugate
sqrt(Re(z)**2 + Im(z)**2)
for z = a + ib this becomes:
sqrt(a*a + b*b)
It's just the euclidean norm. You have to sum the square of real part and imaginary part (without the i) and do the sqrt of it.

https://www.varsitytutors.com/hotmath/hotmath_help/topics/absolute-value-complex-number
np.abs gives magnitude of complex number i.e. sqrt(a^2 + b^2) in your case it's sqrt(8).
https://numpy.org/doc/stable/reference/generated/numpy.absolute.html
"Maximum" is ambiguous when it comes to complex values. The complex value itself doesn't have a min or max. Which is greater, 1+0j or 0+1j? What about 1+0j and 0+.5j? The answer to these questions determines what exactly what you want to do.
You can get the maximum real part (max(1+0j, 0+10j) == 1), maximum imaginary part (max(10+0j, 0+1j) == 1), maximum absolute value (max(10+0j, 0+1j) == 10, max(1+0j, 0+10j) == 10), complex value with the maximum real part (max(1+0j, 0+10j) == 1+0j), complex value with the maximum imaginary part (max(10+0j, 0+1j) == 0+1j), or complex value with the maximum absolute value (max(10+0j, 0+1j) == 10+0j, max(1+0j, 0+10j) == 0+10j). All are possible with numpy arrays.
The default in numpy (arr.max() or np.max(arr) when arr is complex) is the complex value with the maximum real part.
import numpy as np
arr = np.random.random(1000)+np.random.random(1000)*1j # generate example data
maxreal = arr.real.max() # maximum real part
maximag = arr.imag.max() # maximum imaginary part
maxabs = np.abs(arr).max() # maximum absolute value
maxcompreal = arr[arr.real.argmax()] # complex value with maximum real part
maxcomp = arr.max() # complex value with maximum real part, same as above
maxcompimag = arr[arr.imag.argmax()] # complex value with maximum imaginary part
maxcompabs = arr[np.abs(arr).argmax()] # complex value with maximum absolute value
Complex numbers don't have an ordering. But you can calculate the squared magnitude where
is the real part of the complex number
and
is its imaginary part (with the imaginary unit removed). Scan your array and find the largest squared magnitude. You might be able to use the built in function
max, possibly with a custom ordering function.