C supports a variety of useful mathematical functions. Different functions apply to different datatypes. For example, randomization functions apply to integers, whereas trigonometric functions apply to floating-point values.
The mathematical functions for the types int and long are declared in stdlib.h.
int rand( void );
Generates a random number between 0 and RAND_MAX. The constant RAND_MAX has a value of at least 32767, or 215 - 1.
void srand ( unsigned n );
Initializes the random number generator with the seed n. After this function has been called, calls to rand() generate a new sequence of random numbers.
int abs ( int x );
Returns the absolute value of x.
div_t div ( int x , int y );
Divides x by y and stores the integer part of the quotient and the remainder in a structure of type div_t, whose members quot (the quotient) and rem (the remainder) have type int. The type div_t is defined in stdlib.h.
The corresponding (to abs() and div()) functions labs(), llabs()(*), lldiv()(*), and ldiv() are also provided for integers of type long long(*). Furthermore, the functions imaxabs()(*) and imaxdiv()(*) are defined for the type intmax_t(*). These functions are declared in inttypes.h(*).
The mathematical functions declared in math.h were originally defined only for double values, with return values and parameters of type double. These functions are shown in Table 1-30.
ANSI C99 introduces new versions of the functions listed in Table 1-30 for the types float and long double. The names of these functions end with f or l; for example:
double cos( double x );
float cosf( float x );
long double cosl( long double x );
New standard mathematical functions for real numbers have also been added in math.h, as listed in Table 1-31. These functions also have versions for float and long double, with names ending in f and l.
Macros for comparing floating-point numbers are also defined in math.h and are listed in Table 1-32. Unlike the comparative operators, these macros do not raise the FE_INVALID exception when the arguments cannot be compared, as when one of them is a NAN, for example.
ANSI C99 has introduced features to optimize the efficiency of floating-point operations.
The types float_t and double_t, defined in math.h, represent the types used internally in floating-point arithmetic. When these types are used in a program, no conversions are necessary before arithmetic operations are performed. The macro FLT_EVAL_METHOD indicates what the equivalent basic types are, and returns one of the values described in Table 1-33.
Table 1-33. Interpretation of float_t and double_t |
||
FLT_EVAL_METHOD |
Type represented by float_t |
Type represented by double_t |
0 |
float |
double |
1 |
double |
double |
2 |
long double |
long double |
CPUs may have special machine instructions to perform standard arithmetic operations quickly. Rounding and error conditions may also be ignored. Optimizations of these kinds can be enabled by the pragma FP_CONTRACT. For example:
#pragma STDC FP_CONTRACT ON
The same pragma with the switch OFF rather than ON disables such optimizations.
Furthermore, the macro FP_FAST_FMA is defined if the "floating-point multiply-add" function fma( x, y, z ), which returns x*y+z, is implemented as a special instruction, and is thus faster than separate multiplication and addition operations. The macros FP_FAST_FMAF and FP_FAST_FMAL are analogous indicators for the functions fmaf() and fmal().
Functions and macros for complex numbers are declared in the header file complex.h(*). The functions shown in Table 1-34 have one parameter and return a value of type double complex.
The functions shown in Table 1-35 have one parameter of type double complex and return a value of type double.
These functions also have versions for float complex and long double complex, with names ending in f and l.
Table 1-36 shows macros that are defined for complex types.
Arithmetic operations with complex numbers can be accelerated in cases when no overflow or underflow can occur. The programmer can signal such "safe" operations using the pragma:
#pragma STDC CX_LIMITED_RANGE ON
The default setting is OFF.
The type-generic macros defined in header file tgmath.h are unified names that can be used to call the different mathematical functions for specific real and complex floating types.
If a given function is defined for real or for both real and complex floating types, then the type-generic macro name is the same as the name of the function version with type double. (The real function modf() is an exception, however, for which there is no type-generic macro.)
The type-generic macros always call the function that matches the type of the arguments. For example:
complex z = 1.0 + 2.1*I;
cos( z ); // Calls ccos()
ceil( 7.1L ); // Calls ceill()
Type-generic macros are also defined for the complex functions for which there are no corresponding real functions: carg(), conj(), creal(), cimag(), and cproj(). These macros always call the corresponding complex function, if the argument is a real floating-point number or a complex number.
Error conditions are customarily detected by examining the return value of a function and/or the global error variable errno. The variable errno is declared with type int in the header file errno.h.
If a function is passed an argument that is outside the domain for which the function is defined, a "domain error" occurs, and errno is assigned the value of the macro EDOM. Similarly, if the result of a function cannot be represented by the type of the function's return value, then a "range error" occurs, and errno is assigned the value ERANGE. In the case of an overflow—that is, if the magnitude of the result is too great for the specified type—the function returns the value of the macro HUGE_VAL, with the appropriate sign. In case of an underflow—i. e., the magnitude of the result is too small—the function returns 0.
In addition to HUGE_VAL (with type double), ANSI C99 also provides the macros HUGE_VALF (type float) and HUGE_VALL (type long double), which are returned by functions of the corresponding types.
Furthermore, ANSI C99 introduces the macros FP_ILOGB0 and FP_ILOGBNAN. The function ilogb( x ) returns FP_ILOGB0 if x is equal to 0. If x is "not a number" (NaN), ilogb( x ) returns the value of FP_ILOGBNAN.
ANSI C99 has introduced the floating-point environment to permit more detailed representation of error conditions in floating-point arithmetic. All of the declarations for the floating-point environment are contained in the header file fenv.h(*). The floating-point environment contains two system variables: one for the status flags, which are used in handling floating-point exceptions, and one for the control modes, which determine certain behaviors of floating-point arithmetic, such as the rounding method used.
For every exception possible in an implementation that supports floating-point exceptions, an appropriate status flag is defined, as described in Table 1-37.
Several of these constants can be combined by a bitwise OR (|). The macro FE_ALL_EXCEPT is equal to the bitwise OR of all of the floating-point exception constants implemented. The system variable for the floating-point exception status has the type fexcept_t.
The following functions are used to handle floating-point exceptions. With the exception of fetestexcept(), each function returns 0 to indicate success, or a value other than 0 in case of errors. The excepts argument indicates which of the exceptions listed in Table 1-37 are affected.
int fetestexcept ( int excepts );
Tests which of the specified floating-point exceptions are set. Bits are set in the return value to correspond to the exceptions that are currently set.
int feclearexcept ( int excepts );
Clears the specified floating-point exceptions.
int feraiseexcept ( int excepts );
Raises the specified floating-point exceptions.
int fegetexceptflag ( fexcept_t *flagp , int excepts );
Saves the status of the specified exceptions in the object referenced by flagp.
int fesetexceptflag ( const fexcept_t *flagp ,
int excepts );
Sets the exception status according to the flags previously saved (by fegetexceptflag()) in the object referenced by flagp.
The control mode determines certain properties of floating-point arithmetic, including the rounding method used. The symbolic constants described in Table 1-38 are defined for this purpose.
The current rounding direction can be read and changed using the functions int fegetround() and int fesetround( int round ).
The following functions manipulate the floating-point environment as a single entity. The type fenv_t represents the entire floating-point environment.
int fegetenv ( fenv_t *envp );
Saves the current floating-point environment in the object referenced by envp.
int fesetenv ( const fenv_t *envp );
Establishes the floating-point environment referenced by envp.
int feholdexcept ( fenv_t *envp );
Saves the current floating-point environment in the object referenced by envp, then clears the status flags and installs a non-stop mode, so that processing continues in case of further floating-point exceptions.
int feupdateenv ( const fenv_t *envp );
Establishes the floating-point environment referenced by envp, and then raises the exceptions that were set in the saved environment.
The macro FE_DFL_ENV is a pointer to the floating-point environment that is installed at program start-up, and can be used as an argument in the functions fesetenv() and feupdateenv().
The floating-point environment need not be active in an implementation that supports it. It can be activated by the pragma:
#pragma STDC FENV_ACCESS ON
and deactivated by the same pragma with the switch OFF.
The macro math_errhandling, defined in math.h, can be used to determine whether the program uses errno and/or the floating-point environment:
· If the expression math_errhandling & MATH_ERRNO is not 0, then the error variable errno is used.
· If the expression math_errhandling & MATH_ERREXCEPT is not 0, then floating-point errors raise the exceptions defined in fenv.h.