Oracle® Solaris Studio 12.4: Numerical Computation Guide

Exit Print View

Updated: January 2015
 
 

Standards Compliance

The Oracle Solaris Studio compiler products together with the header files and libraries in the Solaris 10 operating environment support multiple standards including: System V Interface Definition Edition 3 (SVID), X/Open, ANSI C (C90), POSIX.1-2001 (SUSv3) and ISO C (C99). (See standards(5) for a more complete discussion.) Some of these standards allow implementations to vary in certain respects. In some cases, the specifications of these standards conflict. For the math libraries, the variances and conflicts are primarily related to special cases and exceptions. This appendix documents the behavior of the functions inlibm in these cases and discusses conditions under which a C program can expect behavior that conforms to each standard. The final section of this appendix documents the conformance of the Sun Studio C and Fortran language products to LIA-1.

E.1 libm Special Cases

Table E–1 lists all of the cases in which two or more of the standards mentioned above specify conflicting behavior for functions in libm. Which behavior a C program will observe depends on the compiler flags that are used when the program is compiled and linked. Possible behaviors include raising floating-point exceptions, calling the user-supplied function matherr with information about the special case that occurred and the value to be returned (see matherr(3M)), printing a message on the standard error file, and setting the global variable errno (see intro(2) and perror(3C)).

The first column in Table E–1 defines the special case. The second column shows the value to which errno will be set if it is set at all. The possible values for errno are defined in <errno.h>; the only two values used by the math library are EDOM for domain errors and ERANGE for range errors. When the second column shows both EDOM and ERANGE, the value to which errno is set is determined by the relevant standard as described below and shown in the fourth or fifth column. The third column shows the error code that will be indicated in any error message that is printed. The fourth, fifth, and sixth columns show the function values that will nominally be returned as defined by various standards. In some cases, a user-supplied matherr routine can override these values and supply another return value.

The specific responses to these special cases are determined by the compiler flags specified when a program is linked as follows. If either –xlibmieee or –xc99=lib is specified, then when any of the special cases in Table E–1 occurs, any appropriate floating-point exceptions are raised, and the function value listed in the sixth column of the table is returned.

If neither –xlibmieee nor –xc99=lib is used, then the behavior depends on the language conformance flag specified when the program is linked.

Specifying the -Xa flag selects X/Open conformance. When any of the special cases in the table occurs, any appropriate floating-point exceptions are raised, errno is set, and the function value listed in the fifth column of the table is returned. If a user-defined matherr routine is supplied, the behavior is undefined. Note that –Xa is the default when no other language conformance flag is given.

Specifying the -Xc flag selects strict C90 conformance. When a special case occurs, any appropriate floating-point exceptions are raised, errno is set, and the function value listed in the fifth column of the table is returned. matherr is not invoked in this case.

Finally, specifying either the –Xs or the –Xt flag selects SVID conformance. When a special case occurs, any appropriate floating-point exceptions are raised, matherr is called, and if matherr returns zero, then errno is set and an error message is printed. The function value listed in the fourth column of the table is returned unless it is overridden by matherr.

See the cc(1) manual page and Oracle Solaris Studio 12.4: C User’s Guide for more information about the –xc99, –Xa, –Xc, –Xs, and –Xt flags.

Table E-1  Special Cases and libm Functions
Function
errno
error message
SVID
X/Open, C90
IEEE, C99, SUSv3
acos(|x|>1)
EDOM
DOMAIN
0.0
0.0
NaN
acosh(x<1)
EDOM
DOMAIN
NaN
NaN
NaN
asin(|x|>1)
EDOM
DOMAIN
0.0
0.0
NaN
atan2(+/-0,+/-0)
EDOM
DOMAIN
0.0
0.0
+/‐0.0,+/‐pi
atanh(|x|>1)
EDOM
DOMAIN
NaN
NaN
NaN
atanh(+/-1)
EDOM/ERANGE
SING
+/‐HUGE1 (EDOM)
+/‐HUGE_VAL2 (ERANGE)
+/‐infinity
cosh overflow
ERANGE
HUGE
HUGE_VAL
infinity
exp overflow
ERANGE
HUGE
HUGE_VAL
infinity
exp underflow
ERANGE
0.0
0.0
0.0
fmod(x,0)
EDOM
DOMAIN
x
NaN
NaN
gamma(0 or ‐integer)
EDOM
SING
HUGE
HUGE_VAL
infinity
gamma overflow
ERANGE
HUGE
HUGE_VAL
infinity
hypot overflow
ERANGE
HUGE
HUGE_VAL
infinity
j0(X_TLOSS3<|x|< inf)
ERANGE
TLOSS
0.0
0.0
computed answer
j1(X_TLOSS<|x|< inf)
ERANGE
TLOSS
0.0
0.0
computed answer
jn(n,X_TLOSS<|x|< inf)
ERANGE
TLOSS
0.0
0.0
computed answer
ldexp overflow
ERANGE
-
+-infinity
+/-infinity
+/-infinity
ldexp underflow
ERANGE
-
+/-0.0
+/-0.0
+/-0.0
lgamma(0 or ‐integer)
EDOM
SING
HUGE
HUGE_VAL
infinity
lgamma overflow
ERANGE
HUGE
HUGE_VAL
infinity
log(0)
EDOM/ERANGE
SING
‐HUGE (EDOM)
‐HUGE_VAL (ERANGE)
‐infinity
log(x<0)
EDOM
DOMAIN
‐HUGE
‐HUGE_VAL
NaN
log10(0)
EDOM/ERANGE
SING
‐HUGE (EDOM)
‐HUGE_VAL (ERANGE)
‐infinity
log10(x<0)
EDOM
DOMAIN
‐HUGE
‐HUGE_VAL
NaN
log1p(‐1)
EDOM/ERANGE
SING
‐HUGE (EDOM)
‐HUGE_VAL (ERANGE)
‐infinity
log1p(x<‐1)
EDOM
DOMAIN
NaN
NaN
NaN
logb(0)
EDOM
-
-HUGE_VAL
-HUGE_VAL
-infinity
nextafter overflow
ERANGE
-
+-HUGE_VAL
+/-HUGE_VAL
+/-infinity
pow(0,0)
EDOM
DOMAIN
0.0
1.0 (no error)
1.0 (no error)
pow(NaN,0)
EDOM
DOMAIN
NaN
NaN
1.0 (no error)
pow(0,x<0)
EDOM
DOMAIN
0.0
‐HUGE_VAL
+/‐infinity
pow(x<0, non‐integer)
EDOM
DOMAIN
0.0
NaN
NaN
pow overflow
ERANGE
+/‐HUGE
+/‐HUGE_VAL
+/‐infinity
pow underflow
ERANGE
+/‐0.0
+/‐0.0
+/‐0.0
remainder(x,0) or remainder(inf,y)
EDOM
DOMAIN
NaN
NaN
NaN
scalb overflow
ERANGE
+‐HUGE_VAL
+/‐HUGE_VAL
+/‐infinity
scalb underflow
ERANGE
+/‐0.0
+/‐0.0
+/‐0.0
scalb(0,+inf) or scalb(inf,-inf)
EDOM/ERANGE
NaN
(ERANGE)
NaN
(EDOM)
NaN
scalb(|x|>0,+inf)
ERANGE
+‐infinity
+/‐infinity
(no error)
+/‐infinity
(no error)
scalb(|x|<inf, ‐inf)
ERANGE
+/‐0.0
+/‐0.0
(no error)
+/‐0.0
(no error)
sinh overflow
ERANGE
+/‐HUGE
+/‐HUGE_VAL
+/‐infinity
sqrt(x<0)
EDOM
DOMAIN
0.0
NaN
NaN
y0(0)
EDOM
DOMAIN
‐HUGE
‐HUGE_VAL
‐infinity
y0(x<0)
EDOM
DOMAIN
‐HUGE
‐HUGE_VAL
NaN
y0(X_TLOSS<x<inf)
ERANGE
TLOSS
0.0
0.0
correct answer
y1(0)
EDOM
DOMAIN
‐HUGE
‐HUGE_VAL
‐infinity
y1(x<0)
EDOM
DOMAIN
‐HUGE
‐HUGE_VAL
NaN
y1(X_TLOSS<x<inf)
ERANGE
TLOSS
0.0
0.0
correct answer
yn(n,0)
EDOM
DOMAIN
‐HUGE
‐HUGE_VAL
‐infinity
yn(n,x<0)
EDOM
DOMAIN
‐HUGE
‐HUGE_VAL
NaN
yn(n,X_TLOSS<x< inf)
ERANGE
TLOSS
0.0
0.0
correct answer

Notes:

  1. HUGE is defined in <math.h>. SVID requires that HUGE be equal to MAXFLOAT, which is approximately 3.4e+38.

  2. HUGE_VAL is defined in <iso/math_iso.h>, which is included in <math.h>. HUGE_VAL evaluates to infinity.

  3. X_TLOSS is defined in <values.h>.

E.1.1 Other Compiler Flags Affecting Standard Conformance

The compiler flags listed above directly select which of several standards will be followed in handling the special cases listed in Table E–1. Other compiler flags can indirectly affect whether a program observes the behavior described above.

First, both the –xlibmil and –xlibmopt flags substitute faster implementations of some of the functions in libm. These faster implementations do not conform to SVID, X/Open, or C90. Neither do they set errno or call matherr. They do, however, raise floating-point exceptions as appropriate and deliver the results specified by IEEE 754 and/or C99. Similar comments apply to the –xvector flag, since it can cause the compiler to transform calls to standard math functions into calls to vector math functions.

Second, the –xbuiltin flag allows the compiler to treat the standard math functions defined in <math.h> as intrinsic and substitute inline code for better performance. The substitute code might not conform to SVID, X/Open, C90, or C99. It need not set errno, call matherr, or raise floating-point exceptions.

Third, when the C preprocessor token __MATHERR_ERRNO_DONTCARE is defined, a number of #pragma directives in <math.h> are compiled. These directives tell the compiler to assume that the standard math functions have no side effects. Under this assumption, the compiler can reorder calls to the math functions and references to global data such as errno or data that might be modified by a user-supplied matherr routine so as to violate the expected behavior described above. For example, consider the code fragment:

#include <errno.h>
#include <math.h>

...
errno = 0;
x = acos(2.0);
if (errno) {
    printf(“error\n”);
}

If this code is compiled with __MATHERR_ERRNO_DONTCARE defined, the compiler might assume that errno is not modified by the call to acos and transform the code accordingly, removing the call to printf entirely.

Note that the –fast macro flag includes the flags –xbuiltin, –xlibmil, –xlibmopt, and –D__MATHERR_ERRNO_DONTCARE.

Finally, since all of the math functions in libm raise floating-point exceptions as needed, running a program with trapping on those exceptions enabled will generally result in behavior other than that specified by the standards listed above. Thus, the –ftrap compiler flag can also affect standard conformance.

E.1.2 Additional Notes on C99 Conformance

C99 specifies two possible methods by which an implementation can handle special cases such as those in Table E–1. An implementation indicates which of the two methods it supports by defining the identifier math_errhandling to evaluate to an integer expression having the value MATH_ERRNO (1) or MATH_ERREXCEPT (2) or the bitwise “or” of these. (These values are defined in <math.h>.) If the expression (math_errhandling & MATH_ERRNO) is nonzero, then the implementation handles cases in which the argument of a function lies outside its mathematical domain by setting errno to EDOM and handles cases in which the result value of a function would underflow, overflow, or equal infinity exactly by setting errno to ERANGE. If the expression (math_errhandling & MATH_ERREXCEPT) is nonzero, then the implementation handles cases in which the argument of a function lies outside its mathematical domain by raising the invalid operation exception and handles cases in which the result value of a function would underflow, overflow or equal infinity exactly by raising the underflow, overflow, or division-by-zero exception, respectively.

On Oracle Solaris, <math.h> defines math_errhandling to be MATH_ERREXCEPT. Although the functions listed in Table E–1 may perform other actions for the special cases shown there, all libm functions---including the float and long double functions, complex functions, and additional functions specified by C99---respond to special cases by raising floating-point exceptions. This is the only method for handling special cases that is supported uniformly for all C99 functions.

Finally, note that there are three functions for which either C99 or SUSv3 requires different behavior from the Oracle Solaris default. The differences are summarized in the following table. The table lists only the double version of each function, but the differences apply to the float and long double versions as well. In each case, the SUSv3 specification is followed when a program is linked with -xc99=lib and the Solaris default is followed otherwise.

Table E-2  Solaris and C99/SUSv3 Differences
Function
Solaris behavior
C99/SUSv3 behavior
pow
pow(1.0, +/-inf) returns NaN
pow(-1.0, +/-inf) returns NaN
pow(1.0, NaN) returns NaN
pow(1.0, +/-inf) returns 1
pow(-1.0, +/-inf) returns 1
pow(1.0, NaN) returns 1
logb
logb(subnormal) returns Emin
logb(x) = ilogb(x) when x issubnormal
ilogb
ilogb(+/-0), ilogb(+/-inf),
ilogb(NaN) raise no exceptions
ilogb(+/-0), ilogb(+/-inf),
ilogb(NaN) raise invalid operation

E.2 LIA-1 Conformance

In this section, LIA-1 refers to ISO/IEC 10967-1:1994 Information Technology - Language Independent Arithmetic - Part 1: Integer and floating-point arithmetic.

The C and Fortran 95 compilers (cc and f95) contained in the Sun Studio compilers release conform to LIA-1 in the following senses (paragraph letters correspond to those in LIA‐1 section 8):

E.2.1 a. TYPES (LIA 5.1):

The LIA-1 conformant types are C int and Fortran INTEGER. Other types can conform as well, but they are not specified here. Further specifications for specific languages await language bindings to LIA-1 from the cognizant language standards organizations.

E.2.2 b. PARAMETERS (LIA 5.1):

#include <values.h> /* defines MAXINT */
#define TRUE 1
#define FALSE 0
#define BOUNDED TRUE
#define MODULO TRUE
#define MAXINT 2147483647
#define MININT ‐2147483648
 logical bounded, modulo
 integer maxint, minint
 parameter (bounded = .TRUE.)
 parameter (modulo = .TRUE.)
 parameter (maxint = 2147483647)
 parameter (minint = ‐2147483648)

E.2.3 d. DIV/REM/MOD (LIA 5.1.3):

C / and %, and Fortran / and mod(), provide DIVtI(x,y) and REMtI(x,y). Also, modaI(x,y) is available with the following code:

int modaI(int x, int y) {
 int t = x % y;
 if (y < 0 && t > 0)
 t ‐= y;
 else if (y > 0 && t < 0)
 t += y;
  return t;
 }

It is also available with the following code:

 integer function modaI(x, y)
 integer x, y, t
 t = mod(x, y)
 if (y .lt. 0 .and. t .gt. 0) t = t ‐ y
 if (y .gt. 0 .and. t .lt. 0) t = t + y
 modaI = t
 return
 end

E.2.4 i. NOTATION (LIA 5.1.3):

The following table shows the notation by which the LIA integer operations can be realized.

Table E-3  LIA‐1 Conformance ‐ Notation
LIA
C
Fortran if different
addI(x,y)
x+y
n/a
subI(x,y)
x‐y
n/a
mulI(x,y)
x*y
n/a
divtI(x,y)
x/y
n/a
remtI(x,y)
x%y
mod(x,y)
modaI(x,y)
see above
n/a
negI(x)
‐x
n/a
absI(x)
#include <stdlib.h>
abs(x)
abs(x)
signI(x)
#define signI(x) (x > 0
? 1 : (x < 0 ? ‐1 : 0))
see below
eqI(x,y)
x==y
x.eq.y
neqI(x,y)
x!=y
x.ne.y
lssI(x,y)
x<y
x.lt.y
leqI(x,y)
x<=y
x.le.y
gtrI(x,y)
x>y
x.gt.y
geqI(x,y)
x>=y
x.ge.y

The following code shows the Fortran notation for signI(x).

integer function signi(x)
integer x, t
if (x .gt. 0) t=1
if (x .lt. 0) t=‐1
if (x .eq. 0) t=0
return
end

E.2.5 j. EXPRESSION EVALUATION:

By default, when no optimization is specified, expressions are evaluated in int (C) or INTEGER (Fortran) precision. Parentheses are respected. The order of evaluation of associative unparenthesized expressions such as a + b + c or a * b * c is not specified.

E.2.6 k. METHOD OF OBTAINING PARAMETERS:

Include the definitions in b. PARAMETERS (LIA 5.1): in your source code.

E.2.7 n. NOTIFICATION:

Integer exceptions are x/0 and x%0 or mod(x,0). By default, these exceptions generate SIGFPE. When no signal handler is specified for SIGFPE, the process terminates and dumps memory.

E.2.8 o. SELECTION MECHANISM:

signal(3) or signal(3F) can be used to enable user exception handling for SIGFPE.