touched up divide_unsigned_array2()
This commit is contained in:
parent
55b18c998c
commit
96f3ebae4b
92
moo/kernel/test-bi.moo
Normal file
92
moo/kernel/test-bi.moo
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
#include 'Moo.moo'.
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
## MAIN
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
class MyObject(Object)
|
||||||
|
{
|
||||||
|
var(#class) a := 100.
|
||||||
|
var(#classinst) K := 200.
|
||||||
|
|
||||||
|
method(#class) testBigintDiv
|
||||||
|
{
|
||||||
|
| i q r divd divr divd_ubound divr_ubound |
|
||||||
|
|
||||||
|
divr_ubound := 16rFFFFFFFFFFFFFFFFFFFFFFFF.
|
||||||
|
divd_ubound := 16rFFFFFFFFFFFFFFFFFFFFFFFF.
|
||||||
|
|
||||||
|
divr := 1.
|
||||||
|
while (divr <= divr_ubound)
|
||||||
|
{
|
||||||
|
('divr => ' & divr asString) dump.
|
||||||
|
|
||||||
|
divd := 0.
|
||||||
|
while (divd <= divd_ubound)
|
||||||
|
{
|
||||||
|
q := divd div: divr.
|
||||||
|
r := divd rem: divr.
|
||||||
|
if (divd ~= (q * divr + r)) { i dump. divd dump. divr dump. q dump. r dump. (q * divr + r) dump. ^false. }.
|
||||||
|
divd := divd + 1.
|
||||||
|
}.
|
||||||
|
divd := divr + 1.
|
||||||
|
}.
|
||||||
|
^true
|
||||||
|
}
|
||||||
|
|
||||||
|
method(#class) testBigintDiv2
|
||||||
|
{
|
||||||
|
| ffi i q r divd divr divd_ubound divr_ubound now x |
|
||||||
|
|
||||||
|
|
||||||
|
ffi := FFI new: 'libc.so.6'.
|
||||||
|
now := ffi call: #time signature: 'l)i' arguments: #(0).
|
||||||
|
####ffi call: #srand signature: 'i)' arguments: %(now).
|
||||||
|
ffi call: #srandom signature: 'i)' arguments: %(now).
|
||||||
|
|
||||||
|
[
|
||||||
|
divr_ubound := 16rFFFFFFFFFFFFFFFFFFFFFFFF.
|
||||||
|
divd_ubound := 16rFFFFFFFFFFFFFFFFFFFFFFFF.
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
##x := (ffi call: #rand signature: ')i' arguments: nil) rem: 20.
|
||||||
|
##divd := (ffi call: #rand signature: ')i' arguments: nil).
|
||||||
|
x := (ffi call: #random signature: ')l' arguments: nil) rem: 20.
|
||||||
|
divd := (ffi call: #random signature: ')l' arguments: nil).
|
||||||
|
while (x > 0)
|
||||||
|
{
|
||||||
|
##divd := (divd bitShift: 7) bitOr: (ffi call: #rand signature: ')i' arguments: nil).
|
||||||
|
divd := (divd bitShift: 7) bitOr: (ffi call: #random signature: ')l' arguments: nil).
|
||||||
|
x := x - 1.
|
||||||
|
}.
|
||||||
|
|
||||||
|
##x := (ffi call: #rand signature: ')i' arguments: nil) rem: 20.
|
||||||
|
##divr := (ffi call: #rand signature: ')i' arguments: nil).
|
||||||
|
x := (ffi call: #random signature: ')l' arguments: nil) rem: 20.
|
||||||
|
divr := (ffi call: #random signature: ')l' arguments: nil).
|
||||||
|
while (x > 0)
|
||||||
|
{
|
||||||
|
##divr := (divr bitShift: 7) bitOr: (ffi call: #rand signature: ')i' arguments: nil).
|
||||||
|
divr := (divr bitShift: 7) bitOr: (ffi call: #random signature: ')l' arguments: nil).
|
||||||
|
x := x - 1.
|
||||||
|
}.
|
||||||
|
if (divr = 0) { divr := 1 }.
|
||||||
|
|
||||||
|
q := divd div: divr.
|
||||||
|
r := divd rem: divr.
|
||||||
|
if (divd ~= (q * divr + r)) { i dump. divd dump. divr dump. q dump. r dump. (q * divr + r) dump. ^false. }.
|
||||||
|
####((q asString) & ' ' & (r asString)) dump
|
||||||
|
}.
|
||||||
|
] ensure: [ ffi close. ].
|
||||||
|
^true
|
||||||
|
}
|
||||||
|
|
||||||
|
method(#class) main
|
||||||
|
{
|
||||||
|
self testBigintDiv2.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
114
moo/lib/bigint.c
114
moo/lib/bigint.c
@ -1702,37 +1702,6 @@ static void divide_unsigned_array (moo_t* moo, const moo_liw_t* x, moo_oow_t xs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
static moo_liw_t adjust_for_over_estimate (moo_liw_t y1, moo_liw_t y2, moo_liw_t quo, moo_liw_t xi, moo_liw_t xi2)
|
|
||||||
{
|
|
||||||
moo_lidw_t dw;
|
|
||||||
moo_liw_t c, c2, y2q;
|
|
||||||
|
|
||||||
/*moo_liw_t y2q = axpy(y2, q, 0, c);*/
|
|
||||||
dw = ((moo_lidw_t)quo * y2);
|
|
||||||
c = (moo_liw_t)(dw >> MOO_LIW_BITS);
|
|
||||||
y2q = (moo_liw_t)dw;
|
|
||||||
|
|
||||||
if (c > xi || (c == xi && y2q > xi2))
|
|
||||||
//if (c > xi || (c == xi && xi2 > y2q))
|
|
||||||
{
|
|
||||||
--quo; /* too large by 1 */
|
|
||||||
|
|
||||||
/*xpy(xi, y1, c2); add back divisor */
|
|
||||||
c2 = (moo_liw_t)(((moo_lidw_t)xi + y1) >> MOO_LIW_BITS);
|
|
||||||
if (c2 == 0)
|
|
||||||
{
|
|
||||||
/*y2q = axpy(y2, q, 0, c);*/
|
|
||||||
dw = ((moo_lidw_t)quo * y2);
|
|
||||||
c = (moo_liw_t)(dw >> MOO_LIW_BITS);
|
|
||||||
y2q = (moo_liw_t)dw;
|
|
||||||
if (c > xi || (c == xi && y2q > xi2)) --quo; /* too large by 2 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return quo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static moo_liw_t adjust_for_underflow (moo_liw_t* qr, moo_liw_t* divisor, moo_oow_t qr_start, moo_oow_t stop)
|
static moo_liw_t adjust_for_underflow (moo_liw_t* qr, moo_liw_t* divisor, moo_oow_t qr_start, moo_oow_t stop)
|
||||||
{
|
{
|
||||||
moo_lidw_t dw;
|
moo_lidw_t dw;
|
||||||
@ -1750,7 +1719,7 @@ static moo_liw_t adjust_for_underflow (moo_liw_t* qr, moo_liw_t* divisor, moo_oo
|
|||||||
return carry;
|
return carry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static moo_liw_t calculate_remainder (moo_t* moo, moo_liw_t* qr, moo_liw_t* y, moo_liw_t quo, int qr_start, int stop)
|
static MOO_INLINE moo_liw_t calculate_remainder (moo_t* moo, moo_liw_t* qr, moo_liw_t* y, moo_liw_t quo, int qr_start, int stop)
|
||||||
{
|
{
|
||||||
moo_lidw_t dw;
|
moo_lidw_t dw;
|
||||||
moo_liw_t b, c, c2, qyk;
|
moo_liw_t b, c, c2, qyk;
|
||||||
@ -1860,12 +1829,12 @@ static void divide_unsigned_array2 (moo_t* moo, const moo_liw_t* x, moo_oow_t xs
|
|||||||
xlo = q[i - 1];
|
xlo = q[i - 1];
|
||||||
|
|
||||||
/* adjust the quotient if over-estimated */
|
/* adjust the quotient if over-estimated */
|
||||||
#if 1
|
|
||||||
dw = ((moo_lidw_t)xhi << MOO_LIW_BITS) + xlo;
|
dw = ((moo_lidw_t)xhi << MOO_LIW_BITS) + xlo;
|
||||||
/* TODO: optimize it with ASM - no seperate / and % */
|
/* TODO: optimize it with ASM - no seperate / and % */
|
||||||
quo = dw / y1;
|
quo = dw / y1;
|
||||||
rem = dw % y1;
|
rem = dw % y1;
|
||||||
/*rem = dw - (quo * y1);*/
|
/*rem = dw - (quo * y1);*/
|
||||||
|
#if 0
|
||||||
adjust_quotient:
|
adjust_quotient:
|
||||||
if (quo > MOO_TYPE_MAX(moo_liw_t) || (quo * y2) > ((rem << MOO_LIW_BITS) + q[i - 2]))
|
if (quo > MOO_TYPE_MAX(moo_liw_t) || (quo * y2) > ((rem << MOO_LIW_BITS) + q[i - 2]))
|
||||||
{
|
{
|
||||||
@ -1874,19 +1843,6 @@ static void divide_unsigned_array2 (moo_t* moo, const moo_liw_t* x, moo_oow_t xs
|
|||||||
if (rem <= MOO_TYPE_MAX(moo_liw_t)) goto adjust_quotient;
|
if (rem <= MOO_TYPE_MAX(moo_liw_t)) goto adjust_quotient;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/*if (xhi == y1)
|
|
||||||
{
|
|
||||||
quo = MOO_TYPE_MAX(moo_liw_t);
|
|
||||||
rem = q[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ */
|
|
||||||
dw = ((moo_lidw_t)xhi << MOO_LIW_BITS) + xlo;
|
|
||||||
/* TODO: optimize it with ASM - no seperate / and % */
|
|
||||||
quo = dw / y1;
|
|
||||||
//q[i] = (moo_liw_t)(dw % y1);
|
|
||||||
rem = dw % y1;
|
|
||||||
/*}*/
|
|
||||||
adjust_quotient:
|
adjust_quotient:
|
||||||
dw = quo * y2;
|
dw = quo * y2;
|
||||||
b = (moo_liw_t)(dw >> MOO_LIW_BITS);
|
b = (moo_liw_t)(dw >> MOO_LIW_BITS);
|
||||||
@ -1901,14 +1857,25 @@ static void divide_unsigned_array2 (moo_t* moo, const moo_liw_t* x, moo_oow_t xs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ---------------------------------------------------------- */
|
/* ---------------------------------------------------------- */
|
||||||
b = calculate_remainder(moo, q, r, quo, i - ys, ys);
|
b = calculate_remainder(moo, q, r, quo, i - ys, ys);
|
||||||
b = (moo_liw_t)((((moo_lidw_t)xhi - b) >> MOO_LIW_BITS) & 1); /* is the sign bit set? */
|
b = (moo_liw_t)((((moo_lidw_t)xhi - b) >> MOO_LIW_BITS) & 1); /* is the sign bit set? */
|
||||||
if (b)
|
if (b)
|
||||||
{
|
{
|
||||||
/* yes. underflow */
|
/* yes. underflow */
|
||||||
b = adjust_for_underflow(q, r, i - ys, ys);
|
moo_lidw_t dw;
|
||||||
MOO_ASSERT (moo, b == 1);
|
moo_liw_t carry;
|
||||||
|
moo_oow_t j, k;
|
||||||
|
|
||||||
|
for (carry = 0, j = i - ys, k = 0; k < ys; j++, k++)
|
||||||
|
{
|
||||||
|
dw = (moo_lidw_t)q[j] + r[k] + carry;
|
||||||
|
carry = (moo_liw_t)(dw >> MOO_LIW_BITS);
|
||||||
|
q[j] = (moo_liw_t)dw;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOO_ASSERT (moo, carry == 1);
|
||||||
q[i] = quo - 1;
|
q[i] = quo - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1937,14 +1904,13 @@ static void divide_unsigned_array2 (moo_t* moo, const moo_liw_t* x, moo_oow_t xs
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < ys; i++) { r[i] = q[i]; q[i] = 0; }
|
for (i = 0; i < ys; i++) { r[i] = q[i]; q[i] = 0; }
|
||||||
for (; i <= xs; i++) { q[i - ys] = q[i]; q[i] = 0; }
|
for (; i <= xs; i++) { q[i - ys] = q[i]; q[i] = 0; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void divide_unsigned_array3 (moo_t* moo, const moo_liw_t* x, moo_oow_t xs, const moo_liw_t* y, moo_oow_t ys, moo_liw_t* q, moo_liw_t* r)
|
static void divide_unsigned_array3 (moo_t* moo, const moo_liw_t* x, moo_oow_t xs, const moo_liw_t* y, moo_oow_t ys, moo_liw_t* q, moo_liw_t* r)
|
||||||
{
|
{
|
||||||
moo_oow_t s, i, j, g;
|
moo_oow_t s, i, j, g, k;
|
||||||
moo_lidw_t dw, qhat, rhat;
|
moo_lidw_t dw, qhat, rhat;
|
||||||
moo_lidi_t t, k;
|
moo_lidi_t di, ci;
|
||||||
moo_liw_t* qq, y1, y2;
|
moo_liw_t* qq, y1, y2;
|
||||||
|
|
||||||
/* the caller must ensure:
|
/* the caller must ensure:
|
||||||
@ -1975,7 +1941,8 @@ static void divide_unsigned_array3 (moo_t* moo, const moo_liw_t* x, moo_oow_t xs
|
|||||||
|
|
||||||
reqcapa = MOO_ALIGN_POW2(xs + 1, 32);
|
reqcapa = MOO_ALIGN_POW2(xs + 1, 32);
|
||||||
t = (moo_liw_t*)moo_reallocmem(moo, moo->inttostr.t.ptr, reqcapa * MOO_SIZEOF(*t));
|
t = (moo_liw_t*)moo_reallocmem(moo, moo->inttostr.t.ptr, reqcapa * MOO_SIZEOF(*t));
|
||||||
//if (!t) return -1; // TOOD:
|
/* TODO: TODO: TODO: ERROR HANDLING
|
||||||
|
if (!t) return -1; */
|
||||||
|
|
||||||
moo->inttostr.t.capa = xs + 1;
|
moo->inttostr.t.capa = xs + 1;
|
||||||
moo->inttostr.t.ptr = t;
|
moo->inttostr.t.ptr = t;
|
||||||
@ -2022,31 +1989,36 @@ static void divide_unsigned_array3 (moo_t* moo, const moo_liw_t* x, moo_oow_t xs
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* multiply and subtract */
|
/* multiply and subtract */
|
||||||
for (k = 0, i = 0; i < ys; i++)
|
for (ci = 0, i = j - ys, k = 0; k < ys; i++, k++)
|
||||||
{
|
{
|
||||||
dw = qhat * r[i];
|
dw = qhat * r[k];
|
||||||
t = qq[g + i] - k - (dw & MOO_TYPE_MAX(moo_liw_t));
|
di = qq[i] - ci - (dw & MOO_TYPE_MAX(moo_liw_t));
|
||||||
qq[g + i] = t;
|
qq[i] = di;
|
||||||
k = (dw >> MOO_LIW_BITS) - (t >> MOO_LIW_BITS);
|
ci = (dw >> MOO_LIW_BITS) - (di >> MOO_LIW_BITS);
|
||||||
}
|
}
|
||||||
MOO_ASSERT (moo, j == g + ys);
|
MOO_ASSERT (moo, i == j);
|
||||||
t = qq[j] - k;
|
di = qq[j] - ci;
|
||||||
qq[j] = t;
|
qq[j] = di;
|
||||||
|
|
||||||
/* test remainder */
|
/* test remainder */
|
||||||
q[g] = qhat; /* store quotient */
|
if (di < 0)
|
||||||
if (t < 0)
|
|
||||||
{
|
{
|
||||||
q[g] = q[g] - 1; /* add back */
|
for (ci = 0, i = j - ys, k = 0; k < ys; i++, k++)
|
||||||
|
|
||||||
for (k = 0, i = 0; i < ys; i++)
|
|
||||||
{
|
{
|
||||||
t = (moo_lidw_t)qq[g + i] + r[i] + k;
|
di = (moo_lidw_t)qq[i] + r[k] + ci;
|
||||||
qq[g + i] = (moo_liw_t)t;
|
ci = (moo_liw_t)(di >> MOO_LIW_BITS);
|
||||||
k = t >> MOO_LIW_BITS;
|
qq[i] = (moo_liw_t)di;
|
||||||
}
|
}
|
||||||
MOO_ASSERT (moo, j == g + ys);
|
|
||||||
qq[j] += k;
|
MOO_ASSERT (moo, i == j);
|
||||||
|
/*MOO_ASSERT (moo, ci == 1);*/
|
||||||
|
qq[j] += ci;
|
||||||
|
|
||||||
|
q[g] = qhat - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
q[g] = qhat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2186,7 +2158,7 @@ static moo_oop_t divide_unsigned_integers (moo_t* moo, moo_oop_t x, moo_oop_t y,
|
|||||||
moo_pushvolat (moo, &x);
|
moo_pushvolat (moo, &x);
|
||||||
moo_pushvolat (moo, &y);
|
moo_pushvolat (moo, &y);
|
||||||
#define USE_DIVIDE_UNSIGNED_ARRAY2
|
#define USE_DIVIDE_UNSIGNED_ARRAY2
|
||||||
//#define USE_DIVIDE_UNSIGNED_ARRAY3
|
/*#define USE_DIVIDE_UNSIGNED_ARRAY3*/
|
||||||
|
|
||||||
#if defined(USE_DIVIDE_UNSIGNED_ARRAY2) || defined(USE_DIVIDE_UNSIGNED_ARRAY3)
|
#if defined(USE_DIVIDE_UNSIGNED_ARRAY2) || defined(USE_DIVIDE_UNSIGNED_ARRAY3)
|
||||||
qq = moo_instantiate(moo, moo->_large_positive_integer, MOO_NULL, MOO_OBJ_GET_SIZE(x) + 1);
|
qq = moo_instantiate(moo, moo->_large_positive_integer, MOO_NULL, MOO_OBJ_GET_SIZE(x) + 1);
|
||||||
|
Loading…
Reference in New Issue
Block a user