cc [ flags ] -I/usr/local/include file(s) -L/usr/local/lib -lmcw [ ... ] #include <mathcw.h> extern float eriducef (float x, float c, int nc, const float cinv[], int *pn, float *perr, int b); extern double eriduce (double x, double c, int nc, const double cinv[], int *pn, double *perr, int b); extern long double eriducel (long double x, long double c, int nc, const long double cinv[], int *pn, long double *perr, int b); extern __float80 eriducew (__float80 x, __float80 c, int nc, const __float80 cinv[], int *pn, __float80 *perr, int b); extern __float128 eriduceq (__float128 x, __float128 c, int nc, const __float128 cinv[], int *pn, __float128 *perr, int b); extern long_long_double eriducell (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 eriducedf (decimal_float x, decimal_float c, int nc, const decimal_float cinv[], int *pn, decimal_float *perr, int b); extern decimal_double eriduced (decimal_double x, decimal_double c, int nc, const decimal_double cinv[], int *pn, decimal_double *perr, int b); extern decimal_long_double eriducedl (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 eriducedll (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 int. A suggested portable value for b is 12, which is suitable for many historical and all current floating-point systems.
The companion function family described in ereduce(3CW) does a similar computation using floating-point arithmetic and floating-point coefficients in cinv[]. Which of these is faster depends on the platform and the value of b.