implement right bit shift over a small integer

This commit is contained in:
hyunghwan.chung 2015-12-22 15:50:01 +00:00
parent 6fb206a265
commit e7d00d89bf
11 changed files with 115 additions and 38 deletions

View File

@ -363,7 +363,10 @@ PROCESS TESTING
(16rFFFFFFFFFF1234567890AAAAAAAAAAAAAAAAAAAAAAAAA22222222222222222F printStringRadix: 32) dump.
(32r3VVVVVVVS938LJOI2LALALALALALALALALAL8H248H248H248HF printStringRadix: 16) dump.
((-2r110101010101010101010101010101111111111111111111111111111111111111111111111111111111100000000001111111 bitShift: 16r1FFFFFFFFFFFFFFFF) printStringRadix: 2) dump.
## ((-2r110101010101010101010101010101111111111111111111111111111111111111111111111111111111100000000001111111 bitShift: 16r1FFFFFFFFFFFFFFFF) printStringRadix: 2) dump.
##((-2r11111111110000000000111110000 bitShift: -31) printStringRadix: 2) dump.
((-536870911 bitShift: -536870912) printStringRadix: 2) dump.
"
FFI isNil dump.

View File

@ -122,7 +122,7 @@ static STIX_INLINE int smooi_mul_overflow (stix_ooi_t a, stix_ooi_t b, stix_ooi_
/* though this fomula basically works for unsigned types in principle,
* the values used here are all absolute values and they fall in
* a safe range to apply this fomula. the safe range is guarantee because
* a safe range to apply this fomula. the safe range is guaranteed because
* the sources are supposed to be smoois. */
return ub != 0 && ua > STIX_TYPE_MAX(stix_ooi_t) / ub;
#endif
@ -234,7 +234,7 @@ static STIX_INLINE stix_oop_t make_bigint_with_ooi (stix_t* stix, stix_ooi_t i)
if (i >= 0)
{
w = i;
hw[0] = w & STIX_LBMASK(stix_oow_t,STIX_LIW_BITS);
hw[0] = w /*& STIX_LBMASK(stix_oow_t,STIX_LIW_BITS)*/;
hw[1] = w >> STIX_LIW_BITS;
return stix_instantiate (stix, stix->_large_positive_integer, &hw, (hw[1] > 0? 2: 1));
}
@ -242,7 +242,7 @@ static STIX_INLINE stix_oop_t make_bigint_with_ooi (stix_t* stix, stix_ooi_t i)
{
STIX_ASSERT (i > STIX_TYPE_MIN(stix_ooi_t));
w = -i;
hw[0] = w & STIX_LBMASK(stix_oow_t,STIX_LIW_BITS);
hw[0] = w /*& STIX_LBMASK(stix_oow_t,STIX_LIW_BITS)*/;
hw[1] = w >> STIX_LIW_BITS;
return stix_instantiate (stix, stix->_large_negative_integer, &hw, (hw[1] > 0? 2: 1));
}
@ -284,7 +284,7 @@ static STIX_INLINE stix_oop_t make_bloated_bigint_with_ooi (stix_t* stix, stix_o
if (i >= 0)
{
w = i;
hw[0] = w & STIX_LBMASK(stix_oow_t,STIX_LIW_BITS);
hw[0] = w /*& STIX_LBMASK(stix_oow_t,STIX_LIW_BITS)*/;
hw[1] = w >> STIX_LIW_BITS;
z = stix_instantiate (stix, stix->_large_positive_integer, STIX_NULL, (hw[1] > 0? 2: 1) + extra);
}
@ -292,7 +292,7 @@ static STIX_INLINE stix_oop_t make_bloated_bigint_with_ooi (stix_t* stix, stix_o
{
STIX_ASSERT (i > STIX_TYPE_MIN(stix_ooi_t));
w = -i;
hw[0] = w & STIX_LBMASK(stix_oow_t,STIX_LIW_BITS);
hw[0] = w /*& STIX_LBMASK(stix_oow_t,STIX_LIW_BITS)*/;
hw[1] = w >> STIX_LIW_BITS;
z = stix_instantiate (stix, stix->_large_negative_integer, STIX_NULL, (hw[1] > 0? 2: 1) + extra);
}
@ -339,7 +339,7 @@ static STIX_INLINE stix_oop_t expand_bigint (stix_t* stix, stix_oop_t oop, stix_
if (inc > STIX_OBJ_SIZE_MAX - count)
{
stix->errnum = STIX_ENOMEM; /* TODO: is it a soft failure or a hard failure? is this error code proper? */
stix->errnum = STIX_EOOMEM; /* TODO: is it a soft failure or a hard failure? is this error code proper? */
return STIX_NULL;
}
@ -857,7 +857,7 @@ static stix_oop_t add_unsigned_integers (stix_t* stix, stix_oop_t x, stix_oop_t
if (zs >= STIX_OBJ_SIZE_MAX)
{
stix->errnum = STIX_ENOMEM; /* TOOD: is it a soft failure or hard failure? */
stix->errnum = STIX_EOOMEM; /* TOOD: is it a soft failure or hard failure? */
return STIX_NULL;
}
zs++;
@ -918,7 +918,7 @@ static stix_oop_t multiply_unsigned_integers (stix_t* stix, stix_oop_t x, stix_o
if (yz > STIX_OBJ_SIZE_MAX - xz)
{
stix->errnum = STIX_ENOMEM; /* TOOD: is it a soft failure or hard failure? */
stix->errnum = STIX_EOOMEM; /* TOOD: is it a soft failure or hard failure? */
return STIX_NULL;
}
@ -1822,7 +1822,7 @@ stix_oop_t stix_bitorints (stix_t* stix, stix_oop_t x, stix_oop_t y)
if (zalloc < zs)
{
/* overflow in zalloc calculation above */
stix->errnum = STIX_ENOMEM; /* TODO: is it a soft failure or hard failure? */
stix->errnum = STIX_EOOMEM; /* TODO: is it a soft failure or hard failure? */
return STIX_NULL;
}
@ -2040,7 +2040,7 @@ stix_oop_t stix_bitxorints (stix_t* stix, stix_oop_t x, stix_oop_t y)
if (zalloc < zs)
{
/* overflow in zalloc calculation above */
stix->errnum = STIX_ENOMEM; /* TODO: is it a soft failure or hard failure? */
stix->errnum = STIX_EOOMEM; /* TODO: is it a soft failure or hard failure? */
return STIX_NULL;
}
@ -2199,7 +2199,7 @@ stix_oop_t stix_bitinvint (stix_t* stix, stix_oop_t x)
if (zalloc < zs)
{
/* overflow in zalloc calculation above */
stix->errnum = STIX_ENOMEM; /* TODO: is it a soft failure or hard failure? */
stix->errnum = STIX_EOOMEM; /* TODO: is it a soft failure or hard failure? */
return STIX_NULL;
}
@ -2288,12 +2288,40 @@ stix_oop_t stix_bitshiftint (stix_t* stix, stix_oop_t x, stix_oop_t y)
{
/* right shift */
stix_ooi_t v;
/* TODO: ... */
/* right shift of a negative number is complex... */
v2 = -v2;
if (v2 >= STIX_OOI_BITS) return STIX_SMOOI_TO_OOP(0);
v = v1 >> v2;
v2 = -v2;
if (v1 < 0)
{
/* guarantee arithmetic shift preserving the sign bit
* regardless of compiler implementation.
*
* binary decimal shifted by
* -------------------------------
* 10000011 (-125) 0
* 11000001 (-63) 1
* 11100000 (-32) 2
* 11110000 (-16) 3
* 11111000 (-8) 4
* 11111100 (-4) 5
* 11111110 (-2) 6
* 11111111 (-1) 7
* 11111111 (-1) 8
*/
if (v2 >= STIX_OOI_BITS - 1) v = -1;
else
{
/* STIX_HBMASK_SAFE(stix_oow_t, v2 + 1) could also be
* used as a mask. but the sign bit is shifted in.
* so, masking up to 'v2' bits is sufficient */
v = (stix_ooi_t)(((stix_oow_t)v1 >> v2) | STIX_HBMASK(stix_oow_t, v2));
}
}
else
{
if (v2 >= STIX_OOI_BITS) v = 0;
else v = v1 >> v2;
}
if (STIX_IN_SMOOI_RANGE(v)) return STIX_SMOOI_TO_OOP(v);
return make_bigint_with_ooi (stix, v);
}
@ -2307,6 +2335,15 @@ stix_oop_t stix_bitshiftint (stix_t* stix, stix_oop_t x, stix_oop_t y)
v = STIX_OOP_TO_SMOOI(x);
if (v == 0) return STIX_SMOOI_TO_OOP(0);
if (STIX_OBJ_GET_CLASS(y) == stix->_large_negative_integer)
{
/* right shift - special case.
* x is a small integer. it is just a few bytes long.
* y is a large negative integer. its smallest absolute value
* is STIX_SMOOI_MAX. i know the final answer. */
return (v < 0)? STIX_SMOOI_TO_OOP(-1): STIX_SMOOI_TO_OOP(0);
}
stix_pushtmp (stix, &y);
x = make_bigint_with_ooi (stix, v);
stix_poptmp (stix);
@ -2348,10 +2385,24 @@ stix_oop_t stix_bitshiftint (stix_t* stix, stix_oop_t x, stix_oop_t y)
/* y is too big or too small */
if (negy)
{
/* TODO: right shift... */
/* right shift */
#if defined(STIX_LIMIT_OBJ_SIZE)
return (negx)? STIX_SMOOI_TO_OOP(-1): STIX_SMOOI_TO_OOP(0);
#else
/* TODO: */
#endif
}
else
{
/* 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 */
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;
#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
@ -2393,6 +2444,7 @@ stix_oop_t stix_bitshiftint (stix_t* stix, stix_oop_t x, stix_oop_t y)
goto left_shift_last;
else
z = x;
#endif
}
}
else if (sign >= 1)
@ -2821,8 +2873,8 @@ stix_oop_t stix_inttostr (stix_t* stix, stix_oop_t num, int radix)
b[0] = stix->bigint[radix].multiplier; /* block divisor */
bs = 1;
#elif (STIX_LIW_BITS == STIX_OOHW_BITS)
b[0] = stix->bigint[radix].multiplier & STIX_LBMASK(stix_oow_t, STIX_OOHW_BITS);
b[1] = stix->bigint[radix].multiplier >> STIX_OOHW_BITS;
b[0] = stix->bigint[radix].multiplier /*& STIX_LBMASK(stix_oow_t, STIX_LIW_BITS)*/;
b[1] = stix->bigint[radix].multiplier >> STIX_LIW_BITS;
bs = (b[1] > 0)? 2: 1;
#else
# error UNSUPPORTED LIW BIT SIZE

View File

@ -2049,7 +2049,7 @@ static stix_ooi_t find_class_level_variable (stix_t* stix, stix_oop_class_t self
super = ((stix_oop_class_t)super)->superclass;
}
stix->errnum = STIX_ENOMEM;
stix->errnum = STIX_ENOENT;
return -1;
done:

View File

@ -54,7 +54,7 @@ static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t oldbuc)
if (inc_max > 0) inc = inc_max;
else
{
stix->errnum = STIX_ENOMEM;
stix->errnum = STIX_EOOMEM;
return STIX_NULL;
}
}

View File

@ -1932,7 +1932,7 @@ static stix_prim_impl_t query_prim_module (stix_t* stix, const stix_ooch_t* name
pair = stix_rbt_insert (stix->modtab, name, mod_name_len, &md, STIX_SIZEOF(md));
if (pair == STIX_NULL)
{
stix->errnum = STIX_ENOMEM;
stix->errnum = STIX_ESYSMEM;
return STIX_NULL;
}
@ -1974,7 +1974,7 @@ static stix_prim_impl_t query_prim_module (stix_t* stix, const stix_ooch_t* name
pair = stix_rbt_insert (&stix->pmtable, (void*)name, mod_name_len, &md, STIX_SIZEOF(md));
if (pair == STIX_NULL)
{
stix->errnum = STIX_ENOMEM;
stix->errnum = STIX_ESYSMEM;
stix->vmprim.mod_close (stix, md.handle);
return STIX_NULL;
}

View File

@ -33,7 +33,7 @@ stix_heap_t* stix_makeheap (stix_t* stix, stix_oow_t size)
heap = (stix_heap_t*)STIX_MMGR_ALLOC(stix->mmgr, STIX_SIZEOF(*heap) + size);
if (!heap)
{
stix->errnum = STIX_ENOMEM;
stix->errnum = STIX_ESYSMEM;
return STIX_NULL;
}
@ -70,7 +70,7 @@ void* stix_allocheapmem (stix_t* stix, stix_heap_t* heap, stix_oow_t size)
if (STIX_GEPTR(stix_uint8_t, heap->ptr, heap->limit) ||
STIX_SUBPTR(stix_uint8_t, heap->limit, heap->ptr) < size)
{
stix->errnum = STIX_ENOMEM;
stix->errnum = STIX_EOOMEM;
return STIX_NULL;
}

View File

@ -347,8 +347,13 @@ typedef stix_ucs_t stix_oocs_t;
# define STIX_NULL ((void*)0)
#endif
/* make a low bit mask that can mask off low n bits*/
/* make a bit mask that can mask off low n bits */
#define STIX_LBMASK(type,n) (~(~((type)0) << (n)))
#define STIX_LBMASK_SAFE(type,n) (((n) < STIX_SIZEOF(type) * 8)? STIX_LBMASK(type,n): ~(type)0)
/* make a bit mask that can mask off hig n bits */
#define STIX_HBMASK(type,n) (~(~((type)0) >> (n)))
#define STIX_HBMASK_SAFE(type,n) (((n) < STIX_SIZEOF(type) * 8)? STIX_HBMASK(type,n): ~(type)0)
/* get 'length' bits starting from the bit at the 'offset' */
#define STIX_GETBITS(type,value,offset,length) \
@ -538,11 +543,11 @@ struct stix_cmgr_t
#define STIX_TYPE_IS_UNSIGNED(type) (((type)0) < ((type)-1))
#define STIX_TYPE_SIGNED_MAX(type) \
((type)~((type)1 << (STIX_SIZEOF(type) * 8 - 1)))
((type)~((type)1 << ((type)STIX_SIZEOF(type) * 8 - 1)))
#define STIX_TYPE_UNSIGNED_MAX(type) ((type)(~(type)0))
#define STIX_TYPE_SIGNED_MIN(type) \
((type)((type)1 << (STIX_SIZEOF(type) * 8 - 1)))
((type)((type)1 << ((type)STIX_SIZEOF(type) * 8 - 1)))
#define STIX_TYPE_UNSIGNED_MIN(type) ((type)0)
#define STIX_TYPE_MAX(type) \

View File

@ -55,6 +55,13 @@
/*#define STIX_DEBUG_EXEC*/
#define STIX_PROFILE_EXEC
/* limit the maximum object size such that:
* 1. an index to an object field can be represented in a small integer.
* 2. the maximum number of bit shifts can be represented in the stix_oow_t type.
*/
#define STIX_LIMIT_OBJ_SIZE
#include <stdio.h> /* TODO: delete these header inclusion lines */
#include <string.h>
#include <assert.h>
@ -207,6 +214,18 @@
#define STIX_MAX_CLASSVARS STIX_BITS_MAX(stix_oow_t, STIX_SMOOI_ABS_BITS / 2)
#define STIX_MAX_CLASSINSTVARS STIX_BITS_MAX(stix_oow_t, STIX_SMOOI_ABS_BITS / 2)
#if defined(STIX_LIMIT_OBJ_SIZE)
/* limit the maximum object size such that:
* 1. an index to an object field can be represented in a small integer.
* 2. the maximum number of bit shifts can be represented in the stix_oow_t type.
*/
# define STIX_OBJ_SIZE_MAX ((stix_oow_t)STIX_SMOOI_MAX)
#else
# define STIX_OBJ_SIZE_MAX ((stix_oow_t)STIX_TYPE_MAX(stix_oow_t))
#endif
#if defined(STIX_INCLUDE_COMPILER)
/* ========================================================================= */

View File

@ -45,7 +45,7 @@ stix_t* stix_open (stix_mmgr_t* mmgr, stix_oow_t xtnsize, stix_oow_t heapsize, c
}
else STIX_MEMSET (stix + 1, 0, xtnsize);
}
else if (errnum) *errnum = STIX_ENOMEM;
else if (errnum) *errnum = STIX_ESYSMEM;
return stix;
}
@ -249,7 +249,7 @@ void* stix_allocmem (stix_t* stix, stix_oow_t size)
void* ptr;
ptr = STIX_MMGR_ALLOC (stix->mmgr, size);
if (!ptr) stix->errnum = STIX_ENOMEM;
if (!ptr) stix->errnum = STIX_ESYSMEM;
return ptr;
}
@ -258,7 +258,7 @@ void* stix_callocmem (stix_t* stix, stix_oow_t size)
void* ptr;
ptr = STIX_MMGR_ALLOC (stix->mmgr, size);
if (!ptr) stix->errnum = STIX_ENOMEM;
if (!ptr) stix->errnum = STIX_ESYSMEM;
else STIX_MEMSET (ptr, 0, size);
return ptr;
}
@ -266,7 +266,7 @@ void* stix_callocmem (stix_t* stix, stix_oow_t size)
void* stix_reallocmem (stix_t* stix, void* ptr, stix_oow_t size)
{
ptr = STIX_MMGR_REALLOC (stix->mmgr, ptr, size);
if (!ptr) stix->errnum = STIX_ENOMEM;
if (!ptr) stix->errnum = STIX_ESYSMEM;
return ptr;
}

View File

@ -45,7 +45,8 @@ enum stix_errnum_t
STIX_ENOIMPL, /**< not implemented */
STIX_ESYSERR, /**< subsystem error */
STIX_EINTERN, /**< internal error */
STIX_ENOMEM, /**< insufficient memory */
STIX_ESYSMEM, /**< insufficient system memory */
STIX_EOOMEM, /**< insufficient object memory */
STIX_EINVAL, /**< invalid parameter or data */
STIX_ERANGE, /**< range error. overflow and underflow */
STIX_ENOENT, /**< no matching entry */
@ -296,9 +297,6 @@ typedef enum stix_obj_type_t stix_obj_type_t;
(((stix_oow_t)(r)) << 0) \
)
#define STIX_OBJ_SIZE_MAX ((stix_oow_t)STIX_SMOOI_MAX)
/*#define STIX_OBJ_SIZE_MAX ((stix_oow_t)STIX_TYPE_MAX(stix_oow_t))*/
#define STIX_OBJ_HEADER \
stix_oow_t _flags; \
stix_oow_t _size; \

View File

@ -53,7 +53,7 @@ static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t oldbuc)
if (inc_max > 0) inc = inc_max;
else
{
stix->errnum = STIX_ENOMEM;
stix->errnum = STIX_EOOMEM;
return STIX_NULL;
}
}