This commit is contained in:
		
							
								
								
									
										205
									
								
								lib/bigint.c
									
									
									
									
									
								
							
							
						
						
									
										205
									
								
								lib/bigint.c
									
									
									
									
									
								
							| @ -92,7 +92,6 @@ static const hcl_uint8_t debruijn_64[64] = | |||||||
| #	define LOG2_FOR_POW2(x) hcl_get_pos_of_msb_set_pow2(x) | #	define LOG2_FOR_POW2(x) hcl_get_pos_of_msb_set_pow2(x) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| #if (HCL_SIZEOF_OOW_T == HCL_SIZEOF_INT) && defined(HCL_HAVE_BUILTIN_UADD_OVERFLOW) | #if (HCL_SIZEOF_OOW_T == HCL_SIZEOF_INT) && defined(HCL_HAVE_BUILTIN_UADD_OVERFLOW) | ||||||
| #	define oow_add_overflow(a,b,c)  __builtin_uadd_overflow(a,b,c) | #	define oow_add_overflow(a,b,c)  __builtin_uadd_overflow(a,b,c) | ||||||
| #elif (HCL_SIZEOF_OOW_T == HCL_SIZEOF_LONG) && defined(HCL_HAVE_BUILTIN_UADDL_OVERFLOW) | #elif (HCL_SIZEOF_OOW_T == HCL_SIZEOF_LONG) && defined(HCL_HAVE_BUILTIN_UADDL_OVERFLOW) | ||||||
| @ -107,7 +106,6 @@ static HCL_INLINE int oow_add_overflow (hcl_oow_t a, hcl_oow_t b, hcl_oow_t* c) | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| #if (HCL_SIZEOF_OOW_T == HCL_SIZEOF_INT) && defined(HCL_HAVE_BUILTIN_UMUL_OVERFLOW) | #if (HCL_SIZEOF_OOW_T == HCL_SIZEOF_INT) && defined(HCL_HAVE_BUILTIN_UMUL_OVERFLOW) | ||||||
| #	define oow_mul_overflow(a,b,c)  __builtin_umul_overflow(a,b,c) | #	define oow_mul_overflow(a,b,c)  __builtin_umul_overflow(a,b,c) | ||||||
| #elif (HCL_SIZEOF_OOW_T == HCL_SIZEOF_LONG) && defined(HCL_HAVE_BUILTIN_UMULL_OVERFLOW) | #elif (HCL_SIZEOF_OOW_T == HCL_SIZEOF_LONG) && defined(HCL_HAVE_BUILTIN_UMULL_OVERFLOW) | ||||||
| @ -418,7 +416,7 @@ int hcl_inttoooi (hcl_t* hcl, hcl_oop_t x, hcl_ooi_t* i) | |||||||
|  |  | ||||||
| 	/* do nothing. required macros are defined in hcl.h */ | 	/* do nothing. required macros are defined in hcl.h */ | ||||||
|  |  | ||||||
| #elif (HCL_SIZEOF_UINTMAX_T == HCL_SIZEOF_OOW_T * 2) | #elif (HCL_SIZEOF_UINTMAX_T == HCL_SIZEOF_OOW_T * 2) || (HCL_SIZEOF_UINTMAX_T == HCL_SIZEOF_OOW_T * 4) | ||||||
| static HCL_INLINE int bigint_to_uintmax (hcl_t* hcl, hcl_oop_t num, hcl_uintmax_t* w) | static HCL_INLINE int bigint_to_uintmax (hcl_t* hcl, hcl_oop_t num, hcl_uintmax_t* w) | ||||||
| { | { | ||||||
| 	HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(num)); | 	HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(num)); | ||||||
| @ -434,9 +432,25 @@ static HCL_INLINE int bigint_to_uintmax (hcl_t* hcl, hcl_oop_t num, hcl_uintmax_ | |||||||
| 			goto done; | 			goto done; | ||||||
|  |  | ||||||
| 		case 2: | 		case 2: | ||||||
| 			*w = ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 0) << HCL_LIW_BITS) | HCL_OBJ_GET_WORD_VAL(num, 1); | 			*w = ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 0) << HCL_LIW_BITS) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 1)); | ||||||
| 			goto done; | 			goto done; | ||||||
|  |  | ||||||
|  | 	#if (HCL_SIZEOF_UINTMAX_T >= HCL_SIZEOF_OOW_T * 4) | ||||||
|  | 		case 3: | ||||||
|  | 			*w = ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 0) << (HCL_LIW_BITS * 2)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 1) << (HCL_LIW_BITS * 1)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 2)) | ||||||
|  | 			goto done; | ||||||
|  |  | ||||||
|  | 		case 4: | ||||||
|  | 			*w = ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 0) << (HCL_LIW_BITS * 3)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 1) << (HCL_LIW_BITS * 2)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 2) << (HCL_LIW_BITS * 1)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_WORD_VAL(num, 3)) | ||||||
|  | 			goto done; | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			goto oops_range; | 			goto oops_range; | ||||||
| 	} | 	} | ||||||
| @ -446,16 +460,39 @@ static HCL_INLINE int bigint_to_uintmax (hcl_t* hcl, hcl_oop_t num, hcl_uintmax_ | |||||||
| 	switch (HCL_OBJ_GET_SIZE(num)) | 	switch (HCL_OBJ_GET_SIZE(num)) | ||||||
| 	{ | 	{ | ||||||
| 		case 2: | 		case 2: | ||||||
| 			*w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << HCL_LIW_BITS) | HCL_OBJ_GET_HALFWORD_VAL(num, 1); | 			*w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << HCL_LIW_BITS) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 1)); | ||||||
| 			goto done; | 			goto done; | ||||||
|  |  | ||||||
| 		case 4: | 		case 4: | ||||||
| 			*w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << HCL_LIW_BITS * 3) | | 			*w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << (HCL_LIW_BITS * 3)) | | ||||||
| 				((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 1) << HCL_LIW_BITS * 2) | | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 1) << (HCL_LIW_BITS * 2)) | | ||||||
| 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 2) << HCL_LIW_BITS * 1) | | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 2) << (HCL_LIW_BITS * 1)) | | ||||||
| 			     HCL_OBJ_GET_HALFWORD_VAL(num, 3); | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 3)); | ||||||
| 			goto done; | 			goto done; | ||||||
|  |  | ||||||
|  | 	#if (HCL_SIZEOF_UINTMAX_T >= HCL_SIZEOF_OOW_T * 4) | ||||||
|  | 		case 6: | ||||||
|  | 			*w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << (HCL_LIW_BITS * 5)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 1) << (HCL_LIW_BITS * 4)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 2) << (HCL_LIW_BITS * 3)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 3) << (HCL_LIW_BITS * 2)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 4) << (HCL_LIW_BITS * 1)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 5)); | ||||||
|  | 			goto done; | ||||||
|  |  | ||||||
|  | 		case 8: | ||||||
|  | 			*w = ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 0) << (HCL_LIW_BITS * 7)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 1) << (HCL_LIW_BITS * 6)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 2) << (HCL_LIW_BITS * 5)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 3) << (HCL_LIW_BITS * 4)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 4) << (HCL_LIW_BITS * 3)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 5) << (HCL_LIW_BITS * 2)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 6) << (HCL_LIW_BITS * 1)) | | ||||||
|  | 			     ((hcl_uintmax_t)HCL_OBJ_GET_HALFWORD_VAL(num, 7)); | ||||||
|  | 			goto done; | ||||||
|  | 	#endif | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			goto oops_range; | 			goto oops_range; | ||||||
| 	} | 	} | ||||||
| @ -529,7 +566,6 @@ int hcl_inttointmax (hcl_t* hcl, hcl_oop_t x, hcl_intmax_t* i) | |||||||
| #	error UNSUPPORTED UINTMAX SIZE | #	error UNSUPPORTED UINTMAX SIZE | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| static HCL_INLINE hcl_oop_t make_bigint_with_oow (hcl_t* hcl, hcl_oow_t w) | static HCL_INLINE hcl_oop_t make_bigint_with_oow (hcl_t* hcl, hcl_oow_t w) | ||||||
| { | { | ||||||
| #if (HCL_LIW_BITS == HCL_OOW_BITS) | #if (HCL_LIW_BITS == HCL_OOW_BITS) | ||||||
| @ -605,7 +641,7 @@ static HCL_INLINE hcl_oop_t make_bloated_bigint_with_ooi (hcl_t* hcl, hcl_ooi_t | |||||||
| 		z = make_nbigint(hcl, HCL_NULL, 1 + extra); | 		z = make_nbigint(hcl, HCL_NULL, 1 + extra); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (!z) return HCL_NULL; | 	if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
| 	HCL_OBJ_SET_LIWORD_VAL (z, 0, w); | 	HCL_OBJ_SET_LIWORD_VAL (z, 0, w); | ||||||
| 	return z; | 	return z; | ||||||
|  |  | ||||||
| @ -630,7 +666,7 @@ static HCL_INLINE hcl_oop_t make_bloated_bigint_with_ooi (hcl_t* hcl, hcl_ooi_t | |||||||
| 		z = make_nbigint(hcl, HCL_NULL, (hw[1] > 0? 2: 1) + extra); | 		z = make_nbigint(hcl, HCL_NULL, (hw[1] > 0? 2: 1) + extra); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (!z) return HCL_NULL; | 	if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
| 	HCL_OBJ_SET_LIWORD_VAL (z, 0, hw[0]); | 	HCL_OBJ_SET_LIWORD_VAL (z, 0, hw[0]); | ||||||
| 	if (hw[1] > 0) HCL_OBJ_SET_LIWORD_VAL (z, 1, hw[1]); | 	if (hw[1] > 0) HCL_OBJ_SET_LIWORD_VAL (z, 1, hw[1]); | ||||||
| 	return z; | 	return z; | ||||||
| @ -760,7 +796,7 @@ static HCL_INLINE hcl_oop_t expand_bigint (hcl_t* hcl, hcl_oop_t oop, hcl_oow_t | |||||||
| 	hcl_pushvolat (hcl, &oop); | 	hcl_pushvolat (hcl, &oop); | ||||||
| 	z = hcl_instantiate(hcl, (hcl_oop_class_t)HCL_OBJ_GET_CLASS(oop), HCL_NULL, count + inc); | 	z = hcl_instantiate(hcl, (hcl_oop_class_t)HCL_OBJ_GET_CLASS(oop), HCL_NULL, count + inc); | ||||||
| 	hcl_popvolat (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (!z) | 	if (HCL_UNLIKELY(!z)) | ||||||
| 	{ | 	{ | ||||||
| 		const hcl_ooch_t* orgmsg = hcl_backuperrmsg(hcl); | 		const hcl_ooch_t* orgmsg = hcl_backuperrmsg(hcl); | ||||||
| 		hcl_seterrbfmt (hcl, HCL_ERRNUM(hcl), "unable to clone bigint %O for expansion - %s", oop, orgmsg); | 		hcl_seterrbfmt (hcl, HCL_ERRNUM(hcl), "unable to clone bigint %O for expansion - %s", oop, orgmsg); | ||||||
| @ -782,12 +818,10 @@ static HCL_INLINE hcl_oop_t _clone_bigint(hcl_t* hcl, hcl_oop_t oop, hcl_oow_t c | |||||||
| 	HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(oop)); | 	HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(oop)); | ||||||
| 	if (count <= 0) count = HCL_OBJ_GET_SIZE(oop); | 	if (count <= 0) count = HCL_OBJ_GET_SIZE(oop); | ||||||
|  |  | ||||||
| 	hcl_pushvolat (hcl, (hcl_oop_t*)&_class); |  | ||||||
| 	hcl_pushvolat (hcl, &oop); | 	hcl_pushvolat (hcl, &oop); | ||||||
| 	z = hcl_instantiate(hcl, _class, HCL_NULL, count); | 	z = hcl_instantiate(hcl, _class, HCL_NULL, count); | ||||||
| 	hcl_popvolat (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	hcl_popvolat (hcl); | 	if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
| 	if (!z) return HCL_NULL; |  | ||||||
|  |  | ||||||
| 	for (i = 0; i < count; i++) | 	for (i = 0; i < count; i++) | ||||||
| 	{ | 	{ | ||||||
| @ -986,7 +1020,7 @@ static HCL_INLINE int is_equal_unsigned (hcl_oop_t x, hcl_oop_t y) | |||||||
| static HCL_INLINE int is_equal (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | static HCL_INLINE int is_equal (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | ||||||
| { | { | ||||||
| 	/* check if two large integers are equal to each other */ | 	/* check if two large integers are equal to each other */ | ||||||
| 	/*return HCL_OBJ_GET_FLAGS_BRAND(x) == HCL_OBJ_GET_FLAGS_BRAND(y) && HCL_OBJ_GET_SIZE(x) == HCL_OBJ_GET_SIZE(y) && | 	/*return HCL_OBJ_GET_CLASS(x) == HCL_OBJ_GET_CLASS(y) && HCL_OBJ_GET_SIZE(x) == HCL_OBJ_GET_SIZE(y) && | ||||||
| 	       HCL_MEMCMP(((hcl_oop_liword_t)x)->slot,  ((hcl_oop_liword_t)y)->slot, HCL_OBJ_GET_SIZE(x) * HCL_SIZEOF(hcl_liw_t)) == 0;*/ | 	       HCL_MEMCMP(((hcl_oop_liword_t)x)->slot,  ((hcl_oop_liword_t)y)->slot, HCL_OBJ_GET_SIZE(x) * HCL_SIZEOF(hcl_liw_t)) == 0;*/ | ||||||
| 	return HCL_OBJ_GET_CLASS(x) == HCL_OBJ_GET_CLASS(y) && HCL_OBJ_GET_SIZE(x) == HCL_OBJ_GET_SIZE(y) && is_equal_unsigned(x, y); | 	return HCL_OBJ_GET_CLASS(x) == HCL_OBJ_GET_CLASS(y) && HCL_OBJ_GET_SIZE(x) == HCL_OBJ_GET_SIZE(y) && is_equal_unsigned(x, y); | ||||||
| } | } | ||||||
| @ -1423,13 +1457,13 @@ static HCL_INLINE hcl_oow_t multiply_unsigned_array_karatsuba (hcl_t* hcl, const | |||||||
| 	tmplen[0] = ndigits_xh + ndigits_yh; | 	tmplen[0] = ndigits_xh + ndigits_yh; | ||||||
| 	tmplen[1] = ndigits_yl + ndigits_yh + 1; | 	tmplen[1] = ndigits_yl + ndigits_yh + 1; | ||||||
| 	if (tmplen[1] < tmplen[0]) tmplen[1] = tmplen[0]; | 	if (tmplen[1] < tmplen[0]) tmplen[1] = tmplen[0]; | ||||||
| 	tmp[1] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[1]); /* TODO: should i use the object memory? */ | 	tmp[1] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[1]); /* TODO: should i use the object memory? if not, reuse the buffer and minimize memory allocation */ | ||||||
| 	if (!tmp[1]) goto oops; | 	if (HCL_UNLIKELY(!tmp[1])) goto oops; | ||||||
|  |  | ||||||
| 	/* make a temporary for (a0 + a1) and (a0 * b0) */ | 	/* make a temporary for (a0 + a1) and (a0 * b0) */ | ||||||
| 	tmplen[0] = ndigits_xl + ndigits_yl + 1; | 	tmplen[0] = ndigits_xl + ndigits_yl + 1; | ||||||
| 	tmp[0] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[0]); | 	tmp[0] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[0]); | ||||||
| 	if (!tmp[0]) goto oops; | 	if (HCL_UNLIKELY(!tmp[0])) goto oops; | ||||||
|  |  | ||||||
| 	/* tmp[0] = a0 + a1 */ | 	/* tmp[0] = a0 + a1 */ | ||||||
| 	tmplen[0] = add_unsigned_array(x, ndigits_xl, x + nshifts, ndigits_xh, tmp[0]); | 	tmplen[0] = add_unsigned_array(x, ndigits_xl, x + nshifts, ndigits_xh, tmp[0]); | ||||||
| @ -1560,12 +1594,12 @@ oops: | |||||||
| 	tmplen[0] = ndigits_yl + ndigits_yh + 1; | 	tmplen[0] = ndigits_yl + ndigits_yh + 1; | ||||||
| 	tmplen[1] = ndigits_xh + ndigits_yh; | 	tmplen[1] = ndigits_xh + ndigits_yh; | ||||||
| 	if (tmplen[1] < tmplen[0]) tmplen[1] = tmplen[0]; | 	if (tmplen[1] < tmplen[0]) tmplen[1] = tmplen[0]; | ||||||
| 	tmp[1] = hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[1]); | 	tmp[1] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[1]); | ||||||
| 	if (!tmp[1]) goto oops; | 	if (!tmp[1]) goto oops; | ||||||
|  |  | ||||||
| 	/* make a temporary for (a0 + a1) and (a0 * b0) */ | 	/* make a temporary for (a0 + a1) and (a0 * b0) */ | ||||||
| 	tmplen[0] = ndigits_xl + ndigits_yl; | 	tmplen[0] = ndigits_xl + ndigits_yl; | ||||||
| 	tmp[0] = hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[0]); | 	tmp[0] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[0]); | ||||||
| 	if (!tmp[0]) goto oops; | 	if (!tmp[0]) goto oops; | ||||||
|  |  | ||||||
| 	/* tmp[0] = a0 + a1 */ | 	/* tmp[0] = a0 + a1 */ | ||||||
| @ -1576,7 +1610,7 @@ oops: | |||||||
|  |  | ||||||
| 	/* tmp[2] = (a0 + a1) * (b0 + b1) */ | 	/* tmp[2] = (a0 + a1) * (b0 + b1) */ | ||||||
| 	tmplen[2] = tmplen[0] + tmplen[1]; | 	tmplen[2] = tmplen[0] + tmplen[1]; | ||||||
| 	tmp[2] = hcl_callocmem (hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[2]); | 	tmp[2] = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(hcl_liw_t) * tmplen[2]); | ||||||
| 	if (!tmp[2]) goto oops; | 	if (!tmp[2]) goto oops; | ||||||
| 	if (CANNOT_KARATSUBA(hcl, tmplen[0], tmplen[1])) | 	if (CANNOT_KARATSUBA(hcl, tmplen[0], tmplen[1])) | ||||||
| 	{ | 	{ | ||||||
| @ -2113,7 +2147,7 @@ static hcl_oop_t add_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 	hcl_pushvolat (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
| 	z = hcl_instantiate(hcl, (hcl_oop_class_t)HCL_OBJ_GET_CLASS(x), HCL_NULL, zs); | 	z = hcl_instantiate(hcl, (hcl_oop_class_t)HCL_OBJ_GET_CLASS(x), HCL_NULL, zs); | ||||||
| 	hcl_popvolats (hcl, 2); | 	hcl_popvolats (hcl, 2); | ||||||
| 	if (!z) return HCL_NULL; | 	if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 	add_unsigned_array ( | 	add_unsigned_array ( | ||||||
| 		((hcl_oop_liword_t)x)->slot, as, | 		((hcl_oop_liword_t)x)->slot, as, | ||||||
| @ -2134,7 +2168,7 @@ static hcl_oop_t subtract_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t | |||||||
| 	hcl_pushvolat (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
| 	z = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(x)); | 	z = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(x)); | ||||||
| 	hcl_popvolats (hcl, 2); | 	hcl_popvolats (hcl, 2); | ||||||
| 	if (!z) return HCL_NULL; | 	if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 	subtract_unsigned_array (hcl, | 	subtract_unsigned_array (hcl, | ||||||
| 		((hcl_oop_liword_t)x)->slot, HCL_OBJ_GET_SIZE(x), | 		((hcl_oop_liword_t)x)->slot, HCL_OBJ_GET_SIZE(x), | ||||||
| @ -2161,7 +2195,7 @@ static hcl_oop_t multiply_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t | |||||||
| 	hcl_pushvolat (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
| 	z = make_pbigint(hcl, HCL_NULL, xs + ys); | 	z = make_pbigint(hcl, HCL_NULL, xs + ys); | ||||||
| 	hcl_popvolats (hcl, 2); | 	hcl_popvolats (hcl, 2); | ||||||
| 	if (!z) return HCL_NULL; | 	if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| #if defined(HCL_ENABLE_KARATSUBA) | #if defined(HCL_ENABLE_KARATSUBA) | ||||||
| 	if (CANNOT_KARATSUBA(hcl, xs, ys)) | 	if (CANNOT_KARATSUBA(hcl, xs, ys)) | ||||||
| @ -2229,7 +2263,7 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, | |||||||
| #else | #else | ||||||
| 	qq = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(x)); | 	qq = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(x)); | ||||||
| #endif | #endif | ||||||
| 	if (!qq) | 	if (HCL_UNLIKELY(!qq)) | ||||||
| 	{ | 	{ | ||||||
| 		hcl_popvolats (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		return HCL_NULL; | 		return HCL_NULL; | ||||||
| @ -2244,8 +2278,7 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, | |||||||
| 	rr = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(y) + 1); | 	rr = make_pbigint(hcl, HCL_NULL, HCL_OBJ_GET_SIZE(y) + 1); | ||||||
| #endif | #endif | ||||||
| 	hcl_popvolats (hcl, 3); | 	hcl_popvolats (hcl, 3); | ||||||
| 	if (!rr) return HCL_NULL; | 	if (HCL_UNLIKELY(!rr)) return HCL_NULL; | ||||||
|  |  | ||||||
|  |  | ||||||
| #if defined(USE_DIVIDE_UNSIGNED_ARRAY3) | #if defined(USE_DIVIDE_UNSIGNED_ARRAY3) | ||||||
| 	divide_unsigned_array3 (hcl, | 	divide_unsigned_array3 (hcl, | ||||||
| @ -2256,7 +2289,8 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, | |||||||
| #endif | #endif | ||||||
| 		((hcl_oop_liword_t)x)->slot, HCL_OBJ_GET_SIZE(x), | 		((hcl_oop_liword_t)x)->slot, HCL_OBJ_GET_SIZE(x), | ||||||
| 		((hcl_oop_liword_t)y)->slot, HCL_OBJ_GET_SIZE(y), | 		((hcl_oop_liword_t)y)->slot, HCL_OBJ_GET_SIZE(y), | ||||||
| 		((hcl_oop_liword_t)qq)->slot, ((hcl_oop_liword_t)rr)->slot); | 		((hcl_oop_liword_t)qq)->slot, ((hcl_oop_liword_t)rr)->slot | ||||||
|  | 	); | ||||||
|  |  | ||||||
| 	*r = rr; | 	*r = rr; | ||||||
| 	return qq; | 	return qq; | ||||||
| @ -2296,7 +2330,7 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			hcl_pushvolat (hcl, &y); | 			hcl_pushvolat (hcl, &y); | ||||||
| 			x = make_bigint_with_ooi(hcl, v); | 			x = make_bigint_with_ooi(hcl, v); | ||||||
| 			hcl_popvolat (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!x) return HCL_NULL; | 			if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else if (HCL_OOP_IS_SMOOI(y)) | 		else if (HCL_OOP_IS_SMOOI(y)) | ||||||
| 		{ | 		{ | ||||||
| @ -2308,7 +2342,7 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			hcl_pushvolat (hcl, &x); | 			hcl_pushvolat (hcl, &x); | ||||||
| 			y = make_bigint_with_ooi(hcl, v); | 			y = make_bigint_with_ooi(hcl, v); | ||||||
| 			hcl_popvolat (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!y) return HCL_NULL; | 			if (HCL_UNLIKELY(!y)) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| @ -2404,7 +2438,7 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			hcl_pushvolat (hcl, &y); | 			hcl_pushvolat (hcl, &y); | ||||||
| 			x = make_bigint_with_ooi(hcl, v); | 			x = make_bigint_with_ooi(hcl, v); | ||||||
| 			hcl_popvolat (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!x) return HCL_NULL; | 			if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else if (HCL_OOP_IS_SMOOI(y)) | 		else if (HCL_OOP_IS_SMOOI(y)) | ||||||
| 		{ | 		{ | ||||||
| @ -2416,7 +2450,7 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			hcl_pushvolat (hcl, &x); | 			hcl_pushvolat (hcl, &x); | ||||||
| 			y = make_bigint_with_ooi(hcl, v); | 			y = make_bigint_with_ooi(hcl, v); | ||||||
| 			hcl_popvolat (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!y) return HCL_NULL; | 			if (HCL_UNLIKELY(!y)) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| @ -2428,7 +2462,7 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		{ | 		{ | ||||||
| 			neg = HCL_IS_NBIGINT(hcl, x); | 			neg = HCL_IS_NBIGINT(hcl, x); | ||||||
| 			z = add_unsigned_integers(hcl, x, y); | 			z = add_unsigned_integers(hcl, x, y); | ||||||
| 			if (!z) return HCL_NULL; | 			if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
| 			if (neg) HCL_OBJ_SET_CLASS (z, (hcl_oop_t)hcl->c_large_negative_integer); | 			if (neg) HCL_OBJ_SET_CLASS (z, (hcl_oop_t)hcl->c_large_negative_integer); | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| @ -2695,7 +2729,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 			hcl_pushvolat (hcl, &y); | 			hcl_pushvolat (hcl, &y); | ||||||
| 			x = make_bigint_with_ooi(hcl, xv); | 			x = make_bigint_with_ooi(hcl, xv); | ||||||
| 			hcl_popvolat (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!x) return HCL_NULL; | 			if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else if (HCL_OOP_IS_SMOOI(y)) | 		else if (HCL_OOP_IS_SMOOI(y)) | ||||||
| 		{ | 		{ | ||||||
| @ -2714,13 +2748,13 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
|  |  | ||||||
| 				case 1: | 				case 1: | ||||||
| 					z = clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); | 					z = clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); | ||||||
| 					if (!z) return HCL_NULL; | 					if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
| 					if (rem) *rem = HCL_SMOOI_TO_OOP(0); | 					if (rem) *rem = HCL_SMOOI_TO_OOP(0); | ||||||
| 					return z; | 					return z; | ||||||
|  |  | ||||||
| 				case -1: | 				case -1: | ||||||
| 					z = clone_bigint_negated(hcl, x, HCL_OBJ_GET_SIZE(x)); | 					z = clone_bigint_negated(hcl, x, HCL_OBJ_GET_SIZE(x)); | ||||||
| 					if (!z) return HCL_NULL; | 					if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
| 					if (rem) *rem = HCL_SMOOI_TO_OOP(0); | 					if (rem) *rem = HCL_SMOOI_TO_OOP(0); | ||||||
| 					return z; | 					return z; | ||||||
|  |  | ||||||
| @ -2741,7 +2775,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 					y_neg_sign = (yv < 0); | 					y_neg_sign = (yv < 0); | ||||||
|  |  | ||||||
| 					z = clone_bigint_to_positive(hcl, x, HCL_OBJ_GET_SIZE(x)); | 					z = clone_bigint_to_positive(hcl, x, HCL_OBJ_GET_SIZE(x)); | ||||||
| 					if (!z) return HCL_NULL; | 					if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 					zw = ((hcl_oop_liword_t)z)->slot; | 					zw = ((hcl_oop_liword_t)z)->slot; | ||||||
| 					zs = HCL_OBJ_GET_SIZE(z); | 					zs = HCL_OBJ_GET_SIZE(z); | ||||||
| @ -2777,7 +2811,6 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 								if (HCL_UNLIKELY(!r)) return HCL_NULL; | 								if (HCL_UNLIKELY(!r)) return HCL_NULL; | ||||||
| 								*rem = r; | 								*rem = r; | ||||||
| 							} | 							} | ||||||
|  |  | ||||||
| 							return z; | 							return z; | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| @ -2791,7 +2824,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 			hcl_pushvolat (hcl, &x); | 			hcl_pushvolat (hcl, &x); | ||||||
| 			y = make_bigint_with_ooi(hcl, yv); | 			y = make_bigint_with_ooi(hcl, yv); | ||||||
| 			hcl_popvolat (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!y) return HCL_NULL; | 			if (HCL_UNLIKELY(!y)) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| @ -2807,7 +2840,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 	hcl_pushvolat (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
| 	z = divide_unsigned_integers(hcl, x, y, &r); | 	z = divide_unsigned_integers(hcl, x, y, &r); | ||||||
| 	hcl_popvolats (hcl, 2); | 	hcl_popvolats (hcl, 2); | ||||||
| 	if (!z) return HCL_NULL; | 	if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 	if (x_neg_sign) | 	if (x_neg_sign) | ||||||
| 	{ | 	{ | ||||||
| @ -2824,7 +2857,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 		hcl_pushvolat (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		r = normalize_bigint(hcl, r); | 		r = normalize_bigint(hcl, r); | ||||||
| 		hcl_popvolats (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		if (!r) return HCL_NULL; | 		if (HCL_UNLIKELY(!r)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (r != HCL_SMOOI_TO_OOP(0) && modulo) | 		if (r != HCL_SMOOI_TO_OOP(0) && modulo) | ||||||
| 		{ | 		{ | ||||||
| @ -2834,17 +2867,17 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 				hcl_pushvolat (hcl, &y); | 				hcl_pushvolat (hcl, &y); | ||||||
| 				r = hcl_addints(hcl, r, y); | 				r = hcl_addints(hcl, r, y); | ||||||
| 				hcl_popvolats (hcl, 2); | 				hcl_popvolats (hcl, 2); | ||||||
| 				if (!r) return HCL_NULL; | 				if (HCL_UNLIKELY(!r)) return HCL_NULL; | ||||||
|  |  | ||||||
| 				hcl_pushvolat (hcl, &r); | 				hcl_pushvolat (hcl, &r); | ||||||
| 				z = normalize_bigint(hcl, z); | 				z = normalize_bigint(hcl, z); | ||||||
| 				hcl_popvolat (hcl); | 				hcl_popvolat (hcl); | ||||||
| 				if (!z) return HCL_NULL; | 				if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 				hcl_pushvolat (hcl, &r); | 				hcl_pushvolat (hcl, &r); | ||||||
| 				z = hcl_subints(hcl, z, HCL_SMOOI_TO_OOP(1)); | 				z = hcl_subints(hcl, z, HCL_SMOOI_TO_OOP(1)); | ||||||
| 				hcl_popvolat (hcl); | 				hcl_popvolat (hcl); | ||||||
| 				if (!z) return HCL_NULL; | 				if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 				*rem = r; | 				*rem = r; | ||||||
| 				return z; | 				return z; | ||||||
| @ -2854,7 +2887,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 				/* remainder is not needed at all */ | 				/* remainder is not needed at all */ | ||||||
| /* TODO: subtract 1 without normalization??? */ | /* TODO: subtract 1 without normalization??? */ | ||||||
| 				z = normalize_bigint(hcl, z); | 				z = normalize_bigint(hcl, z); | ||||||
| 				if (!z) return HCL_NULL; | 				if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
| 				return hcl_subints(hcl, z, HCL_SMOOI_TO_OOP(1)); | 				return hcl_subints(hcl, z, HCL_SMOOI_TO_OOP(1)); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -2864,7 +2897,7 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 		hcl_pushvolat (hcl, &z); | 		hcl_pushvolat (hcl, &z); | ||||||
| 		r = normalize_bigint(hcl, r); | 		r = normalize_bigint(hcl, r); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!r) return HCL_NULL; | 		if (HCL_UNLIKELY(!r)) return HCL_NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_pushvolat (hcl, &r); | 	hcl_pushvolat (hcl, &r); | ||||||
| @ -3089,7 +3122,7 @@ hcl_oop_t hcl_bitandints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		hcl_pushvolat (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		x = make_bigint_with_ooi(hcl, v); | 		x = make_bigint_with_ooi(hcl, v); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| 	} | 	} | ||||||
| @ -3105,7 +3138,7 @@ hcl_oop_t hcl_bitandints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		hcl_pushvolat (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		y = make_bigint_with_ooi (hcl, v); | 		y = make_bigint_with_ooi (hcl, v); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| 	} | 	} | ||||||
| @ -3160,7 +3193,7 @@ hcl_oop_t hcl_bitandints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		hcl_pushvolat (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		z = make_pbigint(hcl, HCL_NULL, zalloc); | 		z = make_pbigint(hcl, HCL_NULL, zalloc); | ||||||
| 		hcl_popvolats (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		if (!z) return HCL_NULL; | 		if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (negx && negy) | 		if (negx && negy) | ||||||
| 		{ | 		{ | ||||||
| @ -3302,7 +3335,7 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		hcl_pushvolat (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		x = make_bigint_with_ooi(hcl, v); | 		x = make_bigint_with_ooi(hcl, v); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| 	} | 	} | ||||||
| @ -3318,7 +3351,7 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		hcl_pushvolat (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		y = make_bigint_with_ooi(hcl, v); | 		y = make_bigint_with_ooi(hcl, v); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| 	} | 	} | ||||||
| @ -3380,7 +3413,7 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		hcl_pushvolat (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		z = make_pbigint(hcl, HCL_NULL, zalloc); | 		z = make_pbigint(hcl, HCL_NULL, zalloc); | ||||||
| 		hcl_popvolats (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		if (!z) return HCL_NULL; | 		if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (negx && negy) | 		if (negx && negy) | ||||||
| 		{ | 		{ | ||||||
| @ -3520,7 +3553,7 @@ hcl_oop_t hcl_bitxorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		hcl_pushvolat (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		x = make_bigint_with_ooi (hcl, v); | 		x = make_bigint_with_ooi (hcl, v); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| 	} | 	} | ||||||
| @ -3536,7 +3569,7 @@ hcl_oop_t hcl_bitxorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		hcl_pushvolat (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		y = make_bigint_with_ooi (hcl, v); | 		y = make_bigint_with_ooi (hcl, v); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| 	} | 	} | ||||||
| @ -3756,7 +3789,7 @@ hcl_oop_t hcl_bitinvint (hcl_t* hcl, hcl_oop_t x) | |||||||
| 		hcl_pushvolat (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		z = make_pbigint(hcl, HCL_NULL, zalloc); | 		z = make_pbigint(hcl, HCL_NULL, zalloc); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!z) return HCL_NULL; | 		if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (negx) | 		if (negx) | ||||||
| 		{ | 		{ | ||||||
| @ -3828,7 +3861,7 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint (hcl_t* hcl, hcl_oop_t x, hcl | |||||||
| 	/* +1 for the second inversion below */ | 	/* +1 for the second inversion below */ | ||||||
| 	z = make_nbigint(hcl, HCL_NULL, xs + 1); | 	z = make_nbigint(hcl, HCL_NULL, xs + 1); | ||||||
| 	hcl_popvolat (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (!z) return HCL_NULL; | 	if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 	/* the following lines roughly for 'z = hcl_bitinv (hcl, x)' */ | 	/* the following lines roughly for 'z = hcl_bitinv (hcl, x)' */ | ||||||
| 	carry = 1; | 	carry = 1; | ||||||
| @ -3851,7 +3884,6 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint (hcl_t* hcl, hcl_oop_t x, hcl | |||||||
| 	} | 	} | ||||||
| 	HCL_OBJ_SET_LIWORD_VAL (z, xs, ~(hcl_liw_t)0); | 	HCL_OBJ_SET_LIWORD_VAL (z, xs, ~(hcl_liw_t)0); | ||||||
|  |  | ||||||
|  |  | ||||||
| 	carry = 1; | 	carry = 1; | ||||||
| 	for (i = 0; i <= xs; i++) | 	for (i = 0; i <= xs; i++) | ||||||
| 	{ | 	{ | ||||||
| @ -3898,7 +3930,7 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint_and_normalize (hcl_t* hcl, hc | |||||||
| 		hcl_pushvolat (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		z = rshift_negative_bigint(hcl, x, shift); | 		z = rshift_negative_bigint(hcl, x, shift); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!z) return HCL_NULL; | 		if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		/* y is a negative number. use hcl_addints() until it becomes 0 */ | 		/* y is a negative number. use hcl_addints() until it becomes 0 */ | ||||||
| 		hcl_pushvolat (hcl, &z); | 		hcl_pushvolat (hcl, &z); | ||||||
| @ -3921,7 +3953,7 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint_and_normalize (hcl_t* hcl, hc | |||||||
| 		hcl_pushvolat (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		x = normalize_bigint(hcl, z); | 		x = normalize_bigint(hcl, z); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (HCL_OOP_IS_SMOOI(x)) | 		if (HCL_OOP_IS_SMOOI(x)) | ||||||
| 		{ | 		{ | ||||||
| @ -3971,7 +4003,7 @@ static HCL_INLINE hcl_oop_t rshift_positive_bigint_and_normalize (hcl_t* hcl, hc | |||||||
| 	hcl_pushvolat (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
| 	z = clone_bigint(hcl, x, zs); | 	z = clone_bigint(hcl, x, zs); | ||||||
| 	hcl_popvolat (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (!z) return HCL_NULL; | 	if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 	/* for convenience in subtraction below. | 	/* for convenience in subtraction below. | ||||||
| 	 * it could be HCL_TYPE_MAX(hcl_oow_t) | 	 * it could be HCL_TYPE_MAX(hcl_oow_t) | ||||||
| @ -4033,14 +4065,14 @@ static HCL_INLINE hcl_oop_t lshift_bigint_and_normalize (hcl_t* hcl, hcl_oop_t x | |||||||
| 		hcl_pushvolat (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		z = expand_bigint(hcl, x, wshift); | 		z = expand_bigint(hcl, x, wshift); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!z) return HCL_NULL; | 		if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); | 		lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); | ||||||
|  |  | ||||||
| 		hcl_pushvolat (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		x = normalize_bigint(hcl, z); | 		x = normalize_bigint(hcl, z); | ||||||
| 		hcl_popvolat (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
|  |  | ||||||
| 		hcl_pushvolat (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		y = hcl_subints(hcl, y, HCL_SMOOI_TO_OOP(shift)); | 		y = hcl_subints(hcl, y, HCL_SMOOI_TO_OOP(shift)); | ||||||
| @ -4096,7 +4128,7 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			if (v2 > wshift * HCL_LIW_BITS) wshift++; | 			if (v2 > wshift * HCL_LIW_BITS) wshift++; | ||||||
|  |  | ||||||
| 			z = make_bloated_bigint_with_ooi(hcl, v1, wshift); | 			z = make_bloated_bigint_with_ooi(hcl, v1, wshift); | ||||||
| 			if (!z) return HCL_NULL; | 			if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 			lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), v2); | 			lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), v2); | ||||||
| 			return normalize_bigint(hcl, z); | 			return normalize_bigint(hcl, z); | ||||||
| @ -4169,7 +4201,7 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			hcl_pushvolat (hcl, &y); | 			hcl_pushvolat (hcl, &y); | ||||||
| 			x = make_bigint_with_ooi(hcl, v); | 			x = make_bigint_with_ooi(hcl, v); | ||||||
| 			hcl_popvolat (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!x) return HCL_NULL; | 			if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
|  |  | ||||||
| 			goto bigint_and_bigint; | 			goto bigint_and_bigint; | ||||||
| 		} | 		} | ||||||
| @ -4254,7 +4286,7 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 				if (shift > wshift * HCL_LIW_BITS) wshift++; | 				if (shift > wshift * HCL_LIW_BITS) wshift++; | ||||||
|  |  | ||||||
| 				z = expand_bigint(hcl, x, wshift); | 				z = expand_bigint(hcl, x, wshift); | ||||||
| 				if (!z) return HCL_NULL; | 				if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
|  |  | ||||||
| 				lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); | 				lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); | ||||||
| 			} | 			} | ||||||
| @ -4268,12 +4300,12 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 				if (negx) | 				if (negx) | ||||||
| 				{ | 				{ | ||||||
| 					z = rshift_negative_bigint(hcl, x, shift); | 					z = rshift_negative_bigint(hcl, x, shift); | ||||||
| 					if (!z) return HCL_NULL; | 					if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| 				{ | 				{ | ||||||
| 					z = clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); | 					z = clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); | ||||||
| 					if (!z) return HCL_NULL; | 					if (HCL_UNLIKELY(!z)) return HCL_NULL; | ||||||
| 					rshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); | 					rshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @ -4364,6 +4396,7 @@ hcl_oop_t hcl_strtoint (hcl_t* hcl, const hcl_ooch_t* str, hcl_oow_t len, int ra | |||||||
|  |  | ||||||
| 		if (outlen > HCL_COUNTOF(hw)) | 		if (outlen > HCL_COUNTOF(hw)) | ||||||
| 		{ | 		{ | ||||||
|  | /* TODO: reuse this buffer? */ | ||||||
| 			hwp = (hcl_liw_t*)hcl_allocmem(hcl, outlen * HCL_SIZEOF(hw[0])); | 			hwp = (hcl_liw_t*)hcl_allocmem(hcl, outlen * HCL_SIZEOF(hw[0])); | ||||||
| 			if (!hwp) return HCL_NULL; | 			if (!hwp) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| @ -4441,7 +4474,6 @@ hcl_oop_t hcl_strtoint (hcl_t* hcl, const hcl_ooch_t* str, hcl_oow_t len, int ra | |||||||
| 				ptr++; | 				ptr++; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  |  | ||||||
| 			r2 = r1; | 			r2 = r1; | ||||||
| 			for (i = 0; i < hwlen; i++) | 			for (i = 0; i < hwlen; i++) | ||||||
| 			{ | 			{ | ||||||
| @ -4499,7 +4531,7 @@ hcl_oop_t hcl_strtoint (hcl_t* hcl, const hcl_ooch_t* str, hcl_oow_t len, int ra | |||||||
|  |  | ||||||
| oops_einval: | oops_einval: | ||||||
| 	if (hwp && hw != hwp) hcl_freemem (hcl, hwp); | 	if (hwp && hw != hwp) hcl_freemem (hcl, hwp); | ||||||
| 	hcl_seterrnum (hcl, HCL_EINVAL); | 	hcl_seterrbfmt (hcl, HCL_EINVAL, "unable to convert '%.*js' to integer", len, str); | ||||||
| 	return HCL_NULL; | 	return HCL_NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -4712,52 +4744,52 @@ hcl_oop_t hcl_sqrtint (hcl_t* hcl, hcl_oop_t x) | |||||||
| 	hcl_pushvolat (hcl, &m2); | 	hcl_pushvolat (hcl, &m2); | ||||||
|  |  | ||||||
| 	a = hcl_ltints(hcl, x, HCL_SMOOI_TO_OOP(0)); | 	a = hcl_ltints(hcl, x, HCL_SMOOI_TO_OOP(0)); | ||||||
| 	if (!a) goto oops; | 	if (HCL_UNLIKELY(!a)) goto oops; | ||||||
| 	if (a == hcl->_true) | 	if (a == hcl->_true) | ||||||
| 	{ | 	{ | ||||||
| 		/* the given number is a negative number. | 		/* the given number is a negative number. | ||||||
| 		 * i will arrange the return value to be negative. */ | 		 * i will arrange the return value to be negative. */ | ||||||
| 		x = hcl_negateint(hcl, x); | 		x = hcl_negateint(hcl, x); | ||||||
| 		if (!x) goto oops; | 		if (HCL_UNLIKELY(!x)) goto oops; | ||||||
| 		neg = 1; | 		neg = 1; | ||||||
| 	} | 	} | ||||||
| 	else neg = 0; | 	else neg = 0; | ||||||
|  |  | ||||||
| 	a = HCL_SMOOI_TO_OOP(1); | 	a = HCL_SMOOI_TO_OOP(1); | ||||||
| 	b = hcl_bitshiftint(hcl, x, HCL_SMOOI_TO_OOP(-5)); | 	b = hcl_bitshiftint(hcl, x, HCL_SMOOI_TO_OOP(-5)); | ||||||
| 	if (!b) goto oops; | 	if (HCL_UNLIKELY(!b)) goto oops; | ||||||
| 	b = hcl_addints(hcl, b, HCL_SMOOI_TO_OOP(8)); | 	b = hcl_addints(hcl, b, HCL_SMOOI_TO_OOP(8)); | ||||||
| 	if (!b) goto oops; | 	if (HCL_UNLIKELY(!b)) goto oops; | ||||||
|  |  | ||||||
| 	while (1) | 	while (1) | ||||||
| 	{ | 	{ | ||||||
| 		t = hcl_geints(hcl, b, a); | 		t = hcl_geints(hcl, b, a); | ||||||
| 		if (!t) return HCL_NULL; | 		if (HCL_UNLIKELY(!t)) return HCL_NULL; | ||||||
| 		if (t == hcl->_false) break; | 		if (t == hcl->_false) break; | ||||||
|  |  | ||||||
| 		m = hcl_addints(hcl, a, b); | 		m = hcl_addints(hcl, a, b); | ||||||
| 		if (!m) goto oops; | 		if (HCL_UNLIKELY(!m)) goto oops; | ||||||
| 		m = hcl_bitshiftint(hcl, m, HCL_SMOOI_TO_OOP(-1)); | 		m = hcl_bitshiftint(hcl, m, HCL_SMOOI_TO_OOP(-1)); | ||||||
| 		if (!m) goto oops; | 		if (HCL_UNLIKELY(!m)) goto oops; | ||||||
| 		m2 = hcl_mulints(hcl, m, m); | 		m2 = hcl_mulints(hcl, m, m); | ||||||
| 		if (!m2) goto oops; | 		if (HCL_UNLIKELY(!m2)) goto oops; | ||||||
| 		t = hcl_gtints(hcl, m2, x); | 		t = hcl_gtints(hcl, m2, x); | ||||||
| 		if (!t) return HCL_NULL; | 		if (HCL_UNLIKELY(!t)) return HCL_NULL; | ||||||
| 		if (t == hcl->_true) | 		if (t == hcl->_true) | ||||||
| 		{ | 		{ | ||||||
| 			b = hcl_subints(hcl, m, HCL_SMOOI_TO_OOP(1)); | 			b = hcl_subints(hcl, m, HCL_SMOOI_TO_OOP(1)); | ||||||
| 			if (!b) goto oops; | 			if (HCL_UNLIKELY(!b)) goto oops; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			a = hcl_addints(hcl, m, HCL_SMOOI_TO_OOP(1)); | 			a = hcl_addints(hcl, m, HCL_SMOOI_TO_OOP(1)); | ||||||
| 			if (!a) goto oops; | 			if (HCL_UNLIKELY(!a)) goto oops; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_popvolats (hcl, 5); | 	hcl_popvolats (hcl, 5); | ||||||
| 	x = hcl_subints(hcl, a, HCL_SMOOI_TO_OOP(1)); | 	x = hcl_subints(hcl, a, HCL_SMOOI_TO_OOP(1)); | ||||||
| 	if (!x) return HCL_NULL; | 	if (HCL_UNLIKELY(!x)) return HCL_NULL; | ||||||
|  |  | ||||||
| 	if (neg) x = hcl_negateint(hcl, x); | 	if (neg) x = hcl_negateint(hcl, x); | ||||||
| 	return x; | 	return x; | ||||||
| @ -4767,7 +4799,6 @@ oops: | |||||||
| 	return HCL_NULL; | 	return HCL_NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| hcl_oop_t hcl_absint (hcl_t* hcl, hcl_oop_t x) | hcl_oop_t hcl_absint (hcl_t* hcl, hcl_oop_t x) | ||||||
| { | { | ||||||
| 	if (HCL_OOP_IS_SMOOI(x)) | 	if (HCL_OOP_IS_SMOOI(x)) | ||||||
| @ -4873,13 +4904,15 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int flagged_radix) | |||||||
| 		return hcl_makestring(hcl, xbuf, xlen); | 		return hcl_makestring(hcl, xbuf, xlen); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* the number can't be represented as a single hcl_oow_t value. | ||||||
|  | 	 * mutli-word conversion begins now */ | ||||||
| 	as = HCL_OBJ_GET_SIZE(num); | 	as = HCL_OBJ_GET_SIZE(num); | ||||||
|  |  | ||||||
| 	reqcapa = as * HCL_LIW_BITS + 1; | 	reqcapa = as * HCL_LIW_BITS + 1; | ||||||
| 	if (hcl->inttostr.xbuf.capa < reqcapa) | 	if (hcl->inttostr.xbuf.capa < reqcapa) | ||||||
| 	{ | 	{ | ||||||
| 		xbuf = (hcl_ooch_t*)hcl_reallocmem(hcl, hcl->inttostr.xbuf.ptr, reqcapa * HCL_SIZEOF(*xbuf)); | 		xbuf = (hcl_ooch_t*)hcl_reallocmem(hcl, hcl->inttostr.xbuf.ptr, reqcapa * HCL_SIZEOF(*xbuf)); | ||||||
| 		if (!xbuf) return HCL_NULL; | 		if (HCL_UNLIKELY(!xbuf)) return HCL_NULL; | ||||||
| 		hcl->inttostr.xbuf.capa = reqcapa; | 		hcl->inttostr.xbuf.capa = reqcapa; | ||||||
| 		hcl->inttostr.xbuf.ptr = xbuf; | 		hcl->inttostr.xbuf.ptr = xbuf; | ||||||
| 	} | 	} | ||||||
| @ -4891,7 +4924,7 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int flagged_radix) | |||||||
| 	if (hcl->inttostr.t.capa < as) | 	if (hcl->inttostr.t.capa < as) | ||||||
|  	{ |  	{ | ||||||
| 		t = (hcl_liw_t*)hcl_reallocmem(hcl, hcl->inttostr.t.ptr, reqcapa * HCL_SIZEOF(*t)); | 		t = (hcl_liw_t*)hcl_reallocmem(hcl, hcl->inttostr.t.ptr, reqcapa * HCL_SIZEOF(*t)); | ||||||
| 		if (!t) return HCL_NULL; | 		if (HCL_UNLIKELY(!t)) return HCL_NULL; | ||||||
| 		hcl->inttostr.t.capa = as; | 		hcl->inttostr.t.capa = as; | ||||||
| 		hcl->inttostr.t.ptr = t; | 		hcl->inttostr.t.ptr = t; | ||||||
| 	} | 	} | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user