LIBULTIM 3 "16 February 2008" "apmathlib-20080216"

Table of contents


libultim - ultimate correctly-rounded elementary-function library


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

#include <MathLib.h>


APMathLib, the IBM Accurate Portable Mathematical Library, provides ultimate 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 GNU General Public License and can be installed on most modern computers that implement the IEEE 754 floating-point system. It can be linked with user code on Unix systems by using -lultim 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 APMathLib 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 <MathLib.h> must also be included. The available functions are named with the prefix letter u:
double uacos ( double ); double uasin ( double ); double uatan ( double ); double uatan2 ( double, double ); double ucos ( double ); double ucot ( double ); double uexp ( double ); double uexp2 ( double ); double ulog ( double ); double ulog2 ( double ); double upow ( double, double ); double uremainder ( double, double ); double usin ( double ); double usqrt ( double ); double utan ( double );
The wrappers provide access to these functions through the ISO C Standard float and double function names. For example, the wrappers for the inverse cosine function are defined like this:
double acos  (double x) { return uacos(x); }
float  acosf (float x)  { return (float)uacos((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 dacos_ (double *x) { return uacos(*x); }
float  acos_  (float *x)  { return (float)uacos((double)(*x)); }
double uacos_ (double *x) { return uacos(*x); }

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

      double precision dacos, uacos
      real acos
      external acos, dacos, uacos
      double precision xx, yy
      real x, y
      y = acos(x)
      yy = dacos(xx)
      yy = uacos(xx)

If functions with the u-prefixed names are invoked, and the -lm option precedes the -lultim option, then it is possible to use both the APMathLib 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 -lmcr, developed at the École Nationale Supérieure-Lyon, INRIA-Lorraine, and the Université de Perpignan (-lcrlibm) and Sun Microsystems (-lmcr), respectively, also provide correctly-rounded mathematical functions, although their function repertoires differ somewhat from that of -lultim.

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.


acos(3), asin(3), atan(3), atan2(3), cos(3), cot(3), exp(3), exp2(3), gcc(1), libcrlibm(3), libmcr(3), log(3), log2(3), mathcw(3CW), opencc(1), pathcc(1), pgcc(1), pow(3), remainder(3), sin(3), sqrt(3), suncc(1), tan(3).