Home | History | Annotate | Download | only in fdlibm
      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