optimized the bigint division a bit more
This commit is contained in:
parent
983026c774
commit
45b21a004b
@ -262,6 +262,27 @@ extend MyObject
|
|||||||
[ (811306333091350399588761 div: 128) = 6338330727276174996787 ],
|
[ (811306333091350399588761 div: 128) = 6338330727276174996787 ],
|
||||||
[ (811306333091350399588761 rem: 128) = 25 ],
|
[ (811306333091350399588761 rem: 128) = 25 ],
|
||||||
[ (811306333091350399588761 mod: 128) = 25 ],
|
[ (811306333091350399588761 mod: 128) = 25 ],
|
||||||
|
[ (-811306333091350399588761 div: -16) = 50706645818209399974297 ],
|
||||||
|
|
||||||
|
## 100-104
|
||||||
|
[ (-811306333091350399588761 rem: -16) = -9 ],
|
||||||
|
[ (-811306333091350399588761 mod: -16) = -9 ],
|
||||||
|
[ (-811306333091350399588761 div: -128) = 6338330727276174996787 ],
|
||||||
|
[ (-811306333091350399588761 rem: -128) = -25 ],
|
||||||
|
[ (-811306333091350399588761 mod: -128) = -25 ],
|
||||||
|
|
||||||
|
## 105-109
|
||||||
|
[ (-8113063330913503995887611892379812731289731289312898971231 div: -1024) = 7922913409095218745983995988652160870400128212219627901 ],
|
||||||
|
[ (-8113063330913503995887611892379812731289731289312898971231 rem: -1024) = -607 ],
|
||||||
|
[ (-8113063330913503995887611892379812731289731289312898971231 mod: -1024) = -607 ],
|
||||||
|
[ (-8113063330913503995887611892379812731289731289312898971231 div: -65535) = 123797411015693964994088836383303772507663558240831600 ],
|
||||||
|
[ (-8113063330913503995887611892379812731289731289312898971231 rem: -65535) = -65231 ],
|
||||||
|
|
||||||
|
## 110-114
|
||||||
|
[ (-8113063330913503995887611892379812731289731289312898971231 mod: -65535) = -65231 ],
|
||||||
|
[ (-8113063330913503995887611892379812731289731289312898971231 div: -65536) = 123795522017112792905999937322690013600002003315931685 ],
|
||||||
|
[ (-8113063330913503995887611892379812731289731289312898971231 rem: -65536) = -63071 ],
|
||||||
|
[ (-8113063330913503995887611892379812731289731289312898971231 mod: -65536) = -63071 ],
|
||||||
|
|
||||||
## =========================
|
## =========================
|
||||||
[
|
[
|
||||||
|
114
moo/lib/bigint.c
114
moo/lib/bigint.c
@ -2192,47 +2192,91 @@ moo_oop_t moo_divints (moo_t* moo, moo_oop_t x, moo_oop_t y, int modulo, moo_oop
|
|||||||
return z;
|
return z;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* TODO: do division by shifting if both x & y are negative here */
|
/* TODO: do division by shifting if both x & y are in different sign */
|
||||||
if (yv > 0 && IS_POW2(yv) && !MOO_POINTER_IS_NBIGINT(moo, x))
|
if (yv < 0)
|
||||||
{
|
{
|
||||||
moo_oow_t nshifts;
|
moo_oow_t yv_neg = -yv;
|
||||||
|
if (IS_POW2(yv_neg) && MOO_POINTER_IS_NBIGINT(moo, x))
|
||||||
/*
|
|
||||||
2**x = v
|
|
||||||
x = log2(v)
|
|
||||||
x is the number of shift to make */
|
|
||||||
nshifts = LOG2_FOR_POW2(yv);
|
|
||||||
|
|
||||||
moo_pushvolat (moo, &x);
|
|
||||||
moo_pushvolat (moo, &y);
|
|
||||||
z = clone_bigint(moo, x, MOO_OBJ_GET_SIZE(x));
|
|
||||||
moo_popvolats (moo, 2);
|
|
||||||
if (!z) return MOO_NULL;
|
|
||||||
|
|
||||||
rshift_unsigned_array (MOO_OBJ_GET_LIWORD_SLOT(z), MOO_OBJ_GET_SIZE(z), nshifts);
|
|
||||||
|
|
||||||
moo_pushvolat (moo, &x);
|
|
||||||
moo_pushvolat (moo, &y);
|
|
||||||
z = normalize_bigint(moo, z);
|
|
||||||
moo_popvolats (moo, 2);
|
|
||||||
if (!z) return MOO_NULL;
|
|
||||||
|
|
||||||
if (rem)
|
|
||||||
{
|
{
|
||||||
|
moo_oow_t nshifts;
|
||||||
|
|
||||||
|
nshifts = LOG2_FOR_POW2(yv_neg);
|
||||||
|
|
||||||
moo_pushvolat (moo, &x);
|
moo_pushvolat (moo, &x);
|
||||||
moo_pushvolat (moo, &z);
|
z = clone_bigint_negated(moo, x, MOO_OBJ_GET_SIZE(x));
|
||||||
r = moo_mulints(moo, y, z);
|
|
||||||
moo_popvolats (moo, 2);
|
|
||||||
if (!r) return MOO_NULL;
|
|
||||||
|
|
||||||
moo_pushvolat (moo, &z);
|
|
||||||
r = moo_subints(moo, x, r);
|
|
||||||
moo_popvolat (moo);
|
moo_popvolat (moo);
|
||||||
if (!r) return MOO_NULL;
|
if (!z) return MOO_NULL;
|
||||||
|
|
||||||
*rem = r;
|
rshift_unsigned_array (MOO_OBJ_GET_LIWORD_SLOT(z), MOO_OBJ_GET_SIZE(z), nshifts);
|
||||||
|
|
||||||
|
moo_pushvolat (moo, &x);
|
||||||
|
z = normalize_bigint(moo, z);
|
||||||
|
moo_popvolat (moo);
|
||||||
|
if (!z) return MOO_NULL;
|
||||||
|
|
||||||
|
if (rem)
|
||||||
|
{
|
||||||
|
moo_pushvolat (moo, &x);
|
||||||
|
moo_pushvolat (moo, &z);
|
||||||
|
r = moo_mulints(moo, MOO_SMOOI_TO_OOP(yv_neg), z);
|
||||||
|
moo_popvolats (moo, 2);
|
||||||
|
if (!r) return MOO_NULL;
|
||||||
|
|
||||||
|
moo_pushvolat (moo, &z);
|
||||||
|
r = moo_addints(moo, x, r);
|
||||||
|
moo_popvolat (moo);
|
||||||
|
if (!r) return MOO_NULL;
|
||||||
|
|
||||||
|
*rem = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* yv > 0 */
|
||||||
|
if (IS_POW2(yv) && MOO_POINTER_IS_PBIGINT(moo, x))
|
||||||
|
{
|
||||||
|
moo_oow_t nshifts;
|
||||||
|
|
||||||
|
/*
|
||||||
|
2**x = v
|
||||||
|
x = log2(v)
|
||||||
|
x is the number of shift to make */
|
||||||
|
nshifts = LOG2_FOR_POW2(yv);
|
||||||
|
|
||||||
|
/* no pushvolat() on y as y is SMOOI here */
|
||||||
|
moo_pushvolat (moo, &x);
|
||||||
|
z = clone_bigint(moo, x, MOO_OBJ_GET_SIZE(x));
|
||||||
|
moo_popvolat (moo);
|
||||||
|
if (!z) return MOO_NULL;
|
||||||
|
|
||||||
|
rshift_unsigned_array (MOO_OBJ_GET_LIWORD_SLOT(z), MOO_OBJ_GET_SIZE(z), nshifts);
|
||||||
|
|
||||||
|
moo_pushvolat (moo, &x);
|
||||||
|
z = normalize_bigint(moo, z);
|
||||||
|
moo_popvolat (moo);
|
||||||
|
if (!z) return MOO_NULL;
|
||||||
|
|
||||||
|
if (rem)
|
||||||
|
{
|
||||||
|
moo_pushvolat (moo, &x);
|
||||||
|
moo_pushvolat (moo, &z);
|
||||||
|
r = moo_mulints(moo, y, z);
|
||||||
|
moo_popvolats (moo, 2);
|
||||||
|
if (!r) return MOO_NULL;
|
||||||
|
|
||||||
|
moo_pushvolat (moo, &z);
|
||||||
|
r = moo_subints(moo, x, r);
|
||||||
|
moo_popvolat (moo);
|
||||||
|
if (!r) return MOO_NULL;
|
||||||
|
|
||||||
|
*rem = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return z;
|
||||||
}
|
}
|
||||||
return z;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user