|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: * ! 17: * All recipients should regard themselves as participants in an ongoing ! 18: * research project and hence should feel obligated to report their ! 19: * experiences (good or bad) with these elementary function codes, using ! 20: * the sendbug(8) program, to the authors. ! 21: */ ! 22: ! 23: #ifndef lint ! 24: static char sccsid[] = "@(#)pow.c 5.3 (Berkeley) 6/30/88"; ! 25: #endif /* not lint */ ! 26: ! 27: /* POW(X,Y) ! 28: * RETURN X**Y ! 29: * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) ! 30: * CODED IN C BY K.C. NG, 1/8/85; ! 31: * REVISED BY K.C. NG on 7/10/85. ! 32: * ! 33: * Required system supported functions: ! 34: * scalb(x,n) ! 35: * logb(x) ! 36: * copysign(x,y) ! 37: * finite(x) ! 38: * drem(x,y) ! 39: * ! 40: * Required kernel functions: ! 41: * exp__E(a,c) ...return exp(a+c) - 1 - a*a/2 ! 42: * log__L(x) ...return (log(1+x) - 2s)/s, s=x/(2+x) ! 43: * pow_p(x,y) ...return +(anything)**(finite non zero) ! 44: * ! 45: * Method ! 46: * 1. Compute and return log(x) in three pieces: ! 47: * log(x) = n*ln2 + hi + lo, ! 48: * where n is an integer. ! 49: * 2. Perform y*log(x) by simulating muti-precision arithmetic and ! 50: * return the answer in three pieces: ! 51: * y*log(x) = m*ln2 + hi + lo, ! 52: * where m is an integer. ! 53: * 3. Return x**y = exp(y*log(x)) ! 54: * = 2^m * ( exp(hi+lo) ). ! 55: * ! 56: * Special cases: ! 57: * (anything) ** 0 is 1 ; ! 58: * (anything) ** 1 is itself; ! 59: * (anything) ** NaN is NaN; ! 60: * NaN ** (anything except 0) is NaN; ! 61: * +-(anything > 1) ** +INF is +INF; ! 62: * +-(anything > 1) ** -INF is +0; ! 63: * +-(anything < 1) ** +INF is +0; ! 64: * +-(anything < 1) ** -INF is +INF; ! 65: * +-1 ** +-INF is NaN and signal INVALID; ! 66: * +0 ** +(anything except 0, NaN) is +0; ! 67: * -0 ** +(anything except 0, NaN, odd integer) is +0; ! 68: * +0 ** -(anything except 0, NaN) is +INF and signal DIV-BY-ZERO; ! 69: * -0 ** -(anything except 0, NaN, odd integer) is +INF with signal; ! 70: * -0 ** (odd integer) = -( +0 ** (odd integer) ); ! 71: * +INF ** +(anything except 0,NaN) is +INF; ! 72: * +INF ** -(anything except 0,NaN) is +0; ! 73: * -INF ** (odd integer) = -( +INF ** (odd integer) ); ! 74: * -INF ** (even integer) = ( +INF ** (even integer) ); ! 75: * -INF ** -(anything except integer,NaN) is NaN with signal; ! 76: * -(x=anything) ** (k=integer) is (-1)**k * (x ** k); ! 77: * -(anything except 0) ** (non-integer) is NaN with signal; ! 78: * ! 79: * Accuracy: ! 80: * pow(x,y) returns x**y nearly rounded. In particular, on a SUN, a VAX, ! 81: * and a Zilog Z8000, ! 82: * pow(integer,integer) ! 83: * always returns the correct integer provided it is representable. ! 84: * In a test run with 100,000 random arguments with 0 < x, y < 20.0 ! 85: * on a VAX, the maximum observed error was 1.79 ulps (units in the ! 86: * last place). ! 87: * ! 88: * Constants : ! 89: * The hexadecimal values are the intended ones for the following constants. ! 90: * The decimal values may be used, provided that the compiler will convert ! 91: * from decimal to binary accurately enough to produce the hexadecimal values ! 92: * shown. ! 93: */ ! 94: ! 95: #if defined(vax)||defined(tahoe) /* VAX D format */ ! 96: #include <errno.h> ! 97: extern double infnan(); ! 98: #ifdef vax ! 99: #define _0x(A,B) 0x/**/A/**/B ! 100: #else /* vax */ ! 101: #define _0x(A,B) 0x/**/B/**/A ! 102: #endif /* vax */ ! 103: /* static double */ ! 104: /* ln2hi = 6.9314718055829871446E-1 , Hex 2^ 0 * .B17217F7D00000 */ ! 105: /* ln2lo = 1.6465949582897081279E-12 , Hex 2^-39 * .E7BCD5E4F1D9CC */ ! 106: /* invln2 = 1.4426950408889634148E0 , Hex 2^ 1 * .B8AA3B295C17F1 */ ! 107: /* sqrt2 = 1.4142135623730950622E0 ; Hex 2^ 1 * .B504F333F9DE65 */ ! 108: static long ln2hix[] = { _0x(7217,4031), _0x(0000,f7d0)}; ! 109: static long ln2lox[] = { _0x(bcd5,2ce7), _0x(d9cc,e4f1)}; ! 110: static long invln2x[] = { _0x(aa3b,40b8), _0x(17f1,295c)}; ! 111: static long sqrt2x[] = { _0x(04f3,40b5), _0x(de65,33f9)}; ! 112: #define ln2hi (*(double*)ln2hix) ! 113: #define ln2lo (*(double*)ln2lox) ! 114: #define invln2 (*(double*)invln2x) ! 115: #define sqrt2 (*(double*)sqrt2x) ! 116: #else /* defined(vax)||defined(tahoe) */ ! 117: static double ! 118: ln2hi = 6.9314718036912381649E-1 , /*Hex 2^ -1 * 1.62E42FEE00000 */ ! 119: ln2lo = 1.9082149292705877000E-10 , /*Hex 2^-33 * 1.A39EF35793C76 */ ! 120: invln2 = 1.4426950408889633870E0 , /*Hex 2^ 0 * 1.71547652B82FE */ ! 121: sqrt2 = 1.4142135623730951455E0 ; /*Hex 2^ 0 * 1.6A09E667F3BCD */ ! 122: #endif /* defined(vax)||defined(tahoe) */ ! 123: ! 124: static double zero=0.0, half=1.0/2.0, one=1.0, two=2.0, negone= -1.0; ! 125: ! 126: double pow(x,y) ! 127: double x,y; ! 128: { ! 129: double drem(),pow_p(),copysign(),t; ! 130: int finite(); ! 131: ! 132: if (y==zero) return(one); ! 133: else if(y==one ! 134: #if !defined(vax)&&!defined(tahoe) ! 135: ||x!=x ! 136: #endif /* !defined(vax)&&!defined(tahoe) */ ! 137: ) return( x ); /* if x is NaN or y=1 */ ! 138: #if !defined(vax)&&!defined(tahoe) ! 139: else if(y!=y) return( y ); /* if y is NaN */ ! 140: #endif /* !defined(vax)&&!defined(tahoe) */ ! 141: else if(!finite(y)) /* if y is INF */ ! 142: if((t=copysign(x,one))==one) return(zero/zero); ! 143: else if(t>one) return((y>zero)?y:zero); ! 144: else return((y<zero)?-y:zero); ! 145: else if(y==two) return(x*x); ! 146: else if(y==negone) return(one/x); ! 147: ! 148: /* sign(x) = 1 */ ! 149: else if(copysign(one,x)==one) return(pow_p(x,y)); ! 150: ! 151: /* sign(x)= -1 */ ! 152: /* if y is an even integer */ ! 153: else if ( (t=drem(y,two)) == zero) return( pow_p(-x,y) ); ! 154: ! 155: /* if y is an odd integer */ ! 156: else if (copysign(t,one) == one) return( -pow_p(-x,y) ); ! 157: ! 158: /* Henceforth y is not an integer */ ! 159: else if(x==zero) /* x is -0 */ ! 160: return((y>zero)?-x:one/(-x)); ! 161: else { /* return NaN */ ! 162: #if defined(vax)||defined(tahoe) ! 163: return (infnan(EDOM)); /* NaN */ ! 164: #else /* defined(vax)||defined(tahoe) */ ! 165: return(zero/zero); ! 166: #endif /* defined(vax)||defined(tahoe) */ ! 167: } ! 168: } ! 169: ! 170: /* pow_p(x,y) return x**y for x with sign=1 and finite y */ ! 171: static double pow_p(x,y) ! 172: double x,y; ! 173: { ! 174: double logb(),scalb(),copysign(),log__L(),exp__E(); ! 175: double c,s,t,z,tx,ty; ! 176: #ifdef tahoe ! 177: double tahoe_tmp; ! 178: #endif /* tahoe */ ! 179: float sx,sy; ! 180: long k=0; ! 181: int n,m; ! 182: ! 183: if(x==zero||!finite(x)) { /* if x is +INF or +0 */ ! 184: #if defined(vax)||defined(tahoe) ! 185: return((y>zero)?x:infnan(ERANGE)); /* if y<zero, return +INF */ ! 186: #else /* defined(vax)||defined(tahoe) */ ! 187: return((y>zero)?x:one/x); ! 188: #endif /* defined(vax)||defined(tahoe) */ ! 189: } ! 190: if(x==1.0) return(x); /* if x=1.0, return 1 since y is finite */ ! 191: ! 192: /* reduce x to z in [sqrt(1/2)-1, sqrt(2)-1] */ ! 193: z=scalb(x,-(n=logb(x))); ! 194: #if !defined(vax)&&!defined(tahoe) /* IEEE double; subnormal number */ ! 195: if(n <= -1022) {n += (m=logb(z)); z=scalb(z,-m);} ! 196: #endif /* !defined(vax)&&!defined(tahoe) */ ! 197: if(z >= sqrt2 ) {n += 1; z *= half;} z -= one ; ! 198: ! 199: /* log(x) = nlog2+log(1+z) ~ nlog2 + t + tx */ ! 200: s=z/(two+z); c=z*z*half; tx=s*(c+log__L(s*s)); ! 201: t= z-(c-tx); tx += (z-t)-c; ! 202: ! 203: /* if y*log(x) is neither too big nor too small */ ! 204: if((s=logb(y)+logb(n+t)) < 12.0) ! 205: if(s>-60.0) { ! 206: ! 207: /* compute y*log(x) ~ mlog2 + t + c */ ! 208: s=y*(n+invln2*t); ! 209: m=s+copysign(half,s); /* m := nint(y*log(x)) */ ! 210: k=y; ! 211: if((double)k==y) { /* if y is an integer */ ! 212: k = m-k*n; ! 213: sx=t; tx+=(t-sx); } ! 214: else { /* if y is not an integer */ ! 215: k =m; ! 216: tx+=n*ln2lo; ! 217: sx=(c=n*ln2hi)+t; tx+=(c-sx)+t; } ! 218: /* end of checking whether k==y */ ! 219: ! 220: sy=y; ty=y-sy; /* y ~ sy + ty */ ! 221: #ifdef tahoe ! 222: s = (tahoe_tmp = sx)*sy-k*ln2hi; ! 223: #else /* tahoe */ ! 224: s=(double)sx*sy-k*ln2hi; /* (sy+ty)*(sx+tx)-kln2 */ ! 225: #endif /* tahoe */ ! 226: z=(tx*ty-k*ln2lo); ! 227: tx=tx*sy; ty=sx*ty; ! 228: t=ty+z; t+=tx; t+=s; ! 229: c= -((((t-s)-tx)-ty)-z); ! 230: ! 231: /* return exp(y*log(x)) */ ! 232: t += exp__E(t,c); return(scalb(one+t,m)); ! 233: } ! 234: /* end of if log(y*log(x)) > -60.0 */ ! 235: ! 236: else ! 237: /* exp(+- tiny) = 1 with inexact flag */ ! 238: {ln2hi+ln2lo; return(one);} ! 239: else if(copysign(one,y)*(n+invln2*t) <zero) ! 240: /* exp(-(big#)) underflows to zero */ ! 241: return(scalb(one,-5000)); ! 242: else ! 243: /* exp(+(big#)) overflows to INF */ ! 244: return(scalb(one, 5000)); ! 245: ! 246: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.