1*c9945492SAndroid Build Coastguard Worker #include "libm.h" 2*c9945492SAndroid Build Coastguard Worker 3*c9945492SAndroid Build Coastguard Worker /* sinh(x) = (exp(x) - 1/exp(x))/2 4*c9945492SAndroid Build Coastguard Worker * = (exp(x)-1 + (exp(x)-1)/exp(x))/2 5*c9945492SAndroid Build Coastguard Worker * = x + x^3/6 + o(x^5) 6*c9945492SAndroid Build Coastguard Worker */ sinh(double x)7*c9945492SAndroid Build Coastguard Workerdouble sinh(double x) 8*c9945492SAndroid Build Coastguard Worker { 9*c9945492SAndroid Build Coastguard Worker union {double f; uint64_t i;} u = {.f = x}; 10*c9945492SAndroid Build Coastguard Worker uint32_t w; 11*c9945492SAndroid Build Coastguard Worker double t, h, absx; 12*c9945492SAndroid Build Coastguard Worker 13*c9945492SAndroid Build Coastguard Worker h = 0.5; 14*c9945492SAndroid Build Coastguard Worker if (u.i >> 63) 15*c9945492SAndroid Build Coastguard Worker h = -h; 16*c9945492SAndroid Build Coastguard Worker /* |x| */ 17*c9945492SAndroid Build Coastguard Worker u.i &= (uint64_t)-1/2; 18*c9945492SAndroid Build Coastguard Worker absx = u.f; 19*c9945492SAndroid Build Coastguard Worker w = u.i >> 32; 20*c9945492SAndroid Build Coastguard Worker 21*c9945492SAndroid Build Coastguard Worker /* |x| < log(DBL_MAX) */ 22*c9945492SAndroid Build Coastguard Worker if (w < 0x40862e42) { 23*c9945492SAndroid Build Coastguard Worker t = expm1(absx); 24*c9945492SAndroid Build Coastguard Worker if (w < 0x3ff00000) { 25*c9945492SAndroid Build Coastguard Worker if (w < 0x3ff00000 - (26<<20)) 26*c9945492SAndroid Build Coastguard Worker /* note: inexact and underflow are raised by expm1 */ 27*c9945492SAndroid Build Coastguard Worker /* note: this branch avoids spurious underflow */ 28*c9945492SAndroid Build Coastguard Worker return x; 29*c9945492SAndroid Build Coastguard Worker return h*(2*t - t*t/(t+1)); 30*c9945492SAndroid Build Coastguard Worker } 31*c9945492SAndroid Build Coastguard Worker /* note: |x|>log(0x1p26)+eps could be just h*exp(x) */ 32*c9945492SAndroid Build Coastguard Worker return h*(t + t/(t+1)); 33*c9945492SAndroid Build Coastguard Worker } 34*c9945492SAndroid Build Coastguard Worker 35*c9945492SAndroid Build Coastguard Worker /* |x| > log(DBL_MAX) or nan */ 36*c9945492SAndroid Build Coastguard Worker /* note: the result is stored to handle overflow */ 37*c9945492SAndroid Build Coastguard Worker t = __expo2(absx, 2*h); 38*c9945492SAndroid Build Coastguard Worker return t; 39*c9945492SAndroid Build Coastguard Worker } 40