Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(183)

Side by Side Diff: src/base/ieee754.cc

Issue 2065473002: [ieee754] Import ANSIfied msun log from FreeBSD. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Moar MSVC fixes. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // The following is adapted from fdlibm (http://www.netlib.org/fdlibm). 1 // The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
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 // The original source code covered by the above license above has been 12 // The original source code covered by the above license above has been
13 // modified significantly by Google Inc. 13 // modified significantly by Google Inc.
14 // Copyright 2016 the V8 project authors. All rights reserved. 14 // Copyright 2016 the V8 project authors. All rights reserved.
15 15
16 #include "src/base/ieee754.h" 16 #include "src/base/ieee754.h"
17 17
18 #include <limits> 18 #include <limits>
19 19
20 #include "src/base/build_config.h" 20 #include "src/base/build_config.h"
21 #include "src/base/macros.h" 21 #include "src/base/macros.h"
22 22
23 namespace v8 { 23 namespace v8 {
24 namespace base { 24 namespace base {
25 namespace ieee754 { 25 namespace ieee754 {
26 26
27 namespace { 27 namespace {
28 28
29 union Float64 { 29 /* Fix-up typedefs so we can use the FreeBSD msun code mostly unmodified. */
30 double v; 30
31 uint64_t w; 31 #if V8_OS_WIN
32
33 typedef uint32_t u_int32_t;
34 typedef uint64_t u_int64_t;
35
36 #endif
37
38 /* Disable "potential divide by 0" warning in Visual Studio compiler. */
39
40 #if V8_CC_MSVC
41
42 #pragma warning(disable : 4723)
43
44 #endif
45
46 /*
47 * The original fdlibm code used statements like:
48 * n0 = ((*(int*)&one)>>29)^1; * index of high word *
49 * ix0 = *(n0+(int*)&x); * high word of x *
50 * ix1 = *((1-n0)+(int*)&x); * low word of x *
51 * to dig two 32 bit words out of the 64 bit IEEE floating point
52 * value. That is non-ANSI, and, moreover, the gcc instruction
53 * scheduler gets it wrong. We instead use the following macros.
54 * Unlike the original code, we determine the endianness at compile
55 * time, not at run time; I don't see much benefit to selecting
56 * endianness at run time.
57 */
58
59 /*
60 * A union which permits us to convert between a double and two 32 bit
61 * ints.
62 */
63
64 #if V8_TARGET_LITTLE_ENDIAN
65
66 typedef union {
67 double value;
32 struct { 68 struct {
33 #if V8_TARGET_LITTLE_ENDIAN 69 u_int32_t lsw;
34 uint32_t lw; 70 u_int32_t msw;
35 uint32_t hw; 71 } parts;
72 struct {
73 u_int64_t w;
74 } xparts;
75 } ieee_double_shape_type;
76
36 #else 77 #else
37 uint32_t hw; 78
38 uint32_t lw; 79 typedef union {
80 double value;
81 struct {
82 u_int32_t msw;
83 u_int32_t lsw;
84 } parts;
85 struct {
86 u_int64_t w;
87 } xparts;
88 } ieee_double_shape_type;
89
39 #endif 90 #endif
40 } words;
41 };
42 91
43 // Extract the less significant 32-bit word from a double. 92 /* Get two 32 bit ints from a double. */
44 V8_INLINE uint32_t extractLowWord32(double v) {
45 Float64 f;
46 f.v = v;
47 return f.words.lw;
48 }
49 93
50 // Extract the most significant 32-bit word from a double. 94 #define EXTRACT_WORDS(ix0, ix1, d) \
51 V8_INLINE uint32_t extractHighWord32(double v) { 95 do { \
52 Float64 f; 96 ieee_double_shape_type ew_u; \
53 f.v = v; 97 ew_u.value = (d); \
54 return f.words.hw; 98 (ix0) = ew_u.parts.msw; \
55 } 99 (ix1) = ew_u.parts.lsw; \
100 } while (0)
56 101
57 // Insert the most significant 32-bit word into a double. 102 /* Get a 64-bit int from a double. */
58 V8_INLINE double insertHighWord32(double v, uint32_t hw) { 103 #define EXTRACT_WORD64(ix, d) \
59 Float64 f; 104 do { \
60 f.v = v; 105 ieee_double_shape_type ew_u; \
61 f.words.hw = hw; 106 ew_u.value = (d); \
62 return f.v; 107 (ix) = ew_u.xparts.w; \
63 } 108 } while (0)
64 109
65 double const kLn2Hi = 6.93147180369123816490e-01; // 3fe62e42 fee00000 110 /* Get the more significant 32 bit int from a double. */
66 double const kLn2Lo = 1.90821492927058770002e-10; // 3dea39ef 35793c76 111
67 double const kTwo54 = 1.80143985094819840000e+16; // 43500000 00000000 112 #define GET_HIGH_WORD(i, d) \
68 double const kLg1 = 6.666666666666735130e-01; // 3FE55555 55555593 113 do { \
69 double const kLg2 = 3.999999999940941908e-01; // 3FD99999 9997FA04 114 ieee_double_shape_type gh_u; \
70 double const kLg3 = 2.857142874366239149e-01; // 3FD24924 94229359 115 gh_u.value = (d); \
71 double const kLg4 = 2.222219843214978396e-01; // 3FCC71C5 1D8E78AF 116 (i) = gh_u.parts.msw; \
72 double const kLg5 = 1.818357216161805012e-01; // 3FC74664 96CB03DE 117 } while (0)
73 double const kLg6 = 1.531383769920937332e-01; // 3FC39A09 D078C69F 118
74 double const kLg7 = 1.479819860511658591e-01; // 3FC2F112 DF3E5244 119 /* Get the less significant 32 bit int from a double. */
120
121 #define GET_LOW_WORD(i, d) \
122 do { \
123 ieee_double_shape_type gl_u; \
124 gl_u.value = (d); \
125 (i) = gl_u.parts.lsw; \
126 } while (0)
127
128 /* Set a double from two 32 bit ints. */
129
130 #define INSERT_WORDS(d, ix0, ix1) \
131 do { \
132 ieee_double_shape_type iw_u; \
133 iw_u.parts.msw = (ix0); \
134 iw_u.parts.lsw = (ix1); \
135 (d) = iw_u.value; \
136 } while (0)
137
138 /* Set a double from a 64-bit int. */
139 #define INSERT_WORD64(d, ix) \
140 do { \
141 ieee_double_shape_type iw_u; \
142 iw_u.xparts.w = (ix); \
143 (d) = iw_u.value; \
144 } while (0)
145
146 /* Set the more significant 32 bits of a double from an int. */
147
148 #define SET_HIGH_WORD(d, v) \
149 do { \
150 ieee_double_shape_type sh_u; \
151 sh_u.value = (d); \
152 sh_u.parts.msw = (v); \
153 (d) = sh_u.value; \
154 } while (0)
155
156 /* Set the less significant 32 bits of a double from an int. */
157
158 #define SET_LOW_WORD(d, v) \
159 do { \
160 ieee_double_shape_type sl_u; \
161 sl_u.value = (d); \
162 sl_u.parts.lsw = (v); \
163 (d) = sl_u.value; \
164 } while (0)
75 165
76 } // namespace 166 } // namespace
77 167
78 /* log(x) 168 /* log(x)
79 * Return the logrithm of x 169 * Return the logrithm of x
80 * 170 *
81 * Method : 171 * Method :
82 * 1. Argument Reduction: find k and f such that 172 * 1. Argument Reduction: find k and f such that
83 * x = 2^k * (1+f), 173 * x = 2^k * (1+f),
84 * where sqrt(2)/2 < 1+f < sqrt(2) . 174 * where sqrt(2)/2 < 1+f < sqrt(2) .
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 * according to an error analysis, the error is always less than 209 * according to an error analysis, the error is always less than
120 * 1 ulp (unit in the last place). 210 * 1 ulp (unit in the last place).
121 * 211 *
122 * Constants: 212 * Constants:
123 * The hexadecimal values are the intended ones for the following 213 * The hexadecimal values are the intended ones for the following
124 * constants. The decimal values may be used, provided that the 214 * constants. The decimal values may be used, provided that the
125 * compiler will convert from decimal to binary accurately enough 215 * compiler will convert from decimal to binary accurately enough
126 * to produce the hexadecimal values shown. 216 * to produce the hexadecimal values shown.
127 */ 217 */
128 double log(double x) { 218 double log(double x) {
129 double hfsq, f, s, z, r, w, t1, t2, dk; 219 static const double /* -- */
130 int32_t k = 0, i, j; 220 ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
131 int32_t hx = extractHighWord32(x); 221 ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
132 uint32_t lx = extractLowWord32(x); 222 two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
223 Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
224 Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
225 Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
226 Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
227 Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
228 Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
229 Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
133 230
231 static const double zero = 0.0;
232 static volatile double vzero = 0.0;
233
234 double hfsq, f, s, z, R, w, t1, t2, dk;
235 int32_t k, hx, i, j;
236 u_int32_t lx;
237
238 EXTRACT_WORDS(hx, lx, x);
239
240 k = 0;
134 if (hx < 0x00100000) { /* x < 2**-1022 */ 241 if (hx < 0x00100000) { /* x < 2**-1022 */
135 if (((hx & 0x7fffffff) | lx) == 0) { 242 if (((hx & 0x7fffffff) | lx) == 0)
136 return -std::numeric_limits<double>::infinity(); 243 return -two54 / vzero; /* log(+-0)=-inf */
137 } 244 if (hx < 0) return (x - x) / zero; /* log(-#) = NaN */
138 if (hx < 0) {
139 return std::numeric_limits<double>::quiet_NaN();
140 }
141 k -= 54; 245 k -= 54;
142 x *= kTwo54; /* subnormal number, scale up x */ 246 x *= two54; /* subnormal number, scale up x */
143 hx = extractHighWord32(x); 247 GET_HIGH_WORD(hx, x);
144 } 248 }
145 if (hx >= 0x7ff00000) return x + x; 249 if (hx >= 0x7ff00000) return x + x;
146 k += (hx >> 20) - 1023; 250 k += (hx >> 20) - 1023;
147 hx &= 0x000fffff; 251 hx &= 0x000fffff;
148 i = (hx + 0x95f64) & 0x100000; 252 i = (hx + 0x95f64) & 0x100000;
149 x = insertHighWord32(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */ 253 SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */
150 k += (i >> 20); 254 k += (i >> 20);
151 f = x - 1.0; 255 f = x - 1.0;
152 if ((0x000fffff & (2 + hx)) < 3) { /* -2**-20 <= f < 2**-20 */ 256 if ((0x000fffff & (2 + hx)) < 3) { /* -2**-20 <= f < 2**-20 */
153 if (f == 0.0) { 257 if (f == zero) {
154 if (k == 0) { 258 if (k == 0) {
155 return 0.0; 259 return zero;
156 } else { 260 } else {
157 dk = static_cast<double>(k); 261 dk = static_cast<double>(k);
158 return dk * kLn2Hi + dk * kLn2Lo; 262 return dk * ln2_hi + dk * ln2_lo;
159 } 263 }
160 } 264 }
161 r = f * f * (0.5 - 0.33333333333333333 * f); 265 R = f * f * (0.5 - 0.33333333333333333 * f);
162 if (k == 0) { 266 if (k == 0) {
163 return f - r; 267 return f - R;
164 } else { 268 } else {
165 dk = static_cast<double>(k); 269 dk = static_cast<double>(k);
166 return dk * kLn2Hi - ((r - dk * kLn2Lo) - f); 270 return dk * ln2_hi - ((R - dk * ln2_lo) - f);
167 } 271 }
168 } 272 }
169 s = f / (2.0 + f); 273 s = f / (2.0 + f);
170 dk = static_cast<double>(k); 274 dk = static_cast<double>(k);
171 z = s * s; 275 z = s * s;
172 i = hx - 0x6147a; 276 i = hx - 0x6147a;
173 w = z * z; 277 w = z * z;
174 j = 0x6b851 - hx; 278 j = 0x6b851 - hx;
175 t1 = w * (kLg2 + w * (kLg4 + w * kLg6)); 279 t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
176 t2 = z * (kLg1 + w * (kLg3 + w * (kLg5 + w * kLg7))); 280 t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
177 i |= j; 281 i |= j;
178 r = t2 + t1; 282 R = t2 + t1;
179 if (i > 0) { 283 if (i > 0) {
180 hfsq = 0.5 * f * f; 284 hfsq = 0.5 * f * f;
181 if (k == 0) { 285 if (k == 0)
182 return f - (hfsq - s * (hfsq + r)); 286 return f - (hfsq - s * (hfsq + R));
183 } else { 287 else
184 return dk * kLn2Hi - ((hfsq - (s * (hfsq + r) + dk * kLn2Lo)) - f); 288 return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f);
185 }
186 } else { 289 } else {
187 if (k == 0) { 290 if (k == 0)
188 return f - s * (f - r); 291 return f - s * (f - R);
189 } else { 292 else
190 return dk * kLn2Hi - ((s * (f - r) - dk * kLn2Lo) - f); 293 return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f);
191 }
192 } 294 }
193 } 295 }
194 296
195 } // namespace ieee754 297 } // namespace ieee754
196 } // namespace base 298 } // namespace base
197 } // namespace v8 299 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698