#include "platform.h"#include "mp.h" #define between(x,min,max) (((min-1-x) & (x-max-1))>>8) static intdec32chr(int c){ int o; o = between(c, 'A', 'Z') & (1+(c-'A')); o |= between(c, 'a', 'z') & (1+(c-'a')); o |= between(c, '2', '7') & (1+26+(c-'2')); return o-1;} static intdec32x(u8int *dest, int ndest, const char *src, int nsrc, int (*chr)(int)){ u8int *start; int i, j, u[8]; if(ndest+1 < (5*nsrc+7)/8) return -1; start = dest; while(nsrc>=8){ for(i=0; i<8; i++){ j = chr(src[i]); if(j < 0) j = 0; u[i] = j; } *dest++ = (u[0]<<3) | (0x7 & (u[1]>>2)); *dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4)); *dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1)); *dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3)); *dest++ = ((0x7 & u[6])<<5) | u[7]; src += 8; nsrc -= 8; } if(nsrc > 0){ if(nsrc == 1 || nsrc == 3 || nsrc == 6) return -1; for(i=0; i<nsrc; i++){ j = chr(src[i]); if(j < 0) j = 0; u[i] = j; } *dest++ = (u[0]<<3) | (0x7 & (u[1]>>2)); if(nsrc == 2) goto out; *dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4)); if(nsrc == 4) goto out; *dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1)); if(nsrc == 5) goto out; *dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3)); }out: return dest-start;} intdec32(u8int *dest, int ndest, const char *src, int nsrc){ return dec32x(dest, ndest, src, nsrc, dec32chr);} static const char *frompow2(const char *a, mpint *b, int s){ const char *p, *next; mpdigit x; u32int i; i = 1<<s; for(p = a; (dec16chr(*p) & 255) < i; p++) ; mpbits(b, (p-a)*s); b->top = 0; next = p; while(p > a){ x = 0; for(i = 0; i < Dbits; i += s){ if(p <= a) break; x |= dec16chr(*--p)<<i; } b->p[b->top++] = x; } return next;} static const char*from8(const char *a, mpint *b){ const char *p, *next; mpdigit x, y; int i; for(p = a; ((*p - '0') & 255) < 8; p++) ; mpbits(b, (p-a)*3); b->top = 0; next = p; i = 0; x = y = 0; while(p > a){ y = *--p - '0'; x |= y << i; i += 3; if(i >= Dbits){Digout: i -= Dbits; b->p[b->top++] = x; if(i <= -(64-3)) x = 0; else x = y >> (3-i); } } if(i > 0) goto Digout; return next;} static u32int mppow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; static const char*from10(const char *a, mpint *b){ u32int x, y; mpint *pow, *r; int i; pow = mpnew(0); r = mpnew(0); b->top = 0; for(;;){ // do a billion at a time in native arithmetic x = 0; for(i = 0; i < 9; i++){ y = *a - '0'; if(y > 9) break; a++; x *= 10; x += y; } if(i == 0) break; // accumulate into mpint uitomp(mppow10[i], pow); uitomp(x, r); mpmul(b, pow, b); mpadd(b, r, b); if(i < 9) break; } mpfree(pow); mpfree(r); return a;} static const char*fromdecx(const char *a, mpint *b, int (*chr)(int), int (*dec)(u8int*, int, const char*, int)){ const char *buf = a; u8int *p; int n, m; b->top = 0; for(; chr(*a) >= 0; a++) ; n = a-buf; if(n > 0){ p = MEM_ALLOC(n); if(p == nil) abort(); m = dec(p, n, buf, n); if(m > 0) betomp(p, m, b); MEM_FREE(p); } return a;} mpint*strtomp(const char *a, char **pp, int base, mpint *b){ int sign; const char *e; if(b == nil) b = mpnew(0); while(*a==' ' || *a=='\t') a++; sign = 1; for(;; a++){ switch(*a){ case '-': sign *= -1; continue; } break; } if(base == 0){ base = 10; if(a[0] == '0'){ if(a[1] == 'x' || a[1] == 'X'){ a += 2; base = 16; }else if(a[1] == 'b' || a[1] == 'B'){ a += 2; base = 2; }else if(a[1] >= '0' && a[1] <= '7'){ a++; base = 8; } } } switch(base){ case 2: e = frompow2(a, b, 1); break; case 4: e = frompow2(a, b, 2); break; case 8: e = from8(a, b); break; case 10: e = from10(a, b); break; case 16: e = frompow2(a, b, 4); break; case 32: e = fromdecx(a, b, dec32chr, dec32); break; default: abort(); return nil; } if(pp != nil) *pp = (char*)e; // if no characters parsed, there wasn't a number to convert if(e == a) return nil; b->sign = sign; return mpnorm(b);}
#include "platform.h"
#include "mp.h"
#define between(x,min,max) (((min-1-x) & (x-max-1))>>8)
static int
dec32chr(int c)
{
int o;
o = between(c, 'A', 'Z') & (1+(c-'A'));
o |= between(c, 'a', 'z') & (1+(c-'a'));
o |= between(c, '2', '7') & (1+26+(c-'2'));
return o-1;
}
static int
dec32x(u8int *dest, int ndest, const char *src, int nsrc, int (*chr)(int))
{
u8int *start;
int i, j, u[8];
if(ndest+1 < (5*nsrc+7)/8)
return -1;
start = dest;
while(nsrc>=8){
for(i=0; i<8; i++){
j = chr(src[i]);
if(j < 0)
j = 0;
u[i] = j;
}
*dest++ = (u[0]<<3) | (0x7 & (u[1]>>2));
*dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4));
*dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1));
*dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3));
*dest++ = ((0x7 & u[6])<<5) | u[7];
src += 8;
nsrc -= 8;
}
if(nsrc > 0){
if(nsrc == 1 || nsrc == 3 || nsrc == 6)
return -1;
for(i=0; i<nsrc; i++){
j = chr(src[i]);
if(j < 0)
j = 0;
u[i] = j;
}
*dest++ = (u[0]<<3) | (0x7 & (u[1]>>2));
if(nsrc == 2)
goto out;
*dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4));
if(nsrc == 4)
goto out;
*dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1));
if(nsrc == 5)
goto out;
*dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3));
}
out:
return dest-start;
}
int
dec32(u8int *dest, int ndest, const char *src, int nsrc)
{
return dec32x(dest, ndest, src, nsrc, dec32chr);
}
static const char *
frompow2(const char *a, mpint *b, int s)
{
const char *p, *next;
mpdigit x;
u32int i;
i = 1<<s;
for(p = a; (dec16chr(*p) & 255) < i; p++)
;
mpbits(b, (p-a)*s);
b->top = 0;
next = p;
while(p > a){
x = 0;
for(i = 0; i < Dbits; i += s){
if(p <= a)
break;
x |= dec16chr(*--p)<<i;
}
b->p[b->top++] = x;
}
return next;
}
static const char*
from8(const char *a, mpint *b)
{
const char *p, *next;
mpdigit x, y;
int i;
for(p = a; ((*p - '0') & 255) < 8; p++)
;
mpbits(b, (p-a)*3);
b->top = 0;
next = p;
i = 0;
x = y = 0;
while(p > a){
y = *--p - '0';
x |= y << i;
i += 3;
if(i >= Dbits){
Digout:
i -= Dbits;
b->p[b->top++] = x;
if(i <= -(64-3))
x = 0;
else
x = y >> (3-i);
}
}
if(i > 0)
goto Digout;
return next;
}
static u32int mppow10[] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
};
static const char*
from10(const char *a, mpint *b)
{
u32int x, y;
mpint *pow, *r;
int i;
pow = mpnew(0);
r = mpnew(0);
b->top = 0;
for(;;){
// do a billion at a time in native arithmetic
x = 0;
for(i = 0; i < 9; i++){
y = *a - '0';
if(y > 9)
break;
a++;
x *= 10;
x += y;
}
if(i == 0)
break;
// accumulate into mpint
uitomp(mppow10[i], pow);
uitomp(x, r);
mpmul(b, pow, b);
mpadd(b, r, b);
if(i < 9)
break;
}
mpfree(pow);
mpfree(r);
return a;
}
static const char*
fromdecx(const char *a, mpint *b, int (*chr)(int), int (*dec)(u8int*, int, const char*, int))
{
const char *buf = a;
u8int *p;
int n, m;
b->top = 0;
for(; chr(*a) >= 0; a++)
;
n = a-buf;
if(n > 0){
p = MEM_ALLOC(n);
if(p == nil)
abort();
m = dec(p, n, buf, n);
if(m > 0)
betomp(p, m, b);
MEM_FREE(p);
}
return a;
}
mpint*
strtomp(const char *a, char **pp, int base, mpint *b)
{
int sign;
const char *e;
if(b == nil)
b = mpnew(0);
while(*a==' ' || *a=='\t')
a++;
sign = 1;
for(;; a++){
switch(*a){
case '-':
sign *= -1;
continue;
}
break;
}
if(base == 0){
base = 10;
if(a[0] == '0'){
if(a[1] == 'x' || a[1] == 'X'){
a += 2;
base = 16;
}else if(a[1] == 'b' || a[1] == 'B'){
a += 2;
base = 2;
}else if(a[1] >= '0' && a[1] <= '7'){
a++;
base = 8;
}
}
}
switch(base){
case 2:
e = frompow2(a, b, 1);
break;
case 4:
e = frompow2(a, b, 2);
break;
case 8:
e = from8(a, b);
break;
case 10:
e = from10(a, b);
break;
case 16:
e = frompow2(a, b, 4);
break;
case 32:
e = fromdecx(a, b, dec32chr, dec32);
break;
default:
abort();
return nil;
}
if(pp != nil)
*pp = (char*)e;
// if no characters parsed, there wasn't a number to convert
if(e == a)
return nil;
b->sign = sign;
return mpnorm(b);
}