?? lzz_pex.cpp
字號:
zz_pE t1, t2;
long k, i;
vec_zz_pE res;
res.SetLength(m);
for (k = 0; k < m; k++) {
const zz_pE& aa = a[k];
set(t1);
for (i = k-1; i >= 0; i--) {
mul(t1, t1, aa);
add(t1, t1, prod[i]);
}
clear(t2);
for (i = k-1; i >= 0; i--) {
mul(t2, t2, aa);
add(t2, t2, res[i]);
}
inv(t1, t1);
sub(t2, b[k], t2);
mul(t1, t1, t2);
for (i = 0; i < k; i++) {
mul(t2, prod[i], t1);
add(res[i], res[i], t2);
}
res[k] = t1;
if (k < m-1) {
if (k == 0)
negate(prod[0], prod[0]);
else {
negate(t1, a[k]);
add(prod[k], t1, prod[k-1]);
for (i = k-1; i >= 1; i--) {
mul(t2, prod[i], t1);
add(prod[i], t2, prod[i-1]);
}
mul(prod[0], prod[0], t1);
}
}
}
while (m > 0 && IsZero(res[m-1])) m--;
res.SetLength(m);
f.rep = res;
}
void InnerProduct(zz_pEX& x, const vec_zz_pE& v, long low, long high,
const vec_zz_pEX& H, long n, vec_zz_pX& t)
{
zz_pX 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_pX& w = rep(v[i]);
for (j = 0; j < m; j++) {
mul(s, w, rep(h[j]));
add(t[j], t[j], s);
}
}
x.rep.SetLength(n);
for (j = 0; j < n; j++)
conv(x.rep[j], t[j]);
x.normalize();
}
void CompMod(zz_pEX& x, const zz_pEX& g, const zz_pEXArgument& A,
const zz_pEXModulus& F)
{
if (deg(g) <= 0) {
x = g;
return;
}
zz_pEX s, t;
vec_zz_pX scratch;
SetSize(scratch, deg(F), 2*zz_pE::degree());
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 build(zz_pEXArgument& A, const zz_pEX& h, const zz_pEXModulus& F, long m)
{
long i;
if (m <= 0 || deg(h) >= F.n)
Error("build: bad args");
if (m > F.n) m = F.n;
if (zz_pEXArgBound > 0) {
double sz = zz_p::storage();
sz = sz*zz_pE::degree();
sz = sz + NTL_VECTOR_HEADER_SIZE + sizeof(vec_zz_p);
sz = sz*F.n;
sz = sz + NTL_VECTOR_HEADER_SIZE + sizeof(vec_zz_pE);
sz = sz/1024;
m = min(m, long(zz_pEXArgBound/sz));
m = max(m, 1);
}
A.H.SetLength(m+1);
set(A.H[0]);
A.H[1] = h;
for (i = 2; i <= m; i++)
MulMod(A.H[i], A.H[i-1], h, F);
}
long zz_pEXArgBound = 0;
void CompMod(zz_pEX& x, const zz_pEX& 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);
CompMod(x, g, A, F);
}
void Comp2Mod(zz_pEX& x1, zz_pEX& x2, const zz_pEX& g1, const zz_pEX& g2,
const zz_pEX& h, const zz_pEXModulus& F)
{
long m = SqrRoot(g1.rep.length() + g2.rep.length());
if (m == 0) {
clear(x1);
clear(x2);
return;
}
zz_pEXArgument A;
build(A, h, F, m);
zz_pEX xx1, xx2;
CompMod(xx1, g1, A, F);
CompMod(xx2, g2, A, F);
x1 = xx1;
x2 = xx2;
}
void Comp3Mod(zz_pEX& x1, zz_pEX& x2, zz_pEX& x3,
const zz_pEX& g1, const zz_pEX& g2, const zz_pEX& g3,
const zz_pEX& h, const zz_pEXModulus& F)
{
long m = SqrRoot(g1.rep.length() + g2.rep.length() + g3.rep.length());
if (m == 0) {
clear(x1);
clear(x2);
clear(x3);
return;
}
zz_pEXArgument A;
build(A, h, F, m);
zz_pEX xx1, xx2, xx3;
CompMod(xx1, g1, A, F);
CompMod(xx2, g2, A, F);
CompMod(xx3, g3, A, F);
x1 = xx1;
x2 = xx2;
x3 = xx3;
}
void build(zz_pEXTransMultiplier& B, const zz_pEX& b, const zz_pEXModulus& F)
{
long db = deg(b);
if (db >= F.n) Error("build TransMultiplier: bad args");
zz_pEX t;
LeftShift(t, b, F.n-1);
div(t, t, F);
// we optimize for low degree b
long d;
d = deg(t);
if (d < 0)
B.shamt_fbi = 0;
else
B.shamt_fbi = F.n-2 - d;
CopyReverse(B.fbi, t, d);
// The following code optimizes the case when
// f = X^n + low degree poly
trunc(t, F.f, F.n);
d = deg(t);
if (d < 0)
B.shamt = 0;
else
B.shamt = d;
CopyReverse(B.f0, t, d);
if (db < 0)
B.shamt_b = 0;
else
B.shamt_b = db;
CopyReverse(B.b, b, db);
}
void TransMulMod(zz_pEX& x, const zz_pEX& a, const zz_pEXTransMultiplier& B,
const zz_pEXModulus& F)
{
if (deg(a) >= F.n) Error("TransMulMod: bad args");
zz_pEX t1, t2;
mul(t1, a, B.b);
RightShift(t1, t1, B.shamt_b);
mul(t2, a, B.f0);
RightShift(t2, t2, B.shamt);
trunc(t2, t2, F.n-1);
mul(t2, t2, B.fbi);
if (B.shamt_fbi > 0) LeftShift(t2, t2, B.shamt_fbi);
trunc(t2, t2, F.n-1);
LeftShift(t2, t2, 1);
sub(x, t1, t2);
}
void ShiftSub(zz_pEX& U, const zz_pEX& V, long n)
// assumes input does not alias output
{
if (IsZero(V))
return;
long du = deg(U);
long dv = deg(V);
long d = max(du, n+dv);
U.rep.SetLength(d+1);
long i;
for (i = du+1; i <= d; i++)
clear(U.rep[i]);
for (i = 0; i <= dv; i++)
sub(U.rep[i+n], U.rep[i+n], V.rep[i]);
U.normalize();
}
void UpdateMap(vec_zz_pE& x, const vec_zz_pE& a,
const zz_pEXTransMultiplier& B, const zz_pEXModulus& F)
{
zz_pEX xx;
TransMulMod(xx, to_zz_pEX(a), B, F);
x = xx.rep;
}
static
void ProjectPowers(vec_zz_pE& x, const zz_pEX& a, long k,
const zz_pEXArgument& H, const zz_pEXModulus& F)
{
if (k < 0 || NTL_OVERFLOW(k, 1, 0) || deg(a) >= F.n)
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);
zz_pEX s;
s = a;
x.SetLength(k);
long i;
for (i = 0; i <= l; i++) {
long m1 = min(m, k-i*m);
for (long j = 0; j < m1; j++)
InnerProduct(x[i*m+j], H.H[j].rep, s.rep);
if (i < l)
TransMulMod(s, s, M, F);
}
}
static
void ProjectPowers(vec_zz_pE& x, const zz_pEX& a, long k, const zz_pEX& h,
const zz_pEXModulus& F)
{
if (k < 0 || deg(a) >= F.n || deg(h) >= F.n)
Error("ProjectPowers: bad args");
if (k == 0) {
x.SetLength(0);;
return;
}
long m = SqrRoot(k);
zz_pEXArgument H;
build(H, h, F, m);
ProjectPowers(x, a, k, H, F);
}
void ProjectPowers(vec_zz_pE& x, const vec_zz_pE& a, long k,
const zz_pEXArgument& H, const zz_pEXModulus& F)
{
ProjectPowers(x, to_zz_pEX(a), k, H, F);
}
void ProjectPowers(vec_zz_pE& x, const vec_zz_pE& a, long k,
const zz_pEX& h, const zz_pEXModulus& F)
{
ProjectPowers(x, to_zz_pEX(a), k, h, F);
}
void BerlekampMassey(zz_pEX& h, const vec_zz_pE& a, long m)
{
zz_pEX Lambda, Sigma, Temp;
long L;
zz_pE Delta, Delta1, t1;
long shamt;
// cerr << "*** " << m << "\n";
Lambda.SetMaxLength(m+1);
Sigma.SetMaxLength(m+1);
Temp.SetMaxLength(m+1);
L = 0;
set(Lambda);
clear(Sigma);
set(Delta);
shamt = 0;
long i, r, dl;
for (r = 1; r <= 2*m; r++) {
// cerr << r << "--";
clear(Delta1);
dl = deg(Lambda);
for (i = 0; i <= dl; i++) {
mul(t1, Lambda.rep[i], a[r-i-1]);
add(Delta1, Delta1, t1);
}
if (IsZero(Delta1)) {
shamt++;
// cerr << "case 1: " << deg(Lambda) << " " << deg(Sigma) << " " << shamt << "\n";
}
else if (2*L < r) {
div(t1, Delta1, Delta);
mul(Temp, Sigma, t1);
Sigma = Lambda;
ShiftSub(Lambda, Temp, shamt+1);
shamt = 0;
L = r-L;
Delta = Delta1;
// cerr << "case 2: " << deg(Lambda) << " " << deg(Sigma) << " " << shamt << "\n";
}
else {
shamt++;
div(t1, Delta1, Delta);
mul(Temp, Sigma, t1);
ShiftSub(Lambda, Temp, shamt);
// cerr << "case 3: " << deg(Lambda) << " " << deg(Sigma) << " " << shamt << "\n";
}
}
// cerr << "finished: " << L << " " << deg(Lambda) << "\n";
dl = deg(Lambda);
h.rep.SetLength(L + 1);
for (i = 0; i < L - dl; i++)
clear(h.rep[i]);
for (i = L - dl; i <= L; i++)
h.rep[i] = Lambda.rep[L - i];
}
void MinPolySeq(zz_pEX& h, const vec_zz_pE& a, long m)
{
if (m < 0 || NTL_OVERFLOW(m, 1, 0)) Error("MinPoly: bad args");
if (a.length() < 2*m) Error("MinPoly: sequence too short");
BerlekampMassey(h, a, m);
}
void DoMinPolyMod(zz_pEX& h, const zz_pEX& g, const zz_pEXModulus& F, long m,
const zz_pEX& R)
{
vec_zz_pE x;
ProjectPowers(x, R, 2*m, g, F);
MinPolySeq(h, x, m);
}
void ProbMinPolyMod(zz_pEX& h, const zz_pEX& g, const zz_pEXModulus& F, long m)
{
long n = F.n;
if (m < 1 || m > n) Error("ProbMinPoly: bad args");
zz_pEX R;
random(R, n);
DoMinPolyMod(h, g, F, m, R);
}
void ProbMinPolyMod(zz_pEX& h, const zz_pEX& g, const zz_pEXModulus& F)
{
ProbMinPolyMod(h, g, F, F.n);
}
void MinPolyMod(zz_pEX& hh, const zz_pEX& g, const zz_pEXModulus& F, long m)
{
zz_pEX h, h1;
long n = F.n;
if (m < 1 || m > n) Error("MinPoly: bad args");
/* probabilistically compute min-poly */
ProbMinPolyMod(h, g, F, m);
if (deg(h) == m) { hh = h; return; }
CompMod(h1, h, g, F);
if (IsZero(h1)) { hh = h; return; }
/* not completely successful...must iterate */
zz_pEX h2, h3;
zz_pEX R;
zz_pEXTransMultiplier H1;
for (;;) {
random(R, n);
build(H1, h1, F);
TransMulMod(R, R, H1, F);
DoMinPolyMod(h2, g, F, m-deg(h), R);
mul(h, h, h2);
if (deg(h) == m) { hh = h; return; }
CompMod(h3, h2, g, F);
MulMod(h1, h3, h1, F);
if (IsZero(h1)) { hh = h; return; }
}
}
void IrredPolyMod(zz_pEX& h, const zz_pEX& g, const zz_pEXModulus& F, long m)
{
if (m < 1 || m > F.n) Error("IrredPoly: bad args");
zz_pEX R;
set(R);
DoMinPolyMod(h, g, F, m, R);
}
void IrredPolyMod(zz_pEX& h, const zz_pEX& g, const zz_pEXModulus& F)
{
IrredPolyMod(h, g, F, F.n);
}
void MinPolyMod(zz_pEX& hh, const zz_pEX& g, const zz_pEXModulus& F)
{
MinPolyMod(hh, g, F, F.n);
}
void diff(zz_pEX& x, const zz_pEX& a)
{
long n = deg(a);
long i;
if (n <= 0) {
clear(x);
return;
}
if (&x != &a)
x.rep.SetLength(n);
for (i = 0; i <= n-1; i++) {
mul(x.rep[i], a.rep[i+1], i+1);
}
if (&x == &a)
x.rep.SetLength(n);
x.normalize();
}
void MakeMonic(zz_pEX& x)
{
if (IsZero(x))
return;
if (IsOne(LeadCoeff(x)))
return;
zz_pE t;
inv(t, LeadCoeff(x));
mul(x, x, t);
}
long divide(zz_pEX& q, const zz_pEX& a, const zz_pEX& b)
{
if (IsZero(b)) {
if (IsZero(a)) {
clear(q);
return 1;
}
else
return 0;
}
zz_pEX lq, r;
DivRem(lq, r, a, b);
if (!IsZero(r)) return 0;
q = lq;
return 1;
}
long divide(const zz_pEX& a, const zz_pEX& b)
{
if (IsZero(b)) return IsZero(a);
zz_pEX lq, r;
DivRem(lq, r, a, b);
if (!IsZero(r)) return 0;
return 1;
}
static
long OptWinSize(long n)
// finds k that minimizes n/(k+1) + 2^{k-1}
{
long k;
double v, v_new;
v = n/2.0 + 1.0;
k = 1;
for (;;) {
v_new = n/(double(k+2)) + double(1L << k);
if (v_new >= v) break;
v = v_new;
k++;
}
return k;
}
void PowerMod(zz_pEX& h, const zz_pEX& g, const ZZ& e, const zz_pEXModulus& F)
// h = g^e mod f using "sliding window" algorithm
{
if (deg(g) >= F.n) Error("PowerMod: bad args");
if (e == 0) {
set(h);
return;
}
if (e == 1) {
h = g;
return;
}
if (e == -1) {
InvMod(h, g, F);
return;
}
if (e == 2) {
SqrMod(h, g, F);
return;
}
if (e == -2) {
SqrMod(h, g, F);
InvMod(h, h, F);
return;
}
long n = NumBits(e);
zz_pEX res;
res.SetMaxLength(F.n);
set(res);
long i;
if (n < 16) {
// plain square-and-multiply algorithm
for (i = n - 1; i >= 0; i--) {
SqrMod(res, res, F);
if (bit(e, i))
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -