|
|
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[] = "@(#)cabs.c 5.5 (Berkeley) 6/1/90";
27: #endif /* not lint */
28:
29: /* HYPOT(X,Y)
30: * RETURN THE SQUARE ROOT OF X^2 + Y^2 WHERE Z=X+iY
31: * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
32: * CODED IN C BY K.C. NG, 11/28/84;
33: * REVISED BY K.C. NG, 7/12/85.
34: *
35: * Required system supported functions :
36: * copysign(x,y)
37: * finite(x)
38: * scalb(x,N)
39: * sqrt(x)
40: *
41: * Method :
42: * 1. replace x by |x| and y by |y|, and swap x and
43: * y if y > x (hence x is never smaller than y).
44: * 2. Hypot(x,y) is computed by:
45: * Case I, x/y > 2
46: *
47: * y
48: * hypot = x + -----------------------------
49: * 2
50: * sqrt ( 1 + [x/y] ) + x/y
51: *
52: * Case II, x/y <= 2
53: * y
54: * hypot = x + --------------------------------------------------
55: * 2
56: * [x/y] - 2
57: * (sqrt(2)+1) + (x-y)/y + -----------------------------
58: * 2
59: * sqrt ( 1 + [x/y] ) + sqrt(2)
60: *
61: *
62: *
63: * Special cases:
64: * hypot(x,y) is INF if x or y is +INF or -INF; else
65: * hypot(x,y) is NAN if x or y is NAN.
66: *
67: * Accuracy:
68: * hypot(x,y) returns the sqrt(x^2+y^2) with error less than 1 ulps (units
69: * in the last place). See Kahan's "Interval Arithmetic Options in the
70: * Proposed IEEE Floating Point Arithmetic Standard", Interval Mathematics
71: * 1980, Edited by Karl L.E. Nickel, pp 99-128. (A faster but less accurate
72: * code follows in comments.) In a test run with 500,000 random arguments
73: * on a VAX, the maximum observed error was .959 ulps.
74: *
75: * Constants:
76: * The hexadecimal values are the intended ones for the following constants.
77: * The decimal values may be used, provided that the compiler will convert
78: * from decimal to binary accurately enough to produce the hexadecimal values
79: * shown.
80: */
81: #include "mathimpl.h"
82:
83: vc(r2p1hi, 2.4142135623730950345E0 ,8279,411a,ef32,99fc, 2, .9A827999FCEF32)
84: vc(r2p1lo, 1.4349369327986523769E-17 ,597d,2484,754b,89b3, -55, .84597D89B3754B)
85: vc(sqrt2, 1.4142135623730950622E0 ,04f3,40b5,de65,33f9, 1, .B504F333F9DE65)
86:
87: ic(r2p1hi, 2.4142135623730949234E0 , 1, 1.3504F333F9DE6)
88: ic(r2p1lo, 1.2537167179050217666E-16 , -53, 1.21165F626CDD5)
89: ic(sqrt2, 1.4142135623730951455E0 , 0, 1.6A09E667F3BCD)
90:
91: #ifdef vccast
92: #define r2p1hi vccast(r2p1hi)
93: #define r2p1lo vccast(r2p1lo)
94: #define sqrt2 vccast(sqrt2)
95: #endif
96:
97: double
98: hypot(x,y)
99: double x, y;
100: {
101: static const double zero=0, one=1,
102: small=1.0E-18; /* fl(1+small)==1 */
103: static const ibig=30; /* fl(1+2**(2*ibig))==1 */
104: double t,r;
105: int exp;
106:
107: if(finite(x))
108: if(finite(y))
109: {
110: x=copysign(x,one);
111: y=copysign(y,one);
112: if(y > x)
113: { t=x; x=y; y=t; }
114: if(x == zero) return(zero);
115: if(y == zero) return(x);
116: exp= logb(x);
117: if(exp-(int)logb(y) > ibig )
118: /* raise inexact flag and return |x| */
119: { one+small; return(x); }
120:
121: /* start computing sqrt(x^2 + y^2) */
122: r=x-y;
123: if(r>y) { /* x/y > 2 */
124: r=x/y;
125: r=r+sqrt(one+r*r); }
126: else { /* 1 <= x/y <= 2 */
127: r/=y; t=r*(r+2.0);
128: r+=t/(sqrt2+sqrt(2.0+t));
129: r+=r2p1lo; r+=r2p1hi; }
130:
131: r=y/r;
132: return(x+r);
133:
134: }
135:
136: else if(y==y) /* y is +-INF */
137: return(copysign(y,one));
138: else
139: return(y); /* y is NaN and x is finite */
140:
141: else if(x==x) /* x is +-INF */
142: return (copysign(x,one));
143: else if(finite(y))
144: return(x); /* x is NaN, y is finite */
145: #if !defined(vax)&&!defined(tahoe)
146: else if(y!=y) return(y); /* x and y is NaN */
147: #endif /* !defined(vax)&&!defined(tahoe) */
148: else return(copysign(y,one)); /* y is INF */
149: }
150:
151: /* CABS(Z)
152: * RETURN THE ABSOLUTE VALUE OF THE COMPLEX NUMBER Z = X + iY
153: * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
154: * CODED IN C BY K.C. NG, 11/28/84.
155: * REVISED BY K.C. NG, 7/12/85.
156: *
157: * Required kernel function :
158: * hypot(x,y)
159: *
160: * Method :
161: * cabs(z) = hypot(x,y) .
162: */
163:
164: double
165: cabs(z)
166: struct { double x, y;} z;
167: {
168: return hypot(z.x,z.y);
169: }
170:
171: double
172: z_abs(z)
173: struct { double x,y;} *z;
174: {
175: return hypot(z->x,z->y);
176: }
177:
178: /* A faster but less accurate version of cabs(x,y) */
179: #if 0
180: double hypot(x,y)
181: double x, y;
182: {
183: static const double zero=0, one=1;
184: small=1.0E-18; /* fl(1+small)==1 */
185: static const ibig=30; /* fl(1+2**(2*ibig))==1 */
186: double temp;
187: int exp;
188:
189: if(finite(x))
190: if(finite(y))
191: {
192: x=copysign(x,one);
193: y=copysign(y,one);
194: if(y > x)
195: { temp=x; x=y; y=temp; }
196: if(x == zero) return(zero);
197: if(y == zero) return(x);
198: exp= logb(x);
199: x=scalb(x,-exp);
200: if(exp-(int)logb(y) > ibig )
201: /* raise inexact flag and return |x| */
202: { one+small; return(scalb(x,exp)); }
203: else y=scalb(y,-exp);
204: return(scalb(sqrt(x*x+y*y),exp));
205: }
206:
207: else if(y==y) /* y is +-INF */
208: return(copysign(y,one));
209: else
210: return(y); /* y is NaN and x is finite */
211:
212: else if(x==x) /* x is +-INF */
213: return (copysign(x,one));
214: else if(finite(y))
215: return(x); /* x is NaN, y is finite */
216: else if(y!=y) return(y); /* x and y is NaN */
217: else return(copysign(y,one)); /* y is INF */
218: }
219: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.