Initial import
This commit is contained in:
6232
third_party/dtoa/dtoa.c
vendored
Normal file
6232
third_party/dtoa/dtoa.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
23
third_party/dtoa/dtoa.h
vendored
Normal file
23
third_party/dtoa/dtoa.h
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef COSMOPOLITAN_THIRD_PARTY_DTOA_DTOA_H_
|
||||
#define COSMOPOLITAN_THIRD_PARTY_DTOA_DTOA_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/* see also xdtoa() in //libc/x */
|
||||
double strtod(const char *s00, char **se);
|
||||
char *g_fmt(char *buf /*[32]*/, double x);
|
||||
|
||||
char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
|
||||
char **rve) nodiscard;
|
||||
void freedtoa(char *s);
|
||||
char *dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign,
|
||||
char **rve, char *buf, size_t blen);
|
||||
double plan9_strtod(const char *as, char **aas);
|
||||
|
||||
/* #if defined(TINY) || defined(TINY_STRTOD) */
|
||||
/* #define strtod(X, Y) plan9_strtod(X, Y) */
|
||||
/* #endif */
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_THIRD_PARTY_DTOA_DTOA_H_ */
|
||||
63
third_party/dtoa/dtoa.mk
vendored
Normal file
63
third_party/dtoa/dtoa.mk
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += THIRD_PARTY_DTOA
|
||||
|
||||
THIRD_PARTY_DTOA_ARTIFACTS += THIRD_PARTY_DTOA_A
|
||||
THIRD_PARTY_DTOA = $(THIRD_PARTY_DTOA_A_DEPS) $(THIRD_PARTY_DTOA_A)
|
||||
THIRD_PARTY_DTOA_A = o/$(MODE)/third_party/dtoa/dtoa.a
|
||||
THIRD_PARTY_DTOA_A_FILES := $(wildcard third_party/dtoa/*)
|
||||
THIRD_PARTY_DTOA_A_HDRS = $(filter %.h,$(THIRD_PARTY_DTOA_A_FILES))
|
||||
THIRD_PARTY_DTOA_A_SRCS_S = $(filter %.S,$(THIRD_PARTY_DTOA_A_FILES))
|
||||
THIRD_PARTY_DTOA_A_SRCS_C = $(filter %.c,$(THIRD_PARTY_DTOA_A_FILES))
|
||||
|
||||
THIRD_PARTY_DTOA_A_SRCS = \
|
||||
$(THIRD_PARTY_DTOA_A_SRCS_S) \
|
||||
$(THIRD_PARTY_DTOA_A_SRCS_C)
|
||||
|
||||
THIRD_PARTY_DTOA_A_OBJS = \
|
||||
$(THIRD_PARTY_DTOA_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(THIRD_PARTY_DTOA_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(THIRD_PARTY_DTOA_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
THIRD_PARTY_DTOA_A_CHECKS = \
|
||||
$(THIRD_PARTY_DTOA_A).pkg \
|
||||
$(THIRD_PARTY_DTOA_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
THIRD_PARTY_DTOA_A_DIRECTDEPS = \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_SYSV
|
||||
|
||||
THIRD_PARTY_DTOA_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(THIRD_PARTY_DTOA_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(THIRD_PARTY_DTOA_A): \
|
||||
third_party/dtoa/ \
|
||||
$(THIRD_PARTY_DTOA_A).pkg \
|
||||
$(THIRD_PARTY_DTOA_A_OBJS)
|
||||
|
||||
$(THIRD_PARTY_DTOA_A).pkg: \
|
||||
$(THIRD_PARTY_DTOA_A_OBJS) \
|
||||
$(foreach x,$(THIRD_PARTY_DTOA_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
$(THIRD_PARTY_DTOA_A_OBJS): \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-ansi \
|
||||
$(OLD_CODE) \
|
||||
$(IEEE_MATH) \
|
||||
-ffunction-sections \
|
||||
-fdata-sections
|
||||
|
||||
THIRD_PARTY_DTOA_LIBS = $(foreach x,$(THIRD_PARTY_DTOA_ARTIFACTS),$($(x)))
|
||||
THIRD_PARTY_DTOA_SRCS = $(foreach x,$(THIRD_PARTY_DTOA_ARTIFACTS),$($(x)_SRCS))
|
||||
THIRD_PARTY_DTOA_HDRS = $(foreach x,$(THIRD_PARTY_DTOA_ARTIFACTS),$($(x)_HDRS))
|
||||
THIRD_PARTY_DTOA_CHECKS = $(foreach x,$(THIRD_PARTY_DTOA_ARTIFACTS),$($(x)_CHECKS))
|
||||
THIRD_PARTY_DTOA_OBJS = $(foreach x,$(THIRD_PARTY_DTOA_ARTIFACTS),$($(x)_OBJS))
|
||||
$(THIRD_PARTY_DTOA_OBJS): $(BUILD_FILES) third_party/dtoa/dtoa.mk
|
||||
|
||||
.PHONY: o/$(MODE)/third_party/dtoa
|
||||
o/$(MODE)/third_party/dtoa: $(THIRD_PARTY_DTOA_CHECKS)
|
||||
114
third_party/dtoa/g_fmt.c
vendored
Normal file
114
third_party/dtoa/g_fmt.c
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
#pragma GCC diagnostic ignored "-Wparentheses"
|
||||
#pragma GCC diagnostic ignored "-Wunused-label"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
dtoa (MIT License)\\n\
|
||||
The author of this software is David M. Gay.\\n\
|
||||
Copyright (c) 1991, 2000, 2001 by Lucent Technologies.\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
|
||||
/* clang-format off */
|
||||
/****************************************************************
|
||||
*
|
||||
* The author of this software is David M. Gay.
|
||||
*
|
||||
* Copyright (c) 1991, 1996 by Lucent Technologies.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
/* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
|
||||
* it suffices to declare buf
|
||||
* char buf[32];
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern char *dtoa(double, int, int, int *, int *, char **);
|
||||
extern char *g_fmt(char *, double);
|
||||
extern void freedtoa(char*);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
char *
|
||||
g_fmt(register char *b, double x)
|
||||
{
|
||||
register int i, k;
|
||||
register char *s;
|
||||
int decpt, j, sign;
|
||||
char *b0, *s0, *se;
|
||||
|
||||
b0 = b;
|
||||
#ifdef IGNORE_ZERO_SIGN
|
||||
if (!x) {
|
||||
*b++ = '0';
|
||||
*b = 0;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
s = s0 = dtoa(x, 0, 0, &decpt, &sign, &se);
|
||||
if (sign)
|
||||
*b++ = '-';
|
||||
if (decpt == 9999) /* Infinity or Nan */ {
|
||||
while(*b++ = *s++);
|
||||
goto done0;
|
||||
}
|
||||
if (decpt <= -4 || decpt > se - s + 5) {
|
||||
*b++ = *s++;
|
||||
if (*s) {
|
||||
*b++ = '.';
|
||||
while(*b = *s++)
|
||||
b++;
|
||||
}
|
||||
*b++ = 'e';
|
||||
/* sprintf(b, "%+.2d", decpt - 1); */
|
||||
if (--decpt < 0) {
|
||||
*b++ = '-';
|
||||
decpt = -decpt;
|
||||
}
|
||||
else
|
||||
*b++ = '+';
|
||||
for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10);
|
||||
for(;;) {
|
||||
i = decpt / k;
|
||||
*b++ = i + '0';
|
||||
if (--j <= 0)
|
||||
break;
|
||||
decpt -= i*k;
|
||||
decpt *= 10;
|
||||
}
|
||||
*b = 0;
|
||||
}
|
||||
else if (decpt <= 0) {
|
||||
*b++ = '.';
|
||||
for(; decpt < 0; decpt++)
|
||||
*b++ = '0';
|
||||
while(*b++ = *s++);
|
||||
}
|
||||
else {
|
||||
while(*b = *s++) {
|
||||
b++;
|
||||
if (--decpt == 0 && *s)
|
||||
*b++ = '.';
|
||||
}
|
||||
for(; decpt > 0; decpt--)
|
||||
*b++ = '0';
|
||||
*b = 0;
|
||||
}
|
||||
done0:
|
||||
freedtoa(s0);
|
||||
done:
|
||||
return b0;
|
||||
}
|
||||
532
third_party/dtoa/strtod.c
vendored
Normal file
532
third_party/dtoa/strtod.c
vendored
Normal file
@@ -0,0 +1,532 @@
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/dtoa/dtoa.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Plan 9 strtod().
|
||||
* It's like dtoa but smaller.
|
||||
*/
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
Plan 9 » strtod (MIT)\\n\
|
||||
The authors of this software are Rob Pike and Ken Thompson.\\n\
|
||||
Copyright (c) 2002 by Lucent Technologies.\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
|
||||
#define nelem(a) ARRAYLEN(a)
|
||||
#define ulong unsigned long
|
||||
#define nil NULL
|
||||
#define __NaN() __builtin_nanf("")
|
||||
|
||||
/* clang-format off */
|
||||
/* The authors of this software are Rob Pike and Ken Thompson.
|
||||
* Copyright (c) 2002 by Lucent Technologies.
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static ulong
|
||||
umuldiv(ulong a, ulong b, ulong c)
|
||||
{
|
||||
double d;
|
||||
|
||||
d = ((double)a * (double)b) / (double)c;
|
||||
if(d >= 4294967295.)
|
||||
d = 4294967295.;
|
||||
return (ulong)d;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine will convert to arbitrary precision
|
||||
* floating point entirely in multi-precision fixed.
|
||||
* The answer is the closest floating point number to
|
||||
* the given decimal number. Exactly half way are
|
||||
* rounded ala ieee rules.
|
||||
* Method is to scale input decimal between .500 and .999...
|
||||
* with external power of 2, then binary search for the
|
||||
* closest mantissa to this decimal number.
|
||||
* Nmant is is the required precision. (53 for ieee dp)
|
||||
* Nbits is the max number of bits/word. (must be <= 28)
|
||||
* Prec is calculated - the number of words of fixed mantissa.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
Nbits = 28, /* bits safely represented in a ulong */
|
||||
Nmant = 53, /* bits of precision required */
|
||||
Prec = (Nmant+Nbits+1)/Nbits, /* words of Nbits each to represent mantissa */
|
||||
Sigbit = 1<<(Prec*Nbits-Nmant), /* first significant bit of Prec-th word */
|
||||
Ndig = 1500,
|
||||
One = (ulong)(1<<Nbits),
|
||||
Half = (ulong)(One>>1),
|
||||
Maxe = 310,
|
||||
|
||||
Fsign = 1<<0, /* found - */
|
||||
Fesign = 1<<1, /* found e- */
|
||||
Fdpoint = 1<<2, /* found . */
|
||||
|
||||
S0 = 0, /* _ _S0 +S1 #S2 .S3 */
|
||||
S1, /* _+ #S2 .S3 */
|
||||
S2, /* _+# #S2 .S4 eS5 */
|
||||
S3, /* _+. #S4 */
|
||||
S4, /* _+#.# #S4 eS5 */
|
||||
S5, /* _+#.#e +S6 #S7 */
|
||||
S6, /* _+#.#e+ #S7 */
|
||||
S7 /* _+#.#e+# #S7 */
|
||||
};
|
||||
|
||||
static int xcmp(char*, char*);
|
||||
static int fpcmp(char*, ulong*);
|
||||
static void frnorm(ulong*);
|
||||
static void divascii(char*, int*, int*, int*);
|
||||
static void mulascii(char*, int*, int*, int*);
|
||||
|
||||
typedef struct Tab Tab;
|
||||
struct Tab
|
||||
{
|
||||
int bp;
|
||||
int siz;
|
||||
char* cmp;
|
||||
};
|
||||
|
||||
double
|
||||
plan9_strtod(const char *as, char **aas)
|
||||
{
|
||||
int na, ex, dp, bp, c, i, flag, state;
|
||||
ulong low[Prec], hig[Prec], mid[Prec];
|
||||
double d;
|
||||
char *s, a[Ndig];
|
||||
|
||||
flag = 0; /* Fsign, Fesign, Fdpoint */
|
||||
na = 0; /* number of digits of a[] */
|
||||
dp = 0; /* na of decimal point */
|
||||
ex = 0; /* exonent */
|
||||
|
||||
state = S0;
|
||||
for(s=(char*)as;; s++) {
|
||||
c = *s;
|
||||
if(c >= '0' && c <= '9') {
|
||||
switch(state) {
|
||||
case S0:
|
||||
case S1:
|
||||
case S2:
|
||||
state = S2;
|
||||
break;
|
||||
case S3:
|
||||
case S4:
|
||||
state = S4;
|
||||
break;
|
||||
|
||||
case S5:
|
||||
case S6:
|
||||
case S7:
|
||||
state = S7;
|
||||
ex = ex*10 + (c-'0');
|
||||
continue;
|
||||
}
|
||||
if(na == 0 && c == '0') {
|
||||
dp--;
|
||||
continue;
|
||||
}
|
||||
if(na < Ndig-50)
|
||||
a[na++] = c;
|
||||
continue;
|
||||
}
|
||||
switch(c) {
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\v':
|
||||
case '\f':
|
||||
case '\r':
|
||||
case ' ':
|
||||
if(state == S0)
|
||||
continue;
|
||||
break;
|
||||
case '-':
|
||||
if(state == S0)
|
||||
flag |= Fsign;
|
||||
else
|
||||
flag |= Fesign;
|
||||
case '+':
|
||||
if(state == S0)
|
||||
state = S1;
|
||||
else
|
||||
if(state == S5)
|
||||
state = S6;
|
||||
else
|
||||
break; /* syntax */
|
||||
continue;
|
||||
case '.':
|
||||
flag |= Fdpoint;
|
||||
dp = na;
|
||||
if(state == S0 || state == S1) {
|
||||
state = S3;
|
||||
continue;
|
||||
}
|
||||
if(state == S2) {
|
||||
state = S4;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
if(state == S2 || state == S4) {
|
||||
state = S5;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* clean up return char-pointer
|
||||
*/
|
||||
switch(state) {
|
||||
case S0:
|
||||
if(strcasecmp(s, "nan") == 0) {
|
||||
if(aas != nil)
|
||||
*aas = s+3;
|
||||
goto retnan;
|
||||
}
|
||||
case S1:
|
||||
if(strcasecmp(s, "infinity") == 0) {
|
||||
if(aas != nil)
|
||||
*aas = s+8;
|
||||
goto retinf;
|
||||
}
|
||||
if(strcasecmp(s, "inf") == 0) {
|
||||
if(aas != nil)
|
||||
*aas = s+3;
|
||||
goto retinf;
|
||||
}
|
||||
case S3:
|
||||
if(aas != nil)
|
||||
*aas = (char*)as;
|
||||
goto ret0; /* no digits found */
|
||||
case S6:
|
||||
s--; /* back over +- */
|
||||
case S5:
|
||||
s--; /* back over e */
|
||||
break;
|
||||
}
|
||||
if(aas != nil)
|
||||
*aas = s;
|
||||
|
||||
if(flag & Fdpoint)
|
||||
while(na > 0 && a[na-1] == '0')
|
||||
na--;
|
||||
if(na == 0)
|
||||
goto ret0; /* zero */
|
||||
a[na] = 0;
|
||||
if(!(flag & Fdpoint))
|
||||
dp = na;
|
||||
if(flag & Fesign)
|
||||
ex = -ex;
|
||||
dp += ex;
|
||||
if(dp < -Maxe){
|
||||
erange();
|
||||
goto ret0; /* underflow by exp */
|
||||
} else
|
||||
if(dp > +Maxe)
|
||||
goto retinf; /* overflow by exp */
|
||||
|
||||
/*
|
||||
* normalize the decimal ascii number
|
||||
* to range .[5-9][0-9]* e0
|
||||
*/
|
||||
bp = 0; /* binary exponent */
|
||||
while(dp > 0)
|
||||
divascii(a, &na, &dp, &bp);
|
||||
while(dp < 0 || a[0] < '5')
|
||||
mulascii(a, &na, &dp, &bp);
|
||||
|
||||
/* close approx by naïve conversion */
|
||||
mid[0] = 0;
|
||||
mid[1] = 1;
|
||||
for(i=0; (c=a[i]) != '\0'; i++) {
|
||||
mid[0] = mid[0]*10 + (c-'0');
|
||||
mid[1] = mid[1]*10;
|
||||
if(i >= 8)
|
||||
break;
|
||||
}
|
||||
low[0] = umuldiv(mid[0], One, mid[1]);
|
||||
hig[0] = umuldiv(mid[0]+1, One, mid[1]);
|
||||
for(i=1; i<Prec; i++) {
|
||||
low[i] = 0;
|
||||
hig[i] = One-1;
|
||||
}
|
||||
|
||||
/* binary search for closest mantissa */
|
||||
for(;;) {
|
||||
/* mid = (hig + low) / 2 */
|
||||
c = 0;
|
||||
for(i=0; i<Prec; i++) {
|
||||
mid[i] = hig[i] + low[i];
|
||||
if(c)
|
||||
mid[i] += One;
|
||||
c = mid[i] & 1;
|
||||
mid[i] >>= 1;
|
||||
}
|
||||
frnorm(mid);
|
||||
|
||||
/* compare */
|
||||
c = fpcmp(a, mid);
|
||||
if(c > 0) {
|
||||
c = 1;
|
||||
for(i=0; i<Prec; i++)
|
||||
if(low[i] != mid[i]) {
|
||||
c = 0;
|
||||
low[i] = mid[i];
|
||||
}
|
||||
if(c)
|
||||
break; /* between mid and hig */
|
||||
continue;
|
||||
}
|
||||
if(c < 0) {
|
||||
for(i=0; i<Prec; i++)
|
||||
hig[i] = mid[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
/* only hard part is if even/odd roundings wants to go up */
|
||||
c = mid[Prec-1] & (Sigbit-1);
|
||||
if(c == Sigbit/2 && (mid[Prec-1]&Sigbit) == 0)
|
||||
mid[Prec-1] -= c;
|
||||
break; /* exactly mid */
|
||||
}
|
||||
|
||||
/* normal rounding applies */
|
||||
c = mid[Prec-1] & (Sigbit-1);
|
||||
mid[Prec-1] -= c;
|
||||
if(c >= Sigbit/2) {
|
||||
mid[Prec-1] += Sigbit;
|
||||
frnorm(mid);
|
||||
}
|
||||
goto out;
|
||||
|
||||
ret0:
|
||||
return 0;
|
||||
|
||||
retnan:
|
||||
return __NaN();
|
||||
|
||||
retinf:
|
||||
/*
|
||||
* Unix strtod requires these. Plan 9 would return Inf(0) or Inf(-1). */
|
||||
erange();
|
||||
if(flag & Fsign)
|
||||
return -HUGE_VAL;
|
||||
return HUGE_VAL;
|
||||
|
||||
out:
|
||||
d = 0;
|
||||
for(i=0; i<Prec; i++)
|
||||
d = d*One + mid[i];
|
||||
if(flag & Fsign)
|
||||
d = -d;
|
||||
d = ldexp(d, bp - Prec*Nbits);
|
||||
if(d == 0){ /* underflow */
|
||||
erange();
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
static void
|
||||
frnorm(ulong *f)
|
||||
{
|
||||
int i, c;
|
||||
|
||||
c = 0;
|
||||
for(i=Prec-1; i>0; i--) {
|
||||
f[i] += c;
|
||||
c = f[i] >> Nbits;
|
||||
f[i] &= One-1;
|
||||
}
|
||||
f[0] += c;
|
||||
}
|
||||
|
||||
static int
|
||||
fpcmp(char *a, ulong* f)
|
||||
{
|
||||
ulong tf[Prec];
|
||||
int i, d, c;
|
||||
|
||||
for(i=0; i<Prec; i++)
|
||||
tf[i] = f[i];
|
||||
|
||||
for(;;) {
|
||||
/* tf *= 10 */
|
||||
for(i=0; i<Prec; i++)
|
||||
tf[i] = tf[i]*10;
|
||||
frnorm(tf);
|
||||
d = (tf[0] >> Nbits) + '0';
|
||||
tf[0] &= One-1;
|
||||
|
||||
/* compare next digit */
|
||||
c = *a;
|
||||
if(c == 0) {
|
||||
if('0' < d)
|
||||
return -1;
|
||||
if(tf[0] != 0)
|
||||
goto cont;
|
||||
for(i=1; i<Prec; i++)
|
||||
if(tf[i] != 0)
|
||||
goto cont;
|
||||
return 0;
|
||||
}
|
||||
if(c > d)
|
||||
return +1;
|
||||
if(c < d)
|
||||
return -1;
|
||||
a++;
|
||||
cont:;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
divby(char *a, int *na, int b)
|
||||
{
|
||||
int n, c;
|
||||
char *p;
|
||||
|
||||
p = a;
|
||||
n = 0;
|
||||
while(n>>b == 0) {
|
||||
c = *a++;
|
||||
if(c == 0) {
|
||||
while(n) {
|
||||
c = n*10;
|
||||
if(c>>b)
|
||||
break;
|
||||
n = c;
|
||||
}
|
||||
goto xx;
|
||||
}
|
||||
n = n*10 + c-'0';
|
||||
(*na)--;
|
||||
}
|
||||
for(;;) {
|
||||
c = n>>b;
|
||||
n -= c<<b;
|
||||
*p++ = c + '0';
|
||||
c = *a++;
|
||||
if(c == 0)
|
||||
break;
|
||||
n = n*10 + c-'0';
|
||||
}
|
||||
(*na)++;
|
||||
xx:
|
||||
while(n) {
|
||||
n = n*10;
|
||||
c = n>>b;
|
||||
n -= c<<b;
|
||||
*p++ = c + '0';
|
||||
(*na)++;
|
||||
}
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
static Tab tab1[] =
|
||||
{
|
||||
{ 1, 0, ""},
|
||||
{ 3, 1, "7"},
|
||||
{ 6, 2, "63"},
|
||||
{ 9, 3, "511"},
|
||||
{13, 4, "8191"},
|
||||
{16, 5, "65535"},
|
||||
{19, 6, "524287"},
|
||||
{23, 7, "8388607"},
|
||||
{26, 8, "67108863"},
|
||||
{27, 9, "134217727"},
|
||||
};
|
||||
|
||||
static void
|
||||
divascii(char *a, int *na, int *dp, int *bp)
|
||||
{
|
||||
int b, d;
|
||||
Tab *t;
|
||||
|
||||
d = *dp;
|
||||
if(d >= (int)(nelem(tab1)))
|
||||
d = (int)(nelem(tab1))-1;
|
||||
t = tab1 + d;
|
||||
b = t->bp;
|
||||
if(memcmp(a, t->cmp, t->siz) > 0)
|
||||
d--;
|
||||
*dp -= d;
|
||||
*bp += b;
|
||||
divby(a, na, b);
|
||||
}
|
||||
|
||||
static void
|
||||
mulby(char *a, char *p, char *q, int b)
|
||||
{
|
||||
int n, c;
|
||||
|
||||
n = 0;
|
||||
*p = 0;
|
||||
for(;;) {
|
||||
q--;
|
||||
if(q < a)
|
||||
break;
|
||||
c = *q - '0';
|
||||
c = (c<<b) + n;
|
||||
n = c/10;
|
||||
c -= n*10;
|
||||
p--;
|
||||
*p = c + '0';
|
||||
}
|
||||
while(n) {
|
||||
c = n;
|
||||
n = c/10;
|
||||
c -= n*10;
|
||||
p--;
|
||||
*p = c + '0';
|
||||
}
|
||||
}
|
||||
|
||||
static Tab tab2[] =
|
||||
{
|
||||
{ 1, 1, ""}, /* dp = 0-0 */
|
||||
{ 3, 3, "125"},
|
||||
{ 6, 5, "15625"},
|
||||
{ 9, 7, "1953125"},
|
||||
{13, 10, "1220703125"},
|
||||
{16, 12, "152587890625"},
|
||||
{19, 14, "19073486328125"},
|
||||
{23, 17, "11920928955078125"},
|
||||
{26, 19, "1490116119384765625"},
|
||||
{27, 19, "7450580596923828125"}, /* dp 8-9 */
|
||||
};
|
||||
|
||||
static void
|
||||
mulascii(char *a, int *na, int *dp, int *bp)
|
||||
{
|
||||
char *p;
|
||||
int d, b;
|
||||
Tab *t;
|
||||
|
||||
d = -*dp;
|
||||
if(d >= (int)(nelem(tab2)))
|
||||
d = (int)(nelem(tab2))-1;
|
||||
t = tab2 + d;
|
||||
b = t->bp;
|
||||
if(memcmp(a, t->cmp, t->siz) < 0)
|
||||
d--;
|
||||
p = a + *na;
|
||||
*bp -= b;
|
||||
*dp += d;
|
||||
*na += d;
|
||||
mulby(a, p+d, p, b);
|
||||
}
|
||||
Reference in New Issue
Block a user