how *not* to use denormalised numbers?

Steve Kargl sgk@troutmask.apl.washington.edu
Tue Nov 10 18:14:00 GMT 2015


On Tue, Nov 10, 2015 at 05:59:12PM +0100, Dominique d'Humières wrote:
> Consider the following modification of the test
> 
> use ieee_arithmetic
> logical :: gradual
>   write (*,*) "Support underflow control:", &
>               ieee_support_underflow_control()
>   call ieee_get_underflow_mode( gradual )
>   write (*,*) "Gradual underflow:", gradual
>   write (*,*) "Support denormals:", ieee_support_denormal()
>   print *, nearest(tiny(1.0d0), -1.0d0)
>   print *, nearest(0.0d0, 1.0d0)
> ! flip underflow mode
>   call ieee_set_underflow_mode( .not. gradual )
>   call ieee_get_underflow_mode( gradual )
>   write (*,*) "Gradual underflow:", gradual
>   write (*,*) "Support denormals:", ieee_support_denormal()
>   print *, nearest(tiny(1.0d0), -1.0d0)
>   print *, nearest(0.0d0, 1.0d0)
> end
> 
> Compiled with gfortran -O, it outputs
> 
>  Support underflow control: F
>  Gradual underflow: T
>  Support denormals: T
>    2.2250738585072009E-308
>    4.9406564584124654E-324
>  Gradual underflow: F
>  Support denormals: T
>    2.2250738585072009E-308
>    4.9406564584124654E-324
> 

Your code is wrong.  gfortran will constant-fold the intrinsic
procedures in your print statements.  This constant folding is
done prior to toggling the FPU.  Changing the above code shows
the desired behavior and re-inforces Nick's advice.  Consider

program foo 

   use ieee_arithmetic

   logical :: gradual
   real x
  
   write (*,*) "Support underflow control:", ieee_support_underflow_control()

   call ieee_get_underflow_mode(gradual)
   write (*,*) "Gradual underflow:", gradual
   write (*,*) "Support denormals:", ieee_support_denormal()

   two = 1
   call bar(two)
   x = tiny(x)
   print *, x, x / two

   ! flip underflow mode
   call ieee_set_underflow_mode(.not.gradual)
   call ieee_get_underflow_mode(gradual)
   write (*,*) "Gradual underflow:", gradual
   write (*,*) "Support denormals:", ieee_support_denormal()

   two = 1
   call bar(two)
   x = tiny(x)
   print *, x, x / two

   contains

   subroutine bar(two)
      real, volatile :: two
      two = 2.
   end subroutine bar

end program foo

troutmask:sgk[215] gfc6 -o z -fdump-tree-original s.f90 && ./z
 Support underflow control: F
 Gradual underflow: T
 Support denormals: T
   1.17549435E-38   5.87747175E-39
 Gradual underflow: F
 Support denormals: T
   1.17549435E-38   0.00000000    



-- 
Steve



More information about the Fortran mailing list