Added strtod.c, use it in atof
This commit is contained in:
parent
2cb7fcf861
commit
ebfc4a15a4
3 changed files with 100 additions and 71 deletions
|
@ -1,6 +1,7 @@
|
||||||
tail_cc.2g.a
|
tail_cc.2g.a
|
||||||
abs.c
|
abs.c
|
||||||
atof.c
|
atof.c
|
||||||
|
strtod.c
|
||||||
atoi.c
|
atoi.c
|
||||||
atol.c
|
atol.c
|
||||||
bcmp.c
|
bcmp.c
|
||||||
|
|
|
@ -1,81 +1,12 @@
|
||||||
/* $Header$ */
|
/* $Header$ */
|
||||||
#ifndef NOFLOAT
|
#ifndef NOFLOAT
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
extern double ldexp();
|
extern double strtod();
|
||||||
|
|
||||||
double
|
double
|
||||||
atof(p)
|
atof(p)
|
||||||
register char *p;
|
register char *p;
|
||||||
{
|
{
|
||||||
register int c;
|
return strtod(p, (char **) 0);
|
||||||
int exp = 0, sign = 1, expsign = 0;
|
|
||||||
double fl;
|
|
||||||
double big = (double)(1L << 30) * (1L << 22);
|
|
||||||
|
|
||||||
while (isspace(*p)) p++;
|
|
||||||
c = *p;
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
case '-':
|
|
||||||
sign = -1;
|
|
||||||
case '+':
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
fl = 0.0;
|
|
||||||
while (isdigit(c = *p++)) {
|
|
||||||
if (fl < big)
|
|
||||||
fl = 10.0 * fl + (double)(c - '0');
|
|
||||||
else
|
|
||||||
exp++;
|
|
||||||
}
|
|
||||||
if (c == '.') {
|
|
||||||
while (isdigit(c = *p++)) {
|
|
||||||
if (fl < big) {
|
|
||||||
fl = 10.0 * fl + (double) (c - '0');
|
|
||||||
exp--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fl == 0) return 0;
|
|
||||||
if (c == 'E' || c == 'e') {
|
|
||||||
int exp1 = 0;
|
|
||||||
int sign = 1;
|
|
||||||
|
|
||||||
switch (*p) {
|
|
||||||
case '-':
|
|
||||||
sign = -1;
|
|
||||||
case '+':
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
while (isdigit(c = *p++)) {
|
|
||||||
exp1 = 10 * exp1 + c - '0';
|
|
||||||
}
|
|
||||||
exp += sign * exp1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp < 0) {
|
|
||||||
expsign = 1;
|
|
||||||
exp = -exp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp != 0) {
|
|
||||||
int oldexp = exp;
|
|
||||||
double exp5 = 5.0;
|
|
||||||
double correction = 1.0;
|
|
||||||
|
|
||||||
while (exp) {
|
|
||||||
if (exp % 2) correction *= exp5;
|
|
||||||
exp /= 2;
|
|
||||||
if (exp != 0) exp5 *= exp5;
|
|
||||||
}
|
|
||||||
if (expsign) fl = fl / correction;
|
|
||||||
else fl = fl * correction;
|
|
||||||
|
|
||||||
fl = ldexp(fl, expsign ? -oldexp : oldexp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sign * fl;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
97
lang/cem/libcc/gen/strtod.c
Normal file
97
lang/cem/libcc/gen/strtod.c
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/* $Header$ */
|
||||||
|
#ifndef NOFLOAT
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
extern double ldexp();
|
||||||
|
|
||||||
|
#define MAX (0x7fffffffL/10)
|
||||||
|
|
||||||
|
double
|
||||||
|
strtod(p, pp)
|
||||||
|
register char *p;
|
||||||
|
char **pp;
|
||||||
|
{
|
||||||
|
register int c;
|
||||||
|
int exp = 0, sign = 1, expsign = 0;
|
||||||
|
double fl;
|
||||||
|
long lowl = 0, highl = 0, pos = 1;
|
||||||
|
int dotseen = 0;
|
||||||
|
int digitseen = 0;
|
||||||
|
|
||||||
|
if (pp) *pp = p;
|
||||||
|
while (isspace(*p)) p++;
|
||||||
|
c = *p;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case '-':
|
||||||
|
sign = -1;
|
||||||
|
case '+':
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (isdigit(c = *p++) || (c == '.' && ! dotseen++)) {
|
||||||
|
if (c == '.') continue;
|
||||||
|
digit_seen = 1;
|
||||||
|
if (highl < MAX) {
|
||||||
|
highl = (highl << 3) + (highl << 1) + (c - '0');
|
||||||
|
}
|
||||||
|
else if (pos < MAX) {
|
||||||
|
pos = (pos << 3) + (pos << 1);
|
||||||
|
lowl = (lowl << 3) + (lowl << 1) + (c - '0');
|
||||||
|
}
|
||||||
|
else exp++;
|
||||||
|
if (dotseen) exp--;
|
||||||
|
}
|
||||||
|
if (! digit_seen) return 0.0;
|
||||||
|
fl = highl;
|
||||||
|
if (pos > 1) {
|
||||||
|
fl = pos * fl + lowl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pp) *pp = p-1;
|
||||||
|
|
||||||
|
if (c == 'E' || c == 'e') {
|
||||||
|
int exp1 = 0;
|
||||||
|
int sign = 1;
|
||||||
|
|
||||||
|
switch (*p) {
|
||||||
|
case '-':
|
||||||
|
sign = -1;
|
||||||
|
case '+':
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
if (isdigit(c = *p)) {
|
||||||
|
do {
|
||||||
|
exp1 = 10 * exp1 + c - '0';
|
||||||
|
} while (isdigit(c = *++p));
|
||||||
|
if (pp) *pp = p;
|
||||||
|
}
|
||||||
|
exp += sign * exp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fl == 0.0) return 0.0;
|
||||||
|
|
||||||
|
if (exp < 0) {
|
||||||
|
expsign = 1;
|
||||||
|
exp = -exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp != 0) {
|
||||||
|
int oldexp = exp;
|
||||||
|
double exp5 = 5.0;
|
||||||
|
double correction = 1.0;
|
||||||
|
|
||||||
|
while (exp) {
|
||||||
|
if (exp % 2) correction *= exp5;
|
||||||
|
exp /= 2;
|
||||||
|
if (exp != 0) exp5 *= exp5;
|
||||||
|
}
|
||||||
|
if (expsign) fl = fl / correction;
|
||||||
|
else fl = fl * correction;
|
||||||
|
|
||||||
|
fl = ldexp(fl, expsign ? -oldexp : oldexp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sign * fl;
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Add table
Reference in a new issue