Is there an intrinsic function in Fortran to compute the square modulus |z|^2
of a complex number z
?
If not, is there a simpler or better way to compute it than the following?
REAL(z, precision_specifier)**2 + AIMAG(z)**2
Is there an intrinsic function in Fortran to compute the square modulus |z|^2
of a complex number z
?
If not, is there a simpler or better way to compute it than the following?
REAL(z, precision_specifier)**2 + AIMAG(z)**2
No, the Fortran standard defines no such intrinsic routine. Nor, as far as I am aware, does any of the current crop of widely-used compilers provide such a routine.
If OP really wants to avoid an expensive sqrt, and doesn't like her existing solution, OP could try:
real :: rslt
real, dimension(2) :: parts
complex :: z
...
parts = transfer(z, parts)
rslt = dot_product(parts, parts)
or, given the same declarations, this might be preferred
rslt = dot_product(transfer(z, parts), transfer(z, parts))
As always, if performance matters to you, measure it.
Simpler or better ? You decide.
As always, transfer
is not to be operated by persons under the age of 18, or persons under the influence of alcohol or other performance-impairing drugs.
Just for fun, here is some attempt to use a (good old??) statement function for defining abs2() with the hope of being inlined... (not recommending its use, just experiment!)
program main
implicit none
integer, parameter :: dp = kind(0.0d0)
complex(dp) z
real(dp) abs2
abs2( z ) = real(z)**2 + aimag(z)**2 ! (could be included or macro-ed??)
! abs2( z ) = conjg( z ) * z ! maybe slower
! abs2( z ) = z % re**2 + z % im**2 ! near future
! intrinsic :: abs2 ! best solution
z = ( 1.0_dp, 2.0_dp )
print *, abs( z )**2
print *, abs2( z )
print *, abs( z + 1.0_dp )**2
print *, abs2( z + 1.0_dp )
end program
Result:
5.0000000000000009
5.0000000000000000
8.0000000000000018
8.0000000000000000
I hope z% re
and z% im
will be coming soon... (not yet with gfortran-6 and ifort-16)
Just exploit well-known formula (a+i*b)*(a-i*b) = a^2 + b^2
SquaredModulus = real part of (Z * CONJG(Z))
CONJG is complex conjugate
https://gcc.gnu.org/onlinedocs/gfortran/ABS.html
You are probably looking for CABS() or CDABS() and then squaring it. I just checked and it worked with f95 compiler.