1 // The following is adapted from fdlibm (http://www.netlib.org/fdlibm), 2 // 3 // ==================================================== 4 // Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved. 5 // 6 // Developed at SunSoft, a Sun Microsystems, Inc. business. 7 // Permission to use, copy, modify, and distribute this 8 // software is freely granted, provided that this notice 9 // is preserved. 10 // ==================================================== 11 // 12 // The original source code covered by the above license above has been 13 // modified significantly by Google Inc. 14 // Copyright 2014 the V8 project authors. All rights reserved. 15 // 16 // The following is a straightforward translation of fdlibm routines 17 // by Raymond Toy (rtoy (a] google.com). 18 19 (function(global, utils) { 20 21 "use strict"; 22 23 %CheckIsBootstrapping(); 24 25 // ------------------------------------------------------------------- 26 // Imports 27 28 var GlobalMath = global.Math; 29 var MathAbs; 30 var MathExpm1; 31 32 utils.Import(function(from) { 33 MathAbs = from.MathAbs; 34 MathExpm1 = from.MathExpm1; 35 }); 36 37 // ES6 draft 09-27-13, section 20.2.2.30. 38 // Math.sinh 39 // Method : 40 // mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 41 // 1. Replace x by |x| (sinh(-x) = -sinh(x)). 42 // 2. 43 // E + E/(E+1) 44 // 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x) 45 // 2 46 // 47 // 22 <= x <= lnovft : sinh(x) := exp(x)/2 48 // lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2) 49 // ln2ovft < x : sinh(x) := x*shuge (overflow) 50 // 51 // Special cases: 52 // sinh(x) is |x| if x is +Infinity, -Infinity, or NaN. 53 // only sinh(0)=0 is exact for finite x. 54 // 55 define KSINH_OVERFLOW = 710.4758600739439; 56 define TWO_M28 = 3.725290298461914e-9; // 2^-28, empty lower half 57 define LOG_MAXD = 709.7822265625; // 0x40862e42 00000000, empty lower half 58 59 function MathSinh(x) { 60 x = x * 1; // Convert to number. 61 var h = (x < 0) ? -0.5 : 0.5; 62 // |x| in [0, 22]. return sign(x)*0.5*(E+E/(E+1)) 63 var ax = MathAbs(x); 64 if (ax < 22) { 65 // For |x| < 2^-28, sinh(x) = x 66 if (ax < TWO_M28) return x; 67 var t = MathExpm1(ax); 68 if (ax < 1) return h * (2 * t - t * t / (t + 1)); 69 return h * (t + t / (t + 1)); 70 } 71 // |x| in [22, log(maxdouble)], return 0.5 * exp(|x|) 72 if (ax < LOG_MAXD) return h * %math_exp(ax); 73 // |x| in [log(maxdouble), overflowthreshold] 74 // overflowthreshold = 710.4758600739426 75 if (ax <= KSINH_OVERFLOW) { 76 var w = %math_exp(0.5 * ax); 77 var t = h * w; 78 return t * w; 79 } 80 // |x| > overflowthreshold or is NaN. 81 // Return Infinity of the appropriate sign or NaN. 82 return x * INFINITY; 83 } 84 85 86 // ES6 draft 09-27-13, section 20.2.2.12. 87 // Math.cosh 88 // Method : 89 // mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 90 // 1. Replace x by |x| (cosh(x) = cosh(-x)). 91 // 2. 92 // [ exp(x) - 1 ]^2 93 // 0 <= x <= ln2/2 : cosh(x) := 1 + ------------------- 94 // 2*exp(x) 95 // 96 // exp(x) + 1/exp(x) 97 // ln2/2 <= x <= 22 : cosh(x) := ------------------- 98 // 2 99 // 22 <= x <= lnovft : cosh(x) := exp(x)/2 100 // lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2) 101 // ln2ovft < x : cosh(x) := huge*huge (overflow) 102 // 103 // Special cases: 104 // cosh(x) is |x| if x is +INF, -INF, or NaN. 105 // only cosh(0)=1 is exact for finite x. 106 // 107 define KCOSH_OVERFLOW = 710.4758600739439; 108 109 function MathCosh(x) { 110 x = x * 1; // Convert to number. 111 var ix = %_DoubleHi(x) & 0x7fffffff; 112 // |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|)) 113 if (ix < 0x3fd62e43) { 114 var t = MathExpm1(MathAbs(x)); 115 var w = 1 + t; 116 // For |x| < 2^-55, cosh(x) = 1 117 if (ix < 0x3c800000) return w; 118 return 1 + (t * t) / (w + w); 119 } 120 // |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2 121 if (ix < 0x40360000) { 122 var t = %math_exp(MathAbs(x)); 123 return 0.5 * t + 0.5 / t; 124 } 125 // |x| in [22, log(maxdouble)], return half*exp(|x|) 126 if (ix < 0x40862e42) return 0.5 * %math_exp(MathAbs(x)); 127 // |x| in [log(maxdouble), overflowthreshold] 128 if (MathAbs(x) <= KCOSH_OVERFLOW) { 129 var w = %math_exp(0.5 * MathAbs(x)); 130 var t = 0.5 * w; 131 return t * w; 132 } 133 if (NUMBER_IS_NAN(x)) return x; 134 // |x| > overflowthreshold. 135 return INFINITY; 136 } 137 138 // ES6 draft 09-27-13, section 20.2.2.33. 139 // Math.tanh(x) 140 // Method : 141 // x -x 142 // e - e 143 // 0. tanh(x) is defined to be ----------- 144 // x -x 145 // e + e 146 // 1. reduce x to non-negative by tanh(-x) = -tanh(x). 147 // 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x) 148 // -t 149 // 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x) 150 // t + 2 151 // 2 152 // 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t = expm1(2x) 153 // t + 2 154 // 22.0 < x <= INF : tanh(x) := 1. 155 // 156 // Special cases: 157 // tanh(NaN) is NaN; 158 // only tanh(0) = 0 is exact for finite argument. 159 // 160 161 define TWO_M55 = 2.77555756156289135105e-17; // 2^-55, empty lower half 162 163 function MathTanh(x) { 164 x = x * 1; // Convert to number. 165 // x is Infinity or NaN 166 if (!NUMBER_IS_FINITE(x)) { 167 if (x > 0) return 1; 168 if (x < 0) return -1; 169 return x; 170 } 171 172 var ax = MathAbs(x); 173 var z; 174 // |x| < 22 175 if (ax < 22) { 176 if (ax < TWO_M55) { 177 // |x| < 2^-55, tanh(small) = small. 178 return x; 179 } 180 if (ax >= 1) { 181 // |x| >= 1 182 var t = MathExpm1(2 * ax); 183 z = 1 - 2 / (t + 2); 184 } else { 185 var t = MathExpm1(-2 * ax); 186 z = -t / (t + 2); 187 } 188 } else { 189 // |x| > 22, return +/- 1 190 z = 1; 191 } 192 return (x >= 0) ? z : -z; 193 } 194 195 //------------------------------------------------------------------- 196 197 utils.InstallFunctions(GlobalMath, DONT_ENUM, [ 198 "sinh", MathSinh, 199 "cosh", MathCosh, 200 "tanh", MathTanh 201 ]); 202 203 }) 204