******************************** * Announcing FDLIBM Version 5 * ******************************** ============================================================ FDLIBM ============================================================ (developed at SunPro, a Sun Microsystems, Inc. business.) Version 5.1, 93/09/24 FDLIBM (Freely Distributable LIBM) is a C math library for machines that support IEEE 754 floating-point arithmetic. In this release, only double precision is supported. FDLIBM is intended to provide a reasonably portable (see assumptions below), reference quality (below one ulp for major functions like sin,cos,exp,log) math library (libm.a). For a copy of FDLIBM, please send e-mail to fdlibm-comments@sunpro.eng.sun.com -------------- 1. ASSUMPTIONS -------------- FDLIBM (double precision version) assumes: a. IEEE 754 style (if not precise compliance) arithmetic; b. 32 bit 2's complement integer arithmetic; c. Each double precision floating-point number must be in IEEE 754 double format, and that each number can be retrieved as two 32-bit integers; Example: let y = 2.0 double fp number y: 2.0 IEEE double format: 0x4000000000000000 Referencing y as two integers: *(int*)&y,*(1+(int*)&y) = {0x40000000,0x0} (on sparc) {0x0,0x40000000} (on 386) Note: FDLIBM will detect, at run time, the correct ordering of the high and low part of a floating-point number. d. IEEE exceptions may trigger "signals" as is common in Unix implementations. ------------------- 2. EXCEPTION CASES ------------------- All exception cases in the FDLIBM functions will be mapped to one of the following four exceptions: +-huge*huge, +-tiny*tiny, +-1.0/0.0, +-0.0/0.0 (overflow) (underflow) (divided-by-zero) (invalid) For example, log(0) is a singularity and is thus mapped to -1.0/0.0 = -infinity. That is, FDLIBM's log will compute -one/zero and return the computed value. On an IEEE machine, this will trigger the divided-by-zero exception and a negative infinity is returned by default. Similarly, exp(-huge) will be mapped to tiny*tiny to generate an underflow signal. -------------------------------- 3. STANDARD CONFORMANCE WRAPPER -------------------------------- The default FDLIBM functions (compiled with -D_IEEE_LIBM flag) are in "IEEE spirit" (i.e., return the most reasonable result in floating-point arithmetic). If one wants FDLIBM to comply with standards like SVID, X/OPEN, or POSIX/ANSI, then one can create a multi-standard compliant FDLIBM. In this case, each function in FDLIBM is actually a standard compliant wrapper function. File organization: 1. For FDLIBM's kernel (internal) function, File name Entry point --------------------------- k_sin.c __kernel_sin k_tan.c __kernel_tan --------------------------- 2. For functions that have no standards conflict File name Entry point --------------------------- s_sin.c sin s_erf.c erf --------------------------- 3. Ieee754 core functions File name Entry point --------------------------- e_exp.c __ieee754_exp e_sinh.c __ieee754_sinh --------------------------- 4. Wrapper functions File name Entry point --------------------------- w_exp.c exp w_sinh.c sinh --------------------------- Wrapper functions will twist the result of the ieee754 function to comply to the standard specified by the value of _LIB_VERSION if _LIB_VERSION = _IEEE_, return the ieee754 result; if _LIB_VERSION = _SVID_, return SVID result; if _LIB_VERSION = _XOPEN_, return XOPEN result; if _LIB_VERSION = _POSIX_, return POSIX/ANSI result. (These are macros, see fdlibm.h for their definition.) -------------------------------- 4. HOW TO CREATE FDLIBM's libm.a -------------------------------- There are two types of libm.a. One is IEEE only, and the other is multi-standard compliant (supports IEEE,XOPEN,POSIX/ANSI,SVID). To create the IEEE only libm.a, use make "CFLAGS = -D_IEEE_LIBM" This will create an IEEE libm.a, which is smaller in size, and somewhat faster. To create a multi-standard compliant libm, use make "CFLAGS = -D_IEEE_MODE" --- multi-standard fdlibm: default to IEEE make "CFLAGS = -D_XOPEN_MODE" --- multi-standard fdlibm: default to X/OPEN make "CFLAGS = -D_POSIX_MODE" --- multi-standard fdlibm: default to POSIX/ANSI make "CFLAGS = -D_SVID3_MODE" --- multi-standard fdlibm: default to SVID Here is how one makes a SVID compliant libm. Make the library by make "CFLAGS = -D_SVID3_MODE". The libm.a of FDLIBM will be multi-standard compliant and _LIB_VERSION is initialized to the value _SVID_ . example1: --------- main() { double y0(); printf("y0(1e300) = %1.20e\n",y0(1e300)); exit(0); } % cc example1.c libm.a % a.out y0: TLOSS error y0(1e300) = 0.00000000000000000000e+00 It is possible to change the default standard in multi-standard fdlibm. Here is an example of how to do it: example2: --------- #include "fdlibm.h" /* must include FDLIBM's fdlibm.h */ main() { double y0(); _LIB_VERSION = _IEEE_; printf("IEEE: y0(1e300) = %1.20e\n",y0(1e300)); _LIB_VERSION = _XOPEN_; printf("XOPEN y0(1e300) = %1.20e\n",y0(1e300)); _LIB_VERSION = _POSIX_; printf("POSIX y0(1e300) = %1.20e\n",y0(1e300)); _LIB_VERSION = _SVID_; printf("SVID y0(1e300) = %1.20e\n",y0(1e300)); exit(0); } % cc example2.c libm.a % a.out IEEE: y0(1e300) = -1.36813604503424810557e-151 XOPEN y0(1e300) = 0.00000000000000000000e+00 POSIX y0(1e300) = 0.00000000000000000000e+00 y0: TLOSS error SVID y0(1e300) = 0.00000000000000000000e+00 Note: Here _LIB_VERSION is a global variable. If global variables are forbidden, then one should modify fdlibm.h to change _LIB_VERSION to be a global constant. In this case, one may not change the value of _LIB_VERSION as in example2. --------------------------- 5. NOTES ON PORTING FDLIBM --------------------------- Care must be taken when installing FDLIBM over existing libm.a. All co-existing function prototypes must agree, otherwise users will encounter mysterious failures. So far, the only known likely conflict is the declaration of the IEEE recommended function scalb: double scalb(double,double) (1) SVID3 defined double scalb(double,int) (2) IBM,DEC,... FDLIBM follows Sun definition and use (1) as default. If one's existing libm.a uses (2), then one may raise the flags _SCALB_INT during the compilation of FDLIBM to get the correct function prototype. (E.g., make "CFLAGS = -D_IEEE_LIBM -D_SCALB_INT".) NOTE that if -D_SCALB_INT is raised, it won't be SVID3 conformant. -------------- 6. PROBLEMS ? -------------- Please send comments and bug report to: fdlibm-comments@sunpro.eng.sun.com