214 lines
4.5 KiB
C
214 lines
4.5 KiB
C
|
|
||
|
#include "stix-prv.h"
|
||
|
|
||
|
/*static normalize_integer (*/
|
||
|
|
||
|
static stix_oop_t normalize (stix_t* stix, stix_oop_t z)
|
||
|
{
|
||
|
return z;
|
||
|
}
|
||
|
|
||
|
static STIX_INLINE int is_less_unsigned_array (const stix_oohw_t* x, stix_oow_t xs, const stix_oohw_t* y, stix_oow_t ys)
|
||
|
{
|
||
|
stix_oow_t i;
|
||
|
|
||
|
if (xs != ys) return xs < ys;
|
||
|
for (i = xs; i > 0; )
|
||
|
{
|
||
|
--i;
|
||
|
if (x[i] != y[i]) return x[i] < y[i];
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static STIX_INLINE int is_less_unsigned (stix_oop_t x, stix_oop_t y)
|
||
|
{
|
||
|
return is_less_unsigned_array (
|
||
|
((stix_oop_halfword_t)x)->slot, STIX_OBJ_GET_SIZE(x),
|
||
|
((stix_oop_halfword_t)y)->slot, STIX_OBJ_GET_SIZE(y));
|
||
|
}
|
||
|
|
||
|
static STIX_INLINE int is_less (stix_t* stix, stix_oop_t x, stix_oop_t y)
|
||
|
{
|
||
|
if (STIX_OBJ_GET_CLASS(x) != STIX_OBJ_GET_CLASS(y))
|
||
|
{
|
||
|
return STIX_OBJ_GET_CLASS(x) == stix->_large_negative_integer;
|
||
|
}
|
||
|
|
||
|
return is_less_unsigned (x, y);
|
||
|
}
|
||
|
|
||
|
static STIX_INLINE int is_equal (stix_t* stix, stix_oop_t x, stix_oop_t y)
|
||
|
{
|
||
|
/* check if two large integers are equal to each other */
|
||
|
return STIX_OBJ_GET_CLASS(x) == STIX_OBJ_GET_CLASS(y) && STIX_OBJ_GET_SIZE(x) == STIX_OBJ_GET_SIZE(y) &&
|
||
|
STIX_MEMCMP(((stix_oop_halfword_t)x)->slot, ((stix_oop_halfword_t)y)->slot, STIX_OBJ_GET_SIZE(x) * STIX_SIZEOF(stix_oohw_t)) == 0;
|
||
|
}
|
||
|
|
||
|
static STIX_INLINE stix_oow_t add_unsigned_array (const stix_oohw_t* x, stix_oow_t xs, const stix_oohw_t* y, stix_oow_t ys, stix_oohw_t* z)
|
||
|
{
|
||
|
stix_oow_t i, w;
|
||
|
stix_oow_t carry = 0;
|
||
|
|
||
|
STIX_ASSERT (xs >= ys);
|
||
|
|
||
|
for (i = 0; i < ys; i++)
|
||
|
{
|
||
|
w = (stix_oow_t)x[i] + (stix_oow_t)y[i] + carry;
|
||
|
carry = w >> STIX_OOHW_BITS;
|
||
|
z[i] = w & STIX_LBMASK(stix_oow_t, STIX_OOHW_BITS);
|
||
|
}
|
||
|
|
||
|
for (; i < xs; i++)
|
||
|
{
|
||
|
w = (stix_oow_t)x[i] + carry;
|
||
|
carry = w >> STIX_OOHW_BITS;
|
||
|
z[i] = w & STIX_LBMASK(stix_oow_t, STIX_OOHW_BITS);
|
||
|
}
|
||
|
|
||
|
if (i > 1 && carry == 0) return i - 1;
|
||
|
z[i] = carry;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
static STIX_INLINE stix_oow_t subtract_unsigned_array (const stix_oohw_t* x, stix_oow_t xs, const stix_oohw_t* y, stix_oow_t ys, stix_oohw_t* z)
|
||
|
{
|
||
|
stix_oow_t i, w;
|
||
|
stix_oow_t borrow = 0;
|
||
|
stix_oow_t borrowed_word;
|
||
|
|
||
|
STIX_ASSERT (!is_less_unsigned_array(x, xs, y, ys));
|
||
|
|
||
|
borrowed_word = (stix_oow_t)1 << STIX_OOHW_BITS;
|
||
|
for (i = 0; i < ys; i++)
|
||
|
{
|
||
|
w = (stix_oow_t)y[i] + borrow;
|
||
|
if ((stix_oow_t)x[i] >= w)
|
||
|
{
|
||
|
z[i] = x[i] - w;
|
||
|
borrow = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
z[i] = (borrowed_word + (stix_oow_t)x[i]) - w;
|
||
|
borrow = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (; i < xs; i++)
|
||
|
{
|
||
|
if (x[i] >= borrow)
|
||
|
{
|
||
|
z[i] = x[i] - (stix_oohw_t)borrow;
|
||
|
borrow = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
z[i] = (borrowed_word + (stix_oow_t)x[i]) - borrow;
|
||
|
borrow = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
STIX_ASSERT (borrow == 0);
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
static stix_oop_t add_unsigned_integers (stix_t* stix, stix_oop_t x, stix_oop_t y)
|
||
|
{
|
||
|
stix_oohw_t* a, * b;
|
||
|
stix_oow_t as, bs, zs, ks;
|
||
|
stix_oop_t z;
|
||
|
|
||
|
as = STIX_OBJ_GET_SIZE(x);
|
||
|
bs = STIX_OBJ_GET_SIZE(y);
|
||
|
zs = (as >= bs? as: bs) + 1;
|
||
|
|
||
|
stix_pushtmp (stix, &x);
|
||
|
stix_pushtmp (stix, &y);
|
||
|
z = stix_instantiate (stix, STIX_OBJ_GET_CLASS(x), STIX_NULL, zs);
|
||
|
stix_poptmps (stix, 2);
|
||
|
|
||
|
if (as >= bs)
|
||
|
{
|
||
|
a = ((stix_oop_halfword_t)x)->slot;
|
||
|
b = ((stix_oop_halfword_t)y)->slot;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
a = ((stix_oop_halfword_t)y)->slot;
|
||
|
b = ((stix_oop_halfword_t)x)->slot;
|
||
|
}
|
||
|
|
||
|
ks = add_unsigned_array (a, as, b, bs, ((stix_oop_halfword_t)z)->slot);
|
||
|
if (ks <= zs)
|
||
|
{
|
||
|
/*normalize;*/
|
||
|
}
|
||
|
|
||
|
return z;
|
||
|
}
|
||
|
|
||
|
static stix_oop_t subtract_unsigned_integers (stix_t* stix, stix_oop_t x, stix_oop_t y)
|
||
|
{
|
||
|
stix_oop_t z;
|
||
|
|
||
|
stix_pushtmp (stix, &x);
|
||
|
stix_pushtmp (stix, &y);
|
||
|
z = stix_instantiate (stix, stix->_large_positive_integer, STIX_NULL, STIX_OBJ_GET_SIZE(x));
|
||
|
stix_poptmps (stix, 2);
|
||
|
|
||
|
subtract_unsigned_array (
|
||
|
((stix_oop_halfword_t)x)->slot, STIX_OBJ_GET_SIZE(x),
|
||
|
((stix_oop_halfword_t)y)->slot, STIX_OBJ_GET_SIZE(y),
|
||
|
((stix_oop_halfword_t)z)->slot);
|
||
|
return z;
|
||
|
}
|
||
|
|
||
|
|
||
|
stix_oop_t stix_addbigints (stix_t* stix, stix_oop_t x, stix_oop_t y)
|
||
|
{
|
||
|
stix_oop_t z;
|
||
|
|
||
|
if (STIX_OBJ_GET_CLASS(x) != STIX_OBJ_GET_CLASS(y))
|
||
|
{
|
||
|
if (STIX_OBJ_GET_CLASS(x) == stix->_large_negative_integer)
|
||
|
z = stix_subbigints (stix, y, x);
|
||
|
else
|
||
|
z = stix_subbigints (stix, x, y);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
z = add_unsigned_integers (stix, x, y);
|
||
|
}
|
||
|
|
||
|
return normalize(stix, z);
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
stix_subbigints (stix_t* stix, stix_oop_t x, stix_oop_t y)
|
||
|
{
|
||
|
/* TOOD: ensure both are LargeIntgers */
|
||
|
|
||
|
if (STIX_OBJ_GET_CLASS(x) != STIX_OBJ_GET_CLASS(y))
|
||
|
{
|
||
|
z = add_unsigned (stix, x, y);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (is_less_unsigned (x, y))
|
||
|
{
|
||
|
z = subtract_unsigned (stix, y, x); /* get the opposite sign of x; */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
z = subtract_unsigned (stix, x, y); /* take x's sign */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return normalize (stix, z);
|
||
|
}
|
||
|
#endif
|