Sigrid Solveig Haflínudóttirfix unboxed numericals on big endian CPUs235563f1 year agoHistory
179 lines · 4.0 KB · C
RawDownload
//sl_v//sl_*_any(sl_v *args, u32int nargs)// input: ACCUM_DEFAULT ARITH_OP(a,b)   MP_OP   ARITH_OVERFLOW// add:   0             a+b             mpadd   sadd_overflow_64// mul:   1             a*b             mpmul   smul_overflow_64 	mpint *Maccum = nil, *m = nil;	s64int Saccum = ACCUM_DEFAULT, x;	double Faccum = ACCUM_DEFAULT;	u64int u64;	bool inexact = false;	int forcetype = -1;	sl_v arg;	sl_numtype pt;	void *a;	sl_cv *cv; 	u32int i, j;	FOR_ARGS(i, 0, arg, args){		if(isfixnum(arg))			x = numval(arg);		else{			if(isubnum(arg)){				pt = ubnumtype(arg);				u64 = ubnumval(arg);				a = ubnumptr(u64, pt);			}else if(iscvalue(arg)){				cv = ptr(arg);				a = cv_data(cv);				pt = cv_numtype(cv);			}else{typeerr:				mpfree(Maccum);				mpfree(m);				type_error(nil, "num", arg);			}			switch(pt){			case T_F64: Faccum = ARITH_OP(Faccum, *(double*)a); inexact = true; continue;			case T_F32: Faccum = ARITH_OP(Faccum, *(float*)a); inexact = true; continue;			case T_S8:  x = *(s8int*)a; break;			case T_U8:  x = *(u8int*)a; break;			case T_S16: x = *(s16int*)a; break;			case T_U16: x = *(u16int*)a; break;			case T_S32: x = *(s32int*)a; break;			case T_P32: if(forcetype < T_P32) forcetype = T_P32;				// fall through			case T_U32: x = *(u32int*)a; break;			case T_S64: x = *(s64int*)a; break;			case T_P64: if(forcetype < T_P64) forcetype = T_P64;				// fall through			case T_U64:				u64 = *(u64int*)a;				if(u64 > INT64_MAX){					x = ACCUM_DEFAULT;					goto overflow;				}				x = u64;				break;			case T_BIG:				x = ACCUM_DEFAULT;				u64 = ACCUM_DEFAULT;				m = mpcopy(*(mpint**)a);				goto overflow;			default:				goto typeerr;			}		} 		s64int accu;		if(ARITH_OVERFLOW(Saccum, x, &accu)){			u64 = ACCUM_DEFAULT;			goto overflow;		}		Saccum = accu;	} 	if(forcetype >= 0){forcedptr:		if(inexact)			lerrorf(sl_errarg, "arithmetic on a mix of ptr and inexact types");		switch(forcetype){		case T_P32: return mk_p32(Saccum);		case T_P64: return mk_p64(Saccum);		default: abort();		}	}	if(inexact)		return mk_f64(ARITH_OP(Faccum, Saccum));	if(fits_fixnum(Saccum))		return fixnum((sl_fx)Saccum);	u64 = ACCUM_DEFAULT;	x = ACCUM_DEFAULT; overflow:	i++;	if(Maccum == nil)		Maccum = vtomp(Saccum, nil);	if(m == nil)		m = u64 != ACCUM_DEFAULT ? uvtomp(u64, nil) : vtomp(x, nil); 	MP_OP(Maccum, m, Maccum); 	FOR_ARGS(j, i, arg, args){		if(isfixnum(arg)){			vtomp(numval(arg), m);			MP_OP(Maccum, m, Maccum);			continue;		}		if(isubnum(arg)){			pt = ubnumtype(arg);			u64 = ubnumval(arg);			a = ubnumptr(u64, pt);		}else if(iscvalue(arg)){			cv = ptr(arg);			a = cv_data(cv);			pt = cv_numtype(cv);		}else{			goto typeerr;		}		switch(pt){		case T_F64: Faccum = ARITH_OP(Faccum, *(double*)a); inexact = true; continue;		case T_F32: Faccum = ARITH_OP(Faccum, *(float*)a); inexact = true; continue;		case T_S8:  x = *(s8int*)a; break;		case T_U8:  x = *(u8int*)a; break;		case T_S16: x = *(s16int*)a; break;		case T_U16: x = *(u16int*)a; break;		case T_S32: x = *(s32int*)a; break;		case T_P32: if(forcetype < T_P32) forcetype = T_P32;			// fall through		case T_U32: x = *(u32int*)a; break;		case T_S64: x = *(s64int*)a; break;		case T_P64: if(forcetype < T_P64) forcetype = T_P64;			// fall through		case T_U64:			uvtomp(*(u64int*)a, m);			MP_OP(Maccum, m, Maccum);			continue;		case T_BIG:			MP_OP(Maccum, *(mpint**)a, Maccum);			continue;		default:			goto typeerr;		}		vtomp(x, m);		MP_OP(Maccum, m, Maccum);	} 	if(forcetype >= 0){		Saccum = mptouv(Maccum);		goto forcedptr;	} 	int n = mpsignif(Maccum);	if(n >= FIXNUM_BITS){		if(inexact){			dtomp(Faccum, m);			MP_OP(Maccum, m, Maccum);			n = mpsignif(Maccum);			if(n < FIXNUM_BITS){				inexact = false;				goto down;			}		}		mpfree(m);		return mk_bignum(Maccum);	}down:	mpfree(m);	Saccum = mptov(Maccum);	mpfree(Maccum);	if(inexact)		return mk_f64(ARITH_OP(Faccum, Saccum));	assert(fits_fixnum(Saccum));	return fixnum((sl_fx)Saccum); #undef ACCUM_DEFAULT#undef ARITH_OP#undef MP_OP#undef ARITH_OVERFLOW

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