removed some deprecated code from bigint.c
fixed a bigint division bug when MOO_USE_FULL_WORD is undefined
This commit is contained in:
		| @ -317,6 +317,13 @@ extend MyObject | ||||
| 			## 135-139 | ||||
| 			[ (-65535 rem: 8113063330913503995887611892379812731289731289312898971231) = -65535 ], | ||||
| 			[ (-65535 mod: 8113063330913503995887611892379812731289731289312898971231) = 8113063330913503995887611892379812731289731289312898905696 ], | ||||
| 			[ (8113063330913503995887611892379812731289731289312898971231 div: 34359738368) = 236121219667649827777862429280643489074710852271 ], | ||||
| 			[ (-8113063330913503995887611892379812731289731289312898971231 div: 34359738368) = -236121219667649827777862429280643489074710852271 ], | ||||
| 			[ (-8113063330913503995887611892379812731289731289312898971231 mdiv: 34359738368) = -236121219667649827777862429280643489074710852272 ], | ||||
|  | ||||
| 			## 140-144 | ||||
| 			[ (-8113063330913503995887611892379812731289731289312898971231 rem: 34359738368) = -31040337503 ], | ||||
| 			[ (-8113063330913503995887611892379812731289731289312898971231 mod: 34359738368) = 3319400865 ], | ||||
|  | ||||
| 			## ========================= | ||||
| 			[  | ||||
|  | ||||
							
								
								
									
										300
									
								
								moo/lib/bigint.c
									
									
									
									
									
								
							
							
						
						
									
										300
									
								
								moo/lib/bigint.c
									
									
									
									
									
								
							| @ -1592,24 +1592,54 @@ static void divide_unsigned_array (moo_t* moo, const moo_liw_t* x, moo_oow_t xs, | ||||
| #if 0 | ||||
| static void divide_unsigned_array2 (moo_t* moo, const moo_liw_t* x, moo_oow_t xs, const moo_liw_t* y, moo_oow_t ys, moo_liw_t* q, moo_liw_t* r) | ||||
| { | ||||
| 	moo_oow_t rsize, qsize; | ||||
| 	moo_oow_t i; | ||||
|  | ||||
| 	/* estimate result sizes */ | ||||
| 	rsize = ys; | ||||
| 	qsize = xs - ys + 1; | ||||
|  | ||||
| 	npos = xs - 1; | ||||
| 	dpos = ys - 1; | ||||
|  | ||||
| 	for (j = qsize - 1; j >= 0; j--, npos--) | ||||
| 	d = (y[ys - 1] == MOO_TYPE_MAX(moo_liw_t)? 1: (((moo_lidw_t)1 << MOO_LIW_BITS) / (y[ys - 1] + 1)); | ||||
| 	if (d > 1) | ||||
| 	{ | ||||
| 		if (ndigs[npos] == ddigs[dpos] | ||||
| 		x[xs] = multiply_unsigned_array_in_place_and_get_last_carry(x, xs, d); | ||||
| 		carry = multiply_unsigned_array_in_place_and_get_last_carry(y, ys, d); /* carry must be zero */ | ||||
| 		MOO_ASSERT (moo, carry == 0); | ||||
| 	} | ||||
|  | ||||
| 	for (i = xs; i >= ys; ) | ||||
| 	{ | ||||
| 		moo_liw_t q; | ||||
| 		moo_liw_t y1, y2; | ||||
|  | ||||
| 		y1 = y[ys - 1]; | ||||
| 		y2 = y[ys - 2]; | ||||
|  | ||||
| 		if (x[i] == y1)  | ||||
| 		{ | ||||
| 			q = MOO_TYPE_MAX(moo_liw_t); | ||||
| 		} | ||||
| 		else | ||||
| 		 | ||||
| 		{ | ||||
| 			moo_lidw_t dw; | ||||
|  | ||||
| 		carry = scarry = 0; | ||||
| 			dw = ((moo_lidw_t)x[i] << MOO_LIW_BITS) + x[i - 1]; | ||||
| 			/* TODO: optimize it with ASM - no seperate / and % */ | ||||
| 			q = dw / y1; | ||||
| 			x[i] = dw % y1; | ||||
| 		} | ||||
|  | ||||
| 		qdigs[j] = qest; | ||||
| 		while (i < ys) { j++; k++; } | ||||
| 		x[i] = q; | ||||
| 		i--; | ||||
| 	} | ||||
| 	if (d != 1) | ||||
| 	{ | ||||
| 		moo_lidw_t dw; | ||||
| 		moo_liw_t carry = 0; | ||||
| 		for (i = ys; i > 0; ) | ||||
| 		{ | ||||
| 			--i; | ||||
| 			dw = ((moo_lidw_t)x[i] << MOO_LIW_BITS) + carry; | ||||
| 			/* TODO: optimize it with ASM - no seperate / and % */ | ||||
| 			x[i] = dw / y1; | ||||
| 			carry = dw % y1; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| #endif | ||||
| @ -1706,6 +1736,25 @@ static moo_oop_t multiply_unsigned_integers (moo_t* moo, moo_oop_t x, moo_oop_t | ||||
| 	return z; | ||||
| } | ||||
|  | ||||
| static moo_liw_t multiply_unsigned_array_in_place_and_get_last_carry (moo_liw_t* x, moo_oow_t xs, moo_liw_t y)  | ||||
| { | ||||
| 	/* multiply unsigned array with a single word and put the result  | ||||
| 	 * back to the array. return the last remaining carry */ | ||||
|  | ||||
| 	moo_lidw_t dw; | ||||
| 	moo_liw_t carry = 0; | ||||
| 	moo_oow_t i; | ||||
|  | ||||
| 	for (i = 0; i < xs; i++) | ||||
| 	{ | ||||
| 		dw = ((moo_lidw_t)x[i] * y) + carry; | ||||
| 		carry = (moo_liw_t)(dw >> MOO_LIW_BITS); | ||||
| 		x[i] = (moo_liw_t)dw/*& MOO_TYPE_MAX(moo_liw_t)*/; | ||||
| 	} | ||||
|  | ||||
| 	return carry; | ||||
| } | ||||
|  | ||||
| static moo_oop_t divide_unsigned_integers (moo_t* moo, moo_oop_t x, moo_oop_t y, moo_oop_t* r) | ||||
| { | ||||
| 	moo_oop_t qq, rr; | ||||
| @ -1960,7 +2009,7 @@ moo_oop_t moo_mulints (moo_t* moo, moo_oop_t x, moo_oop_t y) | ||||
|  | ||||
| 	if (MOO_OOP_IS_SMOOI(x) && MOO_OOP_IS_SMOOI(y)) | ||||
| 	{ | ||||
| 	#if MOO_SIZEOF_INTMAX_T > MOO_SIZEOF_OOI_T | ||||
| 	#if (MOO_SIZEOF_INTMAX_T > MOO_SIZEOF_OOI_T) | ||||
| 		moo_intmax_t i; | ||||
| 		i = (moo_intmax_t)MOO_OOP_TO_SMOOI(x) * (moo_intmax_t)MOO_OOP_TO_SMOOI(y); | ||||
| 		if (MOO_IN_SMOOI_RANGE(i)) return MOO_SMOOI_TO_OOP((moo_ooi_t)i); | ||||
| @ -1985,7 +2034,7 @@ moo_oop_t moo_mulints (moo_t* moo, moo_oop_t x, moo_oop_t y) | ||||
| 			moo_popvolat (moo); | ||||
| 			if (!y) return MOO_NULL; | ||||
|  | ||||
| 			goto normal; | ||||
| 			goto full_multiply; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @ -2045,7 +2094,7 @@ moo_oop_t moo_mulints (moo_t* moo, moo_oop_t x, moo_oop_t y) | ||||
| 			if (!is_bigint(moo,y)) goto oops_einval; | ||||
| 		} | ||||
|  | ||||
| 	normal: | ||||
| 	full_multiply: | ||||
| 		neg = (MOO_OBJ_GET_CLASS(x) != MOO_OBJ_GET_CLASS(y)); /* checking sign before multication. no need to preserve x and y */ | ||||
| 		z = multiply_unsigned_integers(moo, x, y); | ||||
| 		if (!z) return MOO_NULL; | ||||
| @ -2174,20 +2223,26 @@ moo_oop_t moo_divints (moo_t* moo, moo_oop_t x, moo_oop_t y, int modulo, moo_oop | ||||
|  | ||||
| 			if (!is_bigint(moo,y)) goto oops_einval; | ||||
|  | ||||
| 			/* divide a small integer by a big integer.  | ||||
| 			 * the dividend is guaranteed to be greater than the divisor | ||||
| 			 * if both are positive. */ | ||||
|  | ||||
| 			xv = MOO_OOP_TO_SMOOI(x); | ||||
| 			x_neg_sign = (xv < 0); | ||||
| 			y_neg_sign = MOO_POINTER_IS_NBIGINT(moo, y); | ||||
| 			if (x_neg_sign == y_neg_sign || !modulo) | ||||
| 			{ | ||||
| 				/* simple. the quotient is zero and the | ||||
| 				 * dividend becomes the remainder as a whole. */ | ||||
| 				if (rem) *rem = x; | ||||
| 				return MOO_SMOOI_TO_OOP(0); | ||||
| 			} | ||||
|  | ||||
| 			/* carry on to the full bigint division */ | ||||
| 			moo_pushvolat (moo, &y); | ||||
| 			x = make_bigint_with_ooi(moo, xv); | ||||
| 			moo_popvolat (moo); | ||||
| 			if (!x) return MOO_NULL; | ||||
| 			/* carry on the the full division */ | ||||
| 		} | ||||
| 		else if (MOO_OOP_IS_SMOOI(y)) | ||||
| 		{ | ||||
| @ -2195,6 +2250,8 @@ moo_oop_t moo_divints (moo_t* moo, moo_oop_t x, moo_oop_t y, int modulo, moo_oop | ||||
|  | ||||
| 			if (!is_bigint(moo,x)) goto oops_einval; | ||||
|  | ||||
| 			/* divide a big integer by a small integer. */ | ||||
|  | ||||
| 			yv = MOO_OOP_TO_SMOOI(y); | ||||
| 			switch (yv) | ||||
| 			{ | ||||
| @ -2208,7 +2265,6 @@ moo_oop_t moo_divints (moo_t* moo, moo_oop_t x, moo_oop_t y, int modulo, moo_oop | ||||
| 					if (rem) *rem = MOO_SMOOI_TO_OOP(0); | ||||
| 					return z; | ||||
|  | ||||
|  | ||||
| 				case -1: /* divide by -1 */ | ||||
| 					z = clone_bigint_negated(moo, x, MOO_OBJ_GET_SIZE(x)); | ||||
| 					if (!z) return MOO_NULL; | ||||
| @ -2224,6 +2280,10 @@ moo_oop_t moo_divints (moo_t* moo, moo_oop_t x, moo_oop_t y, int modulo, moo_oop | ||||
| 					moo_ooi_t yv_abs, ri; | ||||
|  | ||||
| 					yv_abs = (yv < 0)? -yv: yv; | ||||
| 				#if (MOO_LIW_BITS < MOO_OOI_BITS) | ||||
| 					if (yv_abs > MOO_TYPE_MAX(moo_liw_t)) break; | ||||
| 				#endif | ||||
|  | ||||
| 					x_neg_sign = (MOO_POINTER_IS_NBIGINT(moo, x)); | ||||
| 					y_neg_sign = (yv < 0); | ||||
|  | ||||
| @ -2273,6 +2333,7 @@ moo_oop_t moo_divints (moo_t* moo, moo_oop_t x, moo_oop_t y, int modulo, moo_oop | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			/* carry on to the full bigint division */ | ||||
| 			moo_pushvolat (moo, &x); | ||||
| 			y = make_bigint_with_ooi(moo, yv); | ||||
| 			moo_popvolat (moo); | ||||
| @ -4278,20 +4339,6 @@ moo_oop_t moo_absint (moo_t* moo, moo_oop_t x) | ||||
| 	return x; | ||||
| } | ||||
|  | ||||
| static MOO_INLINE moo_liw_t div_with_carry (moo_liw_t x, moo_liw_t y, moo_liw_t* r) | ||||
| { | ||||
| /* TODO: optimize it with ASM */ | ||||
| 	moo_liw_t q; | ||||
| 	moo_lidw_t dd; | ||||
|  | ||||
| 	dd = ((moo_lidw_t)*r << MOO_LIW_BITS) + x; | ||||
|  | ||||
| 	q = dd / y; | ||||
| 	*r = dd % y; | ||||
|  | ||||
| 	return q; | ||||
| } | ||||
|  | ||||
| static MOO_INLINE moo_liw_t get_last_digit (moo_t* moo, moo_liw_t* x, moo_oow_t* xs, int radix) | ||||
| { | ||||
| 	/* this function changes the contents of the large integer word array */ | ||||
| @ -4305,40 +4352,20 @@ static MOO_INLINE moo_liw_t get_last_digit (moo_t* moo, moo_liw_t* x, moo_oow_t* | ||||
| 	for (i = oxs; i > 0; ) | ||||
| 	{ | ||||
| 		--i; | ||||
| 	#if 0 | ||||
| 		x[i] = div_with_carry(x[i], radix, &carry); | ||||
| 	#else | ||||
| 		dw = ((moo_lidw_t)carry << MOO_LIW_BITS) + x[i]; | ||||
| 		/* TODO: optimize it with ASM - no seperate / and % */ | ||||
| 		x[i] = dw / radix; | ||||
| 		carry = dw % radix; | ||||
| 	#endif | ||||
| 	} | ||||
| 	if (/*oxs > 0 &&*/ x[oxs - 1] == 0) *xs = oxs - 1; | ||||
| 	return carry; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| moo_oop_t moo_inttostr (moo_t* moo, moo_oop_t num, int flagged_radix) | ||||
| { | ||||
| 	moo_ooi_t v = 0; | ||||
| 	moo_oow_t w; | ||||
| 	moo_oow_t as; | ||||
|  | ||||
| /*#define INTTOSTR_SLOW_WORD_BY_WORD_CONVERSION*/ | ||||
| #if defined(INTTOSTR_SLOW_WORD_BY_WORD_CONVERSION) | ||||
| 	moo_oow_t bs, rs; | ||||
| #if (MOO_LIW_BITS == MOO_OOW_BITS) | ||||
| 	moo_liw_t b[1]; | ||||
| #elif (MOO_LIW_BITS == MOO_OOHW_BITS) | ||||
| 	moo_liw_t b[2]; | ||||
| #else | ||||
| #	error UNSUPPORTED LIW BIT SIZE | ||||
| #endif | ||||
| 	moo_liw_t* a, * q, * r; | ||||
| #endif | ||||
|  | ||||
| 	moo_liw_t* t = MOO_NULL; | ||||
| 	moo_ooch_t* xbuf = MOO_NULL; | ||||
| 	moo_oow_t xlen = 0, reqcapa; | ||||
| @ -4389,174 +4416,6 @@ moo_oop_t moo_inttostr (moo_t* moo, moo_oop_t num, int flagged_radix) | ||||
|  | ||||
| 	as = MOO_OBJ_GET_SIZE(num); | ||||
|  | ||||
| #if defined(INTTOSTR_SLOW_WORD_BY_WORD_CONVERSION) | ||||
| 	if (IS_POW2(radix)) | ||||
| 	{ | ||||
| 		unsigned int exp, accbits; | ||||
| 		moo_lidw_t acc; | ||||
| 		moo_oow_t xpos; | ||||
|  | ||||
| 		/*exp = LOG2_FOR_POW2(radix);*/ | ||||
| 		exp = _exp_tab[radix - 1]; | ||||
| 		xlen = as * ((MOO_LIW_BITS + exp) / exp) + 1; | ||||
| 		xpos = xlen; | ||||
|  | ||||
| 		reqcapa = xlen;  | ||||
| 		if (moo->inttostr.xbuf.capa < reqcapa) | ||||
| 		{ | ||||
| 			xbuf = (moo_ooch_t*)moo_reallocmem(moo, moo->inttostr.xbuf.ptr, reqcapa * MOO_SIZEOF(*xbuf)); | ||||
| 			if (!xbuf) return MOO_NULL; | ||||
| 			moo->inttostr.xbuf.capa = reqcapa; | ||||
| 			moo->inttostr.xbuf.ptr = xbuf; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			xbuf = moo->inttostr.xbuf.ptr; | ||||
| 		} | ||||
|  | ||||
| 		acc = 0; | ||||
| 		accbits = 0; | ||||
|  | ||||
| 		w = 0; | ||||
| 		while (w < as) | ||||
| 		{ | ||||
| 			acc |= (moo_lidw_t)MOO_OBJ_GET_LIWORD_SLOT(num)[w] << accbits; | ||||
| 			accbits += MOO_LIW_BITS; | ||||
|  | ||||
| 			w++; | ||||
| 			do | ||||
| 			{ | ||||
| 				xbuf[--xpos] = _digitc[acc & (radix - 1)]; /* acc % radix */ | ||||
| 				accbits -= exp; | ||||
| 				acc >>= exp; | ||||
| 				if (w < as) | ||||
| 				{ | ||||
| 					if (accbits < exp) break; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					if (acc <= 0) break; | ||||
| 				} | ||||
| 			} | ||||
| 			while (1); | ||||
| 		} | ||||
|  | ||||
| 		MOO_ASSERT (moo, xpos >= 1); | ||||
| 		if (MOO_POINTER_IS_NBIGINT(moo, num)) xbuf[--xpos] = '-'; | ||||
|  | ||||
| 		if (flagged_radix & MOO_INTTOSTR_NONEWOBJ) | ||||
| 		{ | ||||
| 			/* special case. don't create a new object. | ||||
| 			 * the caller can use the data left in moo->inttostr.xbuf */ | ||||
| 			MOO_MEMMOVE (&xbuf[0], &xbuf[xpos], MOO_SIZEOF(*xbuf) * (xlen - xpos)); | ||||
| 			moo->inttostr.xbuf.len = xlen - xpos; | ||||
| 			return moo->_nil; | ||||
| 		} | ||||
|  | ||||
| 		return moo_makestring(moo, &xbuf[xpos], xlen - xpos); | ||||
| 	} | ||||
|  | ||||
| 	/* Do it in a hard way for other cases */ | ||||
|  | ||||
| /* TODO: find an optimial buffer size */ | ||||
| 	reqcapa = as * MOO_LIW_BITS + 1;  | ||||
| 	if (moo->inttostr.xbuf.capa < reqcapa) | ||||
| 	{ | ||||
| 		xbuf = (moo_ooch_t*)moo_reallocmem(moo, moo->inttostr.xbuf.ptr, reqcapa * MOO_SIZEOF(*xbuf)); | ||||
| 		if (!xbuf) return MOO_NULL; | ||||
| 		moo->inttostr.xbuf.capa = reqcapa; | ||||
| 		moo->inttostr.xbuf.ptr = xbuf; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		xbuf = moo->inttostr.xbuf.ptr; | ||||
| 	} | ||||
|   | ||||
| 	reqcapa = as * 3; | ||||
| 	if (moo->inttostr.t.capa < reqcapa) | ||||
| 	{ | ||||
| 		t = (moo_liw_t*)moo_reallocmem(moo, moo->inttostr.t.ptr, reqcapa * MOO_SIZEOF(*t)); | ||||
| 		if (!t) return MOO_NULL; | ||||
| 		moo->inttostr.t.capa = reqcapa; | ||||
| 		moo->inttostr.t.ptr = t; | ||||
| 	} | ||||
| 	else  | ||||
| 	{ | ||||
| 		t = moo->inttostr.t.ptr; | ||||
| 	} | ||||
|  | ||||
| #if (MOO_LIW_BITS == MOO_OOW_BITS) | ||||
| 	b[0] = moo->bigint[radix].multiplier; /* block divisor */ | ||||
| 	bs = 1; | ||||
| #elif (MOO_LIW_BITS == MOO_OOHW_BITS) | ||||
| 	b[0] = moo->bigint[radix].multiplier /*& MOO_LBMASK(moo_oow_t, MOO_LIW_BITS)*/; | ||||
| 	b[1] = moo->bigint[radix].multiplier >> MOO_LIW_BITS; | ||||
| 	bs = (b[1] > 0)? 2: 1; | ||||
| #else | ||||
| #	error UNSUPPORTED LIW BIT SIZE | ||||
| #endif | ||||
|  | ||||
| 	a = &t[0]; /* temporary space for the number to convert */ | ||||
| 	q = &t[as]; /* temporary space for intermediate quotient */ | ||||
| 	r = &t[as * 2]; /* temporary space for intermediate remainder */ | ||||
|  | ||||
| 	MOO_MEMCPY (a, MOO_OBJ_GET_LIWORD_SLOT(num), MOO_SIZEOF(*a) * as); | ||||
|  | ||||
| 	do | ||||
| 	{ | ||||
| 		moo_oow_t seglen; | ||||
| 		/* NOTE: this loop is super-slow */ | ||||
|  | ||||
| 		if (is_less_unsigned_array(b, bs, a, as)) | ||||
| 		{ | ||||
| 			moo_liw_t* tmp; | ||||
|  | ||||
| 			divide_unsigned_array(moo, a, as, b, bs, q, r); | ||||
|  | ||||
| 			/* get 'rs' before 'as' gets changed */ | ||||
| 			rs = count_effective(r, as);  | ||||
|   | ||||
| 			/* swap a and q for later division */ | ||||
| 			tmp = a; | ||||
| 			a = q; | ||||
| 			q = tmp; | ||||
|  | ||||
| 			as = count_effective(a, as); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* it is the last block */ | ||||
| 			r = a; | ||||
| 			rs = as; | ||||
| 		} | ||||
|  | ||||
| 	#if (MOO_LIW_BITS == MOO_OOW_BITS) | ||||
| 		MOO_ASSERT (moo, rs == 1); | ||||
| 		w = r[0]; | ||||
| 	#elif (MOO_LIW_BITS == MOO_OOHW_BITS) | ||||
| 		if (rs == 1) w = r[0]; | ||||
| 		else  | ||||
| 		{ | ||||
| 			MOO_ASSERT (moo, rs == 2); | ||||
| 			w = MAKE_WORD(r[0], r[1]); | ||||
| 		} | ||||
| 	#else | ||||
| 	#	error UNSUPPORTED LIW BIT SIZE | ||||
| 	#endif | ||||
| 		seglen = oow_to_text(moo, w, flagged_radix, &xbuf[xlen]); | ||||
| 		xlen += seglen; | ||||
| 		if (r == a) break; /* reached the last block */ | ||||
|  | ||||
| 		/* fill unfilled leading digits with zeros as it's not  | ||||
| 		 * the last block */ | ||||
| 		while (seglen < moo->bigint[radix].safe_ndigits) | ||||
| 		{ | ||||
| 			xbuf[xlen++] = '0'; | ||||
| 			seglen++; | ||||
| 		} | ||||
| 	} | ||||
| 	while (1); | ||||
| #else | ||||
| 	reqcapa = as * MOO_LIW_BITS + 1;  | ||||
| 	if (moo->inttostr.xbuf.capa < reqcapa) | ||||
| 	{ | ||||
| @ -4590,7 +4449,6 @@ moo_oop_t moo_inttostr (moo_t* moo, moo_oop_t num, int flagged_radix) | ||||
| 		xbuf[xlen++] = _digitc[dv]; | ||||
| 	} | ||||
| 	while (as > 0); | ||||
| #endif | ||||
|  | ||||
| 	if (MOO_POINTER_IS_NBIGINT(moo, num)) xbuf[xlen++] = '-'; | ||||
| 	reverse_string (xbuf, xlen); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user