262 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			262 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
 | 
						|
	  *********************************
 | 
						|
 	  * Announcing FDLIBM Version 5.3 *
 | 
						|
	  *********************************
 | 
						|
============================================================
 | 
						|
			FDLIBM
 | 
						|
============================================================
 | 
						|
	developed at Sun Microsystems, Inc. 
 | 
						|
 | 
						|
What's new in FDLIBM 5.3?
 | 
						|
 | 
						|
CONFIGURE
 | 
						|
	To build FDLIBM, edit the supplied Makefile or create
 | 
						|
	a local Makefile by running "sh configure" 
 | 
						|
	using the supplied configure script contributed by Nelson Beebe
 | 
						|
 | 
						|
BUGS FIXED
 | 
						|
 | 
						|
    1. e_pow.c incorrect results when 
 | 
						|
	x is very close to -1.0 and y is very large, e.g.
 | 
						|
  	pow(-1.0000000000000002e+00,4.5035996273704970e+15) = 0
 | 
						|
  	pow(-9.9999999999999978e-01,4.5035996273704970e+15) = 0
 | 
						|
	Correct results are close to -e and -1/e.
 | 
						|
 | 
						|
    2. k_tan.c error was > 1 ulp target for FDLIBM
 | 
						|
	5.2: Worst error at least 1.45 ulp at
 | 
						|
	tan(1.7765241907548024E+269) = 1.7733884462610958E+16
 | 
						|
	5.3: Worst error 0.96 ulp
 | 
						|
 | 
						|
NOT FIXED YET
 | 
						|
 | 
						|
    3. Compiler failure on non-standard code
 | 
						|
	Statements like
 | 
						|
	            *(1+(int*)&t1) = 0;
 | 
						|
	are not standard C and cause some optimizing compilers (e.g. GCC)
 | 
						|
	to generate bad code under optimization.    These cases
 | 
						|
	are to be addressed in the next release.
 | 
						|
	
 | 
						|
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 see
 | 
						|
	http://www.netlib.org/fdlibm/
 | 
						|
or
 | 
						|
	http://www.validlab.com/software/
 | 
						|
 | 
						|
--------------
 | 
						|
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 through the using of pointer bashing as in the example 
 | 
						|
     below:
 | 
						|
 | 
						|
     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: Four macros are defined in fdlibm.h to handle this kind of
 | 
						|
	retrieving:
 | 
						|
 | 
						|
	__HI(x)		the high part of a double x 
 | 
						|
			(sign,exponent,the first 21 significant bits)
 | 
						|
	__LO(x)		the least 32 significant bits of x
 | 
						|
	__HIp(x)	same as __HI except that the argument is a pointer
 | 
						|
			to a double
 | 
						|
	__LOp(x)	same as __LO except that the argument is a pointer
 | 
						|
			to a double
 | 
						|
	
 | 
						|
	To ensure obtaining correct ordering, one must define  __LITTLE_ENDIAN
 | 
						|
	during compilation for little endian machine (like 386,486). The 
 | 
						|
	default is big endian.
 | 
						|
 | 
						|
	If the behavior of pointer bashing is undefined, one may hack on the 
 | 
						|
	macro in fdlibm.h.
 | 
						|
	
 | 
						|
  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, ieee_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, ieee_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 ieee_y0();
 | 
						|
		printf("y0(1e300) = %1.20e\n",y0(1e300));
 | 
						|
		exit(0);
 | 
						|
	    }
 | 
						|
 | 
						|
    % cc example1.c libm.a
 | 
						|
    % a.out
 | 
						|
    y0: TLOSS error
 | 
						|
    ieee_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 ieee_y0();
 | 
						|
		_LIB_VERSION =  _IEEE_;
 | 
						|
		printf("IEEE: ieee_y0(1e300) = %1.20e\n",y0(1e300));
 | 
						|
		_LIB_VERSION = _XOPEN_;
 | 
						|
		printf("XOPEN ieee_y0(1e300) = %1.20e\n",y0(1e300));
 | 
						|
		_LIB_VERSION = _POSIX_;
 | 
						|
		printf("POSIX ieee_y0(1e300) = %1.20e\n",y0(1e300));
 | 
						|
		_LIB_VERSION = _SVID_;
 | 
						|
		printf("SVID  ieee_y0(1e300) = %1.20e\n",y0(1e300));
 | 
						|
		exit(0);
 | 
						|
	}
 | 
						|
 | 
						|
    % cc example2.c libm.a
 | 
						|
    % a.out
 | 
						|
      IEEE: ieee_y0(1e300) = -1.36813604503424810557e-151
 | 
						|
      XOPEN ieee_y0(1e300) = 0.00000000000000000000e+00
 | 
						|
      POSIX ieee_y0(1e300) = 0.00000000000000000000e+00
 | 
						|
      y0: TLOSS error
 | 
						|
      SVID  ieee_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 ieee_scalb(double,double)	(1)	SVID3 defined
 | 
						|
		double ieee_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 reports to the electronic mail address
 | 
						|
suggested by: 
 | 
						|
		fdlibm-comments AT sun.com
 | 
						|
 |