?? zz_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 (NTL_OVERFLOW(2*da+1, n2, 0))
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 (IsZero(a)) {
clear(x);
return;
}
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 (IsZero(a)) {
clear(x);
return;
}
if (n < 0) {
if (n < -NTL_MAX_LONG)
clear(x);
else
RightShift(x, a, -n);
return;
}
if (NTL_OVERFLOW(n, 1, 0))
Error("overflow in LeftShift");
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]);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -