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