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 |