From 2022ac965bb68e63827b0809fa197f0e1d7da750 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Wed, 23 Dec 2015 15:25:29 +0000 Subject: [PATCH] added some code to handle right-shift of a negative number --- stix/kernel/test-005.st | 10 +++- stix/lib/bigint.c | 110 +++++++++++++++++++++++++++++++++++----- 2 files changed, 105 insertions(+), 15 deletions(-) diff --git a/stix/kernel/test-005.st b/stix/kernel/test-005.st index 5853700..7a45dbe 100644 --- a/stix/kernel/test-005.st +++ b/stix/kernel/test-005.st @@ -356,6 +356,7 @@ PROCESS TESTING ((2r1111111 bitInvert) printStringRadix: 16) dump. ((2r11001110000000000000000000000000000000000000000000000000000000000000000000000 bitInvert) printStringRadix: 16) dump. + ((2r1111 bitShift: 100) printStringRadix: 2) dump. ((123123124 bitShift: 100000) printStringRadix: 16) dump. (2r110101010101010101010101010101111111111111111111111111111111111111111111111111111111100000000001111111 printStringRadix: 16) dump. @@ -366,7 +367,14 @@ PROCESS TESTING ## ((-2r110101010101010101010101010101111111111111111111111111111111111111111111111111111111100000000001111111 bitShift: 16r1FFFFFFFFFFFFFFFF) printStringRadix: 2) dump. ##((-2r11111111110000000000111110000 bitShift: -31) printStringRadix: 2) dump. -((-536870911 bitShift: -536870912) printStringRadix: 2) dump. +##((-536870911 bitShift: -536870912) printStringRadix: 2) dump. +((-2r1111 bitShift: -3) printStringRadix: 2) dump. +((-2r11111111111111111111111111111111111111111111111111111111111111111111110001 bitShift: -1) printStringRadix: 2) dump. +((-2r11111111111111111111111111111111111111111111111111111111111111111111110001 bitShift: -2) printStringRadix: 2) dump. +((-2r11111111111111111111111111111111111111111111111111111111111111111111110001 bitShift: -3) printStringRadix: 2) dump. +((-2r11111111111111111111111111111111111111111111111111111111111111111111110001 bitShift: -200) printStringRadix: 2) dump. +((-2r1000000000000000000000000000100000000000000000000000000000000000000000000000 bitShift: -5) printStringRadix: 2) dump. + " FFI isNil dump. diff --git a/stix/lib/bigint.c b/stix/lib/bigint.c index 3941dfa..df985fa 100644 --- a/stix/lib/bigint.c +++ b/stix/lib/bigint.c @@ -547,7 +547,7 @@ static void complement2_unsigned_array (const stix_liw_t* x, stix_oow_t xs, stix for (i = 0; i < xs; i++) { w = (stix_lidw_t)(~x[i]) + carry; - /*w = (stix_lidw_t)(x[i] ^ STIX_TYPE_MAX(stix_liw_t)) + carry;*/ + /*w = (stix_lidw_t)(x[i] ^ (~(stix_liw_t)0)) + carry;*/ carry = w >> STIX_LIW_BITS; z[i] = w; } @@ -1644,7 +1644,7 @@ stix_oop_t stix_bitandints (stix_t* stix, stix_oop_t x, stix_oop_t y) STIX_ASSERT (carry[0] == 0); /* 2's complement on the final result */ - ((stix_oop_liword_t)z)->slot[zs] = STIX_TYPE_MAX(stix_liw_t); + ((stix_oop_liword_t)z)->slot[zs] = ~(stix_liw_t)0; carry[0] = 1; for (i = 0; i <= zs; i++) { @@ -1859,7 +1859,7 @@ stix_oop_t stix_bitorints (stix_t* stix, stix_oop_t x, stix_oop_t y) adjust_to_negative: /* 2's complement on the final result */ - ((stix_oop_liword_t)z)->slot[zs] = STIX_TYPE_MAX(stix_liw_t); + ((stix_oop_liword_t)z)->slot[zs] = ~(stix_liw_t)0; carry[0] = 1; for (i = 0; i <= zs; i++) { @@ -1918,7 +1918,7 @@ stix_oop_t stix_bitorints (stix_t* stix, stix_oop_t x, stix_oop_t y) * redundant. for (; i < xs; i++) { - ((stix_oop_liword_t)z)->slot[i] = STIX_TYPE_MAX(stix_liw_t); + ((stix_oop_liword_t)z)->slot[i] = ~(stix_liw_t)0; } */ goto adjust_to_negative; @@ -2076,7 +2076,7 @@ stix_oop_t stix_bitxorints (stix_t* stix, stix_oop_t x, stix_oop_t y) { w[0] = (stix_lidw_t)((stix_liw_t)~((stix_oop_liword_t)x)->slot[i]) + carry[0]; carry[0] = w[0] >> STIX_LIW_BITS; - ((stix_oop_liword_t)z)->slot[i] = (stix_liw_t)w[0] ^ STIX_TYPE_MAX(stix_liw_t); + ((stix_oop_liword_t)z)->slot[i] = (stix_liw_t)w[0] ^ (~(stix_liw_t)0); } STIX_ASSERT (carry[0] == 0); } @@ -2104,7 +2104,7 @@ stix_oop_t stix_bitxorints (stix_t* stix, stix_oop_t x, stix_oop_t y) adjust_to_negative: /* 2's complement on the final result */ - ((stix_oop_liword_t)z)->slot[zs] = STIX_TYPE_MAX(stix_liw_t); + ((stix_oop_liword_t)z)->slot[zs] = ~(stix_liw_t)0; carry = 1; for (i = 0; i <= zs; i++) { @@ -2134,7 +2134,7 @@ stix_oop_t stix_bitxorints (stix_t* stix, stix_oop_t x, stix_oop_t y) /* treat the lacking part in y as all 1s */ for (; i < xs; i++) { - ((stix_oop_liword_t)z)->slot[i] = ((stix_oop_liword_t)x)->slot[i] ^ STIX_TYPE_MAX(stix_liw_t); + ((stix_oop_liword_t)z)->slot[i] = ((stix_oop_liword_t)x)->slot[i] ^ (~(stix_liw_t)0); } goto adjust_to_negative; @@ -2225,13 +2225,13 @@ stix_oop_t stix_bitinvint (stix_t* stix, stix_oop_t x) { stix_lidw_t w, carry; + #if 0 for (i = 0; i < xs; i++) { ((stix_oop_liword_t)z)->slot[i] = ~((stix_oop_liword_t)x)->slot[i]; } - /* 2's complement on the final result */ - ((stix_oop_liword_t)z)->slot[zs] = STIX_TYPE_MAX(stix_liw_t); + ((stix_oop_liword_t)z)->slot[zs] = ~(stix_liw_t)0; carry = 1; for (i = 0; i <= zs; i++) { @@ -2240,6 +2240,18 @@ stix_oop_t stix_bitinvint (stix_t* stix, stix_oop_t x) ((stix_oop_liword_t)z)->slot[i] = (stix_liw_t)w; } STIX_ASSERT (carry == 0); + #else + carry = 1; + for (i = 0; i < xs; i++) + { + w = (stix_lidw_t)(((stix_oop_liword_t)x)->slot[i]) + carry; + carry = w >> STIX_LIW_BITS; + ((stix_oop_liword_t)z)->slot[i] = (stix_liw_t)w; + } + STIX_ASSERT (i == zs); + ((stix_oop_liword_t)z)->slot[i] = (stix_liw_t)carry; + STIX_ASSERT ((carry >> STIX_LIW_BITS) == 0); + #endif STIX_OBJ_SET_CLASS (z, stix->_large_negative_integer); } @@ -2371,7 +2383,7 @@ stix_oop_t stix_bitshiftint (stix_t* stix, stix_oop_t x, stix_oop_t y) { stix_oop_t z; int sign, negx, negy; - stix_oow_t shift, wshift; + stix_oow_t shift; if (!is_integer(stix,x) || !is_integer(stix, y)) goto oops_einval; @@ -2387,9 +2399,15 @@ stix_oop_t stix_bitshiftint (stix_t* stix, stix_oop_t x, stix_oop_t y) { /* right shift */ #if defined(STIX_LIMIT_OBJ_SIZE) + /* the maximum number of bit shifts are guaranteed to be + * small enough to fit into the stix_oow_t type. so i can + * easily assume that all bits are shifted out */ + STIX_ASSERT (STIX_TYPE_MAX(stix_oow_t) >= STIX_OBJ_SIZE_MAX * 8); return (negx)? STIX_SMOOI_TO_OOP(-1): STIX_SMOOI_TO_OOP(0); #else /* TODO: */ + /* TODO: */ + /* TODO: */ #endif } else @@ -2397,8 +2415,9 @@ stix_oop_t stix_bitshiftint (stix_t* stix, stix_oop_t x, stix_oop_t y) /* left shift */ #if defined(STIX_LIMIT_OBJ_SIZE) /* the maximum number of bit shifts are guaranteed to be - * small enough to fit into the stix_oow_t type, i can - * simply return a failure here */ + * small enough to fit into the stix_oow_t type. so i can + * simply return a failure here becuase it's surely too + * large after shifting */ STIX_ASSERT (STIX_TYPE_MAX(stix_oow_t) >= STIX_OBJ_SIZE_MAX * 8); stix->errnum = STIX_EOOMEM; /* is it a soft failure or a hard failure? is this error code proper? */ return STIX_NULL; @@ -2449,6 +2468,8 @@ stix_oop_t stix_bitshiftint (stix_t* stix, stix_oop_t x, stix_oop_t y) } else if (sign >= 1) { + stix_oow_t wshift; + left_shift_last: wshift = shift / STIX_LIW_BITS; if (shift > wshift * STIX_LIW_BITS) wshift++; @@ -2462,9 +2483,70 @@ stix_oop_t stix_bitshiftint (stix_t* stix, stix_oop_t x, stix_oop_t y) { /* right shift */ STIX_ASSERT (sign <= -1); -/*TODO" */ - } + if (negx) + { + stix_lidw_t w; + stix_lidw_t carry; + stix_oow_t i, xs; + + xs = STIX_OBJ_GET_SIZE(x); + + stix_pushtmp (stix, &x); + stix_pushtmp (stix, &y); + /* +1 for the second inversion below */ + z = stix_instantiate (stix, stix->_large_negative_integer, STIX_NULL, xs + 1); + stix_poptmps (stix, 2); + if (!z) return STIX_NULL; + + /* the following lines roughly for 'z = stix_bitinv (stix, x)' */ + carry = 1; + for (i = 0; i < xs; i++) + { + w = (stix_lidw_t)((stix_liw_t)~((stix_oop_liword_t)x)->slot[i]) + carry; + carry = w >> STIX_LIW_BITS; + ((stix_oop_liword_t)z)->slot[i] = ~(stix_liw_t)w; + } + STIX_ASSERT (carry == 0); + + /* shift to the right */ + rshift_unsigned_array (((stix_oop_liword_t)z)->slot, xs, shift); + + /* the following lines roughly for 'z = stix_bitinv (stix, z)' */ + #if 0 + for (i = 0; i < xs; i++) + { + ((stix_oop_liword_t)z)->slot[i] = ~((stix_oop_liword_t)z)->slot[i]; + } + ((stix_oop_liword_t)z)->slot[xs] = ~(stix_liw_t)0; + + carry = 1; + for (i = 0; i <= xs; i++) + { + w = (stix_lidw_t)((stix_liw_t)~((stix_oop_liword_t)z)->slot[i]) + carry; + carry = w >> STIX_LIW_BITS; + ((stix_oop_liword_t)z)->slot[i] = (stix_liw_t)w; + } + STIX_ASSERT (carry == 0); + #else + carry = 1; + for (i = 0; i < xs; i++) + { + w = (stix_lidw_t)(((stix_oop_liword_t)z)->slot[i]) + carry; + carry = w >> STIX_LIW_BITS; + ((stix_oop_liword_t)z)->slot[i] = (stix_liw_t)w; + } + ((stix_oop_liword_t)z)->slot[i] = (stix_liw_t)carry; + STIX_ASSERT ((carry >> STIX_LIW_BITS) == 0); + #endif + } + else + { + z = clone_bigint (stix, x, STIX_OBJ_GET_SIZE(x)); + if (!z) return STIX_NULL; + rshift_unsigned_array (((stix_oop_liword_t)z)->slot, STIX_OBJ_GET_SIZE(z), shift); + } + } return normalize_bigint(stix, z); }