4.4 Localization  -< ANSI C Rationale  -> 4.6 Nonlocal jumps                    Index 

4.5  Mathematics  <math.h>

For historical reasons, the math library is only defined for the floating type double All the names formed by appending f or l to a name in <math.h> are reserved to allow for the definition of float and long double libraries. 

The functions ecvt, fcvt, and gcvt have been dropped since their capability is available through sprintf

Traditionally, HUGE_VAL has been defined as a manifest constant that approximates the largest representable double value.  As an approximation to infinity it is problematic.  As a function return value indicating overflow, it can cause trouble if first assigned to a float before testing, since a float may not necessarily hold all values representable in a double

After considering several alternatives, the Committee decided to generalize HUGE_VAL to a positive double expression, so that it could be expressed as an external identifier naming a location initialized precisely with the proper bit pattern.  It can even be a special encoding for machine infinity, on implementations that support such codes.  It need not be representable as a float, however. 

Similarly, domain errors in the past were typically indicated by a zero return, which is not necessarily distinguishable from a valid result.  The Committee agreed to make the return value for domain errors implementation-defined, so that special machine codes can be used to advantage.  This makes possible an implementation of the math library in accordance with the IEEE P854 proposal on floating point representation and arithmetic. 

4.5.1  Treatment of error conditions

Whether underflow should be considered a range error, and cause errno to be set, is specified as implementation-defined since detection of underflow is inefficient on some systems. 

The Standard has been crafted to neither require nor preclude any popular implementation of floating point.  This principle affects the definition of domain error: an implementation may define extra domain errors to deal with floating-point arguments such as infinity or ``not-a-number''. 

The Committee considered the adoption of the matherr capability from UNIX System V.  In this feature of that system's math library, any error (such as overflow or underflow) results in a call from the library function to a user-defined exception handler named matherr The Committee rejected this approach for several reasons:

4.5.2  Trigonometric functions

Implementation note: trignometric argument reduction should be performed by a method that causes no catastrophic discontinuities in the error of the computed result.  In particular, methods based solely on naive application of a calculation like

        x - (2*pi) * (int)(x/(2*pi))
are ill-advised.

4.5.2.1  The acos function

4.5.2.2  The asin function

4.5.2.3  The atan function

4.5.2.4  The atan2 function

The atan2 function is modelled after FORTRAN's.  It is described in terms of arctany/x for simplicity; the Committee did not wish to complicate the descriptions by specifying in detail how the determine the appropriate quadrant, since that should be obvious from normal mathematical convention.  atan2(y,x) is well-defined and finite, even when x is 0; the one ambiguity occurs when both arguments are 0, because at that point any value in the range of the function could logically be selected. Since valid reasons can be advanced for all the different choices that have been in this situation by various implements, the Standard preserves the implementor's freedom to return an arbitrary well-defined value such as 0, to report a domain error, or to return an IEEE NaN code. 

4.5.2.5  The cos function

4.5.2.6  The sin function

4.5.2.7  The tan function

The tangent function has singularities at odd multiples of pi/2, approaching +infinity from one side and -infinity from the other.  Implementations commonly perform argument reduction using the best machine representation of pi; for arguments to tan sufficiently close to a singularity, such reduction may yield a value on the wrong side of the singularity.  In view of such problems, the Committee has recognized that tan is an exception to the range error rule (§4.5.1 that an overflowing result produces HUGE_VAL properly signed.)

4.5.3  Hyperbolic functions

4.5.3.1  The cosh function

4.5.3.2  The sinh function

4.5.3.3  The tanh function

4.5.4  Exponential and logarithmic functions

4.5.4.1  The exp function

4.5.4.2  The frexp function

The functions frexp, ldexp, and modf are primitives used by the remainder of the library.  There was some sentiment for dropping them for the same reasons that ecvt, fcvt, and gcvt were dropped, but their adherents rescued them for general use.  Their use is problematic: on nonbinary architectures ldexp may lose precision, and frexp may be inefficient.

4.5.4.3  The ldexp function

See §4.5.4.2

4.5.4.4  The log function

Whether log(0.) is a domain error or a range error is arguable.  The choice in the Standard, range error, is for compatibility with IEEE P854 Some such implementations would represent the result as -infinity, in which case no error is raised. 

4.5.4.5  The log10 function

See §4.5.4.4

4.5.4.6  The modf function

See §4.5.4.2

4.5.5  Power functions

4.5.5.1  The pow function

4.5.5.2  The sqrt function

IEEE P854, unlike the Standard, requires sqrt(-0.) to return a negatively signed magnitude-zero result.  This is an issue on implementations that support a negative floating zero.  The Standard specifies that taking the square root of a negative number (in the mathematical sense: less than 0)  is a domain error which requires the function to return an implementation-defined value.  This rule permits implementations to support either the IEEE P854 or vendor-specific floating point representations. 

4.5.6  Nearest integer, absolute value, and remainder functions

4.5.6.1  The ceil function

Implementation note: The ceil function returns the smallest integral value in double format not less than x, even though that integer might not be representable in a C integral type. ceil(x) equals x for all x sufficiently large in magnitude. An implementation that calculates ceil(x) as

        (double)(int) x
is ill-advised.

4.5.6.2  The fabs function

Adding an absolute value operator was rejected by the Committee.  An implementation can provide a built-in function for efficiency. 

4.5.6.3  The floor function

4.5.6.4  The fmod function

fmod is defined even if the quotient x/y is not representable --- this function is properly implemented by scaled subtraction rather than by division.  The Standard defines the result in terms of the formula x-i*y, where i is some integer. This integer need not be representable, and need not even be explicitly computed.  Thus implementations are advised not to compute the result using a formula like

        x - y * (int)(x/y)
Instead, the result can be computed in principle by subtracting ldexp(y,n) from x, for appropriately chosen decreasing n, until the remainder is between 0 and x --- efficiency considerations may dictate a different actual implementation.

The result of fmod(x,0.0) is either a domain error or 0.0; the result always lies between 0.0 and y, so specifying the non-erroneous result as 0.0 simply recognizes the limit case. 

The Committee considered and rejected a proposal to use the remainder operator % for this function; the operators in general correspond to hardware facilities, and fmod is not supported in hardware on most machines. 


4.4 Localization  -< ANSI C Rationale  -> 4.6 Nonlocal jumps                    Index