OLD | NEW |
1 /* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c */ | 1 /* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c */ |
2 /* | 2 /* |
3 * ==================================================== | 3 * ==================================================== |
4 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. | 4 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
5 * | 5 * |
6 * Developed at SunSoft, a Sun Microsystems, Inc. business. | 6 * Developed at SunSoft, a Sun Microsystems, Inc. business. |
7 * Permission to use, copy, modify, and distribute this | 7 * Permission to use, copy, modify, and distribute this |
8 * software is freely granted, provided that this notice | 8 * software is freely granted, provided that this notice |
9 * is preserved. | 9 * is preserved. |
10 * ==================================================== | 10 * ==================================================== |
11 * | 11 * |
12 * Optimized by Bruce D. Evans. | 12 * Optimized by Bruce D. Evans. |
13 */ | 13 */ |
14 /* __rem_pio2(x,y) | 14 /* __rem_pio2(x,y) |
15 * | 15 * |
16 * return the remainder of x rem pi/2 in y[0]+y[1] | 16 * return the remainder of x rem pi/2 in y[0]+y[1] |
17 * use __rem_pio2_large() for large x | 17 * use __rem_pio2_large() for large x |
18 */ | 18 */ |
19 | 19 |
20 #include "libm.h" | 20 #include "libm.h" |
21 | 21 |
22 #if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 | 22 #if FLT_EVAL_METHOD == 0 || FLT_EVAL_METHOD == 1 |
23 #define EPS DBL_EPSILON | 23 #define EPS DBL_EPSILON |
24 #elif FLT_EVAL_METHOD==2 | 24 #elif FLT_EVAL_METHOD == 2 |
25 #define EPS LDBL_EPSILON | 25 #define EPS LDBL_EPSILON |
26 #endif | 26 #endif |
27 | 27 |
28 /* | 28 /* |
29 * invpio2: 53 bits of 2/pi | 29 * invpio2: 53 bits of 2/pi |
30 * pio2_1: first 33 bit of pi/2 | 30 * pio2_1: first 33 bit of pi/2 |
31 * pio2_1t: pi/2 - pio2_1 | 31 * pio2_1t: pi/2 - pio2_1 |
32 * pio2_2: second 33 bit of pi/2 | 32 * pio2_2: second 33 bit of pi/2 |
33 * pio2_2t: pi/2 - (pio2_1+pio2_2) | 33 * pio2_2t: pi/2 - (pio2_1+pio2_2) |
34 * pio2_3: third 33 bit of pi/2 | 34 * pio2_3: third 33 bit of pi/2 |
35 * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) | 35 * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) |
36 */ | 36 */ |
37 static const double | 37 static const double toint = 1.5 / EPS, |
38 toint = 1.5/EPS, | 38 invpio2 = |
39 invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ | 39 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ |
40 pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ | 40 pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ |
41 pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ | 41 pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ |
42 pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ | 42 pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ |
43 pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ | 43 pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ |
44 pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ | 44 pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ |
45 pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ | 45 pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ |
46 | 46 |
47 /* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ | 47 /* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ |
48 int __rem_pio2(double x, double *y) | 48 int __rem_pio2(double x, double* y) { |
49 { | 49 union { |
50 » union {double f; uint64_t i;} u = {x}; | 50 double f; |
51 » double_t z,w,t,r,fn; | 51 uint64_t i; |
52 » double tx[3],ty[2]; | 52 } u = {x}; |
53 » uint32_t ix; | 53 double_t z, w, t, r, fn; |
54 » int sign, n, ex, ey, i; | 54 double tx[3], ty[2]; |
| 55 uint32_t ix; |
| 56 int sign, n, ex, ey, i; |
55 | 57 |
56 » sign = u.i>>63; | 58 sign = u.i >> 63; |
57 » ix = u.i>>32 & 0x7fffffff; | 59 ix = u.i >> 32 & 0x7fffffff; |
58 » if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */ | 60 if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */ |
59 » » if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */ | 61 if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */ |
60 » » » goto medium; /* cancellation -- use medium case */ | 62 goto medium; /* cancellation -- use medium case */ |
61 » » if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */ | 63 if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */ |
62 » » » if (!sign) { | 64 if (!sign) { |
63 » » » » z = x - pio2_1; /* one round good to 85 bits */ | 65 z = x - pio2_1; /* one round good to 85 bits */ |
64 » » » » y[0] = z - pio2_1t; | 66 y[0] = z - pio2_1t; |
65 » » » » y[1] = (z-y[0]) - pio2_1t; | 67 y[1] = (z - y[0]) - pio2_1t; |
66 » » » » return 1; | 68 return 1; |
67 » » » } else { | 69 } else { |
68 » » » » z = x + pio2_1; | 70 z = x + pio2_1; |
69 » » » » y[0] = z + pio2_1t; | 71 y[0] = z + pio2_1t; |
70 » » » » y[1] = (z-y[0]) + pio2_1t; | 72 y[1] = (z - y[0]) + pio2_1t; |
71 » » » » return -1; | 73 return -1; |
72 » » » } | 74 } |
73 » » } else { | 75 } else { |
74 » » » if (!sign) { | 76 if (!sign) { |
75 » » » » z = x - 2*pio2_1; | 77 z = x - 2 * pio2_1; |
76 » » » » y[0] = z - 2*pio2_1t; | 78 y[0] = z - 2 * pio2_1t; |
77 » » » » y[1] = (z-y[0]) - 2*pio2_1t; | 79 y[1] = (z - y[0]) - 2 * pio2_1t; |
78 » » » » return 2; | 80 return 2; |
79 » » » } else { | 81 } else { |
80 » » » » z = x + 2*pio2_1; | 82 z = x + 2 * pio2_1; |
81 » » » » y[0] = z + 2*pio2_1t; | 83 y[0] = z + 2 * pio2_1t; |
82 » » » » y[1] = (z-y[0]) + 2*pio2_1t; | 84 y[1] = (z - y[0]) + 2 * pio2_1t; |
83 » » » » return -2; | 85 return -2; |
84 » » » } | 86 } |
85 » » } | 87 } |
86 » } | 88 } |
87 » if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */ | 89 if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */ |
88 » » if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */ | 90 if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */ |
89 » » » if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */ | 91 if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */ |
90 » » » » goto medium; | 92 goto medium; |
91 » » » if (!sign) { | 93 if (!sign) { |
92 » » » » z = x - 3*pio2_1; | 94 z = x - 3 * pio2_1; |
93 » » » » y[0] = z - 3*pio2_1t; | 95 y[0] = z - 3 * pio2_1t; |
94 » » » » y[1] = (z-y[0]) - 3*pio2_1t; | 96 y[1] = (z - y[0]) - 3 * pio2_1t; |
95 » » » » return 3; | 97 return 3; |
96 » » » } else { | 98 } else { |
97 » » » » z = x + 3*pio2_1; | 99 z = x + 3 * pio2_1; |
98 » » » » y[0] = z + 3*pio2_1t; | 100 y[0] = z + 3 * pio2_1t; |
99 » » » » y[1] = (z-y[0]) + 3*pio2_1t; | 101 y[1] = (z - y[0]) + 3 * pio2_1t; |
100 » » » » return -3; | 102 return -3; |
101 » » » } | 103 } |
102 » » } else { | 104 } else { |
103 » » » if (ix == 0x401921fb) /* |x| ~= 4pi/2 */ | 105 if (ix == 0x401921fb) /* |x| ~= 4pi/2 */ |
104 » » » » goto medium; | 106 goto medium; |
105 » » » if (!sign) { | 107 if (!sign) { |
106 » » » » z = x - 4*pio2_1; | 108 z = x - 4 * pio2_1; |
107 » » » » y[0] = z - 4*pio2_1t; | 109 y[0] = z - 4 * pio2_1t; |
108 » » » » y[1] = (z-y[0]) - 4*pio2_1t; | 110 y[1] = (z - y[0]) - 4 * pio2_1t; |
109 » » » » return 4; | 111 return 4; |
110 » » » } else { | 112 } else { |
111 » » » » z = x + 4*pio2_1; | 113 z = x + 4 * pio2_1; |
112 » » » » y[0] = z + 4*pio2_1t; | 114 y[0] = z + 4 * pio2_1t; |
113 » » » » y[1] = (z-y[0]) + 4*pio2_1t; | 115 y[1] = (z - y[0]) + 4 * pio2_1t; |
114 » » » » return -4; | 116 return -4; |
115 » » » } | 117 } |
116 » » } | 118 } |
117 » } | 119 } |
118 » if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ | 120 if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ |
119 medium: | 121 medium: |
120 » » /* rint(x/(pi/2)), Assume round-to-nearest. */ | 122 /* rint(x/(pi/2)), Assume round-to-nearest. */ |
121 » » fn = (double_t)x*invpio2 + toint - toint; | 123 fn = (double_t)x * invpio2 + toint - toint; |
122 » » n = (int32_t)fn; | 124 n = (int32_t)fn; |
123 » » r = x - fn*pio2_1; | 125 r = x - fn * pio2_1; |
124 » » w = fn*pio2_1t; /* 1st round, good to 85 bits */ | 126 w = fn * pio2_1t; /* 1st round, good to 85 bits */ |
125 » » y[0] = r - w; | 127 y[0] = r - w; |
126 » » u.f = y[0]; | 128 u.f = y[0]; |
127 » » ey = u.i>>52 & 0x7ff; | 129 ey = u.i >> 52 & 0x7ff; |
128 » » ex = ix>>20; | 130 ex = ix >> 20; |
129 » » if (ex - ey > 16) { /* 2nd round, good to 118 bits */ | 131 if (ex - ey > 16) { /* 2nd round, good to 118 bits */ |
130 » » » t = r; | 132 t = r; |
131 » » » w = fn*pio2_2; | 133 w = fn * pio2_2; |
132 » » » r = t - w; | 134 r = t - w; |
133 » » » w = fn*pio2_2t - ((t-r)-w); | 135 w = fn * pio2_2t - ((t - r) - w); |
134 » » » y[0] = r - w; | 136 y[0] = r - w; |
135 » » » u.f = y[0]; | 137 u.f = y[0]; |
136 » » » ey = u.i>>52 & 0x7ff; | 138 ey = u.i >> 52 & 0x7ff; |
137 » » » if (ex - ey > 49) { /* 3rd round, good to 151 bits, cov
ers all cases */ | 139 if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */ |
138 » » » » t = r; | 140 t = r; |
139 » » » » w = fn*pio2_3; | 141 w = fn * pio2_3; |
140 » » » » r = t - w; | 142 r = t - w; |
141 » » » » w = fn*pio2_3t - ((t-r)-w); | 143 w = fn * pio2_3t - ((t - r) - w); |
142 » » » » y[0] = r - w; | 144 y[0] = r - w; |
143 » » » } | 145 } |
144 » » } | 146 } |
145 » » y[1] = (r - y[0]) - w; | 147 y[1] = (r - y[0]) - w; |
146 » » return n; | 148 return n; |
147 » } | 149 } |
148 » /* | 150 /* |
149 » * all other (large) arguments | 151 * all other (large) arguments |
150 » */ | 152 */ |
151 » if (ix >= 0x7ff00000) { /* x is inf or NaN */ | 153 if (ix >= 0x7ff00000) { /* x is inf or NaN */ |
152 » » y[0] = y[1] = x - x; | 154 y[0] = y[1] = x - x; |
153 » » return 0; | 155 return 0; |
154 » } | 156 } |
155 » /* set z = scalbn(|x|,-ilogb(x)+23) */ | 157 /* set z = scalbn(|x|,-ilogb(x)+23) */ |
156 » u.f = x; | 158 u.f = x; |
157 » u.i &= (uint64_t)-1>>12; | 159 u.i &= (uint64_t)-1 >> 12; |
158 » u.i |= (uint64_t)(0x3ff + 23)<<52; | 160 u.i |= (uint64_t)(0x3ff + 23) << 52; |
159 » z = u.f; | 161 z = u.f; |
160 » for (i=0; i < 2; i++) { | 162 for (i = 0; i < 2; i++) { |
161 » » tx[i] = (double)(int32_t)z; | 163 tx[i] = (double)(int32_t)z; |
162 » » z = (z-tx[i])*0x1p24; | 164 z = (z - tx[i]) * 0x1p24; |
163 » } | 165 } |
164 » tx[i] = z; | 166 tx[i] = z; |
165 » /* skip zero terms, first term is non-zero */ | 167 /* skip zero terms, first term is non-zero */ |
166 » while (tx[i] == 0.0) | 168 while (tx[i] == 0.0) |
167 » » i--; | 169 i--; |
168 » n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1); | 170 n = __rem_pio2_large(tx, ty, (int)(ix >> 20) - (0x3ff + 23), i + 1, 1); |
169 » if (sign) { | 171 if (sign) { |
170 » » y[0] = -ty[0]; | 172 y[0] = -ty[0]; |
171 » » y[1] = -ty[1]; | 173 y[1] = -ty[1]; |
172 » » return -n; | 174 return -n; |
173 » } | 175 } |
174 » y[0] = ty[0]; | 176 y[0] = ty[0]; |
175 » y[1] = ty[1]; | 177 y[1] = ty[1]; |
176 » return n; | 178 return n; |
177 } | 179 } |
OLD | NEW |