1*c9945492SAndroid Build Coastguard Worker #include "libm.h" 2*c9945492SAndroid Build Coastguard Worker tanhf(float x)3*c9945492SAndroid Build Coastguard Workerfloat tanhf(float x) 4*c9945492SAndroid Build Coastguard Worker { 5*c9945492SAndroid Build Coastguard Worker union {float f; uint32_t i;} u = {.f = x}; 6*c9945492SAndroid Build Coastguard Worker uint32_t w; 7*c9945492SAndroid Build Coastguard Worker int sign; 8*c9945492SAndroid Build Coastguard Worker float t; 9*c9945492SAndroid Build Coastguard Worker 10*c9945492SAndroid Build Coastguard Worker /* x = |x| */ 11*c9945492SAndroid Build Coastguard Worker sign = u.i >> 31; 12*c9945492SAndroid Build Coastguard Worker u.i &= 0x7fffffff; 13*c9945492SAndroid Build Coastguard Worker x = u.f; 14*c9945492SAndroid Build Coastguard Worker w = u.i; 15*c9945492SAndroid Build Coastguard Worker 16*c9945492SAndroid Build Coastguard Worker if (w > 0x3f0c9f54) { 17*c9945492SAndroid Build Coastguard Worker /* |x| > log(3)/2 ~= 0.5493 or nan */ 18*c9945492SAndroid Build Coastguard Worker if (w > 0x41200000) { 19*c9945492SAndroid Build Coastguard Worker /* |x| > 10 */ 20*c9945492SAndroid Build Coastguard Worker t = 1 + 0/x; 21*c9945492SAndroid Build Coastguard Worker } else { 22*c9945492SAndroid Build Coastguard Worker t = expm1f(2*x); 23*c9945492SAndroid Build Coastguard Worker t = 1 - 2/(t+2); 24*c9945492SAndroid Build Coastguard Worker } 25*c9945492SAndroid Build Coastguard Worker } else if (w > 0x3e82c578) { 26*c9945492SAndroid Build Coastguard Worker /* |x| > log(5/3)/2 ~= 0.2554 */ 27*c9945492SAndroid Build Coastguard Worker t = expm1f(2*x); 28*c9945492SAndroid Build Coastguard Worker t = t/(t+2); 29*c9945492SAndroid Build Coastguard Worker } else if (w >= 0x00800000) { 30*c9945492SAndroid Build Coastguard Worker /* |x| >= 0x1p-126 */ 31*c9945492SAndroid Build Coastguard Worker t = expm1f(-2*x); 32*c9945492SAndroid Build Coastguard Worker t = -t/(t+2); 33*c9945492SAndroid Build Coastguard Worker } else { 34*c9945492SAndroid Build Coastguard Worker /* |x| is subnormal */ 35*c9945492SAndroid Build Coastguard Worker FORCE_EVAL(x*x); 36*c9945492SAndroid Build Coastguard Worker t = x; 37*c9945492SAndroid Build Coastguard Worker } 38*c9945492SAndroid Build Coastguard Worker return sign ? -t : t; 39*c9945492SAndroid Build Coastguard Worker } 40