LIBMCR 3 "16 February 2008" "libmcr-0.9"

Table of contents


libmcr - correctly-rounded elementary-function library


cc [ flags ] -I/usr/local/include file(s) [ -L/usr/local/lib ] -lmcr [ -lm ] [ ... ]

#include <libmcr.h>


libmcr, the correctly-rounded libm, developed by Sun Microsystems, provides implementations of several common elementary functions in C datatype double that 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 -lmcr before any native math library option, -lm. Depending on the operating system and compiler, it may be necessary to provide the -L/usr/local/lib option to identify the library installation path. On GNU/Linux AMD64 systems, that path is for 32-bit libraries; use -L/usr/local/lib64 for the default 64-bit environment. Additional options may be required on some systems, as described later in the CAVEATS section. The libmcr functions 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);
A companion set of functions stores a correction term providing 20 extra bits in a variable pointed to by a final argument:
double __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 *);
The wrappers provide access to these functions through the ISO C Standard float and double function names. For example, the wrappers for the cosine function are defined like this:
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_cos
      real cos
      external cos, dcos, __libmcr_cos, __libmcr_mx_cos
      double precision corr, xx, yy
      real 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.


Return the correctly-rounded elementary function value.


The float wrappers involve a second rounding from the conversion of the double function value to float. In rare cases, expected with probability 1 in 2**29 or 1 in 536870912, the float value may be rounded incorrectly, differing by one unit in the last place (one ulp) from the correct value.

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.


Two other libraries, -lcrlibm and -lultim, developed at the École Nationale Supérieure-Lyon, INRIA-Lorraine, and the Université de Perpignan (-lcrlibm) and IBM (-lultim), also provide correctly-rounded mathematical functions, although their function repertoires differ somewhat from that of -lmcr.

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.


atan(3), cos(3), exp(3), gcc(1), libcrlibm(3), libmcr(3), log(3), mathcw(3CW), opencc(1), pathcc(1), pgcc(1), pow(3), sin(3), suncc(1), tan(3).