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