|
|
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[] = "@(#)log.c 5.3 (Berkeley) 6/30/88"; ! 25: #endif /* not lint */ ! 26: ! 27: /* LOG(X) ! 28: * RETURN THE LOGARITHM OF x ! 29: * DOUBLE PRECISION (VAX D FORMAT 56 bits or IEEE DOUBLE 53 BITS) ! 30: * CODED IN C BY K.C. NG, 1/19/85; ! 31: * REVISED BY K.C. NG on 2/7/85, 3/7/85, 3/24/85, 4/16/85. ! 32: * ! 33: * Required system supported functions: ! 34: * scalb(x,n) ! 35: * copysign(x,y) ! 36: * logb(x) ! 37: * finite(x) ! 38: * ! 39: * Required kernel function: ! 40: * log__L(z) ! 41: * ! 42: * Method : ! 43: * 1. Argument Reduction: find k and f such that ! 44: * x = 2^k * (1+f), ! 45: * where sqrt(2)/2 < 1+f < sqrt(2) . ! 46: * ! 47: * 2. Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) ! 48: * = 2s + 2/3 s**3 + 2/5 s**5 + ....., ! 49: * log(1+f) is computed by ! 50: * ! 51: * log(1+f) = 2s + s*log__L(s*s) ! 52: * where ! 53: * log__L(z) = z*(L1 + z*(L2 + z*(... (L6 + z*L7)...))) ! 54: * ! 55: * See log__L() for the values of the coefficients. ! 56: * ! 57: * 3. Finally, log(x) = k*ln2 + log(1+f). (Here n*ln2 will be stored ! 58: * in two floating point number: n*ln2hi + n*ln2lo, n*ln2hi is exact ! 59: * since the last 20 bits of ln2hi is 0.) ! 60: * ! 61: * Special cases: ! 62: * log(x) is NaN with signal if x < 0 (including -INF) ; ! 63: * log(+INF) is +INF; log(0) is -INF with signal; ! 64: * log(NaN) is that NaN with no signal. ! 65: * ! 66: * Accuracy: ! 67: * log(x) returns the exact log(x) nearly rounded. In a test run with ! 68: * 1,536,000 random arguments on a VAX, the maximum observed error was ! 69: * .826 ulps (units in the last place). ! 70: * ! 71: * Constants: ! 72: * The hexadecimal values are the intended ones for the following constants. ! 73: * The decimal values may be used, provided that the compiler will convert ! 74: * from decimal to binary accurately enough to produce the hexadecimal values ! 75: * shown. ! 76: */ ! 77: ! 78: #if defined(vax)||defined(tahoe) /* VAX D format */ ! 79: #include <errno.h> ! 80: #ifdef vax ! 81: #define _0x(A,B) 0x/**/A/**/B ! 82: #else /* vax */ ! 83: #define _0x(A,B) 0x/**/B/**/A ! 84: #endif /* vax */ ! 85: /* static double */ ! 86: /* ln2hi = 6.9314718055829871446E-1 , Hex 2^ 0 * .B17217F7D00000 */ ! 87: /* ln2lo = 1.6465949582897081279E-12 , Hex 2^-39 * .E7BCD5E4F1D9CC */ ! 88: /* sqrt2 = 1.4142135623730950622E0 ; Hex 2^ 1 * .B504F333F9DE65 */ ! 89: static long ln2hix[] = { _0x(7217,4031), _0x(0000,f7d0)}; ! 90: static long ln2lox[] = { _0x(bcd5,2ce7), _0x(d9cc,e4f1)}; ! 91: static long sqrt2x[] = { _0x(04f3,40b5), _0x(de65,33f9)}; ! 92: #define ln2hi (*(double*)ln2hix) ! 93: #define ln2lo (*(double*)ln2lox) ! 94: #define sqrt2 (*(double*)sqrt2x) ! 95: #else /* defined(vax)||defined(tahoe) */ ! 96: static double ! 97: ln2hi = 6.9314718036912381649E-1 , /*Hex 2^ -1 * 1.62E42FEE00000 */ ! 98: ln2lo = 1.9082149292705877000E-10 , /*Hex 2^-33 * 1.A39EF35793C76 */ ! 99: sqrt2 = 1.4142135623730951455E0 ; /*Hex 2^ 0 * 1.6A09E667F3BCD */ ! 100: #endif /* defined(vax)||defined(tahoe) */ ! 101: ! 102: double log(x) ! 103: double x; ! 104: { ! 105: static double zero=0.0, negone= -1.0, half=1.0/2.0; ! 106: double logb(),scalb(),copysign(),log__L(),s,z,t; ! 107: int k,n,finite(); ! 108: ! 109: #if !defined(vax)&&!defined(tahoe) ! 110: if(x!=x) return(x); /* x is NaN */ ! 111: #endif /* !defined(vax)&&!defined(tahoe) */ ! 112: if(finite(x)) { ! 113: if( x > zero ) { ! 114: ! 115: /* argument reduction */ ! 116: k=logb(x); x=scalb(x,-k); ! 117: if(k == -1022) /* subnormal no. */ ! 118: {n=logb(x); x=scalb(x,-n); k+=n;} ! 119: if(x >= sqrt2 ) {k += 1; x *= half;} ! 120: x += negone ; ! 121: ! 122: /* compute log(1+x) */ ! 123: s=x/(2+x); t=x*x*half; ! 124: z=k*ln2lo+s*(t+log__L(s*s)); ! 125: x += (z - t) ; ! 126: ! 127: return(k*ln2hi+x); ! 128: } ! 129: /* end of if (x > zero) */ ! 130: ! 131: else { ! 132: #if defined(vax)||defined(tahoe) ! 133: extern double infnan(); ! 134: if ( x == zero ) ! 135: return (infnan(-ERANGE)); /* -INF */ ! 136: else ! 137: return (infnan(EDOM)); /* NaN */ ! 138: #else /* defined(vax)||defined(tahoe) */ ! 139: /* zero argument, return -INF with signal */ ! 140: if ( x == zero ) ! 141: return( negone/zero ); ! 142: ! 143: /* negative argument, return NaN with signal */ ! 144: else ! 145: return ( zero / zero ); ! 146: #endif /* defined(vax)||defined(tahoe) */ ! 147: } ! 148: } ! 149: /* end of if (finite(x)) */ ! 150: /* NOTREACHED if defined(vax)||defined(tahoe) */ ! 151: ! 152: /* log(-INF) is NaN with signal */ ! 153: else if (x<0) ! 154: return(zero/zero); ! 155: ! 156: /* log(+INF) is +INF */ ! 157: else return(x); ! 158: ! 159: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.