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

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

Issue 2060743002: [builtins] Introduce proper Float64Log1p operator. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@Math_Log
Patch Set: REBASE 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
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 // ====================================================
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 /* Set the less significant 32 bits of a double from an int. */ 156 /* Set the less significant 32 bits of a double from an int. */
157 157
158 #define SET_LOW_WORD(d, v) \ 158 #define SET_LOW_WORD(d, v) \
159 do { \ 159 do { \
160 ieee_double_shape_type sl_u; \ 160 ieee_double_shape_type sl_u; \
161 sl_u.value = (d); \ 161 sl_u.value = (d); \
162 sl_u.parts.lsw = (v); \ 162 sl_u.parts.lsw = (v); \
163 (d) = sl_u.value; \ 163 (d) = sl_u.value; \
164 } while (0) 164 } while (0)
165 165
166 /* Support macro. */
167
168 #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
169
166 } // namespace 170 } // namespace
167 171
168 /* log(x) 172 /* log(x)
169 * Return the logrithm of x 173 * Return the logrithm of x
170 * 174 *
171 * Method : 175 * Method :
172 * 1. Argument Reduction: find k and f such that 176 * 1. Argument Reduction: find k and f such that
173 * x = 2^k * (1+f), 177 * x = 2^k * (1+f),
174 * where sqrt(2)/2 < 1+f < sqrt(2) . 178 * where sqrt(2)/2 < 1+f < sqrt(2) .
175 * 179 *
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 else 291 else
288 return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f); 292 return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f);
289 } else { 293 } else {
290 if (k == 0) 294 if (k == 0)
291 return f - s * (f - R); 295 return f - s * (f - R);
292 else 296 else
293 return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f); 297 return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f);
294 } 298 }
295 } 299 }
296 300
301 /* double log1p(double x)
302 *
303 * Method :
304 * 1. Argument Reduction: find k and f such that
305 * 1+x = 2^k * (1+f),
306 * where sqrt(2)/2 < 1+f < sqrt(2) .
307 *
308 * Note. If k=0, then f=x is exact. However, if k!=0, then f
309 * may not be representable exactly. In that case, a correction
310 * term is need. Let u=1+x rounded. Let c = (1+x)-u, then
311 * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
312 * and add back the correction term c/u.
313 * (Note: when x > 2**53, one can simply return log(x))
314 *
315 * 2. Approximation of log1p(f).
316 * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
317 * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
318 * = 2s + s*R
319 * We use a special Reme algorithm on [0,0.1716] to generate
320 * a polynomial of degree 14 to approximate R The maximum error
321 * of this polynomial approximation is bounded by 2**-58.45. In
322 * other words,
323 * 2 4 6 8 10 12 14
324 * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s
325 * (the values of Lp1 to Lp7 are listed in the program)
326 * and
327 * | 2 14 | -58.45
328 * | Lp1*s +...+Lp7*s - R(z) | <= 2
329 * | |
330 * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
331 * In order to guarantee error in log below 1ulp, we compute log
332 * by
333 * log1p(f) = f - (hfsq - s*(hfsq+R)).
334 *
335 * 3. Finally, log1p(x) = k*ln2 + log1p(f).
336 * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
337 * Here ln2 is split into two floating point number:
338 * ln2_hi + ln2_lo,
339 * where n*ln2_hi is always exact for |n| < 2000.
340 *
341 * Special cases:
342 * log1p(x) is NaN with signal if x < -1 (including -INF) ;
343 * log1p(+INF) is +INF; log1p(-1) is -INF with signal;
344 * log1p(NaN) is that NaN with no signal.
345 *
346 * Accuracy:
347 * according to an error analysis, the error is always less than
348 * 1 ulp (unit in the last place).
349 *
350 * Constants:
351 * The hexadecimal values are the intended ones for the following
352 * constants. The decimal values may be used, provided that the
353 * compiler will convert from decimal to binary accurately enough
354 * to produce the hexadecimal values shown.
355 *
356 * Note: Assuming log() return accurate answer, the following
357 * algorithm can be used to compute log1p(x) to within a few ULP:
358 *
359 * u = 1+x;
360 * if(u==1.0) return x ; else
361 * return log(u)*(x/(u-1.0));
362 *
363 * See HP-15C Advanced Functions Handbook, p.193.
364 */
365 double log1p(double x) {
366 static const double /* -- */
367 ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
368 ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
369 two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
370 Lp1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
371 Lp2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
372 Lp3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
373 Lp4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
374 Lp5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
375 Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
376 Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
377
378 static const double zero = 0.0;
379 static volatile double vzero = 0.0;
380
381 double hfsq, f, c, s, z, R, u;
382 int32_t k, hx, hu, ax;
383
384 GET_HIGH_WORD(hx, x);
385 ax = hx & 0x7fffffff;
386
387 k = 1;
388 if (hx < 0x3FDA827A) { /* 1+x < sqrt(2)+ */
389 if (ax >= 0x3ff00000) { /* x <= -1.0 */
390 if (x == -1.0)
391 return -two54 / vzero; /* log1p(-1)=+inf */
392 else
393 return (x - x) / (x - x); /* log1p(x<-1)=NaN */
394 }
395 if (ax < 0x3e200000) { /* |x| < 2**-29 */
396 if (two54 + x > zero /* raise inexact */
397 && ax < 0x3c900000) /* |x| < 2**-54 */
398 return x;
399 else
400 return x - x * x * 0.5;
401 }
402 if (hx > 0 || hx <= static_cast<int32_t>(0xbfd2bec4)) {
403 k = 0;
404 f = x;
405 hu = 1;
406 } /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
407 }
408 if (hx >= 0x7ff00000) return x + x;
409 if (k != 0) {
410 if (hx < 0x43400000) {
411 STRICT_ASSIGN(double, u, 1.0 + x);
412 GET_HIGH_WORD(hu, u);
413 k = (hu >> 20) - 1023;
414 c = (k > 0) ? 1.0 - (u - x) : x - (u - 1.0); /* correction term */
415 c /= u;
416 } else {
417 u = x;
418 GET_HIGH_WORD(hu, u);
419 k = (hu >> 20) - 1023;
420 c = 0;
421 }
422 hu &= 0x000fffff;
423 /*
424 * The approximation to sqrt(2) used in thresholds is not
425 * critical. However, the ones used above must give less
426 * strict bounds than the one here so that the k==0 case is
427 * never reached from here, since here we have committed to
428 * using the correction term but don't use it if k==0.
429 */
430 if (hu < 0x6a09e) { /* u ~< sqrt(2) */
431 SET_HIGH_WORD(u, hu | 0x3ff00000); /* normalize u */
432 } else {
433 k += 1;
434 SET_HIGH_WORD(u, hu | 0x3fe00000); /* normalize u/2 */
435 hu = (0x00100000 - hu) >> 2;
436 }
437 f = u - 1.0;
438 }
439 hfsq = 0.5 * f * f;
440 if (hu == 0) { /* |f| < 2**-20 */
441 if (f == zero) {
442 if (k == 0) {
443 return zero;
444 } else {
445 c += k * ln2_lo;
446 return k * ln2_hi + c;
447 }
448 }
449 R = hfsq * (1.0 - 0.66666666666666666 * f);
450 if (k == 0)
451 return f - R;
452 else
453 return k * ln2_hi - ((R - (k * ln2_lo + c)) - f);
454 }
455 s = f / (2.0 + f);
456 z = s * s;
457 R = z * (Lp1 +
458 z * (Lp2 + z * (Lp3 + z * (Lp4 + z * (Lp5 + z * (Lp6 + z * Lp7))))));
459 if (k == 0)
460 return f - (hfsq - s * (hfsq + R));
461 else
462 return k * ln2_hi - ((hfsq - (s * (hfsq + R) + (k * ln2_lo + c))) - f);
463 }
464
297 } // namespace ieee754 465 } // namespace ieee754
298 } // namespace base 466 } // namespace base
299 } // namespace v8 467 } // namespace v8
OLDNEW
« no previous file with comments | « src/base/ieee754.h ('k') | src/bootstrapper.cc » ('j') | src/builtins.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698