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