IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
e_hypot.cs
Go to the documentation of this file.
1/*
2 * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26/* __ieee754_hypot(x,y)
27 *
28 * Method :
29 * If (assume round-to-nearest) z=x*x+y*y
30 * has error less than sqrt(2)/2 ulp, than
31 * sqrt(z) has error less than 1 ulp (exercise).
32 *
33 * So, compute sqrt(x*x+y*y) with some care as
34 * follows to get the error below 1 ulp:
35 *
36 * Assume x>y>0;
37 * (if possible, set rounding to round-to-nearest)
38 * 1. if x > 2y use
39 * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
40 * where x1 = x with lower 32 bits cleared, x2 = x-x1; else
41 * 2. if x <= 2y use
42 * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y))
43 * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1,
44 * y1= y with lower 32 bits chopped, y2 = y-y1.
45 *
46 * NOTE: scaling may be necessary if some argument is too
47 * large or too tiny
48 *
49 * Special cases:
50 * hypot(x,y) is INF if x or y is +INF or -INF; else
51 * hypot(x,y) is NAN if x or y is NAN.
52 *
53 * Accuracy:
54 * hypot(x,y) returns sqrt(x^2+y^2) with error less
55 * than 1 ulps (units in the last place)
56 */
57
59{
60 static partial class fdlibm
61 {
62 internal static double __ieee754_hypot(double x, double y)
63 {
64 double a = x, b = y, t1, t2, y1, y2, w;
65 int j, k, ha, hb;
66
67 ha = __HI(x) & 0x7fffffff; /* high word of x */
68 hb = __HI(y) & 0x7fffffff; /* high word of y */
69 if (hb > ha) { a = y; b = x; j = ha; ha = hb; hb = j; } else { a = x; b = y; }
70 a = __HI(a, ha); /* a <- |a| */
71 b = __HI(b, hb); /* b <- |b| */
72 if ((ha - hb) > 0x3c00000) { return a + b; } /* x/y > 2**60 */
73 k = 0;
74 if (ha > 0x5f300000)
75 { /* a>2**500 */
76 if (ha >= 0x7ff00000)
77 { /* Inf or NaN */
78 w = a + b; /* for sNaN */
79 if (((ha & 0xfffff) | __LO(a)) == 0) w = a;
80 if (((hb ^ 0x7ff00000) | __LO(b)) == 0) w = b;
81 return w;
82 }
83 /* scale a and b by 2**-600 */
84 ha -= 0x25800000; hb -= 0x25800000; k += 600;
85 a = __HI(a, ha);
86 b = __HI(b, hb);
87 }
88 if (hb < 0x20b00000)
89 { /* b < 2**-500 */
90 if (hb <= 0x000fffff)
91 { /* subnormal b or 0 */
92 if ((hb | (__LO(b))) == 0) return a;
93 t1 = 0;
94 t1 = __HI(t1, 0x7fd00000); /* t1=2^1022 */
95 b *= t1;
96 a *= t1;
97 k -= 1022;
98 }
99 else
100 { /* scale a and b by 2^600 */
101 ha += 0x25800000; /* a *= 2^600 */
102 hb += 0x25800000; /* b *= 2^600 */
103 k -= 600;
104 a = __HI(a, ha);
105 b = __HI(b, hb);
106 }
107 }
108 /* medium size a and b */
109 w = a - b;
110 if (w > b)
111 {
112 t1 = 0;
113 t1 = __HI(t1, ha);
114 t2 = a - t1;
115 w = sqrt(t1 * t1 - (b * (-b) - t2 * (a + t1)));
116 }
117 else
118 {
119 a = a + a;
120 y1 = 0;
121 y1 = __HI(y1, hb);
122 y2 = b - y1;
123 t1 = 0;
124 t1 = __HI(t1, ha + 0x00100000);
125 t2 = a - t1;
126 w = sqrt(t1 * y1 - (w * (-w) - (t1 * y2 + t2 * b)));
127 }
128 if (k != 0)
129 {
130 t1 = 1.0;
131 t1 = __HI(t1, __HI(t1) + (k << 20));
132 return t1 * w;
133 }
134 else return w;
135 }
136 }
137}