Silverfrost Logo About Us | Contact Us
 

Underflows

Here is a summary of how FTN95 handles underflow. Details appear below. By default FTN95 sets underflow as unmasked so that when a underflow occurs an exception is generated. FTN95 handles this exception internally and by default allows the computation to continue. A call to the routine MASK_UNDERFLOW@ sets underflow as masked so that an underflow does not generate an exception. A call of PERMIT_UNDERFLOW@(.FALSE.) resets underflow as unmasked and also triggers a run time error when FTN95 handles the exception internally.

Intel architectures use IEEE format floating point numbers. An underflow occurs when the result of a floating point operation is too small to be represented by the floating point format. The discussion below is illustrated using extended precision as an example. Single and double precision underflows are similar.

If x=1E-3000 then y=x*x cannot be represented because the result is 1E-6000 which is smaller than the smallest normalised floating point number (approximately 1E-4932). y would be set to zero.

The floating point unit has a masked and an unmasked response to underflow. In the above example y is set to zero in both cases. However, the mechanisms are quite different. With the masked response, the actual result is zero and is directly assigned. The unmasked response is to generate an underflow exception which is trapped by the run time library. The failing instruction is decoded and the target register or storage is replaced with zero. Unless PERMIT_UNDERFLOW@(.FALSE.) is used, control is then returned to the program at the following instruction and execution continues as normal.

 

Denormals
Denormals arise for one of two reasons: a) when an integer or an unset variable is passed as an argument that should be an floating point number and b) when the result of a floating point calculation is too small to be a normalised number but still large enough to have a representation (this only occurs when using the masked response to underflow).

In case (b), when the smallest exponent of the number is reached, leading zeroes are introduced into the significand of the number. Thus precision is lost for these numbers. Smaller numbers introduce more leading zeroes and this continues until no more leading zeros can be introduced and the result becomes zero. This process is called gradual underflow. Only when the number is less than about 1E-4951 does it become zero.

For example, the hex pattern below is the smallest positive extended precision normalised number. This is defined as such in the IEEE specification.

Exponent

Significand

0001

8000000000000000 (64 bits of precision)

Note that the most significant bit of the significand is 1 (8 is 1000 in binary). This is the normalisation bit. Every valid floating point number is shifted so that this bit is 1. This allows 64 bits of precision because there are no leading zeroes. However, if a smaller number is generated, the exponent is 0 and a leading zero is introduced into the significand:

Exponent

Significand

0000

4000000000000000 (63 bits of precision)

The number is then termed a denormal. The smallest denormal is:

Exponent

Significand

0000

0000000000000001 (1 bit of precision)

Although precision is lost for these extremely small values, the unmasked response of replacing them with zero represents a total loss of precision. Denormals, therefore give better numerical results although at times they may be non-zero when zero was expected. Denormals are handled like any other number and are printed correctly by the I/O system.

If underflows become unmasked, an attempt to use a denormal results in a run time error whilst the output field for a denormal is filled with "?".

 

Masking underflows
Underflows can be masked by calling the subroutine MASK_UNDERFLOW@

SUBROUTINE MASK_UNDERFLOW@()

Underflows can be unmasked by calling the subroutine UNMASK_UNDERFLOW@

SUBROUTINE UNMASK_UNDERFLOW@()

This is the default. If one of these is used, it should be the first executable line in your program. You are very strongly advised not to change the underflow state after this. Calling PERMIT_UNDERFLOW@(.FALSE.) causes underflows to become unmasked. The environment variable SALFENVAR can be set to MASK_UNDERFLOW or UNMASK_UNDERFLOW in order to provide a default state for your programs. If there is no environment variable setting, then the default is to unmask underflows.

 

Summary
Masking underflows provides a very safe way of handling underflows and achieving better numerical results, although you should be aware of the issues involved.

The table below shows the range of positive floating point values.

Largest

Smallest

Smallest denormal(masked underflows)

Single precision

1E38

1E-38

1E-46

Double precision

1E308

1E-308

1E-324

Extended precision

1E4932

1E-4932

1E-4951

 

 

Copyright © 1999-2017 Silverfrost Limited