the following code produces some mysterious results compiled with g95 (with
several versions, see below). I'm running this on a Thinkpad X200 with Ubuntu
9.04 32 Bit.
<code>
program underflow_test
implicit none
integer, parameter :: pr = kind(0.0D0)
real(pr) :: x, hx
x = tiny(x)
hx = 0.5_pr * x
write(*,*) 'x ! = tiny(x) = ', x
write(*,*) 'half_tiny:'
write(*,*) 'hx ! = 0.5_pr * x = ', hx
write(*,*) 'x * 0.5_pr = ', x * 0.5_pr
write(*,*) 'scale(x, -1) = ', scale(x, -1)
write(*,*) 'scale(tiny(x), -1) = ', scale(tiny(x), -1)
write(*,*) 'quarter_tiny:'
write(*,*) 'scale(x, -2) = ', scale(x, -2)
write(*,*) 'scale(hx, -1) = ', scale(hx, -1)
write(*,*) 'scale(x * 0.5_pr, -1) = ', scale(x * 0.5_pr, -1)
write(*,*) 'scale(tiny(x) * 0.5_pr, -1) = ', scale(tiny(x) * 0.5_pr, -1)
write(*,*) 'x * 0.25_pr = ', x * 0.25_pr
write(*,*) 'scale(hx, -2) = ', scale(hx, -2)
end program underflow_test
</code>
<test>
sep@sep-mobile:~/ws/fortran/test$ g95 -v
Using built-in specs.
Target:
Configured with: ../configure --enable-languages=c : (reconfigured) ../configure
--enable-languages=c
Thread model: posix
gcc version 4.1.3 (g95 0.92!) Jun 18 2009
sep@sep-mobile:~/ws/fortran/test$ g95 underflow_test.f90 -o underflow_test
sep@sep-mobile:~/ws/fortran/test$ ./underflow_test
x ! = tiny(x) = 2.2250738585072014E-308
half_tiny:
hx ! = 0.5_pr * x = 1.1125369292536007E-308
x * 0.5_pr = 1.1125369292536007E-308
scale(x, -1) = 0. | ??
scale(tiny(x), -1) = 1.1125369292536007E-308 | ??
quarter_tiny:
scale(x, -2) = +Inf ! very wrong
scale(hx, -1) = 5.562684646268003E-309
scale(x * 0.5_pr, -1) = 5.562684646268003E-309
scale(tiny(x) * 0.5_pr, -1) = 2.781342323134E-309 | wrong
x * 0.25_pr = 5.562684646268003E-309
scale(hx, -2) = 2.781342323134E-309 | wrong
sep@sep-mobile:~/ws/fortran/test$
sep@sep-mobile:~/ws/fortran/test$ # install other g95 version #
sep@sep-mobile:~/ws/fortran/test$ g95 -v
Using built-in specs.
Target:
Configured with: ../configure --enable-languages=c
Thread model: posix
gcc version 4.0.3 (g95 0.92!) Feb 26 2009
sep@sep-mobile:~/ws/fortran/test$ g95 underflow_test.f90 -o underflow_test
sep@sep-mobile:~/ws/fortran/test$ ./underflow_test
x ! = tiny(x) = 2.2250738585072014E-308
half_tiny:
hx ! = 0.5_pr * x = 1.1125369292536007E-308
x * 0.5_pr = 1.1125369292536007E-308
scale(x, -1) = 0. | ??
scale(tiny(x), -1) = 1.1125369292536007E-308 | ??
quarter_tiny:
scale(x, -2) = +Inf ! very wrong
scale(hx, -1) = 5.562684646268003E-309
scale(x * 0.5_pr, -1) = 5.562684646268003E-309
scale(tiny(x) * 0.5_pr, -1) = 2.781342323134E-309 ! loose of precision
x * 0.25_pr = 5.562684646268003E-309
scale(hx, -2) = 2.781342323134E-309 ! loose of precision
sep@sep-mobile:~/ws/fortran/test$
</test>
??: I don't understand this.
gfortran 4.3.3 calculates all correctly. Compiling with -O0 doesn't help.
Do you have any ideas or explenations on this? Confirmations?
Thx and Best regards
Hans Peschke
>> sep@sep-mobile:~/ws/fortran/test$ ./underflow_test
>> x ! = tiny(x) = 2.2250738585072014E-308
>> half_tiny:
>> hx ! = 0.5_pr * x = 1.1125369292536007E-308
>> x * 0.5_pr = 1.1125369292536007E-308
>> scale(x, -1) = 0. | ??
>> scale(tiny(x), -1) = 1.1125369292536007E-308 | ??
>> quarter_tiny:
>> scale(x, -2) = +Inf ! very wrong
>> scale(hx, -1) = 5.562684646268003E-309
>> scale(x * 0.5_pr, -1) = 5.562684646268003E-309
>> scale(tiny(x) * 0.5_pr, -1) = 2.781342323134E-309 | wrong
>> x * 0.25_pr = 5.562684646268003E-309
>> scale(hx, -2) = 2.781342323134E-309 | wrong
Here are the results of the opensolaris jury (06.2009 with SunStudio 12.1):
x ! = tiny(x) = 2.2250738585072013E-308
half_tiny:
hx ! = 0.5_pr * x = 1.1125369292536006E-308
x * 0.5_pr = 1.1125369292536006E-308
scale(x, -1) = 1.1125369292536006E-308
scale(tiny(x), -1) = 1.1125369292536006E-308
quarter_tiny:
scale(x, -2) = 5.562684646268003E-309
scale(hx, -1) = 5.562684646268003E-309
scale(x * 0.5_pr, -1) = 5.562684646268003E-309
scale(tiny(x) * 0.5_pr, -1) = 5.562684646268003E-309
x * 0.25_pr = 5.562684646268003E-309
scale(hx, -2) = 2.781342323134002E-309
The handling of 80 vs. 64 bit precision seems to be commonly done wrong.
When setting flag -fns (floating point nonstandard(!)) this changes to the
standard (!) behaviour (almost):
x ! = tiny(x) = 2.2250738585072013E-308
half_tiny:
hx ! = 0.5_pr * x = 0.0E+0
x * 0.5_pr = 0.0E+0
scale(x, -1) = 0.0E+0
scale(tiny(x), -1) = 1.1125369292536006E-308
quarter_tiny:
scale(x, -2) = 0.0E+0
scale(hx, -1) = 0.0E+0
scale(x * 0.5_pr, -1) = 0.0E+0
scale(tiny(x) * 0.5_pr, -1) = 5.562684646268003E-309
x * 0.25_pr = 0.0E+0
scale(hx, -2) = 0.0E+0
So g95 is not alone at least ...
--
Dr. Udo Grabowski email: udo.gr...@imk.fzk.de
Institut f. Meteorologie und Klimaforschung ASF,Forschungszentrum Karlsruhe
Postfach 3640, 76021 Karlsruhe, Germany Tel: (+49) 7247 82-6026
http://www.fzk.de/imk/asf/sat/grabowski/ Fax: " -7026