|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 Regents of the University of California. ! 3: * ! 4: * Use and reproduction of this software are granted in accordance with ! 5: * the terms and conditions specified in the Berkeley Software License ! 6: * Agreement (in particular, this entails acknowledgement of the programs' ! 7: * source, and inclusion of this notice) with the additional understanding ! 8: * that all recipients should regard themselves as participants in an ! 9: * ongoing research project and hence should feel obligated to report ! 10: * their experiences (good or bad) with these elementary function codes, ! 11: * using "sendbug 4bsd-bugs@BERKELEY", to the authors. ! 12: */ ! 13: ! 14: #ifndef lint ! 15: static char sccsid[] = "@(#)cabs.c 1.2 (Berkeley) 8/21/85"; ! 16: #endif not lint ! 17: ! 18: /* CABS(Z) ! 19: * RETURN THE ABSOLUTE VALUE OF THE COMPLEX NUMBER Z = X + iY ! 20: * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) ! 21: * CODED IN C BY K.C. NG, 11/28/84. ! 22: * REVISED BY K.C. NG, 7/12/85. ! 23: * ! 24: * Required kernel function : ! 25: * hypot(x,y) ! 26: * ! 27: * Method : ! 28: * cabs(z) = hypot(x,y) . ! 29: */ ! 30: ! 31: double cabs(z) ! 32: struct { double x, y;} z; ! 33: { ! 34: double hypot(); ! 35: return(hypot(z.x,z.y)); ! 36: } ! 37: ! 38: ! 39: /* HYPOT(X,Y) ! 40: * RETURN THE SQUARE ROOT OF X^2 + Y^2 WHERE Z=X+iY ! 41: * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) ! 42: * CODED IN C BY K.C. NG, 11/28/84; ! 43: * REVISED BY K.C. NG, 7/12/85. ! 44: * ! 45: * Required system supported functions : ! 46: * copysign(x,y) ! 47: * finite(x) ! 48: * scalb(x,N) ! 49: * sqrt(x) ! 50: * ! 51: * Method : ! 52: * 1. replace x by |x| and y by |y|, and swap x and ! 53: * y if y > x (hence x is never smaller than y). ! 54: * 2. Hypot(x,y) is computed by: ! 55: * Case I, x/y > 2 ! 56: * ! 57: * y ! 58: * hypot = x + ----------------------------- ! 59: * 2 ! 60: * sqrt ( 1 + [x/y] ) + x/y ! 61: * ! 62: * Case II, x/y <= 2 ! 63: * y ! 64: * hypot = x + -------------------------------------------------- ! 65: * 2 ! 66: * [x/y] - 2 ! 67: * (sqrt(2)+1) + (x-y)/y + ----------------------------- ! 68: * 2 ! 69: * sqrt ( 1 + [x/y] ) + sqrt(2) ! 70: * ! 71: * ! 72: * ! 73: * Special cases: ! 74: * hypot(x,y) is INF if x or y is +INF or -INF; else ! 75: * hypot(x,y) is NAN if x or y is NAN. ! 76: * ! 77: * Accuracy: ! 78: * hypot(x,y) returns the sqrt(x^2+y^2) with error less than 1 ulps (units ! 79: * in the last place). See Kahan's "Interval Arithmetic Options in the ! 80: * Proposed IEEE Floating Point Arithmetic Standard", Interval Mathematics ! 81: * 1980, Edited by Karl L.E. Nickel, pp 99-128. (A faster but less accurate ! 82: * code follows in comments.) In a test run with 500,000 random arguments ! 83: * on a VAX, the maximum observed error was .959 ulps. ! 84: * ! 85: * Constants: ! 86: * The hexadecimal values are the intended ones for the following constants. ! 87: * The decimal values may be used, provided that the compiler will convert ! 88: * from decimal to binary accurately enough to produce the hexadecimal values ! 89: * shown. ! 90: */ ! 91: ! 92: #ifdef VAX /* VAX D format */ ! 93: /* static double */ ! 94: /* r2p1hi = 2.4142135623730950345E0 , Hex 2^ 2 * .9A827999FCEF32 */ ! 95: /* r2p1lo = 1.4349369327986523769E-17 , Hex 2^-55 * .84597D89B3754B */ ! 96: /* sqrt2 = 1.4142135623730950622E0 ; Hex 2^ 1 * .B504F333F9DE65 */ ! 97: static long r2p1hix[] = { 0x8279411a, 0xef3299fc}; ! 98: static long r2p1lox[] = { 0x597d2484, 0x754b89b3}; ! 99: static long sqrt2x[] = { 0x04f340b5, 0xde6533f9}; ! 100: #define r2p1hi (*(double*)r2p1hix) ! 101: #define r2p1lo (*(double*)r2p1lox) ! 102: #define sqrt2 (*(double*)sqrt2x) ! 103: #else /* IEEE double format */ ! 104: static double ! 105: r2p1hi = 2.4142135623730949234E0 , /*Hex 2^1 * 1.3504F333F9DE6 */ ! 106: r2p1lo = 1.2537167179050217666E-16 , /*Hex 2^-53 * 1.21165F626CDD5 */ ! 107: sqrt2 = 1.4142135623730951455E0 ; /*Hex 2^ 0 * 1.6A09E667F3BCD */ ! 108: #endif ! 109: ! 110: double hypot(x,y) ! 111: double x, y; ! 112: { ! 113: static double zero=0, one=1, ! 114: small=1.0E-18; /* fl(1+small)==1 */ ! 115: static ibig=30; /* fl(1+2**(2*ibig))==1 */ ! 116: double copysign(),scalb(),logb(),sqrt(),t,r; ! 117: int finite(), exp; ! 118: ! 119: if(finite(x)) ! 120: if(finite(y)) ! 121: { ! 122: x=copysign(x,one); ! 123: y=copysign(y,one); ! 124: if(y > x) ! 125: { t=x; x=y; y=t; } ! 126: if(x == zero) return(zero); ! 127: if(y == zero) return(x); ! 128: exp= logb(x); ! 129: if(exp-(int)logb(y) > ibig ) ! 130: /* raise inexact flag and return |x| */ ! 131: { one+small; return(x); } ! 132: ! 133: /* start computing sqrt(x^2 + y^2) */ ! 134: r=x-y; ! 135: if(r>y) { /* x/y > 2 */ ! 136: r=x/y; ! 137: r=r+sqrt(one+r*r); } ! 138: else { /* 1 <= x/y <= 2 */ ! 139: r/=y; t=r*(r+2.0); ! 140: r+=t/(sqrt2+sqrt(2.0+t)); ! 141: r+=r2p1lo; r+=r2p1hi; } ! 142: ! 143: r=y/r; ! 144: return(x+r); ! 145: ! 146: } ! 147: ! 148: else if(y==y) /* y is +-INF */ ! 149: return(copysign(y,one)); ! 150: else ! 151: return(y); /* y is NaN and x is finite */ ! 152: ! 153: else if(x==x) /* x is +-INF */ ! 154: return (copysign(x,one)); ! 155: else if(finite(y)) ! 156: return(x); /* x is NaN, y is finite */ ! 157: else if(y!=y) return(y); /* x and y is NaN */ ! 158: else return(copysign(y,one)); /* y is INF */ ! 159: } ! 160: ! 161: /* A faster but less accurate version of cabs(x,y) */ ! 162: #if 0 ! 163: double hypot(x,y) ! 164: double x, y; ! 165: { ! 166: static double zero=0, one=1; ! 167: small=1.0E-18; /* fl(1+small)==1 */ ! 168: static ibig=30; /* fl(1+2**(2*ibig))==1 */ ! 169: double copysign(),scalb(),logb(),sqrt(),temp; ! 170: int finite(), exp; ! 171: ! 172: if(finite(x)) ! 173: if(finite(y)) ! 174: { ! 175: x=copysign(x,one); ! 176: y=copysign(y,one); ! 177: if(y > x) ! 178: { temp=x; x=y; y=temp; } ! 179: if(x == zero) return(zero); ! 180: if(y == zero) return(x); ! 181: exp= logb(x); ! 182: x=scalb(x,-exp); ! 183: if(exp-(int)logb(y) > ibig ) ! 184: /* raise inexact flag and return |x| */ ! 185: { one+small; return(scalb(x,exp)); } ! 186: else y=scalb(y,-exp); ! 187: return(scalb(sqrt(x*x+y*y),exp)); ! 188: } ! 189: ! 190: else if(y==y) /* y is +-INF */ ! 191: return(copysign(y,one)); ! 192: else ! 193: return(y); /* y is NaN and x is finite */ ! 194: ! 195: else if(x==x) /* x is +-INF */ ! 196: return (copysign(x,one)); ! 197: else if(finite(y)) ! 198: return(x); /* x is NaN, y is finite */ ! 199: else if(y!=y) return(y); /* x and y is NaN */ ! 200: else return(copysign(y,one)); /* y is INF */ ! 201: } ! 202: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.