diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /libkern/frexp-mips.c | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'libkern/frexp-mips.c')
| -rw-r--r-- | libkern/frexp-mips.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/libkern/frexp-mips.c b/libkern/frexp-mips.c new file mode 100644 index 00000000..ac22e037 --- /dev/null +++ b/libkern/frexp-mips.c @@ -0,0 +1,80 @@ +#include <u.h> +#include <libc.h> + +#define MASK 0x7ffL +#define SHIFT 20 +#define BIAS 1022L + +typedef union +{ + double d; + struct + { + long ms; + long ls; + }; +} Cheat; + +double +frexp(double d, int *ep) +{ + Cheat x; + + if(d == 0) { + *ep = 0; + return 0; + } + x.d = d; + *ep = ((x.ms >> SHIFT) & MASK) - BIAS; + x.ms &= ~(MASK << SHIFT); + x.ms |= BIAS << SHIFT; + return x.d; +} + +double +ldexp(double d, int e) +{ + Cheat x; + + if(d == 0) + return 0; + x.d = d; + e += (x.ms >> SHIFT) & MASK; + if(e <= 0) + return 0; /* underflow */ + if(e >= MASK){ /* overflow */ + if(d < 0) + return Inf(-1); + return Inf(1); + } + x.ms &= ~(MASK << SHIFT); + x.ms |= (long)e << SHIFT; + return x.d; +} + +double +modf(double d, double *ip) +{ + Cheat x; + int e; + + if(d < 1) { + if(d < 0) { + x.d = modf(-d, ip); + *ip = -*ip; + return -x.d; + } + *ip = 0; + return d; + } + x.d = d; + e = ((x.ms >> SHIFT) & MASK) - BIAS; + if(e <= SHIFT+1) { + x.ms &= ~(0x1fffffL >> e); + x.ls = 0; + } else + if(e <= SHIFT+33) + x.ls &= ~(0x7fffffffL >> (e-SHIFT-2)); + *ip = x.d; + return d - x.d; +} |
