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