Alpha release of Freely-Distributable libm available for testing

David Hough uunet!Eng.Sun.COM!dgh
Fri Nov 20 16:54:09 PST 1992


K-C Ng has built "fdlibm" to the point where he would like to obtain outside
testing assistance.   Persons who are interested in helping to test may
obtain the source code.    Although the source code is not legally enchained,
consider yourself morally enjoined not to incorporate it into any products
or further distribute it until it's had some testing.   
That's why this announcement is only to numeric-interest.

This library will also be compiled and eventually distributed as the bundled
/usr/ccs/lib/libm.a (what you used to call /usr/lib/libm.a) with Solaris 2.x,
for some x to be determined, for SPARC and x86.   The extra "Sun value added"
that was in SunOS 4.x libm.a, beyond that required for external standards,
will continue to be distributed by SunPro as part of its unbundled compiler
products.

The fdlibm source code amounts to some 262K bytes, including an unconscionable
amount devoted to meeting the requirements of various contradictory 
standards test suites.

Here's K-C's Readme:

	***************************************
	* Announcing FDLIBM Version 1.0 alpha *
	***************************************
============================================================
			FDLIBM
============================================================
  (developed at SunPro, a Sun Microsystems, Inc. business.)
	      Version 1.0 alpha, 11/19/92


FDLIBM (Freely Distributable LIBM) is a C math library 
for machines that support IEEE floating-point arithmetic. 
In this release, only double precision is supported.

FDLIBM is intended to provide a reasonably portable, reference 
quality math library (libm.a). For an early release of FDLIBM, 
please send e-mail to 
		david.houghaEng.sun.com

--------------
1. ASSUMPTIONS
--------------
FDLIBM assumes:
 a.  IEEE style (if not precise compliance) arithmetic
 b.  32 bit integer arithmetic,
 c.  each floating-point number must be in IEEE 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 an -infinity is returned by 
default.

Similarly, exp(-huge) will be mapped to tiny*tiny to generate
underflow signal. 


--------------------------------
3. STANDARD CONFORMANCE WRAPPER 
--------------------------------
The default FDLIBM functions (compiled with -D_IEEE_LIBM flag)  
are of IEEE spirit (i.e., return the most reasonable result in 
floating-point arithmetic). If one wants FDLIBM to comply 
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.  

Here is how it works.  For each function (e.g., exp) in libm.a,
there is a core (IEEE) function which has three underscore
prepend to it (i.e., ___exp). The wrapper function will twist
the result of the core function to comply to the standard
specified by the value of a global variable __lib_version:
    if __lib_version = _IEEE_, return the result of the core function;
    if __lib_version = _XOPEN_, return XOPEN result;
    if __lib_version = _SVID3_, return SVID result;
    if __lib_version = _POSIX_, return POSIX/ANSI result.
(See lib_version.h for definition of the macro.)


--------------------------------
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_SOURCE"   --- multi-standard fdlim: default
					 to IEEE
    make "CFLAGS = -D_XOPEN_SOURCE"  --- multi-standard fdlim: default
					 to X/OPEN
    make "CFLAGS = -D_POSIX_SOURCE"  --- multi-standard fdlim: default
					 to POSIX/ANSI
    make "CFLAGS = -D_SVID3_SOURCE"  --- multi-standard fdlim: default
					 to SVID

There is a global variable (__lib_version) to control which 
standard to follow.  See lib_version.h.

Example:
    Here is how one makes a SVID compliant libm.
    First make the library by
		make "CFLAGS = -D_SVID3_SOURCE".
    The libm.a of FDLIBM will be multi-standard compliant and the variable
    __lib_version is initialized to the value _SVID_ (see lib_version.h).

=========== begin of sample.c ==============
    main()
    {
	double y0();
	printf("y0(1e300) = %1.20e\n",y0(1e300));
	exit(0);
    }
=========== end of sample.c ==============

Compile and run the sample.c to get the (default) SVID required result:
    % cc sample.c libm.a
    % a.out
    y0: TLOSS error
    y0(1e300) = 0.00000000000000000000e+00

Given a multi-standard libm.a, one can change the default standard as
follow:

xopen_version.c
===============================
#include "lib_version.h"	/* FDLIBM's include files */
int __lib_version = _XOPEN_;
===============================

    % cc xopen_version.c sample.c libm.a
    % a.out
    y0(1e300) = 0.00000000000000000000e+00	/* XOPEN answer */

ieee_version.c
===============================
#include "lib_version.h"	/* FDLIBM's include files */
int __lib_version = _IEEE_;
===============================

    % cc ieee_version.c sample.c libm.a
    % a.out
    y0(1e300) = -1.36813604503424810557e-151	/* IEEE answer */


Warning: changing the value of  __lib_version affects only the
multi-standard compliant libm.a. It will have no effect on an 
IEEE libm.a (created by setting the compiler flags -D_IEEE_LIBM).

--------------
5. PROBLEMS ?
--------------
Please send comments and bug report to: 
		fdlibm-commentsasunpro.eng.sun.com



More information about the Numeric-interest mailing list