1*c9945492SAndroid Build Coastguard Worker #include "libm.h" 2*c9945492SAndroid Build Coastguard Worker 3*c9945492SAndroid Build Coastguard Worker /* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */ atanhf(float x)4*c9945492SAndroid Build Coastguard Workerfloat atanhf(float x) 5*c9945492SAndroid Build Coastguard Worker { 6*c9945492SAndroid Build Coastguard Worker union {float f; uint32_t i;} u = {.f = x}; 7*c9945492SAndroid Build Coastguard Worker unsigned s = u.i >> 31; 8*c9945492SAndroid Build Coastguard Worker float_t y; 9*c9945492SAndroid Build Coastguard Worker 10*c9945492SAndroid Build Coastguard Worker /* |x| */ 11*c9945492SAndroid Build Coastguard Worker u.i &= 0x7fffffff; 12*c9945492SAndroid Build Coastguard Worker y = u.f; 13*c9945492SAndroid Build Coastguard Worker 14*c9945492SAndroid Build Coastguard Worker if (u.i < 0x3f800000 - (1<<23)) { 15*c9945492SAndroid Build Coastguard Worker if (u.i < 0x3f800000 - (32<<23)) { 16*c9945492SAndroid Build Coastguard Worker /* handle underflow */ 17*c9945492SAndroid Build Coastguard Worker if (u.i < (1<<23)) 18*c9945492SAndroid Build Coastguard Worker FORCE_EVAL((float)(y*y)); 19*c9945492SAndroid Build Coastguard Worker } else { 20*c9945492SAndroid Build Coastguard Worker /* |x| < 0.5, up to 1.7ulp error */ 21*c9945492SAndroid Build Coastguard Worker y = 0.5f*log1pf(2*y + 2*y*y/(1-y)); 22*c9945492SAndroid Build Coastguard Worker } 23*c9945492SAndroid Build Coastguard Worker } else { 24*c9945492SAndroid Build Coastguard Worker /* avoid overflow */ 25*c9945492SAndroid Build Coastguard Worker y = 0.5f*log1pf(2*(y/(1-y))); 26*c9945492SAndroid Build Coastguard Worker } 27*c9945492SAndroid Build Coastguard Worker return s ? -y : y; 28*c9945492SAndroid Build Coastguard Worker } 29