Skip to content

Instantly share code, notes, and snippets.

@weslleyspereira
Last active September 1, 2021 19:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save weslleyspereira/ac5babcc0bc370cb238012e3048440e3 to your computer and use it in GitHub Desktop.
Save weslleyspereira/ac5babcc0bc370cb238012e3048440e3 to your computer and use it in GitHub Desktop.
Test double complex division in Fortran
*> \brief zdiv tests the robustness and precision of the double complex division
*> \author Weslley S. Pereira, University of Colorado Denver, U.S.
*
*> \verbatim
*>
*> Real values for test:
*> (1) x = 2**m, where m = MINEXPONENT-DIGITS, ..., MINEXPONENT-1. Stop on the first success.
*> Mind that not all platforms might implement subnormal numbers.
*> (2) x = 2**m, where m = MINEXPONENT, ..., 0. Stop on the first success.
*> (3) x = OV, where OV is the overflow threshold. OV^2 overflows but the norm is OV.
*> (4) x = 2**m, where m = MAXEXPONENT-1, ..., 1. Stop on the first success.
*>
*> Tests:
*> (a) y = x + 0 * I, y/y = 1
*> (b) y = 0 + x * I, y/y = 1
*> (c) y = x + x * I, y/y = 1
*> (d) y1 = 0 + x * I, y2 = x + 0 * I, y1/y2 = I
*> (e) y1 = 0 + x * I, y2 = x + 0 * I, y2/y1 = -I
*> (f) y = x + x * I, y/conj(y) = I
*>
*> Special cases:
*>
*> (i) Inf inputs:
*> (1) y = ( Inf + 0 * I)
*> (2) y = ( 0 + Inf * I)
*> (3) y = (-Inf + 0 * I)
*> (4) y = ( 0 - Inf * I)
*> (5) y = ( Inf + Inf * I)
*> Tests:
*> (a) 0 / y is either 0 or NaN.
*> (b) 1 / y is either 0 or NaN.
*> (c) y / y is NaN.
*>
*> (n) NaN inputs:
*> (1) y = (NaN + 0 * I)
*> (2) y = (0 + NaN * I)
*> (3) y = (NaN + NaN * I)
*> Tests:
*> (a) 0 / y is NaN.
*> (b) 1 / y is NaN.
*> (c) y / y is NaN.
*>
*> \endverbatim
*
program zdiv
integer N, i, nNaN, nInf, min, Max, m
parameter ( N = 4, nNaN = 3, nInf = 5 )
double precision X( N ), threeFourth, fiveFourth, aInf, aNaN, b,
$ eps, blueMin, blueMax, OV, Xj, stepX(N), limX(N)
parameter ( threeFourth = 3.0d0 / 4,
$ fiveFourth = 5.0d0 / 4 )
double complex Y, Y2, R, cInf( nInf ), cNaN( nNaN ), czero,
$ cone
parameter ( czero = DCMPLX( 0.0d0, 0.0d0 ),
$ cone = DCMPLX( 1.0d0, 0.0d0 ) )
*
intrinsic DCONJG, DBLE, RADIX, CEILING, TINY, DIGITS,
$ MAXEXPONENT, MINEXPONENT, FLOOR, HUGE, DCMPLX,
$ EPSILON
*
min = MINEXPONENT(0.0d0)
Max = MAXEXPONENT(0.0d0)
m = DIGITS(0.0d0)
b = DBLE(RADIX(0.0d0))
eps = EPSILON(0.0d0)
blueMin = b**CEILING( (min - 1) * 0.5d0 )
blueMax = b**FLOOR( (Max - m + 1) * 0.5d0 )
OV = HUGE(0.0d0)
*
X(1) = TINY(0.0d0) * b**( DBLE(1-m) )
X(2) = TINY(0.0d0)
X(3) = OV
X(4) = b**( DBLE(Max-1) )
*
stepX(1) = 2.0
stepX(2) = 2.0
stepX(3) = 0.0
stepX(4) = 0.5
*
limX(1) = X(2)
limX(2) = 1.0
limX(3) = 0.0
limX(4) = 2.0
*
print *, '# X :=', X
print *, '# Blue min constant :=', blueMin
print *, '# Blue max constant :=', blueMax
*
Xj = X(1)
if( Xj .eq. 0.0d0 ) then
print *, "# Subnormal numbers treated as 0"
else
do 100 i = 1, N
Xj = X(i)
if( Xj .eq. 0.0d0 ) print *,
$ "# Subnormal numbers may be treated as 0"
100 continue
endif
*
aInf = OV * 2
cInf(1) = DCMPLX( aInf, 0.0d0 )
cInf(2) = DCMPLX(-aInf, 0.0d0 )
cInf(3) = DCMPLX( 0.0d0, aInf )
cInf(4) = DCMPLX( 0.0d0,-aInf )
cInf(5) = DCMPLX( aInf, aInf )
*
aNaN = aInf / aInf
cNaN(1) = DCMPLX( aNaN, 0.0d0 )
cNaN(2) = DCMPLX( 0.0d0, aNaN )
cNaN(3) = DCMPLX( aNaN, aNaN )
*
* Test (a) y = x + 0 * I, y/y = 1
do 10 i = 1, N
Xj = X(i)
if( Xj .eq. 0.0d0 ) then
print *, "# [a] Subnormal numbers may be treated as 0"
else
do while( Xj .ne. limX(i) )
Y = DCMPLX( Xj, 0.0d0 )
R = Y / Y
if( R .ne. 1.0D0 )
$ WRITE( *, FMT = 9999 ) 'a',i, Y, Y, R, 1.0D0
Xj = Xj * stepX(i)
end do
endif
10 continue
*
* Test (b) y = 0 + x * I, y/y = 1
do 20 i = 1, N
Xj = X(i)
if( Xj .eq. 0.0d0 ) then
print *, "# [b] Subnormal numbers may be treated as 0"
else
do while( Xj .ne. limX(i) )
Y = DCMPLX( 0.0d0, Xj )
R = Y / Y
if( R .ne. 1.0D0 )
$ WRITE( *, FMT = 9999 ) 'b',i, Y, Y, R, 1.0D0
Xj = Xj * stepX(i)
end do
endif
20 continue
*
* Test (c) y = x + x * I, y/y = 1
do 30 i = 1, N
Xj = X(i)
if( Xj .eq. 0.0d0 ) then
print *, "# [c] Subnormal numbers may be treated as 0"
else
do while( Xj .ne. limX(i) )
Y = DCMPLX( Xj, Xj )
R = Y / Y
if( R .ne. 1.0D0 )
$ WRITE( *, FMT = 9999 ) 'c',i, Y, Y, R, 1.0D0
Xj = Xj * stepX(i)
end do
endif
30 continue
*
* Test (d) y1 = 0 + x * I, y2 = x + 0 * I, y1/y2 = I
do 40 i = 1, N
Xj = X(i)
if( Xj .eq. 0.0d0 ) then
print *, "# [d] Subnormal numbers may be treated as 0"
else
do while( Xj .ne. limX(i) )
Y = DCMPLX( 0.0d0, Xj )
Y2 = DCMPLX( Xj, 0.0d0 )
R = Y / Y2
if( R .ne. DCMPLX(0.0D0,1.0D0) )
$ WRITE( *, FMT = 9999 ) 'd',i, Y, Y2, R,
$ DCMPLX(0.0D0,1.0D0)
Xj = Xj * stepX(i)
end do
endif
40 continue
*
* Test (e) y1 = 0 + x * I, y2 = x + 0 * I, y2/y1 = -I
do 50 i = 1, N
Xj = X(i)
if( Xj .eq. 0.0d0 ) then
print *, "# [e] Subnormal numbers may be treated as 0"
else
do while( Xj .ne. limX(i) )
Y = DCMPLX( 0.0d0, Xj )
Y2 = DCMPLX( Xj, 0.0d0 )
R = Y2 / Y
if( R .ne. DCMPLX(0.0D0,-1.0D0) )
$ WRITE( *, FMT = 9999 ) 'e',i, Y2, Y, R,
$ DCMPLX(0.0D0,-1.0D0)
Xj = Xj * stepX(i)
end do
endif
50 continue
*
* Test (f) y = x + x * I, y/conj(y) = I
do 60 i = 1, N
Xj = X(i)
if( Xj .eq. 0.0d0 ) then
print *, "# [f] Subnormal numbers may be treated as 0"
else
do while( Xj .ne. limX(i) )
Y = DCMPLX( Xj, Xj )
R = Y / DCONJG( Y )
if( R .ne. DCMPLX(0.0D0,1.0D0) )
$ WRITE( *, FMT = 9999 ) 'f',i, Y, DCONJG( Y ), R,
$ DCMPLX(0.0D0,1.0D0)
Xj = Xj * stepX(i)
end do
endif
60 continue
*
* Test (g) Infs
do 70 i = 1, nInf
Y = cInf(i)
R = czero / Y
if( (R .ne. czero) .and. (R .eq. R) ) then
WRITE( *, FMT = 9998 ) 'ia',i, czero, Y, R, 'NaN and 0'
endif
R = cone / Y
if( (R .ne. czero) .and. (R .eq. R) ) then
WRITE( *, FMT = 9998 ) 'ib',i, cone, Y, R, 'NaN and 0'
endif
R = Y / Y
if( R .eq. R ) then
WRITE( *, FMT = 9998 ) 'ic',i, Y, Y, R, 'NaN'
endif
70 continue
*
* Test (h) NaNs
do 80 i = 1, nNaN
Y = cNaN(i)
R = czero / Y
if( R .eq. R ) then
WRITE( *, FMT = 9998 ) 'na',i, czero, Y, R, 'NaN'
endif
R = cone / Y
if( R .eq. R ) then
WRITE( *, FMT = 9998 ) 'nb',i, cone, Y, R, 'NaN'
endif
R = Y / Y
if( R .eq. R ) then
WRITE( *, FMT = 9998 ) 'nc',i, Y, Y, R, 'NaN'
endif
80 continue
*
9998 FORMAT( '[',A2,I1, '] (', (ES10.3,SP,ES10.3,"*I"), ' ) / ( ',
$ (ES10.3,SP,ES10.3,"*I"), ' ) = ',
$ (ES10.3,SP,ES10.3,"*I"), ' differs from ', A10 )
*
9999 FORMAT( '[',A2,I1, '] (', (ES10.3,SP,ES10.3,"*I"), ' ) / ( ',
$ (ES10.3,SP,ES10.3,"*I"), ' ) = ',
$ (ES10.3,SP,ES10.3,"*I"), ' differs from ',
$ (ES10.3,SP,ES10.3,"*I") )
*
* End of zdiv
*
END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment