v16i045: 4.3BSD Math library source, Part03/05
Rich Salz
rsalz at uunet.uu.net
Thu Oct 27 06:05:38 AEST 1988
Submitted-by: Thos Sumner <root at ccb.ucsf.edu>
Posting-number: Volume 16, Issue 45
Archive-name: 4.3mathlib/part03
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 5)."
# Contents: libm/IEEE/atan2.c libm/IEEE/cabs.c libm/README
# libm/VAX/atan2.s libm/log1p.c libm/pow.c
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'libm/IEEE/atan2.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libm/IEEE/atan2.c'\"
else
echo shar: Extracting \"'libm/IEEE/atan2.c'\" \(9242 characters\)
sed "s/^X//" >'libm/IEEE/atan2.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1985 Regents of the University of California.
X *
X * Use and reproduction of this software are granted in accordance with
X * the terms and conditions specified in the Berkeley Software License
X * Agreement (in particular, this entails acknowledgement of the programs'
X * source, and inclusion of this notice) with the additional understanding
X * that all recipients should regard themselves as participants in an
X * ongoing research project and hence should feel obligated to report
X * their experiences (good or bad) with these elementary function codes,
X * using "sendbug 4bsd-bugs at BERKELEY", to the authors.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)atan2.c 1.3 (Berkeley) 8/21/85";
X#endif not lint
X
X/* ATAN2(Y,X)
X * RETURN ARG (X+iY)
X * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
X * CODED IN C BY K.C. NG, 1/8/85;
X * REVISED BY K.C. NG on 2/7/85, 2/13/85, 3/7/85, 3/30/85, 6/29/85.
X *
X * Required system supported functions :
X * copysign(x,y)
X * scalb(x,y)
X * logb(x)
X *
X * Method :
X * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
X * 2. Reduce x to positive by (if x and y are unexceptional):
X * ARG (x+iy) = arctan(y/x) ... if x > 0,
X * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,
X * 3. According to the integer k=4t+0.25 truncated , t=y/x, the argument
X * is further reduced to one of the following intervals and the
X * arctangent of y/x is evaluated by the corresponding formula:
X *
X * [0,7/16] atan(y/x) = t - t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
X * [7/16,11/16] atan(y/x) = atan(1/2) + atan( (y-x/2)/(x+y/2) )
X * [11/16.19/16] atan(y/x) = atan( 1 ) + atan( (y-x)/(x+y) )
X * [19/16,39/16] atan(y/x) = atan(3/2) + atan( (y-1.5x)/(x+1.5y) )
X * [39/16,INF] atan(y/x) = atan(INF) + atan( -x/y )
X *
X * Special cases:
X * Notations: atan2(y,x) == ARG (x+iy) == ARG(x,y).
X *
X * ARG( NAN , (anything) ) is NaN;
X * ARG( (anything), NaN ) is NaN;
X * ARG(+(anything but NaN), +-0) is +-0 ;
X * ARG(-(anything but NaN), +-0) is +-PI ;
X * ARG( 0, +-(anything but 0 and NaN) ) is +-PI/2;
X * ARG( +INF,+-(anything but INF and NaN) ) is +-0 ;
X * ARG( -INF,+-(anything but INF and NaN) ) is +-PI;
X * ARG( +INF,+-INF ) is +-PI/4 ;
X * ARG( -INF,+-INF ) is +-3PI/4;
X * ARG( (anything but,0,NaN, and INF),+-INF ) is +-PI/2;
X *
X * Accuracy:
X * atan2(y,x) returns (PI/pi) * the exact ARG (x+iy) nearly rounded,
X * where
X *
X * in decimal:
X * pi = 3.141592653589793 23846264338327 .....
X * 53 bits PI = 3.141592653589793 115997963 ..... ,
X * 56 bits PI = 3.141592653589793 227020265 ..... ,
X *
X * in hexadecimal:
X * pi = 3.243F6A8885A308D313198A2E....
X * 53 bits PI = 3.243F6A8885A30 = 2 * 1.921FB54442D18 error=.276ulps
X * 56 bits PI = 3.243F6A8885A308 = 4 * .C90FDAA22168C2 error=.206ulps
X *
X * In a test run with 356,000 random argument on [-1,1] * [-1,1] on a
X * VAX, the maximum observed error was 1.41 ulps (units of the last place)
X * compared with (PI/pi)*(the exact ARG(x+iy)).
X *
X * Note:
X * We use machine PI (the true pi rounded) in place of the actual
X * value of pi for all the trig and inverse trig functions. In general,
X * if trig is one of sin, cos, tan, then computed trig(y) returns the
X * exact trig(y*pi/PI) nearly rounded; correspondingly, computed arctrig
X * returns the exact arctrig(y)*PI/pi nearly rounded. These guarantee the
X * trig functions have period PI, and trig(arctrig(x)) returns x for
X * all critical values x.
X *
X * Constants:
X * The hexadecimal values are the intended ones for the following constants.
X * The decimal values may be used, provided that the compiler will convert
X * from decimal to binary accurately enough to produce the hexadecimal values
X * shown.
X */
X
Xstatic double
X#ifdef VAX /* VAX D format */
Xathfhi = 4.6364760900080611433E-1 , /*Hex 2^ -1 * .ED63382B0DDA7B */
Xathflo = 1.9338828231967579916E-19 , /*Hex 2^-62 * .E450059CFE92C0 */
XPIo4 = 7.8539816339744830676E-1 , /*Hex 2^ 0 * .C90FDAA22168C2 */
Xat1fhi = 9.8279372324732906796E-1 , /*Hex 2^ 0 * .FB985E940FB4D9 */
Xat1flo = -3.5540295636764633916E-18 , /*Hex 2^-57 * -.831EDC34D6EAEA */
XPIo2 = 1.5707963267948966135E0 , /*Hex 2^ 1 * .C90FDAA22168C2 */
XPI = 3.1415926535897932270E0 , /*Hex 2^ 2 * .C90FDAA22168C2 */
Xa1 = 3.3333333333333473730E-1 , /*Hex 2^ -1 * .AAAAAAAAAAAB75 */
Xa2 = -2.0000000000017730678E-1 , /*Hex 2^ -2 * -.CCCCCCCCCD946E */
Xa3 = 1.4285714286694640301E-1 , /*Hex 2^ -2 * .92492492744262 */
Xa4 = -1.1111111135032672795E-1 , /*Hex 2^ -3 * -.E38E38EBC66292 */
Xa5 = 9.0909091380563043783E-2 , /*Hex 2^ -3 * .BA2E8BB31BD70C */
Xa6 = -7.6922954286089459397E-2 , /*Hex 2^ -3 * -.9D89C827C37F18 */
Xa7 = 6.6663180891693915586E-2 , /*Hex 2^ -3 * .8886B4AE379E58 */
Xa8 = -5.8772703698290408927E-2 , /*Hex 2^ -4 * -.F0BBA58481A942 */
Xa9 = 5.2170707402812969804E-2 , /*Hex 2^ -4 * .D5B0F3A1AB13AB */
Xa10 = -4.4895863157820361210E-2 , /*Hex 2^ -4 * -.B7E4B97FD1048F */
Xa11 = 3.3006147437343875094E-2 , /*Hex 2^ -4 * .8731743CF72D87 */
Xa12 = -1.4614844866464185439E-2 ; /*Hex 2^ -6 * -.EF731A2F3476D9 */
X#else /* IEEE double */
Xathfhi = 4.6364760900080609352E-1 , /*Hex 2^ -2 * 1.DAC670561BB4F */
Xathflo = 4.6249969567426939759E-18 , /*Hex 2^-58 * 1.5543B8F253271 */
XPIo4 = 7.8539816339744827900E-1 , /*Hex 2^ -1 * 1.921FB54442D18 */
Xat1fhi = 9.8279372324732905408E-1 , /*Hex 2^ -1 * 1.F730BD281F69B */
Xat1flo = -2.4407677060164810007E-17 , /*Hex 2^-56 * -1.C23DFEFEAE6B5 */
XPIo2 = 1.5707963267948965580E0 , /*Hex 2^ 0 * 1.921FB54442D18 */
XPI = 3.1415926535897931160E0 , /*Hex 2^ 1 * 1.921FB54442D18 */
Xa1 = 3.3333333333333942106E-1 , /*Hex 2^ -2 * 1.55555555555C3 */
Xa2 = -1.9999999999979536924E-1 , /*Hex 2^ -3 * -1.9999999997CCD */
Xa3 = 1.4285714278004377209E-1 , /*Hex 2^ -3 * 1.24924921EC1D7 */
Xa4 = -1.1111110579344973814E-1 , /*Hex 2^ -4 * -1.C71C7059AF280 */
Xa5 = 9.0908906105474668324E-2 , /*Hex 2^ -4 * 1.745CE5AA35DB2 */
Xa6 = -7.6919217767468239799E-2 , /*Hex 2^ -4 * -1.3B0FA54BEC400 */
Xa7 = 6.6614695906082474486E-2 , /*Hex 2^ -4 * 1.10DA924597FFF */
Xa8 = -5.8358371008508623523E-2 , /*Hex 2^ -5 * -1.DE125FDDBD793 */
Xa9 = 4.9850617156082015213E-2 , /*Hex 2^ -5 * 1.9860524BDD807 */
Xa10 = -3.6700606902093604877E-2 , /*Hex 2^ -5 * -1.2CA6C04C6937A */
Xa11 = 1.6438029044759730479E-2 ; /*Hex 2^ -6 * 1.0D52174A1BB54 */
X#endif
X
Xdouble atan2(y,x)
Xdouble y,x;
X{
X static double zero=0, one=1, small=1.0E-9, big=1.0E18;
X double copysign(),logb(),scalb(),t,z,signy,signx,hi,lo;
X int finite(), k,m;
X
X /* if x or y is NAN */
X if(x!=x) return(x); if(y!=y) return(y);
X
X /* copy down the sign of y and x */
X signy = copysign(one,y) ;
X signx = copysign(one,x) ;
X
X /* if x is 1.0, goto begin */
X if(x==1) { y=copysign(y,one); t=y; if(finite(t)) goto begin;}
X
X /* when y = 0 */
X if(y==zero) return((signx==one)?y:copysign(PI,signy));
X
X /* when x = 0 */
X if(x==zero) return(copysign(PIo2,signy));
X
X /* when x is INF */
X if(!finite(x))
X if(!finite(y))
X return(copysign((signx==one)?PIo4:3*PIo4,signy));
X else
X return(copysign((signx==one)?zero:PI,signy));
X
X /* when y is INF */
X if(!finite(y)) return(copysign(PIo2,signy));
X
X
X /* compute y/x */
X x=copysign(x,one);
X y=copysign(y,one);
X if((m=(k=logb(y))-logb(x)) > 60) t=big+big;
X else if(m < -80 ) t=y/x;
X else { t = y/x ; y = scalb(y,-k); x=scalb(x,-k); }
X
X /* begin argument reduction */
Xbegin:
X if (t < 2.4375) {
X
X /* truncate 4(t+1/16) to integer for branching */
X k = 4 * (t+0.0625);
X switch (k) {
X
X /* t is in [0,7/16] */
X case 0:
X case 1:
X if (t < small)
X { big + small ; /* raise inexact flag */
X return (copysign((signx>zero)?t:PI-t,signy)); }
X
X hi = zero; lo = zero; break;
X
X /* t is in [7/16,11/16] */
X case 2:
X hi = athfhi; lo = athflo;
X z = x+x;
X t = ( (y+y) - x ) / ( z + y ); break;
X
X /* t is in [11/16,19/16] */
X case 3:
X case 4:
X hi = PIo4; lo = zero;
X t = ( y - x ) / ( x + y ); break;
X
X /* t is in [19/16,39/16] */
X default:
X hi = at1fhi; lo = at1flo;
X z = y-x; y=y+y+y; t = x+x;
X t = ( (z+z)-x ) / ( t + y ); break;
X }
X }
X /* end of if (t < 2.4375) */
X
X else
X {
X hi = PIo2; lo = zero;
X
X /* t is in [2.4375, big] */
X if (t <= big) t = - x / y;
X
X /* t is in [big, INF] */
X else
X { big+small; /* raise inexact flag */
X t = zero; }
X }
X /* end of argument reduction */
X
X /* compute atan(t) for t in [-.4375, .4375] */
X z = t*t;
X#ifdef VAX
X z = t*(z*(a1+z*(a2+z*(a3+z*(a4+z*(a5+z*(a6+z*(a7+z*(a8+
X z*(a9+z*(a10+z*(a11+z*a12))))))))))));
X#else /* IEEE double */
X z = t*(z*(a1+z*(a2+z*(a3+z*(a4+z*(a5+z*(a6+z*(a7+z*(a8+
X z*(a9+z*(a10+z*a11)))))))))));
X#endif
X z = lo - z; z += t; z += hi;
X
X return(copysign((signx>zero)?z:PI-z,signy));
X}
END_OF_FILE
if test 9242 -ne `wc -c <'libm/IEEE/atan2.c'`; then
echo shar: \"'libm/IEEE/atan2.c'\" unpacked with wrong size!
fi
# end of 'libm/IEEE/atan2.c'
fi
if test -f 'libm/IEEE/cabs.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libm/IEEE/cabs.c'\"
else
echo shar: Extracting \"'libm/IEEE/cabs.c'\" \(5953 characters\)
sed "s/^X//" >'libm/IEEE/cabs.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1985 Regents of the University of California.
X *
X * Use and reproduction of this software are granted in accordance with
X * the terms and conditions specified in the Berkeley Software License
X * Agreement (in particular, this entails acknowledgement of the programs'
X * source, and inclusion of this notice) with the additional understanding
X * that all recipients should regard themselves as participants in an
X * ongoing research project and hence should feel obligated to report
X * their experiences (good or bad) with these elementary function codes,
X * using "sendbug 4bsd-bugs at BERKELEY", to the authors.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)cabs.c 1.2 (Berkeley) 8/21/85";
X#endif not lint
X
X/* CABS(Z)
X * RETURN THE ABSOLUTE VALUE OF THE COMPLEX NUMBER Z = X + iY
X * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
X * CODED IN C BY K.C. NG, 11/28/84.
X * REVISED BY K.C. NG, 7/12/85.
X *
X * Required kernel function :
X * hypot(x,y)
X *
X * Method :
X * cabs(z) = hypot(x,y) .
X */
X
Xdouble cabs(z)
Xstruct { double x, y;} z;
X{
X double hypot();
X return(hypot(z.x,z.y));
X}
X
X
X/* HYPOT(X,Y)
X * RETURN THE SQUARE ROOT OF X^2 + Y^2 WHERE Z=X+iY
X * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
X * CODED IN C BY K.C. NG, 11/28/84;
X * REVISED BY K.C. NG, 7/12/85.
X *
X * Required system supported functions :
X * copysign(x,y)
X * finite(x)
X * scalb(x,N)
X * sqrt(x)
X *
X * Method :
X * 1. replace x by |x| and y by |y|, and swap x and
X * y if y > x (hence x is never smaller than y).
X * 2. Hypot(x,y) is computed by:
X * Case I, x/y > 2
X *
X * y
X * hypot = x + -----------------------------
X * 2
X * sqrt ( 1 + [x/y] ) + x/y
X *
X * Case II, x/y <= 2
X * y
X * hypot = x + --------------------------------------------------
X * 2
X * [x/y] - 2
X * (sqrt(2)+1) + (x-y)/y + -----------------------------
X * 2
X * sqrt ( 1 + [x/y] ) + sqrt(2)
X *
X *
X *
X * Special cases:
X * hypot(x,y) is INF if x or y is +INF or -INF; else
X * hypot(x,y) is NAN if x or y is NAN.
X *
X * Accuracy:
X * hypot(x,y) returns the sqrt(x^2+y^2) with error less than 1 ulps (units
X * in the last place). See Kahan's "Interval Arithmetic Options in the
X * Proposed IEEE Floating Point Arithmetic Standard", Interval Mathematics
X * 1980, Edited by Karl L.E. Nickel, pp 99-128. (A faster but less accurate
X * code follows in comments.) In a test run with 500,000 random arguments
X * on a VAX, the maximum observed error was .959 ulps.
X *
X * Constants:
X * The hexadecimal values are the intended ones for the following constants.
X * The decimal values may be used, provided that the compiler will convert
X * from decimal to binary accurately enough to produce the hexadecimal values
X * shown.
X */
X
X#ifdef VAX /* VAX D format */
X/* static double */
X/* r2p1hi = 2.4142135623730950345E0 , Hex 2^ 2 * .9A827999FCEF32 */
X/* r2p1lo = 1.4349369327986523769E-17 , Hex 2^-55 * .84597D89B3754B */
X/* sqrt2 = 1.4142135623730950622E0 ; Hex 2^ 1 * .B504F333F9DE65 */
Xstatic long r2p1hix[] = { 0x8279411a, 0xef3299fc};
Xstatic long r2p1lox[] = { 0x597d2484, 0x754b89b3};
Xstatic long sqrt2x[] = { 0x04f340b5, 0xde6533f9};
X#define r2p1hi (*(double*)r2p1hix)
X#define r2p1lo (*(double*)r2p1lox)
X#define sqrt2 (*(double*)sqrt2x)
X#else /* IEEE double format */
Xstatic double
Xr2p1hi = 2.4142135623730949234E0 , /*Hex 2^1 * 1.3504F333F9DE6 */
Xr2p1lo = 1.2537167179050217666E-16 , /*Hex 2^-53 * 1.21165F626CDD5 */
Xsqrt2 = 1.4142135623730951455E0 ; /*Hex 2^ 0 * 1.6A09E667F3BCD */
X#endif
X
Xdouble hypot(x,y)
Xdouble x, y;
X{
X static double zero=0, one=1,
X small=1.0E-18; /* fl(1+small)==1 */
X static ibig=30; /* fl(1+2**(2*ibig))==1 */
X double copysign(),scalb(),logb(),sqrt(),t,r;
X int finite(), exp;
X
X if(finite(x))
X if(finite(y))
X {
X x=copysign(x,one);
X y=copysign(y,one);
X if(y > x)
X { t=x; x=y; y=t; }
X if(x == zero) return(zero);
X if(y == zero) return(x);
X exp= logb(x);
X if(exp-(int)logb(y) > ibig )
X /* raise inexact flag and return |x| */
X { one+small; return(x); }
X
X /* start computing sqrt(x^2 + y^2) */
X r=x-y;
X if(r>y) { /* x/y > 2 */
X r=x/y;
X r=r+sqrt(one+r*r); }
X else { /* 1 <= x/y <= 2 */
X r/=y; t=r*(r+2.0);
X r+=t/(sqrt2+sqrt(2.0+t));
X r+=r2p1lo; r+=r2p1hi; }
X
X r=y/r;
X return(x+r);
X
X }
X
X else if(y==y) /* y is +-INF */
X return(copysign(y,one));
X else
X return(y); /* y is NaN and x is finite */
X
X else if(x==x) /* x is +-INF */
X return (copysign(x,one));
X else if(finite(y))
X return(x); /* x is NaN, y is finite */
X else if(y!=y) return(y); /* x and y is NaN */
X else return(copysign(y,one)); /* y is INF */
X}
X
X/* A faster but less accurate version of cabs(x,y) */
X#if 0
Xdouble hypot(x,y)
Xdouble x, y;
X{
X static double zero=0, one=1;
X small=1.0E-18; /* fl(1+small)==1 */
X static ibig=30; /* fl(1+2**(2*ibig))==1 */
X double copysign(),scalb(),logb(),sqrt(),temp;
X int finite(), exp;
X
X if(finite(x))
X if(finite(y))
X {
X x=copysign(x,one);
X y=copysign(y,one);
X if(y > x)
X { temp=x; x=y; y=temp; }
X if(x == zero) return(zero);
X if(y == zero) return(x);
X exp= logb(x);
X x=scalb(x,-exp);
X if(exp-(int)logb(y) > ibig )
X /* raise inexact flag and return |x| */
X { one+small; return(scalb(x,exp)); }
X else y=scalb(y,-exp);
X return(scalb(sqrt(x*x+y*y),exp));
X }
X
X else if(y==y) /* y is +-INF */
X return(copysign(y,one));
X else
X return(y); /* y is NaN and x is finite */
X
X else if(x==x) /* x is +-INF */
X return (copysign(x,one));
X else if(finite(y))
X return(x); /* x is NaN, y is finite */
X else if(y!=y) return(y); /* x and y is NaN */
X else return(copysign(y,one)); /* y is INF */
X}
X#endif
END_OF_FILE
if test 5953 -ne `wc -c <'libm/IEEE/cabs.c'`; then
echo shar: \"'libm/IEEE/cabs.c'\" unpacked with wrong size!
fi
# end of 'libm/IEEE/cabs.c'
fi
if test -f 'libm/README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libm/README'\"
else
echo shar: Extracting \"'libm/README'\" \(13684 characters\)
sed "s/^X//" >'libm/README' <<'END_OF_FILE'
X***************************************************************************
X* *
X* Copyright (c) 1985 Regents of the University of California. *
X* *
X* Use and reproduction of this software are granted in accordance with *
X* the terms and conditions specified in the Berkeley Software License *
X* Agreement (in particular, this entails acknowledgement of the programs' *
X* source, and inclusion of this notice) with the additional understanding *
X* that all recipients should regard themselves as participants in an *
X* ongoing research project and hence should feel obligated to report *
X* their experiences (good or bad) with these elementary function codes, *
X* using "sendbug 4bsd-bugs at BERKELEY", to the authors. *
X* *
X* K.C. Ng, with Z-S. Alex Liu, S. McDonald, P. Tang, W. Kahan. *
X* Revised on 5/10/85, 5/13/85, 6/14/85, 8/20/85, 8/27/85, 9/11/85. *
X* *
X***************************************************************************
X
X/* @(#)README 1.6 (Berkeley) 9/12/85 */
X
XNB. The machine-independent Version 7 math library found in 4.2BSD
X is now /usr/lib/libom.a. To compile with those routines use -lom.
X
X******************************************************************************
X* This is a description of the upgraded elementary functions (listed in 1). *
X* Bessel functions (j0, j1, jn, y0, y1, yn), floor, and fabs passed over *
X* from 4.2BSD without change except perhaps for the way floating point *
X* exception is signaled on a VAX. Three lines that contain "errno" in erf.c*
X* (error functions erf, erfc) have been deleted to prevent overriding the *
X* system "errno". *
X******************************************************************************
X
X0. Total number of files: 40
X
X IEEE/Makefile VAX/Makefile VAX/support.s erf.c lgamma.c
X IEEE/atan2.c VAX/argred.s VAX/tan.s exp.c log.c
X IEEE/cabs.c VAX/atan2.s acosh.c exp__E.c log10.c
X IEEE/cbrt.c VAX/cabs.s asincos.c expm1.c log1p.c
X IEEE/support.c VAX/cbrt.s asinh.c floor.c log__L.c
X IEEE/trig.c VAX/infnan.s atan.c j0.c pow.c
X Makefile VAX/sincos.s atanh.c j1.c sinh.c
X README VAX/sqrt.s cosh.c jn.c tanh.c
X
X1. Functions implemented :
X (A). Standard elementary functions (total 22) :
X acos(x) ...in file asincos.c
X asin(x) ...in file asincos.c
X atan(x) ...in file atan.c
X atan2(x,y) ...in files IEEE/atan2.c, VAX/atan2.s
X sin(x) ...in files IEEE/trig.c, VAX/sincos.s
X cos(x) ...in files IEEE/trig.c, VAX/sincos.s
X tan(x) ...in files IEEE/trig.c, VAX/tan.s
X cabs(x,y) ...in files IEEE/cabs.c, VAX/cabs.s
X hypot(x,y) ...in files IEEE/cabs.c, VAX/cabs.s
X cbrt(x) ...in files IEEE/cbrt.c, VAX/cbrt.s
X exp(x) ...in file exp.c
X expm1(x):=exp(x)-1 ...in file expm1.c
X log(x) ...in file log.c
X log10(x) ...in file log10.c
X log1p(x):=log(1+x) ...in file log1p.c
X pow(x,y) ...in file pow.c
X sinh(x) ...in file sinh.c
X cosh(x) ...in file cosh.c
X tanh(x) ...in file tanh.c
X asinh(x) ...in file asinh.c
X acosh(x) ...in file acosh.c
X atanh(x) ...in file atanh.c
X
X (B). Kernel functions :
X exp__E(x,c) ...in file exp__E.c, used by expm1/exp/pow/cosh
X log__L(s) ...in file log__L.c, used by log1p/log/pow
X libm$argred ...in file VAX/argred.s, used by VAX version of sin/cos/tan
X
X (C). System supported functions :
X sqrt() ...in files IEEE/support.c, VAX/sqrt.s
X drem() ...in files IEEE/support.c, VAX/support.s
X finite() ...in files IEEE/support.c, VAX/support.s
X logb() ...in files IEEE/support.c, VAX/support.s
X scalb() ...in files IEEE/support.c, VAX/support.s
X copysign() ...in files IEEE/support.c, VAX/support.s
X rint() ...in file floor.c
X
X
X Notes:
X i. The codes in files ending with ".s" are written in VAX assembly
X language. They are intended for VAX computers.
X
X Files that end with ".c" are written in C. They are intended
X for either a VAX or a machine that conforms to the IEEE
X standard 754 for double precision floating-point arithmetic.
X
X ii. On other than VAX or IEEE machines, run the original math
X library, formerly "/usr/lib/libm.a", now "/usr/lib/libom.a", if
X nothing better is available.
X
X iii. The trigonometric functions sin/cos/tan/atan2 in files "VAX/sincos.s",
X "VAX/tan.s" and "VAX/atan2.s" are different from those in
X "IEEE/trig.c" and "IEEE/atan2.c". The VAX assembler code uses the
X true value of pi to perform argument reduction, while the C code uses
X a machine value of PI (see "IEEE/trig.c").
X
X
X2. A computer system that conforms to IEEE standard 754 should provide
X sqrt(x),
X drem(x,p), (double precision remainder function)
X copysign(x,y),
X finite(x),
X scalb(x,N),
X logb(x) and
X rint(x).
X These functions are either required or recommended by the standard.
X For convenience, a (slow) C implementation of these functions is
X provided in the file "IEEE/support.c".
X
X Warning: The functions in IEEE/support.c are somewhat machine dependent.
X Some modifications may be necessary to run them on a different machine.
X Currently, if compiled with a suitable flag, "IEEE/support.c" will work
X on a National 32000, a Zilog 8000, a VAX, and a SUN (cf. the "Makefile"
X in this directory). Invoke the C compiler thus:
X
X cc -c -DVAX IEEE/support.c ... on a VAX, D-format
X cc -c -DNATIONAL IEEE/support.c ... on a National 32000
X cc -c IEEE/support.c ... on other IEEE machines,
X we hope.
X
X Notes:
X 1. Faster versions of "drem" and "sqrt" for IEEE double precision
X (coded in C but intended for assembly language) are given at the
X end of "IEEE/support.c" but commented out since they require certain
X machine-dependent functions.
X
X 2. A fast VAX assembler version of the system supported functions
X copysign(), logb(), scalb(), finite(), and drem() appears in file
X "VAX/support.s". A fast VAX assembler version of sqrt() is in
X file "VAX/sqrt.s".
X
X3. Two formats are supported by all the standard elementary functions:
X the VAX D-format (56-bit precision), and the IEEE double format
X (53-bit precision). The cbrt() in "IEEE/cbrt.c" is for IEEE machines
X only. The functions in files that end with ".s" are for VAX computers
X only. The functions in files that end with ".c" (except "IEEE/cbrt.c")
X are for VAX and IEEE machines. To use the VAX D-format, compile the code
X with -DVAX; to use IEEE double format on various IEEE machines, see
X "Makefile" in this directory).
X
X Example:
X cc -c -DVAX sin.c ... for VAX D-format
X
X Warning: The values of floating-point constants used in the code are
X given in both hexadecimal and decimal. The hexadecimal values
X are the intended ones. The decimal values may be used provided
X that the compiler converts from decimal to binary accurately
X enough to produce the hexadecimal values shown. If the
X conversion is inaccurate, then one must know the exact machine
X representation of the constants and alter the assembly
X language output from the compiler, or play tricks like
X the following in a C program.
X
X Example: to store the floating-point constant
X
X p1= 2^-6 * .F83ABE67E1066A (Hexadecimal)
X
X on a VAX in C, we use two longwords to store its
X machine value and define p1 to be the double constant
X at the location of these two longwords:
X
X static long p1x[] = { 0x3abe3d78, 0x066a67e1};
X #define p1 (*(double*)p1x)
X
X Note: On a VAX, some functions have two codes. For example, cabs() has
X one implementation in "IEEE/cabs.c", and another in "VAX/cabs.s".
X In this case, the assembly language version is preferred.
X
X
X4. Accuracy.
X
X The errors in expm1(), log1p(), exp(), log(), cabs(), hypot()
X and cbrt() are below 1 ULP (Unit in the Last Place).
X
X The error in pow(x,y) grows with the size of y. Nevertheless,
X for integers x and y, pow(x,y) returns the correct integer value
X on all tested machines (VAX, SUN, NATIONAL, ZILOG), provided that
X x to the power of y is representable exactly.
X
X cosh, sinh, acosh, asinh, tanh, atanh and log10 have errors below
X about 3 ULPs.
X
X For trigonometric and inverse trigonometric functions:
X
X Let [trig(x)] denote the value actually computed for trig(x),
X
X 1) Those codes using the machine's value PI (true pi rounded):
X (source codes: IEEE/{trig.c,atan2.c}, asincos.c and atan.c)
X
X The errors in [sin(x)], [cos(x)], and [atan(x)] are below
X 1 ULP compared with sin(x*pi/PI), cos(x*pi/PI), and
X atan(x)*PI/pi respectively, where PI is the machine's
X value of pi rounded. [tan(x)] returns tan(x*pi/PI) within
X about 2 ULPs; [acos(x)], [asin(x)], and [atan2(y,x)]
X return acos(x)*PI/pi, asin(x)*PI/pi, and atan2(y,x)*PI/pi
X respectively to similar accuracy.
X
X
X 2) Those using true pi (for VAX D-format only):
X (source codes: VAX/{sincos.s,tan.s,atan2.s}, asincos.c and
X atan.c)
X
X The errors in [sin(x)], [cos(x)], and [atan(x)] are below
X 1 ULP. [tan(x)], [atan2(y,x)], [acos(x)], and [asin(x)]
X have errors below about 2 ULPs.
X
X
X Here are the results of some test runs to find worst errors on
X the VAX :
X
X tan : 2.09 ULPs ...1,024,000 random arguments (machine PI)
X sin : .861 ULPs ...1,024,000 random arguments (machine PI)
X cos : .857 ULPs ...1,024,000 random arguments (machine PI)
X (compared with tan, sin, cos of (x*pi/PI))
X
X acos : 2.07 ULPs .....200,000 random arguments (machine PI)
X asin : 2.06 ULPs .....200,000 random arguments (machine PI)
X atan2 : 1.41 ULPs .....356,000 random arguments (machine PI)
X atan : 0.86 ULPs ...1,536,000 random arguments (machine PI)
X (compared with (PI/pi)*(atan, asin, acos, atan2 of x))
X
X tan : 2.15 ULPs ...1,024,000 random arguments (true pi)
X sin : .814 ULPs ...1,024,000 random arguments (true pi)
X cos : .792 ULPs ...1,024,000 random arguments (true pi)
X acos : 2.15 ULPs ...1,024,000 random arguments (true pi)
X asin : 1.99 ULPs ...1,024,000 random arguments (true pi)
X atan2 : 1.48 ULPs ...1,024,000 random arguments (true pi)
X atan : .850 ULPs ...1,024,000 random arguments (true pi)
X
X acosh : 3.30 ULPs .....512,000 random arguments
X asinh : 1.58 ULPs .....512,000 random arguments
X atanh : 1.71 ULPs .....512,000 random arguments
X cosh : 1.23 ULPs .....768,000 random arguments
X sinh : 1.93 ULPs ...1,024,000 random arguments
X tanh : 2.22 ULPs ...1,024,000 random arguments
X log10 : 1.74 ULPs ...1,536,000 random arguments
X pow : 1.79 ULPs .....100,000 random arguments, 0 < x, y < 20.
X
X exp : .768 ULPs ...1,156,000 random arguments
X expm1 : .844 ULPs ...1,166,000 random arguments
X log1p : .846 ULPs ...1,536,000 random arguments
X log : .826 ULPs ...1,536,000 random arguments
X cabs : .959 ULPs .....500,000 random arguments
X cbrt : .666 ULPs ...5,120,000 random arguments
X
X
X5. Speed.
X
X Some functions coded in VAX assembly language (cabs(), hypot() and
X sqrt()) are significantly faster than the corresponding ones in 4.2BSD.
X In general, to improve performance, all functions in "IEEE/support.c"
X should be written in assembly language and, whenever possible, should
X be called via short subroutine calls.
X
X
X6. j0, j1, jn.
X
X The modifications to these routines were only in how an invalid
X floating point operations is signaled.
END_OF_FILE
if test 13684 -ne `wc -c <'libm/README'`; then
echo shar: \"'libm/README'\" unpacked with wrong size!
fi
# end of 'libm/README'
fi
if test -f 'libm/VAX/atan2.s' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libm/VAX/atan2.s'\"
else
echo shar: Extracting \"'libm/VAX/atan2.s'\" \(5517 characters\)
sed "s/^X//" >'libm/VAX/atan2.s' <<'END_OF_FILE'
X#
X# Copyright (c) 1985 Regents of the University of California.
X#
X# Use and reproduction of this software are granted in accordance with
X# the terms and conditions specified in the Berkeley Software License
X# Agreement (in particular, this entails acknowledgement of the programs'
X# source, and inclusion of this notice) with the additional understanding
X# that all recipients should regard themselves as participants in an
X# ongoing research project and hence should feel obligated to report
X# their experiences (good or bad) with these elementary function codes,
X# using "sendbug 4bsd-bugs at BERKELEY", to the authors.
X#
X
X# @(#)atan2.s 1.2 (Berkeley) 8/21/85
X
X# ATAN2(Y,X)
X# RETURN ARG (X+iY)
X# VAX D FORMAT (56 BITS PRECISION)
X# CODED IN VAX ASSEMBLY LANGUAGE BY K.C. NG, 4/16/85;
X#
X#
X# Method :
X# 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
X# 2. Reduce x to positive by (if x and y are unexceptional):
X# ARG (x+iy) = arctan(y/x) ... if x > 0,
X# ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,
X# 3. According to the integer k=4t+0.25 truncated , t=y/x, the argument
X# is further reduced to one of the following intervals and the
X# arctangent of y/x is evaluated by the corresponding formula:
X#
X# [0,7/16] atan(y/x) = t - t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
X# [7/16,11/16] atan(y/x) = atan(1/2) + atan( (y-x/2)/(x+y/2) )
X# [11/16.19/16] atan(y/x) = atan( 1 ) + atan( (y-x)/(x+y) )
X# [19/16,39/16] atan(y/x) = atan(3/2) + atan( (y-1.5x)/(x+1.5y) )
X# [39/16,INF] atan(y/x) = atan(INF) + atan( -x/y )
X#
X# Special cases:
X# Notations: atan2(y,x) == ARG (x+iy) == ARG(x,y).
X#
X# ARG( NAN , (anything) ) is NaN;
X# ARG( (anything), NaN ) is NaN;
X# ARG(+(anything but NaN), +-0) is +-0 ;
X# ARG(-(anything but NaN), +-0) is +-PI ;
X# ARG( 0, +-(anything but 0 and NaN) ) is +-PI/2;
X# ARG( +INF,+-(anything but INF and NaN) ) is +-0 ;
X# ARG( -INF,+-(anything but INF and NaN) ) is +-PI;
X# ARG( +INF,+-INF ) is +-PI/4 ;
X# ARG( -INF,+-INF ) is +-3PI/4;
X# ARG( (anything but,0,NaN, and INF),+-INF ) is +-PI/2;
X#
X# Accuracy:
X# atan2(y,x) returns the exact ARG(x+iy) nearly rounded.
X#
X .text
X .align 1
X .globl _atan2
X_atan2 :
X .word 0x0ff4
X movq 4(ap),r2 # r2 = y
X movq 12(ap),r4 # r4 = x
X bicw3 $0x7f,r2,r0
X bicw3 $0x7f,r4,r1
X cmpw r0,$0x8000 # y is the reserved operand
X jeql resop
X cmpw r1,$0x8000 # x is the reserved operand
X jeql resop
X subl2 $8,sp
X bicw3 $0x7fff,r2,-4(fp) # copy y sign bit to -4(fp)
X bicw3 $0x7fff,r4,-8(fp) # copy x sign bit to -8(fp)
X cmpd r4,$0x4080 # x = 1.0 ?
X bneq xnot1
X movq r2,r0
X bicw2 $0x8000,r0 # t = |y|
X movq r0,r2 # y = |y|
X brb begin
Xxnot1:
X bicw3 $0x807f,r2,r11 # yexp
X jeql yeq0 # if y=0 goto yeq0
X bicw3 $0x807f,r4,r10 # xexp
X jeql pio2 # if x=0 goto pio2
X subw2 r10,r11 # k = yexp - xexp
X cmpw r11,$0x2000 # k >= 64 (exp) ?
X jgeq pio2 # atan2 = +-pi/2
X divd3 r4,r2,r0 # t = y/x never overflow
X bicw2 $0x8000,r0 # t > 0
X bicw2 $0xff80,r2 # clear the exponent of y
X bicw2 $0xff80,r4 # clear the exponent of x
X bisw2 $0x4080,r2 # normalize y to [1,2)
X bisw2 $0x4080,r4 # normalize x to [1,2)
X subw2 r11,r4 # scale x so that yexp-xexp=k
Xbegin:
X cmpw r0,$0x411c # t : 39/16
X jgeq L50
X addl3 $0x180,r0,r10 # 8*t
X cvtrfl r10,r10 # [8*t] rounded to int
X ashl $-1,r10,r10 # [8*t]/2
X casel r10,$0,$4
XL1:
X .word L20-L1
X .word L20-L1
X .word L30-L1
X .word L40-L1
X .word L40-L1
XL10:
X movq $0xb4d9940f985e407b,r6 # Hi=.98279372324732906796d0
X movq $0x21b1879a3bc2a2fc,r8 # Lo=-.17092002525602665777d-17
X subd3 r4,r2,r0 # y-x
X addw2 $0x80,r0 # 2(y-x)
X subd2 r4,r0 # 2(y-x)-x
X addw2 $0x80,r4 # 2x
X movq r2,r10
X addw2 $0x80,r10 # 2y
X addd2 r10,r2 # 3y
X addd2 r4,r2 # 3y+2x
X divd2 r2,r0 # (2y-3x)/(2x+3y)
X brw L60
XL20:
X cmpw r0,$0x3280 # t : 2**(-28)
X jlss L80
X clrq r6 # Hi=r6=0, Lo=r8=0
X clrq r8
X brw L60
XL30:
X movq $0xda7b2b0d63383fed,r6 # Hi=.46364760900080611433d0
X movq $0xf0ea17b2bf912295,r8 # Lo=.10147340032515978826d-17
X movq r2,r0
X addw2 $0x80,r0 # 2y
X subd2 r4,r0 # 2y-x
X addw2 $0x80,r4 # 2x
X addd2 r2,r4 # 2x+y
X divd2 r4,r0 # (2y-x)/(2x+y)
X brb L60
XL50:
X movq $0x68c2a2210fda40c9,r6 # Hi=1.5707963267948966135d1
X movq $0x06e0145c26332326,r8 # Lo=.22517417741562176079d-17
X cmpw r0,$0x5100 # y : 2**57
X bgeq L90
X divd3 r2,r4,r0
X bisw2 $0x8000,r0 # -x/y
X brb L60
XL40:
X movq $0x68c2a2210fda4049,r6 # Hi=.78539816339744830676d0
X movq $0x06e0145c263322a6,r8 # Lo=.11258708870781088040d-17
X subd3 r4,r2,r0 # y-x
X addd2 r4,r2 # y+x
X divd2 r2,r0 # (y-x)/(y+x)
XL60:
X movq r0,r10
X muld2 r0,r0
X polyd r0,$12,ptable
X muld2 r10,r0
X subd2 r0,r8
X addd3 r8,r10,r0
X addd2 r6,r0
XL80:
X movw -8(fp),r2
X bneq pim
X bisw2 -4(fp),r0 # return sign(y)*r0
X ret
XL90: # x >= 2**25
X movq r6,r0
X brb L80
Xpim:
X subd3 r0,$0x68c2a2210fda4149,r0 # pi-t
X bisw2 -4(fp),r0
X ret
Xyeq0:
X movw -8(fp),r2
X beql zero # if sign(x)=1 return pi
X movq $0x68c2a2210fda4149,r0 # pi=3.1415926535897932270d1
X ret
Xzero:
X clrq r0 # return 0
X ret
Xpio2:
X movq $0x68c2a2210fda40c9,r0 # pi/2=1.5707963267948966135d1
X bisw2 -4(fp),r0 # return sign(y)*pi/2
X ret
Xresop:
X movq $0x8000,r0 # propagate the reserved operand
X ret
X .align 2
Xptable:
X .quad 0xb50f5ce96e7abd60
X .quad 0x51e44a42c1073e02
X .quad 0x3487e3289643be35
X .quad 0xdb62066dffba3e54
X .quad 0xcf8e2d5199abbe70
X .quad 0x26f39cb884883e88
X .quad 0x135117d18998be9d
X .quad 0x602ce9742e883eba
X .quad 0xa35ad0be8e38bee3
X .quad 0xffac922249243f12
X .quad 0x7f14ccccccccbf4c
X .quad 0xaa8faaaaaaaa3faa
X .quad 0x0000000000000000
END_OF_FILE
if test 5517 -ne `wc -c <'libm/VAX/atan2.s'`; then
echo shar: \"'libm/VAX/atan2.s'\" unpacked with wrong size!
fi
# end of 'libm/VAX/atan2.s'
fi
if test -f 'libm/log1p.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libm/log1p.c'\"
else
echo shar: Extracting \"'libm/log1p.c'\" \(4986 characters\)
sed "s/^X//" >'libm/log1p.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1985 Regents of the University of California.
X *
X * Use and reproduction of this software are granted in accordance with
X * the terms and conditions specified in the Berkeley Software License
X * Agreement (in particular, this entails acknowledgement of the programs'
X * source, and inclusion of this notice) with the additional understanding
X * that all recipients should regard themselves as participants in an
X * ongoing research project and hence should feel obligated to report
X * their experiences (good or bad) with these elementary function codes,
X * using "sendbug 4bsd-bugs at BERKELEY", to the authors.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)log1p.c 1.3 (Berkeley) 8/21/85";
X#endif not lint
X
X/* LOG1P(x)
X * RETURN THE LOGARITHM OF 1+x
X * DOUBLE PRECISION (VAX D FORMAT 56 bits, IEEE DOUBLE 53 BITS)
X * CODED IN C BY K.C. NG, 1/19/85;
X * REVISED BY K.C. NG on 2/6/85, 3/7/85, 3/24/85, 4/16/85.
X *
X * Required system supported functions:
X * scalb(x,n)
X * copysign(x,y)
X * logb(x)
X * finite(x)
X *
X * Required kernel function:
X * log__L(z)
X *
X * Method :
X * 1. Argument Reduction: find k and f such that
X * 1+x = 2^k * (1+f),
X * where sqrt(2)/2 < 1+f < sqrt(2) .
X *
X * 2. Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
X * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
X * log(1+f) is computed by
X *
X * log(1+f) = 2s + s*log__L(s*s)
X * where
X * log__L(z) = z*(L1 + z*(L2 + z*(... (L6 + z*L7)...)))
X *
X * See log__L() for the values of the coefficients.
X *
X * 3. Finally, log(1+x) = k*ln2 + log(1+f).
X *
X * Remarks 1. In step 3 n*ln2 will be stored in two floating point numbers
X * n*ln2hi + n*ln2lo, where ln2hi is chosen such that the last
X * 20 bits (for VAX D format), or the last 21 bits ( for IEEE
X * double) is 0. This ensures n*ln2hi is exactly representable.
X * 2. In step 1, f may not be representable. A correction term c
X * for f is computed. It follows that the correction term for
X * f - t (the leading term of log(1+f) in step 2) is c-c*x. We
X * add this correction term to n*ln2lo to attenuate the error.
X *
X *
X * Special cases:
X * log1p(x) is NaN with signal if x < -1; log1p(NaN) is NaN with no signal;
X * log1p(INF) is +INF; log1p(-1) is -INF with signal;
X * only log1p(0)=0 is exact for finite argument.
X *
X * Accuracy:
X * log1p(x) returns the exact log(1+x) nearly rounded. In a test run
X * with 1,536,000 random arguments on a VAX, the maximum observed
X * error was .846 ulps (units in the last place).
X *
X * Constants:
X * The hexadecimal values are the intended ones for the following constants.
X * The decimal values may be used, provided that the compiler will convert
X * from decimal to binary accurately enough to produce the hexadecimal values
X * shown.
X */
X
X#ifdef VAX /* VAX D format */
X#include <errno.h>
X
X/* double static */
X/* ln2hi = 6.9314718055829871446E-1 , Hex 2^ 0 * .B17217F7D00000 */
X/* ln2lo = 1.6465949582897081279E-12 , Hex 2^-39 * .E7BCD5E4F1D9CC */
X/* sqrt2 = 1.4142135623730950622E0 ; Hex 2^ 1 * .B504F333F9DE65 */
Xstatic long ln2hix[] = { 0x72174031, 0x0000f7d0};
Xstatic long ln2lox[] = { 0xbcd52ce7, 0xd9cce4f1};
Xstatic long sqrt2x[] = { 0x04f340b5, 0xde6533f9};
X#define ln2hi (*(double*)ln2hix)
X#define ln2lo (*(double*)ln2lox)
X#define sqrt2 (*(double*)sqrt2x)
X#else /* IEEE double */
Xdouble static
Xln2hi = 6.9314718036912381649E-1 , /*Hex 2^ -1 * 1.62E42FEE00000 */
Xln2lo = 1.9082149292705877000E-10 , /*Hex 2^-33 * 1.A39EF35793C76 */
Xsqrt2 = 1.4142135623730951455E0 ; /*Hex 2^ 0 * 1.6A09E667F3BCD */
X#endif
X
Xdouble log1p(x)
Xdouble x;
X{
X static double zero=0.0, negone= -1.0, one=1.0,
X half=1.0/2.0, small=1.0E-20; /* 1+small == 1 */
X double logb(),copysign(),scalb(),log__L(),z,s,t,c;
X int k,finite();
X
X#ifndef VAX
X if(x!=x) return(x); /* x is NaN */
X#endif
X
X if(finite(x)) {
X if( x > negone ) {
X
X /* argument reduction */
X if(copysign(x,one)<small) return(x);
X k=logb(one+x); z=scalb(x,-k); t=scalb(one,-k);
X if(z+t >= sqrt2 )
X { k += 1 ; z *= half; t *= half; }
X t += negone; x = z + t;
X c = (t-x)+z ; /* correction term for x */
X
X /* compute log(1+x) */
X s = x/(2+x); t = x*x*half;
X c += (k*ln2lo-c*x);
X z = c+s*(t+log__L(s*s));
X x += (z - t) ;
X
X return(k*ln2hi+x);
X }
X /* end of if (x > negone) */
X
X else {
X#ifdef VAX
X extern double infnan();
X if ( x == negone )
X return (infnan(-ERANGE)); /* -INF */
X else
X return (infnan(EDOM)); /* NaN */
X#else /* IEEE double */
X /* x = -1, return -INF with signal */
X if ( x == negone ) return( negone/zero );
X
X /* negative argument for log, return NaN with signal */
X else return ( zero / zero );
X#endif
X }
X }
X /* end of if (finite(x)) */
X
X /* log(-INF) is NaN */
X else if(x<0)
X return(zero/zero);
X
X /* log(+INF) is INF */
X else return(x);
X}
END_OF_FILE
if test 4986 -ne `wc -c <'libm/log1p.c'`; then
echo shar: \"'libm/log1p.c'\" unpacked with wrong size!
fi
# end of 'libm/log1p.c'
fi
if test -f 'libm/pow.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libm/pow.c'\"
else
echo shar: Extracting \"'libm/pow.c'\" \(7529 characters\)
sed "s/^X//" >'libm/pow.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1985 Regents of the University of California.
X *
X * Use and reproduction of this software are granted in accordance with
X * the terms and conditions specified in the Berkeley Software License
X * Agreement (in particular, this entails acknowledgement of the programs'
X * source, and inclusion of this notice) with the additional understanding
X * that all recipients should regard themselves as participants in an
X * ongoing research project and hence should feel obligated to report
X * their experiences (good or bad) with these elementary function codes,
X * using "sendbug 4bsd-bugs at BERKELEY", to the authors.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)pow.c 4.5 (Berkeley) 8/21/85";
X#endif not lint
X
X/* POW(X,Y)
X * RETURN X**Y
X * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
X * CODED IN C BY K.C. NG, 1/8/85;
X * REVISED BY K.C. NG on 7/10/85.
X *
X * Required system supported functions:
X * scalb(x,n)
X * logb(x)
X * copysign(x,y)
X * finite(x)
X * drem(x,y)
X *
X * Required kernel functions:
X * exp__E(a,c) ...return exp(a+c) - 1 - a*a/2
X * log__L(x) ...return (log(1+x) - 2s)/s, s=x/(2+x)
X * pow_p(x,y) ...return +(anything)**(finite non zero)
X *
X * Method
X * 1. Compute and return log(x) in three pieces:
X * log(x) = n*ln2 + hi + lo,
X * where n is an integer.
X * 2. Perform y*log(x) by simulating muti-precision arithmetic and
X * return the answer in three pieces:
X * y*log(x) = m*ln2 + hi + lo,
X * where m is an integer.
X * 3. Return x**y = exp(y*log(x))
X * = 2^m * ( exp(hi+lo) ).
X *
X * Special cases:
X * (anything) ** 0 is 1 ;
X * (anything) ** 1 is itself;
X * (anything) ** NaN is NaN;
X * NaN ** (anything except 0) is NaN;
X * +-(anything > 1) ** +INF is +INF;
X * +-(anything > 1) ** -INF is +0;
X * +-(anything < 1) ** +INF is +0;
X * +-(anything < 1) ** -INF is +INF;
X * +-1 ** +-INF is NaN and signal INVALID;
X * +0 ** +(anything except 0, NaN) is +0;
X * -0 ** +(anything except 0, NaN, odd integer) is +0;
X * +0 ** -(anything except 0, NaN) is +INF and signal DIV-BY-ZERO;
X * -0 ** -(anything except 0, NaN, odd integer) is +INF with signal;
X * -0 ** (odd integer) = -( +0 ** (odd integer) );
X * +INF ** +(anything except 0,NaN) is +INF;
X * +INF ** -(anything except 0,NaN) is +0;
X * -INF ** (odd integer) = -( +INF ** (odd integer) );
X * -INF ** (even integer) = ( +INF ** (even integer) );
X * -INF ** -(anything except integer,NaN) is NaN with signal;
X * -(x=anything) ** (k=integer) is (-1)**k * (x ** k);
X * -(anything except 0) ** (non-integer) is NaN with signal;
X *
X * Accuracy:
X * pow(x,y) returns x**y nearly rounded. In particular, on a SUN, a VAX,
X * and a Zilog Z8000,
X * pow(integer,integer)
X * always returns the correct integer provided it is representable.
X * In a test run with 100,000 random arguments with 0 < x, y < 20.0
X * on a VAX, the maximum observed error was 1.79 ulps (units in the
X * last place).
X *
X * Constants :
X * The hexadecimal values are the intended ones for the following constants.
X * The decimal values may be used, provided that the compiler will convert
X * from decimal to binary accurately enough to produce the hexadecimal values
X * shown.
X */
X
X#ifdef VAX /* VAX D format */
X#include <errno.h>
Xextern double infnan();
X
X/* double static */
X/* ln2hi = 6.9314718055829871446E-1 , Hex 2^ 0 * .B17217F7D00000 */
X/* ln2lo = 1.6465949582897081279E-12 , Hex 2^-39 * .E7BCD5E4F1D9CC */
X/* invln2 = 1.4426950408889634148E0 , Hex 2^ 1 * .B8AA3B295C17F1 */
X/* sqrt2 = 1.4142135623730950622E0 ; Hex 2^ 1 * .B504F333F9DE65 */
Xstatic long ln2hix[] = { 0x72174031, 0x0000f7d0};
Xstatic long ln2lox[] = { 0xbcd52ce7, 0xd9cce4f1};
Xstatic long invln2x[] = { 0xaa3b40b8, 0x17f1295c};
Xstatic long sqrt2x[] = { 0x04f340b5, 0xde6533f9};
X#define ln2hi (*(double*)ln2hix)
X#define ln2lo (*(double*)ln2lox)
X#define invln2 (*(double*)invln2x)
X#define sqrt2 (*(double*)sqrt2x)
X#else /* IEEE double */
Xdouble static
Xln2hi = 6.9314718036912381649E-1 , /*Hex 2^ -1 * 1.62E42FEE00000 */
Xln2lo = 1.9082149292705877000E-10 , /*Hex 2^-33 * 1.A39EF35793C76 */
Xinvln2 = 1.4426950408889633870E0 , /*Hex 2^ 0 * 1.71547652B82FE */
Xsqrt2 = 1.4142135623730951455E0 ; /*Hex 2^ 0 * 1.6A09E667F3BCD */
X#endif
X
Xdouble static zero=0.0, half=1.0/2.0, one=1.0, two=2.0, negone= -1.0;
X
Xdouble pow(x,y)
Xdouble x,y;
X{
X double drem(),pow_p(),copysign(),t;
X int finite();
X
X if (y==zero) return(one);
X else if(y==one
X#ifndef VAX
X ||x!=x
X#endif
X ) return( x ); /* if x is NaN or y=1 */
X#ifndef VAX
X else if(y!=y) return( y ); /* if y is NaN */
X#endif
X else if(!finite(y)) /* if y is INF */
X if((t=copysign(x,one))==one) return(zero/zero);
X else if(t>one) return((y>zero)?y:zero);
X else return((y<zero)?-y:zero);
X else if(y==two) return(x*x);
X else if(y==negone) return(one/x);
X
X /* sign(x) = 1 */
X else if(copysign(one,x)==one) return(pow_p(x,y));
X
X /* sign(x)= -1 */
X /* if y is an even integer */
X else if ( (t=drem(y,two)) == zero) return( pow_p(-x,y) );
X
X /* if y is an odd integer */
X else if (copysign(t,one) == one) return( -pow_p(-x,y) );
X
X /* Henceforth y is not an integer */
X else if(x==zero) /* x is -0 */
X return((y>zero)?-x:one/(-x));
X else { /* return NaN */
X#ifdef VAX
X return (infnan(EDOM)); /* NaN */
X#else /* IEEE double */
X return(zero/zero);
X#endif
X }
X}
X
X/* pow_p(x,y) return x**y for x with sign=1 and finite y */
Xstatic double pow_p(x,y)
Xdouble x,y;
X{
X double logb(),scalb(),copysign(),log__L(),exp__E();
X double c,s,t,z,tx,ty;
X float sx,sy;
X long k=0;
X int n,m;
X
X if(x==zero||!finite(x)) { /* if x is +INF or +0 */
X#ifdef VAX
X return((y>zero)?x:infnan(ERANGE)); /* if y<zero, return +INF */
X#else
X return((y>zero)?x:one/x);
X#endif
X }
X if(x==1.0) return(x); /* if x=1.0, return 1 since y is finite */
X
X /* reduce x to z in [sqrt(1/2)-1, sqrt(2)-1] */
X z=scalb(x,-(n=logb(x)));
X#ifndef VAX /* IEEE double */ /* subnormal number */
X if(n <= -1022) {n += (m=logb(z)); z=scalb(z,-m);}
X#endif
X if(z >= sqrt2 ) {n += 1; z *= half;} z -= one ;
X
X /* log(x) = nlog2+log(1+z) ~ nlog2 + t + tx */
X s=z/(two+z); c=z*z*half; tx=s*(c+log__L(s*s));
X t= z-(c-tx); tx += (z-t)-c;
X
X /* if y*log(x) is neither too big nor too small */
X if((s=logb(y)+logb(n+t)) < 12.0)
X if(s>-60.0) {
X
X /* compute y*log(x) ~ mlog2 + t + c */
X s=y*(n+invln2*t);
X m=s+copysign(half,s); /* m := nint(y*log(x)) */
X k=y;
X if((double)k==y) { /* if y is an integer */
X k = m-k*n;
X sx=t; tx+=(t-sx); }
X else { /* if y is not an integer */
X k =m;
X tx+=n*ln2lo;
X sx=(c=n*ln2hi)+t; tx+=(c-sx)+t; }
X /* end of checking whether k==y */
X
X sy=y; ty=y-sy; /* y ~ sy + ty */
X s=(double)sx*sy-k*ln2hi; /* (sy+ty)*(sx+tx)-kln2 */
X z=(tx*ty-k*ln2lo);
X tx=tx*sy; ty=sx*ty;
X t=ty+z; t+=tx; t+=s;
X c= -((((t-s)-tx)-ty)-z);
X
X /* return exp(y*log(x)) */
X t += exp__E(t,c); return(scalb(one+t,m));
X }
X /* end of if log(y*log(x)) > -60.0 */
X
X else
X /* exp(+- tiny) = 1 with inexact flag */
X {ln2hi+ln2lo; return(one);}
X else if(copysign(one,y)*(n+invln2*t) <zero)
X /* exp(-(big#)) underflows to zero */
X return(scalb(one,-5000));
X else
X /* exp(+(big#)) overflows to INF */
X return(scalb(one, 5000));
X
X}
END_OF_FILE
if test 7529 -ne `wc -c <'libm/pow.c'`; then
echo shar: \"'libm/pow.c'\" unpacked with wrong size!
fi
# end of 'libm/pow.c'
fi
echo shar: End of archive 3 \(of 5\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 5 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list