Previous Page
Next Page

16.2. Mathematical Functions

The standard library provides many mathematical functions. Most of them operate on real or complex floating-point numbers. However, there are also several functions with integer types, such as the functions to generate random numbers.

The functions to convert numeral strings into arithmetic types are listed in "String Processing," later in this chapter. The remaining math functions are described in the following subsections.

16.2.1. Mathematical Functions for Integer Types

The math functions for the integer types are declared in the header stdlib.h. Two of these functions, abs( ) and div( ), are declared in three variants to operate on the three signed integer types int, long, and long long. As Table 16-3 shows, the functions for the type long have names beginning with the letter l; those for long long with ll. Furthermore, the header inttypes.h declares function variants for the type intmax_t, with names that begin with imax.

Table 16-3. Integer arithmetic functions

Purpose

Functions declared in stdlib.h

Functions declared in stdint.h

Absolute value

abs( ), labs( ), llabs( )

imaxabs( )

Division

div( ), ldiv( ), lldiv( )

imaxdiv( )

Random numbers

rand( ), srand( )

 


16.2.2. Floating-Point Functions

The functions for real floating-point types are declared in the header math.h, and those for complex floating-point types in complex.h. Table 16-4 lists the functions that are available for both real and complex floating-point types. The complex versions of these functions have names that start with the prefix c. Table 16-5 lists the functions that are only defined for the real types; and Table 16-6 lists the functions that are specific to complex types.

For the sake of readability, Tables 16-4 through 16-6 show only the names of the functions for the types double and double _Complex. Each of these functions also exists in variants for the types float (or float _Complex) and long double (or long double _Complex). The names of these variants end in the suffix f for float or l for long double. For example, the functions sin( ) and csin( ) listed in Table 16-4 also exist in the variants sinf( ), sinl( ), csinf( ), and csinl( ) (but see also "Type-generic macros" in the next section).

Table 16-4. Functions for real and complex floating-point types

Mathematical function

C functions in math.h

C functions in complex.h

Trigonometry

sin( ), cos( ), tan( )

asin( ), acos( ), atan( )

csin( ), ccos( ), ctan( )

casin( ), cacos( ), catan( )

Hyperbolic trigonometry

sinh( ), cosh( ), tanh( )

asinh( ), acosh( ), atanh( )

csinh( ), ccosh( ), ctanh( )

casinh( ), cacosh( ), catanh( )

Exponential function

exp( )

cexp( )

Natural logarithm

log( )

clog( )

Powers, square root

pow( ), sqrt( )

cpow( ), csqrt( )

Absolute value

fabs( )

cabs( )


Table 16-5. Functions for real floating-point types

Mathematical function

C function

Arctangent of a quotient

atan2( )

Exponential functions

exp2( ), expm1( ), frexp( ), ldexp( )

scalbn( ), scalbln( )

Logarithmic functions

log10( ), log2( ), log1p( ),

logb( ), ilogb( )

Roots

cbrt( ), hypot( )

Error functions for normal distributions

erf( ), erfc( )

Gamma function

tgamma( ), lgamma( )

Remainder

fmod( ), remainder( ), remquo( )

Separate integer and fractional parts

modf( )

Next integer

ceil( ), floor( )

Next representable number

nextafter( ), nexttoward( )

Rounding functions

trunc( ), round( ), lround( ), llround( ), nearbyint( ), rint( ), lrint( ), llrint( )

Positive difference

fdim( )

Multiply and add

fma( )

Minimum and maximum

fmin( ), fmax( )

Assign one number's sign to another

copysign( )

Generate a NaN

nan( )


Table 16-6. Functions for complex floating-point types

Mathematical function

C function

Isolate real and imaginary parts

creal( ), cimag( )

Argument (the angle in polar coordinates)

carg( )

Conjugate

conj( )

Project onto the Riemann sphere

cproj( )


16.2.3. Function-like Macros

The standard headers math.h and tgmath.h define a number of function-like macros that can be invoked with arguments of different floating-point types. Variable argument types in C are supported only in macros, not in function calls.

16.2.3.1. Type-generic macros

Each floating-point math function exists in three or six different versions: one for each of the three real types, or for each of the three complex types, or for both real and complex types. The header tgmath.h defines the type-generic macros , which allow you to call any version of a given function under a uniform name. The compiler detects the appropriate function from the arguments' type. Thus you do not need to edit the math function calls in your programs when you change an argument's type from double to long double, for example. The type-generic macros are described in the section on tgmath.h in Chapter 15.

16.2.3.2. Categories of floating-point values

C99 defines five kinds of values for the real floating-point types, with distinct integer macros to designate them (see the section on math.h in Chapter 15):

    FP_ZERO  FP_NORMAL  FP_SUBNORMAL  FP_INFINITE  FP_NAN

These classification macros, and the function-like macros listed in Table 16-7, are defined in the header math.h. The argument of each of the function-like macros must be an expression with a real floating-point type.

Table 16-7. Function-like macros to classify floating-point values

Purpose

Function-like macros

Get the category of a floating-point value

fpclassify( )

Test whether a floating-point value belongs to a certain category

isfinite( ), isinf( ), isnan( ), isnormal( ), signbit( )


For example, the following two tests are equivalent:

    if ( fpclassify( x ) == FP_INFINITE )  /* ... */ ;
    if ( isinf( x ) )                      /* ... */ ;

16.2.3.3. Comparison macros

Any two real, finite floating-point numbers can be compared. In other words, one is always less than, equal to, or greater than the other. However, if one or both operands of a comparative operator is a NaNa floating-point value that is not a numberfor example, then the operands are not comparable. In this case, the operation yields the value 0, or "false," and may raise the floating-point exception FE_INVALID.

In practice, you may want to avoid risking an exception when comparing floating-point objects. For this reason, the header math.h defines the function-like macros listed in Table 16-8. These macros yield the same results as the corresponding expressions with comparative operators, but perform a "quiet" comparison; that is, they never raise exceptions. The two arguments of each macro must be expressions with real floating-point types.

Table 16-8. Function-like macros to compare floating-point values

Comparison

Function-like macro

(x) > ( y)

isgreater( x, y )

(x) >= ( y)

isgreaterequal( x, y )

(x) < ( y)

isless( x, y )

(x) <= ( y)

islessequal( x, y )

((x) < ( y) || (x) > ( y))

islessgreater( x, y )a

Test for comparability

isunordered( x, y )

aUnlike the corresponding operator expression, the function-like macro islessgreater( ) evaluates its arguments only once


16.2.4. Pragmas for Arithmetic Operations

The following two standard pragmas influence the way in which arithmetic expressions are compiled:

    #pragma STDC FP_CONTRACT  on_off_switch
    #pragma STDC CX_LIMITED_RANGE  on_off_switch

The value of on_off_switch must be ON, OFF, or DEFAULT. If switched ON, the first of these pragmas, FP_CONTRACT, allows the compiler to contract floating-point expressions with several C operators into fewer machine operations, if possible. Contracted expressions are faster in execution. However, because they also eliminate rounding errors, they may not yield precisely the same results as uncontracted expressions. Furthermore, an uncontracted expression may raise floating-point exceptions that are not raised by the corresponding contracted expression. It is up to the compiler to determine how contractions are performed, and whether expressions are contracted by default.

The second pragma, CX_LIMITED_RANGE , affects the multiplication, division, and absolute values of complex numbers. These operations can cause problems if their operands are infinite, or if they result in invalid overflows or underflows. When switched ON, the pragma CX_LIMITED_RANGE instructs the compiler that it is safe to use simple arithmetic methods for these three operations, as only finite operands will be used, and no overflows or underflows need to be handled. By default, this pragma is switched OFF.

In source code, these pragma directives can be placed outside all functions, or at the beginning of a block, before any declarations or statements. The pragmas take effect from the point where they occur in the source code. If a pragma directive is placed outside all functions, its effect ends with the next directive that invokes the same pragma, or at the end of the translation unit. If the pragma directive is placed within a block, its effect ends with the next directive that invokes the same pragma in a nested block, or at the end of the containing block. At the end of a block, the compiler behavior returns to the state that was in effect at the beginning of the block.

16.2.5. The Floating-Point Environment

The floating-point environment consists of system variables for floating-point status flags and control modes. Status flags are set by operations that raise floating-point exceptions, such as division by zero. Control modes are features of floating-point arithmetic behavior that programs can set, such as the way in which results are rounded to representable values. Support for floating-point exceptions and control modes is optional.

All of the declarations involved in accessing the floating-point environment are contained in the header fenv.h (see Chapter 15).

Programs that access the floating-point environment should inform the compiler beforehand by means of the following standard pragma:

    #pragma STDC FENV_ACCESS ON

This directive prevents the compiler from applying optimizations, such as changes in the order in which expressions are evaluated, that might interfere with querying status flags or applying control modes.

FENV_ACCESS can be applied in the same ways as FP_CONTRACT and CX_LIMITED_RANGE: outside all functions, or locally within a block (see the preceding section). It is up to the compiler whether the default state of FENV_ACCESS is ON or OFF.

16.2.5.1. Accessing status flags

The functions in Table 16-9 allow you to access the exception status flags. One argument to these functions indicates the kind or kinds of exceptions to operate on. The following integer macros are defined in the header fenv.h to designate the individual exception types:

    FE_DIVBYZERO  FE_INEXACT  FE_INVALID  FE_OVERFLOW  FE_UNDERFLOW

Each of these macros is defined only if the implementation supports the corresponding exception. The macro FE_ALL_EXCEPT designates all the supported exception types.

Table 16-9. Functions giving access to the floating-point exceptions

Purpose

Function

Test floating-point exceptions

fetestexcept( )

Clear floating-point exceptions

feclearexcept( )

Raise floating-point exceptions

feraiseexcept( )

Save floating-point exceptions

fegetexceptflag( )

Restore floating-point exceptions

fesetexceptflag( )


16.2.5.2. Rounding modes

The floating-point environment also includes the rounding mode currently in effect for floating-point operations. The header fenv.h defines a distinct integer macro for each supported rounding mode. Each of the following macros is defined only if the implementation supports the corresponding rounding direction:

    FE_DOWNWARD  FE_TONEAREST  FE_TOWARDZERO  FE_UPWARD

Implementations may also define other rounding modes and macro names for them. The values of these macros are used as return values or as argument values by the functions listed in Table 16-10.

Table 16-10. Rounding mode functions

Purpose

Function

Get the current rounding mode

fegetround( )

Set a new rounding mode

fesetround( )


16.2.5.3. Saving the whole floating-point environment

The functions listed in Table 16-11 operate on the floating-point environment as a whole, allowing you to save and restore the floating-point environment's state.

Table 16-11. Functions that operate on the whole floating-point environment

Purpose

Function

Save the floating-point environment

Restore the floating-point environment

fegetenv( )

fesetenv( )

Save the floating-point environment and switch to nonstop processing

feholdexcept( )a

Restore a saved environment and raise any exceptions that are currently set

feupdateenv( )

aIn the nonstop processing mode activated by a call to feholdexcept( ), floating-point exceptions do not interrupt program execution.


16.2.6. Error Handling

C99 defines the behavior of the functions declared in math.h in cases of invalid arguments or mathematical results that are out of range. The value of the macro math_errhandling, which is constant throughout a program's runtime, indicates whether the program can handle errors using the global error variable errno, or the exception flags in the floating-point environment, or both.

16.2.6.1. Domain errors

A domain error occurs when a function is mathematically not defined for a given argument value. For example, the real square root function sqrt( ) is not defined for negative argument values. The domain of each function in math.h is indicated in the description in Chapter 17.

In the case of a domain error, functions return a value determined by the implementation. In addition, if the expression math_errhandling & MATH_ERRNO is not equal to zeroin other words if the expression is truethen a function incurring a domain error sets the error variable errno to the value of EDOM. If the expression math_errhandling & MATH_ERREXCEPT is true, then the function raises the floating-point exception FE_INVALID.

16.2.6.2. Range errors

A range error occurs if the mathematical result of a function is not representable in the function's return type without a substantial rounding error. An overflow occurs if the range error is due to a mathematical result whose magnitude is finite, but too large to be represented by the function's return type. If the default rounding mode is in effect when an overflow occurs, or if the exact result is infinity, then the function returns the value of HUGE_VAL (or HUGE_VALF or HUGE_VALL, if the function's type is float or long double) with the appropriate sign. In addition, if the expression math_errhandling & MATH_ERRNO is true, then the function sets the error variable errno to the value of ERANGE. If the expression math_errhandling & MATH_ERREXCEPT is true, then an overflow raises the exception FE_OVERFLOW if the mathematical result is finite, or FE_DIVBYZERO if it is infinite.

An underflow occurs when a range error is due to a mathematical result whose magnitude is nonzero, but too small to be represented by the function's return type. When an underflow occurs, the function returns a value which is defined by the implementation, but less than or equal to the value of DBL_MIN (or FLT_MIN, or LDBL_MIN, depending on the function's type). The implementation also determines whether the function sets the error variable errno to the value of ERANGE if the expression math_errhandling & MATH_ERRNO is true. Furthermore, the implementation defines whether an underflow raises the exception FE_UNDERFLOW if the expression math_errhandling & MATH_ERREXCEPT is true.


Previous Page
Next Page