summaryrefslogtreecommitdiff
path: root/src/old/c/mpatof.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/old/c/mpatof.c')
-rw-r--r--src/old/c/mpatof.c342
1 files changed, 0 insertions, 342 deletions
diff --git a/src/old/c/mpatof.c b/src/old/c/mpatof.c
deleted file mode 100644
index 07bcf4a27..000000000
--- a/src/old/c/mpatof.c
+++ /dev/null
@@ -1,342 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-
-int mpatof(char*, double*);
-int mpatov(char *s, vlong *v);
-
-enum
-{
- Mpscale = 29, /* safely smaller than bits in a long */
- Mpprec = 36, /* Mpscale*Mpprec sb > largest fp exp */
- Mpbase = 1L<<Mpscale,
-};
-
-typedef
-struct
-{
- long a[Mpprec];
- char ovf;
-} Mp;
-
-static void mpint(Mp*, int);
-static void mppow(Mp*, int, int);
-static void mpmul(Mp*, int);
-static void mpadd(Mp*, Mp*);
-static int mptof(Mp*, double*);
-
-/*
- * convert a string, s, to floating in *d
- * return conversion overflow.
- * required syntax is [+-]d*[.]d*[e[+-]d*]
- */
-int
-mpatof(char *s, double *d)
-{
- Mp a, b;
- int dp, c, f, ef, ex, zer;
- double d1, d2;
-
- dp = 0; /* digits after decimal point */
- f = 0; /* sign */
- ex = 0; /* exponent */
- zer = 1; /* zero */
- memset(&a, 0, sizeof(a));
- for(;;) {
- switch(c = *s++) {
- default:
- goto bad;
- case '-':
- f = 1;
- case ' ':
- case '\t':
- case '+':
- continue;
- case '.':
- dp = 1;
- continue;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- zer = 0;
- case '0':
- mpint(&b, c-'0');
- mpmul(&a, 10);
- mpadd(&a, &b);
- if(dp)
- dp++;
- continue;
- case 'E':
- case 'e':
- ex = 0;
- ef = 0;
- for(;;) {
- c = *s++;
- if(c == '+' || c == ' ' || c == '\t')
- continue;
- if(c == '-') {
- ef = 1;
- continue;
- }
- if(c >= '0' && c <= '9') {
- ex = ex*10 + (c-'0');
- continue;
- }
- break;
- }
- if(ef)
- ex = -ex;
- case 0:
- break;
- }
- break;
- }
- if(a.ovf)
- goto bad;
- if(zer) {
- *d = 0;
- return 0;
- }
- if(dp)
- dp--;
- dp -= ex;
- if(dp > 0) {
- /*
- * must divide by 10**dp
- */
- if(mptof(&a, &d1))
- goto bad;
-
- /*
- * trial exponent of 8**dp
- * 8 (being between 5 and 10)
- * should pick up all underflows
- * in the division of 5**dp.
- */
- d2 = frexp(d1, &ex);
- d2 = ldexp(d2, ex-3*dp);
- if(d2 == 0)
- goto bad;
-
- /*
- * decompose each 10 into 5*2.
- * create 5**dp in fixed point
- * and then play with the exponent
- * for the remaining 2**dp.
- * note that 5**dp will overflow
- * with as few as 134 input digits.
- */
- mpint(&a, 1);
- mppow(&a, 5, dp);
- if(mptof(&a, &d2))
- goto bad;
- d1 = frexp(d1/d2, &ex);
- d1 = ldexp(d1, ex-dp);
- if(d1 == 0)
- goto bad;
- } else {
- /*
- * must multiply by 10**|dp| --
- * just do it in fixed point.
- */
- mppow(&a, 10, -dp);
- if(mptof(&a, &d1))
- goto bad;
- }
- if(f)
- d1 = -d1;
- *d = d1;
- return 0;
-
-bad:
- return 1;
-}
-
-/*
- * convert a to floating in *d
- * return conversion overflow
- */
-static int
-mptof(Mp *a, double *d)
-{
- double f, g;
- long x, *a1;
- int i;
-
- if(a->ovf)
- return 1;
- a1 = a->a;
- f = ldexp(*a1++, 0);
- for(i=Mpscale; i<Mpprec*Mpscale; i+=Mpscale)
- if(x = *a1++) {
- g = ldexp(x, i);
- /*
- * NOTE: the test (g==0) is plan9
- * specific. ansi compliant overflow
- * is signaled by HUGE and errno==ERANGE.
- * change this for your particular ldexp.
- */
- if(g == 0)
- return 1;
- f += g; /* this could bomb! */
- }
- *d = f;
- return 0;
-}
-
-/*
- * return a += b
- */
-static void
-mpadd(Mp *a, Mp *b)
-{
- int i, c;
- long x, *a1, *b1;
-
- if(b->ovf)
- a->ovf = 1;
- if(a->ovf)
- return;
- c = 0;
- a1 = a->a;
- b1 = b->a;
- for(i=0; i<Mpprec; i++) {
- x = *a1 + *b1++ + c;
- c = 0;
- if(x >= Mpbase) {
- x -= Mpbase;
- c = 1;
- }
- *a1++ = x;
- }
- a->ovf = c;
-}
-
-/*
- * return a = c
- */
-static void
-mpint(Mp *a, int c)
-{
-
- memset(a, 0, sizeof(*a));
- a->a[0] = c;
-}
-
-/*
- * return a *= c
- */
-static void
-mpmul(Mp *a, int c)
-{
- Mp p;
- int b;
- memmove(&p, a, sizeof(p));
- if(!(c & 1))
- memset(a, 0, sizeof(*a));
- c &= ~1;
- for(b=2; c; b<<=1) {
- mpadd(&p, &p);
- if(c & b) {
- mpadd(a, &p);
- c &= ~b;
- }
- }
-}
-
-/*
- * return a *= b**e
- */
-static void
-mppow(Mp *a, int b, int e)
-{
- int b1;
-
- b1 = b*b;
- b1 = b1*b1;
- while(e >= 4) {
- mpmul(a, b1);
- e -= 4;
- if(a->ovf)
- return;
- }
- while(e > 0) {
- mpmul(a, b);
- e--;
- }
-}
-
-/*
- * convert a string, s, to vlong in *v
- * return conversion overflow.
- * required syntax is [0[x]]d*
- */
-int
-mpatov(char *s, vlong *v)
-{
- vlong n, nn;
- int c;
- n = 0;
- c = *s;
- if(c == '0')
- goto oct;
- while(c = *s++) {
- if(c >= '0' && c <= '9')
- nn = n*10 + c-'0';
- else
- goto bad;
- if(n < 0 && nn >= 0)
- goto bad;
- n = nn;
- }
- goto out;
-oct:
- s++;
- c = *s;
- if(c == 'x' || c == 'X')
- goto hex;
- while(c = *s++) {
- if(c >= '0' || c <= '7')
- nn = n*8 + c-'0';
- else
- goto bad;
- if(n < 0 && nn >= 0)
- goto bad;
- n = nn;
- }
- goto out;
-hex:
- s++;
- while(c = *s++) {
- if(c >= '0' && c <= '9')
- c += 0-'0';
- else
- if(c >= 'a' && c <= 'f')
- c += 10-'a';
- else
- if(c >= 'A' && c <= 'F')
- c += 10-'A';
- else
- goto bad;
- nn = n*16 + c;
- if(n < 0 && nn >= 0)
- goto bad;
- n = nn;
- }
-out:
- *v = n;
- return 0;
-
-bad:
- *v = ~0;
- return 1;
-}