added more code to stix_bitshiftint()

This commit is contained in:
hyunghwan.chung 2015-12-21 17:12:57 +00:00
parent 5bf467cb29
commit af9b8cd32c
2 changed files with 176 additions and 23 deletions

View File

@ -363,6 +363,8 @@ PROCESS TESTING
(16rFFFFFFFFFF1234567890AAAAAAAAAAAAAAAAAAAAAAAAA22222222222222222F printStringRadix: 32) dump. (16rFFFFFFFFFF1234567890AAAAAAAAAAAAAAAAAAAAAAAAA22222222222222222F printStringRadix: 32) dump.
(32r3VVVVVVVS938LJOI2LALALALALALALALALAL8H248H248H248HF printStringRadix: 16) dump. (32r3VVVVVVVS938LJOI2LALALALALALALALALAL8H248H248H248HF printStringRadix: 16) dump.
((-2r110101010101010101010101010101111111111111111111111111111111111111111111111111111111100000000001111111 bitShift: 16r1FFFFFFFFFFFFFFFF) printStringRadix: 2) dump.
" "
FFI isNil dump. FFI isNil dump.
FFI notNil dump. FFI notNil dump.

View File

@ -178,7 +178,34 @@ static STIX_INLINE int is_integer (stix_t* stix, stix_oop_t oop)
c == stix->_large_negative_integer; c == stix->_large_negative_integer;
} }
static STIX_INLINE int bigint_to_oow (stix_t* stix, stix_oop_t num, stix_oow_t* w)
{
/* return value
* 1 - a positive number including 0 that can fit into stix_oow_t
* -1 - a negative number whose absolute value can fit into stix_oow_t
* 0 - number too large or too small
*/
#if (STIX_LIW_BITS == STIX_OOW_BITS)
STIX_ASSERT (STIX_OBJ_GET_SIZE(num) >= 1);
if (STIX_OBJ_GET_SIZE(num) == 1)
{
*w = ((stix_oop_word_t)num)->slot[0];
return (STIX_OBJ_GET_CLASS(num) == stix->_large_negative_integer)? -1: 1;
}
#elif (STIX_LIW_BITS == STIX_OOHW_BITS)
STIX_ASSERT (STIX_OBJ_GET_SIZE(num) >= 2);
if (STIX_OBJ_GET_SIZE(num) == 2)
{
*w = MAKE_WORD (((stix_oop_halfword_t)num)->slot[0], ((stix_oop_halfword_t)num)->slot[1]);
return (STIX_OBJ_GET_CLASS(num) == stix->_large_negative_integer)? -1: 1;
}
#else
# error UNSUPPORTED LIW BIT SIZE
#endif
return 0; /* not convertable */
}
static STIX_INLINE stix_oop_t make_bigint_with_ooi (stix_t* stix, stix_ooi_t i) static STIX_INLINE stix_oop_t make_bigint_with_ooi (stix_t* stix, stix_ooi_t i)
{ {
@ -301,6 +328,34 @@ static STIX_INLINE stix_oop_t make_bigint_with_intmax (stix_t* stix, stix_intmax
return stix_instantiate (stix, ((v >= 0)? stix->_large_positive_integer: stix->_large_negative_integer), buf, len); return stix_instantiate (stix, ((v >= 0)? stix->_large_positive_integer: stix->_large_negative_integer), buf, len);
} }
static STIX_INLINE stix_oop_t expand_bigint (stix_t* stix, stix_oop_t oop, stix_oow_t inc)
{
stix_oop_t z;
stix_oow_t i;
stix_oow_t count;
STIX_ASSERT (STIX_OOP_IS_POINTER(oop));
count = STIX_OBJ_GET_SIZE(oop);
if (inc > STIX_TYPE_MAX(stix_oow_t) - count)
{
stix->errnum = STIX_ENOMEM; /* TODO: is it a soft failure or a hard failure? is this error code proper? */
return STIX_NULL;
}
stix_pushtmp (stix, &oop);
z = stix_instantiate (stix, STIX_OBJ_GET_CLASS(oop), STIX_NULL, count + inc);
stix_poptmp (stix);
if (!z) return STIX_NULL;
for (i = 0; i < count; i++)
{
((stix_oop_liword_t)z)->slot[i] = ((stix_oop_liword_t)oop)->slot[i];
}
return z;
}
static STIX_INLINE stix_oop_t _clone_bigint (stix_t* stix, stix_oop_t oop, stix_oow_t count, stix_oop_t _class) static STIX_INLINE stix_oop_t _clone_bigint (stix_t* stix, stix_oop_t oop, stix_oow_t count, stix_oop_t _class)
{ {
stix_oop_t z; stix_oop_t z;
@ -798,7 +853,14 @@ static stix_oop_t add_unsigned_integers (stix_t* stix, stix_oop_t x, stix_oop_t
as = STIX_OBJ_GET_SIZE(x); as = STIX_OBJ_GET_SIZE(x);
bs = STIX_OBJ_GET_SIZE(y); bs = STIX_OBJ_GET_SIZE(y);
zs = (as >= bs? as: bs) + 1; zs = (as >= bs? as: bs);
if (zs >= STIX_TYPE_MAX(stix_oow_t))
{
stix->errnum = STIX_ENOMEM; /* TOOD: is it a soft failure or hard failure? */
return STIX_NULL;
}
zs++;
stix_pushtmp (stix, &x); stix_pushtmp (stix, &x);
stix_pushtmp (stix, &y); stix_pushtmp (stix, &y);
@ -849,10 +911,20 @@ static stix_oop_t subtract_unsigned_integers (stix_t* stix, stix_oop_t x, stix_o
static stix_oop_t multiply_unsigned_integers (stix_t* stix, stix_oop_t x, stix_oop_t y) static stix_oop_t multiply_unsigned_integers (stix_t* stix, stix_oop_t x, stix_oop_t y)
{ {
stix_oop_t z; stix_oop_t z;
stix_oow_t xz, yz;
xz = STIX_OBJ_GET_SIZE(x);
yz = STIX_OBJ_GET_SIZE(y);
if (yz > STIX_TYPE_MAX(stix_oow_t) - xz)
{
stix->errnum = STIX_ENOMEM; /* TOOD: is it a soft failure or hard failure? */
return STIX_NULL;
}
stix_pushtmp (stix, &x); stix_pushtmp (stix, &x);
stix_pushtmp (stix, &y); stix_pushtmp (stix, &y);
z = stix_instantiate (stix, stix->_large_positive_integer, STIX_NULL, STIX_OBJ_GET_SIZE(x) + STIX_OBJ_GET_SIZE(y)); z = stix_instantiate (stix, stix->_large_positive_integer, STIX_NULL, xz + yz);
stix_poptmps (stix, 2); stix_poptmps (stix, 2);
if (!z) return STIX_NULL; if (!z) return STIX_NULL;
@ -1747,6 +1819,13 @@ stix_oop_t stix_bitorints (stix_t* stix, stix_oop_t x, stix_oop_t y)
zs = xs; zs = xs;
} }
if (zalloc < zs)
{
/* overflow in zalloc calculation above */
stix->errnum = STIX_ENOMEM; /* TODO: is it a soft failure or hard failure? */
return STIX_NULL;
}
stix_pushtmp (stix, &x); stix_pushtmp (stix, &x);
stix_pushtmp (stix, &y); stix_pushtmp (stix, &y);
z = stix_instantiate (stix, stix->_large_positive_integer, STIX_NULL, zalloc); z = stix_instantiate (stix, stix->_large_positive_integer, STIX_NULL, zalloc);
@ -1958,6 +2037,13 @@ stix_oop_t stix_bitxorints (stix_t* stix, stix_oop_t x, stix_oop_t y)
zs = xs; zs = xs;
} }
if (zalloc < zs)
{
/* overflow in zalloc calculation above */
stix->errnum = STIX_ENOMEM; /* TODO: is it a soft failure or hard failure? */
return STIX_NULL;
}
stix_pushtmp (stix, &x); stix_pushtmp (stix, &x);
stix_pushtmp (stix, &y); stix_pushtmp (stix, &y);
z = stix_instantiate (stix, stix->_large_positive_integer, STIX_NULL, zalloc); z = stix_instantiate (stix, stix->_large_positive_integer, STIX_NULL, zalloc);
@ -2110,6 +2196,13 @@ stix_oop_t stix_bitinvint (stix_t* stix, stix_oop_t x)
zs = xs; zs = xs;
} }
if (zalloc < zs)
{
/* overflow in zalloc calculation above */
stix->errnum = STIX_ENOMEM; /* TODO: is it a soft failure or hard failure? */
return STIX_NULL;
}
stix_pushtmp (stix, &x); stix_pushtmp (stix, &x);
z = stix_instantiate (stix, stix->_large_positive_integer, STIX_NULL, zalloc); z = stix_instantiate (stix, stix->_large_positive_integer, STIX_NULL, zalloc);
stix_poptmp (stix); stix_poptmp (stix);
@ -2240,16 +2333,87 @@ stix_oop_t stix_bitshiftint (stix_t* stix, stix_oop_t x, stix_oop_t y)
else else
{ {
stix_oop_t z; stix_oop_t z;
int negx, negy; int sign, negx, negy;
stix_oow_t shift, wshift;
if (!is_integer(stix,x) || !is_integer(stix, y)) goto oops_einval; if (!is_integer(stix,x) || !is_integer(stix, y)) goto oops_einval;
bigint_and_bigint:
negx = (STIX_OBJ_GET_CLASS(x) == stix->_large_negative_integer)? 1: 0; negx = (STIX_OBJ_GET_CLASS(x) == stix->_large_negative_integer)? 1: 0;
negy = (STIX_OBJ_GET_CLASS(y) == stix->_large_negative_integer)? 1: 0; negy = (STIX_OBJ_GET_CLASS(y) == stix->_large_negative_integer)? 1: 0;
bigint_and_bigint: sign = bigint_to_oow (stix, y, &shift);
if (sign == 0)
{
/* y is too big or too small */
if (negy)
{
/* TODO: right shift... */
}
else
{
/* this loop is very inefficient as shifting is repeated
* with lshift_unsigned_array(). however, this part of the
* code is not likey to be useful because the amount of
* memory available is certainly not enough to support
* huge shifts greater than STIX_TYPE_MAX(stix_oow_t) */
do
{
/* for convenience only in subtraction below.
* should it be between STIX_SMOOI_MAX and STIX_TYPE_MAX(stix_oow_t),
* the second parameter to stix_subints() can't be composed
* using STIX_SMOOI_TO_OOP() */
shift = STIX_SMOOI_MAX;
wshift = shift / STIX_LIW_BITS;
if (shift > wshift * STIX_LIW_BITS) wshift++;
stix_pushtmp (stix, &y);
z = expand_bigint (stix, x, wshift);
stix_poptmp (stix);
if (!z) return STIX_NULL;
lshift_unsigned_array (((stix_oop_liword_t)z)->slot, STIX_OBJ_GET_SIZE(z), shift);
stix_pushtmp (stix, &y);
x = normalize_bigint (stix, z);
stix_poptmp (stix);
if (!x) return STIX_NULL;
stix_pushtmp (stix, &x);
y = stix_subints (stix, y, STIX_SMOOI_TO_OOP(shift));
stix_poptmp (stix);
if (!y) return STIX_NULL;
sign = bigint_to_oow (stix, y, &shift);
}
while (sign == 0);
STIX_ASSERT (sign >= 1);
if (shift)
goto left_shift_last;
else
z = x;
}
}
else if (sign >= 1)
{
left_shift_last:
wshift = shift / STIX_LIW_BITS;
if (shift > wshift * STIX_LIW_BITS) wshift++;
z = expand_bigint (stix, x, wshift);
if (!z) return STIX_NULL;
lshift_unsigned_array (((stix_oop_liword_t)z)->slot, STIX_OBJ_GET_SIZE(z), shift);
}
else
{
/* right shift */
STIX_ASSERT (sign <= -1);
/*TODO" */
}
/* TODO: */
return normalize_bigint(stix, z); return normalize_bigint(stix, z);
} }
@ -2535,9 +2699,9 @@ stix_oop_t stix_inttostr (stix_t* stix, stix_oop_t num, int radix)
stix_ooi_t v = 0; stix_ooi_t v = 0;
stix_oow_t w; stix_oow_t w;
stix_oow_t as, bs, rs; stix_oow_t as, bs, rs;
#if STIX_LIW_BITS == STIX_OOW_BITS #if (STIX_LIW_BITS == STIX_OOW_BITS)
stix_liw_t b[1]; stix_liw_t b[1];
#elif STIX_LIW_BITS == STIX_OOHW_BITS #elif (STIX_LIW_BITS == STIX_OOHW_BITS)
stix_liw_t b[2]; stix_liw_t b[2];
#else #else
# error UNSUPPORTED LIW BIT SIZE # error UNSUPPORTED LIW BIT SIZE
@ -2548,6 +2712,8 @@ stix_oop_t stix_inttostr (stix_t* stix, stix_oop_t num, int radix)
stix_oow_t xlen = 0, seglen; stix_oow_t xlen = 0, seglen;
stix_oop_t s; stix_oop_t s;
STIX_ASSERT (radix >= 2 && radix <= 36);
if (STIX_OOP_IS_SMOOI(num)) if (STIX_OOP_IS_SMOOI(num))
{ {
v = STIX_OOP_TO_SMOOI(num); v = STIX_OOP_TO_SMOOI(num);
@ -2568,22 +2734,7 @@ stix_oop_t stix_inttostr (stix_t* stix, stix_oop_t num, int radix)
} }
else else
{ {
#if (STIX_LIW_BITS == STIX_OOW_BITS) v = bigint_to_oow (stix, num, &w);
if (STIX_OBJ_GET_SIZE(num) == 1)
{
w = ((stix_oop_word_t)num)->slot[0];
v = (STIX_OBJ_GET_CLASS(num) == stix->_large_negative_integer)? -1: 1;
}
#elif (STIX_LIW_BITS == STIX_OOHW_BITS)
STIX_ASSERT (STIX_OBJ_GET_SIZE(num) >= 2);
if (STIX_OBJ_GET_SIZE(num) == 2)
{
w = MAKE_WORD (((stix_oop_halfword_t)num)->slot[0], ((stix_oop_halfword_t)num)->slot[1]);
v = (STIX_OBJ_GET_CLASS(num) == stix->_large_negative_integer)? -1: 1;
}
#else
# error UNSUPPORTED LIW BIT SIZE
#endif
} }
if (v) if (v)