📄 lzz_pex.cpp
字号:
for (i = 0; i <= da; i++)
mul(xp[i], ap[i], t);
x.normalize();
}
void mul(zz_pEX& x, const zz_pEX& a, long b)
{
NTL_zz_pRegister(t);
t = b;
mul(x, a, t);
}
void sqr(zz_pEX& c, const zz_pEX& a)
{
if (IsZero(a)) {
clear(c);
return;
}
if (deg(a) == 0) {
zz_pE res;
sqr(res, ConstTerm(a));
conv(c, res);
return;
}
// general case...Kronecker subst
zz_pX A, C;
long da = deg(a);
long n = zz_pE::degree();
long n2 = 2*n-1;
if (2*da+1 >= (1L << (NTL_BITS_PER_LONG-4))/n2)
Error("overflow in zz_pEX sqr");
long i, j;
A.rep.SetLength((da+1)*n2);
for (i = 0; i <= da; i++) {
const zz_pX& coeff = rep(a.rep[i]);
long dcoeff = deg(coeff);
for (j = 0; j <= dcoeff; j++)
A.rep[n2*i + j] = coeff.rep[j];
}
A.normalize();
sqr(C, A);
long Clen = C.rep.length();
long lc = (Clen + n2 - 1)/n2;
long dc = lc - 1;
c.rep.SetLength(dc+1);
zz_pX tmp;
for (i = 0; i <= dc; i++) {
tmp.rep.SetLength(n2);
for (j = 0; j < n2 && n2*i + j < Clen; j++)
tmp.rep[j] = C.rep[n2*i + j];
for (; j < n2; j++)
clear(tmp.rep[j]);
tmp.normalize();
conv(c.rep[i], tmp);
}
c.normalize();
}
void MulTrunc(zz_pEX& x, const zz_pEX& a, const zz_pEX& b, long n)
{
if (n < 0) Error("MulTrunc: bad args");
zz_pEX t;
mul(t, a, b);
trunc(x, t, n);
}
void SqrTrunc(zz_pEX& x, const zz_pEX& a, long n)
{
if (n < 0) Error("SqrTrunc: bad args");
zz_pEX t;
sqr(t, a);
trunc(x, t, n);
}
void CopyReverse(zz_pEX& x, const zz_pEX& a, long hi)
// x[0..hi] = reverse(a[0..hi]), with zero fill
// input may not alias output
{
long i, j, n, m;
n = hi+1;
m = a.rep.length();
x.rep.SetLength(n);
const zz_pE* ap = a.rep.elts();
zz_pE* xp = x.rep.elts();
for (i = 0; i < n; i++) {
j = hi-i;
if (j < 0 || j >= m)
clear(xp[i]);
else
xp[i] = ap[j];
}
x.normalize();
}
void trunc(zz_pEX& x, const zz_pEX& a, long m)
// x = a % X^m, output may alias input
{
if (m < 0) Error("trunc: bad args");
if (&x == &a) {
if (x.rep.length() > m) {
x.rep.SetLength(m);
x.normalize();
}
}
else {
long n;
long i;
zz_pE* xp;
const zz_pE* ap;
n = min(a.rep.length(), m);
x.rep.SetLength(n);
xp = x.rep.elts();
ap = a.rep.elts();
for (i = 0; i < n; i++) xp[i] = ap[i];
x.normalize();
}
}
void random(zz_pEX& x, long n)
{
long i;
x.rep.SetLength(n);
for (i = 0; i < n; i++)
random(x.rep[i]);
x.normalize();
}
void negate(zz_pEX& x, const zz_pEX& a)
{
long n = a.rep.length();
x.rep.SetLength(n);
const zz_pE* ap = a.rep.elts();
zz_pE* xp = x.rep.elts();
long i;
for (i = n; i; i--, ap++, xp++)
negate((*xp), (*ap));
}
static
void MulByXModAux(zz_pEX& h, const zz_pEX& a, const zz_pEX& f)
{
long i, n, m;
zz_pE* hh;
const zz_pE *aa, *ff;
zz_pE t, z;
n = deg(f);
m = deg(a);
if (m >= n || n == 0) Error("MulByXMod: bad args");
if (m < 0) {
clear(h);
return;
}
if (m < n-1) {
h.rep.SetLength(m+2);
hh = h.rep.elts();
aa = a.rep.elts();
for (i = m+1; i >= 1; i--)
hh[i] = aa[i-1];
clear(hh[0]);
}
else {
h.rep.SetLength(n);
hh = h.rep.elts();
aa = a.rep.elts();
ff = f.rep.elts();
negate(z, aa[n-1]);
if (!IsOne(ff[n]))
div(z, z, ff[n]);
for (i = n-1; i >= 1; i--) {
mul(t, z, ff[i]);
add(hh[i], aa[i-1], t);
}
mul(hh[0], z, ff[0]);
h.normalize();
}
}
void MulByXMod(zz_pEX& h, const zz_pEX& a, const zz_pEX& f)
{
if (&h == &f) {
zz_pEX hh;
MulByXModAux(hh, a, f);
h = hh;
}
else
MulByXModAux(h, a, f);
}
void PlainMul(zz_pEX& x, const zz_pEX& a, const zz_pEX& b)
{
long da = deg(a);
long db = deg(b);
if (da < 0 || db < 0) {
clear(x);
return;
}
long d = da+db;
const zz_pE *ap, *bp;
zz_pE *xp;
zz_pEX la, lb;
if (&x == &a) {
la = a;
ap = la.rep.elts();
}
else
ap = a.rep.elts();
if (&x == &b) {
lb = b;
bp = lb.rep.elts();
}
else
bp = b.rep.elts();
x.rep.SetLength(d+1);
xp = x.rep.elts();
long i, j, jmin, jmax;
static zz_pX t, accum;
for (i = 0; i <= d; i++) {
jmin = max(0, i-db);
jmax = min(da, i);
clear(accum);
for (j = jmin; j <= jmax; j++) {
mul(t, rep(ap[j]), rep(bp[i-j]));
add(accum, accum, t);
}
conv(xp[i], accum);
}
x.normalize();
}
void SetSize(vec_zz_pX& x, long n, long m)
{
x.SetLength(n);
long i;
for (i = 0; i < n; i++)
x[i].rep.SetMaxLength(m);
}
void PlainDivRem(zz_pEX& q, zz_pEX& r, const zz_pEX& a, const zz_pEX& b)
{
long da, db, dq, i, j, LCIsOne;
const zz_pE *bp;
zz_pE *qp;
zz_pX *xp;
zz_pE LCInv, t;
zz_pX s;
da = deg(a);
db = deg(b);
if (db < 0) Error("zz_pEX: division by zero");
if (da < db) {
r = a;
clear(q);
return;
}
zz_pEX lb;
if (&q == &b) {
lb = b;
bp = lb.rep.elts();
}
else
bp = b.rep.elts();
if (IsOne(bp[db]))
LCIsOne = 1;
else {
LCIsOne = 0;
inv(LCInv, bp[db]);
}
vec_zz_pX x;
SetSize(x, da+1, 2*zz_pE::degree());
for (i = 0; i <= da; i++)
x[i] = rep(a.rep[i]);
xp = x.elts();
dq = da - db;
q.rep.SetLength(dq+1);
qp = q.rep.elts();
for (i = dq; i >= 0; i--) {
conv(t, xp[i+db]);
if (!LCIsOne)
mul(t, t, LCInv);
qp[i] = t;
negate(t, t);
for (j = db-1; j >= 0; j--) {
mul(s, rep(t), rep(bp[j]));
add(xp[i+j], xp[i+j], s);
}
}
r.rep.SetLength(db);
for (i = 0; i < db; i++)
conv(r.rep[i], xp[i]);
r.normalize();
}
void PlainRem(zz_pEX& r, const zz_pEX& a, const zz_pEX& b, vec_zz_pX& x)
{
long da, db, dq, i, j, LCIsOne;
const zz_pE *bp;
zz_pX *xp;
zz_pE LCInv, t;
zz_pX s;
da = deg(a);
db = deg(b);
if (db < 0) Error("zz_pEX: division by zero");
if (da < db) {
r = a;
return;
}
bp = b.rep.elts();
if (IsOne(bp[db]))
LCIsOne = 1;
else {
LCIsOne = 0;
inv(LCInv, bp[db]);
}
for (i = 0; i <= da; i++)
x[i] = rep(a.rep[i]);
xp = x.elts();
dq = da - db;
for (i = dq; i >= 0; i--) {
conv(t, xp[i+db]);
if (!LCIsOne)
mul(t, t, LCInv);
negate(t, t);
for (j = db-1; j >= 0; j--) {
mul(s, rep(t), rep(bp[j]));
add(xp[i+j], xp[i+j], s);
}
}
r.rep.SetLength(db);
for (i = 0; i < db; i++)
conv(r.rep[i], xp[i]);
r.normalize();
}
void PlainDivRem(zz_pEX& q, zz_pEX& r, const zz_pEX& a, const zz_pEX& b,
vec_zz_pX& x)
{
long da, db, dq, i, j, LCIsOne;
const zz_pE *bp;
zz_pE *qp;
zz_pX *xp;
zz_pE LCInv, t;
zz_pX s;
da = deg(a);
db = deg(b);
if (db < 0) Error("zz_pEX: division by zero");
if (da < db) {
r = a;
clear(q);
return;
}
zz_pEX lb;
if (&q == &b) {
lb = b;
bp = lb.rep.elts();
}
else
bp = b.rep.elts();
if (IsOne(bp[db]))
LCIsOne = 1;
else {
LCIsOne = 0;
inv(LCInv, bp[db]);
}
for (i = 0; i <= da; i++)
x[i] = rep(a.rep[i]);
xp = x.elts();
dq = da - db;
q.rep.SetLength(dq+1);
qp = q.rep.elts();
for (i = dq; i >= 0; i--) {
conv(t, xp[i+db]);
if (!LCIsOne)
mul(t, t, LCInv);
qp[i] = t;
negate(t, t);
for (j = db-1; j >= 0; j--) {
mul(s, rep(t), rep(bp[j]));
add(xp[i+j], xp[i+j], s);
}
}
r.rep.SetLength(db);
for (i = 0; i < db; i++)
conv(r.rep[i], xp[i]);
r.normalize();
}
void PlainDiv(zz_pEX& q, const zz_pEX& a, const zz_pEX& b)
{
long da, db, dq, i, j, LCIsOne;
const zz_pE *bp;
zz_pE *qp;
zz_pX *xp;
zz_pE LCInv, t;
zz_pX s;
da = deg(a);
db = deg(b);
if (db < 0) Error("zz_pEX: division by zero");
if (da < db) {
clear(q);
return;
}
zz_pEX lb;
if (&q == &b) {
lb = b;
bp = lb.rep.elts();
}
else
bp = b.rep.elts();
if (IsOne(bp[db]))
LCIsOne = 1;
else {
LCIsOne = 0;
inv(LCInv, bp[db]);
}
vec_zz_pX x;
SetSize(x, da+1-db, 2*zz_pE::degree());
for (i = db; i <= da; i++)
x[i-db] = rep(a.rep[i]);
xp = x.elts();
dq = da - db;
q.rep.SetLength(dq+1);
qp = q.rep.elts();
for (i = dq; i >= 0; i--) {
conv(t, xp[i]);
if (!LCIsOne)
mul(t, t, LCInv);
qp[i] = t;
negate(t, t);
long lastj = max(0, db-i);
for (j = db-1; j >= lastj; j--) {
mul(s, rep(t), rep(bp[j]));
add(xp[i+j-db], xp[i+j-db], s);
}
}
}
void PlainRem(zz_pEX& r, const zz_pEX& a, const zz_pEX& b)
{
long da, db, dq, i, j, LCIsOne;
const zz_pE *bp;
zz_pX *xp;
zz_pE LCInv, t;
zz_pX s;
da = deg(a);
db = deg(b);
if (db < 0) Error("zz_pEX: division by zero");
if (da < db) {
r = a;
return;
}
bp = b.rep.elts();
if (IsOne(bp[db]))
LCIsOne = 1;
else {
LCIsOne = 0;
inv(LCInv, bp[db]);
}
vec_zz_pX x;
SetSize(x, da + 1, 2*zz_pE::degree());
for (i = 0; i <= da; i++)
x[i] = rep(a.rep[i]);
xp = x.elts();
dq = da - db;
for (i = dq; i >= 0; i--) {
conv(t, xp[i+db]);
if (!LCIsOne)
mul(t, t, LCInv);
negate(t, t);
for (j = db-1; j >= 0; j--) {
mul(s, rep(t), rep(bp[j]));
add(xp[i+j], xp[i+j], s);
}
}
r.rep.SetLength(db);
for (i = 0; i < db; i++)
conv(r.rep[i], xp[i]);
r.normalize();
}
void RightShift(zz_pEX& x, const zz_pEX& a, long n)
{
if (n < 0) {
if (n < -NTL_MAX_LONG) Error("overflow in RightShift");
LeftShift(x, a, -n);
return;
}
long da = deg(a);
long i;
if (da < n) {
clear(x);
return;
}
if (&x != &a)
x.rep.SetLength(da-n+1);
for (i = 0; i <= da-n; i++)
x.rep[i] = a.rep[i+n];
if (&x == &a)
x.rep.SetLength(da-n+1);
x.normalize();
}
void LeftShift(zz_pEX& x, const zz_pEX& a, long n)
{
if (n < 0) {
if (n < -NTL_MAX_LONG) Error("overflow in LeftShift");
RightShift(x, a, -n);
return;
}
if (n >= (1L << (NTL_BITS_PER_LONG-4)))
Error("overflow in LeftShift");
if (IsZero(a)) {
clear(x);
return;
}
long m = a.rep.length();
x.rep.SetLength(m+n);
long i;
for (i = m-1; i >= 0; i--)
x.rep[i+n] = a.rep[i];
for (i = 0; i < n; i++)
clear(x.rep[i]);
}
void NewtonInv(zz_pEX& c, const zz_pEX& a, long e)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -