xref: /inferno-os/libkern/frexp-mips.c (revision 46439007cf417cbd9ac8049bb4122c890097a0fa)
1 #include <u.h>
2 #include <libc.h>
3 
4 #define	MASK	0x7ffL
5 #define	SHIFT	20
6 #define	BIAS	1022L
7 
8 typedef	union
9 {
10 	double	d;
11 	struct
12 	{
13 		long	ms;
14 		long	ls;
15 	};
16 } Cheat;
17 
18 double
19 frexp(double d, int *ep)
20 {
21 	Cheat x;
22 
23 	if(d == 0) {
24 		*ep = 0;
25 		return 0;
26 	}
27 	x.d = d;
28 	*ep = ((x.ms >> SHIFT) & MASK) - BIAS;
29 	x.ms &= ~(MASK << SHIFT);
30 	x.ms |= BIAS << SHIFT;
31 	return x.d;
32 }
33 
34 double
35 ldexp(double d, int e)
36 {
37 	Cheat x;
38 
39 	if(d == 0)
40 		return 0;
41 	x.d = d;
42 	e += (x.ms >> SHIFT) & MASK;
43 	if(e <= 0)
44 		return 0;	/* underflow */
45 	if(e >= MASK){		/* overflow */
46 		if(d < 0)
47 			return Inf(-1);
48 		return Inf(1);
49 	}
50 	x.ms &= ~(MASK << SHIFT);
51 	x.ms |= (long)e << SHIFT;
52 	return x.d;
53 }
54 
55 double
56 modf(double d, double *ip)
57 {
58 	Cheat x;
59 	int e;
60 
61 	if(d < 1) {
62 		if(d < 0) {
63 			x.d = modf(-d, ip);
64 			*ip = -*ip;
65 			return -x.d;
66 		}
67 		*ip = 0;
68 		return d;
69 	}
70 	x.d = d;
71 	e = ((x.ms >> SHIFT) & MASK) - BIAS;
72 	if(e <= SHIFT+1) {
73 		x.ms &= ~(0x1fffffL >> e);
74 		x.ls = 0;
75 	} else
76 	if(e <= SHIFT+33)
77 		x.ls &= ~(0x7fffffffL >> (e-SHIFT-2));
78 	*ip = x.d;
79 	return d - x.d;
80 }
81