#include "bee2/core/util.h"
#include "bee2/core/word.h"
#include "bee2/math/ww.h"
#include "bee2/math/zm.h"
#include "bee2/math/zz.h"
void zzPowerMod(word c[], const word a[], size_t n, const word b[], size_t m,
const word mod[], void* stack)
{
size_t no;
word* t;
qr_o* r;
ASSERT(n > 0 && mod[n - 1] != 0);
ASSERT(wwCmp(a, mod, n) < 0);
no = wwOctetSize(mod, n);
t = (word*)stack;
r = (qr_o*)(t + n);
stack = (octet*)r + zmCreate_keep(no);
wwTo(t, no, mod);
zmCreate(r, (octet*)t, no, stack);
wwTo(t, no, a);
qrFrom(t, (octet*)t, r, stack);
qrPower(t, t, b, m, r, stack);
qrTo((octet*)t, t, r, stack);
wwFrom(c, t, no);
}
size_t zzPowerMod_deep(size_t n, size_t m)
{
const size_t no = O_OF_W(n);
const size_t r_deep = zmCreate_deep(no);
return no +
utilMax(2,
r_deep,
qrPower_deep(n, m, r_deep));
}
word zzPowerModW(register word a, register word b, register word mod,
void* stack)
{
register dword prod;
register word slide;
register size_t pos;
register size_t slide_size;
word* powers;
ASSERT(mod != 0);
if (b == 0)
return 1;
powers = (word*)stack;
prod = a;
prod *= a, prod %= mod, powers[0] = (word)prod;
prod *= a, prod %= mod, powers[1] = (word)prod;
prod *= powers[0], prod %= mod, powers[2] = (word)prod;
prod *= powers[0], prod %= mod, powers[3] = (word)prod;
powers[0] = a;
pos = B_PER_W - 1 - wordCLZ(b);
slide_size = MIN2(pos + 1, 3);
slide = b >> (pos + 1 - slide_size);
slide &= WORD_BIT_POS(slide_size) - 1;
for (; slide % 2 == 0; slide >>= 1, slide_size--);
a = powers[slide / 2];
pos -= slide_size;
while (pos != SIZE_MAX)
{
prod = a;
if ((b & WORD_BIT_POS(pos)) == 0)
{
prod *= a, a = prod % mod;
--pos;
}
else
{
slide_size = MIN2(pos + 1, 3);
slide = b >> (pos + 1 - slide_size);
slide &= WORD_BIT_POS(slide_size) - 1;
for (; slide % 2 == 0; slide >>= 1, slide_size--);
pos -= slide_size;
while (slide_size--)
prod *= a, prod %= mod, a = (word)prod;
prod *= powers[slide / 2];
prod %= mod;
a = (word)prod;
}
}
CLEAN3(prod, slide, b), CLEAN3(mod, pos, slide_size);
return a;
}
size_t zzPowerModW_deep()
{
return O_OF_W(4);
}