rsalz@uunet.uu.net (Rich Salz) (10/27/88)
Submitted-by: Thos Sumner <root@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@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@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@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@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@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@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@uunet.uu.net.