xref: /haiku/src/system/libroot/posix/musl/math/nexttoward.c (revision f504f61099b010fbfa94b1cc63d2e9072c7f7185)
1*f504f610SAugustin Cavalier #include "libm.h"
2*f504f610SAugustin Cavalier 
3*f504f610SAugustin Cavalier #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
nexttoward(double x,long double y)4*f504f610SAugustin Cavalier double nexttoward(double x, long double y)
5*f504f610SAugustin Cavalier {
6*f504f610SAugustin Cavalier 	return nextafter(x, y);
7*f504f610SAugustin Cavalier }
8*f504f610SAugustin Cavalier #else
nexttoward(double x,long double y)9*f504f610SAugustin Cavalier double nexttoward(double x, long double y)
10*f504f610SAugustin Cavalier {
11*f504f610SAugustin Cavalier 	union {double f; uint64_t i;} ux = {x};
12*f504f610SAugustin Cavalier 	int e;
13*f504f610SAugustin Cavalier 
14*f504f610SAugustin Cavalier 	if (isnan(x) || isnan(y))
15*f504f610SAugustin Cavalier 		return x + y;
16*f504f610SAugustin Cavalier 	if (x == y)
17*f504f610SAugustin Cavalier 		return y;
18*f504f610SAugustin Cavalier 	if (x == 0) {
19*f504f610SAugustin Cavalier 		ux.i = 1;
20*f504f610SAugustin Cavalier 		if (signbit(y))
21*f504f610SAugustin Cavalier 			ux.i |= 1ULL<<63;
22*f504f610SAugustin Cavalier 	} else if (x < y) {
23*f504f610SAugustin Cavalier 		if (signbit(x))
24*f504f610SAugustin Cavalier 			ux.i--;
25*f504f610SAugustin Cavalier 		else
26*f504f610SAugustin Cavalier 			ux.i++;
27*f504f610SAugustin Cavalier 	} else {
28*f504f610SAugustin Cavalier 		if (signbit(x))
29*f504f610SAugustin Cavalier 			ux.i++;
30*f504f610SAugustin Cavalier 		else
31*f504f610SAugustin Cavalier 			ux.i--;
32*f504f610SAugustin Cavalier 	}
33*f504f610SAugustin Cavalier 	e = ux.i>>52 & 0x7ff;
34*f504f610SAugustin Cavalier 	/* raise overflow if ux.f is infinite and x is finite */
35*f504f610SAugustin Cavalier 	if (e == 0x7ff)
36*f504f610SAugustin Cavalier 		FORCE_EVAL(x+x);
37*f504f610SAugustin Cavalier 	/* raise underflow if ux.f is subnormal or zero */
38*f504f610SAugustin Cavalier 	if (e == 0)
39*f504f610SAugustin Cavalier 		FORCE_EVAL(x*x + ux.f*ux.f);
40*f504f610SAugustin Cavalier 	return ux.f;
41*f504f610SAugustin Cavalier }
42*f504f610SAugustin Cavalier #endif
43