| 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 |