270 lines · 4.1 KB · C
RawDownload
#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);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t