Go to main content
Oracle® Developer Studio 12.6: Numerical Computation Guide

Exit Print View

Updated: July 2017
 
 

3.4 IEEE Support Functions

This section describes the IEEE recommended functions, the functions that supply useful values, ieee_flags, ieee_retrospective, and standard_arithmetic and nonstandard_arithmetic. Refer to Exceptions and Exception Handling for more information on the functions ieee_flags and ieee_handler.

3.4.1 ieee_functions(3m) and ieee_sun(3m)

The functions described by ieee_functions(3m) and ieee_sun(3m) provide capabilities either required by the IEEE standard or recommended in its appendix. These are implemented as efficient bit mask operations.

Table 18  ieee_functions(3m)
Function
Description
math.h
Header file
copysign(x,y)
x with y's sign bit
fabs(x)
Absolute value of x
fmod(x, y)
Remainder of x with respect to y
ilogb(x)
Base 2 unbiased exponent of x in integer format
nextafter(x,y)
Next representable number after x, in the direction y
remainder(x,y)
Remainder of x with respect to y
scalbn(x,n)
x × 2n
Table 19  ieee_sun(3m)
Function
Description
sunmath.h
Header file
fp_class(x)
Classification function
isinf(x)
Classification function
isnormal(x)
Classification function
issubnormal(x)
Classification function
iszero(x)
Classification function
signbit(x)
Classification function
nonstandard_arithmetic(void)
Enable nonstandard mode
standard_arithmetic(void)
Enable standard mode
ieee_retrospective(*f)
n/a

The remainder(x,y) is the operation specified in IEEE Standard 754-1985. The difference between remainder(x,y) and fmod(x,y) is that the sign of the result returned by remainder(x,y) might not agree with the sign of either x or y, whereas fmod(x,y) always returns a result whose sign agrees with x. Both functions return exact results and do not generate inexact exceptions.

Table 20  Calling ieee_functions From Fortran
IEEE Function
Single Precision
Double Precision
Quadruple Precision
copysign(x,y)
t=r_copysign(x,y)
z=d_copysign(x,y)
z=q_copysign(x,y)
ilogb(x)
i=ir_ilogb(x)
i=id_ilogb(x)
i=iq_ilogb(x)
nextafter(x,y)
t=r_nextafter(x,y)
z=d_nextafter(x,y)
z=q_nextafter(x,y)
scalbn(x,n)
t=r_scalbn(x,n)
z=d_scalbn(x,n)
z=q_scalbn(x,n)
signbit(x)
i=ir_signbit(x)
i=id_signbit(x)
i=iq_signbit(x)
Table 21  Calling ieee_sun From Fortran
IEEE Function
Single Precision
Double Precision
Quadruple Precision
signbit(x)
i=ir_signbit(x)
i=id_signbit(x)
i=iq_signbit(x)

Note -  You must declare d_function as double precision and q_function as REAL*16 in the Fortran program that uses them.

3.4.2 ieee_values(3m)

IEEE values like infinity, NaN, maximum and minimum positive floating-point numbers are provided by the functions described by the ieee_values(3m) man page. Table 22, Table 23, Table 24, and Table 25 show the decimal values and hexadecimal IEEE representations of the values provided by ieee_values(3m) functions.

Table 22  IEEE Values: Single Precision
IEEE value
Decimal value hexadecimal representation
C, C++ Fortran
max normal
3.40282347e+38 7f7fffff
r = max_normalf(); r = r_max_normal()
min normal
1.17549435e–38 00800000
r = min_normalf(); r = r_min_normal()
max subnormal
1.17549421e–38 007fffff
r = max_subnormalf(); r = r_max_subnormal()
min subnormal
1.40129846e–45 00000001
r = min_subnormalf(); r = r_min_subnormal()
Infinity 7f800000
r = infinityf(); r = r_infinity()
quiet NaN
NaN 7fffffff
r = quiet_nanf(0); r = r_quiet_nan(0)
signaling NaN
NaN 7f800001
r = signaling_nanf(0); r = r_signaling_nan(0)
Table 23  IEEE Values: Double Precision
IEEE value
Decimal Value hexadecimal representation
C, C++ Fortran
max normal
1.7976931348623157e+308
7fefffff ffffffff
d = max_normal(); d = d_max_normal()
min normal
2.2250738585072014e–308
00100000 00000000
d = min_normal(); d = d_min_normal()
max subnormal
2.2250738585072009e–308
000fffff ffffffff
d = max_subnormal(); d = d_max_subnormal()
min subnormal
4.9406564584124654e–324
00000000 00000001
d = min_subnormal(); d = d_min_subnormal()
Infinity
7ff00000 00000000
d = infinity(); d = d_infinity()
quiet NaN
NaN
7fffffff ffffffff
d = quiet_nan(0); d = d_quiet_nan(0)
signaling NaN
NaN
7ff00000 00000001
d = signaling_nan(0); d = d_signaling_nan(0)
Table 24  IEEE Values: Quadruple Precision
IEEE value
Decimal value hexadecimal representation
C, C++ (SPARC)
Fortran (all)
max normal
1.1897314953572317650857593266280070e+4932
7ffeffff ffffffff ffffffff ffffffff
q = max_normall(); q = q_max_normal()
min normal
3.3621031431120935062626778173217526e–4932
00010000 00000000 00000000 00000000
q = min_normall(); q = q_min_normal()
max subnormal
3.3621031431120935062626778173217520e–4932
0000ffff ffffffff ffffffff ffffffff
q = max_subnormall(); q = q_max_subnormal()
min subnormal
6.4751751194380251109244389582276466e–4966
00000000 00000000 00000000 00000001
q = min_subnormall(); q = q_min_subnormal()
Infinity
7fff0000 00000000 00000000 00000000
q = infinityl(); q = q_infinity()
quiet NaN
NaN
7fff8000 00000000 00000000 00000000
q = quiet_nanl(0); q = q_quiet_nan(0)
signaling NaN
NaN
7fff0000 00000000 00000000 00000001
q = signaling_nanl(0); q = q_signaling_nan(0)
Table 25  IEEE Values: Double-Extended Precision (x86)
IEEE value
Decimal value hexadecimal representation (80 bits)
C, C++
max normal
1.18973149535723176505e+4932
7ffe ffffffff ffffffff
x = max_normall();
min positive normal
3.36210314311209350626e–4932
0001 80000000 00000000
x = min_normall();
max subnormal
3.36210314311209350608e–4932
0000 7fffffff ffffffff
x = max_subnormall();
min positive subnormal
1.82259976594123730126e–4951
0000 00000000 00000001
x = min_subnormall();
Infinity
7fff 80000000 00000000
x = infinityl();
quiet NaN
NaN
7fff c0000000 00000000
x = q
signaling NaN
NaN
7fff 80000000 00000001
x = signaling_nanl(0);

3.4.3 ieee_flags(3m)

ieee_flags (3m) is the Oracle interface to:

  • Query or set rounding direction mode

  • Query or set rounding precision mode

  • Examine, clear, or set accrued exception flags

The syntax for a call to ieee_flags(3m) is:

i = ieee_flags(action, mode, in, out);

The ASCII strings that are the possible values for the parameters are shown in Table 26:

Table 26  Parameter Values for ieee_flags
Parameter
C or C++ Type
All Possible Values
action
char *
get, set, clear, clearall
mode
char *
direction, precision, exception
in
char *
nearest, tozero, negative, positive, extended, double, single, inexact, division, underflow, overflow, invalid, all, common
out
char **
nearest, tozero, negative, positive, extended, double, single, inexact, division, underflow, overflow, invalid, all, common

The ieee_flags(3m) man page describes the parameters in complete detail.

Some of the arithmetic features that can be modified by using ieee_flags are covered in the following paragraphs. Chapter 4 contains more information on ieee_flags and IEEE exception flags.

When mode is direction, the specified action applies to the current rounding direction. The possible rounding directions are: round towards nearest, round towards zero, round towards +•, or round towards -•. The IEEE default rounding direction is round towards nearest. This means that when the mathematical result of an operation lies strictly between two adjacent representable numbers, the one nearest to the mathematical result is delivered. (If the mathematical result lies exactly halfway between the two nearest representable numbers, then the result delivered is the one whose least significant bit is zero. The round towards nearest mode is sometimes called round to nearest even to emphasize this.)

Rounding towards zero is the way many pre-IEEE computers work, and corresponds mathematically to truncating the result. For example, if 2/3 is rounded to 6 decimal digits, the result is .666667 when the rounding mode is round towards nearest, but .666666 when the rounding mode is round towards zero.

When using ieee_flags to examine, clear, or set the rounding direction, possible values for the four input parameters are shown in Table 27.

Table 27  ieee_flags Input Values for the Rounding Direction
Parameter
Possible value (mode is direction)
action
get, set, clear, clearall
in
nearest, tozero, negative, positive
out
nearest, tozero, negative, positive

When mode is precision, the specified action applies to the current rounding precision. On x86-based systems, the possible rounding precisions are: single, double, and extended. The default rounding precision is extended; in this mode, arithmetic operations that deliver a result to an x87 floating-point register round their result to the full 64-bit precision of the extended double register format. When the rounding precision is single or double, arithmetic operations that deliver a result to an x87 floating-point register round their result to 24 or 53 significant bits, respectively. Although most programs produce results that are at least as accurate, if not more so, when extended rounding precision is used, some programs that require strict adherence to the semantics of IEEE arithmetic will not work correctly in extended rounding precision mode and must be run with the rounding precision set to single or double as appropriate.

Rounding precision cannot be set on systems using SPARC processors. On these systems, calling ieee_flags with mode = precision has no effect on computation.

Finally, when mode is exception, the specified action applies to the current IEEE exception flags. See Exceptions and Exception Handling for more information about using ieee_flags to examine and control the IEEE exception flags.

3.4.4 ieee_retrospective(3m)

The libsunmath function ieee_retrospective prints information about unrequited exceptions and nonstandard IEEE modes. It reports:

  • Outstanding exceptions.

  • Enabled traps.

  • If rounding direction or precision is set to other than the default.

  • If nonstandard arithmetic is in effect.

The necessary information is obtained from the hardware floating-point status register.

ieee_retrospective prints information about exception flags that are raised, and exceptions for which a trap is enabled. These two distinct, if related, pieces of information should not be confused. If an exception flag is raised, then that exception occurred at some point during program execution. If a trap is enabled for an exception, then the exception might not have actually occurred, but if it had, a SIGFPE signal would have been delivered. The ieee_retrospective message is meant to alert you about exceptions that might need to be investigated, if the exception flag is raised, or to remind you that exceptions might have been handled by a signal handler, if the exception's trap is enabled. Exceptions and Exception Handling discusses exceptions, signals, and traps, and shows how to investigate the cause of a raised exception.

A program can explicitly call ieee_retrospective at any time. Fortran programs compiled with f95 in –f77 compatibility mode automatically call ieee_retrospective before they exit. C/C++ programs and Fortran programs compiled with f95 in the default mode do not automatically call ieee_retrospective.

Note, though, that the f95 compiler enables trapping on common exceptions by default, so unless a program either explicitly disables trapping or installs a SIGFPE handler, it will immediately abort when such an exception occurs. In –f77 compatibility mode, the compiler does not enable trapping, so when floating-point exceptions occur, the program continues execution and reports those exceptions via the ieee_retrospective output on exit.

The syntax for calling this function is as follows:

  • C, C++ - ieee_retrospective(fp);

  • Fortran - call ieee_retrospective()

For the C function, the argument fp specifies the file to which the output will be written. The Fortran function always prints output on stderr.

The following example shows four of the six ieee_retrospective warning messages:

Note: IEEE floating-point exception flags raised:
   Inexact; Underflow; 
Rounding direction toward zero 
IEEE floating-point exception traps enabled: 
   overflow; 
See the Numerical Computation Guide, ieee_flags(3M), 
ieee_handler(3M), ieee_sun(3m)

A warning message appears only if trapping is enabled or an exception was raised.

You can suppress ieee_retrospective messages from Fortran programs by one of three methods. One approach is to clear all outstanding exceptions, disable traps, and restore round-to-nearest, extended precision, and standard modes before the program exits. To do this, call ieee_flags, ieee_handler, and standard_arithmetic as follows:

character*8 out 
i = ieee_flags('clearall', '', '', out) 
call ieee_handler('clear', 'all', 0)
call standard_arithmetic()

Note -  Clearing outstanding exceptions without investigating their cause is not recommended.

Another way to avoid seeing ieee_retrospective messages is to redirect stderr to a file. Of course, this method should not be used if the program sends output other than ieee_retrospective messages to stderr.

The third approach is to include a dummy ieee_retrospective function in the program, for example:

subroutine ieee_retrospective
return
end

3.4.5 nonstandard_arithmetic(3m)

As discussed in IEEE Arithmetic, IEEE arithmetic handles underflowed results using gradual underflow. On some SPARC-based systems, gradual underflow is often implemented partly with software emulation of the arithmetic. If many calculations underflow, this can cause performance degradation.

To obtain some information about whether this is a case in a specific program, you can use ieee_retrospective or ieee_flags to determine if underflow exceptions occur, and check the amount of system time used by the program. If a program spends an unusually large amount of time in the operating system, and raises underflow exceptions, gradual underflow might be the cause. In this case, using non-IEEE arithmetic might speed up program execution.

The function nonstandard_arithmetic enables non-IEEE arithmetic modes on processors that support them. On SPARC systems, this function sets the NS (nonstandard arithmetic) bit in the floating-point status register. On x86 systems supporting the SSE instructions, this function sets the FTZ (flush to zero) bit in the MXCSR register; it also sets the DAZ (denormals are zero) bit in the MXCSR register on those processors that support this bit. Note that the effects of nonstandard modes vary from one processor to another and can cause otherwise robust software to malfunction. Nonstandard mode is not recommended for normal use.

The function standard_arithmetic resets the hardware to use the default IEEE arithmetic. Both functions have no effect on processors that provide only the default IEEE 754 style of arithmetic. SPARC T4 is one such processor.