diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-05-09 04:43:18 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-05-09 04:43:18 +0000 |
commit | e4071b93db0e2fd4aa3b678a6188da2de1c8eb2f (patch) | |
tree | b74cdef21bbdd7d4d09676befce548127217893d | |
parent | 5a25d0f3bc0c9ac81c43b05646575744e93d126c (diff) |
Rework the math library tests per the glibc math test code, with
many unsupported tests disabled for the moment.
-Erik
-rw-r--r-- | test/math/.cvsignore | 8 | ||||
-rw-r--r-- | test/math/Makefile | 113 | ||||
-rw-r--r-- | test/math/drand.c | 158 | ||||
-rw-r--r-- | test/math/econst.c | 96 | ||||
-rw-r--r-- | test/math/eexp.c | 77 | ||||
-rw-r--r-- | test/math/ehead.h | 42 | ||||
-rw-r--r-- | test/math/elog.c | 92 | ||||
-rw-r--r-- | test/math/eparanoi.c | 3550 | ||||
-rw-r--r-- | test/math/epow.c | 215 | ||||
-rw-r--r-- | test/math/etanh.c | 52 | ||||
-rw-r--r-- | test/math/etodec.c | 181 | ||||
-rwxr-xr-x | test/math/gen-libm-test.pl | 738 | ||||
-rw-r--r-- | test/math/ieee.c | 4119 | ||||
-rw-r--r-- | test/math/ieetst.c | 850 | ||||
-rw-r--r-- | test/math/ieetst.doc | 132 | ||||
-rw-r--r-- | test/math/libm-test.inc | 4521 | ||||
-rw-r--r-- | test/math/mconf.h | 108 | ||||
-rw-r--r-- | test/math/mtherr.c | 96 | ||||
-rw-r--r-- | test/math/test-double.c | 34 | ||||
-rw-r--r-- | test/math/test-float.c | 34 | ||||
-rw-r--r-- | test/math/test-idouble.c | 35 | ||||
-rw-r--r-- | test/math/test-ifloat.c | 35 | ||||
-rw-r--r-- | test/math/test-ildoubl.c | 35 | ||||
-rw-r--r-- | test/math/test-ldouble.c | 34 |
24 files changed, 5522 insertions, 9833 deletions
diff --git a/test/math/.cvsignore b/test/math/.cvsignore new file mode 100644 index 000000000..31ed5f055 --- /dev/null +++ b/test/math/.cvsignore @@ -0,0 +1,8 @@ +libm-test-ulps.h +libm-test.c +test-double +test-idouble +test-float +test-ifloat +test-ldouble +test-ildouble diff --git a/test/math/Makefile b/test/math/Makefile index 4d0bc5ee6..d41074939 100644 --- a/test/math/Makefile +++ b/test/math/Makefile @@ -18,74 +18,57 @@ -# Unix makefile for ieetst, eparanoi. -# Set LARGEMEM 1 in qcalc.h for 32-bit memory addresses. -# Define computer type and/or endianness in mconf.h. -# -# Configure eparanoi.c for desired arithmetic test; -# also define appropriate version of setprec.o, or use a stub that -# does no FPU setup. To test native arithmetic, eparanoi uses -# the system libraries only; compile simply by `cc eparanoi.c -lm'. -# - TESTDIR=../ include $(TESTDIR)/Rules.mak - - -#CC = gcc -#CFLAGS= -O -INCS= mconf.h ehead.h -OBJS = ieee.o econst.o eexp.o elog.o epow.o etanh.o etodec.o mtherr.o #setprec.o -TARGETS=ieetst eparanoi - -all: $(TARGETS) - -ieetst: ieetst.o $(OBJS) drand.o $(INCS) - $(CC) -o ieetst ieetst.o $(OBJS) drand.o -lc -lm - -eparanoi: eparanoi.o $(OBJS) $(INCS) - $(CC) -o eparanoi eparanoi.o $(OBJS) -lc -lm - -#setprec.o: setprec.387 -# as -o setprec.o setprec.387 - -#setprec.o: setprec.688 -# as -o setprec.o setprec.688 - -ieee.o: ieee.c $(INCS) - $(CC) $(CFLAGS) -c ieee.c - -econst.o: econst.c $(INCS) - $(CC) $(CFLAGS) -c econst.c - -elog.o: elog.c $(INCS) - $(CC) $(CFLAGS) -c elog.c - -eexp.o: eexp.c $(INCS) - $(CC) $(CFLAGS) -c eexp.c - -etanh.o: etanh.c $(INCS) - $(CC) $(CFLAGS) -c etanh.c - -epow.o: epow.c $(INCS) - $(CC) $(CFLAGS) -c epow.c - -mtherr.o: mtherr.c $(INCS) - $(CC) $(CFLAGS) -c mtherr.c - -ieetst.o: ieetst.c $(INCS) - $(CC) $(CFLAGS) -c ieetst.c - -drand.o: drand.c $(INCS) - $(CC) $(CFLAGS) -c drand.c - -etodec.o: etodec.c $(INCS) - $(CC) $(CFLAGS) -c etodec.c - -eparanoi.o: eparanoi.c $(INCS) - $(CC) $(CFLAGS) -c eparanoi.c +CFLAGS+=-D_GNU_SOURCE -DNO_LONG_DOUBLE +EXTRA_LIBS=-lm +PERL=/usr/bin/perl + +TARGETS:= +libm-tests:= +libm-tests+= test-double test-idouble +#libm-tests+= test-float test-ifloat +#libm-tests+= test-ldouble test-ildouble +libm-tests.o = $(addsuffix .o,$(libm-tests)) + +libm-tests-generated = libm-test-ulps.h libm-test.c +generated += $(libm-tests-generated) libm-test.stmp +TARGETS += $(libm-tests) #$(libm-tests-generated) + +all: libm-test.c $(TARGETS) + +test-double: test-double.o + $(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LIBS) + -./$@ +test-idouble: test-idouble.o + $(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LIBS) + -./$@ +test-float: test-float.o + $(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LIBS) + -./$@ +test-ifloat: test-ifloat.o + $(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LIBS) + -./$@ +test-ldouble: test-ldouble.o + $(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LIBS) + -./$@ +test-ildouble: test-ildoubl.o + $(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LIBS) + -./$@ + +test-float.o: libm-test.c +test-ifloat.o: libm-test.c +test-double.o: libm-test.c +test-idouble.o: libm-test.c +test-ldouble.o: libm-test.c +test-ildoubl.o: libm-test.c + +ulps-file = $(firstword $(wildcard $(config-sysdirs:%=$(..)%/libm-test-ulps))) + +libm-test.c: $(ulps-file) libm-test.inc gen-libm-test.pl + $(PERL) ./gen-libm-test.pl -u $< ./libm-test.inc -o "." 2>&1 > /dev/null clean: - rm -f *.[oa] *~ core $(TARGETS) + rm -f *.[oa] *~ core $(TARGETS) $(generated) diff --git a/test/math/drand.c b/test/math/drand.c deleted file mode 100644 index 9eedf71fc..000000000 --- a/test/math/drand.c +++ /dev/null @@ -1,158 +0,0 @@ -/* drand.c - * - * Pseudorandom number generator - * - * - * - * SYNOPSIS: - * - * double y, drand(); - * - * drand( &y ); - * - * - * - * DESCRIPTION: - * - * Yields a random number 1.0 <= y < 2.0. - * - * The three-generator congruential algorithm by Brian - * Wichmann and David Hill (BYTE magazine, March, 1987, - * pp 127-8) is used. The period, given by them, is - * 6953607871644. - * - * Versions invoked by the different arithmetic compile - * time options DEC, IBMPC, and MIEEE, produce - * approximately the same sequences, differing only in the - * least significant bits of the numbers. The UNK option - * implements the algorithm as recommended in the BYTE - * article. It may be used on all computers. However, - * the low order bits of a double precision number may - * not be adequately random, and may vary due to arithmetic - * implementation details on different computers. - * - * The other compile options generate an additional random - * integer that overwrites the low order bits of the double - * precision number. This reduces the period by a factor of - * two but tends to overcome the problems mentioned. - * - */ - - - -#include "mconf.h" - - -/* Three-generator random number algorithm - * of Brian Wichmann and David Hill - * BYTE magazine, March, 1987 pp 127-8 - * - * The period, given by them, is (p-1)(q-1)(r-1)/4 = 6.95e12. - */ - -static int sx = 1; -static int sy = 10000; -static int sz = 3000; - -static union { - double d; - unsigned short s[4]; -} unkans; - -/* This function implements the three - * congruential generators. - */ - -int ranwh() -{ -int r, s; - -/* sx = sx * 171 mod 30269 */ -r = sx/177; -s = sx - 177 * r; -sx = 171 * s - 2 * r; -if( sx < 0 ) - sx += 30269; - - -/* sy = sy * 172 mod 30307 */ -r = sy/176; -s = sy - 176 * r; -sy = 172 * s - 35 * r; -if( sy < 0 ) - sy += 30307; - -/* sz = 170 * sz mod 30323 */ -r = sz/178; -s = sz - 178 * r; -sz = 170 * s - 63 * r; -if( sz < 0 ) - sz += 30323; -/* The results are in static sx, sy, sz. */ -return 0; -} - -/* drand.c - * - * Random double precision floating point number between 1 and 2. - * - * C callable: - * drand( &x ); - */ - -int drand( a ) -double *a; -{ -unsigned short r; -#ifdef DEC -unsigned short s, t; -#endif - -/* This algorithm of Wichmann and Hill computes a floating point - * result: - */ -ranwh(); -unkans.d = sx/30269.0 + sy/30307.0 + sz/30323.0; -r = unkans.d; -unkans.d -= r; -unkans.d += 1.0; - -/* if UNK option, do nothing further. - * Otherwise, make a random 16 bit integer - * to overwrite the least significant word - * of unkans. - */ -#ifdef UNK -/* do nothing */ -#else -ranwh(); -r = sx * sy + sz; -#endif - -#ifdef DEC -/* To make the numbers as similar as possible - * in all arithmetics, the random integer has - * to be inserted 3 bits higher up in a DEC number. - * An alternative would be put it 3 bits lower down - * in all the other number types. - */ -s = unkans.s[2]; -t = s & 07; /* save these bits to put in at the bottom */ -s &= 0177770; -s |= (r >> 13) & 07; -unkans.s[2] = s; -t |= r << 3; -unkans.s[3] = t; -#endif - -#ifdef IBMPC -unkans.s[0] = r; -#endif - -#ifdef MIEEE -unkans.s[3] = r; -#endif - -*a = unkans.d; -return 0; -} diff --git a/test/math/econst.c b/test/math/econst.c deleted file mode 100644 index cfddbe3e2..000000000 --- a/test/math/econst.c +++ /dev/null @@ -1,96 +0,0 @@ -/* econst.c */ -/* e type constants used by high precision check routines */ - -#include "ehead.h" - - -#if NE == 10 -/* 0.0 */ -unsigned short ezero[NE] = - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,}; - -/* 5.0E-1 */ -unsigned short ehalf[NE] = - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3ffe,}; - -/* 1.0E0 */ -unsigned short eone[NE] = - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,}; - -/* 2.0E0 */ -unsigned short etwo[NE] = - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4000,}; - -/* 3.2E1 */ -unsigned short e32[NE] = - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4004,}; - -/* 6.93147180559945309417232121458176568075500134360255E-1 */ -unsigned short elog2[NE] = - {0x40f3, 0xf6af, 0x03f2, 0xb398, - 0xc9e3, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,}; - -/* 1.41421356237309504880168872420969807856967187537695E0 */ -unsigned short esqrt2[NE] = - {0x1d6f, 0xbe9f, 0x754a, 0x89b3, - 0x597d, 0x6484, 0174736, 0171463, 0132404, 0x3fff,}; - -/* 3.14159265358979323846264338327950288419716939937511E0 */ -unsigned short epi[NE] = - {0x2902, 0x1cd1, 0x80dc, 0x628b, - 0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,}; - -/* 5.7721566490153286060651209008240243104215933593992E-1 */ -unsigned short eeul[NE] = { -0xd1be,0xc7a4,0076660,0063743,0111704,0x3ffe,}; - -#else - -/* 0.0 */ -unsigned short ezero[NE] = { -0, 0000000,0000000,0000000,0000000,0000000,}; -/* 5.0E-1 */ -unsigned short ehalf[NE] = { -0, 0000000,0000000,0000000,0100000,0x3ffe,}; -/* 1.0E0 */ -unsigned short eone[NE] = { -0, 0000000,0000000,0000000,0100000,0x3fff,}; -/* 2.0E0 */ -unsigned short etwo[NE] = { -0, 0000000,0000000,0000000,0100000,0040000,}; -/* 3.2E1 */ -unsigned short e32[NE] = { -0, 0000000,0000000,0000000,0100000,0040004,}; -/* 6.93147180559945309417232121458176568075500134360255E-1 */ -unsigned short elog2[NE] = { -0xc9e4,0x79ab,0150717,0013767,0130562,0x3ffe,}; -/* 1.41421356237309504880168872420969807856967187537695E0 */ -unsigned short esqrt2[NE] = { -0x597e,0x6484,0174736,0171463,0132404,0x3fff,}; -/* 2/sqrt(PI) = - * 1.12837916709551257389615890312154517168810125865800E0 */ -unsigned short eoneopi[NE] = { -0x71d5,0x688d,0012333,0135202,0110156,0x3fff,}; -/* 3.14159265358979323846264338327950288419716939937511E0 */ -unsigned short epi[NE] = { -0xc4c6,0xc234,0020550,0155242,0144417,0040000,}; -/* 5.7721566490153286060651209008240243104215933593992E-1 */ -unsigned short eeul[NE] = { -0xd1be,0xc7a4,0076660,0063743,0111704,0x3ffe,}; -#endif -extern unsigned short ezero[]; -extern unsigned short ehalf[]; -extern unsigned short eone[]; -extern unsigned short etwo[]; -extern unsigned short e32[]; -extern unsigned short elog2[]; -extern unsigned short esqrt2[]; -extern unsigned short eoneopi[]; -extern unsigned short epi[]; -extern unsigned short eeul[]; - diff --git a/test/math/eexp.c b/test/math/eexp.c deleted file mode 100644 index 14ea9899d..000000000 --- a/test/math/eexp.c +++ /dev/null @@ -1,77 +0,0 @@ -/* xexp.c */ -/* exponential function check routine */ -/* by Stephen L. Moshier. */ - - -#include "ehead.h" - -/* -extern int powinited; -extern short maxposint[], maxnegint[]; -*/ - -void eexp( x, y ) -unsigned short *x, *y; -{ -unsigned short num[NE], den[NE], x2[NE]; -long i; -unsigned short sign, expchk; - -/* range reduction theory: x = i + f, 0<=f<1; - * e**x = e**i * e**f - * e**i = 2**(i/log 2). - * Let i/log2 = i1 + f1, 0<=f1<1. - * Then e**i = 2**i1 * 2**f1, so - * e**x = 2**i1 * e**(log 2 * f1) * e**f. - */ -/* -if( powinited == 0 ) - initpow(); -*/ -if( ecmp(x, ezero) == 0 ) - { - emov( eone, y ); - return; - } -emov(x, x2); -expchk = x2[NE-1]; -sign = expchk & 0x8000; -x2[NE-1] &= 0x7fff; - -/* Test for excessively large argument */ -expchk &= 0x7fff; -if( expchk > (EXONE + 15) ) - { - eclear( y ); - if( sign == 0 ) - einfin( y ); - return; - } - -eifrac( x2, &i, num ); /* x = i + f */ - -if( i != 0 ) - { - ltoe( &i, den ); /* floating point i */ - ediv( elog2, den, den ); /* i/log 2 */ - eifrac( den, &i, den ); /* i/log 2 = i1 + f1 */ - emul( elog2, den, den ); /* log 2 * f1 */ - eadd( den, num, x2 ); /* log 2 * f1 + f */ - } - -/*x2[NE-1] -= 1;*/ -eldexp( x2, -1L, x2 ); /* divide by 2 */ -etanh( x2, x2 ); /* tanh( x/2 ) */ -eadd( x2, eone, num ); /* 1 + tanh */ -eneg( x2 ); -eadd( x2, eone, den ); /* 1 - tanh */ -ediv( den, num, y ); /* (1 + tanh)/(1 - tanh) */ - -/*y[NE-1] += i;*/ -if( sign ) - { - ediv( y, eone, y ); - i = -i; - } -eldexp( y, i, y ); /* multiply by 2**i */ -} diff --git a/test/math/ehead.h b/test/math/ehead.h deleted file mode 100644 index 24c95ce05..000000000 --- a/test/math/ehead.h +++ /dev/null @@ -1,42 +0,0 @@ - -/* Include file for extended precision arithmetic programs. - */ - -/* Number of 16 bit words in external x type format */ -#define NE 6 - -/* Number of 16 bit words in internal format */ -#define NI (NE+3) - -/* Array offset to exponent */ -#define E 1 - -/* Array offset to high guard word */ -#define M 2 - -/* Number of bits of precision */ -#define NBITS ((NI-4)*16) - -/* Maximum number of decimal digits in ASCII conversion - * = NBITS*log10(2) - */ -#define NDEC (NBITS*8/27) - -/* The exponent of 1.0 */ -#define EXONE (0x3fff) - -void eadd(), esub(), emul(), ediv(); -int ecmp(), enormlz(), eshift(); -void eshup1(), eshup8(), eshup6(), eshdn1(), eshdn8(), eshdn6(); -void eabs(), eneg(), emov(), eclear(), einfin(), efloor(); -void eldexp(), efrexp(), eifrac(), ltoe(); -void esqrt(), elog(), eexp(), etanh(), epow(); -void asctoe(), asctoe24(), asctoe53(), asctoe64(); -void etoasc(), e24toasc(), e53toasc(), e64toasc(); -void etoe64(), etoe53(), etoe24(), e64toe(), e53toe(), e24toe(); -void mtherr(); -extern unsigned short ezero[], ehalf[], eone[], etwo[]; -extern unsigned short elog2[], esqrt2[]; - - -/* by Stephen L. Moshier. */ diff --git a/test/math/elog.c b/test/math/elog.c deleted file mode 100644 index bc517b197..000000000 --- a/test/math/elog.c +++ /dev/null @@ -1,92 +0,0 @@ -/* xlog.c */ -/* natural logarithm */ -/* by Stephen L. Moshier. */ - -#include "mconf.h" -#include "ehead.h" - - - -void elog( x, y ) -unsigned short *x, *y; -{ -unsigned short xx[NE], z[NE], a[NE], b[NE], t[NE], qj[NE]; -long ex; -int fex; - - -if( x[NE-1] & (unsigned short )0x8000 ) - { - eclear(y); - mtherr( "elog", DOMAIN ); - return; - } -if( ecmp( x, ezero ) == 0 ) - { - einfin( y ); - eneg(y); - mtherr( "elog", SING ); - return; - } -if( ecmp( x, eone ) == 0 ) - { - eclear( y ); - return; - } - -/* range reduction: log x = log( 2**ex * m ) = ex * log2 + log m */ -efrexp( x, &fex, xx ); -/* -emov(x, xx ); -ex = xx[NX-1] & 0x7fff; -ex -= 0x3ffe; -xx[NX-1] = 0x3ffe; -*/ - -/* Adjust range to 1/sqrt(2), sqrt(2) */ -esqrt2[NE-1] -= 1; -if( ecmp( xx, esqrt2 ) < 0 ) - { - fex -= 1; - emul( xx, etwo, xx ); - } -esqrt2[NE-1] += 1; - -esub( eone, xx, a ); -if( a[NE-1] == 0 ) - { - eclear( y ); - goto logdon; - } -eadd( eone, xx, b ); -ediv( b, a, y ); /* store (x-1)/(x+1) in y */ - -emul( y, y, z ); - -emov( eone, a ); -emov( eone, b ); -emov( eone, qj ); -do - { - eadd( etwo, qj, qj ); /* 2 * i + 1 */ - emul( z, a, a ); - ediv( qj, a, t ); - eadd( t, b, b ); - } -while( ((b[NE-1] & 0x7fff) - (t[NE-1] & 0x7fff)) < NBITS ); - - -emul( b, y, y ); -emul( y, etwo, y ); - -logdon: - -/* now add log of 2**ex */ -if( fex != 0 ) - { - ex = fex; - ltoe( &ex, b ); - emul( elog2, b, b ); - eadd( b, y, y ); - } -} diff --git a/test/math/eparanoi.c b/test/math/eparanoi.c deleted file mode 100644 index 84cab73f8..000000000 --- a/test/math/eparanoi.c +++ /dev/null @@ -1,3550 +0,0 @@ -/* paranoia.c arithmetic tester - * - * This is an implementation of the PARANOIA program. It substitutes - * subroutine calls for ALL floating point arithmetic operations. - * This permits you to substitute your own experimental versions of - * arithmetic routines. It also defeats compiler optimizations, - * so for native arithmetic you can be pretty sure you are testing - * the arithmetic and not the compiler. - * - * This version of PARANOIA omits the display of division by zero. - * It also omits the test for extra precise subexpressions, since - * they cannot occur in this context. Otherwise it includes all the - * tests of the 27 Jan 86 distribution, plus a few additional tests. - * Commentary has been reduced to a minimum in order to make the program - * smaller. - * - * The original PARANOIA program, written by W. Kahan, C version - * by Thos Sumner and David Gay, can be downloaded free from the - * Internet NETLIB. An MSDOS disk can be obtained for $15 from: - * Richard Karpinski - * 6521 Raymond Street - * Oakland, CA 94609 - * - * Steve Moshier, 28 Oct 88 - * last rev: 23 May 92 - */ - -#define DEBUG 0 - -/* To use the native arithmetic of the computer, define NATIVE - * to be 1. To use your own supplied arithmetic routines, NATIVE is 0. - */ -#define NATIVE 0 - -/* gcc real.c interface */ -#define L128DOUBLE 0 - -#include <stdio.h> - - - - -/* Data structure of floating point number. If NATIVE was - * selected above, you can define LDOUBLE 1 to test 80-bit long double - * precision or define it 0 to test 64-bit double precision. -*/ -#define LDOUBLE 0 -#if NATIVE - -#define NE 1 -#if LDOUBLE -#define FSIZE long double -#define FLOAT(x) FSIZE x[NE] -static FSIZE eone[NE] = {1.0L}; /* The constant 1.0 */ -#define ZSQRT sqrtl -#define ZLOG logl -#define ZFLOOR floorl -#define ZPOW powl -long double sqrtl(), logl(), floorl(), powl(); -#define FSETUP einit -#else /* not LDOUBLE */ -#define FSIZE double -#define FLOAT(x) FSIZE x[NE] -static FSIZE eone[NE] = {1.0}; /* The constant 1.0 */ -#define ZSQRT sqrt -#define ZLOG log -#define ZFLOOR floor -#define ZPOW pow -double sqrt(), log(), floor(), pow(); -/* Coprocessor initialization, - * defeat underflow trap or what have you. - * This is required mainly on i386 and 68K processors. - */ -#define FSETUP dprec -#endif /* double, not LDOUBLE */ - -#else /* not NATIVE */ - -/* Setup for extended double type. - * Put NE = 10 for real.c operating with TFmode support (16-byte reals) - * Put NE = 6 for real.c operating with XFmode support (10- or 12-byte reals) - * The value of NE must agree with that in ehead.h, if ieee.c is used. - */ -#define NE 6 -#define FSIZE unsigned short -#define FLOAT(x) unsigned short x[NE] -extern unsigned short eone[]; -#define FSETUP einit - -/* default for FSETUP */ -/* -einit() -{} -*/ - -error(s) -char *s; -{ -printf( "error: %s\n", s ); -} - -#endif /* not NATIVE */ - - - -#if L128DOUBLE -/* real.c interface */ - -#undef FSETUP -#define FSETUP efsetup - -FLOAT(enone); - -#define ONE enone - -/* Use emov to convert from widest type to widest type, ... */ -/* -#define ENTOE emov -#define ETOEN emov -*/ - -/* ... else choose e24toe, e53toe, etc. */ -#define ENTOE e64toe -#define ETOEN etoe64 -#define NNBITS 64 - -#define NIBITS ((NE-1)*16) -extern int rndprc; - -efsetup() -{ -rndprc = NNBITS; -ETOEN(eone, enone); -} - -add(a,b,c) -FLOAT(a); -FLOAT(b); -FLOAT(c); -{ -unsigned short aa[10], bb[10], cc[10]; - -ENTOE(a,aa); -ENTOE(b,bb); -eadd(aa,bb,cc); -ETOEN(cc,c); -} - -sub(a,b,c) -FLOAT(a); -FLOAT(b); -FLOAT(c); -{ -unsigned short aa[10], bb[10], cc[10]; - -ENTOE(a,aa); -ENTOE(b,bb); -esub(aa,bb,cc); -ETOEN(cc,c); -} - -mul(a,b,c) -FLOAT(a); -FLOAT(b); -FLOAT(c); -{ -unsigned short aa[10], bb[10], cc[10]; - -ENTOE(a,aa); -ENTOE(b,bb); -emul(aa,bb,cc); -ETOEN(cc,c); -} - -div(a,b,c) -FLOAT(a); -FLOAT(b); -FLOAT(c); -{ -unsigned short aa[10], bb[10], cc[10]; - -ENTOE(a,aa); -ENTOE(b,bb); -ediv(aa,bb,cc); -ETOEN(cc,c); -} - -int cmp(a,b) -FLOAT(a); -FLOAT(b); -{ -unsigned short aa[10], bb[10]; -int c; -int ecmp(); - -ENTOE(a,aa); -ENTOE(b,bb); -c = ecmp(aa,bb); -return(c); -} - -mov(a,b) -FLOAT(a); -FLOAT(b); -{ -int i; - -for( i=0; i<NE; i++ ) - b[i] = a[i]; -} - - -neg(a) -FLOAT(a); -{ -unsigned short aa[10]; - -ENTOE(a,aa); -eneg(aa); -ETOEN(aa,a); -} - -clear(a) -FLOAT(a); -{ -int i; - -for( i=0; i<NE; i++ ) - a[i] = 0; -} - -FABS(a) -FLOAT(a); -{ -unsigned short aa[10]; - -ENTOE(a,aa); -eabs(aa); -ETOEN(aa,a); -} - -FLOOR(a,b) -FLOAT(a); -FLOAT(b); -{ -unsigned short aa[10], bb[10]; - -ENTOE(a,aa); -efloor(aa,bb); -ETOEN(bb,b); -} - -LOG(a,b) -FLOAT(a); -FLOAT(b); -{ -unsigned short aa[10], bb[10]; -int rndsav; - -ENTOE(a,aa); -rndsav = rndprc; -rndprc = NIBITS; -elog(aa,bb); -rndprc = rndsav; -ETOEN(bb,b); -} - -POW(a,b,c) -FLOAT(a); -FLOAT(b); -FLOAT(c); -{ -unsigned short aa[10], bb[10], cc[10]; -int rndsav; - -ENTOE(a,aa); -ENTOE(b,bb); -rndsav = rndprc; -rndprc = NIBITS; -epow(aa,bb,cc); -rndprc = rndsav; -ETOEN(cc,c); -} - -SQRT(a,b) -FLOAT(a); -FLOAT(b); -{ -unsigned short aa[10], bb[10]; - -ENTOE(a,aa); -esqrt(aa,bb); -ETOEN(bb,b); -} - -FTOL(x,ip,f) -FLOAT(x); -long *ip; -FLOAT(f); -{ -unsigned short xx[10], ff[10]; - -ENTOE(x,xx); -eifrac(xx,ip,ff); -ETOEN(ff,f); -} - -LTOF(ip,x) -long *ip; -FLOAT(x); -{ -unsigned short xx[10]; -ltoe(ip,xx); -ETOEN(xx,x); -} - -TOASC(a,b,c) -FLOAT(a); -int b; -char *c; -{ -unsigned short xx[10]; - -ENTOE(a,xx); -etoasc(xx,b,c); -} - -#else /* not L128DOUBLE */ - -#define ONE eone - -/* Note all arguments of operation subroutines are pointers. */ -/* c = b + a */ -#define add(a,b,c) eadd(a,b,c) -/* c = b - a */ -#define sub(a,b,c) esub(a,b,c) -/* c = b * a */ -#define mul(a,b,c) emul(a,b,c) -/* c = b / a */ -#define div(a,b,c) ediv(a,b,c) -/* 1 if a>b, 0 if a==b, -1 if a<b */ -#define cmp(a,b) ecmp(a,b) -/* b = a */ -#define mov(a,b) emov(a,b) -/* a = -a */ -#define neg(a) eneg(a) -/* a = 0 */ -#define clear(a) eclear(a) - -#define FABS(x) eabs(x) -#define FLOOR(x,y) efloor(x,y) -#define LOG(x,y) elog(x,y) -#define POW(x,y,z) epow(x,y,z) -#define SQRT(x,y) esqrt(x,y) - -/* x = &FLOAT input, i = &long integer part, f = &FLOAT fractional part */ -#define FTOL(x,i,f) eifrac(x,i,f) - -/* i = &long integer input, x = &FLOAT output */ -#define LTOF(i,x) ltoe(i,x) - -/* Convert FLOAT a to decimal ASCII string with b digits */ -#define TOASC(a,b,c) etoasc(a,b,c) -#endif /* not L128DOUBLE */ - - - -/* The following subroutines are implementations of the above - * named functions, using the native or default arithmetic. - */ -#if NATIVE -eadd(a,b,c) -FSIZE *a, *b, *c; -{ -*c = *b + *a; -} - -esub(a,b,c) -FSIZE *a, *b, *c; -{ -*c = *b - *a; -} - -emul(a,b,c) -FSIZE *a, *b, *c; -{ -*c = (*b) * (*a); -} - -ediv(a,b,c) -FSIZE *a, *b, *c; -{ -*c = (*b) / (*a); -} - - -/* Important note: comparison can be done by subracting - * or by a compare instruction that may or may not be - * equivalent to subtracting. - */ -ecmp(a,b) -FSIZE *a, *b; -{ -if( (*a) > (*b) ) - return( 1 ); -if( (*a) < (*b) ) - return( -1 ); -if( (*a) != (*b) ) - goto cmpf; -if( (*a) == (*b) ) - return( 0 ); -cmpf: -printf( "Compare fails\n" ); -return(0); -} - - -emov( a, b ) -FSIZE *a, *b; -{ -*b = *a; -} - -eneg( a ) -FSIZE *a; -{ -*a = -(*a); -} - -eclear(a) -FSIZE *a; -{ -*a = 0.0; -} - -eabs(x) -FSIZE *x; -{ -if( (*x) < 0.0 ) - *x = -(*x); -} - -efloor(x,y) -FSIZE *x, *y; -{ - -*y = (FSIZE )ZFLOOR( *x ); -} - -elog(x,y) -FSIZE *x, *y; -{ - -*y = (FSIZE )ZLOG( *x ); -} - -epow(x,y,z) -FSIZE *x, *y, *z; -{ - -*z = (FSIZE )ZPOW( *x, *y ); -} - -esqrt(x,y) -FSIZE *x, *y; -{ - -*y = (FSIZE )ZSQRT( *x ); -} - - -eifrac(x,i,f) -FSIZE *x; -long *i; -FSIZE *f; -{ -FSIZE y; - -y = (FSIZE )ZFLOOR( *x ); -if( y < 0.0 ) - { - *f = y - *x; - *i = -y; - } -else - { - *f = *x - y; - *i = y; - } -} - - -ltoe(i,x) -long *i; -FSIZE *x; -{ -*x = *i; -} - - -etoasc(a,str,n) -FSIZE *a; -char *str; -int n; -{ -double x; - -x = (double )(*a); -sprintf( str, " %.17e ", x ); -} - -/* default for FSETUP */ -einit() -{} - -#endif /* NATIVE */ - - - - -FLOAT(Radix); -FLOAT(BInvrse); -FLOAT(RadixD2); -FLOAT(BMinusU2); -/*Small floating point constants.*/ -FLOAT(Zero); -FLOAT(Half); -FLOAT(One); -FLOAT(Two); -FLOAT(Three); -FLOAT(Four); -FLOAT(Five); -FLOAT(Six); -FLOAT(Eight); -FLOAT(Nine); -FLOAT(Ten); -FLOAT(TwentySeven); -FLOAT(ThirtyTwo); -FLOAT(TwoForty); -FLOAT(MinusOne ); -FLOAT(OneAndHalf); - -/*Integer constants*/ -int NoTrials = 20; /*Number of tests for commutativity. */ -#define False 0 -#define True 1 - -/* Definitions for declared types - Guard == (Yes, No); - Rounding == (Chopped, Rounded, Other); - Message == packed array [1..40] of char; - Class == (Flaw, Defect, Serious, Failure); - */ -#define Yes 1 -#define No 0 -#define Chopped 2 -#define Rounded 1 -#define Other 0 -#define Flaw 3 -#define Defect 2 -#define Serious 1 -#define Failure 0 - -typedef int Guard, Rounding, Class; -typedef char Message; - -/* Declarations of Variables */ -FLOAT(AInvrse); -FLOAT(A1); -FLOAT(C); -FLOAT(CInvrse); -FLOAT(D); -FLOAT(FourD); -FLOAT(E0); -FLOAT(E1); -FLOAT(Exp2); -FLOAT(E3); -FLOAT(MinSqEr); -FLOAT(SqEr); -FLOAT(MaxSqEr); -FLOAT(E9); -FLOAT(Third); -FLOAT(F6); -FLOAT(F9); -FLOAT(H); -FLOAT(HInvrse); -FLOAT(StickyBit); -FLOAT(J); -FLOAT(MyZero); -FLOAT(Precision); -FLOAT(Q); -FLOAT(Q9); -FLOAT(R); -FLOAT(Random9); -FLOAT(T); -FLOAT(Underflow); -FLOAT(S); -FLOAT(OneUlp); -FLOAT(UfThold); -FLOAT(U1); -FLOAT(U2); -FLOAT(V); -FLOAT(V0); -FLOAT(V9); -FLOAT(W); -FLOAT(X); -FLOAT(X1); -FLOAT(X2); -FLOAT(X8); -FLOAT(Random1); -FLOAT(Y); -FLOAT(YY1); -FLOAT(Y2); -FLOAT(Random2); -FLOAT(Z); -FLOAT(PseudoZero); -FLOAT(Z1); -FLOAT(Z2); -FLOAT(Z9); -static FLOAT(t); -FLOAT(t2); -FLOAT(Sqarg); -int ErrCnt[4]; -int fpecount; -int Milestone; -int PageNo; -int I, M, N, N1, stkflg; -Guard GMult, GDiv, GAddSub; -Rounding RMult, RDiv, RAddSub, RSqrt; -int Break, Done, NotMonot, Monot, Anomaly, IEEE; -int SqRWrng, UfNGrad; -int k, k2; -int Indx; -char ch[8]; - -long lngint, lng2; /* intermediate for conversion between int and FLOAT */ - -/* Computed constants. */ -/*U1 gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */ -/*U2 gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */ - - -show( x ) -short x[]; -{ -int i; -char s[80]; - -/* Number of 16-bit groups to display */ -#if NATIVE -#if LDOUBLE -#define NPRT (sizeof( long double )/2) -#else -#define NPRT (sizeof( double )/2) -#endif -#else -#define NPRT NE -#endif - -TOASC( x, s, 70 ); -printf( "%s\n", s ); -for( i=0; i<NPRT; i++ ) - printf( "%04x ", x[i] & 0xffff ); -printf( "\n" ); -} - -/* define NOSIGNAL */ -#ifndef NOSIGNAL -#include <signal.h> -#endif -#include <setjmp.h> -jmp_buf ovfl_buf; -/*typedef int (*Sig_type)();*/ -typedef void (*Sig_type)(); -Sig_type sigsave; - -/* Floating point exception receiver */ -void sigfpe() -{ -fpecount++; -printf( "\n* * * FLOATING-POINT ERROR * * *\n" ); -/* reinitialize the floating point unit */ -FSETUP(); -fflush(stdout); -if( sigsave ) - { -#ifndef NOSIGNAL - signal( SIGFPE, sigsave ); -#endif - sigsave = 0; - longjmp( ovfl_buf, 1 ); - } -abort(); -} - - -main() -{ - -/* Do coprocessor or other initializations */ -FSETUP(); - -printf( - "This version of paranoia omits test for extra precise subexpressions\n" ); -printf( "and includes a few additional tests.\n" ); - -clear(Zero); -printf( "0 = " ); -show( Zero ); -mov( ONE, One); -printf( "1 = " ); -show( One ); -add( One, One, Two ); -printf( "1+1 = " ); -show( Two ); -add( Two, One, Three ); -add( Three, One, Four ); -add( Four, One, Five ); -add( Five, One, Six ); -add( Four, Four, Eight ); -mul( Three, Three, Nine ); -add( Nine, One, Ten ); -mul( Nine, Three, TwentySeven ); -mul( Four, Eight, ThirtyTwo ); -mul( Four, Five, t ); -mul( t, Three, t ); -mul( t, Four, TwoForty ); -mov( One, MinusOne ); -neg( MinusOne ); -div( Two, One, Half ); -add( One, Half, OneAndHalf ); -ErrCnt[Failure] = 0; -ErrCnt[Serious] = 0; -ErrCnt[Defect] = 0; -ErrCnt[Flaw] = 0; -PageNo = 1; -#ifndef NOSIGNAL -signal( SIGFPE, sigfpe ); -#endif -printf("Program is now RUNNING tests on small integers:\n"); - -add( Zero, Zero, t ); -if( cmp( t, Zero ) != 0) - { - printf( "0+0 != 0\n" ); - ErrCnt[Failure] += 1; - } -sub( One, One, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "1-1 != 0\n" ); - ErrCnt[Failure] += 1; - } -if( cmp( One, Zero ) <= 0 ) - { - printf( "1 <= 0\n" ); - ErrCnt[Failure] += 1; - } -add( One, One, t ); -if( cmp( t, Two ) != 0 ) - { - printf( "1+1 != 2\n" ); - ErrCnt[Failure] += 1; - } -mov( Zero, Z ); -neg( Z ); -FLOOR( Z, t ); -if( cmp(t,Zero) != 0 ) - { - ErrCnt[Serious] += 1; - printf( "FLOOR(-0) should equal 0, is = " ); - show( t ); - } -if( cmp(Z, Zero) != 0) - { - ErrCnt[Failure] += 1; - printf("Comparison alleges that -0.0 is Non-zero!\n"); - } -else - { - div( TwoForty, One, U1 ); /* U1 = 0.001 */ - mov( One, Radix ); - TstPtUf(); - } -add( Two, One, t ); -if( cmp( t, Three ) != 0 ) - { - printf( "2+1 != 3\n" ); - ErrCnt[Failure] += 1; - } -add( Three, One, t ); -if( cmp( t, Four ) != 0 ) - { - printf( "3+1 != 4\n" ); - ErrCnt[Failure] += 1; - } -mov( Two, t ); -neg( t ); -mul( Two, t, t ); -add( Four, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "4+2*(-2) != 0\n" ); - ErrCnt[Failure] += 1; - } -sub( Three, Four, t ); -sub( One, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "4-3-1 != 0\n" ); - ErrCnt[Failure] += 1; - } - sub( One, Zero, t ); -if( cmp( t, MinusOne ) != 0 ) - { - printf( "-1 != 0-1\n" ); - ErrCnt[Failure] += 1; - } -add( One, MinusOne, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "1+(-1) != 0\n" ); - ErrCnt[Failure] += 1; - } -mov( One, t ); -FABS( t ); -add( MinusOne, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "-1+abs(1) != 0\n" ); - ErrCnt[Failure] += 1; - } -mul( MinusOne, MinusOne, t ); -add( MinusOne, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "-1+(-1)*(-1) != 0\n" ); - ErrCnt[Failure] += 1; - } -add( Half, MinusOne, t ); -add( Half, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "1/2 + (-1) + 1/2 != 0\n" ); - ErrCnt[Failure] += 1; - } -Milestone = 10; -mul( Three, Three, t ); -if( cmp( t, Nine ) != 0 ) - { - printf( "3*3 != 9\n" ); - ErrCnt[Failure] += 1; - } -mul( Nine, Three, t ); -if( cmp( t, TwentySeven ) != 0 ) - { - printf( "3*9 != 27\n" ); - ErrCnt[Failure] += 1; - } -add( Four, Four, t ); -if( cmp( t, Eight ) != 0 ) - { - printf( "4+4 != 8\n" ); - ErrCnt[Failure] += 1; - } -mul( Eight, Four, t ); -if( cmp( t, ThirtyTwo ) != 0 ) - { - printf( "8*4 != 32\n" ); - ErrCnt[Failure] += 1; - } -sub( TwentySeven, ThirtyTwo, t ); -sub( Four, t, t ); -sub( One, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "32-27-4-1 != 0\n" ); - ErrCnt[Failure] += 1; - } -add( Four, One, t ); -if( cmp( t, Five ) != 0 ) - { - printf( "4+1 != 5\n" ); - ErrCnt[Failure] += 1; - } -mul( Four, Five, t ); -mul( Three, t, t ); -mul( Four, t, t ); -if( cmp( t, TwoForty ) != 0 ) - { - printf( "4*5*3*4 != 240\n" ); - ErrCnt[Failure] += 1; - } -div( Three, TwoForty, t ); -mul( Four, Four, t2 ); -mul( Five, t2, t2 ); -sub( t2, t2, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "240/3 - 4*4*5 != 0\n" ); - ErrCnt[Failure] += 1; - } -div( Four, TwoForty, t ); -mul( Five, Three, t2 ); -mul( Four, t2, t2 ); -sub( t2, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "240/4 - 5*3*4 != 0\n" ); - ErrCnt[Failure] += 1; - } -div( Five, TwoForty, t ); -mul( Four, Three, t2 ); -mul( Four, t2, t2 ); -sub( t2, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "240/5 - 4*3*4 != 0\n" ); - ErrCnt[Failure] += 1; - } -if(ErrCnt[Failure] == 0) - { -printf("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n\n"); - } -printf("Searching for Radix and Precision.\n"); -mov( One, W ); -do - { - add( W, W, W ); - add( W, One, Y ); - sub( W, Y, Z ); - sub( One, Z, Y ); - mov( Y, t ); - FABS(t); - add( MinusOne, t, t ); - k = cmp( t, Zero ); - } -while( k < 0 ); -/*.. now W is just big enough that |((W+1)-W)-1| >= 1 ...*/ -mov( Zero, Precision ); -mov( One, Y ); -do - { - add( W, Y, Radix ); - add( Y, Y, Y ); - sub( W, Radix, Radix ); - k = cmp( Radix, Zero ); - } -while( k == 0); - -if( cmp(Radix, Two) < 0 ) - mov( One, Radix ); -printf("Radix = " ); -show( Radix ); -if( cmp(Radix, One) != 0) - { - mov( One, W ); - do - { - add( One, Precision, Precision ); - mul( W, Radix, W ); - add( W, One, Y ); - sub( W, Y, t ); - k = cmp( t, One ); - } - while( k == 0 ); - } -/* now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1 */ -div( W, One, U1 ); -mul( Radix, U1, U2 ); -printf( "Closest relative separation found is U 1 = " ); -show( U1 ); -printf( "Recalculating radix and precision." ); - -/*save old values*/ -mov( Radix, E0 ); -mov( U1, E1 ); -mov( U2, E9 ); -mov( Precision, E3 ); - -div( Three, Four, X ); -sub( One, X, Third ); -sub( Third, Half, F6 ); -add( F6, F6, X ); -sub( Third, X, X ); -FABS( X ); -if( cmp(X, U2) < 0 ) - mov( U2, X ); - -/*... now X = (unknown no.) ulps of 1+...*/ -do - { - mov( X, U2 ); -/* Y = Half * U2 + ThirtyTwo * U2 * U2; */ - mul( ThirtyTwo, U2, t ); - mul( t, U2, t ); - mul( Half, U2, Y ); - add( t, Y, Y ); - add( One, Y, Y ); - sub( One, Y, X ); - k = cmp( U2, X ); - k2 = cmp( X, Zero ); - } -while ( ! ((k <= 0) || (k2 <= 0))); - -/*... now U2 == 1 ulp of 1 + ... */ -div( Three, Two, X ); -sub( Half, X, F6 ); -add( F6, F6, Third ); -sub( Half, Third, X ); -add( F6, X, X ); -FABS( X ); -if( cmp(X, U1) < 0 ) - mov( U1, X ); - -/*... now X == (unknown no.) ulps of 1 -... */ -do - { - mov( X, U1 ); - /* Y = Half * U1 + ThirtyTwo * U1 * U1;*/ - mul( ThirtyTwo, U1, t ); - mul( U1, t, t ); - mul( Half, U1, Y ); - add( t, Y, Y ); - sub( Y, Half, Y ); - add( Half, Y, X ); - sub( X, Half, Y ); - add( Half, Y, X ); - k = cmp( U1, X ); - k2 = cmp( X, Zero ); - } while ( ! ((k <= 0) || (k2 <= 0))); -/*... now U1 == 1 ulp of 1 - ... */ -if( cmp( U1, E1 ) == 0 ) - printf("confirms closest relative separation U1 .\n"); -else - { - printf("gets better closest relative separation U1 = " ); - show( U1 ); - } -div( U1, One, W ); -sub( U1, Half, F9 ); -add( F9, Half, F9 ); -div( U1, U2, t ); -div( TwoForty, One, t2 ); -add( t2, t, t ); -FLOOR( t, Radix ); -if( cmp(Radix, E0) == 0 ) - printf("Radix confirmed.\n"); -else - { - printf("MYSTERY: recalculated Radix = " ); - show( Radix ); - mov( E0, Radix ); - } -add( Eight, Eight, t ); -if( cmp( Radix, t ) > 0 ) - { - printf( "Radix is too big: roundoff problems\n" ); - ErrCnt[Defect] += 1; - } -k = 1; -if( cmp( Radix, Two ) == 0 ) - k = 0; -if( cmp( Radix, Ten ) == 0 ) - k = 0; -if( cmp( Radix, One ) == 0 ) - k = 0; -if( k != 0 ) - { - printf( "Radix is not as good as 2 or 10\n" ); - ErrCnt[Flaw] += 1; - } -/*=============================================*/ -Milestone = 20; -/*=============================================*/ -sub( Half, F9, t ); -if( cmp( t, Half ) >= 0 ) - { - printf( "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?\n" ); - ErrCnt[Failure] += 1; - } -mov( F9, X ); -I = 1; -sub( Half, X, Y ); -sub( Half, Y, Z ); -if( (cmp( X, One ) == 0) && (cmp( Z, Zero) != 0) ) - { - printf( "Comparison is fuzzy ,X=1 but X-1/2-1/2 != 0\n" ); - ErrCnt[Failure] += 1; - } -add( One, U2, X ); -I = 0; -/*=============================================*/ -Milestone = 25; -/*=============================================*/ -/*... BMinusU2 = nextafter(Radix, 0) */ - -sub( One, Radix, BMinusU2 ); -sub( U2, BMinusU2, t ); -add( One, t, BMinusU2 ); -/* Purify Integers */ -if( cmp(Radix,One) != 0 ) - { -/*X = - TwoForty * LOG(U1) / LOG(Radix);*/ - LOG( U1, X ); - LOG( Radix, t ); - div( t, X, X ); - mul( TwoForty, X, X ); - neg( X ); - - add( Half, X, Y ); - FLOOR( Y, Y ); - sub( Y, X, t ); - FABS( t ); - mul( Four, t, t ); - if( cmp( t, One ) < 0 ) - mov( Y, X ); - div( TwoForty, X, Precision ); - add( Half, Precision, Y ); - FLOOR( Y, Y ); - sub( Y, Precision, t ); - FABS( t ); - mul( TwoForty, t, t ); - if( cmp( t, Half ) < 0 ) - mov( Y, Precision ); - } -FLOOR( Precision, t ); -if( (cmp( Precision, t ) != 0) || (cmp( Radix, One ) == 0) ) - { - printf("Precision cannot be characterized by an Integer number\n"); - printf("of significant digits but, by itself, this is a minor flaw.\n"); - } -if( cmp(Radix, One) == 0 ) - printf("logarithmic encoding has precision characterized solely by U1.\n"); -else - { - printf("The number of significant digits of the Radix is " ); - show( Precision ); - } -mul( U2, Nine, t ); -mul( Nine, t, t ); -mul( TwoForty, t, t ); -if( cmp( t, One ) >= 0 ) - { - printf( "Precision worse than 5 decimal figures\n" ); - ErrCnt[Serious] += 1; - } -/*=============================================*/ -Milestone = 30; -/*=============================================*/ -/* Test for extra-precise subepressions has been deleted. */ -Milestone = 35; -/*=============================================*/ -if( cmp(Radix,Two) >= 0 ) - { - mul( Radix, Radix, t ); - div( t, W, X ); - add( X, One, Y ); - sub( X, Y, Z ); - add( Z, U2, T ); - sub( Z, T, X ); - if( cmp( X, U2 ) != 0 ) - { - printf( "Subtraction is not normalized X=Y,X+Z != Y+Z!\n" ); - ErrCnt[Failure] += 1; - } - if( cmp(X,U2) == 0 ) - printf("Subtraction appears to be normalized, as it should be."); - } - -printf("\nChecking for guard digit in *, /, and -.\n"); -mul( F9, One, Y ); -mul( One, F9, Z ); -sub( Half, F9, X ); -sub( Half, Y, Y ); -sub( X, Y, Y ); -sub( Half, Z, Z ); -sub( X, Z, Z ); -add( One, U2, X ); -mul( X, Radix, T ); -mul( Radix, X, R ); -sub( Radix, T, X ); -mul( Radix, U2, t ); -sub( t, X, X ); -sub( Radix, R, T ); -mul( Radix, U2, t ); -sub( t, T, T ); -sub( One, Radix, t ); -mul( t, X, X ); -sub( One, Radix, t ); -mul( t, T, T ); - -k = cmp(X,Zero); -k |= cmp(Y,Zero); -k |= cmp(Z,Zero); -k |= cmp(T,Zero); -if( k == 0 ) - GMult = Yes; -else - { - GMult = No; - ErrCnt[Serious] += 1; - printf( "* lacks a Guard Digit, so 1*X != X\n" ); - } -mul( Radix, U2, Z ); -add( One, Z, X ); -add( X, Z, Y ); -mul( X, X, t ); -sub( t, Y, Y ); -FABS( Y ); -sub( U2, Y, Y ); -sub( U2, One, X ); -sub( U2, X, Z ); -mul( X, X, t ); -sub( t, Z, Z ); -FABS( Z ); -sub( U1, Z, Z ); -if( (cmp(Y,Zero) > 0) || (cmp(Z,Zero) > 0) ) - { - ErrCnt[Failure] += 1; - printf( "* gets too many final digits wrong.\n" ); - } -sub( U2, One, Y ); -add( One, U2, X ); -div( Y, One, Z ); -sub( X, Z, Y ); -div( Three, One, X ); -div( Nine, Three, Z ); -sub( Z, X, X ); -div( TwentySeven, Nine, T ); -sub( T, Z, Z ); -k = cmp( X, Zero ); -k |= cmp( Y, Zero ); -k |= cmp( Z, Zero ); -if( k ) - { - ErrCnt[Defect] += 1; -printf( "Division lacks a Guard Digit, so error can exceed 1 ulp\n" ); -printf( "or 1/3 and 3/9 and 9/27 may disagree\n" ); - } -div( One, F9, Y ); -sub( Half, F9, X ); -sub( Half, Y, Y ); -sub( X, Y, Y ); -add( One, U2, X ); -div( One, X, T ); -sub( X, T, X ); -k = cmp( X, Zero ); -k |= cmp( Y, Zero ); -k |= cmp( Z, Zero ); -if( k == 0 ) - GDiv = Yes; -else - { - GDiv = No; - ErrCnt[Serious] += 1; - printf( "Division lacks a Guard Digit, so X/1 != X\n" ); - } -add( One, U2, X ); -div( X, One, X ); -sub( Half, X, Y ); -sub( Half, Y, Y ); -if( cmp(Y,Zero) >= 0 ) - { - ErrCnt[Serious] += 1; - printf( "Computed value of 1/1.000..1 >= 1\n" ); - } -sub( U2, One, X ); -mul( Radix, U2, Y ); -add( One, Y, Y ); -mul( X, Radix, Z ); -mul( Y, Radix, T ); -div( Radix, Z, R ); -div( Radix, T, StickyBit ); -sub( X, R, X ); -sub( Y, StickyBit, Y ); -k = cmp( X, Zero ); -k |= cmp( Y, Zero ); -if( k ) - { - ErrCnt[Failure] += 1; - printf( "* and/or / gets too many last digits wrong\n" ); - } -sub( U1, One, Y ); -sub( F9, One, X ); -sub( Y, One, Y ); -sub( U2, Radix, T ); -sub( BMinusU2, Radix, Z ); -sub( T, Radix, T ); -k = cmp( X, U1 ); -k |= cmp( Y, U1 ); -k |= cmp( Z, U2 ); -k |= cmp( T, U2 ); -if( k == 0 ) - GAddSub = Yes; -else - { - GAddSub = No; - ErrCnt[Serious] += 1; - printf( "- lacks Guard Digit, so cancellation is obscured\n" ); - } -sub( One, F9, t ); -if( (cmp(F9,One) != 0) && (cmp(t,Zero) >= 0) ) - { - ErrCnt[Serious] += 1; - printf("comparison alleges (1-U1) < 1 although\n"); - printf(" subtration yields (1-U1) - 1 = 0 , thereby vitiating\n"); - printf(" such precautions against division by zero as\n"); - printf(" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n"); - } -if (GMult == Yes && GDiv == Yes && GAddSub == Yes) - printf(" *, /, and - appear to have guard digits, as they should.\n"); -/*=============================================*/ -Milestone = 40; -/*=============================================*/ -printf("Checking rounding on multiply, divide and add/subtract.\n"); -RMult = Other; -RDiv = Other; -RAddSub = Other; -div( Two, Radix, RadixD2 ); -mov( Two, A1 ); -Done = False; -do - { - mov( Radix, AInvrse ); - do - { - mov( AInvrse, X ); - div( A1, AInvrse, AInvrse ); - FLOOR( AInvrse, t ); - k = cmp( t, AInvrse ); - } - while( ! (k != 0 ) ); - k = cmp( X, One ); - k2 = cmp( A1, Three ); - Done = (k == 0) || (k2 > 0); - if(! Done) - add( Nine, One, A1 ); - } -while( ! (Done)); -if( cmp(X, One) == 0 ) - mov( Radix, A1 ); -div( A1, One, AInvrse ); -mov( A1, X ); -mov( AInvrse, Y ); -Done = False; -do - { - mul( X, Y, Z ); - sub( Half, Z, Z ); - if( cmp( Z, Half ) != 0 ) - { - ErrCnt[Failure] += 1; - printf( "X * (1/X) differs from 1\n" ); - } - k = cmp( X, Radix ); - Done = (k == 0); - mov( Radix, X ); - div( X, One, Y ); - } -while( ! (Done)); - -add( One, U2, Y2 ); -sub( U2, One, YY1 ); -sub( U2, OneAndHalf, X ); -add( OneAndHalf, U2, Y ); -sub( U2, X, Z ); -mul( Z, Y2, Z ); -mul( Y, YY1, T ); -sub( X, Z, Z ); -sub( X, T, T ); -mul( X, Y2, X ); -add( Y, U2, Y ); -mul( Y, YY1, Y ); -sub( OneAndHalf, X, X ); -sub( OneAndHalf, Y, Y ); -k = cmp( X, Zero ); -k |= cmp( Y, Zero ); -k |= cmp( Z, Zero ); -if( cmp( T, Zero ) > 0 ) - k = 1; -if( k == 0 ) - { - add( OneAndHalf, U2, X ); - mul( X, Y2, X ); - sub( U2, OneAndHalf, Y ); - sub( U2, Y, Y ); - add( OneAndHalf, U2, Z ); - add( U2, Z, Z ); - sub( U2, OneAndHalf, T ); - mul( T, YY1, T ); - add( Z, U2, t ); - sub( t, X, X ); - mul( Y, YY1, StickyBit ); - mul( Z, Y2, S ); - sub( Y, T, T ); - sub( Y, U2, Y ); - add( StickyBit, Y, Y ); -/* Z = S - (Z + U2 + U2); */ - add( Z, U2, t ); - add( t, U2, t ); - sub( t, S, Z ); - add( Y2, U2, t ); - mul( t, YY1, StickyBit ); - mul( Y2, YY1, YY1 ); - sub( Y2, StickyBit, StickyBit ); - sub( Half, YY1, YY1 ); - k = cmp( X, Zero ); - k |= cmp( Y, Zero ); - k |= cmp( Z, Zero ); - k |= cmp( T, Zero ); - k |= cmp( StickyBit, Zero ); - k |= cmp( YY1, Half ); - if( k == 0 ) - { - RMult = Rounded; - printf("Multiplication appears to round correctly.\n"); - } - else - { - add( X, U2, t ); - k = cmp( t, Zero ); - if( cmp( Y, Zero ) >= 0 ) - k |= 1; - add( Z, U2, t ); - k |= cmp( t, Zero ); - if( cmp( T, Zero ) >= 0 ) - k |= 1; - add( StickyBit, U2, t ); - k |= cmp( t, Zero ); - if( cmp(YY1, Half) >= 0 ) - k |= 1; - if( k == 0 ) - { - printf("Multiplication appears to chop.\n"); - } - else - { - printf("* is neither chopped nor correctly rounded.\n"); - } - if( (RMult == Rounded) && (GMult == No) ) - printf("Multiplication has inconsistent result"); - } - } -else - printf("* is neither chopped nor correctly rounded.\n"); - -/*=============================================*/ -Milestone = 45; -/*=============================================*/ -add( One, U2, Y2 ); -sub( U2, One, YY1 ); -add( OneAndHalf, U2, Z ); -add( Z, U2, Z ); -div( Y2, Z, X ); -sub( U2, OneAndHalf, T ); -sub( U2, T, T ); -sub( U2, T, Y ); -div( YY1, Y, Y ); -add( Z, U2, Z ); -div( Y2, Z, Z ); -sub( OneAndHalf, X, X ); -sub( T, Y, Y ); -div( YY1, T, T ); -add( OneAndHalf, U2, t ); -sub( t, Z, Z ); -sub( OneAndHalf, U2, t ); -add( t, T, T ); -k = 0; -if( cmp( X, Zero ) > 0 ) - k = 1; -if( cmp( Y, Zero ) > 0 ) - k = 1; -if( cmp( Z, Zero ) > 0 ) - k = 1; -if( cmp( T, Zero ) > 0 ) - k = 1; -if( k == 0 ) - { - div( Y2, OneAndHalf, X ); - sub( U2, OneAndHalf, Y ); - add( U2, OneAndHalf, Z ); - sub( Y, X, X ); - div( YY1, OneAndHalf, T ); - div( YY1, Y, Y ); - add( Z, U2, t ); - sub( t, T, T ); - sub( Z, Y, Y ); - div( Y2, Z, Z ); - add( Y2, U2, YY1 ); - div( Y2, YY1, YY1 ); - sub( OneAndHalf, Z, Z ); - sub( Y2, YY1, Y2 ); - sub( U1, F9, YY1 ); - div( F9, YY1, YY1 ); - k = cmp( X, Zero ); - k |= cmp( Y, Zero ); - k |= cmp( Z, Zero ); - k |= cmp( T, Zero ); - k |= cmp( Y2, Zero ); - sub( Half, YY1, t ); - sub( Half, F9, t2 ); - k |= cmp( t, t2 ); - if( k == 0 ) - { - RDiv = Rounded; - printf("Division appears to round correctly.\n"); - if(GDiv == No) - printf("Division test inconsistent\n"); - } - else - { - k = 0; - if( cmp( X, Zero ) >= 0 ) - k = 1; - if( cmp( Y, Zero ) >= 0 ) - k = 1; - if( cmp( Z, Zero ) >= 0 ) - k = 1; - if( cmp( T, Zero ) >= 0 ) - k = 1; - if( cmp( Y, Zero ) >= 0 ) - k = 1; - sub( Half, YY1, t ); - sub( Half, F9, t2 ); - if( cmp( t, t2 ) >= 0 ) - k = 1; - if( k == 0 ) - { - RDiv = Chopped; - printf("Division appears to chop.\n"); - } - } - } -if(RDiv == Other) - printf("/ is neither chopped nor correctly rounded.\n"); -div( Radix, One, BInvrse ); -mul( BInvrse, Radix, t ); -sub( Half, t, t ); -if( cmp( t, Half ) != 0 ) - { - ErrCnt[Failure] += 1; - printf( "Radix * ( 1 / Radix ) differs from 1\n" ); - } - -Milestone = 50; -/*=============================================*/ -add( F9, U1, t ); -sub( Half, t, t ); -k = cmp( t, Half ); -add( BMinusU2, U2, t ); -sub( One, t, t ); -sub( One, Radix, t2 ); -k |= cmp( t, t2 ); -if( k != 0 ) - { - ErrCnt[Failure] += 1; - printf( "Incomplete carry-propagation in Addition\n" ); - } -mul( U1, U1, X ); -sub( X, One, X ); -sub( U2, One, Y ); -mul( U2, Y, Y ); -add( One, Y, Y ); -sub( Half, F9, Z ); -sub( Half, X, X ); -sub( Z, X, X ); -sub( One, Y, Y ); -if( (cmp(X,Zero) == 0) && (cmp(Y,Zero) == 0) ) - { - RAddSub = Chopped; - printf("Add/Subtract appears to be chopped.\n"); - } -if(GAddSub == Yes) - { - add( Half, U2, X ); - mul( X, U2, X ); - sub( U2, Half, Y ); - mul( Y, U2, Y ); - add( One, X, X ); - add( One, Y, Y ); - add( One, U2, t ); - sub( X, t, X ); - sub( Y, One, Y ); - k = cmp(X,Zero); - if( k ) - printf( "1+U2-[u2(1/2+U2)+1] != 0\n" ); - k2 = cmp(Y,Zero); - if( k2 ) - printf( "1-[U2(1/2-U2)+1] != 0\n" ); - k |= k2; - if( k == 0 ) - { - add( Half, U2, X ); - mul( X, U1, X ); - sub( U2, Half, Y ); - mul( Y, U1, Y ); - sub( X, One, X ); - sub( Y, One, Y ); - sub( X, F9, X ); - sub( Y, One, Y ); - k = cmp(X,Zero); - if( k ) - printf( "F9-[1-U1(1/2+U2)] != 0\n" ); - k2 = cmp(Y,Zero); - if( k2 ) - printf( "1-[1-U1(1/2-U2)] != 0\n" ); - k |= k2; - if( k == 0 ) - { - RAddSub = Rounded; - printf("Addition/Subtraction appears to round correctly.\n"); - if(GAddSub == No) - printf( "Add/Subtract test inconsistent\n"); - } - else - { - printf("Addition/Subtraction neither rounds nor chops.\n"); - } - } - else - printf("Addition/Subtraction neither rounds nor chops.\n"); - } -else - printf("Addition/Subtraction neither rounds nor chops.\n"); - -mov( One, S ); -add( One, Half, X ); -mul( Half, X, X ); -add( One, X, X ); -add( One, U2, Y ); -mul( Y, Half, Y ); -sub( Y, X, Z ); -sub( X, Y, T ); -add( Z, T, StickyBit ); -if( cmp(StickyBit, Zero) != 0 ) - { - mov( Zero, S ); - ErrCnt[Flaw] += 1; - printf( "(X - Y) + (Y - X) is non zero!\n" ); - } -mov( Zero, StickyBit ); -FLOOR( RadixD2, t ); -k2 = cmp( t, RadixD2 ); -k = 1; -if( (GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes) - && (RMult == Rounded) && (RDiv == Rounded) - && (RAddSub == Rounded) && (k2 == 0) ) - { - printf("Checking for sticky bit.\n"); - k = 0; - add( Half, U1, X ); - mul( X, U2, X ); - mul( Half, U2, Y ); - add( One, Y, Z ); - add( One, X, T ); - sub( One, Z, t ); - sub( One, T, t2 ); - if( cmp(t,Zero) > 0 ) - { - k = 1; - printf( "[1+(1/2)U2]-1 > 0\n" ); - } - if( cmp(t2,U2) < 0 ) - { - k = 1; - printf( "[1+U2(1/2+U1)]-1 < U2\n" ); - } - add( T, Y, Z ); - sub( X, Z, Y ); - sub( T, Z, t ); - sub( T, Y, t2 ); - if( cmp(t,U2) < 0 ) - { - k = 1; - printf( "[[1+U2(1/2+U1)]+(1/2)U2]-[1+U2(1/2+U1)] < U2\n" ); - } - if( cmp(t2,Zero) != 0 ) - { - k = 1; - printf( "(1/2)U2-[1+U2(1/2+U1)] != 0\n" ); - } - add( Half, U1, X ); - mul( X, U1, X ); - mul( Half, U1, Y ); - sub( Y, One, Z ); - sub( X, One, T ); - sub( One, Z, t ); - sub( F9, T, t2 ); - if( cmp(t,Zero) != 0 ) - { - k = 1; - printf( "(1-(1/2)U1)-1 != 0\n" ); - } - if( cmp(t2,Zero) != 0 ) - { - k = 1; - printf( "[1-U1(1/2+U1)]-F9 != 0\n" ); - } - sub( U1, Half, Z ); - mul( Z, U1, Z ); - sub( Z, F9, T ); - sub( Y, F9, Q ); - sub( F9, T, t ); - if( cmp( t, Zero ) != 0 ) - { - k = 1; - printf( "[F9-U1(1/2-U1)]-F9 != 0\n" ); - } - sub( U1, F9, t ); - sub( Q, t, t ); - if( cmp( t, Zero ) != 0 ) - { - k = 1; - printf( "(F9-U1)-(F9-(1/2)U1) != 0\n" ); - } - add( One, U2, Z ); - mul( Z, OneAndHalf, Z ); - add( OneAndHalf, U2, T ); - sub( Z, T, T ); - add( U2, T, T ); - div( Radix, Half, X ); - add( One, X, X ); - mul( Radix, U2, Y ); - add( One, Y, Y ); - mul( X, Y, Z ); - if( cmp( T, Zero ) != 0 ) - { - k = 1; - printf( "(3/2+U2)-3/2(1+U2)+U2 != 0\n" ); - } - mul( Radix, U2, t ); - add( X, t, t ); - sub( Z, t, t ); - if( cmp( t, Zero ) != 0 ) - { - k = 1; - printf( "(1+1/2Radix)+Radix*U2-[1+1/(2Radix)][1+Radix*U2] != 0\n" ); - } - if( cmp(Radix, Two) != 0 ) - { - add( Two, U2, X ); - div( Two, X, Y ); - sub( One, Y, t ); - if( cmp( t, Zero) != 0 ) - k = 1; - } - } -if( k == 0 ) - { - printf("Sticky bit apparently used correctly.\n"); - mov( One, StickyBit ); - } -else - { - printf("Sticky bit used incorrectly or not at all.\n"); - } - -if( GMult == No || GDiv == No || GAddSub == No || - RMult == Other || RDiv == Other || RAddSub == Other) - { - ErrCnt[Flaw] += 1; - printf("lack(s) of guard digits or failure(s) to correctly round or chop\n"); -printf( "(noted above) count as one flaw in the final tally below\n" ); - } -/*=============================================*/ -Milestone = 60; -/*=============================================*/ -printf("\n"); -printf("Does Multiplication commute? "); -printf("Testing on %d random pairs.\n", NoTrials); -SQRT( Three, Random9 ); -mov( Third, Random1 ); -I = 1; -do - { - Random(); - mov( Random1, X ); - Random(); - mov( Random1, Y ); - mul( Y, X, Z9 ); - mul( X, Y, Z ); - sub( Z9, Z, Z9 ); - I = I + 1; - } -while ( ! ((I > NoTrials) || (cmp(Z9,Zero) != 0))); -if(I == NoTrials) - { - div( Three, Half, t ); - add( One, t, Random1 ); - add( U2, U1, t ); - add( t, One, Random2 ); - mul( Random1, Random2, Z ); - mul( Random2, Random1, Y ); -/* Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half / - * Three) * ((U2 + U1) + One); - */ - div( Three, Half, t2 ); - add( One, t2, t2 ); - add( U2, U1, t ); - add( t, One, t ); - mul( t2, t, Z9 ); - mul( t2, t, t ); - sub( t, Z9, Z9 ); - } -if(! ((I == NoTrials) || (cmp(Z9,Zero) == 0))) - { - ErrCnt[Defect] += 1; - printf( "X * Y == Y * X trial fails.\n"); - } -else - { - printf(" No failures found in %d integer pairs.\n", NoTrials); - } -/*=============================================*/ -Milestone = 70; -/*=============================================*/ -sqtest(); -Milestone = 90; -pow1test(); - -Milestone = 110; - -printf("Seeking Underflow thresholds UfThold and E0.\n"); -mov( U1, D ); -FLOOR( Precision, t ); -if( cmp(Precision, t) != 0 ) - { - mov( BInvrse, D ); - mov( Precision, X ); - do - { - mul( D, BInvrse, D ); - sub( One, X, X ); - } - while( cmp(X, Zero) > 0 ); - } -mov( One, Y ); -mov( D, Z ); -/* ... D is power of 1/Radix < 1. */ -sigsave = sigfpe; -if( setjmp(ovfl_buf) ) - goto under0; -do - { - mov( Y, C ); - mov( Z, Y ); - mul( Y, Y, Z ); - add( Z, Z, t ); - } -while( (cmp(Y,Z) > 0) && (cmp(t,Z) > 0) ); - -under0: -sigsave = 0; - -mov( C, Y ); -mul( Y, D, Z ); -sigsave = sigfpe; -if( setjmp(ovfl_buf) ) - goto under1; -do - { - mov( Y, C ); - mov( Z, Y ); - mul( Y, D, Z ); - add( Z, Z, t ); - } -while( (cmp(Y,Z) > 0) && (cmp(t,Z) > 0) ); - -under1: -sigsave = 0; - -if( cmp(Radix,Two) < 0 ) - mov( Two, HInvrse ); -else - mov( Radix, HInvrse ); -div( HInvrse, One, H ); -/* ... 1/HInvrse == H == Min(1/Radix, 1/2) */ -div( C, One, CInvrse ); -mov( C, E0 ); -mul( E0, H, Z ); -/* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */ -sigsave = sigfpe; -if( setjmp(ovfl_buf) ) - goto under2; -do - { - mov( E0, Y ); - mov( Z, E0 ); - mul( E0, H, Z ); - add( Z, Z, t ); - } -while( (cmp(E0,Z) > 0) && (cmp(t,Z) > 0) ); - -under2: -sigsave = 0; - -mov( E0, UfThold ); -mov( Zero, E1 ); -mov( Zero, Q ); -mov( U2, E9 ); -add( One, E9, S ); -mul( C, S, D ); -if( cmp(D,C) <= 0 ) - { - mul( Radix, U2, E9 ); - add( One, E9, S ); - mul( C, S, D ); - if( cmp(D, C) <= 0 ) - { - ErrCnt[Failure] += 1; - printf( "multiplication gets too many last digits wrong.\n" ); - mov( E0, Underflow ); - mov( Zero, YY1 ); - mov( Z, PseudoZero ); - } - } -else - { - mov( D, Underflow ); - mul( Underflow, H, PseudoZero ); - mov( Zero, UfThold ); - do - { - mov( Underflow, YY1 ); - mov( PseudoZero, Underflow ); - add( E1, E1, t ); - if( cmp(t, E1) <= 0) - { - mul( Underflow, HInvrse, Y2 ); - sub( Y2, YY1, E1 ); - FABS( E1 ); - mov( YY1, Q ); - if( (cmp( UfThold, Zero ) == 0) - && (cmp(YY1, Y2) != 0) ) - mov( YY1, UfThold ); - } - mul( PseudoZero, H, PseudoZero ); - add( PseudoZero, PseudoZero, t ); - } - while( (cmp(Underflow, PseudoZero) > 0) - && (cmp(t, PseudoZero) > 0) ); - } -/* Comment line 4530 .. 4560 */ -if( cmp(PseudoZero, Zero) != 0 ) - { - printf("\n"); - mov(PseudoZero, Z ); -/* ... Test PseudoZero for "phoney- zero" violates */ -/* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero - ... */ - if( cmp(PseudoZero, Zero) <= 0 ) - { - ErrCnt[Failure] += 1; - printf("Positive expressions can underflow to an\n"); - printf("allegedly negative value\n"); - printf("PseudoZero that prints out as: " ); - show( PseudoZero ); - mov( PseudoZero, X ); - neg( X ); - if( cmp(X, Zero) <= 0 ) - { - printf("But -PseudoZero, which should be\n"); - printf("positive, isn't; it prints out as " ); - show( X ); - } - } - else - { - ErrCnt[Flaw] += 1; - printf( "Underflow can stick at an allegedly positive\n"); - printf("value PseudoZero that prints out as " ); - show( PseudoZero ); - } -/* TstPtUf();*/ - } - -/*=============================================*/ -Milestone = 120; -/*=============================================*/ -mul( CInvrse, Y, t ); -mul( CInvrse, YY1, t2 ); -if( cmp(t,t2) > 0 ) - { - mul( H, S, S ); - mov( Underflow, E0 ); - } -if(! ((cmp(E1,Zero) == 0) || (cmp(E1,E0) == 0)) ) - { - ErrCnt[Defect] += 1; - if( cmp(E1,E0) < 0 ) - { - printf("Products underflow at a higher"); - printf(" threshold than differences.\n"); - if( cmp(PseudoZero,Zero) == 0 ) - mov( E1, E0 ); - } - else - { - printf("Difference underflows at a higher"); - printf(" threshold than products.\n"); - } - } -printf("Smallest strictly positive number found is E0 = " ); -show( E0 ); -mov( E0, Z ); -TstPtUf(); -mov( E0, Underflow ); -if(N == 1) - mov( Y, Underflow ); -I = 4; -if( cmp(E1,Zero) == 0 ) - I = 3; -if( cmp( UfThold,Zero) == 0 ) - I = I - 2; -UfNGrad = True; -switch(I) - { - case 1: - mov( Underflow, UfThold ); - mul( CInvrse, Q, t ); - mul( CInvrse, Y, t2 ); - mul( t2, S, t2 ); - if( cmp( t, t2 ) != 0 ) - { - mov( Y, UfThold ); - ErrCnt[Failure] += 1; - printf( "Either accuracy deteriorates as numbers\n"); - printf("approach a threshold = " ); - show( UfThold ); - printf(" coming down from " ); - show( C ); - printf(" or else multiplication gets too many last digits wrong.\n"); - } - break; - - case 2: - ErrCnt[Failure] += 1; - printf( "Underflow confuses Comparison which alleges that\n"); - printf("Q == Y while denying that |Q - Y| == 0; these values\n"); - printf("print out as Q = " ); - show( Q ); - printf( ", Y = " ); - show( Y ); - sub( Y2, Q, t ); - FABS(t); - printf ("|Q - Y| = " ); - show( t ); - mov( Q, UfThold ); - break; - - case 3: - mov( X, X ); - break; - - case 4: - div( E9, E1, t ); - sub( t, UfThold, t ); - FABS(t); - if( (cmp(Q,UfThold) == 0) && (cmp(E1,E0) == 0) - && (cmp(t,E1) <= 0) ) - { - UfNGrad = False; - printf("Underflow is gradual; it incurs Absolute Error =\n"); - printf("(roundoff in UfThold) < E0.\n"); - mul( E0, CInvrse, Y ); - add( OneAndHalf, U2, t ); - mul( Y, t, Y ); - add( One, U2, X ); - mul( CInvrse, X, X ); - div( X, Y, t ); - IEEE = (cmp(t,E0) == 0); - if( IEEE == 0 ) - { - printf( "((CInvrse E0) (1.5+U2)) / (CInvrse (1+U2)) != E0\n" ); - printf( "CInvrse = " ); - show( CInvrse ); - printf( "E0 = " ); - show( E0 ); - printf( "U2 = " ); - show( U2 ); - printf( "X = " ); - show(X); - printf( "Y = " ); - show(Y); - printf( "Y/X = " ); - show(t); - } - } - } -if(UfNGrad) - { - printf("\n"); - div( UfThold, Underflow, R ); - SQRT( R, R ); - if( cmp(R,H) <= 0) - { - mul( R, UfThold, Z ); -/* X = Z * (One + R * H * (One + H));*/ - add( One, H, X ); - mul( H, X, X ); - mul( R, X, X ); - add( One, X, X ); - mul( Z, X, X ); - } - else - { - mov( UfThold, Z ); -/*X = Z * (One + H * H * (One + H));*/ - add( One, H, X ); - mul( H, X, X ); - mul( H, X, X ); - add( One, X, X ); - mul( Z, X, X ); - } - sub( Z, X, t ); -/* if(! ((cmp(X,Z) == 0) || (cmp(t,Zero) != 0)) )*/ - if( (cmp(X,Z) != 0) && (cmp(t,Zero) == 0) ) - { -/* ErrCnt[Flaw] += 1;*/ - ErrCnt[Serious] += 1; - printf("X = " ); - show( X ); - printf( "\tis not equal to Z = " ); - show( Z ); -/* sub( Z, X, Z9 );*/ - printf("yet X - Z yields " ); - show( t ); - printf("which compares equal to " ); - show( Zero ); - printf(" Should this NOT signal Underflow, "); - printf("this is a SERIOUS DEFECT\nthat causes "); - printf("confusion when innocent statements like\n");; - printf(" if (X == Z) ... else"); - printf(" ... (f(X) - f(Z)) / (X - Z) ...\n"); - printf("encounter Division by Zero although actually\n"); - printf("X / Z = 1 + " ); - div( Z, X, t ); - sub( Half, t, t ); - sub( Half, t, t ); - show(t); - } - } -printf("The Underflow threshold is " ); -show( UfThold ); -printf( "below which calculation may suffer larger Relative error than" ); -printf( " merely roundoff.\n"); -mul( U1, U1, Y2 ); -mul( Y2, Y2, Y ); -mul( Y, U1, Y2 ); -if( cmp( Y2,UfThold) <= 0 ) - { - if( cmp(Y,E0) > 0 ) - { - ErrCnt[Defect] += 1; - I = 5; - } - else - { - ErrCnt[Serious] += 1; - I = 4; - } - printf("Range is too narrow; U1^%d Underflows.\n", I); - } -Milestone = 130; - -/*Y = - FLOOR(Half - TwoForty * LOG(UfThold) / LOG(HInvrse)) / TwoForty;*/ -LOG( UfThold, Y ); -LOG( HInvrse, t ); -div( t, Y, Y ); -mul( TwoForty, Y, Y ); -sub( Y, Half, Y ); -FLOOR( Y, Y ); -div( TwoForty, Y, Y ); -neg(Y); -sub( One, Y, Y2 ); /* ***** changed from Y2 = Y + Y */ -printf("Since underflow occurs below the threshold\n"); -printf("UfThold = " ); -show( HInvrse ); -printf( "\tto the power " ); -show( Y ); -printf( "only underflow should afflict the expression " ); -show( HInvrse ); -printf( "\tto the power " ); -show( Y2 ); -POW( HInvrse, Y2, V9 ); -printf("Actually calculating yields: " ); -show( V9 ); -add( Radix, Radix, t ); -add( t, E9, t ); -mul( t, UfThold, t ); -if( (cmp(V9,Zero) < 0) || (cmp(V9,t) > 0) ) - { - ErrCnt[Serious] += 1; - printf( "this is not between 0 and underflow\n"); - printf(" threshold = " ); - show( UfThold ); - } -else - { - add( One, E9, t ); - mul( UfThold, t, t ); - if( cmp(V9,t) <= 0 ) - printf("This computed value is O.K.\n"); - else - { - ErrCnt[Defect] += 1; - printf( "this is not between 0 and underflow\n"); - printf(" threshold = " ); - show( UfThold ); - } - } - -Milestone = 140; - -pow2test(); - -/*=============================================*/ -Milestone = 160; -/*=============================================*/ -Pause(); -printf("Searching for Overflow threshold:\n"); -printf("This may generate an error.\n"); -sigsave = sigfpe; -I = 0; -mov( CInvrse, Y ); /* a large power of 2 */ -neg(Y); -mul( HInvrse, Y, V9 ); /* HInvrse = 2 */ -if (setjmp(ovfl_buf)) - goto overflow; -do - { - mov( Y, V ); - mov( V9, Y ); - mul( HInvrse, Y, V9 ); - } -while( cmp(V9,Y) < 0 ); /* V9 = 2 * Y */ -I = 1; - -overflow: - -show( HInvrse ); -printf( "\ttimes " ); -show( Y ); -printf( "\tequals " ); -show( V9 ); - -mov( V9, Z ); -printf("Can `Z = -Y' overflow?\n"); -printf("Trying it on Y = " ); -show(Y); -mov( Y, V9 ); -neg( V9 ); -mov( V9, V0 ); -sub( Y, V, t ); -add( V, V0, t2 ); -if( cmp(t,t2) == 0 ) - printf("Seems O.K.\n"); -else - { - printf("finds a Flaw, -(-Y) differs from Y.\n"); - printf( "V-Y=t:" ); - show(V); - show(Y); - show(t); - printf( "V+V0=t2:" ); - show(V); - show(V0); - show(t2); - ErrCnt[Flaw] += 1; - } -if( (cmp(Z, Y) != 0) && (I != 0) ) - { - ErrCnt[Serious] += 1; - printf("overflow past " ); - show( Y ); - printf( "\tshrinks to " ); - show( Z ); - printf( "= Y * " ); - show( HInvrse ); - } -/*Y = V * (HInvrse * U2 - HInvrse);*/ -mul( HInvrse, U2, Y ); -sub( HInvrse, Y, Y ); -mul( V, Y, Y ); -/*Z = Y + ((One - HInvrse) * U2) * V;*/ -sub( HInvrse, One, Z ); -mul( Z, U2, Z ); -mul( Z, V, Z ); -add( Y, Z, Z ); -if( cmp(Z,V0) < 0 ) - mov( Z, Y ); -if( cmp(Y,V0) < 0) - mov( Y, V ); -sub( V, V0, t ); -if( cmp(t,V0) < 0 ) - mov( V0, V ); -printf("Overflow threshold is V = " ); -show( V ); -if(I) - { - printf("Overflow saturates at V0 = " ); - show( V0 ); - } -else -printf("There is no saturation value because the system traps on overflow.\n"); - -mul( V, One, V9 ); -printf("No Overflow should be signaled for V * 1 = " ); -show( V9 ); -div( One, V, V9 ); - printf(" nor for V / 1 = " ); - show( V9 ); - printf("Any overflow signal separating this * from the one\n"); - printf("above is a DEFECT.\n"); -/*=============================================*/ -Milestone = 170; -/*=============================================*/ -mov( V, t ); -neg( t ); -k = 0; -if( cmp(t,V) >= 0 ) - k = 1; -mov( V0, t ); -neg( t ); -if( cmp(t,V0) >= 0 ) - k = 1; -mov( UfThold, t ); -neg(t); -if( cmp(t,V) >= 0 ) - k = 1; -if( cmp(UfThold,V) >= 0 ) - k = 1; -if( k != 0 ) - { - ErrCnt[Failure] += 1; - printf( "Comparisons involving +-"); - show( V ); - show( V0 ); - show( UfThold ); - printf("are confused by Overflow." ); - } -/*=============================================*/ -Milestone = 175; -/*=============================================*/ -printf("\n"); -for(Indx = 1; Indx <= 3; ++Indx) { - switch(Indx) - { - case 1: mov(UfThold, Z); break; - case 2: mov( E0, Z); break; - case 3: mov(PseudoZero, Z); break; - } -if( cmp(Z, Zero) != 0 ) - { - SQRT( Z, V9 ); - mul( V9, V9, Y ); - mul( Radix, E9, t ); - sub( t, One, t ); - div( t, Y, t ); - add( One, Radix, t2 ); - add( t2, E9, t2 ); - mul( t2, Z, t2 ); - if( (cmp(t,Z) < 0) || (cmp(Y,t2) > 0) ) - { - if( cmp(V9,U1) > 0 ) - ErrCnt[Serious] += 1; - else - ErrCnt[Defect] += 1; - printf("Comparison alleges that what prints as Z = " ); - show( Z ); - printf(" is too far from sqrt(Z) ^ 2 = " ); - show( Y ); - } - } -} - -Milestone = 180; - -for(Indx = 1; Indx <= 2; ++Indx) - { - if(Indx == 1) - mov( V, Z ); - else - mov( V0, Z ); - SQRT( Z, V9 ); - mul( Radix, E9, X ); - sub( X, One, X ); - mul( X, V9, X ); - mul( V9, X, V9 ); - mul( Two, Radix, t ); - mul( t, E9, t ); - sub( t, One, t ); - mul( t, Z, t ); - if( (cmp(V9,t) < 0) || (cmp(V9,Z) > 0) ) - { - mov( V9, Y ); - if( cmp(X,W) < 0 ) - ErrCnt[Serious] += 1; - else - ErrCnt[Defect] += 1; - printf("Comparison alleges that Z = " ); - show( Z ); - printf(" is too far from sqrt(Z) ^ 2 :" ); - show( Y ); - } - } - -Milestone = 190; - -Pause(); -mul( UfThold, V, X ); -mul( Radix, Radix, Y ); -mul( X, Y, t ); -if( (cmp(t,One) < 0) || (cmp(X,Y) > 0) ) - { - mul( X, Y, t ); - div( U1, Y, t2 ); - if( (cmp(t,U1) < 0) || (cmp(X,t2) > 0) ) - { - ErrCnt[Defect] += 1; - printf( "Badly " ); - } - else - { - ErrCnt[Flaw] += 1; - } - printf(" unbalanced range; UfThold * V = " ); - show( X ); - printf( "\tis too far from 1.\n"); - } -Milestone = 200; - -for(Indx = 1; Indx <= 5; ++Indx) - { - mov( F9, X ); - switch(Indx) - { - case 2: add( One, U2, X ); break; - case 3: mov( V, X ); break; - case 4: mov(UfThold,X); break; - case 5: mov(Radix,X); - } - mov( X, Y ); - - sigsave = sigfpe; - if (setjmp(ovfl_buf)) - { - printf(" X / X traps when X = " ); - show( X ); - } - else - { -/*V9 = (Y / X - Half) - Half;*/ - div( X, Y, t ); - sub( Half, t, t ); - sub( Half, t, V9 ); - if( cmp(V9,Zero) == 0 ) - continue; - mov( U1, t ); - neg(t); - if( (cmp(V9,t) == 0) && (Indx < 5) ) - { - ErrCnt[Flaw] += 1; - } - else - { - ErrCnt[Serious] += 1; - } - printf(" X / X differs from 1 when X = " ); - show( X ); - printf(" instead, X / X - 1/2 - 1/2 = " ); - show( V9 ); - } - } - - Pause(); - printf("\n"); - { - static char *msg[] = { - "FAILUREs encountered =", - "SERIOUS DEFECTs discovered =", - "DEFECTs discovered =", - "FLAWs discovered =" }; - int i; - for(i = 0; i < 4; i++) if (ErrCnt[i]) - printf("The number of %-29s %d.\n", - msg[i], ErrCnt[i]); - } - printf("\n"); - if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] - + ErrCnt[Flaw]) > 0) { - if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[ - Defect] == 0) && (ErrCnt[Flaw] > 0)) { - printf("The arithmetic diagnosed seems "); - printf("satisfactory though flawed.\n"); - } - if ((ErrCnt[Failure] + ErrCnt[Serious] == 0) - && ( ErrCnt[Defect] > 0)) { - printf("The arithmetic diagnosed may be acceptable\n"); - printf("despite inconvenient Defects.\n"); - } - if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) { - printf("The arithmetic diagnosed has "); - printf("unacceptable serious defects.\n"); - } - if (ErrCnt[Failure] > 0) { - printf("Fatal FAILURE may have spoiled this"); - printf(" program's subsequent diagnoses.\n"); - } - } - else { - printf("No failures, defects nor flaws have been discovered.\n"); - if (! ((RMult == Rounded) && (RDiv == Rounded) - && (RAddSub == Rounded) && (RSqrt == Rounded))) - printf("The arithmetic diagnosed seems satisfactory.\n"); - else { - k = 0; - if( cmp( Radix, Two ) == 0 ) - k = 1; - if( cmp( Radix, Ten ) == 0 ) - k = 1; - if( (cmp(StickyBit,One) >= 0) && (k == 1) ) - { - printf("Rounding appears to conform to "); - printf("the proposed IEEE standard P"); - k = 0; - k |= cmp( Radix, Two ); - mul( Four, Three, t ); - mul( t, Two, t ); - sub( t, Precision, t ); - sub( TwentySeven, Precision, t2 ); - sub( TwentySeven, t2, t2 ); - add( t2, One, t2 ); - mul( t2, t, t ); - if( (cmp(Radix,Two) == 0) - && (cmp(t,Zero) == 0) ) - printf("754"); - else - printf("854"); - if(IEEE) - printf(".\n"); - else - { - printf(",\nexcept for possibly Double Rounding"); - printf(" during Gradual Underflow.\n"); - } - } - printf("The arithmetic diagnosed appears to be excellent!\n"); - } - } - if (fpecount) - printf("\nA total of %d floating point exceptions were registered.\n", - fpecount); - printf("END OF TEST.\n"); - } - - -/* Random */ -/* Random computes - X = (Random1 + Random9)^5 - Random1 = X - FLOOR(X) + 0.000005 * X; - and returns the new value of Random1 -*/ - - -static int randflg = 0; -FLOAT(C5em6); - -Random() -{ - -if( randflg == 0 ) - { - mov( Six, t ); - neg(t); - POW( Ten, t, t ); - mul( Five, t, C5em6 ); - randflg = 1; - } -add( Random1, Random9, t ); -mul( t, t, t2 ); -mul( t2, t2, t2 ); -mul( t, t2, t ); -FLOOR(t, t2 ); -sub( t2, t, t2 ); -mul( t, C5em6, t ); -add( t, t2, Random1 ); -/*return(Random1);*/ -} - -/* SqXMinX */ - -SqXMinX( ErrKind ) -int ErrKind; -{ -mul( X, BInvrse, t2 ); -sub( t2, X, t ); -/*SqEr = ((SQRT(X * X) - XB) - XA) / OneUlp;*/ -mul( X, X, Sqarg ); -SQRT( Sqarg, SqEr ); -sub( t2, SqEr, SqEr ); -sub( t, SqEr, SqEr ); -div( OneUlp, SqEr, SqEr ); -if( cmp(SqEr,Zero) != 0) - { - Showsq( 0 ); - add( J, One, J ); - ErrCnt[ErrKind] += 1; - printf("sqrt of " ); - mul( X, X, t ); - show( t ); - printf( "minus " ); - show( X ); - printf( "equals " ); - mul( OneUlp, SqEr, t ); - show( t ); - printf("\tinstead of correct value 0 .\n"); - } -} - -/* NewD */ - -NewD() -{ -mul( Z1, Q, X ); -/*X = FLOOR(Half - X / Radix) * Radix + X;*/ -div( Radix, X, t ); -sub( t, Half, t ); -FLOOR( t, t ); -mul( t, Radix, t ); -add( t, X, X ); -/*Q = (Q - X * Z) / Radix + X * X * (D / Radix);*/ -mul( X, Z, t ); -sub( t, Q, t ); -div( Radix, t, t ); -div( Radix, D, t2 ); -mul( X, t2, t2 ); -mul( X, t2, t2 ); -add( t, t2, Q ); -/*Z = Z - Two * X * D;*/ -mul( Two, X, t ); -mul( t, D, t ); -sub( t, Z, Z ); - -if( cmp(Z,Zero) <= 0) - { - neg(Z); - neg(Z1); - } -mul( Radix, D, D ); -} - -/* SR3750 */ - -SR3750() -{ -sub( Radix, X, t ); -sub( Radix, Z2, t2 ); -k = 0; -if( cmp(t,t2) < 0 ) - k = 1; -sub( Z2, X, t ); -sub( Z2, W, t2 ); -if( cmp(t,t2) > 0 ) - k = 1; -/*if (! ((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2))) {*/ -if( k == 0 ) - { - I = I + 1; - mul( X, D, X2 ); - mov( X2, Sqarg ); - SQRT( X2, X2 ); -/*Y2 = (X2 - Z2) - (Y - Z2);*/ - sub( Z2, X2, Y2 ); - sub( Z2, Y, t ); - sub( t, Y2, Y2 ); - sub( Half, Y, X2 ); - div( X2, X8, X2 ); - mul( Half, X2, t ); - mul( t, X2, t ); - sub( t, X2, X2 ); -/*SqEr = (Y2 + Half) + (Half - X2);*/ - add( Y2, Half, SqEr ); - sub( X2, Half, t ); - add( t, SqEr, SqEr ); - Showsq( -1 ); - sub( X2, Y2, SqEr ); - Showsq( 1 ); - } -} - -/* IsYeqX */ - -IsYeqX() -{ -if( cmp(Y,X) != 0 ) - { - if (N <= 0) - { - if( (cmp(Z,Zero) == 0) && (cmp(Q,Zero) <= 0) ) - printf("WARNING: computing\n"); - else - { - ErrCnt[Defect] += 1; - printf( "computing\n"); - } - show( Z ); - printf( "\tto the power " ); - show( Q ); - printf("\tyielded " ); - show( Y ); - printf("\twhich compared unequal to correct " ); - show( X ); - sub( X, Y, t ); - printf("\t\tthey differ by " ); - show( t ); - } - N = N + 1; /* ... count discrepancies. */ - } -} - -/* SR3980 */ - -SR3980() -{ -long li; - -do - { -/*Q = (FLOAT) I;*/ - li = I; - LTOF( &li, Q ); - POW( Z, Q, Y ); - IsYeqX(); - if(++I > M) - break; - mul( Z, X, X ); - } -while( cmp(X,W) < 0 ); -} - -/* PrintIfNPositive */ - -PrintIfNPositive() -{ -if(N > 0) - printf("Similar discrepancies have occurred %d times.\n", N); -} - - -/* TstPtUf */ - -TstPtUf() -{ -N = 0; -if( cmp(Z,Zero) != 0) - { - printf( "Z = " ); - show(Z); - printf("Since comparison denies Z = 0, evaluating "); - printf("(Z + Z) / Z should be safe.\n"); - sigsave = sigfpe; - if (setjmp(ovfl_buf)) - goto very_serious; - add( Z, Z, Q9 ); - div( Z, Q9, Q9 ); - printf("What the machine gets for (Z + Z) / Z is " ); - show( Q9 ); - sub( Two, Q9, t ); - FABS(t); - mul( Radix, U2, t2 ); - if( cmp(t,t2) < 0 ) - { - printf("This is O.K., provided Over/Underflow"); - printf(" has NOT just been signaled.\n"); - } - else - { - if( (cmp(Q9,One) < 0) || (cmp(Q9,Two) > 0) ) - { -very_serious: - N = 1; - ErrCnt [Serious] = ErrCnt [Serious] + 1; - printf("This is a VERY SERIOUS DEFECT!\n"); - } - else - { - N = 1; - ErrCnt[Defect] += 1; - printf("This is a DEFECT!\n"); - } - } - mul( Z, One, V9 ); - mov( V9, Random1 ); - mul( One, Z, V9 ); - mov( V9, Random2 ); - div( One, Z, V9 ); - if( (cmp(Z,Random1) == 0) && (cmp(Z,Random2) == 0) - && (cmp(Z,V9) == 0) ) - { - if (N > 0) - Pause(); - } - else - { - N = 1; - ErrCnt[Defect] += 1; - printf( "What prints as Z = "); - show( Z ); - printf( "\tcompares different from " ); - if( cmp(Z,Random1) != 0) - { - printf("Z * 1 = " ); - show( Random1 ); - } - if( (cmp(Z,Random2) != 0) - || (cmp(Random2,Random1) != 0) ) - { - printf("1 * Z == " ); - show( Random2 ); - } - if( cmp(Z,V9) != 0 ) - { - printf("Z / 1 = " ); - show( V9 ); - } - if( cmp(Random2,Random1) != 0 ) - { - ErrCnt[Defect] += 1; - printf( "Multiplication does not commute!\n"); - printf("\tComparison alleges that 1 * Z = " ); - show(Random2); - printf("\tdiffers from Z * 1 = " ); - show(Random1); - } - Pause(); - } - } -} - -Pause() -{ -} - -Sign( x, y ) -FSIZE *x, *y; -{ - -if( cmp( x, Zero ) < 0 ) - { - mov( One, y ); - neg( y ); - } -else - { - mov( One, y ); - } -} - -sqtest() -{ -printf("\nRunning test of square root(x).\n"); - -RSqrt = Other; -k = 0; -SQRT( Zero, t ); -k |= cmp( Zero, t ); -mov( Zero, t ); -neg(t); -SQRT( t, t2 ); -k |= cmp( t, t2 ); -SQRT( One, t ); -k |= cmp( One, t ); -if( k != 0 ) - { - ErrCnt[Failure] += 1; - printf( "Square root of 0.0, -0.0 or 1.0 wrong\n"); - } -mov( Zero, MinSqEr ); -mov( Zero, MaxSqEr ); -mov( Zero, J ); -mov( Radix, X ); -mov( U2, OneUlp ); -SqXMinX( Serious ); -mov( BInvrse, X ); -mul( BInvrse, U1, OneUlp ); -SqXMinX( Serious ); -mov( U1, X ); -mul( U1, U1, OneUlp ); -SqXMinX( Serious ); -if( cmp(J,Zero) != 0) - Pause(); -printf("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials); -mov( Zero, J ); -mov( Two, X ); -mov( Radix, Y ); -if( cmp(Radix,One) != 0 ) - { - lngint = NoTrials; - LTOF( &lngint, t ); - FTOL( t, &lng2, X ); - if( lngint != lng2 ) - { - printf( "Integer conversion error\n" ); - exit(1); - } - do - { - mov( Y, X ); - mul( Radix, Y, Y ); - sub( X, Y, t2 ); - } - while( ! (cmp(t2,t) >= 0) ); - } -mul( X, U2, OneUlp ); -I = 1; -while(I < 10) - { - add( X, One, X ); - SqXMinX( Defect ); - if( cmp(J,Zero) > 0 ) - break; - I = I + 1; - } -printf("Test for sqrt monotonicity.\n"); -I = - 1; -mov( BMinusU2, X ); -mov( Radix, Y ); -mul( Radix, U2, Z ); -add( Radix, Z, Z ); -NotMonot = False; -Monot = False; -while( ! (NotMonot || Monot)) - { - I = I + 1; - SQRT(X, X); - SQRT(Y,Q); - SQRT(Z,Z); - if( (cmp(X,Q) > 0) || (cmp(Q,Z) > 0) ) - NotMonot = True; - else - { - add( Q, Half, Q ); - FLOOR( Q, Q ); - mul( Q, Q, t ); - if( (I > 0) || (cmp(Radix,t) == 0) ) - Monot = True; - else if (I > 0) - { - if(I > 1) - Monot = True; - else - { - mul( Y, BInvrse, Y ); - sub( U1, Y, X ); - add( Y, U1, Z ); - } - } - else - { - mov( Q, Y ); - sub( U2, Y, X ); - add( Y, U2, Z ); - } - } - } -if( Monot ) - printf("sqrt has passed a test for Monotonicity.\n"); -else - { - ErrCnt[Defect] += 1; - printf("sqrt(X) is non-monotonic for X near " ); - show(Y); - } -/*=============================================*/ -Milestone = 80; -/*=============================================*/ -add( MinSqEr, Half, MinSqEr ); -sub( Half, MaxSqEr, MaxSqEr); -/*Y = (SQRT(One + U2) - One) / U2;*/ -add( One, U2, Sqarg ); -SQRT( Sqarg, Y ); -sub( One, Y, Y ); -div( U2, Y, Y ); -/*SqEr = (Y - One) + U2 / Eight;*/ -sub( One, Y, t ); -div( Eight, U2, SqEr ); -add( t, SqEr, SqEr ); -Showsq( 1 ); -div( Eight, U2, SqEr ); -add( Y, SqEr, SqEr ); -Showsq( -1 ); -/*Y = ((SQRT(F9) - U2) - (One - U2)) / U1;*/ -mov( F9, Sqarg ); -SQRT( Sqarg, Y ); -sub( U2, Y, Y ); -sub( U2, One, t ); -sub( t, Y, Y ); -div( U1, Y, Y ); -div( Eight, U1, SqEr ); -add( Y, SqEr, SqEr ); -Showsq( 1 ); -/*SqEr = (Y + One) + U1 / Eight;*/ -div( Eight, U1, t ); -add( Y, One, SqEr ); -add( SqEr, t, SqEr ); -Showsq( -1 ); -mov( U2, OneUlp ); -mov( OneUlp, X ); -for( Indx = 1; Indx <= 3; ++Indx) - { -/*Y = SQRT((X + U1 + X) + F9);*/ - add( X, U1, Y ); - add( Y, X, Y ); - add( Y, F9, Y ); - mov( Y, Sqarg ); - SQRT( Sqarg, Y ); -/*Y = ((Y - U2) - ((One - U2) + X)) / OneUlp;*/ - sub( U2, One, t ); - add( t, X, t ); - sub( U2, Y, Y ); - sub( t, Y, Y ); - div( OneUlp, Y, Y ); -/*Z = ((U1 - X) + F9) * Half * X * X / OneUlp;*/ - sub( X, U1, t ); - add( t, F9, t ); - mul( t, Half, t ); - mul( t, X, t ); - mul( t, X, t ); - div( OneUlp, t, Z ); - add( Y, Half, SqEr ); - add( SqEr, Z, SqEr ); - Showsq( -1 ); - sub( Half, Y, SqEr ); - add( SqEr, Z, SqEr ); - Showsq( 1 ); - if(((Indx == 1) || (Indx == 3))) - { -/*X = OneUlp * Sign (X) * FLOOR(Eight / (Nine * SQRT(OneUlp)));*/ - mov( OneUlp, Sqarg ); - SQRT( Sqarg, t ); - mul( Nine, t, t ); - div( t, Eight, t ); - FLOOR( t, t ); - Sign( X, t2 ); - mul( t2, t, t ); - mul( OneUlp, t, X ); - } - else - { - mov( U1, OneUlp ); - mov( OneUlp, X ); - neg( X ); - } - } -/*=============================================*/ -Milestone = 85; -/*=============================================*/ -SqRWrng = False; -Anomaly = False; -if( cmp(Radix,One) != 0 ) - { - printf("Testing whether sqrt is rounded or chopped.\n"); -/*D = FLOOR(Half + POW(Radix, One + Precision - FLOOR(Precision)));*/ - FLOOR( Precision, t2 ); - add( One, Precision, t ); - sub( t2, t, t ); - POW( Radix, t, D ); - add( Half, D, D ); - FLOOR( D, D ); -/* ... == Radix^(1 + fract) if (Precision == Integer + fract. */ - div( Radix, D, X ); - div( A1, D, Y ); - FLOOR( X, t ); - FLOOR( Y, t2 ); - if( (cmp(X,t) != 0) || (cmp(Y,t2) != 0) ) - { - Anomaly = True; - printf( "Anomaly 1\n" ); - } - else - { - mov( Zero, X ); - mov( X, Z2 ); - mov( One, Y ); - mov( Y, Y2 ); - sub( One, Radix, Z1 ); - mul( Four, D, FourD ); - do - { - if( cmp(Y2,Z2) >0 ) - { - mov( Radix, Q ); - mov( Y, YY1 ); - do - { -/*X1 = FABS(Q + FLOOR(Half - Q / YY1) * YY1);*/ - div( YY1, Q, t ); - sub( t, Half, t ); - FLOOR( t, t ); - mul( t, YY1, t ); - add( Q, t, X1 ); - FABS( X1 ); - mov( YY1, Q ); - mov( X1, YY1 ); - } - while( ! (cmp(X1,Zero) <= 0) ); - if( cmp(Q,One) <= 0 ) - { - mov( Y2, Z2 ); - mov( Y, Z ); - } - } - add( Y, Two, Y ); - add( X, Eight, X ); - add( Y2, X, Y2 ); - if( cmp(Y2,FourD) >= 0 ) - sub( FourD, Y2, Y2 ); - } - while( ! (cmp(Y,D) >= 0) ); - sub( Z2, FourD, X8 ); - mul( Z, Z, Q ); - add( X8, Q, Q ); - div( FourD, Q, Q ); - div( Eight, X8, X8 ); - FLOOR( Q, t ); - if( cmp(Q,t) != 0 ) - { - Anomaly = True; - printf( "Anomaly 2\n" ); - } - else - { - Break = False; - do - { - mul( Z1, Z, X ); -/*X = X - FLOOR(X / Radix) * Radix;*/ - div( Radix, X, t ); - FLOOR( t, t ); - mul( t, Radix, t ); - sub( t, X, X ); - if( cmp(X,One) == 0 ) - Break = True; - else - sub( One, Z1, Z1 ); - } - while( ! (Break || (cmp(Z1,Zero) <= 0)) ); - if( (cmp(Z1,Zero) <= 0) && (! Break)) - { - printf( "Anomaly 3\n" ); - Anomaly = True; - } - else - { - if( cmp(Z1,RadixD2) > 0) - sub( Radix, Z1, Z1 ); - do - { - NewD(); - mul( U2, D, t ); - } - while( ! (cmp(t,F9) >= 0) ); - mul( D, Radix, t ); - sub( D, t, t ); - sub( D, W, t2 ); - if (cmp(t,t2) != 0 ) - { - printf( "Anomaly 4\n" ); - Anomaly = True; - } - else - { - mov( D, Z2 ); - I = 0; - add( One, Z, t ); - mul( t, Half, t ); - add( D, t, Y ); - add( D, Z, X ); - add( X, Q, X ); - SR3750(); - sub( Z, One, t ); - mul( t, Half, t ); - add( D, t, Y ); - add( Y, D, Y ); - sub( Z, D, X ); - add( X, D, X ); - add( X, Q, t ); - add( t, X, X ); - SR3750(); - NewD(); - sub( Z2, D, t ); - sub( Z2, W, t2 ); - if(cmp(t,t2) != 0 ) - { - printf( "Anomaly 5\n" ); - Anomaly = True; - } - else - { -/*Y = (D - Z2) + (Z2 + (One - Z) * Half);*/ - sub( Z, One, t ); - mul( t, Half, t ); - add( Z2, t, t ); - sub( Z2, D, Y ); - add( Y, t, Y ); -/*X = (D - Z2) + (Z2 - Z + Q);*/ - sub( Z, Z2, t ); - add( t, Q, t ); - sub( Z2, D, X ); - add( X, t, X ); - SR3750(); - add( One, Z, Y ); - mul( Y, Half, Y ); - mov( Q, X ); - SR3750(); - if(I == 0) - { - printf( "Anomaly 6\n" ); - Anomaly = True; - } - } - } - } - } - } - if ((I == 0) || Anomaly) - { - ErrCnt[Failure] += 1; - printf( "Anomalous arithmetic with Integer < \n"); - printf("Radix^Precision = " ); - show( W ); - printf(" fails test whether sqrt rounds or chops.\n"); - SqRWrng = True; - } - } -if(! Anomaly) - { - if(! ((cmp(MinSqEr,Zero) < 0) || (cmp(MaxSqEr,Zero) > 0))) { - RSqrt = Rounded; - printf("Square root appears to be correctly rounded.\n"); - } - else - { - k = 0; - add( MaxSqEr, U2, t ); - sub( Half, U2, t2 ); - if( cmp(t,t2) > 0 ) - k = 1; - if( cmp( MinSqEr, Half ) > 0 ) - k = 1; - add( MinSqEr, Radix, t ); - if( cmp( t, Half ) < 0 ) - k = 1; - if( k == 1 ) - SqRWrng = True; - else - { - RSqrt = Chopped; - printf("Square root appears to be chopped.\n"); - } - } - } -if( SqRWrng ) - { - printf("Square root is neither chopped nor correctly rounded.\n"); - printf("Observed errors run from " ); - sub( Half, MinSqEr, t ); - show( t ); - printf("\tto " ); - add( Half, MaxSqEr, t ); - show( t ); - printf( "ulps.\n" ); - sub( MinSqEr, MaxSqEr, t ); - mul( Radix, Radix, t2 ); - if( cmp( t, t2 ) >= 0 ) - { - ErrCnt[Serious] += 1; - printf( "sqrt gets too many last digits wrong\n"); - } - } -} - -Showsq( arg ) -int arg; -{ - -k = 0; -if( arg <= 0 ) - { - if( cmp(SqEr,MinSqEr) < 0 ) - { - k = 1; - mov( SqEr, MinSqEr ); - } - } -if( arg >= 0 ) - { - if( cmp(SqEr,MaxSqEr) > 0 ) - { - k = 2; - mov( SqEr, MaxSqEr ); - } - } -#if DEBUG -if( k != 0 ) - { - printf( "Square root of " ); - show( arg ); - printf( "\tis in error by " ); - show( SqEr ); - } -#endif -} - - -pow1test() -{ - -/*=============================================*/ -Milestone = 90; -/*=============================================*/ -Pause(); -printf("Testing powers Z^i for small Integers Z and i.\n"); -N = 0; -/* ... test powers of zero. */ -I = 0; -mov( Zero, Z ); -neg(Z); -M = 3; -Break = False; -do - { - mov( One, X ); - SR3980(); - if(I <= 10) - { - I = 1023; - SR3980(); - } - if( cmp(Z,MinusOne) == 0 ) - Break = True; - else - { - mov( MinusOne, Z ); - PrintIfNPositive(); - N = 0; -/* .. if(-1)^N is invalid, replace MinusOne by One. */ - I = - 4; - } - } -while( ! Break ); -PrintIfNPositive(); -N1 = N; -N = 0; -mov( A1, Z ); -/*M = FLOOR(Two * LOG(W) / LOG(A1));*/ -LOG( W, t ); -mul( Two, t, t ); -FLOOR( t, t ); -LOG( A1, t2 ); -div( t2, t, t ); -FTOL( t, &lngint, t2 ); -M = lngint; -Break = False; -do - { - mov( Z, X ); - I = 1; - SR3980(); - if( cmp(Z,AInvrse) == 0 ) - Break = True; - else - mov( AInvrse, Z ); - } -while( ! (Break) ); -/*=============================================*/ -Milestone = 100; -/*=============================================*/ -/* Powers of Radix have been tested, */ -/* next try a few primes */ - -M = NoTrials; - -mov( Three, Z ); -do - { - mov( Z, X ); - I = 1; - SR3980(); - do - { - add( Z, Two, Z ); - div( Three, Z, t ); - FLOOR( t, t ); - mul( Three, t, t ); - } - while( cmp(t,Z) == 0 ); - mul( Eight, Three, t ); - } -while( cmp(Z,t) < 0 ); - -if(N > 0) - { - printf("Errors like this may invalidate financial calculations\n"); - printf("\tinvolving interest rates.\n"); - } -PrintIfNPositive(); -N += N1; -if(N == 0) - printf("... no discrepancies found.\n"); -if(N > 0) - Pause(); -else printf("\n"); -} - - - -pow2test() -{ -printf("\n"); -/* ...calculate Exp2 == exp(2) == 7.38905 60989 30650 22723 04275-... */ -mov( Zero, X ); -mov( Two, t2 ); /*I = 2;*/ - -mul( Two, Three, Y ); -mov( Zero, Q ); -N = 0; -do - { - mov( X, Z ); - add( t2, One, t2 ); /*I = I + 1;*/ - add( t2, t2, t ); - div( t, Y, Y ); /*Y = Y / (I + I);*/ - add( Y, Q, R ); - add( Z, R, X ); - sub( X, Z, Q ); - add( Q, R, Q ); - } -while( cmp(X,Z) > 0 ); - -/*Z = (OneAndHalf + One / Eight) + X / (OneAndHalf * ThirtyTwo);*/ -div( Eight, One, t ); -add( OneAndHalf, t, Z ); -mul( OneAndHalf, ThirtyTwo, t ); -div( t, X, t ); -add( Z, t, Z ); -mul( Z, Z, X ); -mul( X, X, Exp2 ); -mov( F9, X ); -sub( U1, X, Y ); -printf("Testing X^((X + 1) / (X - 1)) vs. exp(2) = " ); -show( Exp2 ); -printf( "\tas X -> 1.\n" ); -for(I = 1;;) - { - sub( BInvrse, X, Z ); -/*Z = (X + One) / (Z - (One - BInvrse));*/ - add( X, One, t2 ); - sub( BInvrse, One, t ); - sub( t, Z, t ); - div( t, t2, Z ); - POW( X, Z, Sqarg ); - sub( Exp2, Sqarg, Q ); - mov( Q, t ); - FABS( t ); - mul( TwoForty, U2, t2 ); - if( cmp( t, t2 ) > 0 ) - { - N = 1; - sub( BInvrse, X, V9 ); - sub( BInvrse, One, t ); - sub( t, V9, V9 ); - ErrCnt[Defect] += 1; - printf( "Calculated " ); - show( Sqarg ); - printf(" for \t(1 + " ); - show( V9 ); - printf( "\tto the power " ); - show( Z ); - printf("\tdiffers from correct value by " ); - show( Q ); - printf("\tThis much error may spoil financial\n"); - printf("\tcalculations involving tiny interest rates.\n"); - break; - } - else - { - sub( X, Y, Z ); - mul( Z, Two, Z ); - add( Z, Y, Z ); - mov( Y, X ); - mov( Z, Y ); - sub( F9, X, Z ); - mul( Z, Z, Z ); - add( Z, One, Z ); - if( (cmp(Z,One) > 0) && (I < NoTrials) ) - I++; - else - { - if( cmp(X,One) > 0 ) - { - if(N == 0) - printf("Accuracy seems adequate.\n"); - break; - } - else - { - add( One, U2, X ); - add( U2, U2, Y ); - add( X, Y, Y ); - I = 1; - } - } - } - } -/*=============================================*/ -Milestone = 150; -/*=============================================*/ -printf("Testing powers Z^Q at four nearly extreme values.\n"); -N = 0; -mov( A1, Z ); -/*Q = FLOOR(Half - LOG(C) / LOG(A1));*/ -LOG( C, t ); -LOG( A1, t2 ); -div( t2, t, t ); -sub( t, Half, t ); -FLOOR( t, Q ); -Break = False; -do - { - mov( CInvrse, X ); - POW( Z, Q, Y ); - IsYeqX(); - neg(Q); - mov( C, X ); - POW( Z, Q, Y ); - IsYeqX(); - if( cmp(Z,One) < 0 ) - Break = True; - else - mov( AInvrse, Z ); - } -while( ! (Break)); -PrintIfNPositive(); -if(N == 0) - printf(" ... no discrepancies found.\n"); -printf("\n"); -} diff --git a/test/math/epow.c b/test/math/epow.c deleted file mode 100644 index d756eaee0..000000000 --- a/test/math/epow.c +++ /dev/null @@ -1,215 +0,0 @@ -/* epow.c */ -/* power function: z = x**y */ -/* by Stephen L. Moshier. */ - - -#include "ehead.h" -#define MAXPOS ((long) (((unsigned long) ~(0L)) >> 1)) -#define MAXNEG (-MAXPOS) -/* #define MAXNEG (-MAXPOS - 1L) */ - -extern int rndprc; -void epowi(); -static void epowr(); - - -/* Run-time determination of largest integers */ - -int powinited = 0; -unsigned short maxposint[NE], maxnegint[NE]; - -void initpow() -{ -long li; - -li = MAXPOS; -ltoe( &li, maxposint ); -li = MAXNEG; -ltoe( &li, maxnegint ); -powinited = 1; -} - - - - -void epow( x, y, z ) -unsigned short *x, *y, *z; -{ -unsigned short w[NE]; -int rndsav; -long li; - -if( powinited == 0 ) - initpow(); - -/* Check for integer power. */ - -efloor( y, w ); -if( (ecmp(y,w) == 0) - && (ecmp(maxposint,w) >= 0) - && (ecmp(w,maxnegint) >= 0) ) - { - eifrac( y, &li, w ); - epowi( x, y, z ); - return; - } -epowr( x, y, z ); -} - - - - -/* y is integer valued. */ - -void epowi( x, y, z ) -unsigned short x[], y[], z[]; -{ -unsigned short w[NE]; -long li, lx; -unsigned long lu; -int rndsav; -unsigned short signx; -/* unsigned short signy; */ - -if( powinited == 0 ) - initpow(); - -rndsav = rndprc; - -if( (ecmp(y,maxposint) > 0) || (ecmp(maxnegint,y) > 0) ) - { - epowr( x, y, z ); - return; - } - -eifrac( y, &li, w ); -if( li < 0 ) - lx = -li; -else - lx = li; - -/* -if( (x[NE-1] & (unsigned short )0x7fff) == 0 ) -*/ - -if( ecmp( x, ezero) == 0 ) - { - if( li == 0 ) - { - emov( eone, z ); - return; - } - else if( li < 0 ) - { - einfin( z ); - return; - } - else - { - eclear( z ); - return; - } - } - -if( li == 0L ) - { - emov( eone, z ); - return; - } - -emov( x, w ); -signx = w[NE-1] & (unsigned short )0x8000; -w[NE-1] &= (unsigned short )0x7fff; - -/* Overflow detection */ -/* -lx = li * (w[NE-1] - 0x3fff); -if( lx > 16385L ) - { - einfin( z ); - mtherr( "epowi", OVERFLOW ); - goto done; - } -if( lx < -16450L ) - { - eclear( z ); - return; - } -*/ -rndprc = NBITS; - -if( li < 0 ) - { - lu = (unsigned int )( -li ); -/* signy = 0xffff;*/ - ediv( w, eone, w ); - } -else - { - lu = (unsigned int )li; -/* signy = 0;*/ - } - -/* First bit of the power */ -if( lu & 1 ) - { - emov( w, z ); - } -else - { - emov( eone, z ); - signx = 0; - } - - -lu >>= 1; -while( lu != 0L ) - { - emul( w, w, w ); /* arg to the 2-to-the-kth power */ - if( lu & 1L ) /* if that bit is set, then include in product */ - emul( w, z, z ); - lu >>= 1; - } - - -done: - -if( signx ) - eneg( z ); /* odd power of negative number */ - -/* -if( signy ) - { - if( ecmp( z, ezero ) != 0 ) - { - ediv( z, eone, z ); - } - else - { - einfin( z ); - printf( "epowi OVERFLOW\n" ); - } - } -*/ -rndprc = rndsav; -emul( eone, z, z ); -} - - - -/* z = exp( y * log(x) ) */ - -static void epowr( x, y, z ) -unsigned short *x, *y, *z; -{ -unsigned short w[NE]; -int rndsav; - -rndsav = rndprc; -rndprc = NBITS; -elog( x, w ); -emul( y, w, w ); -eexp( w, z ); -rndprc = rndsav; -emul( eone, z, z ); -} diff --git a/test/math/etanh.c b/test/math/etanh.c deleted file mode 100644 index 8014c6d93..000000000 --- a/test/math/etanh.c +++ /dev/null @@ -1,52 +0,0 @@ -/* xtanh.c */ -/* hyperbolic tangent check routine */ -/* this subroutine is used by the exponential function routine */ -/* by Stephen L. Moshier. */ - - - -#include "ehead.h" - - -void etanh( x, y ) -unsigned short *x, *y; -{ -unsigned short e[NE], r[NE], j[NE], xx[NE], m2[NE]; -short i, n; -long lj; - -emov( x, r ); -r[NE-1] &= (unsigned short )0x7fff; -if( ecmp(r, eone) >= 0 ) - { -/* tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x)) - * Note eexp() calls xtanh, but with an argument less than (1 + log 2)/2. - */ - eexp( r, e ); - ediv( e, eone, r ); - esub( r, e, xx ); - eadd( r, e, j ); - ediv( j, xx, y ); - return; - } - -emov( etwo, m2 ); -eneg( m2 ); - -n = NBITS/8; /* Number of terms to do in the continued fraction */ -lj = 2 * n + 1; -ltoe( &lj, j ); - -emov( j, e ); -emul( x, x, xx ); - -/* continued fraction */ -for( i=0; i<n; i++) - { - ediv( e, xx, r ); - eadd( m2, j, j ); - eadd( r, j, e ); - } - -ediv( e, x, y ); -} diff --git a/test/math/etodec.c b/test/math/etodec.c deleted file mode 100644 index 22545d6fb..000000000 --- a/test/math/etodec.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "ehead.h" -void emovi(), emovo(), ecleaz(), eshdn8(), emdnorm(); -void todec(); -/* -; convert DEC double precision to e type -; double d; -; short e[NE]; -; dectoe( &d, e ); -*/ -void dectoe( d, e ) -unsigned short *d; -unsigned short *e; -{ -unsigned short y[NI]; -register unsigned short r, *p; - -ecleaz(y); /* start with a zero */ -p = y; /* point to our number */ -r = *d; /* get DEC exponent word */ -if( *d & (unsigned int )0x8000 ) - *p = 0xffff; /* fill in our sign */ -++p; /* bump pointer to our exponent word */ -r &= 0x7fff; /* strip the sign bit */ -if( r == 0 ) /* answer = 0 if high order DEC word = 0 */ - goto done; - - -r >>= 7; /* shift exponent word down 7 bits */ -r += EXONE - 0201; /* subtract DEC exponent offset */ - /* add our e type exponent offset */ -*p++ = r; /* to form our exponent */ - -r = *d++; /* now do the high order mantissa */ -r &= 0177; /* strip off the DEC exponent and sign bits */ -r |= 0200; /* the DEC understood high order mantissa bit */ -*p++ = r; /* put result in our high guard word */ - -*p++ = *d++; /* fill in the rest of our mantissa */ -*p++ = *d++; -*p = *d; - -eshdn8(y); /* shift our mantissa down 8 bits */ -done: -emovo( y, e ); -} - - - -/* -; convert e type to DEC double precision -; double d; -; short e[NE]; -; etodec( e, &d ); -*/ -#if 0 -static unsigned short decbit[NI] = {0,0,0,0,0,0,0200,0}; -void etodec( x, d ) -unsigned short *x, *d; -{ -unsigned short xi[NI]; -register unsigned short r; -int i, j; - -emovi( x, xi ); -*d = 0; -if( xi[0] != 0 ) - *d = 0100000; -r = xi[E]; -if( r < (EXONE - 128) ) - goto zout; -i = xi[M+4]; -if( (i & 0200) != 0 ) - { - if( (i & 0377) == 0200 ) - { - if( (i & 0400) != 0 ) - { - /* check all less significant bits */ - for( j=M+5; j<NI; j++ ) - { - if( xi[j] != 0 ) - goto yesrnd; - } - } - goto nornd; - } -yesrnd: - eaddm( decbit, xi ); - r -= enormlz(xi); - } - -nornd: - -r -= EXONE; -r += 0201; -if( r < 0 ) - { -zout: - *d++ = 0; - *d++ = 0; - *d++ = 0; - *d++ = 0; - return; - } -if( r >= 0377 ) - { - *d++ = 077777; - *d++ = -1; - *d++ = -1; - *d++ = -1; - return; - } -r &= 0377; -r <<= 7; -eshup8( xi ); -xi[M] &= 0177; -r |= xi[M]; -*d++ |= r; -*d++ = xi[M+1]; -*d++ = xi[M+2]; -*d++ = xi[M+3]; -} -#else - -extern int rndprc; - -void etodec( x, d ) -unsigned short *x, *d; -{ -unsigned short xi[NI]; -long exp; -int rndsav; - -emovi( x, xi ); -exp = (long )xi[E] - (EXONE - 0201); /* adjust exponent for offsets */ -/* round off to nearest or even */ -rndsav = rndprc; -rndprc = 56; -emdnorm( xi, 0, 0, exp, 64 ); -rndprc = rndsav; -todec( xi, d ); -} - -void todec( x, y ) -unsigned short *x, *y; -{ -unsigned short i; -unsigned short *p; - -p = x; -*y = 0; -if( *p++ ) - *y = 0100000; -i = *p++; -if( i == 0 ) - { - *y++ = 0; - *y++ = 0; - *y++ = 0; - *y++ = 0; - return; - } -if( i > 0377 ) - { - *y++ |= 077777; - *y++ = 0xffff; - *y++ = 0xffff; - *y++ = 0xffff; - return; - } -i &= 0377; -i <<= 7; -eshup8( x ); -x[M] &= 0177; -i |= x[M]; -*y++ |= i; -*y++ = x[M+1]; -*y++ = x[M+2]; -*y++ = x[M+3]; -} -#endif diff --git a/test/math/gen-libm-test.pl b/test/math/gen-libm-test.pl new file mode 100755 index 000000000..26f819a88 --- /dev/null +++ b/test/math/gen-libm-test.pl @@ -0,0 +1,738 @@ +#!/usr/bin/perl -w +# Copyright (C) 1999 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# Contributed by Andreas Jaeger <aj@suse.de>, 1999. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +# This file needs to be tidied up +# Note that functions and tests share the same namespace. + +# Information about tests are stored in: %results +# $results{$test}{"kind"} is either "fct" or "test" and flags whether this +# is a maximal error of a function or a single test. +# $results{$test}{"type"} is the result type, e.g. normal or complex. +# $results{$test}{"has_ulps"} is set if deltas exist. +# $results{$test}{"has_fails"} is set if exptected failures exist. +# In the following description $type and $float are: +# - $type is either "normal", "real" (for the real part of a complex number) +# or "imag" (for the imaginary part # of a complex number). +# - $float is either of float, ifloat, double, idouble, ldouble, ildouble; +# It represents the underlying floating point type (float, double or long +# double) and if inline functions (the leading i stands for inline) +# are used. +# $results{$test}{$type}{"fail"}{$float} is defined and has a 1 if +# the test is expected to fail +# $results{$test}{$type}{"ulp"}{$float} is defined and has a delta as value + + +use Getopt::Std; + +use strict; + +use vars qw ($input $output); +use vars qw (%results); +use vars qw (@tests @functions); +use vars qw ($count); +use vars qw (%beautify @all_floats); +use vars qw ($output_dir $ulps_file); + +# all_floats is sorted and contains all recognised float types +@all_floats = ('double', 'float', 'idouble', + 'ifloat', 'ildouble', 'ldouble'); + +%beautify = + ( "minus_zero" => "-0", + "plus_zero" => "+0", + "minus_infty" => "-inf", + "plus_infty" => "inf", + "nan_value" => "NaN", + "M_El" => "e", + "M_E2l" => "e^2", + "M_E3l" => "e^3", + "M_LOG10El", "log10(e)", + "M_PIl" => "pi", + "M_PI_34l" => "3/4 pi", + "M_PI_2l" => "pi/2", + "M_PI_4l" => "pi/4", + "M_PI_6l" => "pi/6", + "M_PI_34_LOG10El" => "3/4 pi*log10(e)", + "M_PI_LOG10El" => "pi*log10(e)", + "M_PI2_LOG10El" => "pi/2*log10(e)", + "M_PI4_LOG10El" => "pi/4*log10(e)", + "M_LOG_SQRT_PIl" => "log(sqrt(pi))", + "M_LOG_2_SQRT_PIl" => "log(2*sqrt(pi))", + "M_2_SQRT_PIl" => "2 sqrt (pi)", + "M_SQRT_PIl" => "sqrt (pi)", + "INVALID_EXCEPTION" => "invalid exception", + "DIVIDE_BY_ZERO_EXCEPTION" => "division by zero exception", + "INVALID_EXCEPTION_OK" => "invalid exception allowed", + "DIVIDE_BY_ZERO_EXCEPTION_OK" => "division by zero exception allowed", + "EXCEPTIONS_OK" => "exceptions allowed", + "IGNORE_ZERO_INF_SIGN" => "sign of zero/inf not specified", +"INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN" => "invalid exception and sign of zero/inf not specified" + ); + + +# get Options +# Options: +# u: ulps-file +# h: help +# o: output-directory +# n: generate new ulps file +use vars qw($opt_u $opt_h $opt_o $opt_n); +getopts('u:o:nh'); + +$ulps_file = 'libm-test-ulps'; +$output_dir = ''; + +if ($opt_h) { + print "Usage: gen-libm-test.pl [OPTIONS]\n"; + print " -h print this help, then exit\n"; + print " -o DIR directory where generated files will be placed\n"; + print " -n only generate sorted file NewUlps from libm-test-ulps\n"; + print " -u FILE input file with ulps\n"; + exit 0; +} + +$ulps_file = $opt_u if ($opt_u); +$output_dir = $opt_o if ($opt_o); + +$input = "libm-test.inc"; +$output = "${output_dir}libm-test.c"; + +$count = 0; + +&parse_ulps ($ulps_file); +&generate_testfile ($input, $output) unless ($opt_n); +&output_ulps ("${output_dir}libm-test-ulps.h", $ulps_file) unless ($opt_n); +&print_ulps_file ("${output_dir}NewUlps") if ($opt_n); + +# Return a nicer representation +sub beautify { + my ($arg) = @_; + my ($tmp); + + if (exists $beautify{$arg}) { + return $beautify{$arg}; + } + if ($arg =~ /^-/) { + $tmp = $arg; + $tmp =~ s/^-//; + if (exists $beautify{$tmp}) { + return '-' . $beautify{$tmp}; + } + } + if ($arg =~ /[0-9]L$/) { + $arg =~ s/L$//; + } + return $arg; +} + +# Return a nicer representation of a complex number +sub build_complex_beautify { + my ($r, $i) = @_; + my ($str1, $str2); + + $str1 = &beautify ($r); + $str2 = &beautify ($i); + if ($str2 =~ /^-/) { + $str2 =~ s/^-//; + $str1 .= ' - ' . $str2; + } else { + $str1 .= ' + ' . $str2; + } + $str1 .= ' i'; + return $str1; +} + +# Return name of a variable +sub get_variable { + my ($number) = @_; + + return "x" if ($number == 1); + return "y" if ($number == 2); + return "z" if ($number == 3); + # return x1,x2,... + $number =-3; + return "x$number"; +} + +# Add a new test to internal data structures and fill in the +# ulps, failures and exception information for the C line. +sub new_test { + my ($test, $exception) = @_; + my $rest; + + # Add ulp, xfail + if (exists $results{$test}{'has_ulps'}) { + $rest = ", DELTA$count"; + } else { + $rest = ', 0'; + } + if (exists $results{$test}{'has_fails'}) { + $rest .= ", FAIL$count"; + } else { + $rest .= ', 0'; + } + if (defined $exception) { + $rest .= ", $exception"; + } else { + $rest .= ', 0'; + } + $rest .= ");\n"; + # We must increment here to keep @tests and count in sync + push @tests, $test; + ++$count; + return $rest; +} + +# Treat some functions especially. +# Currently only sincos needs extra treatment. +sub special_functions { + my ($file, $args) = @_; + my (@args, $str, $test, $cline); + + @args = split /,\s*/, $args; + + unless ($args[0] =~ /sincos/) { + die ("Don't know how to handle $args[0] extra."); + } + print $file " FUNC (sincos) ($args[1], &sin_res, &cos_res);\n"; + + $str = 'sincos (' . &beautify ($args[1]) . ', &sin_res, &cos_res)'; + # handle sin + $test = $str . ' puts ' . &beautify ($args[2]) . ' in sin_res'; + if ($#args == 4) { + $test .= " plus " . &beautify ($args[4]); + } + + $cline = " check_float (\"$test\", sin_res, $args[2]"; + $cline .= &new_test ($test, $args[4]); + print $file $cline; + + # handle cos + $test = $str . ' puts ' . &beautify ($args[3]) . ' in cos_res'; + $cline = " check_float (\"$test\", cos_res, $args[3]"; + # only tests once for exception + $cline .= &new_test ($test, undef); + print $file $cline; +} + +# Parse the arguments to TEST_x_y +sub parse_args { + my ($file, $descr, $args) = @_; + my (@args, $str, $descr_args, $descr_res, @descr); + my ($current_arg, $cline, $i); + my ($pre, $post, @special); + my ($extra_var, $call, $c_call); + + if ($descr eq 'extra') { + &special_functions ($file, $args); + return; + } + ($descr_args, $descr_res) = split /_/,$descr, 2; + + @args = split /,\s*/, $args; + + $call = "$args[0] ("; + + # Generate first the string that's shown to the user + $current_arg = 1; + $extra_var = 0; + @descr = split //,$descr_args; + for ($i = 0; $i <= $#descr; $i++) { + if ($i >= 1) { + $call .= ', '; + } + # FLOAT, int, long int, long long int + if ($descr[$i] =~ /f|i|l|L/) { + $call .= &beautify ($args[$current_arg]); + ++$current_arg; + next; + } + # &FLOAT, &int - argument is added here + if ($descr[$i] =~ /F|I/) { + ++$extra_var; + $call .= '&' . &get_variable ($extra_var); + next; + } + # complex + if ($descr[$i] eq 'c') { + $call .= &build_complex_beautify ($args[$current_arg], $args[$current_arg+1]); + $current_arg += 2; + next; + } + + die ("$descr[$i] is unknown"); + } + $call .= ')'; + $str = "$call == "; + + # Result + @descr = split //,$descr_res; + foreach (@descr) { + if ($_ =~ /f|i|l|L/) { + $str .= &beautify ($args[$current_arg]); + ++$current_arg; + } elsif ($_ eq 'c') { + $str .= &build_complex_beautify ($args[$current_arg], $args[$current_arg+1]); + $current_arg += 2; + } elsif ($_ eq 'b') { + # boolean + $str .= ($args[$current_arg] == 0) ? "false" : "true"; + ++$current_arg; + } elsif ($_ eq '1') { + ++$current_arg; + } else { + die ("$_ is unknown"); + } + } + # consistency check + if ($current_arg == $#args) { + die ("wrong number of arguments") + unless ($args[$current_arg] =~ /EXCEPTION|IGNORE_ZERO_INF_SIGN/); + } elsif ($current_arg < $#args) { + die ("wrong number of arguments"); + } elsif ($current_arg > ($#args+1)) { + die ("wrong number of arguments"); + } + + + # check for exceptions + if ($current_arg <= $#args) { + $str .= " plus " . &beautify ($args[$current_arg]); + } + + # Put the C program line together + # Reset some variables to start again + $current_arg = 1; + $extra_var = 0; + if (substr($descr_res,0,1) eq 'f') { + $cline = 'check_float' + } elsif (substr($descr_res,0,1) eq 'b') { + $cline = 'check_bool'; + } elsif (substr($descr_res,0,1) eq 'c') { + $cline = 'check_complex'; + } elsif (substr($descr_res,0,1) eq 'i') { + $cline = 'check_int'; + } elsif (substr($descr_res,0,1) eq 'l') { + $cline = 'check_long'; + } elsif (substr($descr_res,0,1) eq 'L') { + $cline = 'check_longlong'; + } + # Special handling for some macros: + $cline .= " (\"$str\", "; + if ($args[0] =~ /fpclassify|isnormal|isfinite|signbit/) { + $c_call = "$args[0] ("; + } else { + $c_call = " FUNC($args[0]) ("; + } + @descr = split //,$descr_args; + for ($i=0; $i <= $#descr; $i++) { + if ($i >= 1) { + $c_call .= ', '; + } + # FLOAT, int, long int, long long int + if ($descr[$i] =~ /f|i|l|L/) { + $c_call .= $args[$current_arg]; + $current_arg++; + next; + } + # &FLOAT, &int + if ($descr[$i] =~ /F|I/) { + ++$extra_var; + $c_call .= '&' . &get_variable ($extra_var); + next; + } + # complex + if ($descr[$i] eq 'c') { + $c_call .= "BUILD_COMPLEX ($args[$current_arg], $args[$current_arg+1])"; + $current_arg += 2; + next; + } + } + $c_call .= ')'; + $cline .= "$c_call, "; + + @descr = split //,$descr_res; + foreach (@descr) { + if ($_ =~ /b|f|i|l|L/ ) { + $cline .= $args[$current_arg]; + $current_arg++; + } elsif ($_ eq 'c') { + $cline .= "BUILD_COMPLEX ($args[$current_arg], $args[$current_arg+1])"; + $current_arg += 2; + } elsif ($_ eq '1') { + push @special, $args[$current_arg]; + ++$current_arg; + } + } + # Add ulp, xfail + $cline .= &new_test ($str, ($current_arg <= $#args) ? $args[$current_arg] : undef); + + # special treatment for some functions + if ($args[0] eq 'frexp') { + if (defined $special[0] && $special[0] ne "IGNORE") { + my ($str) = "$call sets x to $special[0]"; + $post = " check_int (\"$str\", x, $special[0]"; + $post .= &new_test ($str, undef); + } + } elsif ($args[0] eq 'gamma' || $args[0] eq 'lgamma') { + $pre = " signgam = 0;\n"; + if (defined $special[0] && $special[0] ne "IGNORE") { + my ($str) = "$call sets signgam to $special[0]"; + $post = " check_int (\"$str\", signgam, $special[0]"; + $post .= &new_test ($str, undef); + } + } elsif ($args[0] eq 'modf') { + if (defined $special[0] && $special[0] ne "IGNORE") { + my ($str) = "$call sets x to $special[0]"; + $post = " check_float (\"$str\", x, $special[0]"; + $post .= &new_test ($str, undef); + } + } elsif ($args[0] eq 'remquo') { + if (defined $special[0] && $special[0] ne "IGNORE") { + my ($str) = "$call sets x to $special[0]"; + $post = " check_int (\"$str\", x, $special[0]"; + $post .= &new_test ($str, undef); + } + } + + print $file $pre if (defined $pre); + + print $file " $cline"; + + print $file $post if (defined $post); +} + +# Generate libm-test.c +sub generate_testfile { + my ($input, $output) = @_; + my ($lasttext); + my (@args, $i, $str); + + open INPUT, $input or die ("Can't open $input: $!"); + open OUTPUT, ">$output" or die ("Can't open $output: $!"); + + # Replace the special macros + while (<INPUT>) { + + # TEST_... + if (/^\s*TEST_/) { + my ($descr, $args); + chop; + ($descr, $args) = ($_ =~ /TEST_(\w+)\s*\((.*)\)/); + &parse_args (\*OUTPUT, $descr, $args); + next; + } + # START (function) + if (/START/) { + print OUTPUT " init_max_error ();\n"; + next; + } + # END (function) + if (/END/) { + my ($fct, $line, $type); + if (/complex/) { + s/,\s*complex\s*//; + $type = 'complex'; + } else { + $type = 'normal'; + } + ($fct) = ($_ =~ /END\s*\((.*)\)/); + if ($type eq 'complex') { + $line = " print_complex_max_error (\"$fct\", "; + } else { + $line = " print_max_error (\"$fct\", "; + } + if (exists $results{$fct}{'has_ulps'}) { + $line .= "DELTA$fct"; + } else { + $line .= '0'; + } + if (exists $results{$fct}{'has_fails'}) { + $line .= ", FAIL$fct"; + } else { + $line .= ', 0'; + } + $line .= ");\n"; + print OUTPUT $line; + push @functions, $fct; + next; + } + print OUTPUT; + } + close INPUT; + close OUTPUT; +} + + + +# Parse ulps file +sub parse_ulps { + my ($file) = @_; + my ($test, $type, $float, $eps, $kind); + + # $type has the following values: + # "normal": No complex variable + # "real": Real part of complex result + # "imag": Imaginary part of complex result + open ULP, $file or die ("Can't open $file: $!"); + while (<ULP>) { + chop; + # ignore comments and empty lines + next if /^#/; + next if /^\s*$/; + if (/^Test/) { + if (/Real part of:/) { + s/Real part of: //; + $type = 'real'; + } elsif (/Imaginary part of:/) { + s/Imaginary part of: //; + $type = 'imag'; + } else { + $type = 'normal'; + } + s/^.+\"(.*)\".*$/$1/; + $test = $_; + $kind = 'test'; + next; + } + if (/^Function: /) { + if (/Real part of/) { + s/Real part of //; + $type = 'real'; + } elsif (/Imaginary part of/) { + s/Imaginary part of //; + $type = 'imag'; + } else { + $type = 'normal'; + } + ($test) = ($_ =~ /^Function:\s*\"([a-zA-Z0-9_]+)\"/); + $kind = 'fct'; + next; + } + if (/^i?(float|double|ldouble):/) { + ($float, $eps) = split /\s*:\s*/,$_,2; + + if ($eps eq 'fail') { + $results{$test}{$type}{'fail'}{$float} = 1; + $results{$test}{'has_fails'} = 1; + } elsif ($eps eq "0") { + # ignore + next; + } else { + $results{$test}{$type}{'ulp'}{$float} = $eps; + $results{$test}{'has_ulps'} = 1; + } + if ($type =~ /^real|imag$/) { + $results{$test}{'type'} = 'complex'; + } elsif ($type eq 'normal') { + $results{$test}{'type'} = 'normal'; + } + $results{$test}{'kind'} = $kind; + next; + } + print "Skipping unknown entry: `$_'\n"; + } + close ULP; +} + + +# Clean up a floating point number +sub clean_up_number { + my ($number) = @_; + + # Remove trailing zeros + $number =~ s/0+$//; + $number =~ s/\.$//; + return $number; +} + +# Output a file which can be read in as ulps file. +sub print_ulps_file { + my ($file) = @_; + my ($test, $type, $float, $eps, $fct, $last_fct); + + $last_fct = ''; + open NEWULP, ">$file" or die ("Can't open $file: $!"); + print NEWULP "# Begin of automatic generation\n"; + # first the function calls + foreach $test (sort keys %results) { + next if ($results{$test}{'kind'} ne 'test'); + foreach $type ('real', 'imag', 'normal') { + if (exists $results{$test}{$type}) { + if (defined $results{$test}) { + ($fct) = ($test =~ /^(\w+)\s/); + if ($fct ne $last_fct) { + $last_fct = $fct; + print NEWULP "\n# $fct\n"; + } + } + if ($type eq 'normal') { + print NEWULP "Test \"$test\":\n"; + } elsif ($type eq 'real') { + print NEWULP "Test \"Real part of: $test\":\n"; + } elsif ($type eq 'imag') { + print NEWULP "Test \"Imaginary part of: $test\":\n"; + } + foreach $float (@all_floats) { + if (exists $results{$test}{$type}{'ulp'}{$float}) { + print NEWULP "$float: ", + &clean_up_number ($results{$test}{$type}{'ulp'}{$float}), + "\n"; + } + if (exists $results{$test}{$type}{'fail'}{$float}) { + print NEWULP "$float: fail\n"; + } + } + } + } + } + print NEWULP "\n# Maximal error of functions:\n"; + + foreach $fct (sort keys %results) { + next if ($results{$fct}{'kind'} ne 'fct'); + foreach $type ('real', 'imag', 'normal') { + if (exists $results{$fct}{$type}) { + if ($type eq 'normal') { + print NEWULP "Function: \"$fct\":\n"; + } elsif ($type eq 'real') { + print NEWULP "Function: Real part of \"$fct\":\n"; + } elsif ($type eq 'imag') { + print NEWULP "Function: Imaginary part of \"$fct\":\n"; + } + foreach $float (@all_floats) { + if (exists $results{$fct}{$type}{'ulp'}{$float}) { + print NEWULP "$float: ", + &clean_up_number ($results{$fct}{$type}{'ulp'}{$float}), + "\n"; + } + if (exists $results{$fct}{$type}{'fail'}{$float}) { + print NEWULP "$float: fail\n"; + } + } + print NEWULP "\n"; + } + } + } + print NEWULP "# end of automatic generation\n"; + close NEWULP; +} + +sub get_ulps { + my ($test, $type, $float) = @_; + + if ($type eq 'complex') { + my ($res); + # Return 0 instead of BUILD_COMPLEX (0,0) + if (!exists $results{$test}{'real'}{'ulp'}{$float} && + !exists $results{$test}{'imag'}{'ulp'}{$float}) { + return "0"; + } + $res = 'BUILD_COMPLEX ('; + $res .= (exists $results{$test}{'real'}{'ulp'}{$float} + ? $results{$test}{'real'}{'ulp'}{$float} : "0"); + $res .= ', '; + $res .= (exists $results{$test}{'imag'}{'ulp'}{$float} + ? $results{$test}{'imag'}{'ulp'}{$float} : "0"); + $res .= ')'; + return $res; + } + return (exists $results{$test}{'normal'}{'ulp'}{$float} + ? $results{$test}{'normal'}{'ulp'}{$float} : "0"); +} + +sub get_failure { + my ($test, $type, $float) = @_; + if ($type eq 'complex') { + # return x,y + my ($res); + # Return 0 instead of BUILD_COMPLEX_INT (0,0) + if (!exists $results{$test}{'real'}{'ulp'}{$float} && + !exists $results{$test}{'imag'}{'ulp'}{$float}) { + return "0"; + } + $res = 'BUILD_COMPLEX_INT ('; + $res .= (exists $results{$test}{'real'}{'fail'}{$float} + ? $results{$test}{'real'}{'fail'}{$float} : "0"); + $res .= ', '; + $res .= (exists $results{$test}{'imag'}{'fail'}{$float} + ? $results{$test}{'imag'}{'fail'}{$float} : "0"); + $res .= ')'; + return $res; + } + return (exists $results{$test}{'normal'}{'fail'}{$float} + ? $results{$test}{'normal'}{'fail'}{$float} : "0"); + +} + +# Output the defines for a single test +sub output_test { + my ($file, $test, $name) = @_; + my ($ldouble, $double, $float, $ildouble, $idouble, $ifloat); + my ($type); + + # Do we have ulps/failures? + if (!exists $results{$test}{'type'}) { + return; + } + $type = $results{$test}{'type'}; + if (exists $results{$test}{'has_ulps'}) { + # XXX use all_floats (change order!) + $ldouble = &get_ulps ($test, $type, "ldouble"); + $double = &get_ulps ($test, $type, "double"); + $float = &get_ulps ($test, $type, "float"); + $ildouble = &get_ulps ($test, $type, "ildouble"); + $idouble = &get_ulps ($test, $type, "idouble"); + $ifloat = &get_ulps ($test, $type, "ifloat"); + print $file "#define DELTA$name CHOOSE($ldouble, $double, $float, $ildouble, $idouble, $ifloat)\t/* $test */\n"; + } + + if (exists $results{$test}{'has_fails'}) { + $ldouble = &get_failure ($test, "ldouble"); + $double = &get_failure ($test, "double"); + $float = &get_failure ($test, "float"); + $ildouble = &get_failure ($test, "ildouble"); + $idouble = &get_failure ($test, "idouble"); + $ifloat = &get_failure ($test, "ifloat"); + print $file "#define FAIL$name CHOOSE($ldouble, $double, $float $ildouble, $idouble, $ifloat)\t/* $test */\n"; + } +} + +# Print include file +sub output_ulps { + my ($file, $ulps_filename) = @_; + my ($i, $fct); + + open ULP, ">$file" or die ("Can't open $file: $!"); + + print ULP "/* This file is automatically generated\n"; + print ULP " from $ulps_filename with gen-libm-test.pl.\n"; + print ULP " Don't change it - change instead the master files. */\n\n"; + + print ULP "\n/* Maximal error of functions. */\n"; + foreach $fct (@functions) { + output_test (\*ULP, $fct, $fct); + } + + print ULP "\n/* Error of single function calls. */\n"; + for ($i = 0; $i < $count; $i++) { + output_test (\*ULP, $tests[$i], $i); + } + close ULP; +} diff --git a/test/math/ieee.c b/test/math/ieee.c deleted file mode 100644 index 17efea01c..000000000 --- a/test/math/ieee.c +++ /dev/null @@ -1,4119 +0,0 @@ -/* ieee.c - * - * Extended precision IEEE binary floating point arithmetic routines - * - * Numbers are stored in C language as arrays of 16-bit unsigned - * short integers. The arguments of the routines are pointers to - * the arrays. - * - * - * External e type data structure, simulates Intel 8087 chip - * temporary real format but possibly with a larger significand: - * - * NE-1 significand words (least significant word first, - * most significant bit is normally set) - * exponent (value = EXONE for 1.0, - * top bit is the sign) - * - * - * Internal data structure of a number (a "word" is 16 bits): - * - * ei[0] sign word (0 for positive, 0xffff for negative) - * ei[1] biased exponent (value = EXONE for the number 1.0) - * ei[2] high guard word (always zero after normalization) - * ei[3] - * to ei[NI-2] significand (NI-4 significand words, - * most significant word first, - * most significant bit is set) - * ei[NI-1] low guard word (0x8000 bit is rounding place) - * - * - * - * Routines for external format numbers - * - * asctoe( string, e ) ASCII string to extended double e type - * asctoe64( string, &d ) ASCII string to long double - * asctoe53( string, &d ) ASCII string to double - * asctoe24( string, &f ) ASCII string to single - * asctoeg( string, e, prec ) ASCII string to specified precision - * e24toe( &f, e ) IEEE single precision to e type - * e53toe( &d, e ) IEEE double precision to e type - * e64toe( &d, e ) IEEE long double precision to e type - * eabs(e) absolute value - * eadd( a, b, c ) c = b + a - * eclear(e) e = 0 - * ecmp (a, b) Returns 1 if a > b, 0 if a == b, - * -1 if a < b, -2 if either a or b is a NaN. - * ediv( a, b, c ) c = b / a - * efloor( a, b ) truncate to integer, toward -infinity - * efrexp( a, exp, s ) extract exponent and significand - * eifrac( e, &l, frac ) e to long integer and e type fraction - * euifrac( e, &l, frac ) e to unsigned long integer and e type fraction - * einfin( e ) set e to infinity, leaving its sign alone - * eldexp( a, n, b ) multiply by 2**n - * emov( a, b ) b = a - * emul( a, b, c ) c = b * a - * eneg(e) e = -e - * eround( a, b ) b = nearest integer value to a - * esub( a, b, c ) c = b - a - * e24toasc( &f, str, n ) single to ASCII string, n digits after decimal - * e53toasc( &d, str, n ) double to ASCII string, n digits after decimal - * e64toasc( &d, str, n ) long double to ASCII string - * etoasc( e, str, n ) e to ASCII string, n digits after decimal - * etoe24( e, &f ) convert e type to IEEE single precision - * etoe53( e, &d ) convert e type to IEEE double precision - * etoe64( e, &d ) convert e type to IEEE long double precision - * ltoe( &l, e ) long (32 bit) integer to e type - * ultoe( &l, e ) unsigned long (32 bit) integer to e type - * eisneg( e ) 1 if sign bit of e != 0, else 0 - * eisinf( e ) 1 if e has maximum exponent (non-IEEE) - * or is infinite (IEEE) - * eisnan( e ) 1 if e is a NaN - * esqrt( a, b ) b = square root of a - * - * - * Routines for internal format numbers - * - * eaddm( ai, bi ) add significands, bi = bi + ai - * ecleaz(ei) ei = 0 - * ecleazs(ei) set ei = 0 but leave its sign alone - * ecmpm( ai, bi ) compare significands, return 1, 0, or -1 - * edivm( ai, bi ) divide significands, bi = bi / ai - * emdnorm(ai,l,s,exp) normalize and round off - * emovi( a, ai ) convert external a to internal ai - * emovo( ai, a ) convert internal ai to external a - * emovz( ai, bi ) bi = ai, low guard word of bi = 0 - * emulm( ai, bi ) multiply significands, bi = bi * ai - * enormlz(ei) left-justify the significand - * eshdn1( ai ) shift significand and guards down 1 bit - * eshdn8( ai ) shift down 8 bits - * eshdn6( ai ) shift down 16 bits - * eshift( ai, n ) shift ai n bits up (or down if n < 0) - * eshup1( ai ) shift significand and guards up 1 bit - * eshup8( ai ) shift up 8 bits - * eshup6( ai ) shift up 16 bits - * esubm( ai, bi ) subtract significands, bi = bi - ai - * - * - * The result is always normalized and rounded to NI-4 word precision - * after each arithmetic operation. - * - * Exception flags are NOT fully supported. - * - * Define INFINITY in mconf.h for support of infinity; otherwise a - * saturation arithmetic is implemented. - * - * Define NANS for support of Not-a-Number items; otherwise the - * arithmetic will never produce a NaN output, and might be confused - * by a NaN input. - * If NaN's are supported, the output of ecmp(a,b) is -2 if - * either a or b is a NaN. This means asking if(ecmp(a,b) < 0) - * may not be legitimate. Use if(ecmp(a,b) == -1) for less-than - * if in doubt. - * Signaling NaN's are NOT supported; they are treated the same - * as quiet NaN's. - * - * Denormals are always supported here where appropriate (e.g., not - * for conversion to DEC numbers). - */ - -/* - * Revision history: - * - * 5 Jan 84 PDP-11 assembly language version - * 2 Mar 86 fixed bug in asctoq() - * 6 Dec 86 C language version - * 30 Aug 88 100 digit version, improved rounding - * 15 May 92 80-bit long double support - * - * Author: S. L. Moshier. - */ - -#include <stdio.h> -/* #include "\usr\include\stdio.h" */ -#include "ehead.h" -#include "mconf.h" - -/* Change UNK into something else. */ -#ifdef UNK -#undef UNK -#define IBMPC 1 -#endif - -/* NaN's require infinity support. */ -#ifdef NANS -#ifndef INFINITY -#define INFINITY -#endif -#endif - -/* This handles 64-bit long ints. */ -#define LONGBITS (8 * sizeof(long)) - -/* Control register for rounding precision. - * This can be set to 80 (if NE=6), 64, 56, 53, or 24 bits. - */ -int rndprc = NBITS; -extern int rndprc; - -void eaddm(), esubm(), emdnorm(), asctoeg(), enan(); -static void toe24(), toe53(), toe64(), toe113(); -void eremain(), einit(), eiremain(); -int ecmpm(), edivm(), emulm(), eisneg(), eisinf(); -void emovi(), emovo(), emovz(), ecleaz(), eadd1(); -void etodec(), todec(), dectoe(); -int eisnan(), eiisnan(); - - - -void einit() -{ -} - -/* -; Clear out entire external format number. -; -; unsigned short x[]; -; eclear( x ); -*/ - -void eclear( x ) -register unsigned short *x; -{ -register int i; - -for( i=0; i<NE; i++ ) - *x++ = 0; -} - - - -/* Move external format number from a to b. - * - * emov( a, b ); - */ - -void emov( a, b ) -register unsigned short *a, *b; -{ -register int i; - -for( i=0; i<NE; i++ ) - *b++ = *a++; -} - - -/* -; Absolute value of external format number -; -; short x[NE]; -; eabs( x ); -*/ - -void eabs(x) -unsigned short x[]; /* x is the memory address of a short */ -{ - -x[NE-1] &= 0x7fff; /* sign is top bit of last word of external format */ -} - - - - -/* -; Negate external format number -; -; unsigned short x[NE]; -; eneg( x ); -*/ - -void eneg(x) -unsigned short x[]; -{ - -#ifdef NANS -if( eisnan(x) ) - return; -#endif -x[NE-1] ^= 0x8000; /* Toggle the sign bit */ -} - - - -/* Return 1 if external format number is negative, - * else return zero. - */ -int eisneg(x) -unsigned short x[]; -{ - -#ifdef NANS -if( eisnan(x) ) - return( 0 ); -#endif -if( x[NE-1] & 0x8000 ) - return( 1 ); -else - return( 0 ); -} - - -/* Return 1 if external format number has maximum possible exponent, - * else return zero. - */ -int eisinf(x) -unsigned short x[]; -{ - -if( (x[NE-1] & 0x7fff) == 0x7fff ) - { -#ifdef NANS - if( eisnan(x) ) - return( 0 ); -#endif - return( 1 ); - } -else - return( 0 ); -} - -/* Check if e-type number is not a number. - */ -int eisnan(x) -unsigned short x[]; -{ - -#ifdef NANS -int i; -/* NaN has maximum exponent */ -if( (x[NE-1] & 0x7fff) != 0x7fff ) - return (0); -/* ... and non-zero significand field. */ -for( i=0; i<NE-1; i++ ) - { - if( *x++ != 0 ) - return (1); - } -#endif -return (0); -} - -/* -; Fill entire number, including exponent and significand, with -; largest possible number. These programs implement a saturation -; value that is an ordinary, legal number. A special value -; "infinity" may also be implemented; this would require tests -; for that value and implementation of special rules for arithmetic -; operations involving inifinity. -*/ - -void einfin(x) -register unsigned short *x; -{ -register int i; - -#ifdef INFINITY -for( i=0; i<NE-1; i++ ) - *x++ = 0; -*x |= 32767; -#else -for( i=0; i<NE-1; i++ ) - *x++ = 0xffff; -*x |= 32766; -if( rndprc < NBITS ) - { - if (rndprc == 113) - { - *(x - 9) = 0; - *(x - 8) = 0; - } - if( rndprc == 64 ) - { - *(x-5) = 0; - } - if( rndprc == 53 ) - { - *(x-4) = 0xf800; - } - else - { - *(x-4) = 0; - *(x-3) = 0; - *(x-2) = 0xff00; - } - } -#endif -} - - - -/* Move in external format number, - * converting it to internal format. - */ -void emovi( a, b ) -unsigned short *a, *b; -{ -register unsigned short *p, *q; -int i; - -q = b; -p = a + (NE-1); /* point to last word of external number */ -/* get the sign bit */ -if( *p & 0x8000 ) - *q++ = 0xffff; -else - *q++ = 0; -/* get the exponent */ -*q = *p--; -*q++ &= 0x7fff; /* delete the sign bit */ -#ifdef INFINITY -if( (*(q-1) & 0x7fff) == 0x7fff ) - { -#ifdef NANS - if( eisnan(a) ) - { - *q++ = 0; - for( i=3; i<NI; i++ ) - *q++ = *p--; - return; - } -#endif - for( i=2; i<NI; i++ ) - *q++ = 0; - return; - } -#endif -/* clear high guard word */ -*q++ = 0; -/* move in the significand */ -for( i=0; i<NE-1; i++ ) - *q++ = *p--; -/* clear low guard word */ -*q = 0; -} - - -/* Move internal format number out, - * converting it to external format. - */ -void emovo( a, b ) -unsigned short *a, *b; -{ -register unsigned short *p, *q; -unsigned short i; - -p = a; -q = b + (NE-1); /* point to output exponent */ -/* combine sign and exponent */ -i = *p++; -if( i ) - *q-- = *p++ | 0x8000; -else - *q-- = *p++; -#ifdef INFINITY -if( *(p-1) == 0x7fff ) - { -#ifdef NANS - if( eiisnan(a) ) - { - enan( b, NBITS ); - return; - } -#endif - einfin(b); - return; - } -#endif -/* skip over guard word */ -++p; -/* move the significand */ -for( i=0; i<NE-1; i++ ) - *q-- = *p++; -} - - - - -/* Clear out internal format number. - */ - -void ecleaz( xi ) -register unsigned short *xi; -{ -register int i; - -for( i=0; i<NI; i++ ) - *xi++ = 0; -} - -/* same, but don't touch the sign. */ - -void ecleazs( xi ) -register unsigned short *xi; -{ -register int i; - -++xi; -for(i=0; i<NI-1; i++) - *xi++ = 0; -} - - - - -/* Move internal format number from a to b. - */ -void emovz( a, b ) -register unsigned short *a, *b; -{ -register int i; - -for( i=0; i<NI-1; i++ ) - *b++ = *a++; -/* clear low guard word */ -*b = 0; -} - -/* Return nonzero if internal format number is a NaN. - */ - -int eiisnan (x) -unsigned short x[]; -{ -int i; - -if( (x[E] & 0x7fff) == 0x7fff ) - { - for( i=M+1; i<NI; i++ ) - { - if( x[i] != 0 ) - return(1); - } - } -return(0); -} - -#ifdef INFINITY -/* Return nonzero if internal format number is infinite. */ - -static int -eiisinf (x) - unsigned short x[]; -{ - -#ifdef NANS - if (eiisnan (x)) - return (0); -#endif - if ((x[E] & 0x7fff) == 0x7fff) - return (1); - return (0); -} -#endif - -/* -; Compare significands of numbers in internal format. -; Guard words are included in the comparison. -; -; unsigned short a[NI], b[NI]; -; cmpm( a, b ); -; -; for the significands: -; returns +1 if a > b -; 0 if a == b -; -1 if a < b -*/ -int ecmpm( a, b ) -register unsigned short *a, *b; -{ -int i; - -a += M; /* skip up to significand area */ -b += M; -for( i=M; i<NI; i++ ) - { - if( *a++ != *b++ ) - goto difrnt; - } -return(0); - -difrnt: -if( *(--a) > *(--b) ) - return(1); -else - return(-1); -} - - -/* -; Shift significand down by 1 bit -*/ - -void eshdn1(x) -register unsigned short *x; -{ -register unsigned short bits; -int i; - -x += M; /* point to significand area */ - -bits = 0; -for( i=M; i<NI; i++ ) - { - if( *x & 1 ) - bits |= 1; - *x >>= 1; - if( bits & 2 ) - *x |= 0x8000; - bits <<= 1; - ++x; - } -} - - - -/* -; Shift significand up by 1 bit -*/ - -void eshup1(x) -register unsigned short *x; -{ -register unsigned short bits; -int i; - -x += NI-1; -bits = 0; - -for( i=M; i<NI; i++ ) - { - if( *x & 0x8000 ) - bits |= 1; - *x <<= 1; - if( bits & 2 ) - *x |= 1; - bits <<= 1; - --x; - } -} - - - -/* -; Shift significand down by 8 bits -*/ - -void eshdn8(x) -register unsigned short *x; -{ -register unsigned short newbyt, oldbyt; -int i; - -x += M; -oldbyt = 0; -for( i=M; i<NI; i++ ) - { - newbyt = *x << 8; - *x >>= 8; - *x |= oldbyt; - oldbyt = newbyt; - ++x; - } -} - -/* -; Shift significand up by 8 bits -*/ - -void eshup8(x) -register unsigned short *x; -{ -int i; -register unsigned short newbyt, oldbyt; - -x += NI-1; -oldbyt = 0; - -for( i=M; i<NI; i++ ) - { - newbyt = *x >> 8; - *x <<= 8; - *x |= oldbyt; - oldbyt = newbyt; - --x; - } -} - -/* -; Shift significand up by 16 bits -*/ - -void eshup6(x) -register unsigned short *x; -{ -int i; -register unsigned short *p; - -p = x + M; -x += M + 1; - -for( i=M; i<NI-1; i++ ) - *p++ = *x++; - -*p = 0; -} - -/* -; Shift significand down by 16 bits -*/ - -void eshdn6(x) -register unsigned short *x; -{ -int i; -register unsigned short *p; - -x += NI-1; -p = x + 1; - -for( i=M; i<NI-1; i++ ) - *(--p) = *(--x); - -*(--p) = 0; -} - -/* -; Add significands -; x + y replaces y -*/ - -void eaddm( x, y ) -unsigned short *x, *y; -{ -register unsigned long a; -int i; -unsigned int carry; - -x += NI-1; -y += NI-1; -carry = 0; -for( i=M; i<NI; i++ ) - { - a = (unsigned long )(*x) + (unsigned long )(*y) + carry; - if( a & 0x10000 ) - carry = 1; - else - carry = 0; - *y = (unsigned short )a; - --x; - --y; - } -} - -/* -; Subtract significands -; y - x replaces y -*/ - -void esubm( x, y ) -unsigned short *x, *y; -{ -unsigned long a; -int i; -unsigned int carry; - -x += NI-1; -y += NI-1; -carry = 0; -for( i=M; i<NI; i++ ) - { - a = (unsigned long )(*y) - (unsigned long )(*x) - carry; - if( a & 0x10000 ) - carry = 1; - else - carry = 0; - *y = (unsigned short )a; - --x; - --y; - } -} - - -/* Divide significands */ - -static unsigned short equot[NI] = {0}; /* was static */ - -#if 0 -int edivm( den, num ) -unsigned short den[], num[]; -{ -int i; -register unsigned short *p, *q; -unsigned short j; - -p = &equot[0]; -*p++ = num[0]; -*p++ = num[1]; - -for( i=M; i<NI; i++ ) - { - *p++ = 0; - } - -/* Use faster compare and subtraction if denominator - * has only 15 bits of significance. - */ -p = &den[M+2]; -if( *p++ == 0 ) - { - for( i=M+3; i<NI; i++ ) - { - if( *p++ != 0 ) - goto fulldiv; - } - if( (den[M+1] & 1) != 0 ) - goto fulldiv; - eshdn1(num); - eshdn1(den); - - p = &den[M+1]; - q = &num[M+1]; - - for( i=0; i<NBITS+2; i++ ) - { - if( *p <= *q ) - { - *q -= *p; - j = 1; - } - else - { - j = 0; - } - eshup1(equot); - equot[NI-2] |= j; - eshup1(num); - } - goto divdon; - } - -/* The number of quotient bits to calculate is - * NBITS + 1 scaling guard bit + 1 roundoff bit. - */ -fulldiv: - -p = &equot[NI-2]; -for( i=0; i<NBITS+2; i++ ) - { - if( ecmpm(den,num) <= 0 ) - { - esubm(den, num); - j = 1; /* quotient bit = 1 */ - } - else - j = 0; - eshup1(equot); - *p |= j; - eshup1(num); - } - -divdon: - -eshdn1( equot ); -eshdn1( equot ); - -/* test for nonzero remainder after roundoff bit */ -p = &num[M]; -j = 0; -for( i=M; i<NI; i++ ) - { - j |= *p++; - } -if( j ) - j = 1; - - -for( i=0; i<NI; i++ ) - num[i] = equot[i]; -return( (int )j ); -} - -/* Multiply significands */ -int emulm( a, b ) -unsigned short a[], b[]; -{ -unsigned short *p, *q; -int i, j, k; - -equot[0] = b[0]; -equot[1] = b[1]; -for( i=M; i<NI; i++ ) - equot[i] = 0; - -p = &a[NI-2]; -k = NBITS; -while( *p == 0 ) /* significand is not supposed to be all zero */ - { - eshdn6(a); - k -= 16; - } -if( (*p & 0xff) == 0 ) - { - eshdn8(a); - k -= 8; - } - -q = &equot[NI-1]; -j = 0; -for( i=0; i<k; i++ ) - { - if( *p & 1 ) - eaddm(b, equot); -/* remember if there were any nonzero bits shifted out */ - if( *q & 1 ) - j |= 1; - eshdn1(a); - eshdn1(equot); - } - -for( i=0; i<NI; i++ ) - b[i] = equot[i]; - -/* return flag for lost nonzero bits */ -return(j); -} - -#else - -/* Multiply significand of e-type number b -by 16-bit quantity a, e-type result to c. */ - -void m16m( a, b, c ) -unsigned short a; -unsigned short b[], c[]; -{ -register unsigned short *pp; -register unsigned long carry; -unsigned short *ps; -unsigned short p[NI]; -unsigned long aa, m; -int i; - -aa = a; -pp = &p[NI-2]; -*pp++ = 0; -*pp = 0; -ps = &b[NI-1]; - -for( i=M+1; i<NI; i++ ) - { - if( *ps == 0 ) - { - --ps; - --pp; - *(pp-1) = 0; - } - else - { - m = (unsigned long) aa * *ps--; - carry = (m & 0xffff) + *pp; - *pp-- = (unsigned short )carry; - carry = (carry >> 16) + (m >> 16) + *pp; - *pp = (unsigned short )carry; - *(pp-1) = carry >> 16; - } - } -for( i=M; i<NI; i++ ) - c[i] = p[i]; -} - - -/* Divide significands. Neither the numerator nor the denominator -is permitted to have its high guard word nonzero. */ - - -int edivm( den, num ) -unsigned short den[], num[]; -{ -int i; -register unsigned short *p; -unsigned long tnum; -unsigned short j, tdenm, tquot; -unsigned short tprod[NI+1]; - -p = &equot[0]; -*p++ = num[0]; -*p++ = num[1]; - -for( i=M; i<NI; i++ ) - { - *p++ = 0; - } -eshdn1( num ); -tdenm = den[M+1]; -for( i=M; i<NI; i++ ) - { - /* Find trial quotient digit (the radix is 65536). */ - tnum = (((unsigned long) num[M]) << 16) + num[M+1]; - - /* Do not execute the divide instruction if it will overflow. */ - if( (tdenm * 0xffffL) < tnum ) - tquot = 0xffff; - else - tquot = tnum / tdenm; - - /* Prove that the divide worked. */ -/* - tcheck = (unsigned long )tquot * tdenm; - if( tnum - tcheck > tdenm ) - tquot = 0xffff; -*/ - /* Multiply denominator by trial quotient digit. */ - m16m( tquot, den, tprod ); - /* The quotient digit may have been overestimated. */ - if( ecmpm( tprod, num ) > 0 ) - { - tquot -= 1; - esubm( den, tprod ); - if( ecmpm( tprod, num ) > 0 ) - { - tquot -= 1; - esubm( den, tprod ); - } - } -/* - if( ecmpm( tprod, num ) > 0 ) - { - eshow( "tprod", tprod ); - eshow( "num ", num ); - printf( "tnum = %08lx, tden = %04x, tquot = %04x\n", - tnum, den[M+1], tquot ); - } -*/ - esubm( tprod, num ); -/* - if( ecmpm( num, den ) >= 0 ) - { - eshow( "num ", num ); - eshow( "den ", den ); - printf( "tnum = %08lx, tden = %04x, tquot = %04x\n", - tnum, den[M+1], tquot ); - } -*/ - equot[i] = tquot; - eshup6(num); - } -/* test for nonzero remainder after roundoff bit */ -p = &num[M]; -j = 0; -for( i=M; i<NI; i++ ) - { - j |= *p++; - } -if( j ) - j = 1; - -for( i=0; i<NI; i++ ) - num[i] = equot[i]; - -return( (int )j ); -} - - - -/* Multiply significands */ -int emulm( a, b ) -unsigned short a[], b[]; -{ -unsigned short *p, *q; -unsigned short pprod[NI]; -unsigned short j; -int i; - -equot[0] = b[0]; -equot[1] = b[1]; -for( i=M; i<NI; i++ ) - equot[i] = 0; - -j = 0; -p = &a[NI-1]; -q = &equot[NI-1]; -for( i=M+1; i<NI; i++ ) - { - if( *p == 0 ) - { - --p; - } - else - { - m16m( *p--, b, pprod ); - eaddm(pprod, equot); - } - j |= *q; - eshdn6(equot); - } - -for( i=0; i<NI; i++ ) - b[i] = equot[i]; - -/* return flag for lost nonzero bits */ -return( (int)j ); -} - - -/* -eshow(str, x) -char *str; -unsigned short *x; -{ -int i; - -printf( "%s ", str ); -for( i=0; i<NI; i++ ) - printf( "%04x ", *x++ ); -printf( "\n" ); -} -*/ -#endif - - - -/* - * Normalize and round off. - * - * The internal format number to be rounded is "s". - * Input "lost" indicates whether the number is exact. - * This is the so-called sticky bit. - * - * Input "subflg" indicates whether the number was obtained - * by a subtraction operation. In that case if lost is nonzero - * then the number is slightly smaller than indicated. - * - * Input "exp" is the biased exponent, which may be negative. - * the exponent field of "s" is ignored but is replaced by - * "exp" as adjusted by normalization and rounding. - * - * Input "rcntrl" is the rounding control. - */ - -static int rlast = -1; -static int rw = 0; -static unsigned short rmsk = 0; -static unsigned short rmbit = 0; -static unsigned short rebit = 0; -static int re = 0; -static unsigned short rbit[NI] = {0,0,0,0,0,0,0,0}; - -void emdnorm( s, lost, subflg, exp, rcntrl ) -unsigned short s[]; -int lost; -int subflg; -long exp; -int rcntrl; -{ -int i, j; -unsigned short r; - -/* Normalize */ -j = enormlz( s ); - -/* a blank significand could mean either zero or infinity. */ -#ifndef INFINITY -if( j > NBITS ) - { - ecleazs( s ); - return; - } -#endif -exp -= j; -#ifndef INFINITY -if( exp >= 32767L ) - goto overf; -#else -if( (j > NBITS) && (exp < 32767L) ) - { - ecleazs( s ); - return; - } -#endif -if( exp < 0L ) - { - if( exp > (long )(-NBITS-1) ) - { - j = (int )exp; - i = eshift( s, j ); - if( i ) - lost = 1; - } - else - { - ecleazs( s ); - return; - } - } -/* Round off, unless told not to by rcntrl. */ -if( rcntrl == 0 ) - goto mdfin; -/* Set up rounding parameters if the control register changed. */ -if( rndprc != rlast ) - { - ecleaz( rbit ); - switch( rndprc ) - { - default: - case NBITS: - rw = NI-1; /* low guard word */ - rmsk = 0xffff; - rmbit = 0x8000; - rebit = 1; - re = rw - 1; - break; - case 113: - rw = 10; - rmsk = 0x7fff; - rmbit = 0x4000; - rebit = 0x8000; - re = rw; - break; - case 64: - rw = 7; - rmsk = 0xffff; - rmbit = 0x8000; - rebit = 1; - re = rw-1; - break; -/* For DEC arithmetic */ - case 56: - rw = 6; - rmsk = 0xff; - rmbit = 0x80; - rebit = 0x100; - re = rw; - break; - case 53: - rw = 6; - rmsk = 0x7ff; - rmbit = 0x0400; - rebit = 0x800; - re = rw; - break; - case 24: - rw = 4; - rmsk = 0xff; - rmbit = 0x80; - rebit = 0x100; - re = rw; - break; - } - rbit[re] = rebit; - rlast = rndprc; - } - -/* Shift down 1 temporarily if the data structure has an implied - * most significant bit and the number is denormal. - * For rndprc = 64 or NBITS, there is no implied bit. - * But Intel long double denormals lose one bit of significance even so. - */ -#if IBMPC -if( (exp <= 0) && (rndprc != NBITS) ) -#else -if( (exp <= 0) && (rndprc != 64) && (rndprc != NBITS) ) -#endif - { - lost |= s[NI-1] & 1; - eshdn1(s); - } -/* Clear out all bits below the rounding bit, - * remembering in r if any were nonzero. - */ -r = s[rw] & rmsk; -if( rndprc < NBITS ) - { - i = rw + 1; - while( i < NI ) - { - if( s[i] ) - r |= 1; - s[i] = 0; - ++i; - } - } -s[rw] &= ~rmsk; -if( (r & rmbit) != 0 ) - { - if( r == rmbit ) - { - if( lost == 0 ) - { /* round to even */ - if( (s[re] & rebit) == 0 ) - goto mddone; - } - else - { - if( subflg != 0 ) - goto mddone; - } - } - eaddm( rbit, s ); - } -mddone: -#if IBMPC -if( (exp <= 0) && (rndprc != NBITS) ) -#else -if( (exp <= 0) && (rndprc != 64) && (rndprc != NBITS) ) -#endif - { - eshup1(s); - } -if( s[2] != 0 ) - { /* overflow on roundoff */ - eshdn1(s); - exp += 1; - } -mdfin: -s[NI-1] = 0; -if( exp >= 32767L ) - { -#ifndef INFINITY -overf: -#endif -#ifdef INFINITY - s[1] = 32767; - for( i=2; i<NI-1; i++ ) - s[i] = 0; -#else - s[1] = 32766; - s[2] = 0; - for( i=M+1; i<NI-1; i++ ) - s[i] = 0xffff; - s[NI-1] = 0; - if( (rndprc < 64) || (rndprc == 113) ) - { - s[rw] &= ~rmsk; - if( rndprc == 24 ) - { - s[5] = 0; - s[6] = 0; - } - } -#endif - return; - } -if( exp < 0 ) - s[1] = 0; -else - s[1] = (unsigned short )exp; -} - - - -/* -; Subtract external format numbers. -; -; unsigned short a[NE], b[NE], c[NE]; -; esub( a, b, c ); c = b - a -*/ - -static int subflg = 0; - -void esub( a, b, c ) -unsigned short *a, *b, *c; -{ - -#ifdef NANS -if( eisnan(a) ) - { - emov (a, c); - return; - } -if( eisnan(b) ) - { - emov(b,c); - return; - } -/* Infinity minus infinity is a NaN. - * Test for subtracting infinities of the same sign. - */ -if( eisinf(a) && eisinf(b) && ((eisneg (a) ^ eisneg (b)) == 0)) - { - mtherr( "esub", DOMAIN ); - enan( c, NBITS ); - return; - } -#endif -subflg = 1; -eadd1( a, b, c ); -} - - -/* -; Add. -; -; unsigned short a[NE], b[NE], c[NE]; -; eadd( a, b, c ); c = b + a -*/ -void eadd( a, b, c ) -unsigned short *a, *b, *c; -{ - -#ifdef NANS -/* NaN plus anything is a NaN. */ -if( eisnan(a) ) - { - emov(a,c); - return; - } -if( eisnan(b) ) - { - emov(b,c); - return; - } -/* Infinity minus infinity is a NaN. - * Test for adding infinities of opposite signs. - */ -if( eisinf(a) && eisinf(b) - && ((eisneg(a) ^ eisneg(b)) != 0) ) - { - mtherr( "eadd", DOMAIN ); - enan( c, NBITS ); - return; - } -#endif -subflg = 0; -eadd1( a, b, c ); -} - -void eadd1( a, b, c ) -unsigned short *a, *b, *c; -{ -unsigned short ai[NI], bi[NI], ci[NI]; -int i, lost, j, k; -long lt, lta, ltb; - -#ifdef INFINITY -if( eisinf(a) ) - { - emov(a,c); - if( subflg ) - eneg(c); - return; - } -if( eisinf(b) ) - { - emov(b,c); - return; - } -#endif -emovi( a, ai ); -emovi( b, bi ); -if( subflg ) - ai[0] = ~ai[0]; - -/* compare exponents */ -lta = ai[E]; -ltb = bi[E]; -lt = lta - ltb; -if( lt > 0L ) - { /* put the larger number in bi */ - emovz( bi, ci ); - emovz( ai, bi ); - emovz( ci, ai ); - ltb = bi[E]; - lt = -lt; - } -lost = 0; -if( lt != 0L ) - { - if( lt < (long )(-NBITS-1) ) - goto done; /* answer same as larger addend */ - k = (int )lt; - lost = eshift( ai, k ); /* shift the smaller number down */ - } -else - { -/* exponents were the same, so must compare significands */ - i = ecmpm( ai, bi ); - if( i == 0 ) - { /* the numbers are identical in magnitude */ - /* if different signs, result is zero */ - if( ai[0] != bi[0] ) - { - eclear(c); - return; - } - /* if same sign, result is double */ - /* double denomalized tiny number */ - if( (bi[E] == 0) && ((bi[3] & 0x8000) == 0) ) - { - eshup1( bi ); - goto done; - } - /* add 1 to exponent unless both are zero! */ - for( j=1; j<NI-1; j++ ) - { - if( bi[j] != 0 ) - { -/* This could overflow, but let emovo take care of that. */ - ltb += 1; - break; - } - } - bi[E] = (unsigned short )ltb; - goto done; - } - if( i > 0 ) - { /* put the larger number in bi */ - emovz( bi, ci ); - emovz( ai, bi ); - emovz( ci, ai ); - } - } -if( ai[0] == bi[0] ) - { - eaddm( ai, bi ); - subflg = 0; - } -else - { - esubm( ai, bi ); - subflg = 1; - } -emdnorm( bi, lost, subflg, ltb, 64 ); - -done: -emovo( bi, c ); -} - - - -/* -; Divide. -; -; unsigned short a[NE], b[NE], c[NE]; -; ediv( a, b, c ); c = b / a -*/ -void ediv( a, b, c ) -unsigned short *a, *b, *c; -{ -unsigned short ai[NI], bi[NI]; -int i; -long lt, lta, ltb; - -#ifdef NANS -/* Return any NaN input. */ -if( eisnan(a) ) - { - emov(a,c); - return; - } -if( eisnan(b) ) - { - emov(b,c); - return; - } -/* Zero over zero, or infinity over infinity, is a NaN. */ -if( ((ecmp(a,ezero) == 0) && (ecmp(b,ezero) == 0)) - || (eisinf (a) && eisinf (b)) ) - { - mtherr( "ediv", DOMAIN ); - enan( c, NBITS ); - return; - } -#endif -/* Infinity over anything else is infinity. */ -#ifdef INFINITY -if( eisinf(b) ) - { - if( eisneg(a) ^ eisneg(b) ) - *(c+(NE-1)) = 0x8000; - else - *(c+(NE-1)) = 0; - einfin(c); - return; - } -if( eisinf(a) ) - { - eclear(c); - return; - } -#endif -emovi( a, ai ); -emovi( b, bi ); -lta = ai[E]; -ltb = bi[E]; -if( bi[E] == 0 ) - { /* See if numerator is zero. */ - for( i=1; i<NI-1; i++ ) - { - if( bi[i] != 0 ) - { - ltb -= enormlz( bi ); - goto dnzro1; - } - } - eclear(c); - return; - } -dnzro1: - -if( ai[E] == 0 ) - { /* possible divide by zero */ - for( i=1; i<NI-1; i++ ) - { - if( ai[i] != 0 ) - { - lta -= enormlz( ai ); - goto dnzro2; - } - } - if( ai[0] == bi[0] ) - *(c+(NE-1)) = 0; - else - *(c+(NE-1)) = 0x8000; - einfin(c); - mtherr( "ediv", SING ); - return; - } -dnzro2: - -i = edivm( ai, bi ); -/* calculate exponent */ -lt = ltb - lta + EXONE; -emdnorm( bi, i, 0, lt, 64 ); -/* set the sign */ -if( ai[0] == bi[0] ) - bi[0] = 0; -else - bi[0] = 0Xffff; -emovo( bi, c ); -} - - - -/* -; Multiply. -; -; unsigned short a[NE], b[NE], c[NE]; -; emul( a, b, c ); c = b * a -*/ -void emul( a, b, c ) -unsigned short *a, *b, *c; -{ -unsigned short ai[NI], bi[NI]; -int i, j; -long lt, lta, ltb; - -#ifdef NANS -/* NaN times anything is the same NaN. */ -if( eisnan(a) ) - { - emov(a,c); - return; - } -if( eisnan(b) ) - { - emov(b,c); - return; - } -/* Zero times infinity is a NaN. */ -if( (eisinf(a) && (ecmp(b,ezero) == 0)) - || (eisinf(b) && (ecmp(a,ezero) == 0)) ) - { - mtherr( "emul", DOMAIN ); - enan( c, NBITS ); - return; - } -#endif -/* Infinity times anything else is infinity. */ -#ifdef INFINITY -if( eisinf(a) || eisinf(b) ) - { - if( eisneg(a) ^ eisneg(b) ) - *(c+(NE-1)) = 0x8000; - else - *(c+(NE-1)) = 0; - einfin(c); - return; - } -#endif -emovi( a, ai ); -emovi( b, bi ); -lta = ai[E]; -ltb = bi[E]; -if( ai[E] == 0 ) - { - for( i=1; i<NI-1; i++ ) - { - if( ai[i] != 0 ) - { - lta -= enormlz( ai ); - goto mnzer1; - } - } - eclear(c); - return; - } -mnzer1: - -if( bi[E] == 0 ) - { - for( i=1; i<NI-1; i++ ) - { - if( bi[i] != 0 ) - { - ltb -= enormlz( bi ); - goto mnzer2; - } - } - eclear(c); - return; - } -mnzer2: - -/* Multiply significands */ -j = emulm( ai, bi ); -/* calculate exponent */ -lt = lta + ltb - (EXONE - 1); -emdnorm( bi, j, 0, lt, 64 ); -/* calculate sign of product */ -if( ai[0] == bi[0] ) - bi[0] = 0; -else - bi[0] = 0xffff; -emovo( bi, c ); -} - - - - -/* -; Convert IEEE double precision to e type -; double d; -; unsigned short x[N+2]; -; e53toe( &d, x ); -*/ -void e53toe( pe, y ) -unsigned short *pe, *y; -{ -#ifdef DEC - -dectoe( pe, y ); /* see etodec.c */ - -#else - -register unsigned short r; -register unsigned short *p, *e; -unsigned short yy[NI]; -int denorm, k; - -e = pe; -denorm = 0; /* flag if denormalized number */ -ecleaz(yy); -#ifdef IBMPC -e += 3; -#endif -r = *e; -yy[0] = 0; -if( r & 0x8000 ) - yy[0] = 0xffff; -yy[M] = (r & 0x0f) | 0x10; -r &= ~0x800f; /* strip sign and 4 significand bits */ -#ifdef INFINITY -if( r == 0x7ff0 ) - { -#ifdef NANS -#ifdef IBMPC - if( ((pe[3] & 0xf) != 0) || (pe[2] != 0) - || (pe[1] != 0) || (pe[0] != 0) ) - { - enan( y, NBITS ); - return; - } -#else - if( ((pe[0] & 0xf) != 0) || (pe[1] != 0) - || (pe[2] != 0) || (pe[3] != 0) ) - { - enan( y, NBITS ); - return; - } -#endif -#endif /* NANS */ - eclear( y ); - einfin( y ); - if( yy[0] ) - eneg(y); - return; - } -#endif -r >>= 4; -/* If zero exponent, then the significand is denormalized. - * So, take back the understood high significand bit. */ -if( r == 0 ) - { - denorm = 1; - yy[M] &= ~0x10; - } -r += EXONE - 01777; -yy[E] = r; -p = &yy[M+1]; -#ifdef IBMPC -*p++ = *(--e); -*p++ = *(--e); -*p++ = *(--e); -#endif -#ifdef MIEEE -++e; -*p++ = *e++; -*p++ = *e++; -*p++ = *e++; -#endif -(void )eshift( yy, -5 ); -if( denorm ) - { /* if zero exponent, then normalize the significand */ - if( (k = enormlz(yy)) > NBITS ) - ecleazs(yy); - else - yy[E] -= (unsigned short )(k-1); - } -emovo( yy, y ); -#endif /* not DEC */ -} - -void e64toe( pe, y ) -unsigned short *pe, *y; -{ -unsigned short yy[NI]; -unsigned short *p, *q, *e; -int i; - -e = pe; -p = yy; -for( i=0; i<NE-5; i++ ) - *p++ = 0; -#ifdef IBMPC -for( i=0; i<5; i++ ) - *p++ = *e++; -#endif -#ifdef DEC -for( i=0; i<5; i++ ) - *p++ = *e++; -#endif -#ifdef MIEEE -p = &yy[0] + (NE-1); -*p-- = *e++; -++e; -for( i=0; i<4; i++ ) - *p-- = *e++; -#endif - -#ifdef IBMPC -/* For Intel long double, shift denormal significand up 1 - -- but only if the top significand bit is zero. */ -if((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0) - { - unsigned short temp[NI+1]; - emovi(yy, temp); - eshup1(temp); - emovo(temp,y); - return; - } -#endif -#ifdef INFINITY -/* Point to the exponent field. */ -p = &yy[NE-1]; -if( *p == 0x7fff ) - { -#ifdef NANS -#ifdef IBMPC - for( i=0; i<4; i++ ) - { - if((i != 3 && pe[i] != 0) - /* Check for Intel long double infinity pattern. */ - || (i == 3 && pe[i] != 0x8000)) - { - enan( y, NBITS ); - return; - } - } -#else - for( i=1; i<=4; i++ ) - { - if( pe[i] != 0 ) - { - enan( y, NBITS ); - return; - } - } -#endif -#endif /* NANS */ - eclear( y ); - einfin( y ); - if( *p & 0x8000 ) - eneg(y); - return; - } -#endif -p = yy; -q = y; -for( i=0; i<NE; i++ ) - *q++ = *p++; -} - -void e113toe(pe,y) -unsigned short *pe, *y; -{ -register unsigned short r; -unsigned short *e, *p; -unsigned short yy[NI]; -int denorm, i; - -e = pe; -denorm = 0; -ecleaz(yy); -#ifdef IBMPC -e += 7; -#endif -r = *e; -yy[0] = 0; -if( r & 0x8000 ) - yy[0] = 0xffff; -r &= 0x7fff; -#ifdef INFINITY -if( r == 0x7fff ) - { -#ifdef NANS -#ifdef IBMPC - for( i=0; i<7; i++ ) - { - if( pe[i] != 0 ) - { - enan( y, NBITS ); - return; - } - } -#else - for( i=1; i<8; i++ ) - { - if( pe[i] != 0 ) - { - enan( y, NBITS ); - return; - } - } -#endif -#endif /* NANS */ - eclear( y ); - einfin( y ); - if( *e & 0x8000 ) - eneg(y); - return; - } -#endif /* INFINITY */ -yy[E] = r; -p = &yy[M + 1]; -#ifdef IBMPC -for( i=0; i<7; i++ ) - *p++ = *(--e); -#endif -#ifdef MIEEE -++e; -for( i=0; i<7; i++ ) - *p++ = *e++; -#endif -/* If denormal, remove the implied bit; else shift down 1. */ -if( r == 0 ) - { - yy[M] = 0; - } -else - { - yy[M] = 1; - eshift( yy, -1 ); - } -emovo(yy,y); -} - - -/* -; Convert IEEE single precision to e type -; float d; -; unsigned short x[N+2]; -; dtox( &d, x ); -*/ -void e24toe( pe, y ) -unsigned short *pe, *y; -{ -register unsigned short r; -register unsigned short *p, *e; -unsigned short yy[NI]; -int denorm, k; - -e = pe; -denorm = 0; /* flag if denormalized number */ -ecleaz(yy); -#ifdef IBMPC -e += 1; -#endif -#ifdef DEC -e += 1; -#endif -r = *e; -yy[0] = 0; -if( r & 0x8000 ) - yy[0] = 0xffff; -yy[M] = (r & 0x7f) | 0200; -r &= ~0x807f; /* strip sign and 7 significand bits */ -#ifdef INFINITY -if( r == 0x7f80 ) - { -#ifdef NANS -#ifdef MIEEE - if( ((pe[0] & 0x7f) != 0) || (pe[1] != 0) ) - { - enan( y, NBITS ); - return; - } -#else - if( ((pe[1] & 0x7f) != 0) || (pe[0] != 0) ) - { - enan( y, NBITS ); - return; - } -#endif -#endif /* NANS */ - eclear( y ); - einfin( y ); - if( yy[0] ) - eneg(y); - return; - } -#endif -r >>= 7; -/* If zero exponent, then the significand is denormalized. - * So, take back the understood high significand bit. */ -if( r == 0 ) - { - denorm = 1; - yy[M] &= ~0200; - } -r += EXONE - 0177; -yy[E] = r; -p = &yy[M+1]; -#ifdef IBMPC -*p++ = *(--e); -#endif -#ifdef DEC -*p++ = *(--e); -#endif -#ifdef MIEEE -++e; -*p++ = *e++; -#endif -(void )eshift( yy, -8 ); -if( denorm ) - { /* if zero exponent, then normalize the significand */ - if( (k = enormlz(yy)) > NBITS ) - ecleazs(yy); - else - yy[E] -= (unsigned short )(k-1); - } -emovo( yy, y ); -} - -void etoe113(x,e) -unsigned short *x, *e; -{ -unsigned short xi[NI]; -long exp; -int rndsav; - -#ifdef NANS -if( eisnan(x) ) - { - enan( e, 113 ); - return; - } -#endif -emovi( x, xi ); -exp = (long )xi[E]; -#ifdef INFINITY -if( eisinf(x) ) - goto nonorm; -#endif -/* round off to nearest or even */ -rndsav = rndprc; -rndprc = 113; -emdnorm( xi, 0, 0, exp, 64 ); -rndprc = rndsav; -nonorm: -toe113 (xi, e); -} - -/* move out internal format to ieee long double */ -static void toe113(a,b) -unsigned short *a, *b; -{ -register unsigned short *p, *q; -unsigned short i; - -#ifdef NANS -if( eiisnan(a) ) - { - enan( b, 113 ); - return; - } -#endif -p = a; -#ifdef MIEEE -q = b; -#else -q = b + 7; /* point to output exponent */ -#endif - -/* If not denormal, delete the implied bit. */ -if( a[E] != 0 ) - { - eshup1 (a); - } -/* combine sign and exponent */ -i = *p++; -#ifdef MIEEE -if( i ) - *q++ = *p++ | 0x8000; -else - *q++ = *p++; -#else -if( i ) - *q-- = *p++ | 0x8000; -else - *q-- = *p++; -#endif -/* skip over guard word */ -++p; -/* move the significand */ -#ifdef MIEEE -for (i = 0; i < 7; i++) - *q++ = *p++; -#else -for (i = 0; i < 7; i++) - *q-- = *p++; -#endif -} - - -void etoe64( x, e ) -unsigned short *x, *e; -{ -unsigned short xi[NI]; -long exp; -int rndsav; - -#ifdef NANS -if( eisnan(x) ) - { - enan( e, 64 ); - return; - } -#endif -emovi( x, xi ); -exp = (long )xi[E]; /* adjust exponent for offset */ -#ifdef INFINITY -if( eisinf(x) ) - goto nonorm; -#endif -/* round off to nearest or even */ -rndsav = rndprc; -rndprc = 64; -emdnorm( xi, 0, 0, exp, 64 ); -rndprc = rndsav; -nonorm: -toe64( xi, e ); -} - -/* move out internal format to ieee long double */ -static void toe64( a, b ) -unsigned short *a, *b; -{ -register unsigned short *p, *q; -unsigned short i; - -#ifdef NANS -if( eiisnan(a) ) - { - enan( b, 64 ); - return; - } -#endif -#ifdef IBMPC -/* Shift Intel denormal significand down 1. */ -if( a[E] == 0 ) - eshdn1(a); -#endif -p = a; -#ifdef MIEEE -q = b; -#else -q = b + 4; /* point to output exponent */ -#if 1 -/* NOTE: if data type is 96 bits wide, clear the last word here. */ -*(q+1)= 0; -#endif -#endif - -/* combine sign and exponent */ -i = *p++; -#ifdef MIEEE -if( i ) - *q++ = *p++ | 0x8000; -else - *q++ = *p++; -*q++ = 0; -#else -if( i ) - *q-- = *p++ | 0x8000; -else - *q-- = *p++; -#endif -/* skip over guard word */ -++p; -/* move the significand */ -#ifdef MIEEE -for( i=0; i<4; i++ ) - *q++ = *p++; -#else -#ifdef INFINITY -if (eiisinf (a)) - { - /* Intel long double infinity. */ - *q-- = 0x8000; - *q-- = 0; - *q-- = 0; - *q = 0; - return; - } -#endif -for( i=0; i<4; i++ ) - *q-- = *p++; -#endif -} - - -/* -; e type to IEEE double precision -; double d; -; unsigned short x[NE]; -; etoe53( x, &d ); -*/ - -#ifdef DEC - -void etoe53( x, e ) -unsigned short *x, *e; -{ -etodec( x, e ); /* see etodec.c */ -} - -static void toe53( x, y ) -unsigned short *x, *y; -{ -todec( x, y ); -} - -#else - -void etoe53( x, e ) -unsigned short *x, *e; -{ -unsigned short xi[NI]; -long exp; -int rndsav; - -#ifdef NANS -if( eisnan(x) ) - { - enan( e, 53 ); - return; - } -#endif -emovi( x, xi ); -exp = (long )xi[E] - (EXONE - 0x3ff); /* adjust exponent for offsets */ -#ifdef INFINITY -if( eisinf(x) ) - goto nonorm; -#endif -/* round off to nearest or even */ -rndsav = rndprc; -rndprc = 53; -emdnorm( xi, 0, 0, exp, 64 ); -rndprc = rndsav; -nonorm: -toe53( xi, e ); -} - - -static void toe53( x, y ) -unsigned short *x, *y; -{ -unsigned short i; -unsigned short *p; - - -#ifdef NANS -if( eiisnan(x) ) - { - enan( y, 53 ); - return; - } -#endif -p = &x[0]; -#ifdef IBMPC -y += 3; -#endif -*y = 0; /* output high order */ -if( *p++ ) - *y = 0x8000; /* output sign bit */ - -i = *p++; -if( i >= (unsigned int )2047 ) - { /* Saturate at largest number less than infinity. */ -#ifdef INFINITY - *y |= 0x7ff0; -#ifdef IBMPC - *(--y) = 0; - *(--y) = 0; - *(--y) = 0; -#endif -#ifdef MIEEE - ++y; - *y++ = 0; - *y++ = 0; - *y++ = 0; -#endif -#else - *y |= (unsigned short )0x7fef; -#ifdef IBMPC - *(--y) = 0xffff; - *(--y) = 0xffff; - *(--y) = 0xffff; -#endif -#ifdef MIEEE - ++y; - *y++ = 0xffff; - *y++ = 0xffff; - *y++ = 0xffff; -#endif -#endif - return; - } -if( i == 0 ) - { - (void )eshift( x, 4 ); - } -else - { - i <<= 4; - (void )eshift( x, 5 ); - } -i |= *p++ & (unsigned short )0x0f; /* *p = xi[M] */ -*y |= (unsigned short )i; /* high order output already has sign bit set */ -#ifdef IBMPC -*(--y) = *p++; -*(--y) = *p++; -*(--y) = *p; -#endif -#ifdef MIEEE -++y; -*y++ = *p++; -*y++ = *p++; -*y++ = *p++; -#endif -} - -#endif /* not DEC */ - - - -/* -; e type to IEEE single precision -; float d; -; unsigned short x[N+2]; -; xtod( x, &d ); -*/ -void etoe24( x, e ) -unsigned short *x, *e; -{ -long exp; -unsigned short xi[NI]; -int rndsav; - -#ifdef NANS -if( eisnan(x) ) - { - enan( e, 24 ); - return; - } -#endif -emovi( x, xi ); -exp = (long )xi[E] - (EXONE - 0177); /* adjust exponent for offsets */ -#ifdef INFINITY -if( eisinf(x) ) - goto nonorm; -#endif -/* round off to nearest or even */ -rndsav = rndprc; -rndprc = 24; -emdnorm( xi, 0, 0, exp, 64 ); -rndprc = rndsav; -nonorm: -toe24( xi, e ); -} - -static void toe24( x, y ) -unsigned short *x, *y; -{ -unsigned short i; -unsigned short *p; - -#ifdef NANS -if( eiisnan(x) ) - { - enan( y, 24 ); - return; - } -#endif -p = &x[0]; -#ifdef IBMPC -y += 1; -#endif -#ifdef DEC -y += 1; -#endif -*y = 0; /* output high order */ -if( *p++ ) - *y = 0x8000; /* output sign bit */ - -i = *p++; -if( i >= 255 ) - { /* Saturate at largest number less than infinity. */ -#ifdef INFINITY - *y |= (unsigned short )0x7f80; -#ifdef IBMPC - *(--y) = 0; -#endif -#ifdef DEC - *(--y) = 0; -#endif -#ifdef MIEEE - ++y; - *y = 0; -#endif -#else - *y |= (unsigned short )0x7f7f; -#ifdef IBMPC - *(--y) = 0xffff; -#endif -#ifdef DEC - *(--y) = 0xffff; -#endif -#ifdef MIEEE - ++y; - *y = 0xffff; -#endif -#endif - return; - } -if( i == 0 ) - { - (void )eshift( x, 7 ); - } -else - { - i <<= 7; - (void )eshift( x, 8 ); - } -i |= *p++ & (unsigned short )0x7f; /* *p = xi[M] */ -*y |= i; /* high order output already has sign bit set */ -#ifdef IBMPC -*(--y) = *p; -#endif -#ifdef DEC -*(--y) = *p; -#endif -#ifdef MIEEE -++y; -*y = *p; -#endif -} - - -/* Compare two e type numbers. - * - * unsigned short a[NE], b[NE]; - * ecmp( a, b ); - * - * returns +1 if a > b - * 0 if a == b - * -1 if a < b - * -2 if either a or b is a NaN. - */ -int ecmp( a, b ) -unsigned short *a, *b; -{ -unsigned short ai[NI], bi[NI]; -register unsigned short *p, *q; -register int i; -int msign; - -#ifdef NANS -if (eisnan (a) || eisnan (b)) - return( -2 ); -#endif -emovi( a, ai ); -p = ai; -emovi( b, bi ); -q = bi; - -if( *p != *q ) - { /* the signs are different */ -/* -0 equals + 0 */ - for( i=1; i<NI-1; i++ ) - { - if( ai[i] != 0 ) - goto nzro; - if( bi[i] != 0 ) - goto nzro; - } - return(0); -nzro: - if( *p == 0 ) - return( 1 ); - else - return( -1 ); - } -/* both are the same sign */ -if( *p == 0 ) - msign = 1; -else - msign = -1; -i = NI-1; -do - { - if( *p++ != *q++ ) - { - goto diff; - } - } -while( --i > 0 ); - -return(0); /* equality */ - - - -diff: - -if( *(--p) > *(--q) ) - return( msign ); /* p is bigger */ -else - return( -msign ); /* p is littler */ -} - - - - -/* Find nearest integer to x = floor( x + 0.5 ) - * - * unsigned short x[NE], y[NE] - * eround( x, y ); - */ -void eround( x, y ) -unsigned short *x, *y; -{ - -eadd( ehalf, x, y ); -efloor( y, y ); -} - - - - -/* -; convert long (32-bit) integer to e type -; -; long l; -; unsigned short x[NE]; -; ltoe( &l, x ); -; note &l is the memory address of l -*/ -void ltoe( lp, y ) -long *lp; /* lp is the memory address of a long integer */ -unsigned short *y; /* y is the address of a short */ -{ -unsigned short yi[NI]; -unsigned long ll; -int k; - -ecleaz( yi ); -if( *lp < 0 ) - { - ll = (unsigned long )( -(*lp) ); /* make it positive */ - yi[0] = 0xffff; /* put correct sign in the e type number */ - } -else - { - ll = (unsigned long )( *lp ); - } -/* move the long integer to yi significand area */ -if( sizeof(long) == 8 ) - { - yi[M] = (unsigned short) (ll >> (LONGBITS - 16)); - yi[M + 1] = (unsigned short) (ll >> (LONGBITS - 32)); - yi[M + 2] = (unsigned short) (ll >> 16); - yi[M + 3] = (unsigned short) ll; - yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */ - } -else - { - yi[M] = (unsigned short )(ll >> 16); - yi[M+1] = (unsigned short )ll; - yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */ - } -if( (k = enormlz( yi )) > NBITS ) /* normalize the significand */ - ecleaz( yi ); /* it was zero */ -else - yi[E] -= (unsigned short )k; /* subtract shift count from exponent */ -emovo( yi, y ); /* output the answer */ -} - -/* -; convert unsigned long (32-bit) integer to e type -; -; unsigned long l; -; unsigned short x[NE]; -; ltox( &l, x ); -; note &l is the memory address of l -*/ -void ultoe( lp, y ) -unsigned long *lp; /* lp is the memory address of a long integer */ -unsigned short *y; /* y is the address of a short */ -{ -unsigned short yi[NI]; -unsigned long ll; -int k; - -ecleaz( yi ); -ll = *lp; - -/* move the long integer to ayi significand area */ -if( sizeof(long) == 8 ) - { - yi[M] = (unsigned short) (ll >> (LONGBITS - 16)); - yi[M + 1] = (unsigned short) (ll >> (LONGBITS - 32)); - yi[M + 2] = (unsigned short) (ll >> 16); - yi[M + 3] = (unsigned short) ll; - yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */ - } -else - { - yi[M] = (unsigned short )(ll >> 16); - yi[M+1] = (unsigned short )ll; - yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */ - } -if( (k = enormlz( yi )) > NBITS ) /* normalize the significand */ - ecleaz( yi ); /* it was zero */ -else - yi[E] -= (unsigned short )k; /* subtract shift count from exponent */ -emovo( yi, y ); /* output the answer */ -} - - -/* -; Find long integer and fractional parts - -; long i; -; unsigned short x[NE], frac[NE]; -; xifrac( x, &i, frac ); - - The integer output has the sign of the input. The fraction is - the positive fractional part of abs(x). -*/ -void eifrac( x, i, frac ) -unsigned short *x; -long *i; -unsigned short *frac; -{ -unsigned short xi[NI]; -int j, k; -unsigned long ll; - -emovi( x, xi ); -k = (int )xi[E] - (EXONE - 1); -if( k <= 0 ) - { -/* if exponent <= 0, integer = 0 and real output is fraction */ - *i = 0L; - emovo( xi, frac ); - return; - } -if( k > (8 * sizeof(long) - 1) ) - { -/* -; long integer overflow: output large integer -; and correct fraction -*/ - j = 8 * sizeof(long) - 1; - if( xi[0] ) - *i = (long) ((unsigned long) 1) << j; - else - *i = (long) (((unsigned long) (~(0L))) >> 1); - (void )eshift( xi, k ); - } -if( k > 16 ) - { -/* - Shift more than 16 bits: shift up k-16 mod 16 - then shift by 16's. -*/ - j = k - ((k >> 4) << 4); - eshift (xi, j); - ll = xi[M]; - k -= j; - do - { - eshup6 (xi); - ll = (ll << 16) | xi[M]; - } - while ((k -= 16) > 0); - *i = ll; - if (xi[0]) - *i = -(*i); - } -else - { -/* shift not more than 16 bits */ - eshift( xi, k ); - *i = (long )xi[M] & 0xffff; - if( xi[0] ) - *i = -(*i); - } -xi[0] = 0; -xi[E] = EXONE - 1; -xi[M] = 0; -if( (k = enormlz( xi )) > NBITS ) - ecleaz( xi ); -else - xi[E] -= (unsigned short )k; - -emovo( xi, frac ); -} - - -/* -; Find unsigned long integer and fractional parts - -; unsigned long i; -; unsigned short x[NE], frac[NE]; -; xifrac( x, &i, frac ); - - A negative e type input yields integer output = 0 - but correct fraction. -*/ -void euifrac( x, i, frac ) -unsigned short *x; -unsigned long *i; -unsigned short *frac; -{ -unsigned short xi[NI]; -int j, k; -unsigned long ll; - -emovi( x, xi ); -k = (int )xi[E] - (EXONE - 1); -if( k <= 0 ) - { -/* if exponent <= 0, integer = 0 and argument is fraction */ - *i = 0L; - emovo( xi, frac ); - return; - } -if( k > (8 * sizeof(long)) ) - { -/* -; long integer overflow: output large integer -; and correct fraction -*/ - *i = ~(0L); - (void )eshift( xi, k ); - } -else if( k > 16 ) - { -/* - Shift more than 16 bits: shift up k-16 mod 16 - then shift up by 16's. -*/ - j = k - ((k >> 4) << 4); - eshift (xi, j); - ll = xi[M]; - k -= j; - do - { - eshup6 (xi); - ll = (ll << 16) | xi[M]; - } - while ((k -= 16) > 0); - *i = ll; - } -else - { -/* shift not more than 16 bits */ - eshift( xi, k ); - *i = (long )xi[M] & 0xffff; - } - -if( xi[0] ) /* A negative value yields unsigned integer 0. */ - *i = 0L; - -xi[0] = 0; -xi[E] = EXONE - 1; -xi[M] = 0; -if( (k = enormlz( xi )) > NBITS ) - ecleaz( xi ); -else - xi[E] -= (unsigned short )k; - -emovo( xi, frac ); -} - - - -/* -; Shift significand -; -; Shifts significand area up or down by the number of bits -; given by the variable sc. -*/ -int eshift( x, sc ) -unsigned short *x; -int sc; -{ -unsigned short lost; -unsigned short *p; - -if( sc == 0 ) - return( 0 ); - -lost = 0; -p = x + NI-1; - -if( sc < 0 ) - { - sc = -sc; - while( sc >= 16 ) - { - lost |= *p; /* remember lost bits */ - eshdn6(x); - sc -= 16; - } - - while( sc >= 8 ) - { - lost |= *p & 0xff; - eshdn8(x); - sc -= 8; - } - - while( sc > 0 ) - { - lost |= *p & 1; - eshdn1(x); - sc -= 1; - } - } -else - { - while( sc >= 16 ) - { - eshup6(x); - sc -= 16; - } - - while( sc >= 8 ) - { - eshup8(x); - sc -= 8; - } - - while( sc > 0 ) - { - eshup1(x); - sc -= 1; - } - } -if( lost ) - lost = 1; -return( (int )lost ); -} - - - -/* -; normalize -; -; Shift normalizes the significand area pointed to by argument -; shift count (up = positive) is returned. -*/ -int enormlz(x) -unsigned short x[]; -{ -register unsigned short *p; -int sc; - -sc = 0; -p = &x[M]; -if( *p != 0 ) - goto normdn; -++p; -if( *p & 0x8000 ) - return( 0 ); /* already normalized */ -while( *p == 0 ) - { - eshup6(x); - sc += 16; -/* With guard word, there are NBITS+16 bits available. - * return true if all are zero. - */ - if( sc > NBITS ) - return( sc ); - } -/* see if high byte is zero */ -while( (*p & 0xff00) == 0 ) - { - eshup8(x); - sc += 8; - } -/* now shift 1 bit at a time */ -while( (*p & 0x8000) == 0) - { - eshup1(x); - sc += 1; - if( sc > (NBITS+16) ) - { - mtherr( "enormlz", UNDERFLOW ); - return( sc ); - } - } -return( sc ); - -/* Normalize by shifting down out of the high guard word - of the significand */ -normdn: - -if( *p & 0xff00 ) - { - eshdn8(x); - sc -= 8; - } -while( *p != 0 ) - { - eshdn1(x); - sc -= 1; - - if( sc < -NBITS ) - { - mtherr( "enormlz", OVERFLOW ); - return( sc ); - } - } -return( sc ); -} - - - - -/* Convert e type number to decimal format ASCII string. - * The constants are for 64 bit precision. - */ - -#define NTEN 12 -#define MAXP 4096 - -#if NE == 10 -static unsigned short etens[NTEN + 1][NE] = -{ - {0x6576, 0x4a92, 0x804a, 0x153f, - 0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */ - {0x6a32, 0xce52, 0x329a, 0x28ce, - 0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */ - {0x526c, 0x50ce, 0xf18b, 0x3d28, - 0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,}, - {0x9c66, 0x58f8, 0xbc50, 0x5c54, - 0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,}, - {0x851e, 0xeab7, 0x98fe, 0x901b, - 0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,}, - {0x0235, 0x0137, 0x36b1, 0x336c, - 0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,}, - {0x50f8, 0x25fb, 0xc76b, 0x6b71, - 0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,}, - {0x0000, 0x0000, 0x0000, 0x0000, - 0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,}, - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,}, - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,}, - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,}, - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,}, - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */ -}; - -static unsigned short emtens[NTEN + 1][NE] = -{ - {0x2030, 0xcffc, 0xa1c3, 0x8123, - 0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */ - {0x8264, 0xd2cb, 0xf2ea, 0x12d4, - 0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */ - {0xf53f, 0xf698, 0x6bd3, 0x0158, - 0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,}, - {0xe731, 0x04d4, 0xe3f2, 0xd332, - 0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,}, - {0xa23e, 0x5308, 0xfefb, 0x1155, - 0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,}, - {0xe26d, 0xdbde, 0xd05d, 0xb3f6, - 0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,}, - {0x2a20, 0x6224, 0x47b3, 0x98d7, - 0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,}, - {0x0b5b, 0x4af2, 0xa581, 0x18ed, - 0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,}, - {0xbf71, 0xa9b3, 0x7989, 0xbe68, - 0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,}, - {0x3d4d, 0x7c3d, 0x36ba, 0x0d2b, - 0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,}, - {0xc155, 0xa4a8, 0x404e, 0x6113, - 0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,}, - {0xd70a, 0x70a3, 0x0a3d, 0xa3d7, - 0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,}, - {0xcccd, 0xcccc, 0xcccc, 0xcccc, - 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,}, /* 10**-1 */ -}; -#else -static unsigned short etens[NTEN+1][NE] = { -{0xc94c,0x979a,0x8a20,0x5202,0xc460,0x7525,},/* 10**4096 */ -{0xa74d,0x5de4,0xc53d,0x3b5d,0x9e8b,0x5a92,},/* 10**2048 */ -{0x650d,0x0c17,0x8175,0x7586,0xc976,0x4d48,}, -{0xcc65,0x91c6,0xa60e,0xa0ae,0xe319,0x46a3,}, -{0xddbc,0xde8d,0x9df9,0xebfb,0xaa7e,0x4351,}, -{0xc66f,0x8cdf,0x80e9,0x47c9,0x93ba,0x41a8,}, -{0x3cbf,0xa6d5,0xffcf,0x1f49,0xc278,0x40d3,}, -{0xf020,0xb59d,0x2b70,0xada8,0x9dc5,0x4069,}, -{0x0000,0x0000,0x0400,0xc9bf,0x8e1b,0x4034,}, -{0x0000,0x0000,0x0000,0x2000,0xbebc,0x4019,}, -{0x0000,0x0000,0x0000,0x0000,0x9c40,0x400c,}, -{0x0000,0x0000,0x0000,0x0000,0xc800,0x4005,}, -{0x0000,0x0000,0x0000,0x0000,0xa000,0x4002,}, /* 10**1 */ -}; - -static unsigned short emtens[NTEN+1][NE] = { -{0x2de4,0x9fde,0xd2ce,0x04c8,0xa6dd,0x0ad8,}, /* 10**-4096 */ -{0x4925,0x2de4,0x3436,0x534f,0xceae,0x256b,}, /* 10**-2048 */ -{0x87a6,0xc0bd,0xda57,0x82a5,0xa2a6,0x32b5,}, -{0x7133,0xd21c,0xdb23,0xee32,0x9049,0x395a,}, -{0xfa91,0x1939,0x637a,0x4325,0xc031,0x3cac,}, -{0xac7d,0xe4a0,0x64bc,0x467c,0xddd0,0x3e55,}, -{0x3f24,0xe9a5,0xa539,0xea27,0xa87f,0x3f2a,}, -{0x67de,0x94ba,0x4539,0x1ead,0xcfb1,0x3f94,}, -{0x4c2f,0xe15b,0xc44d,0x94be,0xe695,0x3fc9,}, -{0xfdc2,0xcefc,0x8461,0x7711,0xabcc,0x3fe4,}, -{0xd3c3,0x652b,0xe219,0x1758,0xd1b7,0x3ff1,}, -{0x3d71,0xd70a,0x70a3,0x0a3d,0xa3d7,0x3ff8,}, -{0xcccd,0xcccc,0xcccc,0xcccc,0xcccc,0x3ffb,}, /* 10**-1 */ -}; -#endif - -void e24toasc( x, string, ndigs ) -unsigned short x[]; -char *string; -int ndigs; -{ -unsigned short w[NI]; - -e24toe( x, w ); -etoasc( w, string, ndigs ); -} - - -void e53toasc( x, string, ndigs ) -unsigned short x[]; -char *string; -int ndigs; -{ -unsigned short w[NI]; - -e53toe( x, w ); -etoasc( w, string, ndigs ); -} - - -void e64toasc( x, string, ndigs ) -unsigned short x[]; -char *string; -int ndigs; -{ -unsigned short w[NI]; - -e64toe( x, w ); -etoasc( w, string, ndigs ); -} - -void e113toasc (x, string, ndigs) -unsigned short x[]; -char *string; -int ndigs; -{ -unsigned short w[NI]; - -e113toe (x, w); -etoasc (w, string, ndigs); -} - - -void etoasc( x, string, ndigs ) -unsigned short x[]; -char *string; -int ndigs; -{ -long digit; -unsigned short y[NI], t[NI], u[NI], w[NI]; -unsigned short *p, *r, *ten; -unsigned short sign; -int i, j, k, expon, rndsav; -char *s, *ss; -unsigned short m; - -rndsav = rndprc; -#ifdef NANS -if( eisnan(x) ) - { - sprintf( string, " NaN " ); - goto bxit; - } -#endif -rndprc = NBITS; /* set to full precision */ -emov( x, y ); /* retain external format */ -if( y[NE-1] & 0x8000 ) - { - sign = 0xffff; - y[NE-1] &= 0x7fff; - } -else - { - sign = 0; - } -expon = 0; -ten = &etens[NTEN][0]; -emov( eone, t ); -/* Test for zero exponent */ -if( y[NE-1] == 0 ) - { - for( k=0; k<NE-1; k++ ) - { - if( y[k] != 0 ) - goto tnzro; /* denormalized number */ - } - goto isone; /* legal all zeros */ - } -tnzro: - -/* Test for infinity. - */ -if( y[NE-1] == 0x7fff ) - { - if( sign ) - sprintf( string, " -Infinity " ); - else - sprintf( string, " Infinity " ); - goto bxit; - } - -/* Test for exponent nonzero but significand denormalized. - * This is an error condition. - */ -if( (y[NE-1] != 0) && ((y[NE-2] & 0x8000) == 0) ) - { - mtherr( "etoasc", DOMAIN ); - sprintf( string, "NaN" ); - goto bxit; - } - -/* Compare to 1.0 */ -i = ecmp( eone, y ); -if( i == 0 ) - goto isone; - -if( i < 0 ) - { /* Number is greater than 1 */ -/* Convert significand to an integer and strip trailing decimal zeros. */ - emov( y, u ); - u[NE-1] = EXONE + NBITS - 1; - - p = &etens[NTEN-4][0]; - m = 16; -do - { - ediv( p, u, t ); - efloor( t, w ); - for( j=0; j<NE-1; j++ ) - { - if( t[j] != w[j] ) - goto noint; - } - emov( t, u ); - expon += (int )m; -noint: - p += NE; - m >>= 1; - } -while( m != 0 ); - -/* Rescale from integer significand */ - u[NE-1] += y[NE-1] - (unsigned int )(EXONE + NBITS - 1); - emov( u, y ); -/* Find power of 10 */ - emov( eone, t ); - m = MAXP; - p = &etens[0][0]; - while( ecmp( ten, u ) <= 0 ) - { - if( ecmp( p, u ) <= 0 ) - { - ediv( p, u, u ); - emul( p, t, t ); - expon += (int )m; - } - m >>= 1; - if( m == 0 ) - break; - p += NE; - } - } -else - { /* Number is less than 1.0 */ -/* Pad significand with trailing decimal zeros. */ - if( y[NE-1] == 0 ) - { - while( (y[NE-2] & 0x8000) == 0 ) - { - emul( ten, y, y ); - expon -= 1; - } - } - else - { - emovi( y, w ); - for( i=0; i<NDEC+1; i++ ) - { - if( (w[NI-1] & 0x7) != 0 ) - break; -/* multiply by 10 */ - emovz( w, u ); - eshdn1( u ); - eshdn1( u ); - eaddm( w, u ); - u[1] += 3; - while( u[2] != 0 ) - { - eshdn1(u); - u[1] += 1; - } - if( u[NI-1] != 0 ) - break; - if( eone[NE-1] <= u[1] ) - break; - emovz( u, w ); - expon -= 1; - } - emovo( w, y ); - } - k = -MAXP; - p = &emtens[0][0]; - r = &etens[0][0]; - emov( y, w ); - emov( eone, t ); - while( ecmp( eone, w ) > 0 ) - { - if( ecmp( p, w ) >= 0 ) - { - emul( r, w, w ); - emul( r, t, t ); - expon += k; - } - k /= 2; - if( k == 0 ) - break; - p += NE; - r += NE; - } - ediv( t, eone, t ); - } -isone: -/* Find the first (leading) digit. */ -emovi( t, w ); -emovz( w, t ); -emovi( y, w ); -emovz( w, y ); -eiremain( t, y ); -digit = equot[NI-1]; -while( (digit == 0) && (ecmp(y,ezero) != 0) ) - { - eshup1( y ); - emovz( y, u ); - eshup1( u ); - eshup1( u ); - eaddm( u, y ); - eiremain( t, y ); - digit = equot[NI-1]; - expon -= 1; - } -s = string; -if( sign ) - *s++ = '-'; -else - *s++ = ' '; -/* Examine number of digits requested by caller. */ -if( ndigs < 0 ) - ndigs = 0; -if( ndigs > NDEC ) - ndigs = NDEC; -if( digit == 10 ) - { - *s++ = '1'; - *s++ = '.'; - if( ndigs > 0 ) - { - *s++ = '0'; - ndigs -= 1; - } - expon += 1; - } -else - { - *s++ = (char )digit + '0'; - *s++ = '.'; - } -/* Generate digits after the decimal point. */ -for( k=0; k<=ndigs; k++ ) - { -/* multiply current number by 10, without normalizing */ - eshup1( y ); - emovz( y, u ); - eshup1( u ); - eshup1( u ); - eaddm( u, y ); - eiremain( t, y ); - *s++ = (char )equot[NI-1] + '0'; - } -digit = equot[NI-1]; ---s; -ss = s; -/* round off the ASCII string */ -if( digit > 4 ) - { -/* Test for critical rounding case in ASCII output. */ - if( digit == 5 ) - { - emovo( y, t ); - if( ecmp(t,ezero) != 0 ) - goto roun; /* round to nearest */ - if( (*(s-1) & 1) == 0 ) - goto doexp; /* round to even */ - } -/* Round up and propagate carry-outs */ -roun: - --s; - k = *s & 0x7f; -/* Carry out to most significant digit? */ - if( k == '.' ) - { - --s; - k = *s; - k += 1; - *s = (char )k; -/* Most significant digit carries to 10? */ - if( k > '9' ) - { - expon += 1; - *s = '1'; - } - goto doexp; - } -/* Round up and carry out from less significant digits */ - k += 1; - *s = (char )k; - if( k > '9' ) - { - *s = '0'; - goto roun; - } - } -doexp: -/* -if( expon >= 0 ) - sprintf( ss, "e+%d", expon ); -else - sprintf( ss, "e%d", expon ); -*/ - sprintf( ss, "E%d", expon ); -bxit: -rndprc = rndsav; -} - - - - -/* -; ASCTOQ -; ASCTOQ.MAC LATEST REV: 11 JAN 84 -; SLM, 3 JAN 78 -; -; Convert ASCII string to quadruple precision floating point -; -; Numeric input is free field decimal number -; with max of 15 digits with or without -; decimal point entered as ASCII from teletype. -; Entering E after the number followed by a second -; number causes the second number to be interpreted -; as a power of 10 to be multiplied by the first number -; (i.e., "scientific" notation). -; -; Usage: -; asctoq( string, q ); -*/ - -/* ASCII to single */ -void asctoe24( s, y ) -char *s; -unsigned short *y; -{ -asctoeg( s, y, 24 ); -} - - -/* ASCII to double */ -void asctoe53( s, y ) -char *s; -unsigned short *y; -{ -#ifdef DEC -asctoeg( s, y, 56 ); -#else -asctoeg( s, y, 53 ); -#endif -} - - -/* ASCII to long double */ -void asctoe64( s, y ) -char *s; -unsigned short *y; -{ -asctoeg( s, y, 64 ); -} - -/* ASCII to 128-bit long double */ -void asctoe113 (s, y) -char *s; -unsigned short *y; -{ -asctoeg( s, y, 113 ); -} - -/* ASCII to super double */ -void asctoe( s, y ) -char *s; -unsigned short *y; -{ -asctoeg( s, y, NBITS ); -} - -/* Space to make a copy of the input string: */ -static char lstr[82] = {0}; - -void asctoeg( ss, y, oprec ) -char *ss; -unsigned short *y; -int oprec; -{ -unsigned short yy[NI], xt[NI], tt[NI]; -int esign, decflg, sgnflg, nexp, exp, prec, lost; -int k, trail, c, rndsav; -long lexp; -unsigned short nsign, *p; -char *sp, *s; - -/* Copy the input string. */ -s = ss; -while( *s == ' ' ) /* skip leading spaces */ - ++s; -sp = lstr; -for( k=0; k<79; k++ ) - { - if( (*sp++ = *s++) == '\0' ) - break; - } -*sp = '\0'; -s = lstr; - -rndsav = rndprc; -rndprc = NBITS; /* Set to full precision */ -lost = 0; -nsign = 0; -decflg = 0; -sgnflg = 0; -nexp = 0; -exp = 0; -prec = 0; -ecleaz( yy ); -trail = 0; - -nxtcom: -k = *s - '0'; -if( (k >= 0) && (k <= 9) ) - { -/* Ignore leading zeros */ - if( (prec == 0) && (decflg == 0) && (k == 0) ) - goto donchr; -/* Identify and strip trailing zeros after the decimal point. */ - if( (trail == 0) && (decflg != 0) ) - { - sp = s; - while( (*sp >= '0') && (*sp <= '9') ) - ++sp; -/* Check for syntax error */ - c = *sp & 0x7f; - if( (c != 'e') && (c != 'E') && (c != '\0') - && (c != '\n') && (c != '\r') && (c != ' ') - && (c != ',') ) - goto error; - --sp; - while( *sp == '0' ) - *sp-- = 'z'; - trail = 1; - if( *s == 'z' ) - goto donchr; - } -/* If enough digits were given to more than fill up the yy register, - * continuing until overflow into the high guard word yy[2] - * guarantees that there will be a roundoff bit at the top - * of the low guard word after normalization. - */ - if( yy[2] == 0 ) - { - if( decflg ) - nexp += 1; /* count digits after decimal point */ - eshup1( yy ); /* multiply current number by 10 */ - emovz( yy, xt ); - eshup1( xt ); - eshup1( xt ); - eaddm( xt, yy ); - ecleaz( xt ); - xt[NI-2] = (unsigned short )k; - eaddm( xt, yy ); - } - else - { - /* Mark any lost non-zero digit. */ - lost |= k; - /* Count lost digits before the decimal point. */ - if (decflg == 0) - nexp -= 1; - } - prec += 1; - goto donchr; - } - -switch( *s ) - { - case 'z': - break; - case 'E': - case 'e': - goto expnt; - case '.': /* decimal point */ - if( decflg ) - goto error; - ++decflg; - break; - case '-': - nsign = 0xffff; - if( sgnflg ) - goto error; - ++sgnflg; - break; - case '+': - if( sgnflg ) - goto error; - ++sgnflg; - break; - case ',': - case ' ': - case '\0': - case '\n': - case '\r': - goto daldone; - case 'i': - case 'I': - goto infinite; - default: - error: -#ifdef NANS - enan( yy, NI*16 ); -#else - mtherr( "asctoe", DOMAIN ); - ecleaz(yy); -#endif - goto aexit; - } -donchr: -++s; -goto nxtcom; - -/* Exponent interpretation */ -expnt: - -esign = 1; -exp = 0; -++s; -/* check for + or - */ -if( *s == '-' ) - { - esign = -1; - ++s; - } -if( *s == '+' ) - ++s; -while( (*s >= '0') && (*s <= '9') ) - { - exp *= 10; - exp += *s++ - '0'; - if (exp > 4977) - { - if (esign < 0) - goto zero; - else - goto infinite; - } - } -if( esign < 0 ) - exp = -exp; -if( exp > 4932 ) - { -infinite: - ecleaz(yy); - yy[E] = 0x7fff; /* infinity */ - goto aexit; - } -if( exp < -4977 ) - { -zero: - ecleaz(yy); - goto aexit; - } - -daldone: -nexp = exp - nexp; -/* Pad trailing zeros to minimize power of 10, per IEEE spec. */ -while( (nexp > 0) && (yy[2] == 0) ) - { - emovz( yy, xt ); - eshup1( xt ); - eshup1( xt ); - eaddm( yy, xt ); - eshup1( xt ); - if( xt[2] != 0 ) - break; - nexp -= 1; - emovz( xt, yy ); - } -if( (k = enormlz(yy)) > NBITS ) - { - ecleaz(yy); - goto aexit; - } -lexp = (EXONE - 1 + NBITS) - k; -emdnorm( yy, lost, 0, lexp, 64 ); -/* convert to external format */ - - -/* Multiply by 10**nexp. If precision is 64 bits, - * the maximum relative error incurred in forming 10**n - * for 0 <= n <= 324 is 8.2e-20, at 10**180. - * For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947. - * For 0 >= n >= -999, it is -1.55e-19 at 10**-435. - */ -lexp = yy[E]; -if( nexp == 0 ) - { - k = 0; - goto expdon; - } -esign = 1; -if( nexp < 0 ) - { - nexp = -nexp; - esign = -1; - if( nexp > 4096 ) - { /* Punt. Can't handle this without 2 divides. */ - emovi( etens[0], tt ); - lexp -= tt[E]; - k = edivm( tt, yy ); - lexp += EXONE; - nexp -= 4096; - } - } -p = &etens[NTEN][0]; -emov( eone, xt ); -exp = 1; -do - { - if( exp & nexp ) - emul( p, xt, xt ); - p -= NE; - exp = exp + exp; - } -while( exp <= MAXP ); - -emovi( xt, tt ); -if( esign < 0 ) - { - lexp -= tt[E]; - k = edivm( tt, yy ); - lexp += EXONE; - } -else - { - lexp += tt[E]; - k = emulm( tt, yy ); - lexp -= EXONE - 1; - } - -expdon: - -/* Round and convert directly to the destination type */ -if( oprec == 53 ) - lexp -= EXONE - 0x3ff; -else if( oprec == 24 ) - lexp -= EXONE - 0177; -#ifdef DEC -else if( oprec == 56 ) - lexp -= EXONE - 0201; -#endif -rndprc = oprec; -emdnorm( yy, k, 0, lexp, 64 ); - -aexit: - -rndprc = rndsav; -yy[0] = nsign; -switch( oprec ) - { -#ifdef DEC - case 56: - todec( yy, y ); /* see etodec.c */ - break; -#endif - case 53: - toe53( yy, y ); - break; - case 24: - toe24( yy, y ); - break; - case 64: - toe64( yy, y ); - break; - case 113: - toe113( yy, y ); - break; - case NBITS: - emovo( yy, y ); - break; - } -} - - - -/* y = largest integer not greater than x - * (truncated toward minus infinity) - * - * unsigned short x[NE], y[NE] - * - * efloor( x, y ); - */ -static unsigned short bmask[] = { -0xffff, -0xfffe, -0xfffc, -0xfff8, -0xfff0, -0xffe0, -0xffc0, -0xff80, -0xff00, -0xfe00, -0xfc00, -0xf800, -0xf000, -0xe000, -0xc000, -0x8000, -0x0000, -}; - -void efloor( x, y ) -unsigned short x[], y[]; -{ -register unsigned short *p; -int e, expon, i; -unsigned short f[NE]; - -emov( x, f ); /* leave in external format */ -expon = (int )f[NE-1]; -e = (expon & 0x7fff) - (EXONE - 1); -if( e <= 0 ) - { - eclear(y); - goto isitneg; - } -/* number of bits to clear out */ -e = NBITS - e; -emov( f, y ); -if( e <= 0 ) - return; - -p = &y[0]; -while( e >= 16 ) - { - *p++ = 0; - e -= 16; - } -/* clear the remaining bits */ -*p &= bmask[e]; -/* truncate negatives toward minus infinity */ -isitneg: - -if( (unsigned short )expon & (unsigned short )0x8000 ) - { - for( i=0; i<NE-1; i++ ) - { - if( f[i] != y[i] ) - { - esub( eone, y, y ); - break; - } - } - } -} - - -/* unsigned short x[], s[]; - * long *exp; - * - * efrexp( x, exp, s ); - * - * Returns s and exp such that s * 2**exp = x and .5 <= s < 1. - * For example, 1.1 = 0.55 * 2**1 - * Handles denormalized numbers properly using long integer exp. - */ -void efrexp( x, exp, s ) -unsigned short x[]; -long *exp; -unsigned short s[]; -{ -unsigned short xi[NI]; -long li; - -emovi( x, xi ); -li = (long )((short )xi[1]); - -if( li == 0 ) - { - li -= enormlz( xi ); - } -xi[1] = 0x3ffe; -emovo( xi, s ); -*exp = li - 0x3ffe; -} - - - -/* unsigned short x[], y[]; - * long pwr2; - * - * eldexp( x, pwr2, y ); - * - * Returns y = x * 2**pwr2. - */ -void eldexp( x, pwr2, y ) -unsigned short x[]; -long pwr2; -unsigned short y[]; -{ -unsigned short xi[NI]; -long li; -int i; - -emovi( x, xi ); -li = xi[1]; -li += pwr2; -i = 0; -emdnorm( xi, i, i, li, 64 ); -emovo( xi, y ); -} - - -/* c = remainder after dividing b by a - * Least significant integer quotient bits left in equot[]. - */ -void eremain( a, b, c ) -unsigned short a[], b[], c[]; -{ -unsigned short den[NI], num[NI]; - -#ifdef NANS -if( eisinf(b) || (ecmp(a,ezero) == 0) || eisnan(a) || eisnan(b)) - { - enan( c, NBITS ); - return; - } -#endif -if( ecmp(a,ezero) == 0 ) - { - mtherr( "eremain", SING ); - eclear( c ); - return; - } -emovi( a, den ); -emovi( b, num ); -eiremain( den, num ); -/* Sign of remainder = sign of quotient */ -if( a[0] == b[0] ) - num[0] = 0; -else - num[0] = 0xffff; -emovo( num, c ); -} - - -void eiremain( den, num ) -unsigned short den[], num[]; -{ -long ld, ln; -unsigned short j; - -ld = den[E]; -ld -= enormlz( den ); -ln = num[E]; -ln -= enormlz( num ); -ecleaz( equot ); -while( ln >= ld ) - { - if( ecmpm(den,num) <= 0 ) - { - esubm(den, num); - j = 1; - } - else - { - j = 0; - } - eshup1(equot); - equot[NI-1] |= j; - eshup1(num); - ln -= 1; - } -emdnorm( num, 0, 0, ln, 0 ); -} - -/* NaN bit patterns - */ -#ifdef MIEEE -unsigned short nan113[8] = { - 0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; -unsigned short nan64[6] = {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; -unsigned short nan53[4] = {0x7fff, 0xffff, 0xffff, 0xffff}; -unsigned short nan24[2] = {0x7fff, 0xffff}; -#endif - -#ifdef IBMPC -unsigned short nan113[8] = {0, 0, 0, 0, 0, 0, 0xc000, 0xffff}; -unsigned short nan64[6] = {0, 0, 0, 0xc000, 0xffff, 0}; -unsigned short nan53[4] = {0, 0, 0, 0xfff8}; -unsigned short nan24[2] = {0, 0xffc0}; -#endif - - -void enan (nan, size) -unsigned short *nan; -int size; -{ -int i, n; -unsigned short *p; - -switch( size ) - { -#ifndef DEC - case 113: - n = 8; - p = nan113; - break; - - case 64: - n = 6; - p = nan64; - break; - - case 53: - n = 4; - p = nan53; - break; - - case 24: - n = 2; - p = nan24; - break; - - case NBITS: - for( i=0; i<NE-2; i++ ) - *nan++ = 0; - *nan++ = 0xc000; - *nan++ = 0x7fff; - return; - - case NI*16: - *nan++ = 0; - *nan++ = 0x7fff; - *nan++ = 0; - *nan++ = 0xc000; - for( i=4; i<NI; i++ ) - *nan++ = 0; - return; -#endif - default: - mtherr( "enan", DOMAIN ); - return; - } -for (i=0; i < n; i++) - *nan++ = *p++; -} - - - -/* Longhand square root. */ - -static int esqinited = 0; -static unsigned short sqrndbit[NI]; - -void esqrt( x, y ) -short *x, *y; -{ -unsigned short temp[NI], num[NI], sq[NI], xx[NI]; -int i, j, k, n, nlups; -long m, exp; - -if( esqinited == 0 ) - { - ecleaz( sqrndbit ); - sqrndbit[NI-2] = 1; - esqinited = 1; - } -/* Check for arg <= 0 */ -i = ecmp( x, ezero ); -if( i <= 0 ) - { -#ifdef NANS - if (i == -2) - { - enan (y, NBITS); - return; - } -#endif - eclear(y); - if( i < 0 ) - mtherr( "esqrt", DOMAIN ); - return; - } - -#ifdef INFINITY -if( eisinf(x) ) - { - eclear(y); - einfin(y); - return; - } -#endif -/* Bring in the arg and renormalize if it is denormal. */ -emovi( x, xx ); -m = (long )xx[1]; /* local long word exponent */ -if( m == 0 ) - m -= enormlz( xx ); - -/* Divide exponent by 2 */ -m -= 0x3ffe; -exp = (unsigned short )( (m / 2) + 0x3ffe ); - -/* Adjust if exponent odd */ -if( (m & 1) != 0 ) - { - if( m > 0 ) - exp += 1; - eshdn1( xx ); - } - -ecleaz( sq ); -ecleaz( num ); -n = 8; /* get 8 bits of result per inner loop */ -nlups = rndprc; -j = 0; - -while( nlups > 0 ) - { -/* bring in next word of arg */ - if( j < NE ) - num[NI-1] = xx[j+3]; -/* Do additional bit on last outer loop, for roundoff. */ - if( nlups <= 8 ) - n = nlups + 1; - for( i=0; i<n; i++ ) - { -/* Next 2 bits of arg */ - eshup1( num ); - eshup1( num ); -/* Shift up answer */ - eshup1( sq ); -/* Make trial divisor */ - for( k=0; k<NI; k++ ) - temp[k] = sq[k]; - eshup1( temp ); - eaddm( sqrndbit, temp ); -/* Subtract and insert answer bit if it goes in */ - if( ecmpm( temp, num ) <= 0 ) - { - esubm( temp, num ); - sq[NI-2] |= 1; - } - } - nlups -= n; - j += 1; - } - -/* Adjust for extra, roundoff loop done. */ -exp += (NBITS - 1) - rndprc; - -/* Sticky bit = 1 if the remainder is nonzero. */ -k = 0; -for( i=3; i<NI; i++ ) - k |= (int )num[i]; - -/* Renormalize and round off. */ -emdnorm( sq, k, 0, exp, 64 ); -emovo( sq, y ); -} diff --git a/test/math/ieetst.c b/test/math/ieetst.c deleted file mode 100644 index 8c2453898..000000000 --- a/test/math/ieetst.c +++ /dev/null @@ -1,850 +0,0 @@ -/* Floating point to ASCII input and output string test program. - * - * Numbers in the native machine data structure are converted - * to e type, then to and from decimal ASCII strings. Native - * printf() and scanf() functions are also used to produce - * and read strings. The resulting e type binary values - * are compared, with diagnostic printouts of any discrepancies. - * - * Steve Moshier, 16 Dec 88 - * last revision: 16 May 92 - */ - -#include "ehead.h" -#include "mconf.h" - -/* Include tests of 80-bit long double precision: */ -#define LDOUBLE 0 -/* Abort subtest after getting this many errors: */ -#define MAXERR 5 -/* Number of random arguments to try (set as large as you have - * patience for): */ -#define NRAND 100 -/* Perform internal consistency test: */ -#define CHKINTERNAL 0 - -static unsigned short fullp[NE], rounded[NE]; -float prec24, sprec24, ssprec24; -double prec53, sprec53, ssprec53; -#if LDOUBLE -long double prec64, sprec64, ssprec64; -#endif - -static unsigned short rprint[NE], rscan[NE]; -static unsigned short q1[NE], q2[NE], q5[NE]; -static unsigned short e1[NE], e2[NE], e3[NE]; -static double d1, d2; -static int errprint = 0; -static int errscan = 0; -static int identerr = 0; -static int errtot = 0; -static int count = 0; -static char str0[80], str1[80], str2[80], str3[80]; -static unsigned short eten[NE], maxm[NE]; - -int m, n, k2, mprec, SPREC; - -char *Ten = "10.0"; -char tformat[10]; -char *format24 = "%.8e"; -#ifdef DEC -char *format53 = "%.17e"; -#else -char *format53 = "%.16e"; -#endif -char *fformat24 = "%e"; -char *fformat53 = "%le"; -char *pct = "%"; -char *quo = "\042"; -#if LDOUBLE -char *format64 = "%.20Le"; -char *fformat64 = "%Le"; -#endif -char *format; -char *fformat; -char *toomany = "Too many errors; aborting this test.\n"; - -static int mnrflag; -static int etrflag; -void chkit(), printerr(), mnrand(), etrand(), shownoncrit(); -void chkid(), pvec(); - -main() -{ -int i, iprec; - -printf( "Steve Moshier's printf/scanf tester, version 0.2.\n\n" ); -#ifdef DEC - /* DEC PDP-11/VAX single precision not yet implemented */ -for( iprec = 1; iprec<2; iprec++ ) -#else -for( iprec = 0; iprec<3; iprec++ ) -#endif - { - errscan = 0; - identerr = 0; - errprint = 0; - eclear( rprint ); - eclear( rscan ); - -switch( iprec ) - { - case 0: - SPREC = 8; /* # digits after the decimal point */ - mprec = 24; /* # bits in the significand */ - m = 9; /* max # decimal digits for correct rounding */ - n = 13; /* max power of ten for correct rounding */ - k2 = -125; /* underflow beyond 2^-k2 */ - format = format24; /* printf format string */ - fformat = fformat24; /* scanf format string */ - mnrflag = 1; /* sets interval for random numbers */ - etrflag = 1; - printf( "Testing FLOAT precision.\n" ); - break; - - case 1: -#ifdef DEC - SPREC = 17; - mprec = 56; - m = 17; - n = 27; - k2 = -125; - format = format53; - fformat = fformat53; - mnrflag = 2; - etrflag = 1; - printf( "Testing DEC DOUBLE precision.\n" ); - break; -#else - SPREC = 16; - mprec = 53; - m = 17; - n = 27; - k2 = -1021; - format = format53; - fformat = fformat53; - mnrflag = 2; - etrflag = 2; - printf( "Testing DOUBLE precision.\n" ); - break; -#endif - case 2: -#if LDOUBLE - SPREC = 20; - mprec = 64; - m = 20; - n = 34; - k2 = -16382; - format = format64; - fformat = fformat64; - mnrflag = 3; - etrflag = 3; - printf( "Testing LONG DOUBLE precision.\n" ); - break; -#else - goto nodenorm; -#endif - } - - asctoe( Ten, eten ); -/* 10^m - 1 */ - d2 = m; - e53toe( &d2, e1 ); - epow( eten, e1, maxm ); - esub( eone, maxm, maxm ); - -/* test 1 */ - printf( "1. Checking 10^n - 1 for n = %d to %d.\n", -m, m ); - emov( eone, q5 ); - for( count=0; count<=m; count++ ) - { - esub( eone, q5, fullp ); - chkit( 1 ); - ediv( q5, eone, q2 ); - esub( eone, q2, fullp ); - chkit( 1 ); - emul( eten, q5, q5 ); - if( errtot >= MAXERR ) - { - printf( "%s", toomany ); - goto end1; - } - } -end1: - printerr(); - - -/* test 2 */ - printf( "2. Checking powers of 10 from 10^-%d to 10^%d.\n", n, n ); - emov( eone, q5 ); - for( count=0; count<=n; count++ ) - { - emov( q5, fullp ); - chkit( 2 ); - ediv( q5, eone, fullp ); - chkit( 2 ); - emul( eten, q5, q5 ); - if( errtot >= MAXERR ) - { - printf( "%s", toomany ); - goto end2; - } - } -end2: - printerr(); - -/* test 3 */ - printf( "3. Checking (10^%d-1)*10^n from n = -%d to %d.\n", m, n, n ); - emov( eone, q5 ); - for( count= -n; count<=n; count++ ) - { - emul( maxm, q5, fullp ); - chkit( 3 ); - emov( q5, fullp ); - ediv( fullp, eone, fullp ); - emul( maxm, fullp, fullp ); - chkit( 3 ); - emul( eten, q5, q5 ); - if( errtot >= MAXERR ) - { - printf( "%s", toomany ); - goto end3; - } - } -end3: - printerr(); - - - -/* test 4 */ - printf( "4. Checking powers of 2 from 2^-24 to 2^+56.\n" ); - d1 = -24.0; - e53toe( &d1, q1 ); - epow( etwo, q1, q5 ); - - for( count = -24; count <= 56; count++ ) - { - emov( q5, fullp ); - chkit( 4 ); - emul( etwo, q5, q5 ); - if( errtot >= MAXERR ) - { - printf( "%s", toomany ); - goto end4; - } - } -end4: - printerr(); - - -/* test 5 */ - printf( "5. Checking 2^n - 1 for n = 0 to %d.\n", mprec ); - emov( eone, q5 ); - for( count=0; count<=mprec; count++ ) - { - esub( eone, q5, fullp ); - chkit( 5 ); - emul( etwo, q5, q5 ); - if( errtot >= MAXERR ) - { - printf( "%s", toomany ); - goto end5; - } - } -end5: - printerr(); - -/* test 6 */ - printf( "6. Checking 2^n + 1 for n = 0 to %d.\n", mprec ); - emov( eone, q5 ); - for( count=0; count<=mprec; count++ ) - { - eadd( eone, q5, fullp ); - chkit( 6 ); - emul( etwo, q5, q5 ); - if( errtot >= MAXERR ) - { - printf( "%s", toomany ); - goto end6; - } - } -end6: - printerr(); - -/* test 7 */ - printf( - "7. Checking %d values M * 10^N with random integer M and N,\n", - NRAND ); - printf(" 1 <= M <= 10^%d - 1 and -%d <= N <= +%d.\n", m, n, n ); - for( i=0; i<NRAND; i++ ) - { - mnrand( fullp ); - chkit( 7 ); - if( errtot >= MAXERR ) - { - printf( "%s", toomany ); - goto end7; - } - } -end7: - printerr(); - -/* test 8 */ - printf("8. Checking critical rounding cases.\n" ); - for( i=0; i<20; i++ ) - { - mnrand( fullp ); - eabs( fullp ); - if( ecmp( fullp, eone ) < 0 ) - ediv( fullp, eone, fullp ); - efloor( fullp, fullp ); - eadd( ehalf, fullp, fullp ); - chkit( 8 ); - if( errtot >= MAXERR ) - { - printf( "%s", toomany ); - goto end8; - } - } -end8: - printerr(); - - - -/* test 9 */ - printf("9. Testing on %d random non-denormal values.\n", NRAND ); - for( i=0; i<NRAND; i++ ) - { - etrand( fullp ); - chkit( 9 ); - } - printerr(); - shownoncrit(); - -/* test 10 */ - printf( - "Do you want to check denormal numbers in this precision ? (y/n) " ); - gets( str0 ); - if( str0[0] != 'y' ) - goto nodenorm; - - printf( "10. Checking denormal numbers.\n" ); - -/* Form 2^-starting power */ - d1 = k2; - e53toe( &d1, q1 ); - epow( etwo, q1, e1 ); - -/* Find 2^-mprec less than starting power */ - d1 = -mprec + 4; - e53toe( &d1, q1 ); - epow( etwo, q1, e3 ); - emul( e1, e3, e3 ); - emov( e3, e2 ); - ediv( etwo, e2, e2 ); - - while( ecmp(e1,e2) != 0 ) - { - eadd( e1, e2, fullp ); - switch( mprec ) - { -#if LDOUBLE - case 64: - etoe64( e1, &sprec64 ); - e64toe( &sprec64, q1 ); - etoe64( fullp, &prec64 ); - e64toe( &prec64, q2 ); - break; -#endif -#ifdef DEC - case 56: -#endif - case 53: - etoe53( e1, &sprec53 ); - e53toe( &sprec53, q1 ); - etoe53( fullp, &prec53 ); - e53toe( &prec53, q2 ); - break; - - case 24: - etoe24( e1, &sprec24 ); - e24toe( &sprec24, q1 ); - etoe24( fullp, &prec24 ); - e24toe( &prec24, q2 ); - break; - } - if( ecmp( q2, ezero ) == 0 ) - goto maxden; - chkit(10); - if( ecmp(q1,q2) == 0 ) - { - ediv( etwo, e1, e1 ); - emov( e3, e2 ); - } - if( errtot >= MAXERR ) - { - printf( "%s", toomany ); - goto maxden; - } - ediv( etwo, e2, e2 ); - } -maxden: - printerr(); -nodenorm: - printf( "\n" ); - } /* loop on precision */ -printf( "End of test.\n" ); -} - -#if CHKINTERNAL -long double xprec64; -double xprec53; -float xprec24; - -/* Check binary -> printf -> scanf -> binary identity - * of internal routines - */ -void chkinternal( ref, tst, string ) -unsigned short ref[], tst[]; -char *string; -{ - -if( ecmp(ref,tst) != 0 ) - { - printf( "internal identity compare error!\n" ); - chkid( ref, tst, string ); - } -} -#endif - - -/* Check binary -> printf -> scanf -> binary identity - */ -void chkid( print, scan, string ) -unsigned short print[], scan[]; -char *string; -{ -/* Test printf-scanf identity */ -if( ecmp( print, scan ) != 0 ) - { - pvec( print, NE ); - printf( " ->printf-> %s ->scanf->\n", string ); - pvec( scan, NE ); - printf( " is not an identity.\n" ); - ++identerr; - } -} - - -/* Check scanf result - */ -void chkscan( ref, tst, string ) -unsigned short ref[], tst[]; -char *string; -{ -/* Test scanf() */ -if( ecmp( ref, tst ) != 0 ) - { - printf( "scanf(%s) -> ", string ); - pvec( tst, NE ); - printf( "\n should be " ); - pvec( ref, NE ); - printf( ".\n" ); - ++errscan; - ++errtot; - } -} - - -/* Test printf() result - */ -void chkprint( ref, tst, string ) -unsigned short ref[], tst[]; -char *string; -{ -if( ecmp(ref, tst) != 0 ) - { - printf( "printf( "); - pvec( ref, NE ); - printf( ") -> %s\n", string ); - printf( " = " ); - pvec( tst, NE ); - printf( ".\n" ); - ++errprint; - ++errtot; - } -} - - -/* Print array of n 16-bit shorts - */ -void pvec( x, n ) -unsigned short x[]; -int n; -{ -int i; - -for( i=0; i<n; i++ ) - { - printf( "%04x ", x[i] ); - } -} - -/* Measure worst case printf rounding error - */ -void cmpprint( ref, tst ) -unsigned short ref[], tst[]; -{ -unsigned short e[NE]; - -if( ecmp( ref, ezero ) != 0 ) - { - esub( ref, tst, e ); - ediv( ref, e, e ); - eabs( e ); - if( ecmp( e, rprint ) > 0 ) - emov( e, rprint ); - } -} - -/* Measure worst case scanf rounding error - */ -void cmpscan( ref, tst ) -unsigned short ref[], tst[]; -{ -unsigned short er[NE]; - -if( ecmp( ref, ezero ) != 0 ) - { - esub( ref, tst, er ); - ediv( ref, er, er ); - eabs( er ); - if( ecmp( er, rscan ) > 0 ) - emov( er, rscan ); - if( ecmp( er, ehalf ) > 0 ) - { - etoasc( tst, str1, 21 ); - printf( "Bad error: scanf(%s) = %s !\n", str0, str1 ); - } - } -} - -/* Check rounded-down decimal string output of printf - */ -void cmptrunc( ref, tst ) -unsigned short ref[], tst[]; -{ -if( ecmp( ref, tst ) != 0 ) - { - printf( "printf(%s%s%s, %s) -> %s\n", quo, tformat, quo, str1, str2 ); - printf( "should be %s .\n", str3 ); - errprint += 1; - } -} - - -void shownoncrit() -{ - -etoasc( rprint, str0, 3 ); -printf( "Maximum relative printf error found = %s .\n", str0 ); -etoasc( rscan, str0, 3 ); -printf( "Maximum relative scanf error found = %s .\n", str0 ); -} - - - -/* Produce arguments and call comparison subroutines. - */ -void chkit( testno ) -int testno; -{ -unsigned short t[NE], u[NE], v[NE]; -int j; - -switch( mprec ) - { -#if LDOUBLE - case 64: - etoe64( fullp, &prec64 ); - e64toe( &prec64, rounded ); -#if CHKINTERNAL - e64toasc( &prec64, str1, SPREC ); - asctoe64( str1, &xprec64 ); - e64toe( &xprec64, t ); - chkinternal( rounded, t, str1 ); -#endif -/* check printf and scanf */ - sprintf( str2, format, prec64 ); - sscanf( str2, fformat, &sprec64 ); - e64toe( &sprec64, u ); - chkid( rounded, u, str2 ); - asctoe64( str2, &ssprec64 ); - e64toe( &ssprec64, v ); - chkscan( v, u, str2 ); - chkprint( rounded, v, str2 ); - if( testno < 8 ) - break; -/* rounding error measurement */ - etoasc( fullp, str0, 24 ); - etoe64( fullp, &ssprec64 ); - e64toe( &ssprec64, u ); - sprintf( str2, format, ssprec64 ); - asctoe( str2, t ); - cmpprint( u, t ); - sscanf( str0, fformat, &sprec64 ); - e64toe( &sprec64, t ); - cmpscan( fullp, t ); - if( testno < 8 ) - break; -/* strings rounded to less than maximum precision */ - e64toasc( &ssprec64, str1, 24 ); - for( j=SPREC-1; j>0; j-- ) - { - e64toasc( &ssprec64, str3, j ); - asctoe( str3, v ); - sprintf( tformat, "%s.%dLe", pct, j ); - sprintf( str2, tformat, ssprec64 ); - asctoe( str2, t ); - cmptrunc( v, t ); - } - break; -#endif -#ifdef DEC - case 56: -#endif - case 53: - etoe53( fullp, &prec53 ); - e53toe( &prec53, rounded ); -#if CHKINTERNAL - e53toasc( &prec53, str1, SPREC ); - asctoe53( str1, &xprec53 ); - e53toe( &xprec53, t ); - chkinternal( rounded, t, str1 ); -#endif - sprintf( str2, format, prec53 ); - sscanf( str2, fformat, &sprec53 ); - e53toe( &sprec53, u ); - chkid( rounded, u, str2 ); - asctoe53( str2, &ssprec53 ); - e53toe( &ssprec53, v ); - chkscan( v, u, str2 ); - chkprint( rounded, v, str2 ); - if( testno < 8 ) - break; -/* rounding error measurement */ - etoasc( fullp, str0, 24 ); - etoe53( fullp, &ssprec53 ); - e53toe( &ssprec53, u ); - sprintf( str2, format, ssprec53 ); - asctoe( str2, t ); - cmpprint( u, t ); - sscanf( str0, fformat, &sprec53 ); - e53toe( &sprec53, t ); - cmpscan( fullp, t ); - if( testno < 8 ) - break; - e53toasc( &ssprec53, str1, 24 ); - for( j=SPREC-1; j>0; j-- ) - { - e53toasc( &ssprec53, str3, j ); - asctoe( str3, v ); - sprintf( tformat, "%s.%de", pct, j ); - sprintf( str2, tformat, ssprec53 ); - asctoe( str2, t ); - cmptrunc( v, t ); - } - break; - - case 24: - etoe24( fullp, &prec24 ); - e24toe( &prec24, rounded ); -#if CHKINTERNAL - e24toasc( &prec24, str1, SPREC ); - asctoe24( str1, &xprec24 ); - e24toe( &xprec24, t ); - chkinternal( rounded, t, str1 ); -#endif - sprintf( str2, format, prec24 ); - sscanf( str2, fformat, &sprec24 ); - e24toe( &sprec24, u ); - chkid( rounded, u, str2 ); - asctoe24( str2, &ssprec24 ); - e24toe( &ssprec24, v ); - chkscan( v, u, str2 ); - chkprint( rounded, v, str2 ); - if( testno < 8 ) - break; -/* rounding error measurement */ - etoasc( fullp, str0, 24 ); - etoe24( fullp, &ssprec24 ); - e24toe( &ssprec24, u ); - sprintf( str2, format, ssprec24 ); - asctoe( str2, t ); - cmpprint( u, t ); - sscanf( str0, fformat, &sprec24 ); - e24toe( &sprec24, t ); - cmpscan( fullp, t ); -/* - if( testno < 8 ) - break; -*/ - e24toasc( &ssprec24, str1, 24 ); - for( j=SPREC-1; j>0; j-- ) - { - e24toasc( &ssprec24, str3, j ); - asctoe( str3, v ); - sprintf( tformat, "%s.%de", pct, j ); - sprintf( str2, tformat, ssprec24 ); - asctoe( str2, t ); - cmptrunc( v, t ); - } - break; - } -} - - -void printerr() -{ -if( (errscan == 0) && (identerr == 0) && (errprint == 0) ) - printf( "No errors found.\n" ); -else - { - printf( "%d binary -> decimal errors found.\n", errprint ); - printf( "%d decimal -> binary errors found.\n", errscan ); - } -errscan = 0; /* reset for next test */ -identerr = 0; -errprint = 0; -errtot = 0; -} - - -/* Random number generator - * in the range M * 10^N, where 1 <= M <= 10^17 - 1 - * and -27 <= N <= +27. Test values of M are logarithmically distributed - * random integers; test values of N are uniformly distributed random integers. - */ - -static char *fwidth = "1.036163291797320557783096e1"; /* log(sqrt(10^9-1)) */ -static char *dwidth = "1.957197329044938830915E1"; /* log(sqrt(10^17-1)) */ -static char *ldwidth = "2.302585092994045684017491e1"; /* log(sqrt(10^20-1)) */ - -static char *a13 = "13.0"; -static char *a27 = "27.0"; -static char *a34 = "34.0"; -static char *a10m13 = "1.0e-13"; -static unsigned short LOW[ NE ], WIDTH[NE], e27[NE], e10m13[NE]; - - -void mnrand( erand ) -unsigned short erand[]; -{ -unsigned short ea[NE], em[NE], en[NE], ex[NE]; -double x, a; - -if( mnrflag ) - { - if( mnrflag == 3 ) - { - asctoe( ldwidth, WIDTH ); - asctoe( a34, e27 ); - } - if( mnrflag == 2 ) - { - asctoe( dwidth, WIDTH ); - asctoe( a27, e27 ); - } - if( mnrflag == 1 ) - { - asctoe( fwidth, WIDTH ); - asctoe( a13, e27 ); - } - asctoe( a10m13, e10m13 ); - mnrflag = 0; - } -drand( &x ); -e53toe( &x, ex ); /* x = WIDTH * ( x - 1.0 ) + LOW; */ -esub( eone, ex, ex ); -emul( WIDTH, ex, ex ); -eexp( ex, ex ); /* x = exp(x); */ - -drand( &a ); -e53toe( &a, ea ); -emul( ea, ex, ea ); /* a = 1.0e-13 * x * a; */ -emul( e10m13, ea, ea ); -eabs( ea ); -eadd( ea, ex, ex ); /* add fuzz */ -emul( ex, ex, ex ); /* square it, to get range to 10^17 - 1 */ -efloor( ex, em ); /* this is M */ - -/* Random power of 10 */ -drand( &a ); -e53toe( &a, ex ); -esub( eone, ex, ex ); /* y3 = 54.0 * ( y3 - 1.0 ) + 0.5; */ -emul( e27, ex, ex ); -eadd( ex, ex, ex ); -eadd( ehalf, ex, ex ); -efloor( ex, ex ); /* y3 = floor( y3 ) - 27.0; */ -esub( e27, ex, en ); /* this is N */ -epow( eten, en, ex ); -emul( ex, em, erand ); -} - -/* -ln 2^16382 */ -char *ldemin = "-1.1355137111933024058873097E4"; -char *ldewid = "2.2710274223866048117746193E4"; -/* -ln 2^1022 */ -char *demin = "-7.0839641853226410622441123E2"; -char *dewid = "1.4167928370645282124488225E3"; -/* -ln 2^125 */ -char *femin = "-8.6643397569993163677154015E1"; -char *fewid = "1.7328679513998632735430803E2"; - -void etrand( erand ) -unsigned short erand[]; -{ -unsigned short ea[NE], ex[NE]; -double x, a; - -if( etrflag ) - { - if( etrflag == 3 ) - { - asctoe( ldemin, LOW ); - asctoe( ldewid, WIDTH ); - asctoe( a34, e27 ); - } - if( etrflag == 2 ) - { - asctoe( demin, LOW ); - asctoe( dewid, WIDTH ); - asctoe( a27, e27 ); - } - if( etrflag == 1 ) - { - asctoe( femin, LOW ); - asctoe( fewid, WIDTH ); - asctoe( a13, e27 ); - } - asctoe( a10m13, e10m13 ); - etrflag = 0; - } -drand( &x ); -e53toe( &x, ex ); /* x = WIDTH * ( x - 1.0 ) + LOW; */ -esub( eone, ex, ex ); -emul( WIDTH, ex, ex ); -eadd( LOW, ex, ex ); -eexp( ex, ex ); /* x = exp(x); */ - -/* add fuzz - */ -drand( &a ); -e53toe( &a, ea ); -emul( ea, ex, ea ); /* a = 1.0e-13 * x * a; */ -emul( e10m13, ea, ea ); -if( ecmp( ex, ezero ) > 0 ) - eneg( ea ); -eadd( ea, ex, erand ); -} - diff --git a/test/math/ieetst.doc b/test/math/ieetst.doc deleted file mode 100644 index bd5134beb..000000000 --- a/test/math/ieetst.doc +++ /dev/null @@ -1,132 +0,0 @@ - - ieetst, version 0.2 - - This software tests the numerical accuracy of floating point -binary <-> decimal string conversion, as done by your C language -library functions printf() and scanf(), for compliance with the -IEEE arithmetic standards ANSI/IEEE Std 754-1985 and ANSI/IEEE -Std 854-1987. The test covers 32-bit float, 64-bit double, and -80-bit long double precision conversions to and from decimal -ASCII strings. - - The test program checks for proper implementation of the -following specifications of the standards: - - (1) correctly rounded conversions of numbers of the form M * - 10^N, where M and N are integers such that, in double precision, - for example, |M| < 10^17, |N| <= 27. - - (2) binary -> decimal -> binary conversions to be an identity - if a sufficiently large number of decimal digits is requested. - - (3) correctly rounded decimal outputs of less than the maximum - number of digits - - (4) The maximum observed conversion error of numbers outside the - domain covered by (1) is reported by the test program; it is - not supposed to exceed 0.97 ulp. - -There are 10 separate tests. Tests 1 through 6 use values near -2^n and 10^n. Test 7 addresses item (1) above. Test 8 checks -the rounding of exact half-integer numbers. Test 9 is for item -(4) above. Test 10 checks denormal numbers. Tests 8 through 10 -address item (3) using printf formats that produce outputs of 1, -2, 3, ... digits after the decimal point. All tests check, when -appropriate, that the binary output of scanf is the same as the -binary input to printf, item (2). - -Example error messages: - - 0000 0000 0000 1000 8000 3f80 ->printf-> 5.87748296e-39 ->scanf-> - 0000 0000 0000 0000 8000 3f6e is not an identity. - - scanf(-9.9999900000000003e-01) -> 0000 4800 085f ef39 ffff bffe - should be 0000 5000 085f ef39 ffff bffe . - - printf("%.14e", 6.13592315154256467968352E-3) -> 6.13592315154257e-03 - should be 6.13592315154256E-3 . - -Binary values are displayed as four-digit hex groups in the -little-endian format of the internal reference arithmetic. The -least significant 16-bit word is first, the exponent is last. - - The design of the test program requires knowing the binary -data structure of the floating point format under test. For -configuration, check the .h files carefully. All the programs -need to be told via mconf.h if the numeric format is -little-endian (IBMPC) or big-endian (MIEEE). If your system -supports an 80-bit long double precision data type, define -LDOUBLE 1 in ieetst.c; otherwise define LDOUBLE 0. A provision -for DEC PDP-11/VAX numbers is implemented (double precision -only). Conversions for other data structures can be added by -analogy to the ifdefs for DEC. - - Most of the tests rely on comparison with the results of a -portable reference arithmetic, contained in the file ieee.c. -This is configured for an 80-bit significand, to have enough -precision to satisfy the conversion requirements of IEEE 854 for -the extended double format of IEEE 754. The reference arithmetic -includes binary <--> ASCII conversion routines and single <--> -double <--> extended double conversions. A strictly rounded -square root function is given in esqrt.c. Additional functions -are provided by elog.c, eexp.c, etanh.c, epow.c, all of which -call on ieee.c for their arithmetic. Some of the ANSI C -functions are supplied in ieee.c; for example, efloor(), -efrexp(), eldexp(). The functions and the reference arithmetic -are described further in the book _Methods and Programs for -Mathematical Functions_ (Prentice-Hall or Simon & Schuster -International, 1989), by S. L. Moshier. - - As an aid in diagnosis, a calculator program, ecalc.c, is -supplied. It uses ieee.c for its arithmetic. Documentation for -the calculator's user interface is in the file calc100.doc -(calc100 is a fuller featured 100-digit version of ecalc). The -calculator needs to be told by qcalc.h if addresses are 32 bits -long (define LARGEMEM 1) or 16 bits long (define LARGEMEM 0). - - Because the source code of ieee.c is included here, a version -of W. Kahan's PARANOIA is also provided; this has been heavily -modified by substituting subroutine calls to ieee.c in place of -all arithmetic operators. It is important that you use PARANOIA -to check the arithmetic after any modifications you may make to -ieee.c. - - Several systems have been tested with the initial version of -ieetst. Sun 4 (SPARC) passes; DEC VMS C has only a small flaw; -Microsoft flunks; ATT SysVR2 (Motorola) flunks even worse. - - - Files: - -calc100.doc calculator documentaton -descrip.mms part of VAX VMS makefile -drand.c random number generator -ecalc.c calculator -ecalc.opt part of VAX VMS makefile -econst.c constants for reference arithmetic -eexp.c reference exponential function -ehead.h declarations for reference arithmetic routines -elog.c reference logarithm -eparanoi.c floating point arithmetic tester -eparanoi.opt part of VAX VMS makefile -epow.c reference exponentiation -esqrt.c reference square root -etanh.c reference hyperbolic tangent -etodec.c conversions to and from DEC double precision format -ieee.c the reference arithmetic -ieetst.c printf/scanf tester -ieetst.doc this file -ieetst.mak Microsoft make file -ieetst.opt part of VAX VMS makefile -makefile Unix make file -mconf.h definitions for arithmetic format -mtherr.c common error reporter -qcalc.h definitions for calculator - - -This software may be copied freely. - --- Steve Moshier - -v0.1 July, 1992 -v0.2 January, 1993 diff --git a/test/math/libm-test.inc b/test/math/libm-test.inc new file mode 100644 index 000000000..a0d08cefb --- /dev/null +++ b/test/math/libm-test.inc @@ -0,0 +1,4521 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Part of testsuite for libm. + + This file is processed by a perl script. The resulting file has to + be included by a master file that defines: + + Makros: + FUNC(function): converts general function name (like cos) to + name with correct suffix (e.g. cosl or cosf) + MATHCONST(x): like FUNC but for constants (e.g convert 0.0 to 0.0L) + FLOAT: floating point type to test + - TEST_MSG: informal message to be displayed + CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat): + chooses one of the parameters as delta for testing + equality + PRINTF_EXPR Floating point conversion specification to print a variable + of type FLOAT with printf. PRINTF_EXPR just contains + the specifier, not the percent and width arguments, + e.g. "f". + PRINTF_XEXPR Like PRINTF_EXPR, but print in hexadecimal format. + PRINTF_NEXPR Like PRINTF_EXPR, but print nice. */ + +/* This testsuite has currently tests for: + acos, acosh, asin, asinh, atan, atan2, atanh, + cbrt, ceil, copysign, cos, cosh, erf, erfc, exp, exp10, exp2, expm1, + fabs, fdim, floor, fma, fmax, fmin, fmod, fpclassify, + frexp, gamma, hypot, + ilogb, isfinite, isinf, isnan, isnormal, + isless, islessequal, isgreater, isgreaterequal, islessgreater, isunordered, + j0, j1, jn, + ldexp, lgamma, log, log10, log1p, log2, logb, + modf, nearbyint, nextafter, + pow, remainder, remquo, rint, lrint, llrint, + round, lround, llround, + scalb, scalbn, scalbln, signbit, sin, sincos, sinh, sqrt, tan, tanh, tgamma, trunc, + y0, y1, yn + + and for the following complex math functions: + cabs, cacos, cacosh, carg, casin, casinh, catan, catanh, + ccos, ccosh, cexp, clog, cpow, cproj, csin, csinh, csqrt, ctan, ctanh. + + At the moment the following functions aren't tested: + drem, significand, nan + + Parameter handling is primitive in the moment: + --verbose=[0..3] for different levels of output: + 0: only error count + 1: basic report on failed tests (default) + 2: full report on all tests + -v for full output (equals --verbose=3) + -u for generation of an ULPs file + */ + +/* "Philosophy": + + This suite tests some aspects of the correct implementation of + mathematical functions in libm. Some simple, specific parameters + are tested for correctness but there's no exhaustive + testing. Handling of specific inputs (e.g. infinity, not-a-number) + is also tested. Correct handling of exceptions is checked + against. These implemented tests should check all cases that are + specified in ISO C99. + + Exception testing: At the moment only divide-by-zero and invalid + exceptions are tested. Overflow/underflow and inexact exceptions + aren't checked at the moment. + + NaN values: There exist signalling and quiet NaNs. This implementation + only uses signalling NaN as parameter but does not differenciate + between the two kinds of NaNs as result. + + Inline functions: Inlining functions should give an improvement in + speed - but not in precission. The inlined functions return + reasonable values for a reasonable range of input values. The + result is not necessarily correct for all values and exceptions are + not correctly raised in all cases. Problematic input and return + values are infinity, not-a-number and minus zero. This suite + therefore does not check these specific inputs and the exception + handling for inlined mathematical functions - just the "reasonable" + values are checked. + + Beware: The tests might fail for any of the following reasons: + - Tests are wrong + - Functions are wrong + - Floating Point Unit not working properly + - Compiler has errors + + With e.g. gcc 2.7.2.2 the test for cexp fails because of a compiler error. + + + To Do: All parameter should be numbers that can be represented as + exact floating point values. Currently some values cannot be represented + exactly and therefore the result is not the expected result. +*/ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include "libm-test-ulps.h" +#include <complex.h> +#include <math.h> +#include <float.h> +#include <limits.h> + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <getopt.h> + +//#include <fenv.h> +#define feclearexcept(X) +#define fetestexcept(X) 0 + +/* Possible exceptions */ +#define NO_EXCEPTION 0x0 +#define INVALID_EXCEPTION 0x1 +#define DIVIDE_BY_ZERO_EXCEPTION 0x2 +/* The next flags signals that those exceptions are allowed but not required. */ +#define INVALID_EXCEPTION_OK 0x4 +#define DIVIDE_BY_ZERO_EXCEPTION_OK 0x8 +#define EXCEPTIONS_OK INVALID_EXCEPTION_OK+DIVIDE_BY_ZERO_EXCEPTION_OK +/* Some special test flags, passed togther with exceptions. */ +#define IGNORE_ZERO_INF_SIGN 0x10 + +/* Various constants (we must supply them precalculated for accuracy). */ +#define M_PI_6l .52359877559829887307710723054658383L +#define M_E2l 7.389056098930650227230427460575008L +#define M_E3l 20.085536923187667740928529654581719L +#define M_2_SQRT_PIl 3.5449077018110320545963349666822903L /* 2 sqrt (M_PIl) */ +#define M_SQRT_PIl 1.7724538509055160272981674833411451L /* sqrt (M_PIl) */ +#define M_LOG_SQRT_PIl 0.57236494292470008707171367567652933L /* log(sqrt(M_PIl)) */ +#define M_LOG_2_SQRT_PIl 1.265512123484645396488945797134706L /* log(2*sqrt(M_PIl)) */ +#define M_PI_34l (M_PIl - M_PI_4l) /* 3*pi/4 */ +#define M_PI_34_LOG10El (M_PIl - M_PI_4l) * M_LOG10El +#define M_PI2_LOG10El M_PI_2l * M_LOG10El +#define M_PI4_LOG10El M_PI_4l * M_LOG10El +#define M_PI_LOG10El M_PIl * M_LOG10El + +static FILE *ulps_file; /* File to document difference. */ +static int output_ulps; /* Should ulps printed? */ + +static int noErrors; /* number of errors */ +static int noTests; /* number of tests (without testing exceptions) */ +static int noExcTests; /* number of tests for exception flags */ +static int noXFails; /* number of expected failures. */ +static int noXPasses; /* number of unexpected passes. */ + +static int verbose; +static int output_max_error; /* Should the maximal errors printed? */ +static int output_points; /* Should the single function results printed? */ +static int ignore_max_ulp; /* Should we ignore max_ulp? */ + +static FLOAT minus_zero, plus_zero; +static FLOAT plus_infty, minus_infty, nan_value; + +static FLOAT max_error, real_max_error, imag_max_error; + + +#define BUILD_COMPLEX(real, imag) \ + ({ __complex__ FLOAT __retval; \ + __real__ __retval = (real); \ + __imag__ __retval = (imag); \ + __retval; }) + +#define BUILD_COMPLEX_INT(real, imag) \ + ({ __complex__ int __retval; \ + __real__ __retval = (real); \ + __imag__ __retval = (imag); \ + __retval; }) + + +#define MANT_DIG CHOOSE ((LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1), \ + (LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1)) + +static void +init_max_error (void) +{ + max_error = 0; + real_max_error = 0; + imag_max_error = 0; + feclearexcept (FE_ALL_EXCEPT); +} + +static void +set_max_error (FLOAT current, FLOAT *curr_max_error) +{ + if (current > *curr_max_error) + *curr_max_error = current; +} + + +/* Should the message print to screen? This depends on the verbose flag, + and the test status. */ +static int +print_screen (int ok, int xfail) +{ + if (output_points + && (verbose > 1 + || (verbose == 1 && ok == xfail))) + return 1; + return 0; +} + + +/* Should the message print to screen? This depends on the verbose flag, + and the test status. */ +static int +print_screen_max_error (int ok, int xfail) +{ + if (output_max_error + && (verbose > 1 + || ((verbose == 1) && (ok == xfail)))) + return 1; + return 0; +} + +/* Update statistic counters. */ +static void +update_stats (int ok, int xfail) +{ + ++noTests; + if (ok && xfail) + ++noXPasses; + else if (!ok && xfail) + ++noXFails; + else if (!ok && !xfail) + ++noErrors; +} + +static void +print_ulps (const char *test_name, FLOAT ulp) +{ + if (output_ulps) + { + fprintf (ulps_file, "Test \"%s\":\n", test_name); + fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n", + CHOOSE("ldouble", "double", "float", + "ildouble", "idouble", "ifloat"), + FUNC(ceil) (ulp)); + } +} + +static void +print_function_ulps (const char *function_name, FLOAT ulp) +{ + if (output_ulps) + { + fprintf (ulps_file, "Function: \"%s\":\n", function_name); + fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n", + CHOOSE("ldouble", "double", "float", + "ildouble", "idouble", "ifloat"), + FUNC(ceil) (ulp)); + } +} + + +static void +print_complex_function_ulps (const char *function_name, FLOAT real_ulp, + FLOAT imag_ulp) +{ + if (output_ulps) + { + if (real_ulp != 0.0) + { + fprintf (ulps_file, "Function: Real part of \"%s\":\n", function_name); + fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n", + CHOOSE("ldouble", "double", "float", + "ildouble", "idouble", "ifloat"), + FUNC(ceil) (real_ulp)); + } + if (imag_ulp != 0.0) + { + fprintf (ulps_file, "Function: Imaginary part of \"%s\":\n", function_name); + fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n", + CHOOSE("ldouble", "double", "float", + "ildouble", "idouble", "ifloat"), + FUNC(ceil) (imag_ulp)); + } + + + } +} + + + +/* Test if Floating-Point stack hasn't changed */ +static void +fpstack_test (const char *test_name) +{ +#ifdef i386 + static int old_stack; + int sw; + + asm ("fnstsw" : "=a" (sw)); + sw >>= 11; + sw &= 7; + + if (sw != old_stack) + { + printf ("FP-Stack wrong after test %s (%d, should be %d)\n", + test_name, sw, old_stack); + ++noErrors; + old_stack = sw; + } +#endif +} + + +static void +print_max_error (const char *func_name, FLOAT allowed, int xfail) +{ + int ok = 0; + + if (max_error == 0.0 || (max_error <= allowed && !ignore_max_ulp)) + { + ok = 1; + } + + if (!ok) + print_function_ulps (func_name, max_error); + + + if (print_screen_max_error (ok, xfail)) + { + printf ("Maximal error of `%s'\n", func_name); + printf (" is : %.0" PRINTF_NEXPR " ulp\n", FUNC(ceil) (max_error)); + printf (" accepted: %.0" PRINTF_NEXPR " ulp\n", FUNC(ceil) (allowed)); + } + + update_stats (ok, xfail); +} + + +static void +print_complex_max_error (const char *func_name, __complex__ FLOAT allowed, + __complex__ int xfail) +{ + int ok = 0; + + if ((real_max_error == 0 && imag_max_error == 0) + || (real_max_error <= __real__ allowed + && imag_max_error <= __imag__ allowed + && !ignore_max_ulp)) + { + ok = 1; + } + + if (!ok) + print_complex_function_ulps (func_name, real_max_error, imag_max_error); + + + if (print_screen_max_error (ok, xfail)) + { + printf ("Maximal error of real part of: %s\n", func_name); + printf (" is : %.0" PRINTF_NEXPR " ulp\n", + FUNC(ceil) (real_max_error)); + printf (" accepted: %.0" PRINTF_NEXPR " ulp\n", + FUNC(ceil) (__real__ allowed)); + printf ("Maximal error of imaginary part of: %s\n", func_name); + printf (" is : %.0" PRINTF_NEXPR " ulp\n", + FUNC(ceil) (imag_max_error)); + printf (" accepted: %.0" PRINTF_NEXPR " ulp\n", + FUNC(ceil) (__imag__ allowed)); + } + + update_stats (ok, xfail); +} + + +/* Test whether a given exception was raised. */ +static void +test_single_exception (const char *test_name, + int exception, + int exc_flag, + int fe_flag, + const char *flag_name) +{ +#ifndef TEST_INLINE + int ok = 1; + if (exception & exc_flag) + { + if (fetestexcept (fe_flag)) + { + if (print_screen (1, 0)) + printf ("Pass: %s: Exception \"%s\" set\n", test_name, flag_name); + } + else + { + ok = 0; + if (print_screen (0, 0)) + printf ("Failure: %s: Exception \"%s\" not set\n", + test_name, flag_name); + } + } + else + { + if (fetestexcept (fe_flag)) + { + ok = 0; + if (print_screen (0, 0)) + printf ("Failure: %s: Exception \"%s\" set\n", + test_name, flag_name); + } + else + { + if (print_screen (1, 0)) + printf ("%s: Exception \"%s\" not set\n", test_name, + flag_name); + } + } + if (!ok) + ++noErrors; + +#endif +} + + +/* Test whether exceptions given by EXCEPTION are raised. Ignore thereby + allowed but not required exceptions. +*/ +static void +test_exceptions (const char *test_name, int exception) +{ + ++noExcTests; +#ifdef FE_DIVBYZERO + if ((exception & DIVIDE_BY_ZERO_EXCEPTION_OK) == 0) + test_single_exception (test_name, exception, + DIVIDE_BY_ZERO_EXCEPTION, FE_DIVBYZERO, + "Divide by zero"); +#endif +#ifdef FE_INVALID + if ((exception & INVALID_EXCEPTION_OK) == 0) + test_single_exception (test_name, exception, INVALID_EXCEPTION, FE_INVALID, + "Invalid operation"); +#endif + feclearexcept (FE_ALL_EXCEPT); +} + + +static void +check_float_internal (const char *test_name, FLOAT computed, FLOAT expected, + FLOAT max_ulp, int xfail, int exceptions, + FLOAT *curr_max_error) +{ + int ok = 0; + int print_diff = 0; + FLOAT diff = 0; + FLOAT ulp = 0; + + test_exceptions (test_name, exceptions); + if (isnan (computed) && isnan (expected)) + ok = 1; + else if (isinf (computed) && isinf (expected)) + { + /* Test for sign of infinities. */ + if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0 + && signbit (computed) != signbit (expected)) + { + ok = 0; + printf ("infinity has wrong sign.\n"); + } + else + ok = 1; + } + /* Don't calc ulp for NaNs or infinities. */ + else if (isinf (computed) || isnan (computed) || isinf (expected) || isnan (expected)) + ok = 0; + else + { + diff = FUNC(fabs) (computed - expected); + /* ilogb (0) isn't allowed. */ + if (expected == 0.0) + ulp = diff / FUNC(ldexp) (1.0, - MANT_DIG); + else + ulp = diff / FUNC(ldexp) (1.0, FUNC(ilogb) (expected) - MANT_DIG); + set_max_error (ulp, curr_max_error); + print_diff = 1; + if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0 + && computed == 0.0 && expected == 0.0 + && signbit(computed) != signbit (expected)) + ok = 0; + else if (ulp == 0.0 || (ulp <= max_ulp && !ignore_max_ulp)) + ok = 1; + else + { + ok = 0; + print_ulps (test_name, ulp); + } + + } + if (print_screen (ok, xfail)) + { + if (!ok) + printf ("Failure: "); + printf ("Test: %s\n", test_name); + printf ("Result:\n"); + printf (" is: % .20" PRINTF_EXPR " % .20" PRINTF_XEXPR "\n", + computed, computed); + printf (" should be: % .20" PRINTF_EXPR " % .20" PRINTF_XEXPR "\n", + expected, expected); + if (print_diff) + { + printf (" difference: % .20" PRINTF_EXPR " % .20" PRINTF_XEXPR + "\n", diff, diff); + printf (" ulp : % .4" PRINTF_NEXPR "\n", ulp); + printf (" max.ulp : % .4" PRINTF_NEXPR "\n", max_ulp); + } + } + update_stats (ok, xfail); + + fpstack_test (test_name); +} + + +static void +check_float (const char *test_name, FLOAT computed, FLOAT expected, + FLOAT max_ulp, int xfail, int exceptions) +{ + check_float_internal (test_name, computed, expected, max_ulp, xfail, + exceptions, &max_error); +} + + +static void +check_complex (const char *test_name, __complex__ FLOAT computed, + __complex__ FLOAT expected, + __complex__ FLOAT max_ulp, __complex__ int xfail, + int exception) +{ + FLOAT part_comp, part_exp, part_max_ulp; + int part_xfail; + char str[200]; + + sprintf (str, "Real part of: %s", test_name); + part_comp = __real__ computed; + part_exp = __real__ expected; + part_max_ulp = __real__ max_ulp; + part_xfail = __real__ xfail; + + check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail, + exception, &real_max_error); + + sprintf (str, "Imaginary part of: %s", test_name); + part_comp = __imag__ computed; + part_exp = __imag__ expected; + part_max_ulp = __imag__ max_ulp; + part_xfail = __imag__ xfail; + + /* Don't check again for exceptions, just pass through the + zero/inf sign test. */ + check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail, + exception & IGNORE_ZERO_INF_SIGN, + &imag_max_error); +} + + +/* Check that computed and expected values are equal (int values). */ +static void +check_int (const char *test_name, int computed, int expected, int max_ulp, + int xfail, int exceptions) +{ + int diff = computed - expected; + int ok = 0; + + test_exceptions (test_name, exceptions); + noTests++; + if (abs (diff) <= max_ulp) + ok = 1; + + if (!ok) + print_ulps (test_name, diff); + + if (print_screen (ok, xfail)) + { + if (!ok) + printf ("Failure: "); + printf ("Test: %s\n", test_name); + printf ("Result:\n"); + printf (" is: %d\n", computed); + printf (" should be: %d\n", expected); + } + + update_stats (ok, xfail); + fpstack_test (test_name); +} + + +/* Check that computed and expected values are equal (long int values). */ +static void +check_long (const char *test_name, long int computed, long int expected, + long int max_ulp, int xfail, int exceptions) +{ + long int diff = computed - expected; + int ok = 0; + + test_exceptions (test_name, exceptions); + noTests++; + if (labs (diff) <= max_ulp) + ok = 1; + + if (!ok) + print_ulps (test_name, diff); + + if (print_screen (ok, xfail)) + { + if (!ok) + printf ("Failure: "); + printf ("Test: %s\n", test_name); + printf ("Result:\n"); + printf (" is: %ld\n", computed); + printf (" should be: %ld\n", expected); + } + + update_stats (ok, xfail); + fpstack_test (test_name); +} + + +/* Check that computed value is true/false. */ +static void +check_bool (const char *test_name, int computed, int expected, + long int max_ulp, int xfail, int exceptions) +{ + int ok = 0; + + test_exceptions (test_name, exceptions); + noTests++; + if ((computed == 0) == (expected == 0)) + ok = 1; + + if (print_screen (ok, xfail)) + { + if (!ok) + printf ("Failure: "); + printf ("Test: %s\n", test_name); + printf ("Result:\n"); + printf (" is: %d\n", computed); + printf (" should be: %d\n", expected); + } + + update_stats (ok, xfail); + fpstack_test (test_name); +} + + +/* check that computed and expected values are equal (long int values) */ +static void +check_longlong (const char *test_name, long long int computed, + long long int expected, + long long int max_ulp, int xfail, + int exceptions) +{ + long long int diff = computed - expected; + int ok = 0; + + test_exceptions (test_name, exceptions); + noTests++; + if (llabs (diff) <= max_ulp) + ok = 1; + + if (!ok) + print_ulps (test_name, diff); + + if (print_screen (ok, xfail)) + { + if (!ok) + printf ("Failure:"); + printf ("Test: %s\n", test_name); + printf ("Result:\n"); + printf (" is: %lld\n", computed); + printf (" should be: %lld\n", expected); + } + + update_stats (ok, xfail); + fpstack_test (test_name); +} + + + +/* This is to prevent messages from the SVID libm emulation. */ +int +matherr (struct exception *x __attribute__ ((unused))) +{ + return 1; +} + + +/**************************************************************************** + Tests for single functions of libm. + Please keep them alphabetically sorted! +****************************************************************************/ + +static void +acos_test (void) +{ + errno = 0; + FUNC(acos) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (acos); + + TEST_f_f (acos, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (acos, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (acos, nan_value, nan_value); + + /* |x| > 1: */ + TEST_f_f (acos, 1.1L, nan_value, INVALID_EXCEPTION); + TEST_f_f (acos, -1.1L, nan_value, INVALID_EXCEPTION); + + TEST_f_f (acos, 0, M_PI_2l); + TEST_f_f (acos, minus_zero, M_PI_2l); + TEST_f_f (acos, 1, 0); + TEST_f_f (acos, -1, M_PIl); + TEST_f_f (acos, 0.5, M_PI_6l*2.0); + TEST_f_f (acos, -0.5, M_PI_6l*4.0); + TEST_f_f (acos, 0.7L, 0.79539883018414355549096833892476432L); + + END (acos); +} + +static void +acosh_test (void) +{ + errno = 0; + FUNC(acosh) (7); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (acosh); + + TEST_f_f (acosh, plus_infty, plus_infty); + TEST_f_f (acosh, minus_infty, nan_value, INVALID_EXCEPTION); + + /* x < 1: */ + TEST_f_f (acosh, -1.1L, nan_value, INVALID_EXCEPTION); + + TEST_f_f (acosh, 1, 0); + TEST_f_f (acosh, 7, 2.633915793849633417250092694615937L); + + END (acosh); +} + +static void +asin_test (void) +{ + errno = 0; + FUNC(asin) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (asin); + + TEST_f_f (asin, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (asin, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (asin, nan_value, nan_value); + + /* asin x == NaN plus invalid exception for |x| > 1. */ + TEST_f_f (asin, 1.1L, nan_value, INVALID_EXCEPTION); + TEST_f_f (asin, -1.1L, nan_value, INVALID_EXCEPTION); + + TEST_f_f (asin, 0, 0); + TEST_f_f (asin, minus_zero, minus_zero); + TEST_f_f (asin, 0.5, M_PI_6l); + TEST_f_f (asin, -0.5, -M_PI_6l); + TEST_f_f (asin, 1.0, M_PI_2l); + TEST_f_f (asin, -1.0, -M_PI_2l); + TEST_f_f (asin, 0.7L, 0.77539749661075306374035335271498708L); + + END (asin); +} + +static void +asinh_test (void) +{ + errno = 0; + FUNC(asinh) (0.7L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (asinh); + + TEST_f_f (asinh, 0, 0); + TEST_f_f (asinh, minus_zero, minus_zero); +#ifndef TEST_INLINE + TEST_f_f (asinh, plus_infty, plus_infty); + TEST_f_f (asinh, minus_infty, minus_infty); +#endif + TEST_f_f (asinh, nan_value, nan_value); + TEST_f_f (asinh, 0.7L, 0.652666566082355786L); + + END (asinh); +} + +static void +atan_test (void) +{ + errno = 0; + FUNC(atan) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (atan); + + TEST_f_f (atan, 0, 0); + TEST_f_f (atan, minus_zero, minus_zero); + + TEST_f_f (atan, plus_infty, M_PI_2l); + TEST_f_f (atan, minus_infty, -M_PI_2l); + TEST_f_f (atan, nan_value, nan_value); + + TEST_f_f (atan, 1, M_PI_4l); + TEST_f_f (atan, -1, -M_PI_4l); + + TEST_f_f (atan, 0.7L, 0.61072596438920861654375887649023613L); + + END (atan); +} + + + +static void +atanh_test (void) +{ + errno = 0; + FUNC(atanh) (0.7L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (atanh); + + + TEST_f_f (atanh, 0, 0); + TEST_f_f (atanh, minus_zero, minus_zero); + + TEST_f_f (atanh, 1, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (atanh, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (atanh, nan_value, nan_value); + + /* atanh (x) == NaN plus invalid exception if |x| > 1. */ + TEST_f_f (atanh, 1.1L, nan_value, INVALID_EXCEPTION); + TEST_f_f (atanh, -1.1L, nan_value, INVALID_EXCEPTION); + + TEST_f_f (atanh, 0.7L, 0.8673005276940531944L); + + END (atanh); +} + +static void +atan2_test (void) +{ + errno = 0; + FUNC(atan2) (-0, 1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (atan2); + + /* atan2 (0,x) == 0 for x > 0. */ + TEST_ff_f (atan2, 0, 1, 0); + + /* atan2 (-0,x) == -0 for x > 0. */ + TEST_ff_f (atan2, minus_zero, 1, minus_zero); + + TEST_ff_f (atan2, 0, 0, 0); + TEST_ff_f (atan2, minus_zero, 0, minus_zero); + + /* atan2 (+0,x) == +pi for x < 0. */ + TEST_ff_f (atan2, 0, -1, M_PIl); + + /* atan2 (-0,x) == -pi for x < 0. */ + TEST_ff_f (atan2, minus_zero, -1, -M_PIl); + + TEST_ff_f (atan2, 0, minus_zero, M_PIl); + TEST_ff_f (atan2, minus_zero, minus_zero, -M_PIl); + + /* atan2 (y,+0) == pi/2 for y > 0. */ + TEST_ff_f (atan2, 1, 0, M_PI_2l); + + /* atan2 (y,-0) == pi/2 for y > 0. */ + TEST_ff_f (atan2, 1, minus_zero, M_PI_2l); + + /* atan2 (y,+0) == -pi/2 for y < 0. */ + TEST_ff_f (atan2, -1, 0, -M_PI_2l); + + /* atan2 (y,-0) == -pi/2 for y < 0. */ + TEST_ff_f (atan2, -1, minus_zero, -M_PI_2l); + + /* atan2 (y,inf) == +0 for finite y > 0. */ + TEST_ff_f (atan2, 1, plus_infty, 0); + + /* atan2 (y,inf) == -0 for finite y < 0. */ + TEST_ff_f (atan2, -1, plus_infty, minus_zero); + + /* atan2(+inf, x) == pi/2 for finite x. */ + TEST_ff_f (atan2, plus_infty, -1, M_PI_2l); + + /* atan2(-inf, x) == -pi/2 for finite x. */ + TEST_ff_f (atan2, minus_infty, 1, -M_PI_2l); + + /* atan2 (y,-inf) == +pi for finite y > 0. */ + TEST_ff_f (atan2, 1, minus_infty, M_PIl); + + /* atan2 (y,-inf) == -pi for finite y < 0. */ + TEST_ff_f (atan2, -1, minus_infty, -M_PIl); + + TEST_ff_f (atan2, plus_infty, plus_infty, M_PI_4l); + TEST_ff_f (atan2, minus_infty, plus_infty, -M_PI_4l); + TEST_ff_f (atan2, plus_infty, minus_infty, M_PI_34l); + TEST_ff_f (atan2, minus_infty, minus_infty, -M_PI_34l); + TEST_ff_f (atan2, nan_value, nan_value, nan_value); + + TEST_ff_f (atan2, 0.7L, 1, 0.61072596438920861654375887649023613L); + TEST_ff_f (atan2, -0.7L, 1.0L, -0.61072596438920861654375887649023613L); + TEST_ff_f (atan2, 0.7L, -1.0L, 2.530866689200584621918884506789267L); + TEST_ff_f (atan2, -0.7L, -1.0L, -2.530866689200584621918884506789267L); + TEST_ff_f (atan2, 0.4L, 0.0003L, 1.5700463269355215717704032607580829L); + TEST_ff_f (atan2, 1.4L, -0.93L, 2.1571487668237843754887415992772736L); + + END (atan2); +} + + +static void +cabs_test (void) +{ + errno = 0; + FUNC(cabs) (BUILD_COMPLEX (0.7L, 12.4L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cabs); + + /* cabs (x + iy) is specified as hypot (x,y) */ + + /* cabs (+inf + i x) == +inf. */ + TEST_c_f (cabs, plus_infty, 1.0, plus_infty); + /* cabs (-inf + i x) == +inf. */ + TEST_c_f (cabs, minus_infty, 1.0, plus_infty); + + TEST_c_f (cabs, minus_infty, nan_value, plus_infty); + TEST_c_f (cabs, minus_infty, nan_value, plus_infty); + + TEST_c_f (cabs, nan_value, nan_value, nan_value); + + /* cabs (x,y) == cabs (y,x). */ + TEST_c_f (cabs, 0.7L, 12.4L, 12.419742348374220601176836866763271L); + /* cabs (x,y) == cabs (-x,y). */ + TEST_c_f (cabs, -12.4L, 0.7L, 12.419742348374220601176836866763271L); + /* cabs (x,y) == cabs (-y,x). */ + TEST_c_f (cabs, -0.7L, 12.4L, 12.419742348374220601176836866763271L); + /* cabs (x,y) == cabs (-x,-y). */ + TEST_c_f (cabs, -12.4L, -0.7L, 12.419742348374220601176836866763271L); + /* cabs (x,y) == cabs (-y,-x). */ + TEST_c_f (cabs, -0.7L, -12.4L, 12.419742348374220601176836866763271L); + /* cabs (x,0) == fabs (x). */ + TEST_c_f (cabs, -0.7L, 0, 0.7L); + TEST_c_f (cabs, 0.7L, 0, 0.7L); + TEST_c_f (cabs, -1.0L, 0, 1.0L); + TEST_c_f (cabs, 1.0L, 0, 1.0L); + TEST_c_f (cabs, -5.7e7L, 0, 5.7e7L); + TEST_c_f (cabs, 5.7e7L, 0, 5.7e7L); + + TEST_c_f (cabs, 0.7L, 1.2L, 1.3892443989449804508432547041028554L); + + END (cabs); +} + +#if 0 +static void +cacos_test (void) +{ + errno = 0; + FUNC(cacos) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cacos); + + + TEST_c_c (cacos, 0, 0, M_PI_2l, minus_zero); + TEST_c_c (cacos, minus_zero, 0, M_PI_2l, minus_zero); + TEST_c_c (cacos, minus_zero, minus_zero, M_PI_2l, 0.0); + TEST_c_c (cacos, 0, minus_zero, M_PI_2l, 0.0); + + TEST_c_c (cacos, minus_infty, plus_infty, M_PI_34l, minus_infty); + TEST_c_c (cacos, minus_infty, minus_infty, M_PI_34l, plus_infty); + + TEST_c_c (cacos, plus_infty, plus_infty, M_PI_4l, minus_infty); + TEST_c_c (cacos, plus_infty, minus_infty, M_PI_4l, plus_infty); + + TEST_c_c (cacos, -10.0, plus_infty, M_PI_2l, minus_infty); + TEST_c_c (cacos, -10.0, minus_infty, M_PI_2l, plus_infty); + TEST_c_c (cacos, 0, plus_infty, M_PI_2l, minus_infty); + TEST_c_c (cacos, 0, minus_infty, M_PI_2l, plus_infty); + TEST_c_c (cacos, 0.1L, plus_infty, M_PI_2l, minus_infty); + TEST_c_c (cacos, 0.1L, minus_infty, M_PI_2l, plus_infty); + + TEST_c_c (cacos, minus_infty, 0, M_PIl, minus_infty); + TEST_c_c (cacos, minus_infty, minus_zero, M_PIl, plus_infty); + TEST_c_c (cacos, minus_infty, 100, M_PIl, minus_infty); + TEST_c_c (cacos, minus_infty, -100, M_PIl, plus_infty); + + TEST_c_c (cacos, plus_infty, 0, 0.0, minus_infty); + TEST_c_c (cacos, plus_infty, minus_zero, 0.0, plus_infty); + TEST_c_c (cacos, plus_infty, 0.5, 0.0, minus_infty); + TEST_c_c (cacos, plus_infty, -0.5, 0.0, plus_infty); + + TEST_c_c (cacos, plus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + TEST_c_c (cacos, minus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (cacos, 0, nan_value, M_PI_2l, nan_value); + TEST_c_c (cacos, minus_zero, nan_value, M_PI_2l, nan_value); + + TEST_c_c (cacos, nan_value, plus_infty, nan_value, minus_infty); + TEST_c_c (cacos, nan_value, minus_infty, nan_value, plus_infty); + + TEST_c_c (cacos, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cacos, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (cacos, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cacos, nan_value, -0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (cacos, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (cacos, 0.7L, 1.2L, 1.1351827477151551088992008271819053L, -1.0927647857577371459105272080819308L); + TEST_c_c (cacos, -2, -3, 2.1414491111159960199416055713254211L, 1.9833870299165354323470769028940395L); + + END (cacos, complex); +} + + +static void +cacosh_test (void) +{ + errno = 0; + FUNC(cacosh) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cacosh); + + + TEST_c_c (cacosh, 0, 0, 0.0, M_PI_2l); + TEST_c_c (cacosh, minus_zero, 0, 0.0, M_PI_2l); + TEST_c_c (cacosh, 0, minus_zero, 0.0, -M_PI_2l); + TEST_c_c (cacosh, minus_zero, minus_zero, 0.0, -M_PI_2l); + TEST_c_c (cacosh, minus_infty, plus_infty, plus_infty, M_PI_34l); + TEST_c_c (cacosh, minus_infty, minus_infty, plus_infty, -M_PI_34l); + + TEST_c_c (cacosh, plus_infty, plus_infty, plus_infty, M_PI_4l); + TEST_c_c (cacosh, plus_infty, minus_infty, plus_infty, -M_PI_4l); + + TEST_c_c (cacosh, -10.0, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (cacosh, -10.0, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (cacosh, 0, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (cacosh, 0, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (cacosh, 0.1L, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (cacosh, 0.1L, minus_infty, plus_infty, -M_PI_2l); + + TEST_c_c (cacosh, minus_infty, 0, plus_infty, M_PIl); + TEST_c_c (cacosh, minus_infty, minus_zero, plus_infty, -M_PIl); + TEST_c_c (cacosh, minus_infty, 100, plus_infty, M_PIl); + TEST_c_c (cacosh, minus_infty, -100, plus_infty, -M_PIl); + + TEST_c_c (cacosh, plus_infty, 0, plus_infty, 0.0); + TEST_c_c (cacosh, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (cacosh, plus_infty, 0.5, plus_infty, 0.0); + TEST_c_c (cacosh, plus_infty, -0.5, plus_infty, minus_zero); + + TEST_c_c (cacosh, plus_infty, nan_value, plus_infty, nan_value); + TEST_c_c (cacosh, minus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (cacosh, 0, nan_value, nan_value, nan_value); + TEST_c_c (cacosh, minus_zero, nan_value, nan_value, nan_value); + + TEST_c_c (cacosh, nan_value, plus_infty, plus_infty, nan_value); + TEST_c_c (cacosh, nan_value, minus_infty, plus_infty, nan_value); + + TEST_c_c (cacosh, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cacosh, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (cacosh, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cacosh, nan_value, -0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (cacosh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (cacosh, 0.7L, 1.2L, 1.0927647857577371459105272080819308L, 1.1351827477151551088992008271819053L); + TEST_c_c (cacosh, -2, -3, -1.9833870299165354323470769028940395L, 2.1414491111159960199416055713254211L); + + END (cacosh, complex); +} + +static void +carg_test (void) +{ + START (carg); + + /* carg (x + iy) is specified as atan2 (y, x) */ + + /* carg (x + i 0) == 0 for x > 0. */ + TEST_c_f (carg, 2.0, 0, 0); + /* carg (x - i 0) == -0 for x > 0. */ + TEST_c_f (carg, 2.0, minus_zero, minus_zero); + + TEST_c_f (carg, 0, 0, 0); + TEST_c_f (carg, 0, minus_zero, minus_zero); + + /* carg (x + i 0) == +pi for x < 0. */ + TEST_c_f (carg, -2.0, 0, M_PIl); + + /* carg (x - i 0) == -pi for x < 0. */ + TEST_c_f (carg, -2.0, minus_zero, -M_PIl); + + TEST_c_f (carg, minus_zero, 0, M_PIl); + TEST_c_f (carg, minus_zero, minus_zero, -M_PIl); + + /* carg (+0 + i y) == pi/2 for y > 0. */ + TEST_c_f (carg, 0, 2.0, M_PI_2l); + + /* carg (-0 + i y) == pi/2 for y > 0. */ + TEST_c_f (carg, minus_zero, 2.0, M_PI_2l); + + /* carg (+0 + i y) == -pi/2 for y < 0. */ + TEST_c_f (carg, 0, -2.0, -M_PI_2l); + + /* carg (-0 + i y) == -pi/2 for y < 0. */ + TEST_c_f (carg, minus_zero, -2.0, -M_PI_2l); + + /* carg (inf + i y) == +0 for finite y > 0. */ + TEST_c_f (carg, plus_infty, 2.0, 0); + + /* carg (inf + i y) == -0 for finite y < 0. */ + TEST_c_f (carg, plus_infty, -2.0, minus_zero); + + /* carg(x + i inf) == pi/2 for finite x. */ + TEST_c_f (carg, 10.0, plus_infty, M_PI_2l); + + /* carg(x - i inf) == -pi/2 for finite x. */ + TEST_c_f (carg, 10.0, minus_infty, -M_PI_2l); + + /* carg (-inf + i y) == +pi for finite y > 0. */ + TEST_c_f (carg, minus_infty, 10.0, M_PIl); + + /* carg (-inf + i y) == -pi for finite y < 0. */ + TEST_c_f (carg, minus_infty, -10.0, -M_PIl); + + TEST_c_f (carg, plus_infty, plus_infty, M_PI_4l); + + TEST_c_f (carg, plus_infty, minus_infty, -M_PI_4l); + + TEST_c_f (carg, minus_infty, plus_infty, 3 * M_PI_4l); + + TEST_c_f (carg, minus_infty, minus_infty, -3 * M_PI_4l); + + TEST_c_f (carg, nan_value, nan_value, nan_value); + + END (carg); +} + +static void +casin_test (void) +{ + errno = 0; + FUNC(casin) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (casin); + + TEST_c_c (casin, 0, 0, 0.0, 0.0); + TEST_c_c (casin, minus_zero, 0, minus_zero, 0.0); + TEST_c_c (casin, 0, minus_zero, 0.0, minus_zero); + TEST_c_c (casin, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (casin, plus_infty, plus_infty, M_PI_4l, plus_infty); + TEST_c_c (casin, plus_infty, minus_infty, M_PI_4l, minus_infty); + TEST_c_c (casin, minus_infty, plus_infty, -M_PI_4l, plus_infty); + TEST_c_c (casin, minus_infty, minus_infty, -M_PI_4l, minus_infty); + + TEST_c_c (casin, -10.0, plus_infty, minus_zero, plus_infty); + TEST_c_c (casin, -10.0, minus_infty, minus_zero, minus_infty); + TEST_c_c (casin, 0, plus_infty, 0.0, plus_infty); + TEST_c_c (casin, 0, minus_infty, 0.0, minus_infty); + TEST_c_c (casin, minus_zero, plus_infty, minus_zero, plus_infty); + TEST_c_c (casin, minus_zero, minus_infty, minus_zero, minus_infty); + TEST_c_c (casin, 0.1L, plus_infty, 0.0, plus_infty); + TEST_c_c (casin, 0.1L, minus_infty, 0.0, minus_infty); + + TEST_c_c (casin, minus_infty, 0, -M_PI_2l, plus_infty); + TEST_c_c (casin, minus_infty, minus_zero, -M_PI_2l, minus_infty); + TEST_c_c (casin, minus_infty, 100, -M_PI_2l, plus_infty); + TEST_c_c (casin, minus_infty, -100, -M_PI_2l, minus_infty); + + TEST_c_c (casin, plus_infty, 0, M_PI_2l, plus_infty); + TEST_c_c (casin, plus_infty, minus_zero, M_PI_2l, minus_infty); + TEST_c_c (casin, plus_infty, 0.5, M_PI_2l, plus_infty); + TEST_c_c (casin, plus_infty, -0.5, M_PI_2l, minus_infty); + + TEST_c_c (casin, nan_value, plus_infty, nan_value, plus_infty); + TEST_c_c (casin, nan_value, minus_infty, nan_value, minus_infty); + + TEST_c_c (casin, 0.0, nan_value, 0.0, nan_value); + TEST_c_c (casin, minus_zero, nan_value, minus_zero, nan_value); + + TEST_c_c (casin, plus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + TEST_c_c (casin, minus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (casin, nan_value, 10.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (casin, nan_value, -10.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (casin, 0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (casin, -0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (casin, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (casin, 0.7L, 1.2L, 0.4356135790797415103321208644578462L, 1.0927647857577371459105272080819308L); + TEST_c_c (casin, -2, -3, -0.57065278432109940071028387968566963L, -1.9833870299165354323470769028940395L); + + END (casin, complex); +} + + +static void +casinh_test (void) +{ + errno = 0; + FUNC(casinh) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (casinh); + + TEST_c_c (casinh, 0, 0, 0.0, 0.0); + TEST_c_c (casinh, minus_zero, 0, minus_zero, 0); + TEST_c_c (casinh, 0, minus_zero, 0.0, minus_zero); + TEST_c_c (casinh, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (casinh, plus_infty, plus_infty, plus_infty, M_PI_4l); + TEST_c_c (casinh, plus_infty, minus_infty, plus_infty, -M_PI_4l); + TEST_c_c (casinh, minus_infty, plus_infty, minus_infty, M_PI_4l); + TEST_c_c (casinh, minus_infty, minus_infty, minus_infty, -M_PI_4l); + + TEST_c_c (casinh, -10.0, plus_infty, minus_infty, M_PI_2l); + TEST_c_c (casinh, -10.0, minus_infty, minus_infty, -M_PI_2l); + TEST_c_c (casinh, 0, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (casinh, 0, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (casinh, minus_zero, plus_infty, minus_infty, M_PI_2l); + TEST_c_c (casinh, minus_zero, minus_infty, minus_infty, -M_PI_2l); + TEST_c_c (casinh, 0.1L, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (casinh, 0.1L, minus_infty, plus_infty, -M_PI_2l); + + TEST_c_c (casinh, minus_infty, 0, minus_infty, 0.0); + TEST_c_c (casinh, minus_infty, minus_zero, minus_infty, minus_zero); + TEST_c_c (casinh, minus_infty, 100, minus_infty, 0.0); + TEST_c_c (casinh, minus_infty, -100, minus_infty, minus_zero); + + TEST_c_c (casinh, plus_infty, 0, plus_infty, 0.0); + TEST_c_c (casinh, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (casinh, plus_infty, 0.5, plus_infty, 0.0); + TEST_c_c (casinh, plus_infty, -0.5, plus_infty, minus_zero); + + TEST_c_c (casinh, plus_infty, nan_value, plus_infty, nan_value); + TEST_c_c (casinh, minus_infty, nan_value, minus_infty, nan_value); + + TEST_c_c (casinh, nan_value, 0, nan_value, 0.0); + TEST_c_c (casinh, nan_value, minus_zero, nan_value, minus_zero); + + TEST_c_c (casinh, nan_value, plus_infty, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN); + TEST_c_c (casinh, nan_value, minus_infty, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (casinh, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (casinh, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (casinh, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (casinh, -0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (casinh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (casinh, 0.7L, 1.2L, 0.97865459559367387689317593222160964L, 0.91135418953156011567903546856170941L); + TEST_c_c (casinh, -2, -3, -1.9686379257930962917886650952454982L, -0.96465850440760279204541105949953237L); + + END (casinh, complex); +} + + +static void +catan_test (void) +{ + errno = 0; + FUNC(catan) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (catan); + + TEST_c_c (catan, 0, 0, 0, 0); + TEST_c_c (catan, minus_zero, 0, minus_zero, 0); + TEST_c_c (catan, 0, minus_zero, 0, minus_zero); + TEST_c_c (catan, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (catan, plus_infty, plus_infty, M_PI_2l, 0); + TEST_c_c (catan, plus_infty, minus_infty, M_PI_2l, minus_zero); + TEST_c_c (catan, minus_infty, plus_infty, -M_PI_2l, 0); + TEST_c_c (catan, minus_infty, minus_infty, -M_PI_2l, minus_zero); + + + TEST_c_c (catan, plus_infty, -10.0, M_PI_2l, minus_zero); + TEST_c_c (catan, minus_infty, -10.0, -M_PI_2l, minus_zero); + TEST_c_c (catan, plus_infty, minus_zero, M_PI_2l, minus_zero); + TEST_c_c (catan, minus_infty, minus_zero, -M_PI_2l, minus_zero); + TEST_c_c (catan, plus_infty, 0.0, M_PI_2l, 0); + TEST_c_c (catan, minus_infty, 0.0, -M_PI_2l, 0); + TEST_c_c (catan, plus_infty, 0.1L, M_PI_2l, 0); + TEST_c_c (catan, minus_infty, 0.1L, -M_PI_2l, 0); + + TEST_c_c (catan, 0.0, minus_infty, M_PI_2l, minus_zero); + TEST_c_c (catan, minus_zero, minus_infty, -M_PI_2l, minus_zero); + TEST_c_c (catan, 100.0, minus_infty, M_PI_2l, minus_zero); + TEST_c_c (catan, -100.0, minus_infty, -M_PI_2l, minus_zero); + + TEST_c_c (catan, 0.0, plus_infty, M_PI_2l, 0); + TEST_c_c (catan, minus_zero, plus_infty, -M_PI_2l, 0); + TEST_c_c (catan, 0.5, plus_infty, M_PI_2l, 0); + TEST_c_c (catan, -0.5, plus_infty, -M_PI_2l, 0); + + TEST_c_c (catan, nan_value, 0.0, nan_value, 0); + TEST_c_c (catan, nan_value, minus_zero, nan_value, minus_zero); + + TEST_c_c (catan, nan_value, plus_infty, nan_value, 0); + TEST_c_c (catan, nan_value, minus_infty, nan_value, minus_zero); + + TEST_c_c (catan, 0.0, nan_value, nan_value, nan_value); + TEST_c_c (catan, minus_zero, nan_value, nan_value, nan_value); + + TEST_c_c (catan, plus_infty, nan_value, M_PI_2l, 0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (catan, minus_infty, nan_value, -M_PI_2l, 0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (catan, nan_value, 10.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (catan, nan_value, -10.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (catan, 0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (catan, -0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (catan, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (catan, 0.7L, 1.2L, 1.0785743834118921877443707996386368L, 0.57705737765343067644394541889341712L); + + TEST_c_c (catan, -2, -3, -1.4099210495965755225306193844604208L, -0.22907268296853876629588180294200276L); + + END (catan, complex); +} + +static void +catanh_test (void) +{ + errno = 0; + FUNC(catanh) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (catanh); + + TEST_c_c (catanh, 0, 0, 0.0, 0.0); + TEST_c_c (catanh, minus_zero, 0, minus_zero, 0.0); + TEST_c_c (catanh, 0, minus_zero, 0.0, minus_zero); + TEST_c_c (catanh, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (catanh, plus_infty, plus_infty, 0.0, M_PI_2l); + TEST_c_c (catanh, plus_infty, minus_infty, 0.0, -M_PI_2l); + TEST_c_c (catanh, minus_infty, plus_infty, minus_zero, M_PI_2l); + TEST_c_c (catanh, minus_infty, minus_infty, minus_zero, -M_PI_2l); + + TEST_c_c (catanh, -10.0, plus_infty, minus_zero, M_PI_2l); + TEST_c_c (catanh, -10.0, minus_infty, minus_zero, -M_PI_2l); + TEST_c_c (catanh, minus_zero, plus_infty, minus_zero, M_PI_2l); + TEST_c_c (catanh, minus_zero, minus_infty, minus_zero, -M_PI_2l); + TEST_c_c (catanh, 0, plus_infty, 0.0, M_PI_2l); + TEST_c_c (catanh, 0, minus_infty, 0.0, -M_PI_2l); + TEST_c_c (catanh, 0.1L, plus_infty, 0.0, M_PI_2l); + TEST_c_c (catanh, 0.1L, minus_infty, 0.0, -M_PI_2l); + + TEST_c_c (catanh, minus_infty, 0, minus_zero, M_PI_2l); + TEST_c_c (catanh, minus_infty, minus_zero, minus_zero, -M_PI_2l); + TEST_c_c (catanh, minus_infty, 100, minus_zero, M_PI_2l); + TEST_c_c (catanh, minus_infty, -100, minus_zero, -M_PI_2l); + + TEST_c_c (catanh, plus_infty, 0, 0.0, M_PI_2l); + TEST_c_c (catanh, plus_infty, minus_zero, 0.0, -M_PI_2l); + TEST_c_c (catanh, plus_infty, 0.5, 0.0, M_PI_2l); + TEST_c_c (catanh, plus_infty, -0.5, 0.0, -M_PI_2l); + + TEST_c_c (catanh, 0, nan_value, 0.0, nan_value); + TEST_c_c (catanh, minus_zero, nan_value, minus_zero, nan_value); + + TEST_c_c (catanh, plus_infty, nan_value, 0.0, nan_value); + TEST_c_c (catanh, minus_infty, nan_value, minus_zero, nan_value); + + TEST_c_c (catanh, nan_value, 0, nan_value, nan_value); + TEST_c_c (catanh, nan_value, minus_zero, nan_value, nan_value); + + TEST_c_c (catanh, nan_value, plus_infty, 0.0, M_PI_2l, IGNORE_ZERO_INF_SIGN); + TEST_c_c (catanh, nan_value, minus_infty, 0.0, -M_PI_2l, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (catanh, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (catanh, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (catanh, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (catanh, nan_value, -0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (catanh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (catanh, 0.7L, 1.2L, 0.2600749516525135959200648705635915L, 0.97024030779509898497385130162655963L); + TEST_c_c (catanh, -2, -3, -0.14694666622552975204743278515471595L, -1.3389725222944935611241935759091443L); + + END (catanh, complex); +} +#endif + +static void +cbrt_test (void) +{ + errno = 0; + FUNC(cbrt) (8); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cbrt); + + TEST_f_f (cbrt, 0.0, 0.0); + TEST_f_f (cbrt, minus_zero, minus_zero); + + TEST_f_f (cbrt, plus_infty, plus_infty); + TEST_f_f (cbrt, minus_infty, minus_infty); + TEST_f_f (cbrt, nan_value, nan_value); + + TEST_f_f (cbrt, -0.001L, -0.1L); + TEST_f_f (cbrt, 8, 2); + TEST_f_f (cbrt, -27.0, -3.0); + TEST_f_f (cbrt, 0.970299L, 0.99L); + TEST_f_f (cbrt, 0.7L, 0.8879040017426007084L); + + END (cbrt); +} + +#if 0 +static void +ccos_test (void) +{ + errno = 0; + FUNC(ccos) (BUILD_COMPLEX (0, 0)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (ccos); + + TEST_c_c (ccos, 0.0, 0.0, 1.0, minus_zero); + TEST_c_c (ccos, minus_zero, 0.0, 1.0, 0.0); + TEST_c_c (ccos, 0.0, minus_zero, 1.0, 0.0); + TEST_c_c (ccos, minus_zero, minus_zero, 1.0, minus_zero); + + TEST_c_c (ccos, plus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccos, plus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccos, minus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccos, minus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccos, 0.0, plus_infty, plus_infty, minus_zero); + TEST_c_c (ccos, 0.0, minus_infty, plus_infty, 0.0); + TEST_c_c (ccos, minus_zero, plus_infty, plus_infty, 0.0); + TEST_c_c (ccos, minus_zero, minus_infty, plus_infty, minus_zero); + + TEST_c_c (ccos, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, minus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ccos, 4.625, plus_infty, minus_infty, plus_infty); + TEST_c_c (ccos, 4.625, minus_infty, minus_infty, minus_infty); + TEST_c_c (ccos, -4.625, plus_infty, minus_infty, minus_infty); + TEST_c_c (ccos, -4.625, minus_infty, minus_infty, plus_infty); + + TEST_c_c (ccos, plus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, plus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, minus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, minus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ccos, nan_value, 0.0, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccos, nan_value, minus_zero, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccos, nan_value, plus_infty, plus_infty, nan_value); + TEST_c_c (ccos, nan_value, minus_infty, plus_infty, nan_value); + + TEST_c_c (ccos, nan_value, 9.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccos, nan_value, -9.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccos, 0.0, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccos, minus_zero, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccos, 10.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccos, -10.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccos, plus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccos, minus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccos, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (ccos, 0.7L, 1.2L, 1.3848657645312111080L, -0.97242170335830028619L); + + TEST_c_c (ccos, -2, -3, -4.1896256909688072301L, -9.1092278937553365979L); + + END (ccos, complex); +} + + +static void +ccosh_test (void) +{ + errno = 0; + FUNC(ccosh) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (ccosh); + + TEST_c_c (ccosh, 0.0, 0.0, 1.0, 0.0); + TEST_c_c (ccosh, minus_zero, 0.0, 1.0, minus_zero); + TEST_c_c (ccosh, 0.0, minus_zero, 1.0, minus_zero); + TEST_c_c (ccosh, minus_zero, minus_zero, 1.0, 0.0); + + TEST_c_c (ccosh, 0.0, plus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccosh, minus_zero, plus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccosh, 0.0, minus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccosh, minus_zero, minus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccosh, plus_infty, 0.0, plus_infty, 0.0); + TEST_c_c (ccosh, minus_infty, 0.0, plus_infty, minus_zero); + TEST_c_c (ccosh, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (ccosh, minus_infty, minus_zero, plus_infty, 0.0); + + TEST_c_c (ccosh, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, minus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ccosh, plus_infty, 4.625, minus_infty, minus_infty); + TEST_c_c (ccosh, minus_infty, 4.625, minus_infty, plus_infty); + TEST_c_c (ccosh, plus_infty, -4.625, minus_infty, plus_infty); + TEST_c_c (ccosh, minus_infty, -4.625, minus_infty, minus_infty); + + TEST_c_c (ccosh, 6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, -6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, 6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, -6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ccosh, 0.0, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccosh, minus_zero, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccosh, plus_infty, nan_value, plus_infty, nan_value); + TEST_c_c (ccosh, minus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (ccosh, 9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccosh, -9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccosh, nan_value, 0.0, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccosh, nan_value, minus_zero, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccosh, nan_value, 10.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccosh, nan_value, -10.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccosh, nan_value, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccosh, nan_value, minus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccosh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (ccosh, 0.7L, 1.2L, 0.4548202223691477654L, 0.7070296600921537682L); + + TEST_c_c (ccosh, -2, -3, -3.7245455049153225654L, 0.5118225699873846088L); + + END (ccosh, complex); +} +#endif + +static void +ceil_test (void) +{ + START (ceil); + + TEST_f_f (ceil, 0.0, 0.0); + TEST_f_f (ceil, minus_zero, minus_zero); + TEST_f_f (ceil, plus_infty, plus_infty); + TEST_f_f (ceil, minus_infty, minus_infty); + TEST_f_f (ceil, nan_value, nan_value); + + TEST_f_f (ceil, M_PIl, 4.0); + TEST_f_f (ceil, -M_PIl, -3.0); + + END (ceil); +} + +#if 0 +static void +cexp_test (void) +{ + errno = 0; + FUNC(cexp) (BUILD_COMPLEX (0, 0)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cexp); + + TEST_c_c (cexp, plus_zero, plus_zero, 1, 0.0); + TEST_c_c (cexp, minus_zero, plus_zero, 1, 0.0); + TEST_c_c (cexp, plus_zero, minus_zero, 1, minus_zero); + TEST_c_c (cexp, minus_zero, minus_zero, 1, minus_zero); + + TEST_c_c (cexp, plus_infty, plus_zero, plus_infty, 0.0); + TEST_c_c (cexp, plus_infty, minus_zero, plus_infty, minus_zero); + + TEST_c_c (cexp, minus_infty, plus_zero, 0.0, 0.0); + TEST_c_c (cexp, minus_infty, minus_zero, 0.0, minus_zero); + + TEST_c_c (cexp, 0.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (cexp, minus_zero, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (cexp, 0.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (cexp, minus_zero, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (cexp, 100.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (cexp, -100.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (cexp, 100.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (cexp, -100.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (cexp, minus_infty, 2.0, minus_zero, 0.0); + TEST_c_c (cexp, minus_infty, 4.0, minus_zero, minus_zero); + TEST_c_c (cexp, plus_infty, 2.0, minus_infty, plus_infty); + TEST_c_c (cexp, plus_infty, 4.0, minus_infty, minus_infty); + + TEST_c_c (cexp, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (cexp, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (cexp, minus_infty, plus_infty, 0.0, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (cexp, minus_infty, minus_infty, 0.0, minus_zero, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (cexp, minus_infty, nan_value, 0, 0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (cexp, plus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (cexp, nan_value, 0.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cexp, nan_value, 1.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (cexp, nan_value, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cexp, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cexp, 1, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cexp, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (cexp, 0.7L, 1.2L, 0.72969890915032360123451688642930727L, 1.8768962328348102821139467908203072L); + TEST_c_c (cexp, -2.0, -3.0, -0.13398091492954261346140525546115575L, -0.019098516261135196432576240858800925L); + + END (cexp, complex); +} + +static void +cimag_test (void) +{ + START (cimag); + TEST_c_f (cimag, 1.0, 0.0, 0.0); + TEST_c_f (cimag, 1.0, minus_zero, minus_zero); + TEST_c_f (cimag, 1.0, nan_value, nan_value); + TEST_c_f (cimag, nan_value, nan_value, nan_value); + TEST_c_f (cimag, 1.0, plus_infty, plus_infty); + TEST_c_f (cimag, 1.0, minus_infty, minus_infty); + TEST_c_f (cimag, 2.0, 3.0, 3.0); + + END (cimag); +} + +static void +clog_test (void) +{ + errno = 0; + FUNC(clog) (BUILD_COMPLEX (-2, -3)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (clog); + + TEST_c_c (clog, minus_zero, 0, minus_infty, M_PIl, DIVIDE_BY_ZERO_EXCEPTION); + TEST_c_c (clog, minus_zero, minus_zero, minus_infty, -M_PIl, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_c_c (clog, 0, 0, minus_infty, 0.0, DIVIDE_BY_ZERO_EXCEPTION); + TEST_c_c (clog, 0, minus_zero, minus_infty, minus_zero, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_c_c (clog, minus_infty, plus_infty, plus_infty, M_PI_34l); + TEST_c_c (clog, minus_infty, minus_infty, plus_infty, -M_PI_34l); + + TEST_c_c (clog, plus_infty, plus_infty, plus_infty, M_PI_4l); + TEST_c_c (clog, plus_infty, minus_infty, plus_infty, -M_PI_4l); + + TEST_c_c (clog, 0, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (clog, 3, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (clog, minus_zero, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (clog, -3, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (clog, 0, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (clog, 3, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (clog, minus_zero, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (clog, -3, minus_infty, plus_infty, -M_PI_2l); + + TEST_c_c (clog, minus_infty, 0, plus_infty, M_PIl); + TEST_c_c (clog, minus_infty, 1, plus_infty, M_PIl); + TEST_c_c (clog, minus_infty, minus_zero, plus_infty, -M_PIl); + TEST_c_c (clog, minus_infty, -1, plus_infty, -M_PIl); + + TEST_c_c (clog, plus_infty, 0, plus_infty, 0.0); + TEST_c_c (clog, plus_infty, 1, plus_infty, 0.0); + TEST_c_c (clog, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (clog, plus_infty, -1, plus_infty, minus_zero); + + TEST_c_c (clog, plus_infty, nan_value, plus_infty, nan_value); + TEST_c_c (clog, minus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (clog, nan_value, plus_infty, plus_infty, nan_value); + TEST_c_c (clog, nan_value, minus_infty, plus_infty, nan_value); + + TEST_c_c (clog, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, 3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, -3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (clog, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, nan_value, 5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, nan_value, -5, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (clog, nan_value, nan_value, nan_value, nan_value); + TEST_c_c (clog, -2, -3, 1.2824746787307683680267437207826593L, -2.1587989303424641704769327722648368L); + + END (clog, complex); +} + + +static void +clog10_test (void) +{ + errno = 0; + FUNC(clog10) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (clog10); + + TEST_c_c (clog10, minus_zero, 0, minus_infty, M_PIl, DIVIDE_BY_ZERO_EXCEPTION); + TEST_c_c (clog10, minus_zero, minus_zero, minus_infty, -M_PIl, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_c_c (clog10, 0, 0, minus_infty, 0.0, DIVIDE_BY_ZERO_EXCEPTION); + TEST_c_c (clog10, 0, minus_zero, minus_infty, minus_zero, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_c_c (clog10, minus_infty, plus_infty, plus_infty, M_PI_34_LOG10El); + + TEST_c_c (clog10, plus_infty, plus_infty, plus_infty, M_PI4_LOG10El); + TEST_c_c (clog10, plus_infty, minus_infty, plus_infty, -M_PI4_LOG10El); + + TEST_c_c (clog10, 0, plus_infty, plus_infty, M_PI2_LOG10El); + TEST_c_c (clog10, 3, plus_infty, plus_infty, M_PI2_LOG10El); + TEST_c_c (clog10, minus_zero, plus_infty, plus_infty, M_PI2_LOG10El); + TEST_c_c (clog10, -3, plus_infty, plus_infty, M_PI2_LOG10El); + TEST_c_c (clog10, 0, minus_infty, plus_infty, -M_PI2_LOG10El); + TEST_c_c (clog10, 3, minus_infty, plus_infty, -M_PI2_LOG10El); + TEST_c_c (clog10, minus_zero, minus_infty, plus_infty, -M_PI2_LOG10El); + TEST_c_c (clog10, -3, minus_infty, plus_infty, -M_PI2_LOG10El); + + TEST_c_c (clog10, minus_infty, 0, plus_infty, M_PI_LOG10El); + TEST_c_c (clog10, minus_infty, 1, plus_infty, M_PI_LOG10El); + TEST_c_c (clog10, minus_infty, minus_zero, plus_infty, -M_PI_LOG10El); + TEST_c_c (clog10, minus_infty, -1, plus_infty, -M_PI_LOG10El); + + TEST_c_c (clog10, plus_infty, 0, plus_infty, 0.0); + TEST_c_c (clog10, plus_infty, 1, plus_infty, 0.0); + TEST_c_c (clog10, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (clog10, plus_infty, -1, plus_infty, minus_zero); + + TEST_c_c (clog10, plus_infty, nan_value, plus_infty, nan_value); + TEST_c_c (clog10, minus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (clog10, nan_value, plus_infty, plus_infty, nan_value); + TEST_c_c (clog10, nan_value, minus_infty, plus_infty, nan_value); + + TEST_c_c (clog10, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, 3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, -3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (clog10, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, nan_value, 5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, nan_value, -5, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (clog10, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (clog10, 0.7L, 1.2L, 0.1427786545038868803L, 0.4528483579352493248L); + TEST_c_c (clog10, -2, -3, 0.5569716761534183846L, -0.9375544629863747085L); + + END (clog10, complex); +} +#endif + +static void +conj_test (void) +{ + START (conj); + TEST_c_c (conj, 0.0, 0.0, 0.0, minus_zero); + TEST_c_c (conj, 0.0, minus_zero, 0.0, 0.0); + TEST_c_c (conj, nan_value, nan_value, nan_value, nan_value); + TEST_c_c (conj, plus_infty, minus_infty, plus_infty, plus_infty); + TEST_c_c (conj, plus_infty, plus_infty, plus_infty, minus_infty); + TEST_c_c (conj, 1.0, 2.0, 1.0, -2.0); + TEST_c_c (conj, 3.0, -4.0, 3.0, 4.0); + + END (conj, complex); +} + + +static void +copysign_test (void) +{ + START (copysign); + + TEST_ff_f (copysign, 0, 4, 0); + TEST_ff_f (copysign, 0, -4, minus_zero); + TEST_ff_f (copysign, minus_zero, 4, 0); + TEST_ff_f (copysign, minus_zero, -4, minus_zero); + + TEST_ff_f (copysign, plus_infty, 0, plus_infty); + TEST_ff_f (copysign, plus_infty, minus_zero, minus_infty); + TEST_ff_f (copysign, minus_infty, 0, plus_infty); + TEST_ff_f (copysign, minus_infty, minus_zero, minus_infty); + + TEST_ff_f (copysign, 0, plus_infty, 0); + TEST_ff_f (copysign, 0, minus_zero, minus_zero); + TEST_ff_f (copysign, minus_zero, plus_infty, 0); + TEST_ff_f (copysign, minus_zero, minus_zero, minus_zero); + + /* XXX More correctly we would have to check the sign of the NaN. */ + TEST_ff_f (copysign, nan_value, 0, nan_value); + TEST_ff_f (copysign, nan_value, minus_zero, nan_value); + TEST_ff_f (copysign, -nan_value, 0, nan_value); + TEST_ff_f (copysign, -nan_value, minus_zero, nan_value); + + END (copysign); +} + +static void +cos_test (void) +{ + errno = 0; + FUNC(cos) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cos); + + TEST_f_f (cos, 0, 1); + TEST_f_f (cos, minus_zero, 1); + TEST_f_f (cos, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (cos, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (cos, nan_value, nan_value); + + TEST_f_f (cos, M_PI_6l * 2.0, 0.5); + TEST_f_f (cos, M_PI_6l * 4.0, -0.5); + TEST_f_f (cos, M_PI_2l, 0); + + TEST_f_f (cos, 0.7L, 0.76484218728448842625585999019186495L); + + END (cos); +} + +static void +cosh_test (void) +{ + errno = 0; + FUNC(cosh) (0.7L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cosh); + TEST_f_f (cosh, 0, 1); + TEST_f_f (cosh, minus_zero, 1); + +#ifndef TEST_INLINE + TEST_f_f (cosh, plus_infty, plus_infty); + TEST_f_f (cosh, minus_infty, plus_infty); +#endif + TEST_f_f (cosh, nan_value, nan_value); + + TEST_f_f (cosh, 0.7L, 1.255169005630943018L); + END (cosh); +} + +#if 0 +static void +cpow_test (void) +{ + errno = 0; + FUNC(cpow) (BUILD_COMPLEX (1, 0), BUILD_COMPLEX (0, 0)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cpow); + + TEST_cc_c (cpow, 1, 0, 0, 0, 1.0, 0.0); + TEST_cc_c (cpow, 2, 0, 10, 0, 1024.0, 0.0); + + TEST_cc_c (cpow, M_El, 0, 0, 2 * M_PIl, 1.0, 0.0); + TEST_cc_c (cpow, 2, 3, 4, 0, -119.0, -120.0); + + TEST_cc_c (cpow, nan_value, nan_value, nan_value, nan_value, nan_value, nan_value); + + END (cpow, complex); +} + +static void +cproj_test (void) +{ + START (cproj); + TEST_c_c (cproj, 0.0, 0.0, 0.0, 0.0); + TEST_c_c (cproj, minus_zero, minus_zero, minus_zero, minus_zero); + TEST_c_c (cproj, 0.0, minus_zero, 0.0, minus_zero); + TEST_c_c (cproj, minus_zero, 0.0, minus_zero, 0.0); + + TEST_c_c (cproj, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (cproj, plus_infty, plus_infty, plus_infty, 0.0); + TEST_c_c (cproj, plus_infty, minus_infty, plus_infty, minus_zero); + TEST_c_c (cproj, minus_infty, plus_infty, plus_infty, 0.0); + TEST_c_c (cproj, minus_infty, minus_infty, plus_infty, minus_zero); + + TEST_c_c (cproj, 1.0, 0.0, 1.0, 0.0); + TEST_c_c (cproj, 2.0, 3.0, 0.2857142857142857142857142857142857L, 0.42857142857142857142857142857142855L); + + END (cproj, complex); +} + +static void +creal_test (void) +{ + START (creal); + TEST_c_f (creal, 0.0, 1.0, 0.0); + TEST_c_f (creal, minus_zero, 1.0, minus_zero); + TEST_c_f (creal, nan_value, 1.0, nan_value); + TEST_c_f (creal, nan_value, nan_value, nan_value); + TEST_c_f (creal, plus_infty, 1.0, plus_infty); + TEST_c_f (creal, minus_infty, 1.0, minus_infty); + TEST_c_f (creal, 2.0, 3.0, 2.0); + + END (creal); +} + +static void +csin_test (void) +{ + errno = 0; + FUNC(csin) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (csin); + + TEST_c_c (csin, 0.0, 0.0, 0.0, 0.0); + TEST_c_c (csin, minus_zero, 0.0, minus_zero, 0.0); + TEST_c_c (csin, 0.0, minus_zero, 0, minus_zero); + TEST_c_c (csin, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (csin, 0.0, plus_infty, 0.0, plus_infty); + TEST_c_c (csin, minus_zero, plus_infty, minus_zero, plus_infty); + TEST_c_c (csin, 0.0, minus_infty, 0.0, minus_infty); + TEST_c_c (csin, minus_zero, minus_infty, minus_zero, minus_infty); + + TEST_c_c (csin, plus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, minus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, plus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, minus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csin, plus_infty, plus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, minus_infty, plus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, plus_infty, minus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, minus_infty, minus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csin, plus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csin, plus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csin, minus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csin, minus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (csin, 4.625, plus_infty, minus_infty, minus_infty); + TEST_c_c (csin, 4.625, minus_infty, minus_infty, plus_infty); + TEST_c_c (csin, -4.625, plus_infty, plus_infty, minus_infty); + TEST_c_c (csin, -4.625, minus_infty, plus_infty, plus_infty); + + TEST_c_c (csin, nan_value, 0.0, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, nan_value, minus_zero, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csin, nan_value, plus_infty, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, nan_value, minus_infty, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csin, nan_value, 9.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csin, nan_value, -9.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csin, 0.0, nan_value, 0.0, nan_value); + TEST_c_c (csin, minus_zero, nan_value, minus_zero, nan_value); + + TEST_c_c (csin, 10.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csin, nan_value, -10.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csin, plus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csin, minus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csin, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (csin, 0.7L, 1.2L, 1.1664563419657581376L, 1.1544997246948547371L); + + TEST_c_c (csin, -2, -3, -9.1544991469114295734L, 4.1689069599665643507L); + + END (csin, complex); +} + + +static void +csinh_test (void) +{ + errno = 0; + FUNC(csinh) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (csinh); + + TEST_c_c (csinh, 0.0, 0.0, 0.0, 0.0); + TEST_c_c (csinh, minus_zero, 0.0, minus_zero, 0.0); + TEST_c_c (csinh, 0.0, minus_zero, 0.0, minus_zero); + TEST_c_c (csinh, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (csinh, 0.0, plus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_zero, plus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, 0.0, minus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_zero, minus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csinh, plus_infty, 0.0, plus_infty, 0.0); + TEST_c_c (csinh, minus_infty, 0.0, minus_infty, 0.0); + TEST_c_c (csinh, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (csinh, minus_infty, minus_zero, minus_infty, minus_zero); + + TEST_c_c (csinh, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csinh, plus_infty, 4.625, minus_infty, minus_infty); + TEST_c_c (csinh, minus_infty, 4.625, plus_infty, minus_infty); + TEST_c_c (csinh, plus_infty, -4.625, minus_infty, plus_infty); + TEST_c_c (csinh, minus_infty, -4.625, plus_infty, plus_infty); + + TEST_c_c (csinh, 6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csinh, -6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csinh, 6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csinh, -6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (csinh, 0.0, nan_value, 0.0, nan_value, IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_zero, nan_value, 0.0, nan_value, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csinh, plus_infty, nan_value, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_infty, nan_value, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csinh, 9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csinh, -9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csinh, nan_value, 0.0, nan_value, 0.0); + TEST_c_c (csinh, nan_value, minus_zero, nan_value, minus_zero); + + TEST_c_c (csinh, nan_value, 10.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csinh, nan_value, -10.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csinh, nan_value, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csinh, nan_value, minus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csinh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (csinh, 0.7L, 1.2L, 0.27487868678117583582L, 1.1698665727426565139L); + TEST_c_c (csinh, -2, -3, 3.5905645899857799520L, -0.5309210862485198052L); + + END (csinh, complex); +} + +static void +csqrt_test (void) +{ + errno = 0; + FUNC(csqrt) (BUILD_COMPLEX (-1, 0)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (csqrt); + + TEST_c_c (csqrt, 0, 0, 0.0, 0.0); + TEST_c_c (csqrt, 0, minus_zero, 0, minus_zero); + TEST_c_c (csqrt, minus_zero, 0, 0.0, 0.0); + TEST_c_c (csqrt, minus_zero, minus_zero, 0.0, minus_zero); + + TEST_c_c (csqrt, minus_infty, 0, 0.0, plus_infty); + TEST_c_c (csqrt, minus_infty, 6, 0.0, plus_infty); + TEST_c_c (csqrt, minus_infty, minus_zero, 0.0, minus_infty); + TEST_c_c (csqrt, minus_infty, -6, 0.0, minus_infty); + + TEST_c_c (csqrt, plus_infty, 0, plus_infty, 0.0); + TEST_c_c (csqrt, plus_infty, 6, plus_infty, 0.0); + TEST_c_c (csqrt, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (csqrt, plus_infty, -6, plus_infty, minus_zero); + + TEST_c_c (csqrt, 0, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, 4, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, plus_infty, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, minus_zero, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, -4, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, minus_infty, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, 0, minus_infty, plus_infty, minus_infty); + TEST_c_c (csqrt, 4, minus_infty, plus_infty, minus_infty); + TEST_c_c (csqrt, plus_infty, minus_infty, plus_infty, minus_infty); + TEST_c_c (csqrt, minus_zero, minus_infty, plus_infty, minus_infty); + TEST_c_c (csqrt, -4, minus_infty, plus_infty, minus_infty); + TEST_c_c (csqrt, minus_infty, minus_infty, plus_infty, minus_infty); + + TEST_c_c (csqrt, minus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csqrt, plus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (csqrt, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, 1, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, -1, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csqrt, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, nan_value, 8, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, nan_value, -8, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csqrt, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (csqrt, 16.0, -30.0, 5.0, -3.0); + TEST_c_c (csqrt, -1, 0, 0.0, 1.0); + TEST_c_c (csqrt, 0, 2, 1.0, 1.0); + TEST_c_c (csqrt, 119, 120, 12.0, 5.0); + TEST_c_c (csqrt, 0.7L, 1.2L, 1.022067610030026450706487883081139L, 0.58704531296356521154977678719838035L); + TEST_c_c (csqrt, -2, -3, 0.89597747612983812471573375529004348L, -1.6741492280355400404480393008490519L); + TEST_c_c (csqrt, -2, 3, 0.89597747612983812471573375529004348L, 1.6741492280355400404480393008490519L); + + END (csqrt, complex); +} + +static void +ctan_test (void) +{ + errno = 0; + FUNC(ctan) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (ctan); + + TEST_c_c (ctan, 0, 0, 0.0, 0.0); + TEST_c_c (ctan, 0, minus_zero, 0.0, minus_zero); + TEST_c_c (ctan, minus_zero, 0, minus_zero, 0.0); + TEST_c_c (ctan, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (ctan, 0, plus_infty, 0.0, 1.0); + TEST_c_c (ctan, 1, plus_infty, 0.0, 1.0); + TEST_c_c (ctan, minus_zero, plus_infty, minus_zero, 1.0); + TEST_c_c (ctan, -1, plus_infty, minus_zero, 1.0); + + TEST_c_c (ctan, 0, minus_infty, 0.0, -1.0); + TEST_c_c (ctan, 1, minus_infty, 0.0, -1.0); + TEST_c_c (ctan, minus_zero, minus_infty, minus_zero, -1.0); + TEST_c_c (ctan, -1, minus_infty, minus_zero, -1.0); + + TEST_c_c (ctan, plus_infty, 0, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, plus_infty, 2, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, minus_infty, 0, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, minus_infty, 2, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, plus_infty, minus_zero, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, plus_infty, -2, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, minus_infty, minus_zero, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, minus_infty, -2, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ctan, nan_value, plus_infty, 0.0, 1.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ctan, nan_value, minus_infty, 0.0, -1.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ctan, 0, nan_value, 0.0, nan_value); + TEST_c_c (ctan, minus_zero, nan_value, minus_zero, nan_value); + + TEST_c_c (ctan, 0.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctan, -4.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ctan, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctan, nan_value, 5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctan, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctan, nan_value, -0.25, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ctan, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (ctan, 0.7L, 1.2L, 0.1720734197630349001L, 0.9544807059989405538L); + TEST_c_c (ctan, -2, -3, 0.0037640256415042482L, -1.0032386273536098014L); + + END (ctan, complex); +} + + +static void +ctanh_test (void) +{ + errno = 0; + FUNC(ctanh) (BUILD_COMPLEX (0, 0)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (ctanh); + + TEST_c_c (ctanh, 0, 0, 0.0, 0.0); + TEST_c_c (ctanh, 0, minus_zero, 0.0, minus_zero); + TEST_c_c (ctanh, minus_zero, 0, minus_zero, 0.0); + TEST_c_c (ctanh, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (ctanh, plus_infty, 0, 1.0, 0.0); + TEST_c_c (ctanh, plus_infty, 1, 1.0, 0.0); + TEST_c_c (ctanh, plus_infty, minus_zero, 1.0, minus_zero); + TEST_c_c (ctanh, plus_infty, -1, 1.0, minus_zero); + TEST_c_c (ctanh, minus_infty, 0, -1.0, 0.0); + TEST_c_c (ctanh, minus_infty, 1, -1.0, 0.0); + TEST_c_c (ctanh, minus_infty, minus_zero, -1.0, minus_zero); + TEST_c_c (ctanh, minus_infty, -1, -1.0, minus_zero); + + TEST_c_c (ctanh, 0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, 2, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, 0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, 2, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, minus_zero, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, -2, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, minus_zero, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, -2, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ctanh, plus_infty, nan_value, 1.0, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ctanh, minus_infty, nan_value, -1.0, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ctanh, nan_value, 0, nan_value, 0.0); + TEST_c_c (ctanh, nan_value, minus_zero, nan_value, minus_zero); + + TEST_c_c (ctanh, nan_value, 0.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctanh, nan_value, -4.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ctanh, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctanh, 5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctanh, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctanh, -0.25, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ctanh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (ctanh, 0, M_PI_4l, 0.0, 1.0); + + TEST_c_c (ctanh, 0.7L, 1.2L, 1.3472197399061191630L, 0.4778641038326365540L); + TEST_c_c (ctanh, -2, -3, -0.9653858790221331242L, 0.0098843750383224937L); + + END (ctanh, complex); +} +#endif + +static void +erf_test (void) +{ + errno = 0; + FUNC(erf) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (erf); + + TEST_f_f (erf, 0, 0); + TEST_f_f (erf, minus_zero, minus_zero); + TEST_f_f (erf, plus_infty, 1); + TEST_f_f (erf, minus_infty, -1); + TEST_f_f (erf, nan_value, nan_value); + + TEST_f_f (erf, 0.7L, 0.67780119383741847297L); + + TEST_f_f (erf, 1.2L, 0.91031397822963538024L); + TEST_f_f (erf, 2.0, 0.99532226501895273416L); + TEST_f_f (erf, 4.1L, 0.99999999329997234592L); + TEST_f_f (erf, 27, 1.0L); + + END (erf); +} + + +static void +erfc_test (void) +{ + errno = 0; + FUNC(erfc) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (erfc); + + TEST_f_f (erfc, plus_infty, 0.0); + TEST_f_f (erfc, minus_infty, 2.0); + TEST_f_f (erfc, 0.0, 1.0); + TEST_f_f (erfc, minus_zero, 1.0); + TEST_f_f (erfc, nan_value, nan_value); + + TEST_f_f (erfc, 0.7L, 0.32219880616258152702L); + + TEST_f_f (erfc, 1.2L, 0.089686021770364619762L); + TEST_f_f (erfc, 2.0, 0.0046777349810472658379L); + TEST_f_f (erfc, 4.1L, 0.67000276540848983727e-8L); + TEST_f_f (erfc, 9, 0.41370317465138102381e-36L); + + END (erfc); +} + +static void +exp_test (void) +{ + errno = 0; + FUNC(exp) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (exp); + + TEST_f_f (exp, 0, 1); + TEST_f_f (exp, minus_zero, 1); + +#ifndef TEST_INLINE + TEST_f_f (exp, plus_infty, plus_infty); + TEST_f_f (exp, minus_infty, 0); +#endif + TEST_f_f (exp, nan_value, nan_value); + TEST_f_f (exp, 1, M_El); + + TEST_f_f (exp, 2, M_E2l); + TEST_f_f (exp, 3, M_E3l); + TEST_f_f (exp, 0.7L, 2.0137527074704765216L); + TEST_f_f (exp, 50.0L, 5184705528587072464087.45332293348538L); +#ifdef TEST_LDOUBLE + /* The result can only be represented in long double. */ + TEST_f_f (exp, 1000.0L, 0.197007111401704699388887935224332313e435L); +#endif + END (exp); +} + + +#if 0 +static void +exp10_test (void) +{ + errno = 0; + FUNC(exp10) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (exp10); + + TEST_f_f (exp10, 0, 1); + TEST_f_f (exp10, minus_zero, 1); + + TEST_f_f (exp10, plus_infty, plus_infty); + TEST_f_f (exp10, minus_infty, 0); + TEST_f_f (exp10, nan_value, nan_value); + TEST_f_f (exp10, 3, 1000); + TEST_f_f (exp10, -1, 0.1L); + TEST_f_f (exp10, 1e6, plus_infty); + TEST_f_f (exp10, -1e6, 0); + TEST_f_f (exp10, 0.7L, 5.0118723362727228500155418688494574L); + + END (exp10); +} + +static void +exp2_test (void) +{ + errno = 0; + FUNC(exp2) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (exp2); + + TEST_f_f (exp2, 0, 1); + TEST_f_f (exp2, minus_zero, 1); + TEST_f_f (exp2, plus_infty, plus_infty); + TEST_f_f (exp2, minus_infty, 0); + TEST_f_f (exp2, nan_value, nan_value); + + TEST_f_f (exp2, 10, 1024); + TEST_f_f (exp2, -1, 0.5); + TEST_f_f (exp2, 1e6, plus_infty); + TEST_f_f (exp2, -1e6, 0); + TEST_f_f (exp2, 0.7L, 1.6245047927124710452L); + + END (exp2); +} +#endif + +static void +expm1_test (void) +{ + errno = 0; + FUNC(expm1) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (expm1); + + TEST_f_f (expm1, 0, 0); + TEST_f_f (expm1, minus_zero, minus_zero); + +#ifndef TEST_INLINE + TEST_f_f (expm1, plus_infty, plus_infty); + TEST_f_f (expm1, minus_infty, -1); +#endif + TEST_f_f (expm1, nan_value, nan_value); + + TEST_f_f (expm1, 1, M_El - 1.0); + TEST_f_f (expm1, 0.7L, 1.0137527074704765216L); + + END (expm1); +} + +static void +fabs_test (void) +{ + START (fabs); + + TEST_f_f (fabs, 0, 0); + TEST_f_f (fabs, minus_zero, 0); + + TEST_f_f (fabs, plus_infty, plus_infty); + TEST_f_f (fabs, minus_infty, plus_infty); + TEST_f_f (fabs, nan_value, nan_value); + + TEST_f_f (fabs, 38.0, 38.0); + TEST_f_f (fabs, -M_El, M_El); + + END (fabs); +} + +#if 0 +static void +fdim_test (void) +{ + START (fdim); + + TEST_ff_f (fdim, 0, 0, 0); + TEST_ff_f (fdim, 9, 0, 9); + TEST_ff_f (fdim, 0, 9, 0); + TEST_ff_f (fdim, -9, 0, 0); + TEST_ff_f (fdim, 0, -9, 9); + + TEST_ff_f (fdim, plus_infty, 9, plus_infty); + TEST_ff_f (fdim, plus_infty, -9, plus_infty); + TEST_ff_f (fdim, minus_infty, 9, 0); + TEST_ff_f (fdim, minus_infty, -9, 0); + TEST_ff_f (fdim, 9, minus_infty, plus_infty); + TEST_ff_f (fdim, -9, minus_infty, plus_infty); + TEST_ff_f (fdim, 9, plus_infty, 0); + TEST_ff_f (fdim, -9, plus_infty, 0); + + TEST_ff_f (fdim, 0, nan_value, nan_value); + TEST_ff_f (fdim, 9, nan_value, nan_value); + TEST_ff_f (fdim, -9, nan_value, nan_value); + TEST_ff_f (fdim, nan_value, 9, nan_value); + TEST_ff_f (fdim, nan_value, -9, nan_value); + TEST_ff_f (fdim, plus_infty, nan_value, nan_value); + TEST_ff_f (fdim, minus_infty, nan_value, nan_value); + TEST_ff_f (fdim, nan_value, plus_infty, nan_value); + TEST_ff_f (fdim, nan_value, minus_infty, nan_value); + TEST_ff_f (fdim, nan_value, nan_value, nan_value); + + END (fdim); +} +#endif + +static void +floor_test (void) +{ + START (floor); + + TEST_f_f (floor, 0.0, 0.0); + TEST_f_f (floor, minus_zero, minus_zero); + TEST_f_f (floor, plus_infty, plus_infty); + TEST_f_f (floor, minus_infty, minus_infty); + TEST_f_f (floor, nan_value, nan_value); + + TEST_f_f (floor, M_PIl, 3.0); + TEST_f_f (floor, -M_PIl, -4.0); + + END (floor); +} + +#if 0 +static void +fma_test (void) +{ + START (fma); + + TEST_fff_f (fma, 1.0, 2.0, 3.0, 5.0); + TEST_fff_f (fma, nan_value, 2.0, 3.0, nan_value); + TEST_fff_f (fma, 1.0, nan_value, 3.0, nan_value); + TEST_fff_f (fma, 1.0, 2.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_fff_f (fma, plus_infty, 0.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_fff_f (fma, minus_infty, 0.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_fff_f (fma, 0.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_fff_f (fma, 0.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_fff_f (fma, plus_infty, 0.0, 1.0, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, minus_infty, 0.0, 1.0, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, 0.0, plus_infty, 1.0, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, 0.0, minus_infty, 1.0, nan_value, INVALID_EXCEPTION); + + TEST_fff_f (fma, plus_infty, plus_infty, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, minus_infty, minus_infty, minus_infty, nan_value, INVALID_EXCEPTION); + + END (fma); +} + + +static void +fmax_test (void) +{ + START (fmax); + + TEST_ff_f (fmax, 0, 0, 0); + TEST_ff_f (fmax, minus_zero, minus_zero, minus_zero); + TEST_ff_f (fmax, 9, 0, 9); + TEST_ff_f (fmax, 0, 9, 9); + TEST_ff_f (fmax, -9, 0, 0); + TEST_ff_f (fmax, 0, -9, 0); + + TEST_ff_f (fmax, plus_infty, 9, plus_infty); + TEST_ff_f (fmax, 0, plus_infty, plus_infty); + TEST_ff_f (fmax, -9, plus_infty, plus_infty); + TEST_ff_f (fmax, plus_infty, -9, plus_infty); + + TEST_ff_f (fmax, minus_infty, 9, 9); + TEST_ff_f (fmax, minus_infty, -9, -9); + TEST_ff_f (fmax, 9, minus_infty, 9); + TEST_ff_f (fmax, -9, minus_infty, -9); + + TEST_ff_f (fmax, 0, nan_value, 0); + TEST_ff_f (fmax, 9, nan_value, 9); + TEST_ff_f (fmax, -9, nan_value, -9); + TEST_ff_f (fmax, nan_value, 0, 0); + TEST_ff_f (fmax, nan_value, 9, 9); + TEST_ff_f (fmax, nan_value, -9, -9); + TEST_ff_f (fmax, plus_infty, nan_value, plus_infty); + TEST_ff_f (fmax, minus_infty, nan_value, minus_infty); + TEST_ff_f (fmax, nan_value, plus_infty, plus_infty); + TEST_ff_f (fmax, nan_value, minus_infty, minus_infty); + TEST_ff_f (fmax, nan_value, nan_value, nan_value); + + END (fmax); +} + + +static void +fmin_test (void) +{ + START (fmin); + + TEST_ff_f (fmin, 0, 0, 0); + TEST_ff_f (fmin, minus_zero, minus_zero, minus_zero); + TEST_ff_f (fmin, 9, 0, 0); + TEST_ff_f (fmin, 0, 9, 0); + TEST_ff_f (fmin, -9, 0, -9); + TEST_ff_f (fmin, 0, -9, -9); + + TEST_ff_f (fmin, plus_infty, 9, 9); + TEST_ff_f (fmin, 9, plus_infty, 9); + TEST_ff_f (fmin, plus_infty, -9, -9); + TEST_ff_f (fmin, -9, plus_infty, -9); + TEST_ff_f (fmin, minus_infty, 9, minus_infty); + TEST_ff_f (fmin, minus_infty, -9, minus_infty); + TEST_ff_f (fmin, 9, minus_infty, minus_infty); + TEST_ff_f (fmin, -9, minus_infty, minus_infty); + + TEST_ff_f (fmin, 0, nan_value, 0); + TEST_ff_f (fmin, 9, nan_value, 9); + TEST_ff_f (fmin, -9, nan_value, -9); + TEST_ff_f (fmin, nan_value, 0, 0); + TEST_ff_f (fmin, nan_value, 9, 9); + TEST_ff_f (fmin, nan_value, -9, -9); + TEST_ff_f (fmin, plus_infty, nan_value, plus_infty); + TEST_ff_f (fmin, minus_infty, nan_value, minus_infty); + TEST_ff_f (fmin, nan_value, plus_infty, plus_infty); + TEST_ff_f (fmin, nan_value, minus_infty, minus_infty); + TEST_ff_f (fmin, nan_value, nan_value, nan_value); + + END (fmin); +} +#endif + +static void +fmod_test (void) +{ + errno = 0; + FUNC(fmod) (6.5, 2.3L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (fmod); + + /* fmod (+0, y) == +0 for y != 0. */ + TEST_ff_f (fmod, 0, 3, 0); + + /* fmod (-0, y) == -0 for y != 0. */ + TEST_ff_f (fmod, minus_zero, 3, minus_zero); + + /* fmod (+inf, y) == NaN plus invalid exception. */ + TEST_ff_f (fmod, plus_infty, 3, nan_value, INVALID_EXCEPTION); + /* fmod (-inf, y) == NaN plus invalid exception. */ + TEST_ff_f (fmod, minus_infty, 3, nan_value, INVALID_EXCEPTION); + /* fmod (x, +0) == NaN plus invalid exception. */ + TEST_ff_f (fmod, 3, 0, nan_value, INVALID_EXCEPTION); + /* fmod (x, -0) == NaN plus invalid exception. */ + TEST_ff_f (fmod, 3, minus_zero, nan_value, INVALID_EXCEPTION); + + /* fmod (x, +inf) == x for x not infinite. */ + TEST_ff_f (fmod, 3.0, plus_infty, 3.0); + /* fmod (x, -inf) == x for x not infinite. */ + TEST_ff_f (fmod, 3.0, minus_infty, 3.0); + + TEST_ff_f (fmod, nan_value, nan_value, nan_value); + + TEST_ff_f (fmod, 6.5, 2.3L, 1.9L); + TEST_ff_f (fmod, -6.5, 2.3L, -1.9L); + TEST_ff_f (fmod, 6.5, -2.3L, 1.9L); + TEST_ff_f (fmod, -6.5, -2.3L, -1.9L); + + END (fmod); +} + +static void +fpclassify_test (void) +{ + START (fpclassify); + + TEST_f_i (fpclassify, nan_value, FP_NAN); + TEST_f_i (fpclassify, plus_infty, FP_INFINITE); + TEST_f_i (fpclassify, minus_infty, FP_INFINITE); + TEST_f_i (fpclassify, plus_zero, FP_ZERO); + TEST_f_i (fpclassify, minus_zero, FP_ZERO); + TEST_f_i (fpclassify, 1000, FP_NORMAL); + + END (fpclassify); +} + + +static void +frexp_test (void) +{ + int x; + + START (frexp); + + TEST_fI_f1 (frexp, plus_infty, plus_infty, IGNORE); + TEST_fI_f1 (frexp, minus_infty, minus_infty, IGNORE); + TEST_fI_f1 (frexp, nan_value, nan_value, IGNORE); + + TEST_fI_f1 (frexp, 0.0, 0.0, 0.0); + TEST_fI_f1 (frexp, minus_zero, minus_zero, 0.0); + + TEST_fI_f1 (frexp, 12.8L, 0.8L, 4); + TEST_fI_f1 (frexp, -27.34L, -0.854375L, 5); + + END (frexp); +} + + +static void +gamma_test (void) +{ + errno = 0; + FUNC(gamma) (1); + + if (errno == ENOSYS) + /* Function not implemented. */ + return; + feclearexcept (FE_ALL_EXCEPT); + + START (gamma); + + TEST_f_f (gamma, plus_infty, plus_infty); + TEST_f_f (gamma, 0, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (gamma, -3, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (gamma, minus_infty, plus_infty); + TEST_f_f (gamma, nan_value, nan_value); + + TEST_f_f1 (gamma, 1, 0, 1); + TEST_f_f1 (gamma, 3, M_LN2l, 1); + + TEST_f_f1 (gamma, 0.5, M_LOG_SQRT_PIl, 1); + TEST_f_f1 (gamma, -0.5, M_LOG_2_SQRT_PIl, -1); + + END (gamma); +} + +static void +hypot_test (void) +{ + errno = 0; + FUNC(hypot) (0.7L, 12.4L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (hypot); + + TEST_ff_f (hypot, plus_infty, 1, plus_infty, IGNORE_ZERO_INF_SIGN); + TEST_ff_f (hypot, minus_infty, 1, plus_infty, IGNORE_ZERO_INF_SIGN); + +#ifndef TEST_INLINE + TEST_ff_f (hypot, plus_infty, nan_value, plus_infty); + TEST_ff_f (hypot, minus_infty, nan_value, plus_infty); + TEST_ff_f (hypot, nan_value, plus_infty, plus_infty); + TEST_ff_f (hypot, nan_value, minus_infty, plus_infty); +#endif + + TEST_ff_f (hypot, nan_value, nan_value, nan_value); + + /* hypot (x,y) == hypot (+-x, +-y) */ + TEST_ff_f (hypot, 0.7L, 12.4L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, -0.7L, 12.4L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, 0.7L, -12.4L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, -0.7L, -12.4L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, 12.4L, 0.7L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, -12.4L, 0.7L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, 12.4L, -0.7L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, -12.4L, -0.7L, 12.419742348374220601176836866763271L); + + /* hypot (x,0) == fabs (x) */ + TEST_ff_f (hypot, 0.7L, 0, 0.7L); + TEST_ff_f (hypot, -0.7L, 0, 0.7L); + TEST_ff_f (hypot, -5.7e7, 0, 5.7e7L); + + TEST_ff_f (hypot, 0.7L, 1.2L, 1.3892443989449804508432547041028554L); + + END (hypot); +} + + +static void +ilogb_test (void) +{ + START (ilogb); + + TEST_f_i (ilogb, 1, 0); + TEST_f_i (ilogb, M_El, 1); + TEST_f_i (ilogb, 1024, 10); + TEST_f_i (ilogb, -2000, 10); + + /* XXX We have a problem here: the standard does not tell us whether + exceptions are allowed/required. ignore them for now. */ + + TEST_f_i (ilogb, 0.0, FP_ILOGB0, EXCEPTIONS_OK); + TEST_f_i (ilogb, nan_value, FP_ILOGBNAN, EXCEPTIONS_OK); + TEST_f_i (ilogb, plus_infty, INT_MAX, EXCEPTIONS_OK); + TEST_f_i (ilogb, minus_infty, INT_MAX, EXCEPTIONS_OK); + + END (ilogb); +} + +static void +isfinite_test (void) +{ + START (isfinite); + + TEST_f_b (isfinite, 0, 1); + TEST_f_b (isfinite, minus_zero, 1); + TEST_f_b (isfinite, 10, 1); + TEST_f_b (isfinite, plus_infty, 0); + TEST_f_b (isfinite, minus_infty, 0); + TEST_f_b (isfinite, nan_value, 0); + + END (isfinite); +} + +static void +isnormal_test (void) +{ + START (isnormal); + + TEST_f_b (isnormal, 0, 0); + TEST_f_b (isnormal, minus_zero, 0); + TEST_f_b (isnormal, 10, 1); + TEST_f_b (isnormal, plus_infty, 0); + TEST_f_b (isnormal, minus_infty, 0); + TEST_f_b (isnormal, nan_value, 0); + + END (isnormal); +} + +static void +j0_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(j0) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (j0); + + /* j0 is the Bessel function of the first kind of order 0 */ + TEST_f_f (j0, nan_value, nan_value); + TEST_f_f (j0, plus_infty, 0); + TEST_f_f (j0, -1.0, 0.76519768655796655145L); + TEST_f_f (j0, 0.0, 1.0); + TEST_f_f (j0, 0.1L, 0.99750156206604003228L); + TEST_f_f (j0, 0.7L, 0.88120088860740528084L); + TEST_f_f (j0, 1.0, 0.76519768655796655145L); + TEST_f_f (j0, 1.5, 0.51182767173591812875L); + TEST_f_f (j0, 2.0, 0.22389077914123566805L); + TEST_f_f (j0, 8.0, 0.17165080713755390609L); + TEST_f_f (j0, 10.0, -0.24593576445134833520L); + TEST_f_f (j0, 4.0, -3.9714980986384737228659076845169804197562E-1L); + TEST_f_f (j0, -4.0, -3.9714980986384737228659076845169804197562E-1L); + + END (j0); +} + + +static void +j1_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(j1) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + /* j1 is the Bessel function of the first kind of order 1 */ + + START (j1); + + TEST_f_f (j1, nan_value, nan_value); + TEST_f_f (j1, plus_infty, 0); + + TEST_f_f (j1, -1.0, -0.44005058574493351596L); + TEST_f_f (j1, 0.0, 0.0); + TEST_f_f (j1, 0.1L, 0.049937526036241997556L); + TEST_f_f (j1, 0.7L, 0.32899574154005894785L); + TEST_f_f (j1, 1.0, 0.44005058574493351596L); + TEST_f_f (j1, 1.5, 0.55793650791009964199L); + TEST_f_f (j1, 2.0, 0.57672480775687338720L); + TEST_f_f (j1, 8.0, 0.23463634685391462438L); + TEST_f_f (j1, 10.0, 0.043472746168861436670L); + + END (j1); +} + +static void +jn_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(jn) (1, 1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + /* jn is the Bessel function of the first kind of order n. */ + START (jn); + + /* jn (0, x) == j0 (x) */ + TEST_ff_f (jn, 0, nan_value, nan_value); + TEST_ff_f (jn, 0, plus_infty, 0); + TEST_ff_f (jn, 0, -1.0, 0.76519768655796655145L); + TEST_ff_f (jn, 0, 0.0, 1.0); + TEST_ff_f (jn, 0, 0.1L, 0.99750156206604003228L); + TEST_ff_f (jn, 0, 0.7L, 0.88120088860740528084L); + TEST_ff_f (jn, 0, 1.0, 0.76519768655796655145L); + TEST_ff_f (jn, 0, 1.5, 0.51182767173591812875L); + TEST_ff_f (jn, 0, 2.0, 0.22389077914123566805L); + TEST_ff_f (jn, 0, 8.0, 0.17165080713755390609L); + TEST_ff_f (jn, 0, 10.0, -0.24593576445134833520L); + + /* jn (1, x) == j1 (x) */ + TEST_ff_f (jn, 1, nan_value, nan_value); + TEST_ff_f (jn, 1, plus_infty, 0); + + TEST_ff_f (jn, 1, -1.0, -0.44005058574493351596L); + TEST_ff_f (jn, 1, 0.0, 0.0); + TEST_ff_f (jn, 1, 0.1L, 0.049937526036241997556L); + TEST_ff_f (jn, 1, 0.7L, 0.32899574154005894785L); + TEST_ff_f (jn, 1, 1.0, 0.44005058574493351596L); + TEST_ff_f (jn, 1, 1.5, 0.55793650791009964199L); + TEST_ff_f (jn, 1, 2.0, 0.57672480775687338720L); + TEST_ff_f (jn, 1, 8.0, 0.23463634685391462438L); + TEST_ff_f (jn, 1, 10.0, 0.043472746168861436670L); + + /* jn (3, x) */ + TEST_ff_f (jn, 3, nan_value, nan_value); + TEST_ff_f (jn, 3, plus_infty, 0); + + TEST_ff_f (jn, 3, -1.0, -0.019563353982668405919L); + TEST_ff_f (jn, 3, 0.0, 0.0); + TEST_ff_f (jn, 3, 0.1L, 0.000020820315754756261429L); + TEST_ff_f (jn, 3, 0.7L, 0.0069296548267508408077L); + TEST_ff_f (jn, 3, 1.0, 0.019563353982668405919L); + TEST_ff_f (jn, 3, 2.0, 0.12894324947440205110L); + TEST_ff_f (jn, 3, 10.0, 0.058379379305186812343L); + + /* jn (10, x) */ + TEST_ff_f (jn, 10, nan_value, nan_value); + TEST_ff_f (jn, 10, plus_infty, 0); + + TEST_ff_f (jn, 10, -1.0, 0.26306151236874532070e-9L); + TEST_ff_f (jn, 10, 0.0, 0.0); + TEST_ff_f (jn, 10, 0.1L, 0.26905328954342155795e-19L); + TEST_ff_f (jn, 10, 0.7L, 0.75175911502153953928e-11L); + TEST_ff_f (jn, 10, 1.0, 0.26306151236874532070e-9L); + TEST_ff_f (jn, 10, 2.0, 0.25153862827167367096e-6L); + TEST_ff_f (jn, 10, 10.0, 0.20748610663335885770L); + + END (jn); +} + + +static void +ldexp_test (void) +{ + TEST_ff_f (ldexp, 0, 0, 0); + TEST_ff_f (ldexp, minus_zero, 0, minus_zero); + + TEST_ff_f (ldexp, plus_infty, 1, plus_infty); + TEST_ff_f (ldexp, minus_infty, 1, minus_infty); + TEST_ff_f (ldexp, nan_value, 1, nan_value); + + TEST_ff_f (ldexp, 0.8L, 4, 12.8L); + TEST_ff_f (ldexp, -0.854375L, 5, -27.34L); + + /* ldexp (x, 0) == x. */ + TEST_ff_f (ldexp, 1.0L, 0L, 1.0L); +} + +static void +lgamma_test (void) +{ + errno = 0; + FUNC(lgamma) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + feclearexcept (FE_ALL_EXCEPT); + + START (lgamma); + + TEST_f_f (lgamma, plus_infty, plus_infty); + TEST_f_f (lgamma, 0, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (lgamma, nan_value, nan_value); + + /* lgamma (x) == +inf plus divide by zero exception for integer x <= 0. */ + TEST_f_f (lgamma, -3, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (lgamma, minus_infty, plus_infty); + + TEST_f_f1 (lgamma, 1, 0, 1); + + TEST_f_f1 (lgamma, 3, M_LN2l, 1); + + TEST_f_f1 (lgamma, 0.5, M_LOG_SQRT_PIl, 1); + TEST_f_f1 (lgamma, -0.5, M_LOG_2_SQRT_PIl, -1); + TEST_f_f1 (lgamma, 0.7L, 0.26086724653166651439L, 1); + TEST_f_f1 (lgamma, 1.2L, -0.853740900033158497197e-1L, 1); + + END (lgamma); +} + +#if 0 +static void +lrint_test (void) +{ + /* XXX this test is incomplete. We need to have a way to specifiy + the rounding method and test the critical cases. So far, only + unproblematic numbers are tested. */ + + START (lrint); + + TEST_f_l (lrint, 0.0, 0); + TEST_f_l (lrint, minus_zero, 0); + TEST_f_l (lrint, 0.2L, 0); + TEST_f_l (lrint, -0.2L, 0); + + TEST_f_l (lrint, 1.4L, 1); + TEST_f_l (lrint, -1.4L, -1); + + TEST_f_l (lrint, 8388600.3L, 8388600); + TEST_f_l (lrint, -8388600.3L, -8388600); + + END (lrint); +} + +static void +llrint_test (void) +{ + /* XXX this test is incomplete. We need to have a way to specifiy + the rounding method and test the critical cases. So far, only + unproblematic numbers are tested. */ + + START (llrint); + + TEST_f_L (llrint, 0.0, 0); + TEST_f_L (llrint, minus_zero, 0); + TEST_f_L (llrint, 0.2L, 0); + TEST_f_L (llrint, -0.2L, 0); + + TEST_f_L (llrint, 1.4L, 1); + TEST_f_L (llrint, -1.4L, -1); + + TEST_f_L (llrint, 8388600.3L, 8388600); + TEST_f_L (llrint, -8388600.3L, -8388600); + + /* Test boundary conditions. */ + /* 0x1FFFFF */ + TEST_f_L (llrint, 2097151.0,2097151LL); + /* 0x800000 */ + TEST_f_L (llrint, 8388608.0, 8388608LL); + /* 0x1000000 */ + TEST_f_L (llrint, 16777216.0, 16777216LL); + /* 0x20000000000 */ + TEST_f_L (llrint, 2199023255552.0, 2199023255552LL); + /* 0x40000000000 */ + TEST_f_L (llrint, 4398046511104.0, 4398046511104LL); + /* 0x10000000000000 */ + TEST_f_L (llrint, 4503599627370496.0, 4503599627370496LL); + /* 0x10000080000000 */ + TEST_f_L (llrint, 4503601774854144.0, 4503601774854144LL); + /* 0x20000000000000 */ + TEST_f_L (llrint, 9007199254740992.0, 9007199254740992LL); + /* 0x80000000000000 */ + TEST_f_L (llrint, 36028797018963968.0, 36028797018963968LL); + /* 0x100000000000000 */ + TEST_f_L (llrint, 72057594037927936.0, 72057594037927936LL); + + END (llrint); +} +#endif + +static void +log_test (void) +{ + errno = 0; + FUNC(log) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + START (log); + + TEST_f_f (log, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (log, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_f_f (log, 1, 0); + + TEST_f_f (log, -1, nan_value, INVALID_EXCEPTION); + TEST_f_f (log, plus_infty, plus_infty); + + TEST_f_f (log, M_El, 1); + TEST_f_f (log, 1.0 / M_El, -1); + TEST_f_f (log, 2, M_LN2l); + TEST_f_f (log, 10, M_LN10l); + TEST_f_f (log, 0.7L, -0.35667494393873237891263871124118447L); + + END (log); +} + + +static void +log10_test (void) +{ + errno = 0; + FUNC(log10) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (log10); + + TEST_f_f (log10, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (log10, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_f_f (log10, 1, 0); + + /* log10 (x) == NaN plus invalid exception if x < 0. */ + TEST_f_f (log10, -1, nan_value, INVALID_EXCEPTION); + + TEST_f_f (log10, plus_infty, plus_infty); + TEST_f_f (log10, nan_value, nan_value); + + TEST_f_f (log10, 0.1L, -1); + TEST_f_f (log10, 10.0, 1); + TEST_f_f (log10, 100.0, 2); + TEST_f_f (log10, 10000.0, 4); + TEST_f_f (log10, M_El, M_LOG10El); + TEST_f_f (log10, 0.7L, -0.15490195998574316929L); + + END (log10); +} + + +static void +log1p_test (void) +{ + errno = 0; + FUNC(log1p) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (log1p); + + TEST_f_f (log1p, 0, 0); + TEST_f_f (log1p, minus_zero, minus_zero); + + TEST_f_f (log1p, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (log1p, -2, nan_value, INVALID_EXCEPTION); + + TEST_f_f (log1p, plus_infty, plus_infty); + TEST_f_f (log1p, nan_value, nan_value); + + TEST_f_f (log1p, M_El - 1.0, 1); + + TEST_f_f (log1p, -0.3L, -0.35667494393873237891263871124118447L); + + END (log1p); +} + +#if 0 +static void +log2_test (void) +{ + errno = 0; + FUNC(log2) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (log2); + + TEST_f_f (log2, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (log2, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_f_f (log2, 1, 0); + + TEST_f_f (log2, -1, nan_value, INVALID_EXCEPTION); + + TEST_f_f (log2, plus_infty, plus_infty); + TEST_f_f (log2, nan_value, nan_value); + + TEST_f_f (log2, M_El, M_LOG2El); + TEST_f_f (log2, 2.0, 1); + TEST_f_f (log2, 16.0, 4); + TEST_f_f (log2, 256.0, 8); + TEST_f_f (log2, 0.7L, -0.51457317282975824043L); + + END (log2); +} +#endif + + +static void +logb_test (void) +{ + START (logb); + + TEST_f_f (logb, plus_infty, plus_infty); + TEST_f_f (logb, minus_infty, plus_infty); + + TEST_f_f (logb, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_f_f (logb, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (logb, nan_value, nan_value); + + TEST_f_f (logb, 1, 0); + TEST_f_f (logb, M_El, 1); + TEST_f_f (logb, 1024, 10); + TEST_f_f (logb, -2000, 10); + + END (logb); +} + +#if 0 +static void +lround_test (void) +{ + START (lround); + + TEST_f_l (lround, 0, 0); + TEST_f_l (lround, minus_zero, 0); + TEST_f_l (lround, 0.2L, 0.0); + TEST_f_l (lround, -0.2L, 0); + TEST_f_l (lround, 0.5, 1); + TEST_f_l (lround, -0.5, -1); + TEST_f_l (lround, 0.8L, 1); + TEST_f_l (lround, -0.8L, -1); + TEST_f_l (lround, 1.5, 2); + TEST_f_l (lround, -1.5, -2); + TEST_f_l (lround, 22514.5, 22515); + TEST_f_l (lround, -22514.5, -22515); +#ifndef TEST_FLOAT + TEST_f_l (lround, 2097152.5, 2097153); + TEST_f_l (lround, -2097152.5, -2097153); +#endif + END (lround); +} + + +static void +llround_test (void) +{ + START (llround); + + TEST_f_L (llround, 0, 0); + TEST_f_L (llround, minus_zero, 0); + TEST_f_L (llround, 0.2L, 0.0); + TEST_f_L (llround, -0.2L, 0); + TEST_f_L (llround, 0.5, 1); + TEST_f_L (llround, -0.5, -1); + TEST_f_L (llround, 0.8L, 1); + TEST_f_L (llround, -0.8L, -1); + TEST_f_L (llround, 1.5, 2); + TEST_f_L (llround, -1.5, -2); + TEST_f_L (llround, 22514.5, 22515); + TEST_f_L (llround, -22514.5, -22515); +#ifndef TEST_FLOAT + TEST_f_L (llround, 2097152.5, 2097153); + TEST_f_L (llround, -2097152.5, -2097153); + TEST_f_L (llround, 34359738368.5, 34359738369ll); + TEST_f_L (llround, -34359738368.5, -34359738369ll); +#endif + + /* Test boundary conditions. */ + /* 0x1FFFFF */ + TEST_f_L (llround, 2097151.0, 2097151LL); + /* 0x800000 */ + TEST_f_L (llround, 8388608.0, 8388608LL); + /* 0x1000000 */ + TEST_f_L (llround, 16777216.0, 16777216LL); + /* 0x20000000000 */ + TEST_f_L (llround, 2199023255552.0, 2199023255552LL); + /* 0x40000000000 */ + TEST_f_L (llround, 4398046511104.0, 4398046511104LL); + /* 0x10000000000000 */ + TEST_f_L (llround, 4503599627370496.0, 4503599627370496LL); + /* 0x10000080000000 */ + TEST_f_L (llrint, 4503601774854144.0, 4503601774854144LL); + /* 0x20000000000000 */ + TEST_f_L (llround, 9007199254740992.0, 9007199254740992LL); + /* 0x80000000000000 */ + TEST_f_L (llround, 36028797018963968.0, 36028797018963968LL); + /* 0x100000000000000 */ + TEST_f_L (llround, 72057594037927936.0, 72057594037927936LL); + +#ifndef TEST_FLOAT + /* 0x100000000 */ + TEST_f_L (llround, 4294967295.5, 4294967296LL); + /* 0x200000000 */ + TEST_f_L (llround, 8589934591.5, 8589934592LL); +#endif + + END (llround); +} +#endif + +static void +modf_test (void) +{ + FLOAT x; + + START (modf); + + TEST_fF_f1 (modf, plus_infty, 0, plus_infty); + TEST_fF_f1 (modf, minus_infty, minus_zero, minus_infty); + TEST_fF_f1 (modf, nan_value, nan_value, nan_value); + TEST_fF_f1 (modf, 0, 0, 0); + TEST_fF_f1 (modf, 1.5, 0.5, 1); + TEST_fF_f1 (modf, 2.5, 0.5, 2); + TEST_fF_f1 (modf, -2.5, -0.5, -2); + TEST_fF_f1 (modf, 20, 0, 20); + TEST_fF_f1 (modf, 21, 0, 21); + TEST_fF_f1 (modf, 89.5, 0.5, 89); + + END (modf); +} + + +#if 0 +static void +nearbyint_test (void) +{ + START (nearbyint); + + TEST_f_f (nearbyint, 0.0, 0.0); + TEST_f_f (nearbyint, minus_zero, minus_zero); + TEST_f_f (nearbyint, plus_infty, plus_infty); + TEST_f_f (nearbyint, minus_infty, minus_infty); + TEST_f_f (nearbyint, nan_value, nan_value); + + /* Default rounding mode is round to nearest. */ + TEST_f_f (nearbyint, 0.5, 0.0); + TEST_f_f (nearbyint, 1.5, 2.0); + TEST_f_f (nearbyint, -0.5, minus_zero); + TEST_f_f (nearbyint, -1.5, -2.0); + + END (nearbyint); +} + +static void +nextafter_test (void) +{ + + START (nextafter); + + TEST_ff_f (nextafter, 0, 0, 0); + TEST_ff_f (nextafter, minus_zero, 0, 0); + TEST_ff_f (nextafter, 0, minus_zero, minus_zero); + TEST_ff_f (nextafter, minus_zero, minus_zero, minus_zero); + + TEST_ff_f (nextafter, 9, 9, 9); + TEST_ff_f (nextafter, -9, -9, -9); + TEST_ff_f (nextafter, plus_infty, plus_infty, plus_infty); + TEST_ff_f (nextafter, minus_infty, minus_infty, minus_infty); + + TEST_ff_f (nextafter, nan_value, 1.1L, nan_value); + TEST_ff_f (nextafter, 1.1L, nan_value, nan_value); + TEST_ff_f (nextafter, nan_value, nan_value, nan_value); + + /* XXX We need the hexadecimal FP number representation here for further + tests. */ + + END (nextafter); +} + + +static void +nexttoward_test (void) +{ + START (nexttoward); + TEST_ff_f (nexttoward, 0, 0, 0); + TEST_ff_f (nexttoward, minus_zero, 0, 0); + TEST_ff_f (nexttoward, 0, minus_zero, minus_zero); + TEST_ff_f (nexttoward, minus_zero, minus_zero, minus_zero); + + TEST_ff_f (nexttoward, 9, 9, 9); + TEST_ff_f (nexttoward, -9, -9, -9); + TEST_ff_f (nexttoward, plus_infty, plus_infty, plus_infty); + TEST_ff_f (nexttoward, minus_infty, minus_infty, minus_infty); + + TEST_ff_f (nexttoward, nan_value, 1.1L, nan_value); + TEST_ff_f (nexttoward, 1.1L, nan_value, nan_value); + TEST_ff_f (nexttoward, nan_value, nan_value, nan_value); + + /* XXX We need the hexadecimal FP number representation here for further + tests. */ + + END (nexttoward); +} +#endif + +static void +pow_test (void) +{ + + errno = 0; + FUNC(pow) (0, 0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (pow); + + TEST_ff_f (pow, 0, 0, 1); + TEST_ff_f (pow, 0, minus_zero, 1); + TEST_ff_f (pow, minus_zero, 0, 1); + TEST_ff_f (pow, minus_zero, minus_zero, 1); + + TEST_ff_f (pow, 10, 0, 1); + TEST_ff_f (pow, 10, minus_zero, 1); + TEST_ff_f (pow, -10, 0, 1); + TEST_ff_f (pow, -10, minus_zero, 1); + + TEST_ff_f (pow, nan_value, 0, 1); + TEST_ff_f (pow, nan_value, minus_zero, 1); + + +#ifndef TEST_INLINE + TEST_ff_f (pow, 1.1L, plus_infty, plus_infty); + TEST_ff_f (pow, plus_infty, plus_infty, plus_infty); + TEST_ff_f (pow, -1.1L, plus_infty, plus_infty); + TEST_ff_f (pow, minus_infty, plus_infty, plus_infty); + + TEST_ff_f (pow, 0.9L, plus_infty, 0); + TEST_ff_f (pow, 1e-7L, plus_infty, 0); + TEST_ff_f (pow, -0.9L, plus_infty, 0); + TEST_ff_f (pow, -1e-7L, plus_infty, 0); + + TEST_ff_f (pow, 1.1L, minus_infty, 0); + TEST_ff_f (pow, plus_infty, minus_infty, 0); + TEST_ff_f (pow, -1.1L, minus_infty, 0); + TEST_ff_f (pow, minus_infty, minus_infty, 0); + + TEST_ff_f (pow, 0.9L, minus_infty, plus_infty); + TEST_ff_f (pow, 1e-7L, minus_infty, plus_infty); + TEST_ff_f (pow, -0.9L, minus_infty, plus_infty); + TEST_ff_f (pow, -1e-7L, minus_infty, plus_infty); + + TEST_ff_f (pow, plus_infty, 1e-7L, plus_infty); + TEST_ff_f (pow, plus_infty, 1, plus_infty); + TEST_ff_f (pow, plus_infty, 1e7L, plus_infty); + + TEST_ff_f (pow, plus_infty, -1e-7L, 0); + TEST_ff_f (pow, plus_infty, -1, 0); + TEST_ff_f (pow, plus_infty, -1e7L, 0); + + TEST_ff_f (pow, minus_infty, 1, minus_infty); + TEST_ff_f (pow, minus_infty, 11, minus_infty); + TEST_ff_f (pow, minus_infty, 1001, minus_infty); + + TEST_ff_f (pow, minus_infty, 2, plus_infty); + TEST_ff_f (pow, minus_infty, 12, plus_infty); + TEST_ff_f (pow, minus_infty, 1002, plus_infty); + TEST_ff_f (pow, minus_infty, 0.1L, plus_infty); + TEST_ff_f (pow, minus_infty, 1.1L, plus_infty); + TEST_ff_f (pow, minus_infty, 11.1L, plus_infty); + TEST_ff_f (pow, minus_infty, 1001.1L, plus_infty); + + TEST_ff_f (pow, minus_infty, -1, minus_zero); + TEST_ff_f (pow, minus_infty, -11, minus_zero); + TEST_ff_f (pow, minus_infty, -1001, minus_zero); + + TEST_ff_f (pow, minus_infty, -2, 0); + TEST_ff_f (pow, minus_infty, -12, 0); + TEST_ff_f (pow, minus_infty, -1002, 0); + TEST_ff_f (pow, minus_infty, -0.1L, 0); + TEST_ff_f (pow, minus_infty, -1.1L, 0); + TEST_ff_f (pow, minus_infty, -11.1L, 0); + TEST_ff_f (pow, minus_infty, -1001.1L, 0); +#endif + + TEST_ff_f (pow, nan_value, nan_value, nan_value); + TEST_ff_f (pow, 0, nan_value, nan_value); + TEST_ff_f (pow, 1, nan_value, 1); + TEST_ff_f (pow, -1, nan_value, nan_value); + TEST_ff_f (pow, nan_value, 1, nan_value); + TEST_ff_f (pow, nan_value, -1, nan_value); + + /* pow (x, NaN) == NaN. */ + TEST_ff_f (pow, 3.0, nan_value, nan_value); + + TEST_ff_f (pow, 1, plus_infty, 1); + TEST_ff_f (pow, -1, plus_infty, 1); + TEST_ff_f (pow, 1, minus_infty, 1); + TEST_ff_f (pow, -1, minus_infty, 1); + + TEST_ff_f (pow, -0.1L, 1.1L, nan_value, INVALID_EXCEPTION); + TEST_ff_f (pow, -0.1L, -1.1L, nan_value, INVALID_EXCEPTION); + TEST_ff_f (pow, -10.1L, 1.1L, nan_value, INVALID_EXCEPTION); + TEST_ff_f (pow, -10.1L, -1.1L, nan_value, INVALID_EXCEPTION); + + TEST_ff_f (pow, 0, -1, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, 0, -11, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, minus_zero, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, minus_zero, -11, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_ff_f (pow, 0, -2, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, 0, -11.1L, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, minus_zero, -2, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, minus_zero, -11.1L, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + + TEST_ff_f (pow, 0, 1, 0); + TEST_ff_f (pow, 0, 11, 0); + + TEST_ff_f (pow, minus_zero, 1, minus_zero); + TEST_ff_f (pow, minus_zero, 11, minus_zero); + + + TEST_ff_f (pow, 0, 2, 0); + TEST_ff_f (pow, 0, 11.1L, 0); + + + TEST_ff_f (pow, minus_zero, 2, 0); + TEST_ff_f (pow, minus_zero, 11.1L, 0); + +#ifndef TEST_INLINE + /* pow (x, +inf) == +inf for |x| > 1. */ + TEST_ff_f (pow, 1.5, plus_infty, plus_infty); + + /* pow (x, +inf) == +0 for |x| < 1. */ + TEST_ff_f (pow, 0.5, plus_infty, 0.0); + + /* pow (x, -inf) == +0 for |x| > 1. */ + TEST_ff_f (pow, 1.5, minus_infty, 0.0); + + /* pow (x, -inf) == +inf for |x| < 1. */ + TEST_ff_f (pow, 0.5, minus_infty, plus_infty); +#endif + + /* pow (+inf, y) == +inf for y > 0. */ + TEST_ff_f (pow, plus_infty, 2, plus_infty); + + /* pow (+inf, y) == +0 for y < 0. */ + TEST_ff_f (pow, plus_infty, -1, 0.0); + + /* pow (-inf, y) == -inf for y an odd integer > 0. */ + TEST_ff_f (pow, minus_infty, 27, minus_infty); + + /* pow (-inf, y) == +inf for y > 0 and not an odd integer. */ + TEST_ff_f (pow, minus_infty, 28, plus_infty); + + /* pow (-inf, y) == -0 for y an odd integer < 0. */ + TEST_ff_f (pow, minus_infty, -3, minus_zero); + /* pow (-inf, y) == +0 for y < 0 and not an odd integer. */ + TEST_ff_f (pow, minus_infty, -2.0, 0.0); + + /* pow (+0, y) == +0 for y an odd integer > 0. */ + TEST_ff_f (pow, 0.0, 27, 0.0); + + /* pow (-0, y) == -0 for y an odd integer > 0. */ + TEST_ff_f (pow, minus_zero, 27, minus_zero); + + /* pow (+0, y) == +0 for y > 0 and not an odd integer. */ + TEST_ff_f (pow, 0.0, 4, 0.0); + + /* pow (-0, y) == +0 for y > 0 and not an odd integer. */ + TEST_ff_f (pow, minus_zero, 4, 0.0); + + TEST_ff_f (pow, 0.7L, 1.2L, 0.65180494056638638188L); + +#if defined TEST_DOUBLE || defined TEST_LDOUBLE + TEST_ff_f (pow, -7.49321e+133, -9.80818e+16, 0); +#endif + + END (pow); +} + +static void +remainder_test (void) +{ + errno = 0; + FUNC(remainder) (1.625, 1.0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (remainder); + + TEST_ff_f (remainder, 1, 0, nan_value, INVALID_EXCEPTION); + TEST_ff_f (remainder, 1, minus_zero, nan_value, INVALID_EXCEPTION); + TEST_ff_f (remainder, plus_infty, 1, nan_value, INVALID_EXCEPTION); + TEST_ff_f (remainder, minus_infty, 1, nan_value, INVALID_EXCEPTION); + TEST_ff_f (remainder, nan_value, nan_value, nan_value); + + TEST_ff_f (remainder, 1.625, 1.0, -0.375); + TEST_ff_f (remainder, -1.625, 1.0, 0.375); + TEST_ff_f (remainder, 1.625, -1.0, -0.375); + TEST_ff_f (remainder, -1.625, -1.0, 0.375); + TEST_ff_f (remainder, 5.0, 2.0, 1.0); + TEST_ff_f (remainder, 3.0, 2.0, -1.0); + + END (remainder); +} + +#if 0 +static void +remquo_test (void) +{ + /* x is needed. */ + int x; + + errno = 0; + FUNC(remquo) (1.625, 1.0, &x); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (remquo); + + TEST_ffI_f1 (remquo, 1, 0, nan_value, IGNORE, INVALID_EXCEPTION); + TEST_ffI_f1 (remquo, 1, minus_zero, nan_value, IGNORE, INVALID_EXCEPTION); + TEST_ffI_f1 (remquo, plus_infty, 1, nan_value, IGNORE, INVALID_EXCEPTION); + TEST_ffI_f1 (remquo, minus_infty, 1, nan_value, IGNORE, INVALID_EXCEPTION); + TEST_ffI_f1 (remquo, nan_value, nan_value, nan_value, IGNORE); + + TEST_ffI_f1 (remquo, 1.625, 1.0, -0.375, 2); + TEST_ffI_f1 (remquo, -1.625, 1.0, 0.375, -2); + TEST_ffI_f1 (remquo, 1.625, -1.0, -0.375, -2); + TEST_ffI_f1 (remquo, -1.625, -1.0, 0.375, 2); + + TEST_ffI_f1 (remquo, 5, 2, 1, 2); + TEST_ffI_f1 (remquo, 3, 2, -1, 2); + + END (remquo); +} +#endif + +static void +rint_test (void) +{ + START (rint); + + TEST_f_f (rint, 0.0, 0.0); + TEST_f_f (rint, minus_zero, minus_zero); + TEST_f_f (rint, plus_infty, plus_infty); + TEST_f_f (rint, minus_infty, minus_infty); + + /* Default rounding mode is round to even. */ + TEST_f_f (rint, 0.5, 0.0); + TEST_f_f (rint, 1.5, 2.0); + TEST_f_f (rint, 2.5, 2.0); + TEST_f_f (rint, 3.5, 4.0); + TEST_f_f (rint, 4.5, 4.0); + TEST_f_f (rint, -0.5, -0.0); + TEST_f_f (rint, -1.5, -2.0); + TEST_f_f (rint, -2.5, -2.0); + TEST_f_f (rint, -3.5, -4.0); + TEST_f_f (rint, -4.5, -4.0); + + END (rint); +} + +#if 0 +static void +round_test (void) +{ + START (round); + + TEST_f_f (round, 0, 0); + TEST_f_f (round, minus_zero, minus_zero); + TEST_f_f (round, 0.2L, 0.0); + TEST_f_f (round, -0.2L, minus_zero); + TEST_f_f (round, 0.5, 1.0); + TEST_f_f (round, -0.5, -1.0); + TEST_f_f (round, 0.8L, 1.0); + TEST_f_f (round, -0.8L, -1.0); + TEST_f_f (round, 1.5, 2.0); + TEST_f_f (round, -1.5, -2.0); + TEST_f_f (round, 2097152.5, 2097153); + TEST_f_f (round, -2097152.5, -2097153); + + END (round); +} +#endif + + +static void +scalb_test (void) +{ + + START (scalb); + + TEST_ff_f (scalb, 2.0, 0.5, nan_value, INVALID_EXCEPTION); + TEST_ff_f (scalb, 3.0, -2.5, nan_value, INVALID_EXCEPTION); + + TEST_ff_f (scalb, 0, nan_value, nan_value); + TEST_ff_f (scalb, 1, nan_value, nan_value); + + TEST_ff_f (scalb, 1, 0, 1); + TEST_ff_f (scalb, -1, 0, -1); + + TEST_ff_f (scalb, 0, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_ff_f (scalb, minus_zero, plus_infty, nan_value, INVALID_EXCEPTION); + + TEST_ff_f (scalb, 0, 2, 0); + TEST_ff_f (scalb, minus_zero, -4, minus_zero); + TEST_ff_f (scalb, 0, 0, 0); + TEST_ff_f (scalb, minus_zero, 0, minus_zero); + TEST_ff_f (scalb, 0, -1, 0); + TEST_ff_f (scalb, minus_zero, -10, minus_zero); + TEST_ff_f (scalb, 0, minus_infty, 0); + TEST_ff_f (scalb, minus_zero, minus_infty, minus_zero); + + TEST_ff_f (scalb, plus_infty, -1, plus_infty); + TEST_ff_f (scalb, minus_infty, -10, minus_infty); + TEST_ff_f (scalb, plus_infty, 0, plus_infty); + TEST_ff_f (scalb, minus_infty, 0, minus_infty); + TEST_ff_f (scalb, plus_infty, 2, plus_infty); + TEST_ff_f (scalb, minus_infty, 100, minus_infty); + + TEST_ff_f (scalb, 0.1L, minus_infty, 0.0); + TEST_ff_f (scalb, -0.1L, minus_infty, minus_zero); + + TEST_ff_f (scalb, 1, plus_infty, plus_infty); + TEST_ff_f (scalb, -1, plus_infty, minus_infty); + TEST_ff_f (scalb, plus_infty, plus_infty, plus_infty); + TEST_ff_f (scalb, minus_infty, plus_infty, minus_infty); + + TEST_ff_f (scalb, plus_infty, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_ff_f (scalb, minus_infty, minus_infty, nan_value, INVALID_EXCEPTION); + + TEST_ff_f (scalb, nan_value, 1, nan_value); + TEST_ff_f (scalb, 1, nan_value, nan_value); + TEST_ff_f (scalb, nan_value, 0, nan_value); + TEST_ff_f (scalb, 0, nan_value, nan_value); + TEST_ff_f (scalb, nan_value, plus_infty, nan_value); + TEST_ff_f (scalb, plus_infty, nan_value, nan_value); + TEST_ff_f (scalb, nan_value, nan_value, nan_value); + + TEST_ff_f (scalb, 0.8L, 4, 12.8L); + TEST_ff_f (scalb, -0.854375L, 5, -27.34L); + + END (scalb); +} + + +static void +scalbn_test (void) +{ + + START (scalbn); + + TEST_fi_f (scalbn, 0, 0, 0); + TEST_fi_f (scalbn, minus_zero, 0, minus_zero); + + TEST_fi_f (scalbn, plus_infty, 1, plus_infty); + TEST_fi_f (scalbn, minus_infty, 1, minus_infty); + TEST_fi_f (scalbn, nan_value, 1, nan_value); + + TEST_fi_f (scalbn, 0.8L, 4, 12.8L); + TEST_fi_f (scalbn, -0.854375L, 5, -27.34L); + + TEST_fi_f (scalbn, 1, 0L, 1); + + END (scalbn); +} + +#if 0 +static void +scalbln_test (void) +{ + + START (scalbln); + + TEST_fl_f (scalbln, 0, 0, 0); + TEST_fl_f (scalbln, minus_zero, 0, minus_zero); + + TEST_fl_f (scalbln, plus_infty, 1, plus_infty); + TEST_fl_f (scalbln, minus_infty, 1, minus_infty); + TEST_fl_f (scalbln, nan_value, 1, nan_value); + + TEST_fl_f (scalbln, 0.8L, 4, 12.8L); + TEST_fl_f (scalbln, -0.854375L, 5, -27.34L); + + TEST_fl_f (scalbln, 1, 0L, 1); + + END (scalbn); +} +#endif + +static void +signbit_test (void) +{ + + START (signbit); + + TEST_f_b (signbit, 0, 0); + TEST_f_b (signbit, minus_zero, 1); + TEST_f_b (signbit, plus_infty, 0); + TEST_f_b (signbit, minus_infty, 1); + + /* signbit (x) != 0 for x < 0. */ + TEST_f_b (signbit, -1, 1); + /* signbit (x) == 0 for x >= 0. */ + TEST_f_b (signbit, 1, 0); + + END (signbit); +} + +static void +sin_test (void) +{ + errno = 0; + FUNC(sin) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (sin); + + TEST_f_f (sin, 0, 0); + TEST_f_f (sin, minus_zero, minus_zero); + TEST_f_f (sin, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (sin, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (sin, nan_value, nan_value); + + TEST_f_f (sin, M_PI_6l, 0.5); + TEST_f_f (sin, -M_PI_6l, -0.5); + TEST_f_f (sin, M_PI_2l, 1); + TEST_f_f (sin, -M_PI_2l, -1); + TEST_f_f (sin, 0.7L, 0.64421768723769105367261435139872014L); + + END (sin); + +} + +#if 0 +static void +sincos_test (void) +{ + FLOAT sin_res, cos_res; + + errno = 0; + FUNC(sincos) (0, &sin_res, &cos_res); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (sincos); + + /* sincos is treated differently because it returns void. */ + TEST_extra (sincos, 0, 0, 1); + + TEST_extra (sincos, minus_zero, minus_zero, 1); + TEST_extra (sincos, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_extra (sincos, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_extra (sincos, nan_value, nan_value, nan_value); + + TEST_extra (sincos, M_PI_2l, 1, 0); + TEST_extra (sincos, M_PI_6l, 0.5, 0.86602540378443864676372317075293616L); + TEST_extra (sincos, M_PI_6l*2.0, 0.86602540378443864676372317075293616L, 0.5); + TEST_extra (sincos, 0.7L, 0.64421768723769105367261435139872014L, 0.76484218728448842625585999019186495L); + + END (sincos); +} +#endif + +static void +sinh_test (void) +{ + errno = 0; + FUNC(sinh) (0.7L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (sinh); + TEST_f_f (sinh, 0, 0); + TEST_f_f (sinh, minus_zero, minus_zero); + +#ifndef TEST_INLINE + TEST_f_f (sinh, plus_infty, plus_infty); + TEST_f_f (sinh, minus_infty, minus_infty); +#endif + TEST_f_f (sinh, nan_value, nan_value); + + TEST_f_f (sinh, 0.7L, 0.75858370183953350346L); + TEST_f_f (sinh, 0x8p-32L, 1.86264514923095703232705808926175479e-9L); + + END (sinh); +} + +static void +sqrt_test (void) +{ + errno = 0; + FUNC(sqrt) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (sqrt); + + TEST_f_f (sqrt, 0, 0); + TEST_f_f (sqrt, nan_value, nan_value); + TEST_f_f (sqrt, plus_infty, plus_infty); + + TEST_f_f (sqrt, minus_zero, minus_zero); + + /* sqrt (x) == NaN plus invalid exception for x < 0. */ + TEST_f_f (sqrt, -1, nan_value, INVALID_EXCEPTION); + TEST_f_f (sqrt, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (sqrt, nan_value, nan_value); + + TEST_f_f (sqrt, 2209, 47); + TEST_f_f (sqrt, 4, 2); + TEST_f_f (sqrt, 2, M_SQRT2l); + TEST_f_f (sqrt, 0.25, 0.5); + TEST_f_f (sqrt, 6642.25, 81.5); + TEST_f_f (sqrt, 15239.9025L, 123.45L); + TEST_f_f (sqrt, 0.7L, 0.83666002653407554797817202578518747L); + + END (sqrt); +} + +static void +tan_test (void) +{ + errno = 0; + FUNC(tan) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (tan); + + TEST_f_f (tan, 0, 0); + TEST_f_f (tan, minus_zero, minus_zero); + TEST_f_f (tan, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (tan, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (tan, nan_value, nan_value); + + TEST_f_f (tan, M_PI_4l, 1); + TEST_f_f (tan, 0.7L, 0.84228838046307944812813500221293775L); + + END (tan); +} + +static void +tanh_test (void) +{ + errno = 0; + FUNC(tanh) (0.7L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (tanh); + + TEST_f_f (tanh, 0, 0); + TEST_f_f (tanh, minus_zero, minus_zero); + +#ifndef TEST_INLINE + TEST_f_f (tanh, plus_infty, 1); + TEST_f_f (tanh, minus_infty, -1); +#endif + TEST_f_f (tanh, nan_value, nan_value); + + TEST_f_f (tanh, 0.7L, 0.60436777711716349631L); + TEST_f_f (tanh, -0.7L, -0.60436777711716349631L); + + TEST_f_f (tanh, 1.0L, 0.7615941559557648881194582826047935904L); + TEST_f_f (tanh, -1.0L, -0.7615941559557648881194582826047935904L); + + /* 2^-57 */ + TEST_f_f (tanh, 6.938893903907228377647697925567626953125e-18L,6.938893903907228377647697925567626953125e-18L); + + END (tanh); +} + +#if 0 +static void +tgamma_test (void) +{ + errno = 0; + FUNC(tgamma) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + feclearexcept (FE_ALL_EXCEPT); + + START (tgamma); + + TEST_f_f (tgamma, plus_infty, plus_infty); + TEST_f_f (tgamma, 0, nan_value, INVALID_EXCEPTION); + TEST_f_f (tgamma, minus_zero, nan_value, INVALID_EXCEPTION); + /* tgamma (x) == NaN plus invalid exception for integer x <= 0. */ + TEST_f_f (tgamma, -2, nan_value, INVALID_EXCEPTION); + TEST_f_f (tgamma, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (tgamma, nan_value, nan_value); + + TEST_f_f (tgamma, 0.5, M_SQRT_PIl); + TEST_f_f (tgamma, -0.5, -M_2_SQRT_PIl); + + TEST_f_f (tgamma, 1, 1); + TEST_f_f (tgamma, 4, 6); + + TEST_f_f (tgamma, 0.7L, 1.29805533264755778568L); + TEST_f_f (tgamma, 1.2L, 0.91816874239976061064L); + + END (tgamma); +} +#endif + +#if 0 +static void +trunc_test (void) +{ + START (trunc); + + TEST_f_f (trunc, plus_infty, plus_infty); + TEST_f_f (trunc, minus_infty, minus_infty); + TEST_f_f (trunc, nan_value, nan_value); + + TEST_f_f (trunc, 0, 0); + TEST_f_f (trunc, minus_zero, minus_zero); + TEST_f_f (trunc, 0.625, 0); + TEST_f_f (trunc, -0.625, minus_zero); + TEST_f_f (trunc, 1, 1); + TEST_f_f (trunc, -1, -1); + TEST_f_f (trunc, 1.625, 1); + TEST_f_f (trunc, -1.625, -1); + + TEST_f_f (trunc, 1048580.625L, 1048580L); + TEST_f_f (trunc, -1048580.625L, -1048580L); + + TEST_f_f (trunc, 8388610.125L, 8388610.0L); + TEST_f_f (trunc, -8388610.125L, -8388610.0L); + + TEST_f_f (trunc, 4294967296.625L, 4294967296.0L); + TEST_f_f (trunc, -4294967296.625L, -4294967296.0L); + + + END (trunc); +} +#endif + +static void +y0_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(y0) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + /* y0 is the Bessel function of the second kind of order 0 */ + START (y0); + + TEST_f_f (y0, -1.0, minus_infty); + TEST_f_f (y0, 0.0, minus_infty); + TEST_f_f (y0, nan_value, nan_value); + TEST_f_f (y0, plus_infty, 0); + + TEST_f_f (y0, 0.1L, -1.5342386513503668441L); + TEST_f_f (y0, 0.7L, -0.19066492933739506743L); + TEST_f_f (y0, 1.0, 0.088256964215676957983L); + TEST_f_f (y0, 1.5, 0.38244892379775884396L); + TEST_f_f (y0, 2.0, 0.51037567264974511960L); + TEST_f_f (y0, 8.0, 0.22352148938756622053L); + TEST_f_f (y0, 10.0, 0.055671167283599391424L); + + END (y0); +} + + +static void +y1_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(y1) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + /* y1 is the Bessel function of the second kind of order 1 */ + START (y1); + + TEST_f_f (y1, -1.0, minus_infty); + TEST_f_f (y1, 0.0, minus_infty); + TEST_f_f (y1, plus_infty, 0); + TEST_f_f (y1, nan_value, nan_value); + + TEST_f_f (y1, 0.1L, -6.4589510947020269877L); + TEST_f_f (y1, 0.7L, -1.1032498719076333697L); + TEST_f_f (y1, 1.0, -0.78121282130028871655L); + TEST_f_f (y1, 1.5, -0.41230862697391129595L); + TEST_f_f (y1, 2.0, -0.10703243154093754689L); + TEST_f_f (y1, 8.0, -0.15806046173124749426L); + TEST_f_f (y1, 10.0, 0.24901542420695388392L); + + END (y1); +} + +static void +yn_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(yn) (1, 1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + /* yn is the Bessel function of the second kind of order n */ + START (yn); + + /* yn (0, x) == y0 (x) */ + TEST_ff_f (yn, 0, -1.0, minus_infty); + TEST_ff_f (yn, 0, 0.0, minus_infty); + TEST_ff_f (yn, 0, nan_value, nan_value); + TEST_ff_f (yn, 0, plus_infty, 0); + + TEST_ff_f (yn, 0, 0.1L, -1.5342386513503668441L); + TEST_ff_f (yn, 0, 0.7L, -0.19066492933739506743L); + TEST_ff_f (yn, 0, 1.0, 0.088256964215676957983L); + TEST_ff_f (yn, 0, 1.5, 0.38244892379775884396L); + TEST_ff_f (yn, 0, 2.0, 0.51037567264974511960L); + TEST_ff_f (yn, 0, 8.0, 0.22352148938756622053L); + TEST_ff_f (yn, 0, 10.0, 0.055671167283599391424L); + + /* yn (1, x) == y1 (x) */ + TEST_ff_f (yn, 1, -1.0, minus_infty); + TEST_ff_f (yn, 1, 0.0, minus_infty); + TEST_ff_f (yn, 1, plus_infty, 0); + TEST_ff_f (yn, 1, nan_value, nan_value); + + TEST_ff_f (yn, 1, 0.1L, -6.4589510947020269877L); + TEST_ff_f (yn, 1, 0.7L, -1.1032498719076333697L); + TEST_ff_f (yn, 1, 1.0, -0.78121282130028871655L); + TEST_ff_f (yn, 1, 1.5, -0.41230862697391129595L); + TEST_ff_f (yn, 1, 2.0, -0.10703243154093754689L); + TEST_ff_f (yn, 1, 8.0, -0.15806046173124749426L); + TEST_ff_f (yn, 1, 10.0, 0.24901542420695388392L); + + /* yn (3, x) */ + TEST_ff_f (yn, 3, plus_infty, 0); + TEST_ff_f (yn, 3, nan_value, nan_value); + + TEST_ff_f (yn, 3, 0.1L, -5099.3323786129048894L); + TEST_ff_f (yn, 3, 0.7L, -15.819479052819633505L); + TEST_ff_f (yn, 3, 1.0, -5.8215176059647288478L); + TEST_ff_f (yn, 3, 2.0, -1.1277837768404277861L); + TEST_ff_f (yn, 3, 10.0, -0.25136265718383732978L); + + /* yn (10, x) */ + TEST_ff_f (yn, 10, plus_infty, 0); + TEST_ff_f (yn, 10, nan_value, nan_value); + + TEST_ff_f (yn, 10, 0.1L, -0.11831335132045197885e19L); + TEST_ff_f (yn, 10, 0.7L, -0.42447194260703866924e10L); + TEST_ff_f (yn, 10, 1.0, -0.12161801427868918929e9L); + TEST_ff_f (yn, 10, 2.0, -129184.54220803928264L); + TEST_ff_f (yn, 10, 10.0, -0.35981415218340272205L); + + END (yn); + +} + + + +static void +initialize (void) +{ + fpstack_test ("start *init*"); + plus_zero = 0.0; + nan_value = plus_zero / plus_zero; /* Suppress GCC warning */ + + minus_zero = FUNC(copysign) (0.0, -1.0); + plus_infty = CHOOSE (HUGE_VALL, HUGE_VAL, HUGE_VALF, + HUGE_VALL, HUGE_VAL, HUGE_VALF); + minus_infty = CHOOSE (-HUGE_VALL, -HUGE_VAL, -HUGE_VALF, + -HUGE_VALL, -HUGE_VAL, -HUGE_VALF); + + (void) &plus_zero; + (void) &nan_value; + (void) &minus_zero; + (void) &plus_infty; + (void) &minus_infty; + + /* Clear all exceptions. From now on we must not get random exceptions. */ + feclearexcept (FE_ALL_EXCEPT); + + /* Test to make sure we start correctly. */ + fpstack_test ("end *init*"); +} + +#if 0 +/* function to check our ulp calculation. */ +void +check_ulp (void) +{ + int i; + + FLOAT u, diff, ulp; + /* This gives one ulp. */ + u = FUNC(nextafter) (10, 20); + check_equal (10.0, u, 1, &diff, &ulp); + printf ("One ulp: % .4" PRINTF_NEXPR "\n", ulp); + + /* This gives one more ulp. */ + u = FUNC(nextafter) (u, 20); + check_equal (10.0, u, 2, &diff, &ulp); + printf ("two ulp: % .4" PRINTF_NEXPR "\n", ulp); + + /* And now calculate 100 ulp. */ + for (i = 2; i < 100; i++) + u = FUNC(nextafter) (u, 20); + check_equal (10.0, u, 100, &diff, &ulp); + printf ("100 ulp: % .4" PRINTF_NEXPR "\n", ulp); +} +#endif + +int +main (int argc, char **argv) +{ + + int key, remaining; + + verbose = 1; + output_ulps = 0; + output_max_error = 1; + output_points = 1; + /* XXX set to 0 for releases. */ + ignore_max_ulp = 0; + + /* Parse and process arguments. */ + while ((key = getopt(argc, argv, "fi:puv")) > 0) { + switch (key) + { + case 'f': + output_max_error = 0; + break; + case 'i': + if (strcmp (optarg, "yes") == 0) + ignore_max_ulp = 1; + else if (strcmp (optarg, "no") == 0) + ignore_max_ulp = 0; + break; + case 'p': + output_points = 0; + break; + case 'u': + output_ulps = 1; + break; + case 'v': + verbose = 3; + break; + default: + fprintf (stderr, "Unknown argument: %c", key); + exit (EXIT_FAILURE); + } + } + + if (optind != argc) + { + fprintf (stderr, "wrong number of arguments"); + exit (EXIT_FAILURE); + } + + if (output_ulps) + { + ulps_file = fopen ("ULPs", "a"); + if (ulps_file == NULL) + { + perror ("can't open file `ULPs' for writing: "); + exit (1); + } + } + + + initialize (); + printf (TEST_MSG); + +#if 0 + check_ulp (); +#endif + + /* Keep the tests a wee bit ordered (according to ISO C99). */ + /* Classification macros: */ + fpclassify_test (); + isfinite_test (); + isnormal_test (); + signbit_test (); + + /* Trigonometric functions: */ + acos_test (); + asin_test (); + atan_test (); + atan2_test (); + cos_test (); + sin_test (); +#if 0 + sincos_test (); +#endif + tan_test (); + + /* Hyperbolic functions: */ + acosh_test (); + asinh_test (); + atanh_test (); + cosh_test (); + sinh_test (); + tanh_test (); + + /* Exponential and logarithmic functions: */ + exp_test (); +#if 0 + exp10_test (); + exp2_test (); +#endif + expm1_test (); + frexp_test (); + ldexp_test (); + log_test (); + log10_test (); + log1p_test (); +#if 0 + log2_test (); +#endif + logb_test (); + modf_test (); + ilogb_test (); + scalb_test (); + scalbn_test (); +#if 0 + scalbln_test (); +#endif + + /* Power and absolute value functions: */ + cbrt_test (); + fabs_test (); + hypot_test (); + pow_test (); + sqrt_test (); + + /* Error and gamma functions: */ + erf_test (); + erfc_test (); + gamma_test (); + lgamma_test (); +#if 0 + tgamma_test (); +#endif + + /* Nearest integer functions: */ + ceil_test (); + floor_test (); +#if 0 + nearbyint_test (); +#endif + rint_test (); +#if 0 + lrint_test (); + llrint_test (); + round_test (); + lround_test (); + llround_test (); + trunc_test (); +#endif + + /* Remainder functions: */ + fmod_test (); + remainder_test (); +#if 0 + remquo_test (); +#endif + + /* Manipulation functions: */ + copysign_test (); +#if 0 + nextafter_test (); + nexttoward_test (); + + /* maximum, minimum and positive difference functions */ + fdim_test (); + fmax_test (); + fmin_test (); + + /* Multiply and add: */ + fma_test (); + + /* Complex functions: */ + cabs_test (); + cacos_test (); + cacosh_test (); + carg_test (); + casin_test (); + casinh_test (); + catan_test (); + catanh_test (); + ccos_test (); + ccosh_test (); + cexp_test (); + cimag_test (); + clog10_test (); + clog_test (); + conj_test (); + cpow_test (); + cproj_test (); + creal_test (); + csin_test (); + csinh_test (); + csqrt_test (); + ctan_test (); + ctanh_test (); +#endif + + /* Bessel functions: */ +#if 0 + j0_test (); + j1_test (); + jn_test (); + y0_test (); + y1_test (); + yn_test (); +#endif + + if (output_ulps) + fclose (ulps_file); + + printf ("\nTest suite completed:\n"); + printf (" %d test cases plus %d tests for exception flags executed.\n", + noTests, noExcTests); + if (noXFails) + printf (" %d expected failures occurred.\n", noXFails); + if (noXPasses) + printf (" %d unexpected passes occurred.\n", noXPasses); + if (noErrors) + { + printf (" %d errors occurred.\n", noErrors); + return 1; + } + printf (" All tests passed successfully.\n"); + + return 0; +} + +/* + * Local Variables: + * mode:c + * End: + */ diff --git a/test/math/mconf.h b/test/math/mconf.h deleted file mode 100644 index faf789b26..000000000 --- a/test/math/mconf.h +++ /dev/null @@ -1,108 +0,0 @@ -/* mconf.h - * - * Common include file for math routines - * - * - * - * SYNOPSIS: - * - * #include "mconf.h" - * - * - * - * DESCRIPTION: - * - * This file contains definitions for error codes that are - * passed to the common error handling routine mtherr() - * (which see). - * - * The file also includes a conditional assembly definition - * for the type of computer arithmetic (IEEE, DEC, Motorola - * IEEE, or UNKnown). - * - * For Digital Equipment PDP-11 and VAX computers, certain - * IBM systems, and others that use numbers with a 56-bit - * significand, the symbol DEC should be defined. In this - * mode, most floating point constants are given as arrays - * of octal integers to eliminate decimal to binary conversion - * errors that might be introduced by the compiler. - * - * For computers, such as IBM PC, that follow the IEEE - * Standard for Binary Floating Point Arithmetic (ANSI/IEEE - * Std 754-1985), the symbol IBMPC should be defined. These - * numbers have 53-bit significands. In this mode, constants - * are provided as arrays of hexadecimal 16 bit integers. - * - * To accommodate other types of computer arithmetic, all - * constants are also provided in a normal decimal radix - * which one can hope are correctly converted to a suitable - * format by the available C language compiler. To invoke - * this mode, the symbol UNK is defined. - * - * An important difference among these modes is a predefined - * set of machine arithmetic constants for each. The numbers - * MACHEP (the machine roundoff error), MAXNUM (largest number - * represented), and several other parameters are preset by - * the configuration symbol. Check the file const.c to - * ensure that these values are correct for your computer. - * - */ - -/* -Cephes Math Library Release 2.0: April, 1987 -by Stephen L. Moshier -Direct inquiries to 30 Frost Street, Cambridge, MA 02140 -*/ - - -/* Constant definitions for math error conditions - */ - -#define DOMAIN 1 /* argument domain error */ -#define SING 2 /* argument singularity */ -#define OVERFLOW 3 /* overflow range error */ -#define UNDERFLOW 4 /* underflow range error */ -#define TLOSS 5 /* total loss of precision */ -#define PLOSS 6 /* partial loss of precision */ - -#define EDOM 33 -#define ERANGE 34 - -/* -typedef struct - { - double r; - double i; - }cmplx; -*/ - -/* Type of computer arithmetic */ - -/* PDP-11, Pro350, VAX: - */ -/*define DEC 1*/ - -/* Intel IEEE, low order words come first: - */ -#define IBMPC 1 - -/* Motorola IEEE, high order words come first - * (Sun workstation): - */ -/*define MIEEE 1*/ - -/* UNKnown arithmetic, invokes coefficients given in - * normal decimal format. Beware of range boundary - * problems (MACHEP, MAXLOG, etc. in const.c) and - * roundoff problems in pow.c: - */ - /*define UNK 1*/ - -/* Define to ask for infinity support, else undefine. */ -#define INFINITY - -/* Define to ask for Not-a-Number support, else undefine. */ -#define NANS - -/* Define to support denormal numbers, else undefine. */ -#define DENORMAL diff --git a/test/math/mtherr.c b/test/math/mtherr.c deleted file mode 100644 index 52e3ec2ad..000000000 --- a/test/math/mtherr.c +++ /dev/null @@ -1,96 +0,0 @@ -/* mtherr.c - * - * Library common error handling routine - * - * - * - * SYNOPSIS: - * - * char *fctnam; - * int code; - * void mtherr(); - * - * mtherr( fctnam, code ); - * - * - * - * DESCRIPTION: - * - * This routine may be called to report one of the following - * error conditions (in the include file mconf.h). - * - * Mnemonic Value Significance - * - * DOMAIN 1 argument domain error - * SING 2 function singularity - * OVERFLOW 3 overflow range error - * UNDERFLOW 4 underflow range error - * TLOSS 5 total loss of precision - * PLOSS 6 partial loss of precision - * EDOM 33 Unix domain error code - * ERANGE 34 Unix range error code - * - * The default version of the file prints the function name, - * passed to it by the pointer fctnam, followed by the - * error condition. The display is directed to the standard - * output device. The routine then returns to the calling - * program. Users may wish to modify the program to abort by - * calling exit() under severe error conditions such as domain - * errors. - * - * Since all error conditions pass control to this function, - * the display may be easily changed, eliminated, or directed - * to an error logging device. - * - * SEE ALSO: - * - * mconf.h - * - */ - -/* -Cephes Math Library Release 2.0: April, 1987 -by Stephen L. Moshier -Direct inquiries to 30 Frost Street, Cambridge, MA 02140 -*/ - -#include "mconf.h" - -/* Notice: the order of appearance of the following - * messages is bound to the error codes defined - * in mconf.h. - */ -static char *ermsg[7] = { -"unknown", /* error code 0 */ -"domain", /* error code 1 */ -"singularity", /* et seq. */ -"overflow", -"underflow", -"total loss of precision", -"partial loss of precision" -}; - - - -void mtherr( name, code ) -char *name; -int code; -{ - -/* Display string passed by calling program, - * which is supposed to be the name of the - * function in which the error occurred: - */ -printf( "\n%s ", name ); - -/* Display error message defined - * by the code argument. - */ -if( (code <= 0) || (code >= 6) ) - code = 0; -printf( "%s error\n", ermsg[code] ); - -/* Return to calling - * program - */ -} diff --git a/test/math/test-double.c b/test/math/test-double.c new file mode 100644 index 000000000..4d239a71d --- /dev/null +++ b/test/math/test-double.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function +#define FLOAT double +#define TEST_MSG "testing double (without inline functions)\n" +#define MATHCONST(x) x +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cdouble +#define PRINTF_EXPR "e" +#define PRINTF_XEXPR "a" +#define PRINTF_NEXPR "f" +#define TEST_DOUBLE 1 + +#ifndef __NO_MATH_INLINES +# define __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/test-float.c b/test/math/test-float.c new file mode 100644 index 000000000..26a4213b4 --- /dev/null +++ b/test/math/test-float.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function ## f +#define FLOAT float +#define TEST_MSG "testing float (without inline functions)\n" +#define MATHCONST(x) x +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cfloat +#define PRINTF_EXPR "e" +#define PRINTF_XEXPR "a" +#define PRINTF_NEXPR "f" +#define TEST_FLOAT 1 + +#ifndef __NO_MATH_INLINES +# define __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/test-idouble.c b/test/math/test-idouble.c new file mode 100644 index 000000000..7606a89ff --- /dev/null +++ b/test/math/test-idouble.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function +#define FLOAT double +#define TEST_MSG "testing double (inline functions)\n" +#define MATHCONST(x) x +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cinlinedouble +#define PRINTF_EXPR "e" +#define PRINTF_XEXPR "a" +#define PRINTF_NEXPR "f" +#define TEST_DOUBLE 1 +#define TEST_INLINE + +#ifdef __NO_MATH_INLINES +# undef __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/test-ifloat.c b/test/math/test-ifloat.c new file mode 100644 index 000000000..9eb9ce502 --- /dev/null +++ b/test/math/test-ifloat.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function ## f +#define FLOAT float +#define TEST_MSG "testing float (inline functions)\n" +#define MATHCONST(x) x +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cinlinefloat +#define PRINTF_EXPR "e" +#define PRINTF_XEXPR "a" +#define PRINTF_NEXPR "f" +#define TEST_FLOAT 1 +#define TEST_INLINE 1 + +#ifdef __NO_MATH_INLINES +# undef __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/test-ildoubl.c b/test/math/test-ildoubl.c new file mode 100644 index 000000000..597edbca1 --- /dev/null +++ b/test/math/test-ildoubl.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function##l +#define FLOAT long double +#define TEST_MSG "testing long double (inline functions)\n" +#define MATHCONST(x) x##L +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cinlinelongdouble +#define PRINTF_EXPR "Le" +#define PRINTF_XEXPR "La" +#define PRINTF_NEXPR "Lf" +#define TEST_INLINE +#define TEST_LDOUBLE 1 + +#ifdef __NO_MATH_INLINES +# undef __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/test-ldouble.c b/test/math/test-ldouble.c new file mode 100644 index 000000000..272122766 --- /dev/null +++ b/test/math/test-ldouble.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function##l +#define FLOAT long double +#define TEST_MSG "testing long double (without inline functions)\n" +#define MATHCONST(x) x##L +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Clongdouble +#define PRINTF_EXPR "Le" +#define PRINTF_XEXPR "La" +#define PRINTF_NEXPR "Lf" +#define TEST_LDOUBLE 1 + +#ifndef __NO_MATH_INLINES +# define __NO_MATH_INLINES +#endif + +#include "libm-test.c" |