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