ERIDUCE 3CW "01 June 2009" "mathcw-1.00"

Table of contents


NAME

eriducef, eriduce, eriducel, eriducew, eriduceq, eriducell, eriducedf, eriduced, eriducedl, eriducedll - exact argument reduction

SYNOPSIS

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.


DESCRIPTION

Given a floating-point number x and a (usually irrational) positive constant c, find a reduced value r in [-c/2,+c/2] such that x = Nc + r for some integer N (possibly too large to represent in a standard integer data type).

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.


CAVEAT

A temporary limitation prevents implementation of the decimal versions of these functions: they can be called, but they fail immediately with an assertion error and core dump.

RETURN VALUES

Return the reduced number r as the function value, and return the eight low-order bits of N via the pointer pn, if it is not NULL. If perr is not NULL, return via that pointer a correction which, when summed with the return value, represents the reduced arithmetic to roughly twice working precision.

ERRORS

If the argument is a NaN, return that argument and set errno to EDOM. If the argument is +Infinity, return that argument and set errno to ERANGE.

SEE ALSO

ereduce(3CW).