?? lzz_pex.cpp
字號:
MulMod(res, res, g, F);
}
if (e < 0) InvMod(res, res, F);
h = res;
return;
}
long k = OptWinSize(n);
k = min(k, 3);
vec_zz_pEX v;
v.SetLength(1L << (k-1));
v[0] = g;
if (k > 1) {
zz_pEX t;
SqrMod(t, g, F);
for (i = 1; i < (1L << (k-1)); i++)
MulMod(v[i], v[i-1], t, F);
}
long val;
long cnt;
long m;
val = 0;
for (i = n-1; i >= 0; i--) {
val = (val << 1) | bit(e, i);
if (val == 0)
SqrMod(res, res, F);
else if (val >= (1L << (k-1)) || i == 0) {
cnt = 0;
while ((val & 1) == 0) {
val = val >> 1;
cnt++;
}
m = val;
while (m > 0) {
SqrMod(res, res, F);
m = m >> 1;
}
MulMod(res, res, v[val >> 1], F);
while (cnt > 0) {
SqrMod(res, res, F);
cnt--;
}
val = 0;
}
}
if (e < 0) InvMod(res, res, F);
h = res;
}
void InvMod(zz_pEX& x, const zz_pEX& a, const zz_pEX& f)
{
if (deg(a) >= deg(f) || deg(f) == 0) Error("InvMod: bad args");
zz_pEX d, t;
XGCD(d, x, t, a, f);
if (!IsOne(d))
Error("zz_pEX InvMod: can't compute multiplicative inverse");
}
long InvModStatus(zz_pEX& x, const zz_pEX& a, const zz_pEX& f)
{
if (deg(a) >= deg(f) || deg(f) == 0) Error("InvModStatus: bad args");
zz_pEX d, t;
XGCD(d, x, t, a, f);
if (!IsOne(d)) {
x = d;
return 1;
}
else
return 0;
}
void MulMod(zz_pEX& x, const zz_pEX& a, const zz_pEX& b, const zz_pEX& f)
{
if (deg(a) >= deg(f) || deg(b) >= deg(f) || deg(f) == 0)
Error("MulMod: bad args");
zz_pEX t;
mul(t, a, b);
rem(x, t, f);
}
void SqrMod(zz_pEX& x, const zz_pEX& a, const zz_pEX& f)
{
if (deg(a) >= deg(f) || deg(f) == 0) Error("SqrMod: bad args");
zz_pEX t;
sqr(t, a);
rem(x, t, f);
}
void PowerXMod(zz_pEX& hh, const ZZ& e, const zz_pEXModulus& F)
{
if (F.n < 0) Error("PowerXMod: uninitialized modulus");
if (IsZero(e)) {
set(hh);
return;
}
long n = NumBits(e);
long i;
zz_pEX h;
h.SetMaxLength(F.n);
set(h);
for (i = n - 1; i >= 0; i--) {
SqrMod(h, h, F);
if (bit(e, i))
MulByXMod(h, h, F.f);
}
if (e < 0) InvMod(h, h, F);
hh = h;
}
void reverse(zz_pEX& x, const zz_pEX& a, long hi)
{
if (hi < 0) { clear(x); return; }
if (NTL_OVERFLOW(hi, 1, 0))
Error("overflow in reverse");
if (&x == &a) {
zz_pEX tmp;
CopyReverse(tmp, a, hi);
x = tmp;
}
else
CopyReverse(x, a, hi);
}
void power(zz_pEX& x, const zz_pEX& a, long e)
{
if (e < 0) {
Error("power: negative exponent");
}
if (e == 0) {
x = 1;
return;
}
if (a == 0 || a == 1) {
x = a;
return;
}
long da = deg(a);
if (da == 0) {
x = power(ConstTerm(a), e);
return;
}
if (da > (NTL_MAX_LONG-1)/e)
Error("overflow in power");
zz_pEX res;
res.SetMaxLength(da*e + 1);
res = 1;
long k = NumBits(e);
long i;
for (i = k - 1; i >= 0; i--) {
sqr(res, res);
if (bit(e, i))
mul(res, res, a);
}
x = res;
}
static
void FastTraceVec(vec_zz_pE& S, const zz_pEXModulus& f)
{
long n = deg(f);
zz_pEX x = reverse(-LeftShift(reverse(diff(reverse(f)), n-1), n-1)/f, n-1);
S.SetLength(n);
S[0] = n;
long i;
for (i = 1; i < n; i++)
S[i] = coeff(x, i);
}
void PlainTraceVec(vec_zz_pE& S, const zz_pEX& ff)
{
if (deg(ff) <= 0)
Error("TraceVec: bad args");
zz_pEX f;
f = ff;
MakeMonic(f);
long n = deg(f);
S.SetLength(n);
if (n == 0)
return;
long k, i;
zz_pX acc, t;
zz_pE t1;
S[0] = n;
for (k = 1; k < n; k++) {
mul(acc, rep(f.rep[n-k]), k);
for (i = 1; i < k; i++) {
mul(t, rep(f.rep[n-i]), rep(S[k-i]));
add(acc, acc, t);
}
conv(t1, acc);
negate(S[k], t1);
}
}
void TraceVec(vec_zz_pE& S, const zz_pEX& f)
{
if (deg(f) < zz_pE::DivCross())
PlainTraceVec(S, f);
else
FastTraceVec(S, f);
}
static
void ComputeTraceVec(const zz_pEXModulus& F)
{
vec_zz_pE& S = *((vec_zz_pE *) &F.tracevec);
if (S.length() > 0)
return;
if (F.method == zz_pEX_MOD_PLAIN) {
PlainTraceVec(S, F.f);
}
else {
FastTraceVec(S, F);
}
}
void TraceMod(zz_pE& x, const zz_pEX& a, const zz_pEXModulus& F)
{
long n = F.n;
if (deg(a) >= n)
Error("trace: bad args");
if (F.tracevec.length() == 0)
ComputeTraceVec(F);
InnerProduct(x, a.rep, F.tracevec);
}
void TraceMod(zz_pE& x, const zz_pEX& a, const zz_pEX& f)
{
if (deg(a) >= deg(f) || deg(f) <= 0)
Error("trace: bad args");
project(x, TraceVec(f), a);
}
void PlainResultant(zz_pE& rres, const zz_pEX& a, const zz_pEX& b)
{
zz_pE res;
if (IsZero(a) || IsZero(b))
clear(res);
else if (deg(a) == 0 && deg(b) == 0)
set(res);
else {
long d0, d1, d2;
zz_pE lc;
set(res);
long n = max(deg(a),deg(b)) + 1;
zz_pEX u(INIT_SIZE, n), v(INIT_SIZE, n);
vec_zz_pX tmp;
SetSize(tmp, n, 2*zz_pE::degree());
u = a;
v = b;
for (;;) {
d0 = deg(u);
d1 = deg(v);
lc = LeadCoeff(v);
PlainRem(u, u, v, tmp);
swap(u, v);
d2 = deg(v);
if (d2 >= 0) {
power(lc, lc, d0-d2);
mul(res, res, lc);
if (d0 & d1 & 1) negate(res, res);
}
else {
if (d1 == 0) {
power(lc, lc, d0);
mul(res, res, lc);
}
else
clear(res);
break;
}
}
rres = res;
}
}
void resultant(zz_pE& rres, const zz_pEX& a, const zz_pEX& b)
{
PlainResultant(rres, a, b);
}
void NormMod(zz_pE& x, const zz_pEX& a, const zz_pEX& f)
{
if (deg(f) <= 0 || deg(a) >= deg(f))
Error("norm: bad args");
if (IsZero(a)) {
clear(x);
return;
}
zz_pE t;
resultant(t, f, a);
if (!IsOne(LeadCoeff(f))) {
zz_pE t1;
power(t1, LeadCoeff(f), deg(a));
inv(t1, t1);
mul(t, t, t1);
}
x = t;
}
// tower stuff...
void InnerProduct(zz_pEX& x, const vec_zz_p& v, long low, long high,
const vec_zz_pEX& H, long n, vec_zz_pE& t)
{
zz_pE s;
long i, j;
for (j = 0; j < n; j++)
clear(t[j]);
high = min(high, v.length()-1);
for (i = low; i <= high; i++) {
const vec_zz_pE& h = H[i-low].rep;
long m = h.length();
const zz_p& w = v[i];
for (j = 0; j < m; j++) {
mul(s, h[j], w);
add(t[j], t[j], s);
}
}
x.rep.SetLength(n);
for (j = 0; j < n; j++)
x.rep[j] = t[j];
x.normalize();
}
void CompTower(zz_pEX& x, const zz_pX& g, const zz_pEXArgument& A,
const zz_pEXModulus& F)
{
if (deg(g) <= 0) {
conv(x, g);
return;
}
zz_pEX s, t;
vec_zz_pE scratch;
scratch.SetLength(deg(F));
long m = A.H.length() - 1;
long l = ((g.rep.length()+m-1)/m) - 1;
const zz_pEX& M = A.H[m];
InnerProduct(t, g.rep, l*m, l*m + m - 1, A.H, F.n, scratch);
for (long i = l-1; i >= 0; i--) {
InnerProduct(s, g.rep, i*m, i*m + m - 1, A.H, F.n, scratch);
MulMod(t, t, M, F);
add(t, t, s);
}
x = t;
}
void CompTower(zz_pEX& x, const zz_pX& g, const zz_pEX& h,
const zz_pEXModulus& F)
// x = g(h) mod f
{
long m = SqrRoot(g.rep.length());
if (m == 0) {
clear(x);
return;
}
zz_pEXArgument A;
build(A, h, F, m);
CompTower(x, g, A, F);
}
void PrepareProjection(vec_vec_zz_p& tt, const vec_zz_pE& s,
const vec_zz_p& proj)
{
long l = s.length();
tt.SetLength(l);
zz_pXMultiplier M;
long i;
for (i = 0; i < l; i++) {
build(M, rep(s[i]), zz_pE::modulus());
UpdateMap(tt[i], proj, M, zz_pE::modulus());
}
}
void ProjectedInnerProduct(zz_p& x, const vec_zz_pE& a,
const vec_vec_zz_p& b)
{
long n = min(a.length(), b.length());
zz_p t, res;
res = 0;
long i;
for (i = 0; i < n; i++) {
project(t, b[i], rep(a[i]));
res += t;
}
x = res;
}
void PrecomputeProj(vec_zz_p& proj, const zz_pX& f)
{
long n = deg(f);
if (n <= 0) Error("PrecomputeProj: bad args");
if (ConstTerm(f) != 0) {
proj.SetLength(1);
proj[0] = 1;
}
else {
proj.SetLength(n);
clear(proj);
proj[n-1] = 1;
}
}
void ProjectPowersTower(vec_zz_p& x, const vec_zz_pE& a, long k,
const zz_pEXArgument& H, const zz_pEXModulus& F,
const vec_zz_p& proj)
{
long n = F.n;
if (a.length() > n || k < 0 || NTL_OVERFLOW(k, 1, 0))
Error("ProjectPowers: bad args");
long m = H.H.length()-1;
long l = (k+m-1)/m - 1;
zz_pEXTransMultiplier M;
build(M, H.H[m], F);
vec_zz_pE s(INIT_SIZE, n);
s = a;
x.SetLength(k);
vec_vec_zz_p tt;
for (long i = 0; i <= l; i++) {
long m1 = min(m, k-i*m);
zz_p* w = &x[i*m];
PrepareProjection(tt, s, proj);
for (long j = 0; j < m1; j++)
ProjectedInnerProduct(w[j], H.H[j].rep, tt);
if (i < l)
UpdateMap(s, s, M, F);
}
}
void ProjectPowersTower(vec_zz_p& x, const vec_zz_pE& a, long k,
const zz_pEX& h, const zz_pEXModulus& F,
const vec_zz_p& proj)
{
if (a.length() > F.n || k < 0) Error("ProjectPowers: bad args");
if (k == 0) {
x.SetLength(0);
return;
}
long m = SqrRoot(k);
zz_pEXArgument H;
build(H, h, F, m);
ProjectPowersTower(x, a, k, H, F, proj);
}
void DoMinPolyTower(zz_pX& h, const zz_pEX& g, const zz_pEXModulus& F, long m,
const vec_zz_pE& R, const vec_zz_p& proj)
{
vec_zz_p x;
ProjectPowersTower(x, R, 2*m, g, F, proj);
MinPolySeq(h, x, m);
}
void ProbMinPolyTower(zz_pX& h, const zz_pEX& g, const zz_pEXModulus& F,
long m)
{
long n = F.n;
if (m < 1 || m > n*zz_pE::degree()) Error("ProbMinPoly: bad args");
vec_zz_pE R;
R.SetLength(n);
long i;
for (i = 0; i < n; i++)
random(R[i]);
vec_zz_p proj;
PrecomputeProj(proj, zz_pE::modulus());
DoMinPolyTower(h, g, F, m, R, proj);
}
void ProbMinPolyTower(zz_pX& h, const zz_pEX& g, const zz_pEXModulus& F,
long m, const vec_zz_p& proj)
{
long n = F.n;
if (m < 1 || m > n*zz_pE::degree()) Error("ProbMinPoly: bad args");
vec_zz_pE R;
R.SetLength(n);
long i;
for (i = 0; i < n; i++)
random(R[i]);
DoMinPolyTower(h, g, F, m, R, proj);
}
void MinPolyTower(zz_pX& hh, const zz_pEX& g, const zz_pEXModulus& F, long m)
{
zz_pX h;
zz_pEX h1;
long n = F.n;
if (m < 1 || m > n*zz_pE::degree()) {
Error("MinPoly: bad args");
}
vec_zz_p proj;
PrecomputeProj(proj, zz_pE::modulus());
/* probabilistically compute min-poly */
ProbMinPolyTower(h, g, F, m, proj);
if (deg(h) == m) { hh = h; return; }
CompTower(h1, h, g, F);
if (IsZero(h1)) { hh = h; return; }
/* not completely successful...must iterate */
long i;
zz_pX h2;
zz_pEX h3;
vec_zz_pE R;
zz_pEXTransMultiplier H1;
for (;;) {
R.SetLength(n);
for (i = 0; i < n; i++) random(R[i]);
build(H1, h1, F);
UpdateMap(R, R, H1, F);
DoMinPolyTower(h2, g, F, m-deg(h), R, proj);
mul(h, h, h2);
if (deg(h) == m) { hh = h; return; }
CompTower(h3, h2, g, F);
MulMod(h1, h3, h1, F);
if (IsZero(h1)) { hh = h; return; }
}
}
void IrredPolyTower(zz_pX& h, const zz_pEX& g, const zz_pEXModulus& F, long m)
{
if (m < 1 || m > deg(F)*zz_pE::degree()) Error("IrredPoly: bad args");
vec_zz_pE R;
R.SetLength(1);
R[0] = 1;
vec_zz_p proj;
proj.SetLength(1);
proj[0] = 1;
DoMinPolyTower(h, g, F, m, R, proj);
}
NTL_END_IMPL
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -