| 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 // ==================================================== |
| (...skipping 10 matching lines...) Expand all Loading... |
| 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 "use strict"; | 26 "use strict"; |
| 27 | 27 |
| 28 var kMath; | 28 var kMath; |
| 29 var rempio2result; | 29 var rempio2result; |
| 30 | 30 |
| 31 (function() { |
| 32 |
| 31 const INVPIO2 = kMath[0]; | 33 const INVPIO2 = kMath[0]; |
| 32 const PIO2_1 = kMath[1]; | 34 const PIO2_1 = kMath[1]; |
| 33 const PIO2_1T = kMath[2]; | 35 const PIO2_1T = kMath[2]; |
| 34 const PIO2_2 = kMath[3]; | 36 const PIO2_2 = kMath[3]; |
| 35 const PIO2_2T = kMath[4]; | 37 const PIO2_2T = kMath[4]; |
| 36 const PIO2_3 = kMath[5]; | 38 const PIO2_3 = kMath[5]; |
| 37 const PIO2_3T = kMath[6]; | 39 const PIO2_3T = kMath[6]; |
| 38 const PIO4 = kMath[32]; | 40 const PIO4 = kMath[32]; |
| 39 const PIO4LO = kMath[33]; | 41 const PIO4LO = kMath[33]; |
| 40 | 42 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 } else { | 74 } else { |
| 73 // near pi/2, use 33+33+53 bit pi | 75 // near pi/2, use 33+33+53 bit pi |
| 74 z += PIO2_2; | 76 z += PIO2_2; |
| 75 y0 = z + PIO2_2T; | 77 y0 = z + PIO2_2T; |
| 76 y1 = (z - y0) + PIO2_2T; | 78 y1 = (z - y0) + PIO2_2T; |
| 77 } | 79 } |
| 78 n = -1; | 80 n = -1; |
| 79 } | 81 } |
| 80 } else if (ix <= 0x413921fb) { | 82 } else if (ix <= 0x413921fb) { |
| 81 // |X| ~<= 2^19*(pi/2), medium size | 83 // |X| ~<= 2^19*(pi/2), medium size |
| 82 var t = MathAbs(X); | 84 var t = $abs(X); |
| 83 n = (t * INVPIO2 + 0.5) | 0; | 85 n = (t * INVPIO2 + 0.5) | 0; |
| 84 var r = t - n * PIO2_1; | 86 var r = t - n * PIO2_1; |
| 85 var w = n * PIO2_1T; | 87 var w = n * PIO2_1T; |
| 86 // First round good to 85 bit | 88 // First round good to 85 bit |
| 87 y0 = r - w; | 89 y0 = r - w; |
| 88 if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x1000000) { | 90 if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x1000000) { |
| 89 // 2nd iteration needed, good to 118 | 91 // 2nd iteration needed, good to 118 |
| 90 t = r; | 92 t = r; |
| 91 w = n * PIO2_2; | 93 w = n * PIO2_2; |
| 92 r = t - w; | 94 r = t - w; |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 | 252 |
| 251 function KernelTan(x, y, returnTan) { | 253 function KernelTan(x, y, returnTan) { |
| 252 var z; | 254 var z; |
| 253 var w; | 255 var w; |
| 254 var hx = %_DoubleHi(x); | 256 var hx = %_DoubleHi(x); |
| 255 var ix = hx & 0x7fffffff; | 257 var ix = hx & 0x7fffffff; |
| 256 | 258 |
| 257 if (ix < 0x3e300000) { // |x| < 2^-28 | 259 if (ix < 0x3e300000) { // |x| < 2^-28 |
| 258 if (((ix | %_DoubleLo(x)) | (returnTan + 1)) == 0) { | 260 if (((ix | %_DoubleLo(x)) | (returnTan + 1)) == 0) { |
| 259 // x == 0 && returnTan = -1 | 261 // x == 0 && returnTan = -1 |
| 260 return 1 / MathAbs(x); | 262 return 1 / $abs(x); |
| 261 } else { | 263 } else { |
| 262 if (returnTan == 1) { | 264 if (returnTan == 1) { |
| 263 return x; | 265 return x; |
| 264 } else { | 266 } else { |
| 265 // Compute -1/(x + y) carefully | 267 // Compute -1/(x + y) carefully |
| 266 var w = x + y; | 268 var w = x + y; |
| 267 var z = %_ConstructDouble(%_DoubleHi(w), 0); | 269 var z = %_ConstructDouble(%_DoubleHi(w), 0); |
| 268 var v = y - (z - x); | 270 var v = y - (z - x); |
| 269 var a = -1 / w; | 271 var a = -1 / w; |
| 270 var t = %_ConstructDouble(%_DoubleHi(a), 0); | 272 var t = %_ConstructDouble(%_DoubleHi(a), 0); |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 // only sinh(0)=0 is exact for finite x. | 740 // only sinh(0)=0 is exact for finite x. |
| 739 // | 741 // |
| 740 const KSINH_OVERFLOW = kMath[51]; | 742 const KSINH_OVERFLOW = kMath[51]; |
| 741 const TWO_M28 = 3.725290298461914e-9; // 2^-28, empty lower half | 743 const TWO_M28 = 3.725290298461914e-9; // 2^-28, empty lower half |
| 742 const LOG_MAXD = 709.7822265625; // 0x40862e42 00000000, empty lower half | 744 const LOG_MAXD = 709.7822265625; // 0x40862e42 00000000, empty lower half |
| 743 | 745 |
| 744 function MathSinh(x) { | 746 function MathSinh(x) { |
| 745 x = x * 1; // Convert to number. | 747 x = x * 1; // Convert to number. |
| 746 var h = (x < 0) ? -0.5 : 0.5; | 748 var h = (x < 0) ? -0.5 : 0.5; |
| 747 // |x| in [0, 22]. return sign(x)*0.5*(E+E/(E+1)) | 749 // |x| in [0, 22]. return sign(x)*0.5*(E+E/(E+1)) |
| 748 var ax = MathAbs(x); | 750 var ax = $abs(x); |
| 749 if (ax < 22) { | 751 if (ax < 22) { |
| 750 // For |x| < 2^-28, sinh(x) = x | 752 // For |x| < 2^-28, sinh(x) = x |
| 751 if (ax < TWO_M28) return x; | 753 if (ax < TWO_M28) return x; |
| 752 var t = MathExpm1(ax); | 754 var t = MathExpm1(ax); |
| 753 if (ax < 1) return h * (2 * t - t * t / (t + 1)); | 755 if (ax < 1) return h * (2 * t - t * t / (t + 1)); |
| 754 return h * (t + t / (t + 1)); | 756 return h * (t + t / (t + 1)); |
| 755 } | 757 } |
| 756 // |x| in [22, log(maxdouble)], return 0.5 * exp(|x|) | 758 // |x| in [22, log(maxdouble)], return 0.5 * exp(|x|) |
| 757 if (ax < LOG_MAXD) return h * MathExp(ax); | 759 if (ax < LOG_MAXD) return h * $exp(ax); |
| 758 // |x| in [log(maxdouble), overflowthreshold] | 760 // |x| in [log(maxdouble), overflowthreshold] |
| 759 // overflowthreshold = 710.4758600739426 | 761 // overflowthreshold = 710.4758600739426 |
| 760 if (ax <= KSINH_OVERFLOW) { | 762 if (ax <= KSINH_OVERFLOW) { |
| 761 var w = MathExp(0.5 * ax); | 763 var w = $exp(0.5 * ax); |
| 762 var t = h * w; | 764 var t = h * w; |
| 763 return t * w; | 765 return t * w; |
| 764 } | 766 } |
| 765 // |x| > overflowthreshold or is NaN. | 767 // |x| > overflowthreshold or is NaN. |
| 766 // Return Infinity of the appropriate sign or NaN. | 768 // Return Infinity of the appropriate sign or NaN. |
| 767 return x * INFINITY; | 769 return x * INFINITY; |
| 768 } | 770 } |
| 769 | 771 |
| 770 | 772 |
| 771 // ES6 draft 09-27-13, section 20.2.2.12. | 773 // ES6 draft 09-27-13, section 20.2.2.12. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 789 // cosh(x) is |x| if x is +INF, -INF, or NaN. | 791 // cosh(x) is |x| if x is +INF, -INF, or NaN. |
| 790 // only cosh(0)=1 is exact for finite x. | 792 // only cosh(0)=1 is exact for finite x. |
| 791 // | 793 // |
| 792 const KCOSH_OVERFLOW = kMath[51]; | 794 const KCOSH_OVERFLOW = kMath[51]; |
| 793 | 795 |
| 794 function MathCosh(x) { | 796 function MathCosh(x) { |
| 795 x = x * 1; // Convert to number. | 797 x = x * 1; // Convert to number. |
| 796 var ix = %_DoubleHi(x) & 0x7fffffff; | 798 var ix = %_DoubleHi(x) & 0x7fffffff; |
| 797 // |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|)) | 799 // |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|)) |
| 798 if (ix < 0x3fd62e43) { | 800 if (ix < 0x3fd62e43) { |
| 799 var t = MathExpm1(MathAbs(x)); | 801 var t = MathExpm1($abs(x)); |
| 800 var w = 1 + t; | 802 var w = 1 + t; |
| 801 // For |x| < 2^-55, cosh(x) = 1 | 803 // For |x| < 2^-55, cosh(x) = 1 |
| 802 if (ix < 0x3c800000) return w; | 804 if (ix < 0x3c800000) return w; |
| 803 return 1 + (t * t) / (w + w); | 805 return 1 + (t * t) / (w + w); |
| 804 } | 806 } |
| 805 // |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2 | 807 // |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2 |
| 806 if (ix < 0x40360000) { | 808 if (ix < 0x40360000) { |
| 807 var t = MathExp(MathAbs(x)); | 809 var t = $exp($abs(x)); |
| 808 return 0.5 * t + 0.5 / t; | 810 return 0.5 * t + 0.5 / t; |
| 809 } | 811 } |
| 810 // |x| in [22, log(maxdouble)], return half*exp(|x|) | 812 // |x| in [22, log(maxdouble)], return half*exp(|x|) |
| 811 if (ix < 0x40862e42) return 0.5 * MathExp(MathAbs(x)); | 813 if (ix < 0x40862e42) return 0.5 * $exp($abs(x)); |
| 812 // |x| in [log(maxdouble), overflowthreshold] | 814 // |x| in [log(maxdouble), overflowthreshold] |
| 813 if (MathAbs(x) <= KCOSH_OVERFLOW) { | 815 if ($abs(x) <= KCOSH_OVERFLOW) { |
| 814 var w = MathExp(0.5 * MathAbs(x)); | 816 var w = $exp(0.5 * $abs(x)); |
| 815 var t = 0.5 * w; | 817 var t = 0.5 * w; |
| 816 return t * w; | 818 return t * w; |
| 817 } | 819 } |
| 818 if (NUMBER_IS_NAN(x)) return x; | 820 if (NUMBER_IS_NAN(x)) return x; |
| 819 // |x| > overflowthreshold. | 821 // |x| > overflowthreshold. |
| 820 return INFINITY; | 822 return INFINITY; |
| 821 } | 823 } |
| 822 | 824 |
| 823 // ES6 draft 09-27-13, section 20.2.2.21. | 825 // ES6 draft 09-27-13, section 20.2.2.21. |
| 824 // Return the base 10 logarithm of x | 826 // Return the base 10 logarithm of x |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 | 874 |
| 873 // Infinity or NaN. | 875 // Infinity or NaN. |
| 874 if (hx >= 0x7ff00000) return x; | 876 if (hx >= 0x7ff00000) return x; |
| 875 | 877 |
| 876 k += (hx >> 20) - 1023; | 878 k += (hx >> 20) - 1023; |
| 877 i = (k & 0x80000000) >> 31; | 879 i = (k & 0x80000000) >> 31; |
| 878 hx = (hx & 0x000fffff) | ((0x3ff - i) << 20); | 880 hx = (hx & 0x000fffff) | ((0x3ff - i) << 20); |
| 879 y = k + i; | 881 y = k + i; |
| 880 x = %_ConstructDouble(hx, lx); | 882 x = %_ConstructDouble(hx, lx); |
| 881 | 883 |
| 882 z = y * LOG10_2LO + IVLN10 * MathLog(x); | 884 z = y * LOG10_2LO + IVLN10 * %_MathLogRT(x); |
| 883 return z + y * LOG10_2HI; | 885 return z + y * LOG10_2HI; |
| 884 } | 886 } |
| 885 | 887 |
| 886 | 888 |
| 887 // ES6 draft 09-27-13, section 20.2.2.22. | 889 // ES6 draft 09-27-13, section 20.2.2.22. |
| 888 // Return the base 2 logarithm of x | 890 // Return the base 2 logarithm of x |
| 889 // | 891 // |
| 890 // fdlibm does not have an explicit log2 function, but fdlibm's pow | 892 // fdlibm does not have an explicit log2 function, but fdlibm's pow |
| 891 // function does implement an accurate log2 function as part of the | 893 // function does implement an accurate log2 function as part of the |
| 892 // pow implementation. This extracts the core parts of that as a | 894 // pow implementation. This extracts the core parts of that as a |
| (...skipping 14 matching lines...) Expand all Loading... |
| 907 | 909 |
| 908 // cp = 2/(3*ln(2)). Note that cp_h + cp_l is cp, but with more accuracy. | 910 // cp = 2/(3*ln(2)). Note that cp_h + cp_l is cp, but with more accuracy. |
| 909 const CP = kMath[61]; | 911 const CP = kMath[61]; |
| 910 const CP_H = kMath[62]; | 912 const CP_H = kMath[62]; |
| 911 const CP_L = kMath[63]; | 913 const CP_L = kMath[63]; |
| 912 // 2^53 | 914 // 2^53 |
| 913 const TWO53 = 9007199254740992; | 915 const TWO53 = 9007199254740992; |
| 914 | 916 |
| 915 function MathLog2(x) { | 917 function MathLog2(x) { |
| 916 x = x * 1; // Convert to number. | 918 x = x * 1; // Convert to number. |
| 917 var ax = MathAbs(x); | 919 var ax = $abs(x); |
| 918 var hx = %_DoubleHi(x); | 920 var hx = %_DoubleHi(x); |
| 919 var lx = %_DoubleLo(x); | 921 var lx = %_DoubleLo(x); |
| 920 var ix = hx & 0x7fffffff; | 922 var ix = hx & 0x7fffffff; |
| 921 | 923 |
| 922 // Handle special cases. | 924 // Handle special cases. |
| 923 // log2(+/- 0) = -Infinity | 925 // log2(+/- 0) = -Infinity |
| 924 if ((ix | lx) == 0) return -INFINITY; | 926 if ((ix | lx) == 0) return -INFINITY; |
| 925 | 927 |
| 926 // log(x) = NaN, if x < 0 | 928 // log(x) = NaN, if x < 0 |
| 927 if (hx < 0) return NAN; | 929 if (hx < 0) return NAN; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 z_l = CP_L * p_h + p_l * CP + dp_l; | 992 z_l = CP_L * p_h + p_l * CP + dp_l; |
| 991 | 993 |
| 992 // log2(ax) = (ss + ...) * 2 / (3 * log(2)) = n + dp_h + z_h + z_l | 994 // log2(ax) = (ss + ...) * 2 / (3 * log(2)) = n + dp_h + z_h + z_l |
| 993 var t = n; | 995 var t = n; |
| 994 var t1 = %_ConstructDouble(%_DoubleHi(((z_h + z_l) + dp_h) + t), 0); | 996 var t1 = %_ConstructDouble(%_DoubleHi(((z_h + z_l) + dp_h) + t), 0); |
| 995 var t2 = z_l - (((t1 - t) - dp_h) - z_h); | 997 var t2 = z_l - (((t1 - t) - dp_h) - z_h); |
| 996 | 998 |
| 997 // t1 + t2 = log2(ax), sum up because we do not care about extra precision. | 999 // t1 + t2 = log2(ax), sum up because we do not care about extra precision. |
| 998 return t1 + t2; | 1000 return t1 + t2; |
| 999 } | 1001 } |
| 1002 |
| 1003 InstallFunctions($Math, DONT_ENUM, $Array( |
| 1004 "cos", MathCos, |
| 1005 "sin", MathSin, |
| 1006 "tan", MathTan, |
| 1007 "sinh", MathSinh, |
| 1008 "cosh", MathCosh, |
| 1009 "log10", MathLog10, |
| 1010 "log2", MathLog2, |
| 1011 "log1p", MathLog1p, |
| 1012 "expm1", MathExpm1 |
| 1013 )); |
| 1014 |
| 1015 %SetInlineBuiltinFlag(MathSin); |
| 1016 %SetInlineBuiltinFlag(MathCos); |
| 1017 |
| 1018 })(); |
| OLD | NEW |