cc [ flags ] -I/usr/local/include file(s) -L/usr/local/lib -lmcw [ ... ] #include <mathcw.h> extern float ereducef (float x, float c, int nc, const float cinv[], int *pn, float *perr, int b); extern double ereduce (double x, double c, int nc, const double cinv[], int *pn, double *perr, int b); extern long double ereducel (long double x, long double c, int nc, const long double cinv[], int *pn, long double *perr, int b); extern __float80 ereducew (__float80 x, __float80 c, int nc, const __float80 cinv[], int *pn, __float80 *perr, int b); extern __float128 ereduceq (__float128 x, __float128 c, int nc, const __float128 cinv[], int *pn, __float128 *perr, int b); extern long_long_double ereducell (long_long_double x, long_long_double c, int nc, const long_long_double cinv[], int *pn, long_long_double *perr, int b); extern decimal_float ereducedf (decimal_float x, decimal_float c, int nc, const decimal_float cinv[], int *pn, decimal_float *perr, int b); extern decimal_double ereduced (decimal_double x, decimal_double c, int nc, const decimal_double cinv[], int *pn, decimal_double *perr, int b); extern decimal_long_double ereducedl (decimal_long_double x, decimal_long_double c, int nc, const decimal_long_double cinv[], int *pn, decimal_long_double *perr, int b); extern decimal_long_long_double ereducedll (decimal_long_long_double x, decimal_long_long_double c, int nc, const decimal_long_long_double cinv[], int *pn, decimal_long_long_double *perr, int b);
NB: Functions with prototypes containing underscores in type names may be available only with certain extended compilers.
The inverse of the constant c is represented to high precision as an array of nc + 1 coefficients such that
1/c = sum(k = 0:nc) cinv[k] * (2**b)**(-k).The coefficients cinv[k] lie in [0,2**b - 1], and therefore require at most b bits each.
The computation of r and a few low-order bits of N is done with a highly-abbreviated form of multiple-precision arithmetic that is much faster than a brute-force multiple-precision arithmetic package could provide. This makes correctly-rounded argument reduction practical for many elementary functions, such as the trigonometric, logarithm, and exponential functions.
The computation requires exact representation of sums of a few products of two coefficients in a value of type double or larger. A suggested portable value for b is 20, which is suitable for historical and current floating-point systems.
The companion function family described in eriduce(3CW) does a similar computation using integer arithmetic and integer coefficients cinv[]. Which of these is faster depends on the platform and the value of b.