xref: /inferno-os/libkern/frexp-arm.c (revision 7b3bf63c0d3f8b97a41a7022310b70c5d40c6fc6)
137da2899SCharles.Forsyth #include <lib9.h>
237da2899SCharles.Forsyth 
337da2899SCharles.Forsyth #define	MASK	0x7ffL
437da2899SCharles.Forsyth #define	SHIFT	20
537da2899SCharles.Forsyth #define	BIAS	1022L
637da2899SCharles.Forsyth 
737da2899SCharles.Forsyth typedef	union
837da2899SCharles.Forsyth {
937da2899SCharles.Forsyth 	double	d;
10*7b3bf63cSCharles.Forsyth 	struct
1137da2899SCharles.Forsyth 	{
1237da2899SCharles.Forsyth 		long	ls;
13*7b3bf63cSCharles.Forsyth 		long	ms;
1437da2899SCharles.Forsyth 	};
1537da2899SCharles.Forsyth } Cheat;
1637da2899SCharles.Forsyth 
1737da2899SCharles.Forsyth double
frexp(double d,int * ep)1837da2899SCharles.Forsyth frexp(double d, int *ep)
1937da2899SCharles.Forsyth {
2037da2899SCharles.Forsyth 	Cheat x;
2137da2899SCharles.Forsyth 
2237da2899SCharles.Forsyth 	if(d == 0) {
2337da2899SCharles.Forsyth 		*ep = 0;
2437da2899SCharles.Forsyth 		return 0;
2537da2899SCharles.Forsyth 	}
2637da2899SCharles.Forsyth 	x.d = d;
2737da2899SCharles.Forsyth 	*ep = ((x.ms >> SHIFT) & MASK) - BIAS;
2837da2899SCharles.Forsyth 	x.ms &= ~(MASK << SHIFT);
2937da2899SCharles.Forsyth 	x.ms |= BIAS << SHIFT;
3037da2899SCharles.Forsyth 	return x.d;
3137da2899SCharles.Forsyth }
3237da2899SCharles.Forsyth 
3337da2899SCharles.Forsyth double
ldexp(double d,int e)3437da2899SCharles.Forsyth ldexp(double d, int e)
3537da2899SCharles.Forsyth {
3637da2899SCharles.Forsyth 	Cheat x;
3737da2899SCharles.Forsyth 
3837da2899SCharles.Forsyth 	if(d == 0)
3937da2899SCharles.Forsyth 		return 0;
4037da2899SCharles.Forsyth 	x.d = d;
4137da2899SCharles.Forsyth 	e += (x.ms >> SHIFT) & MASK;
4237da2899SCharles.Forsyth 	if(e <= 0)
4337da2899SCharles.Forsyth 		return 0;	/* underflow */
4437da2899SCharles.Forsyth 	if(e >= MASK){		/* overflow */
4537da2899SCharles.Forsyth 		if(d < 0)
4637da2899SCharles.Forsyth 			return Inf(-1);
4737da2899SCharles.Forsyth 		return Inf(1);
4837da2899SCharles.Forsyth 	}
4937da2899SCharles.Forsyth 	x.ms &= ~(MASK << SHIFT);
5037da2899SCharles.Forsyth 	x.ms |= (long)e << SHIFT;
5137da2899SCharles.Forsyth 	return x.d;
5237da2899SCharles.Forsyth }
5337da2899SCharles.Forsyth 
5437da2899SCharles.Forsyth double
modf(double d,double * ip)5537da2899SCharles.Forsyth modf(double d, double *ip)
5637da2899SCharles.Forsyth {
5737da2899SCharles.Forsyth 	Cheat x;
5837da2899SCharles.Forsyth 	int e;
5937da2899SCharles.Forsyth 
6037da2899SCharles.Forsyth 	if(d < 1) {
6137da2899SCharles.Forsyth 		if(d < 0) {
6237da2899SCharles.Forsyth 			x.d = modf(-d, ip);
6337da2899SCharles.Forsyth 			*ip = -*ip;
6437da2899SCharles.Forsyth 			return -x.d;
6537da2899SCharles.Forsyth 		}
6637da2899SCharles.Forsyth 		*ip = 0;
6737da2899SCharles.Forsyth 		return d;
6837da2899SCharles.Forsyth 	}
6937da2899SCharles.Forsyth 	x.d = d;
7037da2899SCharles.Forsyth 	e = ((x.ms >> SHIFT) & MASK) - BIAS;
7137da2899SCharles.Forsyth 	if(e <= SHIFT+1) {
7237da2899SCharles.Forsyth 		x.ms &= ~(0x1fffffL >> e);
7337da2899SCharles.Forsyth 		x.ls = 0;
7437da2899SCharles.Forsyth 	} else
7537da2899SCharles.Forsyth 	if(e <= SHIFT+33)
7637da2899SCharles.Forsyth 		x.ls &= ~(0x7fffffffL >> (e-SHIFT-2));
7737da2899SCharles.Forsyth 	*ip = x.d;
7837da2899SCharles.Forsyth 	return d - x.d;
7937da2899SCharles.Forsyth }
80