Mathematical Functions

For the development of this module, the functions present in many of the system libraries are taken as reference with the idea of offering them in CML as an option for when they are not present.

This chapter describes basic mathematical functions.

The functions and macros described in this chapter are defined in the header file cml/math.h.

Mathematical Constants

The library ensures that the standard BSD mathematical constants are defined. For reference, here is a list of the constants:

M_E The base of exponentials, e
M_LOG2E The base-2 logarithm of e, \log_2 (e)
M_LOG10E The base-10 logarithm of e, \log_{10} (e)
M_SQRT2 The square root of two, \sqrt 2
M_SQRT1_2 The square root of one-half, \sqrt{1/2}
M_SQRT3 The square root of three, \sqrt 3
M_PI The constant pi, \pi
M_PI_2 Pi divided by two, \pi/2
M_PI_4 Pi divided by four, \pi/4
M_SQRTPI The square root of pi, \sqrt\pi
M_2_SQRTPI Two divided by the square root of pi, 2/\sqrt\pi
M_1_PI The reciprocal of pi, 1/\pi
M_2_PI Twice the reciprocal of pi, 2/\pi
M_LN10 The natural logarithm of ten, \ln(10)
M_LN2 The natural logarithm of two, \ln(2)
M_LNPI The natural logarithm of pi, \ln(\pi)
M_EULER Euler’s constant, \gamma

Infinities and Not-a-number

CML_POSINF

This macro contains the IEEE representation of positive infinity, +\infty. It is computed from the expression +1.0/0.0.

CML_NEGINF

This macro contains the IEEE representation of negative infinity, -\infty. It is computed from the expression -1.0/0.0.

CML_NAN

This macro contains the IEEE representation of the Not-a-Number symbol, NaN. It is computed from the ratio 0.0/0.0.

bool cml_isnan(double x)

This function returns 1 if x is not-a-number.

bool cml_isinf(double x)

This function returns +1 if x is positive infinity, -1 if x is negative infinity and 0 otherwise. [1]

bool cml_isfinite(double x)

This function returns 1 if x is a real number, and 0 if it is infinite or not-a-number.

Elementary Functions

The following routines provide portable implementations of functions found in the BSD math library, e.g. When native versions are not available the functions described here can be used instead. The substitution can be made automatically if you use autoconf to compile your application (see portability-functions).

double cml_log1p(double x)

This function computes the value of \log(1+x) in a way that is accurate for small x. It provides an alternative to the BSD math function log1p(x).

double cml_expm1(double x)

This function computes the value of \exp(x)-1 in a way that is accurate for small x. It provides an alternative to the BSD math function expm1(x).

double cml_hypot(double x, double y)

This function computes the value of \sqrt{x^2 + y^2} in a way that avoids overflow. It provides an alternative to the BSD math function hypot(x,y).

double cml_hypot3(double x, double y, double cml_x)

This function computes the value of \sqrt{x^2 + y^2 + x^2} in a way that avoids overflow.

double cml_acosh(double x)

This function computes the value of \arccosh{(x)}. It provides an alternative to the standard math function acosh(x).

double cml_asinh(double x)

This function computes the value of \arcsinh{(x)}. It provides an alternative to the standard math function asinh(x).

double cml_atanh(double x)

This function computes the value of \arctanh{(x)}. It provides an alternative to the standard math function atanh(x).

double cml_ldexp(double x, int e)

This function computes the value of x * 2^e. It provides an alternative to the standard math function ldexp(x,e).

double cml_frexp(double x, int *e)

This function splits the number x into its normalized fraction f and exponent e, such that x = f * 2^e and 0.5 <= f < 1. The function returns f and stores the exponent in e. If x is zero, both f and e are set to zero. This function provides an alternative to the standard math function frexp(x, e).

double cml_sqrt(double x)

This function returns the square root of the number x, \sqrt z. The branch cut is the negative real axis. The result always lies in the right half of the plane.

double cml_pow(double x, double a)

The function returns the number x raised to the double-precision power a, x^a. This is computed as \exp(\log(x)*a) using logarithms and exponentials.

double cml_exp(double x)

This function returns the exponential of the number x, \exp(x).

double cml_log(double x)

This function returns the natural logarithm (base e) of the number x, \log(x). The branch cut is the negative real axis.

double cml_log10(double x)

This function returns the base-10 logarithm of the number x, \log_{10} (x).

double cml_log_b(double x, double b)

This function returns the base-b logarithm of the double-precision number x, \log_b(x). This quantity is computed as the ratio \log(x)/\log(b).

Trigonometric Functions

double cml_sin(double x)

This function returns the sine of the number x, \sin(x).

double cml_cos(double x)

This function returns the cosine of the number x, \cos(x).

double doublean(double x)

This function returns the tangent of the number x, \tan(x).

double cml_sec(double x)

This function returns the secant of the number x, \sec(x) = 1/\cos(x).

double cml_csc(double x)

This function returns the cosecant of the number x, \csc(x) = 1/\sin(x).

double cml_cot(double x)

This function returns the cotangent of the number x, \cot(x) = 1/\tan(x).

Inverse Trigonometric Functions

double cml_asin(double x)

This function returns the arcsine of the number x, \arcsin(x).

double cml_acos(double x)

This function returns the arccosine of the number x, \arccos(x).

double cml_atan(double x)

This function returns the arctangent of the number x, \arctan(x).

double cml_asec(double x)

This function returns the arcsecant of the number x, \arcsec(x) = \arccos(1/x).

double cml_acsc(double x)

This function returns the arccosecant of the number x, \arccsc(x) = \arcsin(1/x).

double cml_acot(double x)

This function returns the arccotangent of the number x, \arccot(x) = \arctan(1/x).

Hyperbolic Functions

double cml_sinh(double x)

This function returns the hyperbolic sine of the number x, \sinh(x) = (\exp(x) - \exp(-x))/2.

double cml_cosh(double x)

This function returns the hyperbolic cosine of the number x, \cosh(x) = (\exp(x) + \exp(-x))/2.

double doubleanh(double x)

This function returns the hyperbolic tangent of the number x, \tanh(x) = \sinh(x)/\cosh(x).

double cml_sech(double x)

This function returns the hyperbolic secant of the double-precision number x, \sech(x) = 1/\cosh(x).

double cml_csch(double x)

This function returns the hyperbolic cosecant of the double-precision number x, \csch(x) = 1/\sinh(x).

double cml_coth(double x)

This function returns the hyperbolic cotangent of the double-precision number x, \coth(x) = 1/\tanh(x).

Inverse Hyperbolic Functions

double cml_asinh(double x)

This function returns the hyperbolic arcsine of the number x, \arcsinh(x).

double cml_acosh(double x)

This function returns the hyperbolic arccosine of the double-precision number x, \arccosh(x).

double cml_atanh(double x)

This function returns the hyperbolic arctangent of the double-precision number x, \arctanh(x).

double cml_asech(double x)

This function returns the hyperbolic arcsecant of the double-precision number x, \arcsech(x) = \arccosh(1/x).

double cml_acsch(double x)

This function returns the hyperbolic arccosecant of the double-precision number x, \arccsch(x) = \arcsinh(1/x).

double cml_acoth(double x)

This function returns the hyperbolic arccotangent of the double-precision number x, \arccoth(x) = \arctanh(1/x).

Small integer powers

A common complaint about the standard C library is its lack of a function for calculating (small) integer powers. CML provides some simple functions to fill this gap. For reasons of efficiency, these functions do not check for overflow or underflow conditions.

double cml_pow_int(double x, int n)
double cml_pow_uint(double x, unsigned int n)

These routines computes the power x^n for integer n. The power is computed efficiently—for example, x^8 is computed as ((x^2)^2)^2, requiring only 3 multiplications.

double cml_pow_2(double x)
double cml_pow_3(double x)
double cml_pow_4(double x)
double cml_pow_5(double x)
double cml_pow_6(double x)
double cml_pow_7(double x)
double cml_pow_8(double x)
double cml_pow_9(double x)

These functions can be used to compute small integer powers x^2, x^3, etc. efficiently. The functions will be inlined when HAVE_INLINE is defined, so that use of these functions should be as efficient as explicitly writing the corresponding product expression:

#include <cml/math.h>
[...]
double y = pow_4(3.141);  /* compute 3.141**4 */

Testing the Sign of Numbers

double cml_sgn(double x)

This macro returns the sign of x. It is defined as ((x) >= 0 ? 1 : -1). Note that with this definition the sign of zero is positive (regardless of its IEEE sign bit).

Maximum and Minimum functions

Note that the following macros perform multiple evaluations of their arguments, so they should not be used with arguments that have side effects (such as a call to a random number generator).

CML_MAX(a, b)

This macro returns the maximum of a and b. It is defined as ((a) > (b) ? (a):(b)).

CML_MIN(a, b)

This macro returns the minimum of a and b. It is defined as ((a) < (b) ? (a):(b)).

Approximate Comparison of Floating Point Numbers

It is sometimes useful to be able to compare two floating point numbers approximately, to allow for rounding and truncation errors. The following function implements the approximate floating-point comparison algorithm proposed by D.E. Knuth in Section 4.2.2 of “Seminumerical Algorithms” (3rd edition).

bool cml_cmp(double x, double y, double epsilon)

This function determines whether x and y are approximately equal to a relative accuracy epsilon.

The relative accuracy is measured using an interval of size 2
\delta, where \delta = 2^k \epsilon and k is the maximum base-2 exponent of x and y as computed by the function frexp().

If x and y lie within this interval, they are considered approximately equal and the function returns 0. Otherwise if x <
y, the function returns -1, or if x > y, the function returns +1.

Note that x and y are compared to relative accuracy, so this function is not suitable for testing whether a value is approximately zero.

The implementation is based on the package fcmp by T.C. Belding.

Footnotes

[1]Note that the C99 standard only requires the system isinf() function to return a non-zero value, without the sign of the infinity. The implementation in some earlier versions of CML used the system isinf() function and may have this behavior on some platforms. Therefore, it is advisable to test the sign of x separately, if needed, rather than relying the sign of the return value from isinf().