xref: /aosp_15_r20/external/musl/src/math/tanhf.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1*c9945492SAndroid Build Coastguard Worker #include "libm.h"
2*c9945492SAndroid Build Coastguard Worker 
tanhf(float x)3*c9945492SAndroid Build Coastguard Worker float 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