1*8ccd4a63SDavid du Colombier #include <u.h> 2*8ccd4a63SDavid du Colombier #include <libc.h> 3*8ccd4a63SDavid du Colombier #include <ctype.h> 4*8ccd4a63SDavid du Colombier 5*8ccd4a63SDavid du Colombier /* 6*8ccd4a63SDavid du Colombier * This routine will convert to arbitrary precision 7*8ccd4a63SDavid du Colombier * floating point entirely in multi-precision fixed. 8*8ccd4a63SDavid du Colombier * The answer is the closest floating point number to 9*8ccd4a63SDavid du Colombier * the given decimal number. Exactly half way are 10*8ccd4a63SDavid du Colombier * rounded ala ieee rules. 11*8ccd4a63SDavid du Colombier * Method is to scale input decimal between .500 and .999... 12*8ccd4a63SDavid du Colombier * with external power of 2, then binary search for the 13*8ccd4a63SDavid du Colombier * closest mantissa to this decimal number. 14*8ccd4a63SDavid du Colombier * Nmant is is the required precision. (53 for ieee dp) 15*8ccd4a63SDavid du Colombier * Nbits is the max number of bits/word. (must be <= 28) 16*8ccd4a63SDavid du Colombier * Prec is calculated - the number of words of fixed mantissa. 17*8ccd4a63SDavid du Colombier */ 18*8ccd4a63SDavid du Colombier enum 19*8ccd4a63SDavid du Colombier { 20*8ccd4a63SDavid du Colombier Nbits = 28, // bits safely represented in a ulong 21*8ccd4a63SDavid du Colombier Nmant = 53, // bits of precision required 22*8ccd4a63SDavid du Colombier Bias = 1022, 23*8ccd4a63SDavid du Colombier Prec = (Nmant+Nbits+1)/Nbits, // words of Nbits each to represent mantissa 24*8ccd4a63SDavid du Colombier Sigbit = 1<<(Prec*Nbits-Nmant), // first significant bit of Prec-th word 25*8ccd4a63SDavid du Colombier Ndig = 1500, 26*8ccd4a63SDavid du Colombier One = (ulong)(1<<Nbits), 27*8ccd4a63SDavid du Colombier Half = (ulong)(One>>1), 28*8ccd4a63SDavid du Colombier Maxe = 310, 29*8ccd4a63SDavid du Colombier Fsign = 1<<0, // found - 30*8ccd4a63SDavid du Colombier Fesign = 1<<1, // found e- 31*8ccd4a63SDavid du Colombier Fdpoint = 1<<2, // found . 32*8ccd4a63SDavid du Colombier 33*8ccd4a63SDavid du Colombier S0 = 0, // _ _S0 +S1 #S2 .S3 34*8ccd4a63SDavid du Colombier S1, // _+ #S2 .S3 35*8ccd4a63SDavid du Colombier S2, // _+# #S2 .S4 eS5 36*8ccd4a63SDavid du Colombier S3, // _+. #S4 37*8ccd4a63SDavid du Colombier S4, // _+#.# #S4 eS5 38*8ccd4a63SDavid du Colombier S5, // _+#.#e +S6 #S7 39*8ccd4a63SDavid du Colombier S6, // _+#.#e+ #S7 40*8ccd4a63SDavid du Colombier S7, // _+#.#e+# #S7 41*8ccd4a63SDavid du Colombier }; 42*8ccd4a63SDavid du Colombier 43*8ccd4a63SDavid du Colombier static ulong 44*8ccd4a63SDavid du Colombier umuldiv(ulong a, ulong b, ulong c) 45*8ccd4a63SDavid du Colombier { 46*8ccd4a63SDavid du Colombier double d; 47*8ccd4a63SDavid du Colombier 48*8ccd4a63SDavid du Colombier d = ((double)a * (double)b) / (double)c; 49*8ccd4a63SDavid du Colombier if(d >= 4294967295.) 50*8ccd4a63SDavid du Colombier d = 4294967295.; 51*8ccd4a63SDavid du Colombier return d; 52*8ccd4a63SDavid du Colombier } 53*8ccd4a63SDavid du Colombier 54*8ccd4a63SDavid du Colombier static int xcmp(char*, char*); 55*8ccd4a63SDavid du Colombier static int fpcmp(char*, ulong*); 56*8ccd4a63SDavid du Colombier static void frnorm(ulong*); 57*8ccd4a63SDavid du Colombier static void divascii(char*, int*, int*, int*); 58*8ccd4a63SDavid du Colombier static void mulascii(char*, int*, int*, int*); 59*8ccd4a63SDavid du Colombier static void divby(char*, int*, int); 60*8ccd4a63SDavid du Colombier 61*8ccd4a63SDavid du Colombier typedef struct Tab Tab; 62*8ccd4a63SDavid du Colombier struct Tab 63*8ccd4a63SDavid du Colombier { 64*8ccd4a63SDavid du Colombier int bp; 65*8ccd4a63SDavid du Colombier int siz; 66*8ccd4a63SDavid du Colombier char* cmp; 67*8ccd4a63SDavid du Colombier }; 68*8ccd4a63SDavid du Colombier 69*8ccd4a63SDavid du Colombier double 70*8ccd4a63SDavid du Colombier strtod(char *as, char **aas) 71*8ccd4a63SDavid du Colombier { 72*8ccd4a63SDavid du Colombier int na, ona, ex, dp, bp, c, i, flag, state; 73*8ccd4a63SDavid du Colombier ulong low[Prec], hig[Prec], mid[Prec], num, den; 74*8ccd4a63SDavid du Colombier double d; 75*8ccd4a63SDavid du Colombier char *s, a[Ndig]; 76*8ccd4a63SDavid du Colombier 77*8ccd4a63SDavid du Colombier flag = 0; // Fsign, Fesign, Fdpoint 78*8ccd4a63SDavid du Colombier na = 0; // number of digits of a[] 79*8ccd4a63SDavid du Colombier dp = 0; // na of decimal point 80*8ccd4a63SDavid du Colombier ex = 0; // exonent 81*8ccd4a63SDavid du Colombier 82*8ccd4a63SDavid du Colombier state = S0; 83*8ccd4a63SDavid du Colombier for(s=as;; s++) { 84*8ccd4a63SDavid du Colombier c = *s; 85*8ccd4a63SDavid du Colombier if(c >= '0' && c <= '9') { 86*8ccd4a63SDavid du Colombier switch(state) { 87*8ccd4a63SDavid du Colombier case S0: 88*8ccd4a63SDavid du Colombier case S1: 89*8ccd4a63SDavid du Colombier case S2: 90*8ccd4a63SDavid du Colombier state = S2; 91*8ccd4a63SDavid du Colombier break; 92*8ccd4a63SDavid du Colombier case S3: 93*8ccd4a63SDavid du Colombier case S4: 94*8ccd4a63SDavid du Colombier state = S4; 95*8ccd4a63SDavid du Colombier break; 96*8ccd4a63SDavid du Colombier 97*8ccd4a63SDavid du Colombier case S5: 98*8ccd4a63SDavid du Colombier case S6: 99*8ccd4a63SDavid du Colombier case S7: 100*8ccd4a63SDavid du Colombier state = S7; 101*8ccd4a63SDavid du Colombier ex = ex*10 + (c-'0'); 102*8ccd4a63SDavid du Colombier continue; 103*8ccd4a63SDavid du Colombier } 104*8ccd4a63SDavid du Colombier if(na == 0 && c == '0') { 105*8ccd4a63SDavid du Colombier dp--; 106*8ccd4a63SDavid du Colombier continue; 107*8ccd4a63SDavid du Colombier } 108*8ccd4a63SDavid du Colombier if(na < Ndig-50) 109*8ccd4a63SDavid du Colombier a[na++] = c; 110*8ccd4a63SDavid du Colombier continue; 111*8ccd4a63SDavid du Colombier } 112*8ccd4a63SDavid du Colombier switch(c) { 113*8ccd4a63SDavid du Colombier case '\t': 114*8ccd4a63SDavid du Colombier case '\n': 115*8ccd4a63SDavid du Colombier case '\v': 116*8ccd4a63SDavid du Colombier case '\f': 117*8ccd4a63SDavid du Colombier case '\r': 118*8ccd4a63SDavid du Colombier case ' ': 119*8ccd4a63SDavid du Colombier if(state == S0) 120*8ccd4a63SDavid du Colombier continue; 121*8ccd4a63SDavid du Colombier break; 122*8ccd4a63SDavid du Colombier case '-': 123*8ccd4a63SDavid du Colombier if(state == S0) 124*8ccd4a63SDavid du Colombier flag |= Fsign; 125*8ccd4a63SDavid du Colombier else 126*8ccd4a63SDavid du Colombier flag |= Fesign; 127*8ccd4a63SDavid du Colombier case '+': 128*8ccd4a63SDavid du Colombier if(state == S0) 129*8ccd4a63SDavid du Colombier state = S1; 130*8ccd4a63SDavid du Colombier else 131*8ccd4a63SDavid du Colombier if(state == S5) 132*8ccd4a63SDavid du Colombier state = S6; 133*8ccd4a63SDavid du Colombier else 134*8ccd4a63SDavid du Colombier break; // syntax 135*8ccd4a63SDavid du Colombier continue; 136*8ccd4a63SDavid du Colombier case '.': 137*8ccd4a63SDavid du Colombier flag |= Fdpoint; 138*8ccd4a63SDavid du Colombier dp = na; 139*8ccd4a63SDavid du Colombier if(state == S0 || state == S1) { 140*8ccd4a63SDavid du Colombier state = S3; 141*8ccd4a63SDavid du Colombier continue; 142*8ccd4a63SDavid du Colombier } 143*8ccd4a63SDavid du Colombier if(state == S2) { 144*8ccd4a63SDavid du Colombier state = S4; 145*8ccd4a63SDavid du Colombier continue; 146*8ccd4a63SDavid du Colombier } 147*8ccd4a63SDavid du Colombier break; 148*8ccd4a63SDavid du Colombier case 'e': 149*8ccd4a63SDavid du Colombier case 'E': 150*8ccd4a63SDavid du Colombier if(state == S2 || state == S4) { 151*8ccd4a63SDavid du Colombier state = S5; 152*8ccd4a63SDavid du Colombier continue; 153*8ccd4a63SDavid du Colombier } 154*8ccd4a63SDavid du Colombier break; 155*8ccd4a63SDavid du Colombier } 156*8ccd4a63SDavid du Colombier break; 157*8ccd4a63SDavid du Colombier } 158*8ccd4a63SDavid du Colombier 159*8ccd4a63SDavid du Colombier /* 160*8ccd4a63SDavid du Colombier * clean up return char-pointer 161*8ccd4a63SDavid du Colombier */ 162*8ccd4a63SDavid du Colombier switch(state) { 163*8ccd4a63SDavid du Colombier case S0: 164*8ccd4a63SDavid du Colombier if(xcmp(s, "nan") == 0) { 165*8ccd4a63SDavid du Colombier if(aas != nil) 166*8ccd4a63SDavid du Colombier *aas = s+3; 167*8ccd4a63SDavid du Colombier goto retnan; 168*8ccd4a63SDavid du Colombier } 169*8ccd4a63SDavid du Colombier case S1: 170*8ccd4a63SDavid du Colombier if(xcmp(s, "infinity") == 0) { 171*8ccd4a63SDavid du Colombier if(aas != nil) 172*8ccd4a63SDavid du Colombier *aas = s+8; 173*8ccd4a63SDavid du Colombier goto retinf; 174*8ccd4a63SDavid du Colombier } 175*8ccd4a63SDavid du Colombier if(xcmp(s, "inf") == 0) { 176*8ccd4a63SDavid du Colombier if(aas != nil) 177*8ccd4a63SDavid du Colombier *aas = s+3; 178*8ccd4a63SDavid du Colombier goto retinf; 179*8ccd4a63SDavid du Colombier } 180*8ccd4a63SDavid du Colombier case S3: 181*8ccd4a63SDavid du Colombier if(aas != nil) 182*8ccd4a63SDavid du Colombier *aas = as; 183*8ccd4a63SDavid du Colombier goto ret0; // no digits found 184*8ccd4a63SDavid du Colombier case S6: 185*8ccd4a63SDavid du Colombier s--; // back over +- 186*8ccd4a63SDavid du Colombier case S5: 187*8ccd4a63SDavid du Colombier s--; // back over e 188*8ccd4a63SDavid du Colombier break; 189*8ccd4a63SDavid du Colombier } 190*8ccd4a63SDavid du Colombier if(aas != nil) 191*8ccd4a63SDavid du Colombier *aas = s; 192*8ccd4a63SDavid du Colombier 193*8ccd4a63SDavid du Colombier if(flag & Fdpoint) 194*8ccd4a63SDavid du Colombier while(na > 0 && a[na-1] == '0') 195*8ccd4a63SDavid du Colombier na--; 196*8ccd4a63SDavid du Colombier if(na == 0) 197*8ccd4a63SDavid du Colombier goto ret0; // zero 198*8ccd4a63SDavid du Colombier a[na] = 0; 199*8ccd4a63SDavid du Colombier if(!(flag & Fdpoint)) 200*8ccd4a63SDavid du Colombier dp = na; 201*8ccd4a63SDavid du Colombier if(flag & Fesign) 202*8ccd4a63SDavid du Colombier ex = -ex; 203*8ccd4a63SDavid du Colombier dp += ex; 204*8ccd4a63SDavid du Colombier if(dp < -Maxe-Nmant/3) /* actually -Nmant*log(2)/log(10), but Nmant/3 close enough */ 205*8ccd4a63SDavid du Colombier goto ret0; // underflow by exp 206*8ccd4a63SDavid du Colombier else 207*8ccd4a63SDavid du Colombier if(dp > +Maxe) 208*8ccd4a63SDavid du Colombier goto retinf; // overflow by exp 209*8ccd4a63SDavid du Colombier 210*8ccd4a63SDavid du Colombier /* 211*8ccd4a63SDavid du Colombier * normalize the decimal ascii number 212*8ccd4a63SDavid du Colombier * to range .[5-9][0-9]* e0 213*8ccd4a63SDavid du Colombier */ 214*8ccd4a63SDavid du Colombier bp = 0; // binary exponent 215*8ccd4a63SDavid du Colombier while(dp > 0) 216*8ccd4a63SDavid du Colombier divascii(a, &na, &dp, &bp); 217*8ccd4a63SDavid du Colombier while(dp < 0 || a[0] < '5') 218*8ccd4a63SDavid du Colombier mulascii(a, &na, &dp, &bp); 219*8ccd4a63SDavid du Colombier a[na] = 0; 220*8ccd4a63SDavid du Colombier 221*8ccd4a63SDavid du Colombier /* 222*8ccd4a63SDavid du Colombier * very small numbers are represented using 223*8ccd4a63SDavid du Colombier * bp = -Bias+1. adjust accordingly. 224*8ccd4a63SDavid du Colombier */ 225*8ccd4a63SDavid du Colombier if(bp < -Bias+1){ 226*8ccd4a63SDavid du Colombier ona = na; 227*8ccd4a63SDavid du Colombier divby(a, &na, -bp-Bias+1); 228*8ccd4a63SDavid du Colombier if(na < ona){ 229*8ccd4a63SDavid du Colombier memmove(a+ona-na, a, na); 230*8ccd4a63SDavid du Colombier memset(a, '0', ona-na); 231*8ccd4a63SDavid du Colombier na = ona; 232*8ccd4a63SDavid du Colombier } 233*8ccd4a63SDavid du Colombier a[na] = 0; 234*8ccd4a63SDavid du Colombier bp = -Bias+1; 235*8ccd4a63SDavid du Colombier } 236*8ccd4a63SDavid du Colombier 237*8ccd4a63SDavid du Colombier /* close approx by naive conversion */ 238*8ccd4a63SDavid du Colombier num = 0; 239*8ccd4a63SDavid du Colombier den = 1; 240*8ccd4a63SDavid du Colombier for(i=0; i<9 && (c=a[i]); i++) { 241*8ccd4a63SDavid du Colombier num = num*10 + (c-'0'); 242*8ccd4a63SDavid du Colombier den *= 10; 243*8ccd4a63SDavid du Colombier } 244*8ccd4a63SDavid du Colombier low[0] = umuldiv(num, One, den); 245*8ccd4a63SDavid du Colombier hig[0] = umuldiv(num+1, One, den); 246*8ccd4a63SDavid du Colombier for(i=1; i<Prec; i++) { 247*8ccd4a63SDavid du Colombier low[i] = 0; 248*8ccd4a63SDavid du Colombier hig[i] = One-1; 249*8ccd4a63SDavid du Colombier } 250*8ccd4a63SDavid du Colombier 251*8ccd4a63SDavid du Colombier /* binary search for closest mantissa */ 252*8ccd4a63SDavid du Colombier for(;;) { 253*8ccd4a63SDavid du Colombier /* mid = (hig + low) / 2 */ 254*8ccd4a63SDavid du Colombier c = 0; 255*8ccd4a63SDavid du Colombier for(i=0; i<Prec; i++) { 256*8ccd4a63SDavid du Colombier mid[i] = hig[i] + low[i]; 257*8ccd4a63SDavid du Colombier if(c) 258*8ccd4a63SDavid du Colombier mid[i] += One; 259*8ccd4a63SDavid du Colombier c = mid[i] & 1; 260*8ccd4a63SDavid du Colombier mid[i] >>= 1; 261*8ccd4a63SDavid du Colombier } 262*8ccd4a63SDavid du Colombier frnorm(mid); 263*8ccd4a63SDavid du Colombier 264*8ccd4a63SDavid du Colombier /* compare */ 265*8ccd4a63SDavid du Colombier c = fpcmp(a, mid); 266*8ccd4a63SDavid du Colombier if(c > 0) { 267*8ccd4a63SDavid du Colombier c = 1; 268*8ccd4a63SDavid du Colombier for(i=0; i<Prec; i++) 269*8ccd4a63SDavid du Colombier if(low[i] != mid[i]) { 270*8ccd4a63SDavid du Colombier c = 0; 271*8ccd4a63SDavid du Colombier low[i] = mid[i]; 272*8ccd4a63SDavid du Colombier } 273*8ccd4a63SDavid du Colombier if(c) 274*8ccd4a63SDavid du Colombier break; // between mid and hig 275*8ccd4a63SDavid du Colombier continue; 276*8ccd4a63SDavid du Colombier } 277*8ccd4a63SDavid du Colombier if(c < 0) { 278*8ccd4a63SDavid du Colombier for(i=0; i<Prec; i++) 279*8ccd4a63SDavid du Colombier hig[i] = mid[i]; 280*8ccd4a63SDavid du Colombier continue; 281*8ccd4a63SDavid du Colombier } 282*8ccd4a63SDavid du Colombier 283*8ccd4a63SDavid du Colombier /* only hard part is if even/odd roundings wants to go up */ 284*8ccd4a63SDavid du Colombier c = mid[Prec-1] & (Sigbit-1); 285*8ccd4a63SDavid du Colombier if(c == Sigbit/2 && (mid[Prec-1]&Sigbit) == 0) 286*8ccd4a63SDavid du Colombier mid[Prec-1] -= c; 287*8ccd4a63SDavid du Colombier break; // exactly mid 288*8ccd4a63SDavid du Colombier } 289*8ccd4a63SDavid du Colombier 290*8ccd4a63SDavid du Colombier /* normal rounding applies */ 291*8ccd4a63SDavid du Colombier c = mid[Prec-1] & (Sigbit-1); 292*8ccd4a63SDavid du Colombier mid[Prec-1] -= c; 293*8ccd4a63SDavid du Colombier if(c >= Sigbit/2) { 294*8ccd4a63SDavid du Colombier mid[Prec-1] += Sigbit; 295*8ccd4a63SDavid du Colombier frnorm(mid); 296*8ccd4a63SDavid du Colombier } 297*8ccd4a63SDavid du Colombier d = 0; 298*8ccd4a63SDavid du Colombier for(i=0; i<Prec; i++) 299*8ccd4a63SDavid du Colombier d = d*One + mid[i]; 300*8ccd4a63SDavid du Colombier if(flag & Fsign) 301*8ccd4a63SDavid du Colombier d = -d; 302*8ccd4a63SDavid du Colombier d = ldexp(d, bp - Prec*Nbits); 303*8ccd4a63SDavid du Colombier return d; 304*8ccd4a63SDavid du Colombier 305*8ccd4a63SDavid du Colombier ret0: 306*8ccd4a63SDavid du Colombier return 0; 307*8ccd4a63SDavid du Colombier 308*8ccd4a63SDavid du Colombier retnan: 309*8ccd4a63SDavid du Colombier return __NaN(); 310*8ccd4a63SDavid du Colombier 311*8ccd4a63SDavid du Colombier retinf: 312*8ccd4a63SDavid du Colombier if(flag & Fsign) 313*8ccd4a63SDavid du Colombier return __Inf(-1); 314*8ccd4a63SDavid du Colombier return __Inf(+1); 315*8ccd4a63SDavid du Colombier } 316*8ccd4a63SDavid du Colombier 317*8ccd4a63SDavid du Colombier static void 318*8ccd4a63SDavid du Colombier frnorm(ulong *f) 319*8ccd4a63SDavid du Colombier { 320*8ccd4a63SDavid du Colombier int i, c; 321*8ccd4a63SDavid du Colombier 322*8ccd4a63SDavid du Colombier c = 0; 323*8ccd4a63SDavid du Colombier for(i=Prec-1; i>0; i--) { 324*8ccd4a63SDavid du Colombier f[i] += c; 325*8ccd4a63SDavid du Colombier c = f[i] >> Nbits; 326*8ccd4a63SDavid du Colombier f[i] &= One-1; 327*8ccd4a63SDavid du Colombier } 328*8ccd4a63SDavid du Colombier f[0] += c; 329*8ccd4a63SDavid du Colombier } 330*8ccd4a63SDavid du Colombier 331*8ccd4a63SDavid du Colombier static int 332*8ccd4a63SDavid du Colombier fpcmp(char *a, ulong* f) 333*8ccd4a63SDavid du Colombier { 334*8ccd4a63SDavid du Colombier ulong tf[Prec]; 335*8ccd4a63SDavid du Colombier int i, d, c; 336*8ccd4a63SDavid du Colombier 337*8ccd4a63SDavid du Colombier for(i=0; i<Prec; i++) 338*8ccd4a63SDavid du Colombier tf[i] = f[i]; 339*8ccd4a63SDavid du Colombier 340*8ccd4a63SDavid du Colombier for(;;) { 341*8ccd4a63SDavid du Colombier /* tf *= 10 */ 342*8ccd4a63SDavid du Colombier for(i=0; i<Prec; i++) 343*8ccd4a63SDavid du Colombier tf[i] = tf[i]*10; 344*8ccd4a63SDavid du Colombier frnorm(tf); 345*8ccd4a63SDavid du Colombier d = (tf[0] >> Nbits) + '0'; 346*8ccd4a63SDavid du Colombier tf[0] &= One-1; 347*8ccd4a63SDavid du Colombier 348*8ccd4a63SDavid du Colombier /* compare next digit */ 349*8ccd4a63SDavid du Colombier c = *a; 350*8ccd4a63SDavid du Colombier if(c == 0) { 351*8ccd4a63SDavid du Colombier if('0' < d) 352*8ccd4a63SDavid du Colombier return -1; 353*8ccd4a63SDavid du Colombier if(tf[0] != 0) 354*8ccd4a63SDavid du Colombier goto cont; 355*8ccd4a63SDavid du Colombier for(i=1; i<Prec; i++) 356*8ccd4a63SDavid du Colombier if(tf[i] != 0) 357*8ccd4a63SDavid du Colombier goto cont; 358*8ccd4a63SDavid du Colombier return 0; 359*8ccd4a63SDavid du Colombier } 360*8ccd4a63SDavid du Colombier if(c > d) 361*8ccd4a63SDavid du Colombier return +1; 362*8ccd4a63SDavid du Colombier if(c < d) 363*8ccd4a63SDavid du Colombier return -1; 364*8ccd4a63SDavid du Colombier a++; 365*8ccd4a63SDavid du Colombier cont:; 366*8ccd4a63SDavid du Colombier } 367*8ccd4a63SDavid du Colombier return 0; 368*8ccd4a63SDavid du Colombier } 369*8ccd4a63SDavid du Colombier 370*8ccd4a63SDavid du Colombier static void 371*8ccd4a63SDavid du Colombier _divby(char *a, int *na, int b) 372*8ccd4a63SDavid du Colombier { 373*8ccd4a63SDavid du Colombier int n, c; 374*8ccd4a63SDavid du Colombier char *p; 375*8ccd4a63SDavid du Colombier 376*8ccd4a63SDavid du Colombier p = a; 377*8ccd4a63SDavid du Colombier n = 0; 378*8ccd4a63SDavid du Colombier while(n>>b == 0) { 379*8ccd4a63SDavid du Colombier c = *a++; 380*8ccd4a63SDavid du Colombier if(c == 0) { 381*8ccd4a63SDavid du Colombier while(n) { 382*8ccd4a63SDavid du Colombier c = n*10; 383*8ccd4a63SDavid du Colombier if(c>>b) 384*8ccd4a63SDavid du Colombier break; 385*8ccd4a63SDavid du Colombier n = c; 386*8ccd4a63SDavid du Colombier } 387*8ccd4a63SDavid du Colombier goto xx; 388*8ccd4a63SDavid du Colombier } 389*8ccd4a63SDavid du Colombier n = n*10 + c-'0'; 390*8ccd4a63SDavid du Colombier (*na)--; 391*8ccd4a63SDavid du Colombier } 392*8ccd4a63SDavid du Colombier for(;;) { 393*8ccd4a63SDavid du Colombier c = n>>b; 394*8ccd4a63SDavid du Colombier n -= c<<b; 395*8ccd4a63SDavid du Colombier *p++ = c + '0'; 396*8ccd4a63SDavid du Colombier c = *a++; 397*8ccd4a63SDavid du Colombier if(c == 0) 398*8ccd4a63SDavid du Colombier break; 399*8ccd4a63SDavid du Colombier n = n*10 + c-'0'; 400*8ccd4a63SDavid du Colombier } 401*8ccd4a63SDavid du Colombier (*na)++; 402*8ccd4a63SDavid du Colombier xx: 403*8ccd4a63SDavid du Colombier while(n) { 404*8ccd4a63SDavid du Colombier n = n*10; 405*8ccd4a63SDavid du Colombier c = n>>b; 406*8ccd4a63SDavid du Colombier n -= c<<b; 407*8ccd4a63SDavid du Colombier *p++ = c + '0'; 408*8ccd4a63SDavid du Colombier (*na)++; 409*8ccd4a63SDavid du Colombier } 410*8ccd4a63SDavid du Colombier *p = 0; 411*8ccd4a63SDavid du Colombier } 412*8ccd4a63SDavid du Colombier 413*8ccd4a63SDavid du Colombier static void 414*8ccd4a63SDavid du Colombier divby(char *a, int *na, int b) 415*8ccd4a63SDavid du Colombier { 416*8ccd4a63SDavid du Colombier while(b > 9){ 417*8ccd4a63SDavid du Colombier _divby(a, na, 9); 418*8ccd4a63SDavid du Colombier a[*na] = 0; 419*8ccd4a63SDavid du Colombier b -= 9; 420*8ccd4a63SDavid du Colombier } 421*8ccd4a63SDavid du Colombier if(b > 0) 422*8ccd4a63SDavid du Colombier _divby(a, na, b); 423*8ccd4a63SDavid du Colombier } 424*8ccd4a63SDavid du Colombier 425*8ccd4a63SDavid du Colombier static Tab tab1[] = 426*8ccd4a63SDavid du Colombier { 427*8ccd4a63SDavid du Colombier 1, 0, "", 428*8ccd4a63SDavid du Colombier 3, 1, "7", 429*8ccd4a63SDavid du Colombier 6, 2, "63", 430*8ccd4a63SDavid du Colombier 9, 3, "511", 431*8ccd4a63SDavid du Colombier 13, 4, "8191", 432*8ccd4a63SDavid du Colombier 16, 5, "65535", 433*8ccd4a63SDavid du Colombier 19, 6, "524287", 434*8ccd4a63SDavid du Colombier 23, 7, "8388607", 435*8ccd4a63SDavid du Colombier 26, 8, "67108863", 436*8ccd4a63SDavid du Colombier 27, 9, "134217727", 437*8ccd4a63SDavid du Colombier }; 438*8ccd4a63SDavid du Colombier 439*8ccd4a63SDavid du Colombier static void 440*8ccd4a63SDavid du Colombier divascii(char *a, int *na, int *dp, int *bp) 441*8ccd4a63SDavid du Colombier { 442*8ccd4a63SDavid du Colombier int b, d; 443*8ccd4a63SDavid du Colombier Tab *t; 444*8ccd4a63SDavid du Colombier 445*8ccd4a63SDavid du Colombier d = *dp; 446*8ccd4a63SDavid du Colombier if(d >= nelem(tab1)) 447*8ccd4a63SDavid du Colombier d = nelem(tab1)-1; 448*8ccd4a63SDavid du Colombier t = tab1 + d; 449*8ccd4a63SDavid du Colombier b = t->bp; 450*8ccd4a63SDavid du Colombier if(memcmp(a, t->cmp, t->siz) > 0) 451*8ccd4a63SDavid du Colombier d--; 452*8ccd4a63SDavid du Colombier *dp -= d; 453*8ccd4a63SDavid du Colombier *bp += b; 454*8ccd4a63SDavid du Colombier divby(a, na, b); 455*8ccd4a63SDavid du Colombier } 456*8ccd4a63SDavid du Colombier 457*8ccd4a63SDavid du Colombier static void 458*8ccd4a63SDavid du Colombier mulby(char *a, char *p, char *q, int b) 459*8ccd4a63SDavid du Colombier { 460*8ccd4a63SDavid du Colombier int n, c; 461*8ccd4a63SDavid du Colombier 462*8ccd4a63SDavid du Colombier n = 0; 463*8ccd4a63SDavid du Colombier *p = 0; 464*8ccd4a63SDavid du Colombier for(;;) { 465*8ccd4a63SDavid du Colombier q--; 466*8ccd4a63SDavid du Colombier if(q < a) 467*8ccd4a63SDavid du Colombier break; 468*8ccd4a63SDavid du Colombier c = *q - '0'; 469*8ccd4a63SDavid du Colombier c = (c<<b) + n; 470*8ccd4a63SDavid du Colombier n = c/10; 471*8ccd4a63SDavid du Colombier c -= n*10; 472*8ccd4a63SDavid du Colombier p--; 473*8ccd4a63SDavid du Colombier *p = c + '0'; 474*8ccd4a63SDavid du Colombier } 475*8ccd4a63SDavid du Colombier while(n) { 476*8ccd4a63SDavid du Colombier c = n; 477*8ccd4a63SDavid du Colombier n = c/10; 478*8ccd4a63SDavid du Colombier c -= n*10; 479*8ccd4a63SDavid du Colombier p--; 480*8ccd4a63SDavid du Colombier *p = c + '0'; 481*8ccd4a63SDavid du Colombier } 482*8ccd4a63SDavid du Colombier } 483*8ccd4a63SDavid du Colombier 484*8ccd4a63SDavid du Colombier static Tab tab2[] = 485*8ccd4a63SDavid du Colombier { 486*8ccd4a63SDavid du Colombier 1, 1, "", // dp = 0-0 487*8ccd4a63SDavid du Colombier 3, 3, "125", 488*8ccd4a63SDavid du Colombier 6, 5, "15625", 489*8ccd4a63SDavid du Colombier 9, 7, "1953125", 490*8ccd4a63SDavid du Colombier 13, 10, "1220703125", 491*8ccd4a63SDavid du Colombier 16, 12, "152587890625", 492*8ccd4a63SDavid du Colombier 19, 14, "19073486328125", 493*8ccd4a63SDavid du Colombier 23, 17, "11920928955078125", 494*8ccd4a63SDavid du Colombier 26, 19, "1490116119384765625", 495*8ccd4a63SDavid du Colombier 27, 19, "7450580596923828125", // dp 8-9 496*8ccd4a63SDavid du Colombier }; 497*8ccd4a63SDavid du Colombier 498*8ccd4a63SDavid du Colombier static void 499*8ccd4a63SDavid du Colombier mulascii(char *a, int *na, int *dp, int *bp) 500*8ccd4a63SDavid du Colombier { 501*8ccd4a63SDavid du Colombier char *p; 502*8ccd4a63SDavid du Colombier int d, b; 503*8ccd4a63SDavid du Colombier Tab *t; 504*8ccd4a63SDavid du Colombier 505*8ccd4a63SDavid du Colombier d = -*dp; 506*8ccd4a63SDavid du Colombier if(d >= nelem(tab2)) 507*8ccd4a63SDavid du Colombier d = nelem(tab2)-1; 508*8ccd4a63SDavid du Colombier t = tab2 + d; 509*8ccd4a63SDavid du Colombier b = t->bp; 510*8ccd4a63SDavid du Colombier if(memcmp(a, t->cmp, t->siz) < 0) 511*8ccd4a63SDavid du Colombier d--; 512*8ccd4a63SDavid du Colombier p = a + *na; 513*8ccd4a63SDavid du Colombier *bp -= b; 514*8ccd4a63SDavid du Colombier *dp += d; 515*8ccd4a63SDavid du Colombier *na += d; 516*8ccd4a63SDavid du Colombier mulby(a, p+d, p, b); 517*8ccd4a63SDavid du Colombier } 518*8ccd4a63SDavid du Colombier 519*8ccd4a63SDavid du Colombier static int 520*8ccd4a63SDavid du Colombier xcmp(char *a, char *b) 521*8ccd4a63SDavid du Colombier { 522*8ccd4a63SDavid du Colombier int c1, c2; 523*8ccd4a63SDavid du Colombier 524*8ccd4a63SDavid du Colombier while((c1 = *b++)) { 525*8ccd4a63SDavid du Colombier c2 = *a++; 526*8ccd4a63SDavid du Colombier if(isupper(c2)) 527*8ccd4a63SDavid du Colombier c2 = tolower(c2); 528*8ccd4a63SDavid du Colombier if(c1 != c2) 529*8ccd4a63SDavid du Colombier return 1; 530*8ccd4a63SDavid du Colombier } 531*8ccd4a63SDavid du Colombier return 0; 532*8ccd4a63SDavid du Colombier } 533