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 |