1 /* The authors of this software are Rob Pike and Ken Thompson.
2 * Copyright (c) 2002 by Lucent Technologies.
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose without fee is hereby granted, provided that this entire notice
5 * is included in all copies of any software which is or includes a copy
6 * or modification of this software and in all copies of the supporting
7 * documentation for such software.
8 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
9 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
10 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
11 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
14 #include "mupdf/fitz.h"
24 #define INFINITY (DBL_MAX+DBL_MAX)
27 #define NAN (INFINITY-INFINITY)
32 typedef unsigned long ulong;
36 umuldiv(ulong a, ulong b, ulong c)
40 d = ((double)a * (double)b) / (double)c;
47 * This routine will convert to arbitrary precision
48 * floating point entirely in multi-precision fixed.
49 * The answer is the closest floating point number to
50 * the given decimal number. Exactly half way are
51 * rounded ala ieee rules.
52 * Method is to scale input decimal between .500 and .999...
53 * with external power of 2, then binary search for the
54 * closest mantissa to this decimal number.
55 * Nmant is is the required precision. (53 for ieee dp)
56 * Nbits is the max number of bits/word. (must be <= 28)
57 * Prec is calculated - the number of words of fixed mantissa.
61 Nbits = 28, /* bits safely represented in a ulong */
62 Nmant = 53, /* bits of precision required */
63 Prec = (Nmant+Nbits+1)/Nbits, /* words of Nbits each to represent mantissa */
64 Sigbit = 1<<(Prec*Nbits-Nmant), /* first significant bit of Prec-th word */
66 One = (ulong)(1<<Nbits),
67 Half = (ulong)(One>>1),
70 Fsign = 1<<0, /* found - */
71 Fesign = 1<<1, /* found e- */
72 Fdpoint = 1<<2, /* found . */
74 S0 = 0, /* _ _S0 +S1 #S2 .S3 */
76 S2, /* _+# #S2 .S4 eS5 */
78 S4, /* _+#.# #S4 eS5 */
79 S5, /* _+#.#e +S6 #S7 */
84 static int xcmp(char*, char*);
85 static int fpcmp(char*, ulong*);
86 static void frnorm(ulong*);
87 static void divascii(char*, int*, int*, int*);
88 static void mulascii(char*, int*, int*, int*);
90 typedef struct Tab Tab;
99 fz_strtod(const char *as, char **aas)
101 int na, ex, dp, bp, c, i, flag, state;
102 ulong low[Prec], hig[Prec], mid[Prec];
106 flag = 0; /* Fsign, Fesign, Fdpoint */
107 na = 0; /* number of digits of a[] */
108 dp = 0; /* na of decimal point */
109 ex = 0; /* exonent */
112 for(s=(char*)as;; s++) {
114 if(c >= '0' && c <= '9') {
130 ex = ex*10 + (c-'0');
133 if(na == 0 && c == '0') {
168 if(state == S0 || state == S1) {
179 if(state == S2 || state == S4) {
189 * clean up return char-pointer
193 if(xcmp(s, "nan") == 0) {
199 if(xcmp(s, "infinity") == 0) {
204 if(xcmp(s, "inf") == 0) {
212 goto ret0; /* no digits found */
214 s--; /* back over +- */
216 s--; /* back over e */
223 while(na > 0 && a[na-1] == '0')
226 goto ret0; /* zero */
228 if(!(flag & Fdpoint))
235 goto ret0; /* underflow by exp */
238 goto retinf; /* overflow by exp */
241 * normalize the decimal ascii number
242 * to range .[5-9][0-9]* e0
244 bp = 0; /* binary exponent */
246 divascii(a, &na, &dp, &bp);
247 while(dp < 0 || a[0] < '5')
248 mulascii(a, &na, &dp, &bp);
250 /* close approx by naive conversion */
253 for(i=0; (c=a[i]) != '\0'; i++) {
254 mid[0] = mid[0]*10 + (c-'0');
259 low[0] = umuldiv(mid[0], One, mid[1]);
260 hig[0] = umuldiv(mid[0]+1, One, mid[1]);
261 for(i=1; i<Prec; i++) {
266 /* binary search for closest mantissa */
268 /* mid = (hig + low) / 2 */
270 for(i=0; i<Prec; i++) {
271 mid[i] = hig[i] + low[i];
283 for(i=0; i<Prec; i++)
284 if(low[i] != mid[i]) {
289 break; /* between mid and hig */
293 for(i=0; i<Prec; i++)
298 /* only hard part is if even/odd roundings wants to go up */
299 c = mid[Prec-1] & (Sigbit-1);
300 if(c == Sigbit/2 && (mid[Prec-1]&Sigbit) == 0)
302 break; /* exactly mid */
305 /* normal rounding applies */
306 c = mid[Prec-1] & (Sigbit-1);
309 mid[Prec-1] += Sigbit;
322 * Unix strtod requires these. Plan 9 would return Inf(0) or Inf(-1). */
330 for(i=0; i<Prec; i++)
334 d = ldexp(d, bp - Prec*Nbits);
335 if(d == 0){ /* underflow */
347 for(i=Prec-1; i>0; i--) {
356 fpcmp(char *a, ulong* f)
361 for(i=0; i<Prec; i++)
366 for(i=0; i<Prec; i++)
369 d = (tf[0] >> Nbits) + '0';
372 /* compare next digit */
379 for(i=1; i<Prec; i++)
394 divby(char *a, int *na, int b)
445 { 23, 7, "8388607" },
446 { 26, 8, "67108863" },
447 { 27, 9, "134217727" },
451 divascii(char *a, int *na, int *dp, int *bp)
457 if(d >= (int)(nelem(tab1)))
458 d = (int)(nelem(tab1))-1;
461 if(memcmp(a, t->cmp, t->siz) > 0)
469 mulby(char *a, char *p, char *q, int b)
497 { 1, 1, "" }, /* dp = 0-0 */
501 { 13, 10, "1220703125" },
502 { 16, 12, "152587890625" },
503 { 19, 14, "19073486328125" },
504 { 23, 17, "11920928955078125" },
505 { 26, 19, "1490116119384765625" },
506 { 27, 19, "7450580596923828125" }, /* dp 8-9 */
510 mulascii(char *a, int *na, int *dp, int *bp)
517 if(d >= (int)(nelem(tab2)))
518 d = (int)(nelem(tab2))-1;
521 if(memcmp(a, t->cmp, t->siz) < 0)
531 xcmp(char *a, char *b)
535 while((c1 = *b++) != '\0') {
537 if(c2 >= 'A' && c2 <= 'Z')