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