📄 gf2x1.cpp
字号:
vp++;
vv = *vp;
}
}
x.xrep = t;
x.normalize();
}
void CompMod(GF2X& x, const GF2X& g, const GF2XArgument& A, const GF2XModulus& F)
{
long dg = deg(g);
if (dg <= 0) {
x = g;
return;
}
GF2X s, t;
WordVector scratch(INIT_SIZE, F.size);
long m = A.H.length() - 1;
long l = (((dg+1)+m-1)/m) - 1;
InnerProduct(t, g, dg, l*m, l*m + m - 1, A.H, F.size, scratch);
for (long i = l-1; i >= 0; i--) {
InnerProduct(s, g, dg, i*m, i*m + m - 1, A.H, F.size, scratch);
MulMod(t, t, A.H[m], F);
add(t, t, s);
}
x = t;
}
void build(GF2XArgument& A, const GF2X& h, const GF2XModulus& F, long m)
{
if (m <= 0 || deg(h) >= F.n) Error("build GF2XArgument: bad args");
if (m > F.n) m = F.n;
long i;
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);
}
void CompMod(GF2X& x, const GF2X& g, const GF2X& h, const GF2XModulus& F)
// x = g(h) mod f
{
long m = SqrRoot(deg(g)+1);
if (m == 0) {
clear(x);
return;
}
GF2XArgument A;
build(A, h, F, m);
CompMod(x, g, A, F);
}
void Comp2Mod(GF2X& x1, GF2X& x2, const GF2X& g1, const GF2X& g2,
const GF2X& h, const GF2XModulus& F)
{
long m = SqrRoot(deg(g1) + deg(g2) + 2);
if (m == 0) {
clear(x1);
clear(x2);
return;
}
GF2XArgument A;
build(A, h, F, m);
GF2X xx1, xx2;
CompMod(xx1, g1, A, F);
CompMod(xx2, g2, A, F);
x1 = xx1;
x2 = xx2;
}
void Comp3Mod(GF2X& x1, GF2X& x2, GF2X& x3,
const GF2X& g1, const GF2X& g2, const GF2X& g3,
const GF2X& h, const GF2XModulus& F)
{
long m = SqrRoot(deg(g1) + deg(g2) + deg(g3) + 3);
if (m == 0) {
clear(x1);
clear(x2);
clear(x3);
return;
}
GF2XArgument A;
build(A, h, F, m);
GF2X 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(GF2XTransMultiplier& B, const GF2X& b, const GF2XModulus& F)
{
long db = deg(b);
if (db >= F.n) Error("build TransMultiplier: bad args");
GF2X 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);
if (F.method != GF2X_MOD_TRI && F.method != GF2X_MOD_PENT) {
// 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(GF2X& x, const GF2X& a, const GF2XTransMultiplier& B,
const GF2XModulus& F)
{
if (deg(a) >= F.n) Error("TransMulMod: bad args");
GF2XRegister(t1);
GF2XRegister(t2);
GF2XRegister(t3);
mul(t1, a, B.b);
RightShift(t1, t1, B.shamt_b);
if (F.method == GF2X_MOD_TRI) {
RightShift(t2, a, F.k3);
add(t2, t2, a);
}
else if (F.method == GF2X_MOD_PENT) {
RightShift(t2, a, F.k3);
RightShift(t3, a, F.k2);
add(t2, t2, t3);
RightShift(t3, a, F.k1);
add(t2, t2, t3);
add(t2, t2, a);
}
else {
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);
MulByX(t2, t2);
add(x, t1, t2);
}
void UpdateMap(vec_GF2& x, const vec_GF2& a, const GF2XTransMultiplier& B,
const GF2XModulus& F)
{
GF2XRegister(xx);
GF2XRegister(aa);
conv(aa, a);
TransMulMod(xx, aa, B, F);
conv(x, xx);
}
void ProjectPowers(GF2X& x, const GF2X& a, long k, const GF2XArgument& H,
const GF2XModulus& F)
{
long n = F.n;
if (deg(a) >= 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;
GF2XTransMultiplier M;
build(M, H.H[m], F);
GF2X s;
s = a;
x.SetMaxLength(k);
clear(x);
long i;
for (i = 0; i <= l; i++) {
long m1 = min(m, k-i*m);
for (long j = 0; j < m1; j++)
SetCoeff(x, i*m+j, InnerProduct(H.H[j].xrep, s.xrep));
if (i < l)
TransMulMod(s, s, M, F);
}
}
void ProjectPowers(vec_GF2& x, const vec_GF2& a, long k,
const GF2XArgument& H, const GF2XModulus& F)
{
GF2X xx;
ProjectPowers(xx, to_GF2X(a), k, H, F);
VectorCopy(x, xx, k);
}
void ProjectPowers(GF2X& x, const GF2X& a, long k, const GF2X& h,
const GF2XModulus& F)
{
if (deg(a) >= F.n || k < 0) Error("ProjectPowers: bad args");
if (k == 0) {
clear(x);
return;
}
long m = SqrRoot(k);
GF2XArgument H;
build(H, h, F, m);
ProjectPowers(x, a, k, H, F);
}
void ProjectPowers(vec_GF2& x, const vec_GF2& a, long k, const GF2X& H,
const GF2XModulus& F)
{
GF2X xx;
ProjectPowers(xx, to_GF2X(a), k, H, F);
VectorCopy(x, xx, k);
}
void MinPolyInternal(GF2X& h, const GF2X& x, long m)
{
GF2X a, b, r, s;
GF2X a_in, b_in;
if (IsZero(x)) {
set(h);
return;
}
clear(a_in);
SetCoeff(a_in, 2*m);
CopyReverse(b_in, x, 2*m-1);
a.xrep.SetMaxLength(a_in.xrep.length()+1);
b.xrep.SetMaxLength(b_in.xrep.length()+1);
long max_sz = max(a_in.xrep.length(), b_in.xrep.length());
r.xrep.SetLength(max_sz+1);
s.xrep.SetLength(max_sz+1);
_ntl_ulong *rp = r.xrep.elts();
_ntl_ulong *sp = s.xrep.elts();
long i;
for (i = 0; i <= max_sz; i++) {
rp[i] = sp[i] = 0;
}
sp[0] = 1;
long sr = 0;
long ss = 1;
a = a_in;
b = b_in;
_ntl_ulong *ap = a.xrep.elts();
_ntl_ulong *bp = b.xrep.elts();
long da = deg(a);
long wa = da/NTL_BITS_PER_LONG;
long ba = da - wa*NTL_BITS_PER_LONG;
long db = deg(b);
long wb = db/NTL_BITS_PER_LONG;
long bb = db - wb*NTL_BITS_PER_LONG;
long parity = 0;
for (;;) {
if (da < db) {
swap(ap, bp);
swap(da, db);
swap(wa, wb);
swap(ba, bb);
parity = 1 - parity;
swap(rp, sp);
swap(sr, ss);
}
// da >= db
if (db < m) break;
ShiftAdd(ap, bp, wb+1, da-db);
ShiftAdd(rp, sp, ss, da-db);
long t = ss + (da-db+NTL_BITS_PER_LONG-1)/NTL_BITS_PER_LONG;
if (t > sr) {
while (t > 0 && rp[t-1] == 0) t--;
sr = t;
}
_ntl_ulong msk = 1UL << ba;
_ntl_ulong aa = ap[wa];
while ((aa & msk) == 0) {
da--;
msk = msk >> 1;
ba--;
if (!msk) {
wa--;
ba = NTL_BITS_PER_LONG-1;
msk = 1UL << (NTL_BITS_PER_LONG-1);
if (wa < 0) break;
aa = ap[wa];
}
}
}
a.normalize();
b.normalize();
r.normalize();
s.normalize();
if (!parity) {
h = s;
}
else {
h = r;
}
}
void DoMinPolyMod(GF2X& h, const GF2X& g, const GF2XModulus& F, long m,
const GF2X& R)
{
GF2X x;
ProjectPowers(x, R, 2*m, g, F);
MinPolyInternal(h, x, m);
}
void MinPolySeq(GF2X& h, const vec_GF2& 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");
GF2X x;
x.xrep = a.rep;
x.normalize();
MinPolyInternal(h, x, m);
}
void ProbMinPolyMod(GF2X& h, const GF2X& g, const GF2XModulus& F, long m)
{
long n = F.n;
if (m < 1 || m > n) Error("ProbMinPoly: bad args");
GF2X R;
random(R, n);
DoMinPolyMod(h, g, F, m, R);
}
void ProbMinPolyMod(GF2X& h, const GF2X& g, const GF2XModulus& F)
{
ProbMinPolyMod(h, g, F, F.n);
}
void MinPolyMod(GF2X& hh, const GF2X& g, const GF2XModulus& F, long m)
{
GF2X 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 */
GF2X h2, h3;
GF2X R;
GF2XTransMultiplier 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(GF2X& h, const GF2X& g, const GF2XModulus& F, long m)
{
if (m < 1 || m > F.n) Error("IrredPoly: bad args");
GF2X R;
set(R);
DoMinPolyMod(h, g, F, m, R);
}
void IrredPolyMod(GF2X& h, const GF2X& g, const GF2XModulus& F)
{
IrredPolyMod(h, g, F, F.n);
}
void MinPolyMod(GF2X& hh, const GF2X& g, const GF2XModulus& F)
{
MinPolyMod(hh, g, F, F.n);
}
void MulByXMod(GF2X& c, const GF2X& a, const GF2XModulus& F)
{
long da = deg(a);
long df = deg(F);
if (da >= df) Error("MulByXMod: bad args");
MulByX(c, a);
if (da >= 0 && da == df-1)
add(c, c, F);
}
static
void MulByXModAux(GF2X& c, const GF2X& a, const GF2X& f)
{
long da = deg(a);
long df = deg(f);
if (da >= df) Error("MulByXMod: bad args");
MulByX(c, a);
if (da >= 0 && da == df-1)
add(c, c, f);
}
void MulByXMod(GF2X& h, const GF2X& a, const GF2X& f)
{
if (&h == &f) {
GF2X hh;
MulByXModAux(hh, a, f);
h = hh;
}
else
MulByXModAux(h, a, f);
}
void power(GF2X& x, const GF2X& 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 > (NTL_MAX_LONG-1)/e)
Error("overflow in power");
GF2X 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_GF2& S, const GF2XModulus& f)
{
long n = deg(f);
if (n <= 0) Error("TraceVec: bad args");
GF2X x = reverse(-LeftShift(reverse(diff(reverse(f)), n-1), n-1)/f, n-1);
VectorCopy(S, x, n);
S.put(0, to_GF2(n));
}
static
void PlainTraceVec(vec_GF2& S, const GF2X& f)
{
long n = deg(f);
if (n <= 0)
Error("TraceVec: bad args");
if (n == 0) {
S.SetLength(0);
return;
}
GF2X x = reverse(-LeftShift(reverse(diff(reverse(f)), n-1), n-1)/f, n-1);
VectorCopy(S, x, n);
S.put(0, to_GF2(n));
}
void TraceVec(vec_GF2& S, const GF2X& f)
{
PlainTraceVec(S, f);
}
static
void ComputeTraceVec(const GF2XModulus& F)
{
vec_GF2& S = *((vec_GF2 *) &F.tracevec);
if (S.length() > 0)
return;
if (F.method == GF2X_MOD_PLAIN) {
PlainTraceVec(S, F.f);
}
else {
FastTraceVec(S, F);
}
}
void TraceMod(GF2& x, const GF2X& a, const GF2XModulus& F)
{
long n = F.n;
if (deg(a) >= n)
Error("trace: bad args");
if (F.tracevec.length() == 0)
ComputeTraceVec(F);
project(x, F.tracevec, a);
}
void TraceMod(GF2& x, const GF2X& a, const GF2X& f)
{
if (deg(a) >= deg(f) || deg(f) <= 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -