Implement log10 via fdlibm port.
authoryangguo <yangguo@chromium.org>
Thu, 20 Nov 2014 09:37:18 +0000 (01:37 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 20 Nov 2014 09:37:27 +0000 (09:37 +0000)
R=rtoy@chromium.org
BUG=v8:3579
LOG=N

Review URL: https://codereview.chromium.org/739913003

Cr-Commit-Position: refs/heads/master@{#25433}

src/math.js
src/third_party/fdlibm/fdlibm.cc
src/third_party/fdlibm/fdlibm.h
src/third_party/fdlibm/fdlibm.js
test/mjsunit/es6/math-log2-log10.js

index 860b62f63e50d771625a76b0c5d411b84097085d..a8c42f47a96c6a70c9dc895f354c44d84ded0ed1 100644 (file)
@@ -227,12 +227,6 @@ function MathAtanh(x) {
   return 0.5 * MathLog((1 + x) / (1 - x));
 }
 
-// ES6 draft 09-27-13, section 20.2.2.21.
-function MathLog10(x) {
-  return MathLog(x) * 0.434294481903251828;  // log10(x) = log(x)/log(10).
-}
-
-
 // ES6 draft 09-27-13, section 20.2.2.22.
 function MathLog2(x) {
   return MathLog(x) * 1.442695040888963407;  // log2(x) = log(x)/log(2).
@@ -369,7 +363,7 @@ function SetUpMath() {
     "asinh", MathAsinh,
     "acosh", MathAcosh,
     "atanh", MathAtanh,
-    "log10", MathLog10,
+    "log10", MathLog10,   // implemented by third_party/fdlibm
     "log2", MathLog2,
     "hypot", MathHypot,
     "fround", MathFroundJS,
index 050bd2a58ec986172a3d167f71780703dfec393a..23c13c0f058ba3091e9217de466650edb9153b00 100644 (file)
@@ -27,59 +27,62 @@ inline double scalbn(double x, int y) { return _scalb(x, y); }
 #endif  // _MSC_VER
 
 const double MathConstants::constants[] = {
-    6.36619772367581382433e-01,   // invpio2   0
-    1.57079632673412561417e+00,   // pio2_1    1
-    6.07710050650619224932e-11,   // pio2_1t   2
-    6.07710050630396597660e-11,   // pio2_2    3
-    2.02226624879595063154e-21,   // pio2_2t   4
-    2.02226624871116645580e-21,   // pio2_3    5
-    8.47842766036889956997e-32,   // pio2_3t   6
-    -1.66666666666666324348e-01,  // S1        7  coefficients for sin
-    8.33333333332248946124e-03,   //           8
-    -1.98412698298579493134e-04,  //           9
-    2.75573137070700676789e-06,   //          10
-    -2.50507602534068634195e-08,  //          11
-    1.58969099521155010221e-10,   // S6       12
-    4.16666666666666019037e-02,   // C1       13  coefficients for cos
-    -1.38888888888741095749e-03,  //          14
-    2.48015872894767294178e-05,   //          15
-    -2.75573143513906633035e-07,  //          16
-    2.08757232129817482790e-09,   //          17
-    -1.13596475577881948265e-11,  // C6       18
-    3.33333333333334091986e-01,   // T0       19  coefficients for tan
-    1.33333333333201242699e-01,   //          20
-    5.39682539762260521377e-02,   //          21
-    2.18694882948595424599e-02,   //          22
-    8.86323982359930005737e-03,   //          23
-    3.59207910759131235356e-03,   //          24
-    1.45620945432529025516e-03,   //          25
-    5.88041240820264096874e-04,   //          26
-    2.46463134818469906812e-04,   //          27
-    7.81794442939557092300e-05,   //          28
-    7.14072491382608190305e-05,   //          29
-    -1.85586374855275456654e-05,  //          30
-    2.59073051863633712884e-05,   // T12      31
-    7.85398163397448278999e-01,   // pio4     32
-    3.06161699786838301793e-17,   // pio4lo   33
-    6.93147180369123816490e-01,   // ln2_hi   34
-    1.90821492927058770002e-10,   // ln2_lo   35
-    1.80143985094819840000e+16,   // 2^54     36
-    6.666666666666666666e-01,     // 2/3      37
-    6.666666666666735130e-01,     // LP1      38  coefficients for log1p
-    3.999999999940941908e-01,     //          39
-    2.857142874366239149e-01,     //          40
-    2.222219843214978396e-01,     //          41
-    1.818357216161805012e-01,     //          42
-    1.531383769920937332e-01,     //          43
-    1.479819860511658591e-01,     // LP7      44
-    7.09782712893383973096e+02,   //          45  overflow threshold for expm1
-    1.44269504088896338700e+00,   // 1/ln2    46
-    -3.33333333333331316428e-02,  // Q1       47  coefficients for expm1
-    1.58730158725481460165e-03,   //          48
-    -7.93650757867487942473e-05,  //          49
-    4.00821782732936239552e-06,   //          50
-    -2.01099218183624371326e-07,  // Q5       51
-    710.4758600739439             //          52  overflow threshold sinh, cosh
+    6.36619772367581382433e-01,   // invpio2    0
+    1.57079632673412561417e+00,   // pio2_1     1
+    6.07710050650619224932e-11,   // pio2_1t    2
+    6.07710050630396597660e-11,   // pio2_2     3
+    2.02226624879595063154e-21,   // pio2_2t    4
+    2.02226624871116645580e-21,   // pio2_3     5
+    8.47842766036889956997e-32,   // pio2_3t    6
+    -1.66666666666666324348e-01,  // S1         7  coefficients for sin
+    8.33333333332248946124e-03,   //            8
+    -1.98412698298579493134e-04,  //            9
+    2.75573137070700676789e-06,   //           10
+    -2.50507602534068634195e-08,  //           11
+    1.58969099521155010221e-10,   // S6        12
+    4.16666666666666019037e-02,   // C1        13  coefficients for cos
+    -1.38888888888741095749e-03,  //           14
+    2.48015872894767294178e-05,   //           15
+    -2.75573143513906633035e-07,  //           16
+    2.08757232129817482790e-09,   //           17
+    -1.13596475577881948265e-11,  // C6        18
+    3.33333333333334091986e-01,   // T0        19  coefficients for tan
+    1.33333333333201242699e-01,   //           20
+    5.39682539762260521377e-02,   //           21
+    2.18694882948595424599e-02,   //           22
+    8.86323982359930005737e-03,   //           23
+    3.59207910759131235356e-03,   //           24
+    1.45620945432529025516e-03,   //           25
+    5.88041240820264096874e-04,   //           26
+    2.46463134818469906812e-04,   //           27
+    7.81794442939557092300e-05,   //           28
+    7.14072491382608190305e-05,   //           29
+    -1.85586374855275456654e-05,  //           30
+    2.59073051863633712884e-05,   // T12       31
+    7.85398163397448278999e-01,   // pio4      32
+    3.06161699786838301793e-17,   // pio4lo    33
+    6.93147180369123816490e-01,   // ln2_hi    34
+    1.90821492927058770002e-10,   // ln2_lo    35
+    1.80143985094819840000e+16,   // 2^54      36
+    6.666666666666666666e-01,     // 2/3       37
+    6.666666666666735130e-01,     // LP1       38  coefficients for log1p
+    3.999999999940941908e-01,     //           39
+    2.857142874366239149e-01,     //           40
+    2.222219843214978396e-01,     //           41
+    1.818357216161805012e-01,     //           42
+    1.531383769920937332e-01,     //           43
+    1.479819860511658591e-01,     // LP7       44
+    7.09782712893383973096e+02,   //           45  overflow threshold for expm1
+    1.44269504088896338700e+00,   // 1/ln2     46
+    -3.33333333333331316428e-02,  // Q1        47  coefficients for expm1
+    1.58730158725481460165e-03,   //           48
+    -7.93650757867487942473e-05,  //           49
+    4.00821782732936239552e-06,   //           50
+    -2.01099218183624371326e-07,  // Q5        51
+    710.4758600739439,            //           52  overflow threshold sinh, cosh
+    4.34294481903251816668e-01,   // ivln10    53  coefficients for log10
+    3.01029995663611771306e-01,   // log10_2hi 54
+    3.69423907715893078616e-13    // log10_2lo 55
 };
 
 
index cadf85b95a1fb704921df5034cd3f1b9bdc9d115..e2a61c85833bdddc38eed2a5792b86d4cf46719a 100644 (file)
@@ -23,7 +23,7 @@ int rempio2(double x, double* y);
 
 // Constants to be exposed to builtins via Float64Array.
 struct MathConstants {
-  static const double constants[53];
+  static const double constants[56];
 };
 }
 }  // namespace v8::internal
index b52f1de2693feb84f2f39cc9a180db73210ca1cd..93a15483c27b09f35411d92e458ae9d10073cb8d 100644 (file)
@@ -812,3 +812,66 @@ function MathCosh(x) {
   // |x| > overflowthreshold.
   return INFINITY;
 }
+
+// ES6 draft 09-27-13, section 20.2.2.21.
+// Return the base 10 logarithm of x
+//
+// Method :
+//      Let log10_2hi = leading 40 bits of log10(2) and
+//          log10_2lo = log10(2) - log10_2hi,
+//          ivln10   = 1/log(10) rounded.
+//      Then
+//              n = ilogb(x),
+//              if(n<0)  n = n+1;
+//              x = scalbn(x,-n);
+//              log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
+//
+// Note 1:
+//      To guarantee log10(10**n)=n, where 10**n is normal, the rounding
+//      mode must set to Round-to-Nearest.
+// Note 2:
+//      [1/log(10)] rounded to 53 bits has error .198 ulps;
+//      log10 is monotonic at all binary break points.
+//
+// Special cases:
+//      log10(x) is NaN if x < 0;
+//      log10(+INF) is +INF; log10(0) is -INF;
+//      log10(NaN) is that NaN;
+//      log10(10**N) = N  for N=0,1,...,22.
+//
+
+const IVLN10 = kMath[53];
+const LOG10_2HI = kMath[54];
+const LOG10_2LO = kMath[55];
+
+function MathLog10(x) {
+  x = x * 1;  // Convert to number.
+  var hx = %_DoubleHi(x);
+  var lx = %_DoubleLo(x);
+  var k = 0;
+
+  if (hx < 0x00100000) {
+    // x < 2^-1022
+    // log10(+/- 0) = -Infinity.
+    if (((hx & 0x7fffffff) | lx) === 0) return -INFINITY;
+    // log10 of negative number is NaN.
+    if (hx < 0) return NAN;
+    // Subnormal number. Scale up x.
+    k -= 54;
+    x *= TWO54;
+    hx = %_DoubleHi(x);
+    lx = %_DoubleLo(x);
+  }
+
+  // Infinity or NaN.
+  if (hx >= 0x7ff00000) return x;
+
+  k += (hx >> 20) - 1023;
+  i = (k & 0x80000000) >> 31;
+  hx = (hx & 0x000fffff) | ((0x3ff - i) << 20);
+  y = k + i;
+  x = %_ConstructDouble(hx, lx);
+
+  z = y * LOG10_2LO + IVLN10 * MathLog(x);
+  return z + y * LOG10_2HI;
+}
index 4479894d7d89a0ebcd0ce4ecc6e8e5040e4f6421..863506c7055d77127d4694a6c461fc54a7b28d4e 100644 (file)
   assertEquals("Infinity", String(fun(Infinity)));
 });
 
-for (var i = -300; i < 300; i += 0.7) {
-  assertEqualsDelta(i, Math.log10(Math.pow(10, i)), 1E-13);
+for (var i = -310; i <= 308; i += 0.5) {
+  assertEquals(i, Math.log10(Math.pow(10, i)));
   assertEqualsDelta(i, Math.log2(Math.pow(2, i)), 1E-13);
 }
+
+// Test denormals.
+assertEquals(-307.77759430519706, Math.log10(1.5 * Math.pow(2, -1023)));