|
| 1 | +*> \brief zabs tests the robustness and precision of the intrinsic ABS for double complex |
| 2 | +*> \author Weslley S. Pereira, University of Colorado Denver, U.S. |
| 3 | +* |
| 4 | +*> \verbatim |
| 5 | +*> |
| 6 | +*> Real values for test: |
| 7 | +*> (1) x = 2**m, where m = MINEXPONENT-DIGITS, ..., MINEXPONENT-1. Stop on the first success. |
| 8 | +*> Mind that not all platforms might implement subnormal numbers. |
| 9 | +*> (2) x = 2**m, where m = MINEXPONENT, ..., 0. Stop on the first success. |
| 10 | +*> (3) x = OV, where OV is the overflow threshold. OV^2 overflows but the norm is OV. |
| 11 | +*> (4) x = 2**m, where m = MAXEXPONENT-1, ..., 1. Stop on the first success. |
| 12 | +*> |
| 13 | +*> Tests: |
| 14 | +*> (a) y = x + 0 * I, |y| = x |
| 15 | +*> (b) y = 0 + x * I, |y| = x |
| 16 | +*> (c) y = (3/4)*x + x * I, |y| = (5/4)*x whenever (3/4)*x and (5/4)*x can be exactly stored |
| 17 | +*> (d) y = (1/2)*x + (1/2)*x * I, |y| = (1/2)*x*sqrt(2) whenever (1/2)*x can be exactly stored |
| 18 | +*> |
| 19 | +*> Special cases: |
| 20 | +*> |
| 21 | +*> (i) Inf propagation |
| 22 | +*> (1) y = Inf + 0 * I, |y| is Inf. |
| 23 | +*> (2) y =-Inf + 0 * I, |y| is Inf. |
| 24 | +*> (3) y = 0 + Inf * I, |y| is Inf. |
| 25 | +*> (4) y = 0 - Inf * I, |y| is Inf. |
| 26 | +*> (5) y = Inf + Inf * I, |y| is Inf. |
| 27 | +*> |
| 28 | +*> (n) NaN propagation |
| 29 | +*> (1) y = NaN + 0 * I, |y| is NaN. |
| 30 | +*> (2) y = 0 + NaN * I, |y| is NaN. |
| 31 | +*> (3) y = NaN + NaN * I, |y| is NaN. |
| 32 | +*> |
| 33 | +*> \endverbatim |
| 34 | +* |
| 35 | + program zabs |
| 36 | + |
| 37 | + logical debug |
| 38 | + parameter ( debug = .false. ) |
| 39 | + |
| 40 | + integer N, i, nNaN, nInf, min, Max, m |
| 41 | + parameter ( N = 4, nNaN = 3, nInf = 5 ) |
| 42 | + |
| 43 | + double precision X( N ), R, threeFourth, fiveFourth, answerC, |
| 44 | + $ answerD, oneHalf, aInf, aNaN, relDiff, b, |
| 45 | + $ eps, blueMin, blueMax, Xj, stepX(N), limX(N) |
| 46 | + parameter ( threeFourth = 3.0d0 / 4, |
| 47 | + $ fiveFourth = 5.0d0 / 4, |
| 48 | + $ oneHalf = 1.0d0 / 2 ) |
| 49 | + |
| 50 | + double complex Y, cInf( nInf ), cNaN( nNaN ) |
| 51 | + intrinsic ABS, DBLE, RADIX, CEILING, TINY, DIGITS, SQRT, |
| 52 | + $ MAXEXPONENT, MINEXPONENT, FLOOR, HUGE, DCMPLX, |
| 53 | + $ EPSILON |
| 54 | + |
| 55 | + integer subnormalTreatedAs0, caseAFails, caseBFails, |
| 56 | + $ caseCFails, caseDFails |
| 57 | +* |
| 58 | + subnormalTreatedAs0 = 0 |
| 59 | + caseAFails = 0 |
| 60 | + caseBFails = 0 |
| 61 | + caseCFails = 0 |
| 62 | + caseDFails = 0 |
| 63 | +* |
| 64 | + min = MINEXPONENT(0.0d0) |
| 65 | + Max = MAXEXPONENT(0.0d0) |
| 66 | + m = DIGITS(0.0d0) |
| 67 | + b = DBLE(RADIX(0.0d0)) |
| 68 | + eps = EPSILON(0.0d0) |
| 69 | + blueMin = b**CEILING( (min - 1) * 0.5d0 ) |
| 70 | + blueMax = b**FLOOR( (Max - m + 1) * 0.5d0 ) |
| 71 | +* |
| 72 | + X(1) = TINY(0.0d0) * b**( DBLE(1-m) ) |
| 73 | + X(2) = TINY(0.0d0) |
| 74 | + X(3) = HUGE(0.0d0) |
| 75 | + X(4) = b**( DBLE(Max-1) ) |
| 76 | +* |
| 77 | + stepX(1) = 2.0 |
| 78 | + stepX(2) = 2.0 |
| 79 | + stepX(3) = 0.0 |
| 80 | + stepX(4) = 0.5 |
| 81 | +* |
| 82 | + limX(1) = X(2) |
| 83 | + limX(2) = 1.0 |
| 84 | + limX(3) = 0.0 |
| 85 | + limX(4) = 2.0 |
| 86 | +* |
| 87 | + if( debug ) then |
| 88 | + print *, '# X :=', X |
| 89 | + print *, '# Blue min constant :=', blueMin |
| 90 | + print *, '# Blue max constant :=', blueMax |
| 91 | + endif |
| 92 | +* |
| 93 | + Xj = X(1) |
| 94 | + if( Xj .eq. 0.0d0 ) then |
| 95 | + subnormalTreatedAs0 = subnormalTreatedAs0 + 1 |
| 96 | + if( debug .or. subnormalTreatedAs0 .eq. 1 ) then |
| 97 | + print *, "!! fl( subnormal ) may be 0" |
| 98 | + endif |
| 99 | + else |
| 100 | + do 100 i = 1, N |
| 101 | + Xj = X(i) |
| 102 | + if( Xj .eq. 0.0d0 ) then |
| 103 | + subnormalTreatedAs0 = subnormalTreatedAs0 + 1 |
| 104 | + if( debug .or. subnormalTreatedAs0 .eq. 1 ) then |
| 105 | + print *, "!! fl( subnormal ) may be 0" |
| 106 | + endif |
| 107 | + endif |
| 108 | + 100 continue |
| 109 | + endif |
| 110 | +* |
| 111 | + aInf = X(3) * 2 |
| 112 | + cInf(1) = DCMPLX( aInf, 0.0d0 ) |
| 113 | + cInf(2) = DCMPLX(-aInf, 0.0d0 ) |
| 114 | + cInf(3) = DCMPLX( 0.0d0, aInf ) |
| 115 | + cInf(4) = DCMPLX( 0.0d0,-aInf ) |
| 116 | + cInf(5) = DCMPLX( aInf, aInf ) |
| 117 | +* |
| 118 | + aNaN = aInf / aInf |
| 119 | + cNaN(1) = DCMPLX( aNaN, 0.0d0 ) |
| 120 | + cNaN(2) = DCMPLX( 0.0d0, aNaN ) |
| 121 | + cNaN(3) = DCMPLX( aNaN, aNaN ) |
| 122 | +* |
| 123 | +* Test (a) y = x + 0 * I, |y| = x |
| 124 | + do 10 i = 1, N |
| 125 | + Xj = X(i) |
| 126 | + if( Xj .eq. 0.0d0 ) then |
| 127 | + subnormalTreatedAs0 = subnormalTreatedAs0 + 1 |
| 128 | + if( debug .or. subnormalTreatedAs0 .eq. 1 ) then |
| 129 | + print *, "!! [a] fl( subnormal ) may be 0" |
| 130 | + endif |
| 131 | + else |
| 132 | + do while( Xj .ne. limX(i) ) |
| 133 | + Y = DCMPLX( Xj, 0.0d0 ) |
| 134 | + R = ABS( Y ) |
| 135 | + if( R .ne. Xj ) then |
| 136 | + caseAFails = caseAFails + 1 |
| 137 | + if( caseAFails .eq. 1 ) then |
| 138 | + print *, "!! Some ABS(x+0*I) differ from ABS(x)" |
| 139 | + endif |
| 140 | + WRITE( 0, FMT = 9999 ) 'a',i, Xj, '(1+0*I)', R, Xj |
| 141 | + endif |
| 142 | + Xj = Xj * stepX(i) |
| 143 | + end do |
| 144 | + endif |
| 145 | + 10 continue |
| 146 | +* |
| 147 | +* Test (b) y = 0 + x * I, |y| = x |
| 148 | + do 20 i = 1, N |
| 149 | + Xj = X(i) |
| 150 | + if( Xj .eq. 0.0d0 ) then |
| 151 | + subnormalTreatedAs0 = subnormalTreatedAs0 + 1 |
| 152 | + if( debug .or. subnormalTreatedAs0 .eq. 1 ) then |
| 153 | + print *, "!! [b] fl( subnormal ) may be 0" |
| 154 | + endif |
| 155 | + else |
| 156 | + do while( Xj .ne. limX(i) ) |
| 157 | + Y = DCMPLX( 0.0d0, Xj ) |
| 158 | + R = ABS( Y ) |
| 159 | + if( R .ne. Xj ) then |
| 160 | + caseBFails = caseBFails + 1 |
| 161 | + if( caseBFails .eq. 1 ) then |
| 162 | + print *, "!! Some ABS(0+x*I) differ from ABS(x)" |
| 163 | + endif |
| 164 | + WRITE( 0, FMT = 9999 ) 'b',i, Xj, '(0+1*I)', R, Xj |
| 165 | + endif |
| 166 | + Xj = Xj * stepX(i) |
| 167 | + end do |
| 168 | + endif |
| 169 | + 20 continue |
| 170 | +* |
| 171 | +* Test (c) y = (3/4)*x + x * I, |y| = (5/4)*x |
| 172 | + do 30 i = 1, N |
| 173 | + if( i .eq. 3 ) go to 30 |
| 174 | + if( i .eq. 1 ) then |
| 175 | + Xj = 4*X(i) |
| 176 | + else |
| 177 | + Xj = X(i) |
| 178 | + endif |
| 179 | + if( Xj .eq. 0.0d0 ) then |
| 180 | + subnormalTreatedAs0 = subnormalTreatedAs0 + 1 |
| 181 | + if( debug .or. subnormalTreatedAs0 .eq. 1 ) then |
| 182 | + print *, "!! [c] fl( subnormal ) may be 0" |
| 183 | + endif |
| 184 | + else |
| 185 | + do while( Xj .ne. limX(i) ) |
| 186 | + answerC = fiveFourth * Xj |
| 187 | + Y = DCMPLX( threeFourth * Xj, Xj ) |
| 188 | + R = ABS( Y ) |
| 189 | + if( R .ne. answerC ) then |
| 190 | + caseCFails = caseCFails + 1 |
| 191 | + if( caseCFails .eq. 1 ) then |
| 192 | + print *, |
| 193 | + $ "!! Some ABS(x*(3/4+I)) differ from (5/4)*ABS(x)" |
| 194 | + endif |
| 195 | + WRITE( 0, FMT = 9999 ) 'c',i, Xj, '(3/4+I)', R, |
| 196 | + $ answerC |
| 197 | + endif |
| 198 | + Xj = Xj * stepX(i) |
| 199 | + end do |
| 200 | + endif |
| 201 | + 30 continue |
| 202 | +* |
| 203 | +* Test (d) y = (1/2)*x + (1/2)*x * I, |y| = (1/2)*x*sqrt(2) |
| 204 | + do 40 i = 1, N |
| 205 | + if( i .eq. 1 ) then |
| 206 | + Xj = 2*X(i) |
| 207 | + else |
| 208 | + Xj = X(i) |
| 209 | + endif |
| 210 | + if( Xj .eq. 0.0d0 ) then |
| 211 | + subnormalTreatedAs0 = subnormalTreatedAs0 + 1 |
| 212 | + if( debug .or. subnormalTreatedAs0 .eq. 1 ) then |
| 213 | + print *, "!! [d] fl( subnormal ) may be 0" |
| 214 | + endif |
| 215 | + else |
| 216 | + do while( Xj .ne. limX(i) ) |
| 217 | + answerD = (oneHalf * Xj) * SQRT(2.0d0) |
| 218 | + if( answerD .eq. 0.0d0 ) then |
| 219 | + subnormalTreatedAs0 = subnormalTreatedAs0 + 1 |
| 220 | + if( debug .or. subnormalTreatedAs0 .eq. 1 ) then |
| 221 | + print *, "!! [d] fl( subnormal ) may be 0" |
| 222 | + endif |
| 223 | + else |
| 224 | + Y = DCMPLX( oneHalf * Xj, oneHalf * Xj ) |
| 225 | + R = ABS( Y ) |
| 226 | + relDiff = ABS(R-answerD)/answerD |
| 227 | + if( relDiff .ge. (0.5*eps) ) then |
| 228 | + caseDFails = caseDFails + 1 |
| 229 | + if( caseDFails .eq. 1 ) then |
| 230 | + print *, |
| 231 | + $ "!! Some ABS(x*(1+I)) differ from sqrt(2)*ABS(x)" |
| 232 | + endif |
| 233 | + WRITE( 0, FMT = 9999 ) 'd',i, (oneHalf*Xj), |
| 234 | + $ '(1+1*I)', R, answerD |
| 235 | + endif |
| 236 | + endif |
| 237 | + Xj = Xj * stepX(i) |
| 238 | + end do |
| 239 | + endif |
| 240 | + 40 continue |
| 241 | +* |
| 242 | +* Test (e) Infs |
| 243 | + do 50 i = 1, nInf |
| 244 | + Y = cInf(i) |
| 245 | + R = ABS( Y ) |
| 246 | + if( .not.(R .gt. HUGE(0.0d0)) ) then |
| 247 | + WRITE( *, FMT = 9997 ) 'i',i, Y, R |
| 248 | + endif |
| 249 | + 50 continue |
| 250 | +* |
| 251 | +* Test (f) NaNs |
| 252 | + do 60 i = 1, nNaN |
| 253 | + Y = cNaN(i) |
| 254 | + R = ABS( Y ) |
| 255 | + if( R .eq. R ) then |
| 256 | + WRITE( *, FMT = 9998 ) 'n',i, Y, R |
| 257 | + endif |
| 258 | + 60 continue |
| 259 | +* |
| 260 | + if( (caseAFails .gt. 0) .or. (caseBFails .gt. 0) .or. |
| 261 | + $ (caseCFails .gt. 0) .or. (caseDFails .gt. 0) ) |
| 262 | + $ print *, "# Please check the failed ABS(a+b*I) in [stderr]" |
| 263 | +* |
| 264 | + 9997 FORMAT( '[',A1,I1, '] ABS(', (ES8.1,SP,ES8.1,"*I"), ' ) = ', |
| 265 | + $ ES8.1, ' differs from Inf' ) |
| 266 | +* |
| 267 | + 9998 FORMAT( '[',A1,I1, '] ABS(', (ES8.1,SP,ES8.1,"*I"), ' ) = ', |
| 268 | + $ ES8.1, ' differs from NaN' ) |
| 269 | +* |
| 270 | + 9999 FORMAT( '[',A1,I1, '] ABS(', ES24.16E3, ' * ', A7, ' ) = ', |
| 271 | + $ ES24.16E3, ' differs from ', ES24.16E3 ) |
| 272 | +* |
| 273 | +* End of zabs |
| 274 | +* |
| 275 | + END |
0 commit comments