xref: /plan9/sys/src/ape/lib/ap/math/modf.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1*3e12c5d1SDavid du Colombier #include <math.h>
2*3e12c5d1SDavid du Colombier #include <errno.h>
3*3e12c5d1SDavid du Colombier 
4*3e12c5d1SDavid du Colombier /* modf suitable for IEEE double-precision */
5*3e12c5d1SDavid du Colombier 
6*3e12c5d1SDavid du Colombier #define	MASK	0x7ffL
7*3e12c5d1SDavid du Colombier #define SIGN	0x80000000
8*3e12c5d1SDavid du Colombier #define	SHIFT	20
9*3e12c5d1SDavid du Colombier #define	BIAS	1022L
10*3e12c5d1SDavid du Colombier 
11*3e12c5d1SDavid du Colombier typedef	union
12*3e12c5d1SDavid du Colombier {
13*3e12c5d1SDavid du Colombier 	double	d;
14*3e12c5d1SDavid du Colombier 	struct
15*3e12c5d1SDavid du Colombier 	{
16*3e12c5d1SDavid du Colombier 		long	ms;
17*3e12c5d1SDavid du Colombier 		long	ls;
18*3e12c5d1SDavid du Colombier 	} i;
19*3e12c5d1SDavid du Colombier } Cheat;
20*3e12c5d1SDavid du Colombier 
21*3e12c5d1SDavid du Colombier double
modf(double d,double * ip)22*3e12c5d1SDavid du Colombier modf(double d, double *ip)
23*3e12c5d1SDavid du Colombier {
24*3e12c5d1SDavid du Colombier 	Cheat x;
25*3e12c5d1SDavid du Colombier 	int e;
26*3e12c5d1SDavid du Colombier 
27*3e12c5d1SDavid du Colombier 	if(-1 < d && d < 1) {
28*3e12c5d1SDavid du Colombier 		*ip = 0;
29*3e12c5d1SDavid du Colombier 		return d;
30*3e12c5d1SDavid du Colombier 	}
31*3e12c5d1SDavid du Colombier 	x.d = d;
32*3e12c5d1SDavid du Colombier 	x.i.ms &= ~SIGN;
33*3e12c5d1SDavid du Colombier 	e = (x.i.ms >> SHIFT) & MASK;
34*3e12c5d1SDavid du Colombier 	if(e == MASK || e == 0){
35*3e12c5d1SDavid du Colombier 		errno = EDOM;
36*3e12c5d1SDavid du Colombier 		*ip = (d > 0)? HUGE_VAL : -HUGE_VAL;
37*3e12c5d1SDavid du Colombier 		return 0;
38*3e12c5d1SDavid du Colombier 	}
39*3e12c5d1SDavid du Colombier 	e -= BIAS;
40*3e12c5d1SDavid du Colombier 	if(e <= SHIFT+1) {
41*3e12c5d1SDavid du Colombier 		x.i.ms &= ~(0x1fffffL >> e);
42*3e12c5d1SDavid du Colombier 		x.i.ls = 0;
43*3e12c5d1SDavid du Colombier 	} else
44*3e12c5d1SDavid du Colombier 	if(e <= SHIFT+33)
45*3e12c5d1SDavid du Colombier 		x.i.ls &= ~(0x7fffffffL >> (e-SHIFT-2));
46*3e12c5d1SDavid du Colombier 	if(d > 0){
47*3e12c5d1SDavid du Colombier 		*ip = x.d;
48*3e12c5d1SDavid du Colombier 		return d - x.d;
49*3e12c5d1SDavid du Colombier 	}else{
50*3e12c5d1SDavid du Colombier 		*ip = -x.d;
51*3e12c5d1SDavid du Colombier 		return d + x.d;
52*3e12c5d1SDavid du Colombier 	}
53*3e12c5d1SDavid du Colombier }
54