libmach
This commit is contained in:
parent
0e3cc9f456
commit
a84cbb2a17
53 changed files with 12038 additions and 0 deletions
169
src/libmach/ieee.c
Normal file
169
src/libmach/ieee.c
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <mach.h>
|
||||
|
||||
/*
|
||||
* These routines assume that if the number is representable
|
||||
* in IEEE floating point, it will be representable in the native
|
||||
* double format. Naive but workable, probably.
|
||||
*/
|
||||
int
|
||||
ieeeftoa64(char *buf, uint n, u32int h, u32int l)
|
||||
{
|
||||
double fr;
|
||||
int exp;
|
||||
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
|
||||
|
||||
if(h & (1L<<31)){
|
||||
*buf++ = '-';
|
||||
h &= ~(1L<<31);
|
||||
}else
|
||||
*buf++ = ' ';
|
||||
n--;
|
||||
if(l == 0 && h == 0)
|
||||
return snprint(buf, n, "0.");
|
||||
exp = (h>>20) & ((1L<<11)-1L);
|
||||
if(exp == 0)
|
||||
return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l);
|
||||
if(exp == ((1L<<11)-1L)){
|
||||
if(l==0 && (h&((1L<<20)-1L)) == 0)
|
||||
return snprint(buf, n, "Inf");
|
||||
else
|
||||
return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l);
|
||||
}
|
||||
exp -= (1L<<10) - 2L;
|
||||
fr = l & ((1L<<16)-1L);
|
||||
fr /= 1L<<16;
|
||||
fr += (l>>16) & ((1L<<16)-1L);
|
||||
fr /= 1L<<16;
|
||||
fr += (h & (1L<<20)-1L) | (1L<<20);
|
||||
fr /= 1L<<21;
|
||||
fr = ldexp(fr, exp);
|
||||
return snprint(buf, n, "%.18g", fr);
|
||||
}
|
||||
|
||||
int
|
||||
ieeeftoa32(char *buf, uint n, u32int h)
|
||||
{
|
||||
double fr;
|
||||
int exp;
|
||||
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
|
||||
if(h & (1L<<31)){
|
||||
*buf++ = '-';
|
||||
h &= ~(1L<<31);
|
||||
}else
|
||||
*buf++ = ' ';
|
||||
n--;
|
||||
if(h == 0)
|
||||
return snprint(buf, n, "0.");
|
||||
exp = (h>>23) & ((1L<<8)-1L);
|
||||
if(exp == 0)
|
||||
return snprint(buf, n, "DeN(%.8lux)", h);
|
||||
if(exp == ((1L<<8)-1L)){
|
||||
if((h&((1L<<23)-1L)) == 0)
|
||||
return snprint(buf, n, "Inf");
|
||||
else
|
||||
return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L));
|
||||
}
|
||||
exp -= (1L<<7) - 2L;
|
||||
fr = (h & ((1L<<23)-1L)) | (1L<<23);
|
||||
fr /= 1L<<24;
|
||||
fr = ldexp(fr, exp);
|
||||
return snprint(buf, n, "%.9g", fr);
|
||||
}
|
||||
|
||||
int
|
||||
beieeeftoa32(char *buf, uint n, void *s)
|
||||
{
|
||||
return ieeeftoa32(buf, n, beswap4(*(u32int*)s));
|
||||
}
|
||||
|
||||
int
|
||||
beieeeftoa64(char *buf, uint n, void *s)
|
||||
{
|
||||
return ieeeftoa64(buf, n, beswap4(*(u32int*)s), beswap4(((u32int*)(s))[1]));
|
||||
}
|
||||
|
||||
int
|
||||
leieeeftoa32(char *buf, uint n, void *s)
|
||||
{
|
||||
return ieeeftoa32(buf, n, leswap4(*(u32int*)s));
|
||||
}
|
||||
|
||||
int
|
||||
leieeeftoa64(char *buf, uint n, void *s)
|
||||
{
|
||||
return ieeeftoa64(buf, n, leswap4(((u32int*)(s))[1]), leswap4(*(u32int*)s));
|
||||
}
|
||||
|
||||
/* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/
|
||||
int
|
||||
beieeeftoa80(char *buf, uint n, void *s)
|
||||
{
|
||||
uchar *reg = (uchar*)s;
|
||||
int i;
|
||||
ulong x;
|
||||
uchar ieee[8+8]; /* room for slop */
|
||||
uchar *p, *q;
|
||||
|
||||
memset(ieee, 0, sizeof(ieee));
|
||||
/* sign */
|
||||
if(reg[0] & 0x80)
|
||||
ieee[0] |= 0x80;
|
||||
|
||||
/* exponent */
|
||||
x = ((reg[0]&0x7F)<<8) | reg[1];
|
||||
if(x == 0) /* number is ±0 */
|
||||
goto done;
|
||||
if(x == 0x7FFF){
|
||||
if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */
|
||||
x = 2047;
|
||||
}else{ /* NaN */
|
||||
x = 2047;
|
||||
ieee[7] = 0x1; /* make sure */
|
||||
}
|
||||
ieee[0] |= x>>4;
|
||||
ieee[1] |= (x&0xF)<<4;
|
||||
goto done;
|
||||
}
|
||||
x -= 0x3FFF; /* exponent bias */
|
||||
x += 1023;
|
||||
if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0))
|
||||
return snprint(buf, n, "not in range");
|
||||
ieee[0] |= x>>4;
|
||||
ieee[1] |= (x&0xF)<<4;
|
||||
|
||||
/* mantissa */
|
||||
p = reg+4;
|
||||
q = ieee+1;
|
||||
for(i=0; i<56; i+=8, p++, q++){ /* move one byte */
|
||||
x = (p[0]&0x7F) << 1;
|
||||
if(p[1] & 0x80)
|
||||
x |= 1;
|
||||
q[0] |= x>>4;
|
||||
q[1] |= (x&0xF)<<4;
|
||||
}
|
||||
done:
|
||||
return beieeeftoa64(buf, n, (void*)ieee);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
leieeeftoa80(char *buf, uint n, void *s)
|
||||
{
|
||||
int i;
|
||||
char *cp;
|
||||
char b[12];
|
||||
|
||||
cp = (char*) s;
|
||||
for(i=0; i<12; i++)
|
||||
b[11-i] = *cp++;
|
||||
return beieeeftoa80(buf, n, b);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue