xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/frexp.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <math.h>
2 #include <errno.h>
3 #define _RESEARCH_SOURCE
4 #include <float.h>
5 
6 #define	MASK	0x7ffL
7 #define	SHIFT	20
8 #define	BIAS	1022L
9 
10 typedef	union
11 {
12 	double	d;
13 	struct
14 	{
15 #ifdef IEEE_8087
16 		long	ls;
17 		long	ms;
18 #else
19 		long	ms;
20 		long	ls;
21 #endif
22 	};
23 } Cheat;
24 
25 double
26 frexp(double d, int *ep)
27 {
28 	Cheat x;
29 
30 	if(d == 0) {
31 		*ep = 0;
32 		return 0;
33 	}
34 	x.d = d;
35 	*ep = ((x.ms >> SHIFT) & MASK) - BIAS;
36 	x.ms &= ~(MASK << SHIFT);
37 	x.ms |= BIAS << SHIFT;
38 	return x.d;
39 }
40 
41 double
42 ldexp(double d, int e)
43 {
44 	Cheat x;
45 
46 	if(d == 0)
47 		return 0;
48 	x.d = d;
49 	e += (x.ms >> SHIFT) & MASK;
50 	if(e <= 0)
51 		return 0;
52 	if(e >= MASK){
53 		errno = ERANGE;
54 		if(d < 0)
55 			return -HUGE_VAL;
56 		return HUGE_VAL;
57 	}
58 	x.ms &= ~(MASK << SHIFT);
59 	x.ms |= (long)e << SHIFT;
60 	return x.d;
61 }
62 
63 double
64 modf(double d, double *ip)
65 {
66 	double f;
67 	Cheat x;
68 	int e;
69 
70 	if(d < 1) {
71 		if(d < 0) {
72 			f = modf(-d, ip);
73 			*ip = -*ip;
74 			return -f;
75 		}
76 		*ip = 0;
77 		return d;
78 	}
79 	x.d = d;
80 	e = ((x.ms >> SHIFT) & MASK) - BIAS;
81 	if(e <= SHIFT+1) {
82 		x.ms &= ~(0x1fffffL >> e);
83 		x.ls = 0;
84 	} else
85 	if(e <= SHIFT+33)
86 		x.ls &= ~(0x7fffffffL >> (e-SHIFT-2));
87 	*ip = x.d;
88 	return d - x.d;
89 }
90