Mathematical Functions

1.18 Mathematical Functions

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.

1.18.1 Mathematical Functions for Integer Types

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(*).

1.18.2 Mathematical Functions for Real Floating Types

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.

Table 1-30. The traditional mathematical functions for double values

Mathematical function

C function

Trigonometric functions:

         Sine, cosine, tangent

         Arcsine, arccosine

         Arctangent

sin(), cos(), tan()
asin(), acos()
atan(), atan2()

Hyperbolic functions

sinh(), cosh(), tanh()

Powers, square root

pow(), sqrt(),

Exponential functions

exp(), frexp(), ldexp()

Logarithms

log(), log10()

Next integer

ceil(), floor()

Absolute value

fabs()

Remainder (modular division)

fmod()

Separation of integer and fractional parts

modf()

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.

Table 1-31. New mathematical functions for double values in ANSI C99

Mathematical function

C function

Trigonometric functions

asinh(), acosh(), atanh()

Exponential functions

exp2(), expm1()

Logarithms

ilogb(), logb(), log1p(), log2()

Roots

cbrt(), hypot()

Remainder

remainder(), remquo()

Positive difference

fdim()

Minimum and maximum

fmin(), fmax()

Rounding

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

Next number

nearbyint(), nextafter(), nexttoward()

Copy sign

copysign()

Optimized operations

scalbn(), scalbln(), fma()

Gamma function

tgamma(), lgamma()

Error functions

erf(), erfc()

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.

Table 1-32. Macros for comparing floating-point numbers

Macro

Comparative expression

isgreater( x, y )
(x) > (y)
isgreaterequal( x, y )
(x) >= (y)
isless( x, y )
(x) < (y)
islessequal( x, y )
(x) <= (y)
islessgreater( x, y )
(x) < (y) || (x) > (y)
isunordered( x, y )

1 if x and y cannot be compared, otherwise 0

1.18.3 Optimizing Runtime Efficiency

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().

1.18.4 Mathematical Functions for Complex Floating Types

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.

Table 1-34. Mathematical functions for the type double complex

Mathematical function

C function

Trigonometric functions:

         Sine, cosine, tangent

         Arcsine, arccosine

         Arctangent

csin(), ccos(), ctan()
casin(), cacos()
catan()

Hyperbolic functions

csinh(), ccosh(), ctanh(), casinh(), cacosh(), catanh()

Powers, square root

cpow(), csqrt()

Exponential function

cexp()

Logarithm

clog()

Complex conjugate

conj()

The functions shown in Table 1-35 have one parameter of type double complex and return a value of type double.

Table 1-35. Complex functions with type double

Mathematical function

C function

Absolute value

cabs()

Argument (phase angle)

carg()

Real and imaginary parts

creal(), cimag()

Projection onto the Riemann sphere

cproj()

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.

Table 1-36. Macros for complex types

Macro

Replacement value

complex
_Complex
_Complex_I

The imaginary unit, i. e., the number i such that i2 = -1, with type const float _Complex

imaginary
_Imaginary
_Imaginary_I

The imaginary unit, with type const float _Imaginary

I

_Imaginary_I if the compiler supports the type _Imaginary, otherwise _Complex_I

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.

1.18.5 Type-Generic Macros

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.

1.18.6 Error Handling for Mathematical Functions

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.

1.18.7 The Floating-Point Environment

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.

Table 1-37. Macros for floating-point exceptions in fenv.h(*)

Macro

Error condition

FE_DIVBYZERO

Division by 0

FE_INEXACT

The result of the operation is not exact

FE_INVALID

The result is undefined, e.g., a value was outside the domain for which the function is defined

FE_OVERFLOW

A floating-point overflow occurred

FE_UNDERFLOW

An underflow occurred

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.

Table 1-38. Controlling rounding behavior

Macro

Rounding direction

FE_DOWNWARD

Round down to the next lower value.

FE_TONEAREST

Round to the nearest value.

FE_TOWARDZERO

Truncate.

FE_UPWARD

Round up to the next higher value.

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.

 



C Pocket Reference
C Pocket Reference
ISBN: 0596004362
EAN: 2147483647
Year: 2002
Pages: 29

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net