95 lines
1.5 KiB
C
95 lines
1.5 KiB
C
/*
|
|
* C library - ascii to floating
|
|
*/
|
|
|
|
#include <ctype.h>
|
|
#include <values.h>
|
|
|
|
extern double ldexp();
|
|
|
|
double
|
|
atof(p)
|
|
register char *p;
|
|
{
|
|
register int c, eexp, exp, neg, negexp, bexp;
|
|
double fl, flexp, exp5;
|
|
|
|
neg = 1;
|
|
while(isspace(*p))
|
|
++p;
|
|
if(*p == '-') {
|
|
++p;
|
|
neg = -1;
|
|
}
|
|
else if(*p == '+')
|
|
++p;
|
|
|
|
exp = 0;
|
|
fl = 0;
|
|
while((c = *p++), isdigit(c))
|
|
if(fl < 2.0 * MAXPOWTWO)
|
|
fl = 10*fl + (c-'0');
|
|
else
|
|
exp++;
|
|
|
|
if(c == '.')
|
|
while((c = *p++), isdigit(c))
|
|
if(fl < 2.0 * MAXPOWTWO) {
|
|
fl = 10*fl + (c-'0');
|
|
exp--;
|
|
}
|
|
|
|
negexp = 1;
|
|
eexp = 0;
|
|
if((c == 'E') || (c == 'e')) {
|
|
if((c = *p++) == '+')
|
|
;
|
|
else if(c == '-')
|
|
negexp = -1;
|
|
else
|
|
--p;
|
|
|
|
while((c = *p++), isdigit(c))
|
|
eexp = 10*eexp + (c-'0');
|
|
|
|
if(negexp < 0)
|
|
eexp = -eexp;
|
|
exp = exp + eexp;
|
|
}
|
|
|
|
negexp = 1;
|
|
if(exp < 0) {
|
|
negexp = -1;
|
|
exp = -exp;
|
|
}
|
|
|
|
/*
|
|
* The following computation is done in two stages,
|
|
* first accumulating powers of 5, then jamming powers of 2,
|
|
* to avoid underflow in situations like the following (for
|
|
* the DEC representation): 1.2345678901234567890e-37,
|
|
* where exp would be about (-37 + -18) = -55, and the
|
|
* value 10^(-55) can't be represented, but 5^(-55) can
|
|
* be represented, and then 2^(-55) jammed via ldexp().
|
|
*/
|
|
flexp = 1;
|
|
exp5 = 5;
|
|
bexp = exp;
|
|
while(1) {
|
|
if(exp&01)
|
|
flexp *= exp5;
|
|
exp >>= 1;
|
|
if(exp == 0)
|
|
break;
|
|
exp5 *= exp5;
|
|
}
|
|
if(negexp < 0)
|
|
fl /= flexp;
|
|
else
|
|
fl *= flexp;
|
|
fl = ldexp(fl, negexp*bexp);
|
|
if(neg < 0)
|
|
fl = -fl;
|
|
return(fl);
|
|
}
|