#include "bee2/core/util.h"
#include "bee2/math/ww.h"
void ppGCD(word d[], const word a[], size_t n, const word b[], size_t m,
void* stack)
{
register size_t s;
word* u = (word*)stack;
word* v = u + n;
ASSERT(wwIsDisjoint2(a, n, d, MIN2(n, m)));
ASSERT(wwIsDisjoint2(b, m, d, MIN2(n, m)));
ASSERT(!wwIsZero(a, n) && !wwIsZero(b, m));
wwSetZero(d, MIN2(n, m));
wwCopy(u, a, n);
wwCopy(v, b, m);
s = utilMin(2, wwLoZeroBits(u, n), wwLoZeroBits(v, m));
wwShLo(u, n, s);
n = wwWordSize(u, n);
wwShLo(v, m, s);
m = wwWordSize(v, m);
do
{
wwShLo(u, n, wwLoZeroBits(u, n));
n = wwWordSize(u, n);
wwShLo(v, m, wwLoZeroBits(v, m));
m = wwWordSize(v, m);
if (wwCmp2(u, n, v, m) >= 0)
wwXor2(u, v, m);
else
wwXor2(v, u, n);
}
while (!wwIsZero(u, n));
wwCopy(d, v, m);
wwShHi(d, W_OF_B(wwBitSize(d, m) + s), s);
CLEAN(s);
}
size_t ppGCD_deep(size_t n, size_t m)
{
return O_OF_W(n + m);
}
void ppExGCD(word d[], word da[], word db[], const word a[], size_t n,
const word b[], size_t m, void* stack)
{
register size_t s;
size_t nu, mv;
word* aa = (word*)stack;
word* bb = aa + n;
word* u = bb + m;
word* v = u + n;
word* da0 = v + m;
word* db0 = da0 + m;
ASSERT(wwIsDisjoint3(da, m, db, n, d, MIN2(n, m)));
ASSERT(wwIsDisjoint2(a, n, da, m));
ASSERT(wwIsDisjoint2(b, m, da, m));
ASSERT(wwIsDisjoint2(a, n, db, n));
ASSERT(wwIsDisjoint2(b, m, db, n));
ASSERT(!wwIsZero(a, n) && !wwIsZero(b, m));
wwSetZero(d, MIN2(n, m));
wwSetW(da0, m, 1);
wwSetZero(db0, n);
wwSetZero(da, m);
wwSetW(db, n, 1);
s = utilMin(2, wwLoZeroBits(a, n), wwLoZeroBits(b, m));
wwCopy(aa, a, n), wwShLo(aa, n, s), n = wwWordSize(aa, n);
wwCopy(bb, b, m), wwShLo(bb, m, s), m = wwWordSize(bb, m);
wwCopy(u, aa, n);
wwCopy(v, bb, m);
nu = n, mv = m;
do
{
for (; wwTestBit(u, 0) == 0; wwShLo(u, nu, 1))
if (wwTestBit(da0, 0) == 0)
{
wwShLo(da0, m, 1);
ASSERT(wwTestBit(db0, 0) == 0);
wwShLo(db0, n, 1);
}
else
{
wwXor2(da0, bb, m), wwShLo(da0, m, 1);
ASSERT(wwTestBit(db0, 0) == 1);
wwXor2(db0, aa, n), wwShLo(db0, n, 1);
}
for (; wwTestBit(v, 0) == 0; wwShLo(v, mv, 1))
if (wwTestBit(da, 0) == 0)
{
wwShLo(da, m, 1);
ASSERT(wwTestBit(db, 0) == 0);
wwShLo(db, n, 1);
}
else
{
wwXor2(da, bb, m), wwShLo(da, m, 1);
ASSERT(wwTestBit(db, 0) == 1);
wwXor2(db, aa, n), wwShLo(db, n, 1);
}
nu = wwWordSize(u, nu);
mv = wwWordSize(v, mv);
if (wwCmp2(u, nu, v, mv) >= 0)
{
wwXor2(u, v, mv);
wwXor2(da0, da, m);
wwXor2(db0, db, n);
}
else
{
wwXor2(v, u, nu);
wwXor2(da, da0, m);
wwXor2(db, db0, n);
}
}
while (!wwIsZero(u, nu));
wwCopy(d, v, m);
wwShHi(d, W_OF_B(wwBitSize(d, m) + s), s);
CLEAN(s);
}
size_t ppExGCD_deep(size_t n, size_t m)
{
return O_OF_W(3 * n + 3 * m);
}