|  | #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 & (1UL<<31)){ | 
|  | *buf++ = '-'; | 
|  | h &= ~(1UL<<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 & (1UL<<31)){ | 
|  | *buf++ = '-'; | 
|  | h &= ~(1UL<<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); | 
|  | } |