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 // rempio2result is used as a container for return values of %RemPiO2. It is | 23 // rempio2result is used as a container for return values of %RemPiO2. It is |
24 // initialized to a two-element Float64Array during genesis. | 24 // initialized to a two-element Float64Array during genesis. |
25 | 25 |
26 var kMath; | 26 var kMath; |
27 var rempio2result; | 27 var rempio2result; |
28 | 28 |
29 (function(global, utils) { | 29 (function(global, shared, exports) { |
30 | 30 |
31 "use strict"; | 31 "use strict"; |
32 | 32 |
33 %CheckIsBootstrapping(); | 33 %CheckIsBootstrapping(); |
34 | 34 |
35 // ------------------------------------------------------------------- | |
36 // Imports | |
37 | |
38 var GlobalMath = global.Math; | 35 var GlobalMath = global.Math; |
39 | 36 |
40 var MathAbs; | 37 //------------------------------------------------------------------- |
41 var MathExp; | |
42 | |
43 utils.Import(function(from) { | |
44 MathAbs = from.MathAbs; | |
45 MathExp = from.MathExp; | |
46 }); | |
47 | |
48 // ------------------------------------------------------------------- | |
49 | 38 |
50 define INVPIO2 = kMath[0]; | 39 define INVPIO2 = kMath[0]; |
51 define PIO2_1 = kMath[1]; | 40 define PIO2_1 = kMath[1]; |
52 define PIO2_1T = kMath[2]; | 41 define PIO2_1T = kMath[2]; |
53 define PIO2_2 = kMath[3]; | 42 define PIO2_2 = kMath[3]; |
54 define PIO2_2T = kMath[4]; | 43 define PIO2_2T = kMath[4]; |
55 define PIO2_3 = kMath[5]; | 44 define PIO2_3 = kMath[5]; |
56 define PIO2_3T = kMath[6]; | 45 define PIO2_3T = kMath[6]; |
57 define PIO4 = kMath[32]; | 46 define PIO4 = kMath[32]; |
58 define PIO4LO = kMath[33]; | 47 define PIO4LO = kMath[33]; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 } else { | 80 } else { |
92 // near pi/2, use 33+33+53 bit pi | 81 // near pi/2, use 33+33+53 bit pi |
93 z += PIO2_2; | 82 z += PIO2_2; |
94 y0 = z + PIO2_2T; | 83 y0 = z + PIO2_2T; |
95 y1 = (z - y0) + PIO2_2T; | 84 y1 = (z - y0) + PIO2_2T; |
96 } | 85 } |
97 n = -1; | 86 n = -1; |
98 } | 87 } |
99 } else if (ix <= 0x413921fb) { | 88 } else if (ix <= 0x413921fb) { |
100 // |X| ~<= 2^19*(pi/2), medium size | 89 // |X| ~<= 2^19*(pi/2), medium size |
101 var t = MathAbs(X); | 90 var t = $abs(X); |
102 n = (t * INVPIO2 + 0.5) | 0; | 91 n = (t * INVPIO2 + 0.5) | 0; |
103 var r = t - n * PIO2_1; | 92 var r = t - n * PIO2_1; |
104 var w = n * PIO2_1T; | 93 var w = n * PIO2_1T; |
105 // First round good to 85 bit | 94 // First round good to 85 bit |
106 y0 = r - w; | 95 y0 = r - w; |
107 if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x1000000) { | 96 if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x1000000) { |
108 // 2nd iteration needed, good to 118 | 97 // 2nd iteration needed, good to 118 |
109 t = r; | 98 t = r; |
110 w = n * PIO2_2; | 99 w = n * PIO2_2; |
111 r = t - w; | 100 r = t - w; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 | 262 |
274 function KernelTan(x, y, returnTan) { | 263 function KernelTan(x, y, returnTan) { |
275 var z; | 264 var z; |
276 var w; | 265 var w; |
277 var hx = %_DoubleHi(x); | 266 var hx = %_DoubleHi(x); |
278 var ix = hx & 0x7fffffff; | 267 var ix = hx & 0x7fffffff; |
279 | 268 |
280 if (ix < 0x3e300000) { // |x| < 2^-28 | 269 if (ix < 0x3e300000) { // |x| < 2^-28 |
281 if (((ix | %_DoubleLo(x)) | (returnTan + 1)) == 0) { | 270 if (((ix | %_DoubleLo(x)) | (returnTan + 1)) == 0) { |
282 // x == 0 && returnTan = -1 | 271 // x == 0 && returnTan = -1 |
283 return 1 / MathAbs(x); | 272 return 1 / $abs(x); |
284 } else { | 273 } else { |
285 if (returnTan == 1) { | 274 if (returnTan == 1) { |
286 return x; | 275 return x; |
287 } else { | 276 } else { |
288 // Compute -1/(x + y) carefully | 277 // Compute -1/(x + y) carefully |
289 var w = x + y; | 278 var w = x + y; |
290 var z = %_ConstructDouble(%_DoubleHi(w), 0); | 279 var z = %_ConstructDouble(%_DoubleHi(w), 0); |
291 var v = y - (z - x); | 280 var v = y - (z - x); |
292 var a = -1 / w; | 281 var a = -1 / w; |
293 var t = %_ConstructDouble(%_DoubleHi(a), 0); | 282 var t = %_ConstructDouble(%_DoubleHi(a), 0); |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 // only sinh(0)=0 is exact for finite x. | 750 // only sinh(0)=0 is exact for finite x. |
762 // | 751 // |
763 define KSINH_OVERFLOW = kMath[51]; | 752 define KSINH_OVERFLOW = kMath[51]; |
764 define TWO_M28 = 3.725290298461914e-9; // 2^-28, empty lower half | 753 define TWO_M28 = 3.725290298461914e-9; // 2^-28, empty lower half |
765 define LOG_MAXD = 709.7822265625; // 0x40862e42 00000000, empty lower half | 754 define LOG_MAXD = 709.7822265625; // 0x40862e42 00000000, empty lower half |
766 | 755 |
767 function MathSinh(x) { | 756 function MathSinh(x) { |
768 x = x * 1; // Convert to number. | 757 x = x * 1; // Convert to number. |
769 var h = (x < 0) ? -0.5 : 0.5; | 758 var h = (x < 0) ? -0.5 : 0.5; |
770 // |x| in [0, 22]. return sign(x)*0.5*(E+E/(E+1)) | 759 // |x| in [0, 22]. return sign(x)*0.5*(E+E/(E+1)) |
771 var ax = MathAbs(x); | 760 var ax = $abs(x); |
772 if (ax < 22) { | 761 if (ax < 22) { |
773 // For |x| < 2^-28, sinh(x) = x | 762 // For |x| < 2^-28, sinh(x) = x |
774 if (ax < TWO_M28) return x; | 763 if (ax < TWO_M28) return x; |
775 var t = MathExpm1(ax); | 764 var t = MathExpm1(ax); |
776 if (ax < 1) return h * (2 * t - t * t / (t + 1)); | 765 if (ax < 1) return h * (2 * t - t * t / (t + 1)); |
777 return h * (t + t / (t + 1)); | 766 return h * (t + t / (t + 1)); |
778 } | 767 } |
779 // |x| in [22, log(maxdouble)], return 0.5 * exp(|x|) | 768 // |x| in [22, log(maxdouble)], return 0.5 * exp(|x|) |
780 if (ax < LOG_MAXD) return h * MathExp(ax); | 769 if (ax < LOG_MAXD) return h * $exp(ax); |
781 // |x| in [log(maxdouble), overflowthreshold] | 770 // |x| in [log(maxdouble), overflowthreshold] |
782 // overflowthreshold = 710.4758600739426 | 771 // overflowthreshold = 710.4758600739426 |
783 if (ax <= KSINH_OVERFLOW) { | 772 if (ax <= KSINH_OVERFLOW) { |
784 var w = MathExp(0.5 * ax); | 773 var w = $exp(0.5 * ax); |
785 var t = h * w; | 774 var t = h * w; |
786 return t * w; | 775 return t * w; |
787 } | 776 } |
788 // |x| > overflowthreshold or is NaN. | 777 // |x| > overflowthreshold or is NaN. |
789 // Return Infinity of the appropriate sign or NaN. | 778 // Return Infinity of the appropriate sign or NaN. |
790 return x * INFINITY; | 779 return x * INFINITY; |
791 } | 780 } |
792 | 781 |
793 | 782 |
794 // ES6 draft 09-27-13, section 20.2.2.12. | 783 // ES6 draft 09-27-13, section 20.2.2.12. |
(...skipping 17 matching lines...) Expand all Loading... |
812 // cosh(x) is |x| if x is +INF, -INF, or NaN. | 801 // cosh(x) is |x| if x is +INF, -INF, or NaN. |
813 // only cosh(0)=1 is exact for finite x. | 802 // only cosh(0)=1 is exact for finite x. |
814 // | 803 // |
815 define KCOSH_OVERFLOW = kMath[51]; | 804 define KCOSH_OVERFLOW = kMath[51]; |
816 | 805 |
817 function MathCosh(x) { | 806 function MathCosh(x) { |
818 x = x * 1; // Convert to number. | 807 x = x * 1; // Convert to number. |
819 var ix = %_DoubleHi(x) & 0x7fffffff; | 808 var ix = %_DoubleHi(x) & 0x7fffffff; |
820 // |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|)) | 809 // |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|)) |
821 if (ix < 0x3fd62e43) { | 810 if (ix < 0x3fd62e43) { |
822 var t = MathExpm1(MathAbs(x)); | 811 var t = MathExpm1($abs(x)); |
823 var w = 1 + t; | 812 var w = 1 + t; |
824 // For |x| < 2^-55, cosh(x) = 1 | 813 // For |x| < 2^-55, cosh(x) = 1 |
825 if (ix < 0x3c800000) return w; | 814 if (ix < 0x3c800000) return w; |
826 return 1 + (t * t) / (w + w); | 815 return 1 + (t * t) / (w + w); |
827 } | 816 } |
828 // |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2 | 817 // |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2 |
829 if (ix < 0x40360000) { | 818 if (ix < 0x40360000) { |
830 var t = MathExp(MathAbs(x)); | 819 var t = $exp($abs(x)); |
831 return 0.5 * t + 0.5 / t; | 820 return 0.5 * t + 0.5 / t; |
832 } | 821 } |
833 // |x| in [22, log(maxdouble)], return half*exp(|x|) | 822 // |x| in [22, log(maxdouble)], return half*exp(|x|) |
834 if (ix < 0x40862e42) return 0.5 * MathExp(MathAbs(x)); | 823 if (ix < 0x40862e42) return 0.5 * $exp($abs(x)); |
835 // |x| in [log(maxdouble), overflowthreshold] | 824 // |x| in [log(maxdouble), overflowthreshold] |
836 if (MathAbs(x) <= KCOSH_OVERFLOW) { | 825 if ($abs(x) <= KCOSH_OVERFLOW) { |
837 var w = MathExp(0.5 * MathAbs(x)); | 826 var w = $exp(0.5 * $abs(x)); |
838 var t = 0.5 * w; | 827 var t = 0.5 * w; |
839 return t * w; | 828 return t * w; |
840 } | 829 } |
841 if (NUMBER_IS_NAN(x)) return x; | 830 if (NUMBER_IS_NAN(x)) return x; |
842 // |x| > overflowthreshold. | 831 // |x| > overflowthreshold. |
843 return INFINITY; | 832 return INFINITY; |
844 } | 833 } |
845 | 834 |
846 // ES6 draft 09-27-13, section 20.2.2.21. | 835 // ES6 draft 09-27-13, section 20.2.2.21. |
847 // Return the base 10 logarithm of x | 836 // Return the base 10 logarithm of x |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
930 | 919 |
931 // cp = 2/(3*ln(2)). Note that cp_h + cp_l is cp, but with more accuracy. | 920 // cp = 2/(3*ln(2)). Note that cp_h + cp_l is cp, but with more accuracy. |
932 define CP = kMath[61]; | 921 define CP = kMath[61]; |
933 define CP_H = kMath[62]; | 922 define CP_H = kMath[62]; |
934 define CP_L = kMath[63]; | 923 define CP_L = kMath[63]; |
935 // 2^53 | 924 // 2^53 |
936 define TWO53 = 9007199254740992; | 925 define TWO53 = 9007199254740992; |
937 | 926 |
938 function MathLog2(x) { | 927 function MathLog2(x) { |
939 x = x * 1; // Convert to number. | 928 x = x * 1; // Convert to number. |
940 var ax = MathAbs(x); | 929 var ax = $abs(x); |
941 var hx = %_DoubleHi(x); | 930 var hx = %_DoubleHi(x); |
942 var lx = %_DoubleLo(x); | 931 var lx = %_DoubleLo(x); |
943 var ix = hx & 0x7fffffff; | 932 var ix = hx & 0x7fffffff; |
944 | 933 |
945 // Handle special cases. | 934 // Handle special cases. |
946 // log2(+/- 0) = -Infinity | 935 // log2(+/- 0) = -Infinity |
947 if ((ix | lx) == 0) return -INFINITY; | 936 if ((ix | lx) == 0) return -INFINITY; |
948 | 937 |
949 // log(x) = NaN, if x < 0 | 938 // log(x) = NaN, if x < 0 |
950 if (hx < 0) return NAN; | 939 if (hx < 0) return NAN; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 "log10", MathLog10, | 1021 "log10", MathLog10, |
1033 "log2", MathLog2, | 1022 "log2", MathLog2, |
1034 "log1p", MathLog1p, | 1023 "log1p", MathLog1p, |
1035 "expm1", MathExpm1 | 1024 "expm1", MathExpm1 |
1036 ]); | 1025 ]); |
1037 | 1026 |
1038 %SetInlineBuiltinFlag(MathSin); | 1027 %SetInlineBuiltinFlag(MathSin); |
1039 %SetInlineBuiltinFlag(MathCos); | 1028 %SetInlineBuiltinFlag(MathCos); |
1040 | 1029 |
1041 }) | 1030 }) |
OLD | NEW |