A companion set of functions stores a correction term providing 20 extra bits in a variable pointed to by a final argument:cc [ flags ] -I/usr/local/include file(s) [ -L/usr/local/lib ] -lmcr [ -lm ] [ ... ]#include <libmcr.h>

## DESCRIPTION

libmcr, the correctly-roundedlibm, developed by Sun Microsystems, provides implementations of several common elementary functions in C datatypedoublethat are guaranteed to be correctly rounded to the nearest representable floating-point value, with ties to even, over their entire argument domain. This library is available under the Sun Microsystems' Inc. Public License and can be installed on certain modern computers that implement the IEEE 754 floating-point system. It can be linked with user code on Unix systems by using-lmcrbefore any native math library option,-lm. Depending on the operating system and compiler, it may be necessary to provide the-L/usr/local/liboption to identify the library installation path. On GNU/Linux AMD64 systems, that path is for 32-bit libraries; use-L/usr/local/lib64for the default 64-bit environment. Additional options may be required on some systems, as described later in theCAVEATSsection. Thelibmcrfunctions have names distinct from those used in the ISO Standard C math Library, but wrappers are provided to make them available under their standard names. If only the latter names are used, then the standard header file<math.h>provides the necessary function prototypes. If the distinct names are used, then the header file<libmcr.h>must also be included. The available functions are named with a distinctive prefix:double __libmcr_atan (double);double __libmcr_cos (double);double __libmcr_exp (double);double __libmcr_log (double);double __libmcr_pow (double, double);double __libmcr_sin (double);double __libmcr_tan (double);

The wrappers provide access to these functions through the ISO C Standarddouble __libmcr_mx_atan(double, double *);double __libmcr_mx_cos(double, double *);double __libmcr_mx_exp(double, double *);double __libmcr_mx_log(double, double *);double __libmcr_mx_pow(double, double, double *);double __libmcr_mx_sin(double, double *);double __libmcr_mx_tan(double, double *);

double cos (double x) { return __libmcr_cos(x); }float cosf (float x) { return (float)__libmcr_cos((double)x); }

A separate set of wrappers makes these functions available to Fortran 77, 90, and 95 code. That language passes scalar arguments by address, rather than by value, and most Unix Fortran compilers append an underscore to external names to keep them distinct from names in the C library. Typical wrappers look like this:

double dcos_ (double *px) { return __libmcr_cos(*px); }float cos_ (float *px) { return (float)__libmcr_cos((double)(*px)); }double __libmcr_cos_ (double *px) { return __libmcr_cos(*px); }double __libmcr_mx_cos_ (double *px, double *pc){ return __libmcr_mx_cos(*px, pc); }

The functions would then be declared and used in Fortran like this:

double precision dcos, __libmcr_cosreal cosexternal cos, dcos, __libmcr_cos, __libmcr_mx_cosdouble precision corr, xx, yyreal x, y...y = cos(x)yy = dcos(xx)yy = __libmcr_cos(xx)yy = __libmcr_mx_cos(xx, corr)

If functions with the `__libmcr_`-prefixed names are invoked, and the
`-lm` option *precedes* the `-lmcr` option, then it
is possible to use both the **libmcr** functions and the native C or
Fortran routines in the same program. This feature could be used, for
example, to compare the accuracy of the native functions with the
ultimate ones.

Even though the ISO C Standard has a strict separation between the language and the library, and has no reserved library function names, some C and C++ compilers recognize certain math library function names, and replace calls to them with calls to internal math library functions, or with hardware instruction sequences that compute the functions inline.

With such compilers, it may be necessary to supply an additional compile-time option to suppress this unwanted substitution, and ensure that the ultimate functions are used instead.

For example, with the GNU C compiler family, the Open64 compilers, and
the PathScale compilers, the option `-fno-builtin` must be used
for this purpose. Fine-grained control is possible by appending the
function name to the option: `-fno-builtin-exp` only prevents
replacement of the exponential function.

The Portland Group compilers provide a similar feature with the
`-Mnobuiltin` option.

The Sun Microsystems compilers have the option `-xbuiltin=%none`
for this purpose.

None of these libraries provides correctly-rounded functions of type
`long double`. Implementation of such functions remains a
challenging research problem in 2008, and almost always requires
arithmetic of even higher precision: that arithmetic must then be
provided in software.