xref: /aosp_15_r20/external/musl/src/math/cosh.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1*c9945492SAndroid Build Coastguard Worker #include "libm.h"
2*c9945492SAndroid Build Coastguard Worker 
3*c9945492SAndroid Build Coastguard Worker /* cosh(x) = (exp(x) + 1/exp(x))/2
4*c9945492SAndroid Build Coastguard Worker  *         = 1 + 0.5*(exp(x)-1)*(exp(x)-1)/exp(x)
5*c9945492SAndroid Build Coastguard Worker  *         = 1 + x*x/2 + o(x^4)
6*c9945492SAndroid Build Coastguard Worker  */
cosh(double x)7*c9945492SAndroid Build Coastguard Worker double cosh(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;
12*c9945492SAndroid Build Coastguard Worker 
13*c9945492SAndroid Build Coastguard Worker 	/* |x| */
14*c9945492SAndroid Build Coastguard Worker 	u.i &= (uint64_t)-1/2;
15*c9945492SAndroid Build Coastguard Worker 	x = u.f;
16*c9945492SAndroid Build Coastguard Worker 	w = u.i >> 32;
17*c9945492SAndroid Build Coastguard Worker 
18*c9945492SAndroid Build Coastguard Worker 	/* |x| < log(2) */
19*c9945492SAndroid Build Coastguard Worker 	if (w < 0x3fe62e42) {
20*c9945492SAndroid Build Coastguard Worker 		if (w < 0x3ff00000 - (26<<20)) {
21*c9945492SAndroid Build Coastguard Worker 			/* raise inexact if x!=0 */
22*c9945492SAndroid Build Coastguard Worker 			FORCE_EVAL(x + 0x1p120f);
23*c9945492SAndroid Build Coastguard Worker 			return 1;
24*c9945492SAndroid Build Coastguard Worker 		}
25*c9945492SAndroid Build Coastguard Worker 		t = expm1(x);
26*c9945492SAndroid Build Coastguard Worker 		return 1 + t*t/(2*(1+t));
27*c9945492SAndroid Build Coastguard Worker 	}
28*c9945492SAndroid Build Coastguard Worker 
29*c9945492SAndroid Build Coastguard Worker 	/* |x| < log(DBL_MAX) */
30*c9945492SAndroid Build Coastguard Worker 	if (w < 0x40862e42) {
31*c9945492SAndroid Build Coastguard Worker 		t = exp(x);
32*c9945492SAndroid Build Coastguard Worker 		/* note: if x>log(0x1p26) then the 1/t is not needed */
33*c9945492SAndroid Build Coastguard Worker 		return 0.5*(t + 1/t);
34*c9945492SAndroid Build Coastguard Worker 	}
35*c9945492SAndroid Build Coastguard Worker 
36*c9945492SAndroid Build Coastguard Worker 	/* |x| > log(DBL_MAX) or nan */
37*c9945492SAndroid Build Coastguard Worker 	/* note: the result is stored to handle overflow */
38*c9945492SAndroid Build Coastguard Worker 	t = __expo2(x, 1.0);
39*c9945492SAndroid Build Coastguard Worker 	return t;
40*c9945492SAndroid Build Coastguard Worker }
41