?? lzz_px1.cpp
字號:
}
}
void mul(zz_p* x, const zz_p* a, const zz_p* b, long n)
{
zz_p t, accum;
long i, j, jmin, jmax;
long d = 2*n-1;
for (i = 0; i <= d; i++) {
jmin = max(0, i-(n-1));
jmax = min(n-1, i);
clear(accum);
for (j = jmin; j <= jmax; j++) {
mul(t, (a[j]), (b[i-j]));
add(accum, accum, t);
}
if (i >= n) {
add(accum, accum, (a[i-n]));
add(accum, accum, (b[i-n]));
}
x[i] = accum;
}
}
void BuildFromRoots(zz_pX& x, const vec_zz_p& a)
{
long n = a.length();
if (n == 0) {
set(x);
return;
}
long k0 = NextPowerOfTwo(NTL_zz_pX_MUL_CROSSOVER)-1;
long crossover = 1L << k0;
if (n <= NTL_zz_pX_MUL_CROSSOVER) {
x.rep.SetMaxLength(n+1);
x.rep = a;
IterBuild(&x.rep[0], n);
x.rep.SetLength(n+1);
SetCoeff(x, n);
return;
}
long k = NextPowerOfTwo(n);
long m = 1L << k;
long i, j;
long l, width;
zz_pX b(INIT_SIZE, m+1);
b.rep = a;
b.rep.SetLength(m+1);
for (i = n; i < m; i++)
clear(b.rep[i]);
set(b.rep[m]);
fftRep R1(INIT_SIZE, k), R2(INIT_SIZE, k);
zz_p t1, one;
set(one);
vec_zz_p G(INIT_SIZE, crossover), H(INIT_SIZE, crossover);
zz_p *g = G.elts();
zz_p *h = H.elts();
zz_p *tmp;
for (i = 0; i < m; i+= crossover) {
for (j = 0; j < crossover; j++)
negate(g[j], b.rep[i+j]);
if (k0 > 0) {
for (j = 0; j < crossover; j+=2) {
mul(t1, g[j], g[j+1]);
add(g[j+1], g[j], g[j+1]);
g[j] = t1;
}
}
for (l = 1; l < k0; l++) {
width = 1L << l;
for (j = 0; j < crossover; j += 2*width)
mul(&h[j], &g[j], &g[j+width], width);
tmp = g; g = h; h = tmp;
}
for (j = 0; j < crossover; j++)
b.rep[i+j] = g[j];
}
for (l = k0; l < k; l++) {
width = 1L << l;
for (i = 0; i < m; i += 2*width) {
t1 = b.rep[i+width];
set(b.rep[i+width]);
TofftRep(R1, b, l+1, i, i+width);
b.rep[i+width] = t1;
t1 = b.rep[i+2*width];
set(b.rep[i+2*width]);
TofftRep(R2, b, l+1, i+width, i+2*width);
b.rep[i+2*width] = t1;
mul(R1, R1, R2);
FromfftRep(&b.rep[i], R1, 0, 2*width-1);
sub(b.rep[i], b.rep[i], one);
}
}
x.rep.SetLength(n+1);
long delta = m-n;
for (i = 0; i <= n; i++)
x.rep[i] = b.rep[i+delta];
// no need to normalize
}
void eval(zz_p& b, const zz_pX& f, zz_p a)
// does a Horner evaluation
{
zz_p acc;
long i;
clear(acc);
for (i = deg(f); i >= 0; i--) {
mul(acc, acc, a);
add(acc, acc, f.rep[i]);
}
b = acc;
}
void eval(vec_zz_p& b, const zz_pX& f, const vec_zz_p& a)
// naive algorithm: repeats Horner
{
if (&b == &f.rep) {
vec_zz_p bb;
eval(bb, f, a);
b = bb;
return;
}
long m = a.length();
b.SetLength(m);
long i;
for (i = 0; i < m; i++)
eval(b[i], f, a[i]);
}
void interpolate(zz_pX& f, const vec_zz_p& a, const vec_zz_p& b)
{
long m = a.length();
if (b.length() != m) Error("interpolate: vector length mismatch");
if (m == 0) {
clear(f);
return;
}
vec_zz_p prod;
prod = a;
zz_p t1, t2;
long k, i;
vec_zz_p res;
res.SetLength(m);
for (k = 0; k < m; k++) {
const zz_p& 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;
}
NTL_vector_impl(zz_pX,vec_zz_pX)
NTL_eq_vector_impl(zz_pX,vec_zz_pX)
NTL_io_vector_impl(zz_pX,vec_zz_pX)
void InnerProduct(zz_pX& x, const vec_zz_p& v, long low, long high,
const vec_zz_pX& H, long n, vec_zz_p& t)
{
zz_p s;
long i, j;
zz_p *tp = t.elts();
for (j = 0; j < n; j++)
clear(tp[j]);
long p = zz_p::modulus();
double pinv = zz_p::ModulusInverse();
high = min(high, v.length()-1);
for (i = low; i <= high; i++) {
const vec_zz_p& h = H[i-low].rep;
long m = h.length();
zz_p w = (v[i]);
long W = rep(w);
mulmod_precon_t Wpinv = PrepMulModPrecon(W, p, pinv); // ((double) W)*pinv;
const zz_p *hp = h.elts();
for (j = 0; j < m; j++) {
long S = MulModPrecon(rep(hp[j]), W, p, Wpinv);
S = AddMod(S, rep(tp[j]), p);
tp[j].LoopHole() = S;
}
}
x.rep = t;
x.normalize();
}
void CompMod(zz_pX& x, const zz_pX& g, const zz_pXArgument& A,
const zz_pXModulus& F)
{
if (deg(g) <= 0) {
x = g;
return;
}
zz_pX s, t;
vec_zz_p scratch(INIT_SIZE, F.n);
long m = A.H.length() - 1;
long l = ((g.rep.length()+m-1)/m) - 1;
zz_pXMultiplier M;
build(M, A.H[m], F);
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_pXArgument& A, const zz_pX& h, const zz_pXModulus& F, long m)
{
if (m <= 0 || deg(h) >= F.n) Error("build: bad args");
if (m > F.n) m = F.n;
long i;
if (zz_pXArgBound > 0) {
double sz = 1;
sz = sz*F.n;
sz = sz+6;
sz = sz*(sizeof (long));
sz = sz/1024;
m = min(m, long(zz_pXArgBound/sz));
m = max(m, 1);
}
zz_pXMultiplier M;
build(M, h, F);
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], M, F);
}
long zz_pXArgBound = 0;
void CompMod(zz_pX& x, const zz_pX& g, const zz_pX& h, const zz_pXModulus& F)
// x = g(h) mod f
{
long m = SqrRoot(g.rep.length());
if (m == 0) {
clear(x);
return;
}
zz_pXArgument A;
build(A, h, F, m);
CompMod(x, g, A, F);
}
void Comp2Mod(zz_pX& x1, zz_pX& x2, const zz_pX& g1, const zz_pX& g2,
const zz_pX& h, const zz_pXModulus& F)
{
long m = SqrRoot(g1.rep.length() + g2.rep.length());
if (m == 0) {
clear(x1);
clear(x2);
return;
}
zz_pXArgument A;
build(A, h, F, m);
zz_pX xx1, xx2;
CompMod(xx1, g1, A, F);
CompMod(xx2, g2, A, F);
x1 = xx1;
x2 = xx2;
}
void Comp3Mod(zz_pX& x1, zz_pX& x2, zz_pX& x3,
const zz_pX& g1, const zz_pX& g2, const zz_pX& g3,
const zz_pX& h, const zz_pXModulus& F)
{
long m = SqrRoot(g1.rep.length() + g2.rep.length() + g3.rep.length());
if (m == 0) {
clear(x1);
clear(x2);
clear(x3);
return;
}
zz_pXArgument A;
build(A, h, F, m);
zz_pX xx1, xx2, xx3;
CompMod(xx1, g1, A, F);
CompMod(xx2, g2, A, F);
CompMod(xx3, g3, A, F);
x1 = xx1;
x2 = xx2;
x3 = xx3;
}
static void StripZeroes(vec_zz_p& x)
{
long n = x.length();
while (n > 0 && IsZero(x[n-1]))
n--;
x.SetLength(n);
}
void PlainUpdateMap(vec_zz_p& xx, const vec_zz_p& a,
const zz_pX& b, const zz_pX& f)
{
long n = deg(f);
long i, m;
if (IsZero(b)) {
xx.SetLength(0);
return;
}
m = n-1 - deg(b);
vec_zz_p x(INIT_SIZE, n);
for (i = 0; i <= m; i++)
InnerProduct(x[i], a, b.rep, i);
if (deg(b) != 0) {
zz_pX c(INIT_SIZE, n);
LeftShift(c, b, m);
for (i = m+1; i < n; i++) {
MulByXMod(c, c, f);
InnerProduct(x[i], a, c.rep);
}
}
xx = x;
}
void UpdateMap(vec_zz_p& x, const vec_zz_p& aa,
const zz_pXMultiplier& B, const zz_pXModulus& F)
{
long n = F.n;
vec_zz_p a;
a = aa;
StripZeroes(a);
if (a.length() > n) Error("UpdateMap: bad args");
long i;
if (!B.UseFFT) {
PlainUpdateMap(x, a, B.b, F.f);
StripZeroes(x);
return;
}
fftRep R1(INIT_SIZE, F.k), R2(INIT_SIZE, F.l);
vec_zz_p V1(INIT_SIZE, n);
RevTofftRep(R1, a, F.k, 0, a.length()-1, 0);
mul(R2, R1, F.FRep);
RevFromfftRep(V1, R2, 0, n-2);
for (i = 0; i <= n-2; i++) negate(V1[i], V1[i]);
RevTofftRep(R2, V1, F.l, 0, n-2, n-1);
mul(R2, R2, B.B1);
mul(R1, R1, B.B2);
AddExpand(R2, R1);
RevFromfftRep(x, R2, 0, n-1);
StripZeroes(x);
}
void ProjectPowers(vec_zz_p& x, const vec_zz_p& a, long k,
const zz_pXArgument& H, const zz_pXModulus& F)
{
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_pXMultiplier M;
build(M, H.H[m], F);
vec_zz_p s(INIT_SIZE, n);
s = a;
StripZeroes(s);
x.SetLength(k);
for (long i = 0; i <= l; i++) {
long m1 = min(m, k-i*m);
zz_p* w = &x[i*m];
for (long j = 0; j < m1; j++)
InnerProduct(w[j], H.H[j].rep, s);
if (i < l)
UpdateMap(s, s, M, F);
}
}
void ProjectPowers(vec_zz_p& x, const vec_zz_p& a, long k,
const zz_pX& h, const zz_pXModulus& F)
{
if (a.length() > F.n || k < 0) Error("ProjectPowers: bad args");
if (k == 0) {
x.SetLength(0);
return;
}
long m = SqrRoot(k);
zz_pXArgument H;
build(H, h, F, m);
ProjectPowers(x, a, k, H, F);
}
void BerlekampMassey(zz_pX& h, const vec_zz_p& a, long m)
{
zz_pX Lambda, Sigma, Temp;
long L;
zz_p 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 GCDMinPolySeq(zz_pX& h, const vec_zz_p& x, long m)
{
long i;
zz_pX a, b;
zz_pXMatrix M;
zz_p t;
a.rep.SetLength(2*m);
for (i = 0; i < 2*m; i++) a.rep[i] = x[2*m-1-i];
a.normalize();
SetCoeff(b, 2*m);
HalfGCD(M, b, a, m+1);
/* make monic */
inv(t, LeadCoeff(M(1,1)));
mul(h, M(1,1), t);
}
void MinPolySeq(zz_pX& h, const vec_zz_p& 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");
if (m > NTL_zz_pX_BERMASS_CROSSOVER)
GCDMinPolySeq(h, a, m);
else
BerlekampMassey(h, a, m);
}
void DoMinPolyMod(zz_pX& h, const zz_pX& g, const zz_pXModulus& F, long m,
const vec_zz_p& R)
{
vec_zz_p x;
ProjectPowers(x, R, 2*m, g, F);
MinPolySeq(h, x, m);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -