119 lines
3.5 KiB
C
119 lines
3.5 KiB
C
/* _Stoxflt function */
|
|
#include "xmath.h"
|
|
#include <ctype.h>
|
|
#include <locale.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
_C_STD_BEGIN
|
|
#if !defined(MRTDLL)
|
|
_C_LIB_DECL
|
|
#endif /* defined(MRTDLL) */
|
|
|
|
#define BASE 16 /* hexadecimal */
|
|
#define NDIG 7 /* hexadecimal digits per long element */
|
|
#define MAXSIG (5 * NDIG) /* maximum significant digits to keep */
|
|
|
|
_CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Stoxflt(const char *s0, const char *s,
|
|
char **endptr, long lo[], int maxsig)
|
|
{ /* convert string to array of long plus exponent */
|
|
char buf[MAXSIG + 1]; /* worst case, with room for rounding digit */
|
|
int nsig; /* number of significant digits seen */
|
|
int seen; /* any valid field characters seen */
|
|
int word = 0; /* current long word to fill */
|
|
|
|
const char *pd;
|
|
static const char digits[] = "0123456789abcdefABCDEF";
|
|
static const char vals[] =
|
|
{ /* values of hex digits */
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
10, 11, 12, 13, 14, 15};
|
|
|
|
maxsig *= NDIG; /* convert word count to digit count */
|
|
if (MAXSIG < maxsig)
|
|
maxsig = MAXSIG; /* protect against bad call */
|
|
|
|
lo[0] = 0; /* power of ten exponent */
|
|
lo[1] = 0; /* first NDIG-digit word of fraction */
|
|
|
|
for (seen = 0; *s == '0'; ++s, seen = 1)
|
|
; /* strip leading zeros */
|
|
for (nsig = 0; (pd = (char *)memchr(&digits[0], *s, 22)) != 0;
|
|
++s, seen = 1)
|
|
if (nsig <= maxsig)
|
|
buf[nsig++] = vals[pd - digits]; /* accumulate a digit */
|
|
else
|
|
++lo[0]; /* too many digits, just scale exponent */
|
|
|
|
if (*s == localeconv()->decimal_point[0])
|
|
++s;
|
|
if (nsig == 0)
|
|
for (; *s == '0'; ++s, seen = 1)
|
|
--lo[0]; /* strip zeros after point */
|
|
for (; (pd = (char *)memchr(&digits[0], *s, 22)) != 0; ++s, seen = 1)
|
|
if (nsig <= maxsig)
|
|
{ /* accumulate a fraction digit */
|
|
buf[nsig++] = vals[pd - digits];
|
|
--lo[0];
|
|
}
|
|
|
|
if (maxsig < nsig)
|
|
{ /* discard excess digit after rounding up */
|
|
unsigned int ms = maxsig; /* to quiet warnings */
|
|
|
|
if (BASE / 2 <= buf[ms])
|
|
++buf[ms - 1]; /* okay if digit becomes BASE */
|
|
nsig = maxsig;
|
|
++lo[0];
|
|
}
|
|
for (; 0 < nsig && buf[nsig - 1] == '\0'; --nsig)
|
|
++lo[0]; /* discard trailing zeros */
|
|
if (nsig == 0)
|
|
buf[nsig++] = '\0'; /* ensure at least one digit */
|
|
lo[0] <<= 2; /* change hex exponent to binary exponent */
|
|
|
|
if (seen)
|
|
{ /* convert digit sequence to words */
|
|
int bufidx = 0; /* next digit in buffer */
|
|
int wordidx = NDIG - nsig % NDIG; /* next digit in word (% NDIG) */
|
|
|
|
word = wordidx % NDIG == 0 ? 0 : 1;
|
|
for (; bufidx < nsig; ++wordidx, ++bufidx)
|
|
if (wordidx % NDIG == 0)
|
|
lo[++word] = buf[bufidx];
|
|
else
|
|
lo[word] = lo[word] * BASE + buf[bufidx];
|
|
|
|
if (*s == 'p' || *s == 'P')
|
|
{ /* parse exponent */
|
|
const char *ssav = s;
|
|
const char esign = *++s == '+' || *s == '-' ? *s++ : '+';
|
|
int eseen = 0;
|
|
long lexp = 0;
|
|
|
|
for (; isdigit((unsigned char)*s); ++s, eseen = 1)
|
|
if (lexp < 100000000) /* else overflow */
|
|
lexp = lexp * 10 + (unsigned char)*s - '0';
|
|
if (esign == '-')
|
|
lexp = -lexp;
|
|
lo[0] += lexp;
|
|
if (!eseen)
|
|
s = ssav; /* roll back if incomplete exponent */
|
|
}
|
|
}
|
|
|
|
if (!seen)
|
|
word = 0; /* return zero if bad parse */
|
|
if (endptr)
|
|
*endptr = (char *)(seen ? s : s0); /* roll back if bad parse */
|
|
return (word);
|
|
}
|
|
#if !defined(MRTDLL)
|
|
_END_C_LIB_DECL
|
|
#endif /* !defined(MRTDLL) */
|
|
_C_STD_END
|
|
|
|
/*
|
|
* Copyright (c) 1992-2012 by P.J. Plauger. ALL RIGHTS RESERVED.
|
|
* Consult your license regarding permissions and restrictions.
|
|
V6.00:0009 */
|