*** empty log message ***
This commit is contained in:
parent
050196400e
commit
f2fdaa05a8
207
ase/awk/misc.c
207
ase/awk/misc.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: misc.c,v 1.2 2006-04-04 16:22:01 bacon Exp $
|
||||
* $Id: misc.c,v 1.3 2006-04-04 16:45:21 bacon Exp $
|
||||
*/
|
||||
|
||||
#include <xp/awk/awk_i.h>
|
||||
@ -13,7 +13,7 @@ xp_long_t xp_awk_strtolong (const xp_char_t* str, int base)
|
||||
{
|
||||
xp_long_t n = 0;
|
||||
const xp_char_t* p;
|
||||
int digit, sign = 0;
|
||||
int digit, negative = 0;
|
||||
|
||||
xp_assert (base < 37);
|
||||
|
||||
@ -23,7 +23,7 @@ xp_long_t xp_awk_strtolong (const xp_char_t* str, int base)
|
||||
{
|
||||
if (*p == XP_CHAR('-'))
|
||||
{
|
||||
sign = ~sign;
|
||||
negative = ~negative;
|
||||
p++;
|
||||
}
|
||||
else if (*p == XP_CHAR('+')) p++;
|
||||
@ -74,12 +74,207 @@ xp_long_t xp_awk_strtolong (const xp_char_t* str, int base)
|
||||
p++;
|
||||
}
|
||||
|
||||
return (sign)? -n: n;
|
||||
return (negative)? -n: n;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* xp_awk_strtoreal is almost a replica of strtod.
|
||||
*
|
||||
* strtod.c --
|
||||
*
|
||||
* Source code for the "strtod" library procedure.
|
||||
*
|
||||
* Copyright (c) 1988-1993 The Regents of the University of California.
|
||||
* Copyright (c) 1994 Sun Microsystems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose and without
|
||||
* fee is hereby granted, provided that the above copyright
|
||||
* notice appear in all copies. The University of California
|
||||
* makes no representations about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without
|
||||
* express or implied warranty.
|
||||
*/
|
||||
|
||||
#define MAX_EXPONENT 511
|
||||
|
||||
xp_real_t xp_awk_strtoreal (const xp_char_t* str)
|
||||
{
|
||||
/* TODO: */
|
||||
return (xp_real_t)0.0;
|
||||
/*
|
||||
* Table giving binary powers of 10. Entry is 10^2^i.
|
||||
* Used to convert decimal exponents into floating-point numbers.
|
||||
*/
|
||||
static xp_real_t powersOf10[] = {
|
||||
10., 100., 1.0e4, 1.0e8, 1.0e16,
|
||||
1.0e32, 1.0e64, 1.0e128, 1.0e256
|
||||
};
|
||||
|
||||
xp_real_t fraction, dblExp, * d;
|
||||
const xp_char_t* p;
|
||||
xp_cint_t c;
|
||||
int exp = 0; // Exponent read from "EX" field.
|
||||
|
||||
/*
|
||||
* Exponent that derives from the fractional part. Under normal
|
||||
* circumstatnces, it is the negative of the number of digits in F.
|
||||
* However, if I is very long, the last digits of I get dropped
|
||||
* (otherwise a long I with a large negative exponent could cause an
|
||||
* unnecessary overflow on I alone). In this case, fracExp is
|
||||
* incremented one for each dropped digit.
|
||||
*/
|
||||
|
||||
int fracExp = 0;
|
||||
int mantSize; // Number of digits in mantissa.
|
||||
int decPt; // Number of mantissa digits BEFORE decimal point
|
||||
const xp_char_t *pExp; // Temporarily holds location of exponent in string.
|
||||
int sign = 0, expSign = 0;
|
||||
|
||||
p = str;
|
||||
|
||||
// Strip off leading blanks and check for a sign.
|
||||
while (xp_isspace(*p)) p++;
|
||||
|
||||
while (*p != XP_CHAR('\0'))
|
||||
{
|
||||
if (*p == XP_CHAR('-'))
|
||||
{
|
||||
sign = ~sign;
|
||||
p++;
|
||||
}
|
||||
else if (*p == XP_CHAR('+')) p++;
|
||||
else break;
|
||||
}
|
||||
|
||||
// Count the number of digits in the mantissa (including the decimal
|
||||
// point), and also locate the decimal point.
|
||||
decPt = -1;
|
||||
for (mantSize = 0; ; mantSize++) {
|
||||
c = *p;
|
||||
if (!xp_isdigit(c)) {
|
||||
if ((c != XP_CHAR('.')) || (decPt >= 0)) break;
|
||||
decPt = mantSize;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now suck up the digits in the mantissa. Use two integers to
|
||||
* collect 9 digits each (this is faster than using floating-point).
|
||||
* If the mantissa has more than 18 digits, ignore the extras, since
|
||||
* they can't affect the value anyway.
|
||||
*/
|
||||
pExp = p;
|
||||
p -= mantSize;
|
||||
if (decPt < 0)
|
||||
{
|
||||
decPt = mantSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
mantSize -= 1; // One of the digits was the point.
|
||||
}
|
||||
if (mantSize > 18)
|
||||
{
|
||||
fracExp = decPt - 18;
|
||||
mantSize = 18;
|
||||
}
|
||||
else
|
||||
{
|
||||
fracExp = decPt - mantSize;
|
||||
}
|
||||
|
||||
if (mantSize == 0)
|
||||
{
|
||||
fraction = 0.0;
|
||||
p = str;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
{
|
||||
int frac1, frac2;
|
||||
frac1 = 0;
|
||||
for ( ; mantSize > 9; mantSize -= 1)
|
||||
{
|
||||
c = *p;
|
||||
p++;
|
||||
if (c == XP_CHAR('.'))
|
||||
{
|
||||
c = *p;
|
||||
p++;
|
||||
}
|
||||
frac1 = 10 * frac1 + (c - XP_CHAR('0'));
|
||||
}
|
||||
frac2 = 0;
|
||||
for (; mantSize > 0; mantSize -= 1) {
|
||||
c = *p;
|
||||
p++;
|
||||
if (c == XP_CHAR('.'))
|
||||
{
|
||||
c = *p;
|
||||
p++;
|
||||
}
|
||||
frac2 = 10*frac2 + (c - XP_CHAR('0'));
|
||||
}
|
||||
fraction = (1.0e9 * frac1) + frac2;
|
||||
}
|
||||
|
||||
// Skim off the exponent.
|
||||
p = pExp;
|
||||
if ((*p == XP_CHAR('E')) || (*p == XP_CHAR('e')))
|
||||
{
|
||||
p++;
|
||||
if (*p == XP_CHAR('-'))
|
||||
{
|
||||
expSign = 1;
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p == XP_CHAR('+')) p++;
|
||||
expSign = 0;
|
||||
}
|
||||
if (!xp_isdigit(*p))
|
||||
{
|
||||
p = pExp;
|
||||
goto done;
|
||||
}
|
||||
while (xp_isdigit(*p))
|
||||
{
|
||||
exp = exp * 10 + (*p - XP_CHAR('0'));
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (expSign) exp = fracExp - exp;
|
||||
else exp = fracExp + exp;
|
||||
|
||||
/*
|
||||
* Generate a floating-point number that represents the exponent.
|
||||
* Do this by processing the exponent one bit at a time to combine
|
||||
* many powers of 2 of 10. Then combine the exponent with the
|
||||
* fraction.
|
||||
*/
|
||||
if (exp < 0)
|
||||
{
|
||||
expSign = 1;
|
||||
exp = -exp;
|
||||
}
|
||||
else expSign = 0;
|
||||
|
||||
if (exp > MAX_EXPONENT) exp = MAX_EXPONENT;
|
||||
|
||||
dblExp = 1.0;
|
||||
|
||||
for (d = powersOf10; exp != 0; exp >>= 1, d++)
|
||||
{
|
||||
if (exp & 01) dblExp *= *d;
|
||||
}
|
||||
|
||||
if (expSign) fraction /= dblExp;
|
||||
else fraction *= dblExp;
|
||||
|
||||
done:
|
||||
return (sign)? -fraction: fraction;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user