packages icon

	  ********************************
 	  * 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