Chromium Code Reviews| OLD | NEW |
|---|---|
| 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-2004 by Sun Microsystems, Inc. All rights reserved. | 4 // Copyright (C) 1993-2004 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 2014 the V8 project authors. All rights reserved. | 14 // Copyright 2014 the V8 project authors. All rights reserved. |
| 15 // | 15 // |
| 16 // The following is a straightforward translation of fdlibm routines | 16 // The following is a straightforward translation of fdlibm routines |
| 17 // by Raymond Toy (rtoy@google.com). | 17 // by Raymond Toy (rtoy@google.com). |
| 18 | 18 |
| 19 // Double constants that do not have empty lower 32 bits are found in fdlibm.cc | 19 // Double constants that do not have empty lower 32 bits are found in fdlibm.cc |
| 20 // and exposed through kMath as typed array. We assume the compiler to convert | 20 // and exposed through kMath as typed array. We assume the compiler to convert |
| 21 // from decimal to binary accurately enough to produce the intended values. | 21 // from decimal to binary accurately enough to produce the intended values. |
| 22 // kMath is initialized to a Float64Array during genesis and not writable. | 22 // kMath is initialized to a Float64Array during genesis and not writable. |
| 23 | |
| 24 "use strict"; | |
| 25 | |
| 23 var kMath; | 26 var kMath; |
| 24 | 27 |
| 25 const INVPIO2 = kMath[0]; | 28 const INVPIO2 = kMath[0]; |
| 26 const PIO2_1 = kMath[1]; | 29 const PIO2_1 = kMath[1]; |
| 27 const PIO2_1T = kMath[2]; | 30 const PIO2_1T = kMath[2]; |
| 28 const PIO2_2 = kMath[3]; | 31 const PIO2_2 = kMath[3]; |
| 29 const PIO2_2T = kMath[4]; | 32 const PIO2_2T = kMath[4]; |
| 30 const PIO2_3 = kMath[5]; | 33 const PIO2_3 = kMath[5]; |
| 31 const PIO2_3T = kMath[6]; | 34 const PIO2_3T = kMath[6]; |
| 32 const PIO4 = kMath[32]; | 35 const PIO4 = kMath[32]; |
| (...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 868 | 871 |
| 869 k += (hx >> 20) - 1023; | 872 k += (hx >> 20) - 1023; |
| 870 i = (k & 0x80000000) >> 31; | 873 i = (k & 0x80000000) >> 31; |
| 871 hx = (hx & 0x000fffff) | ((0x3ff - i) << 20); | 874 hx = (hx & 0x000fffff) | ((0x3ff - i) << 20); |
| 872 y = k + i; | 875 y = k + i; |
| 873 x = %_ConstructDouble(hx, lx); | 876 x = %_ConstructDouble(hx, lx); |
| 874 | 877 |
| 875 z = y * LOG10_2LO + IVLN10 * MathLog(x); | 878 z = y * LOG10_2LO + IVLN10 * MathLog(x); |
| 876 return z + y * LOG10_2HI; | 879 return z + y * LOG10_2HI; |
| 877 } | 880 } |
| 881 | |
| 882 | |
| 883 // ES6 draft 09-27-13, section 20.2.2.22. | |
| 884 // Return the base 2 logarithm of x | |
| 885 // | |
| 886 // fdlibm does not have an explicit log2 function, but fdlibm's pow | |
| 887 // function does implement an accurate log2 function as part of the | |
| 888 // pow implementation. This extracts the core parts of that as a | |
| 889 // separate log2 function. | |
| 890 | |
| 891 // Method: | |
| 892 // Compute log2(x) in two pieces: | |
| 893 // log2(x) = w1 + w2 | |
| 894 // where w1 has 53-24 = 29 bits of trailing zeroes. | |
| 895 | |
| 896 const DP_H = kMath[65]; | |
| 897 const DP_L = kMath[66]; | |
| 898 | |
| 899 // Polynomial coefficients for (3/2)*(log2(x) - 2*s - 2/3*s^3) | |
| 900 macro KLOG2(x) | |
| 901 (kMath[56+x]) | |
| 902 endmacro | |
| 903 | |
| 904 // cp = 2/(3*ln(2)). Note that cp_h + cp_l is cp, but with more accuracy. | |
| 905 const CP = kMath[62]; | |
| 906 const CP_H = kMath[63]; | |
| 907 const CP_L = kMath[64]; | |
| 908 | |
| 909 function MathLog2(x) { | |
| 910 x = x * 1; // Convert to number. | |
| 911 var ax = MathAbs(x); | |
| 912 var hx = %_DoubleHi(x); | |
| 913 var lx = %_DoubleLo(x); | |
| 914 var ix = hx & 0x7fffffff; | |
| 915 | |
| 916 // Handle special cases. | |
| 917 // log2(+/- 0) = -Infinity | |
| 918 if ((ix | lx) == 0) return -INFINITY; | |
| 919 | |
| 920 // log(x) = NaN, if x < 0 | |
| 921 if (hx < 0) return NAN; | |
| 922 | |
| 923 // log2(Infinity) = Infinity, log2(NaN) = NaN | |
| 924 if (ix >= 0x7ff00000) return x; | |
| 925 | |
| 926 var n = 0; | |
| 927 | |
| 928 // Take care of subnormal number. | |
| 929 if (ix < 0x00100000) { | |
| 930 ax *= TWO54; | |
| 931 n -= 54; | |
|
Raymond Toy
2014/12/09 20:37:38
Why 54? The original code multiplied by 2^53. I s
Yang
2014/12/10 10:01:41
Done.
| |
| 932 ix = %_DoubleHi(ax); | |
| 933 } | |
| 934 | |
| 935 n += (ix >> 20) - 0x3ff; | |
| 936 var j = ix & 0x000fffff; | |
| 937 | |
| 938 // Determine interval. | |
| 939 ix = j | 0x3ff00000; // normalize ix. | |
| 940 | |
| 941 var bp = 1; | |
| 942 var dp_h = 0; | |
| 943 var dp_l = 0; | |
| 944 var th_offset = 0x00080000; | |
| 945 if (j > 0x3988e) { // |x| > sqrt(3/2) | |
| 946 if (j < 0xbb67a) { // |x| < sqrt(3) | |
| 947 bp = 1.5; | |
| 948 dp_h = DP_H; | |
| 949 dp_l = DP_L; | |
| 950 th_offset = 0x000c0000; | |
| 951 } else { | |
| 952 n += 1; | |
| 953 ix -= 0x00100000; | |
| 954 } | |
| 955 } | |
| 956 | |
| 957 ax = %_ConstructDouble(ix, %_DoubleLo(ax)); | |
| 958 | |
| 959 // Compute ss = s_h + s_l = (x - 1)/(x+1) or (x - 1.5)/(x + 1.5) | |
| 960 var u = ax - bp; | |
| 961 var v = 1 / (ax + bp); | |
| 962 var ss = u * v; | |
| 963 var s_h = %_ConstructDouble(%_DoubleHi(ss), 0); | |
| 964 | |
| 965 // t_h = ax + bp[k] High | |
| 966 var t_h = %_ConstructDouble(((ix >> 1) | 0x20000000) + th_offset, 0); | |
|
Raymond Toy
2014/12/09 20:37:38
If the comment on line 965 is correct, and I belie
Yang
2014/12/10 10:01:41
Done.
| |
| 967 var t_l = ax - (t_h - bp); | |
| 968 var s_l = v * ((u - s_h * t_h) - s_h * t_l); | |
| 969 | |
| 970 // Compute log2(ax) | |
| 971 var s2 = ss * ss; | |
| 972 var r = s2 * s2 * (KLOG2(0) + s2 * (KLOG2(1) + s2 * (KLOG2(2) + s2 * ( | |
| 973 KLOG2(3) + s2 * (KLOG2(4) + s2 * KLOG2(5)))))); | |
| 974 r += s_l * (s_h + ss); | |
| 975 s2 = s_h * s_h; | |
| 976 t_h = %_ConstructDouble(%_DoubleHi(3.0 + s2 + r), 0); | |
| 977 t_l = r - ((t_h - 3.0) - s2); | |
| 978 // u + v = ss * (1 + ...) | |
| 979 u = s_h * t_h; | |
| 980 v = s_l * t_h + t_l * ss; | |
| 981 | |
| 982 // 2 / (3 * log(2)) * (ss + ...) | |
| 983 p_h = %_ConstructDouble(%_DoubleHi(u + v), 0); | |
| 984 p_l = v - (p_h - u); | |
| 985 z_h = CP_H * p_h; | |
| 986 z_l = CP_L * p_h + p_l * CP + dp_l; | |
| 987 | |
| 988 // log2(ax) = (ss + ...) * 2 / (3 * log(2)) = n + dp_h + z_h + z_l | |
| 989 var t = n; | |
| 990 var t1 = %_ConstructDouble(%_DoubleHi(((z_h + z_l) + dp_h) + t), 0); | |
| 991 var t2 = z_l - (((t1 - t) - dp_h) - z_h); | |
| 992 | |
| 993 // t1 + t2 = log2(ax), sum up because we do not care about extra precision. | |
| 994 return t1 + t2; | |
| 995 } | |
| OLD | NEW |