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) 
      LogicError("ProjectPowers: bad args");
   if (NTL_OVERFLOW(k, 1, 0)) 
      ResourceError("ProjectPowers: excessive 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);
   }
}
static void StripZeroes(vec_ZZ_p& x)
{
   long n = x.length();
   while (n > 0 && IsZero(x[n-1]))
      n--;
   x.SetLength(n);
}
Example #3
0
void negate(vec_ZZ_p& x, const vec_ZZ_p& a)
{
    long n = a.length();
    x.SetLength(n);
    long i;
    for (i = 0; i < n; i++)
        negate(x[i], a[i]);
}
Example #4
0
void sub(vec_ZZ_p& x, const vec_ZZ_p& a, const vec_ZZ_p& b)
{
    long n = a.length();
    if (b.length() != n) LogicError("vector sub: dimension mismatch");
    x.SetLength(n);
    long i;
    for (i = 0; i < n; i++)
        sub(x[i], a[i], b[i]);
}
Example #5
0
void mul(vec_ZZ_p& x, const vec_ZZ_p& a, long b_in)
{
    NTL_ZZ_pRegister(b);
    b = b_in;
    long n = a.length();
    x.SetLength(n);
    long i;
    for (i = 0; i < n; i++)
        mul(x[i], a[i], b);
}
Example #6
0
void FindRoots(vec_ZZ_p& x, const ZZ_pX& ff)
{
   ZZ_pX f = ff;

   if (!IsOne(LeadCoeff(f)))
      Error("FindRoots: bad args");

   x.SetMaxLength(deg(f));
   x.SetLength(0);
   RecFindRoots(x, f);
}
void conv(vec_ZZ_p& x, const vec_ZZ& a)
{
   long i, n;

   n = a.length();
   x.SetLength(n);

   ZZ_p* xp = x.elts();
   const ZZ* ap = a.elts();

   for (i = 0; i < n; i++)
      conv(xp[i], ap[i]);
}
Example #8
0
void InnerProduct(ZZ_p& x, const vec_ZZ_p& a, const vec_ZZ_p& b)
{
    long n = min(a.length(), b.length());
    long i;
    NTL_ZZRegister(accum);
    NTL_ZZRegister(t);

    clear(accum);
    for (i = 0; i < n; i++) {
        mul(t, rep(a[i]), rep(b[i]));
        add(accum, accum, t);
    }

    conv(x, accum);
}
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]);
}
Example #10
0
void clear(vec_ZZ_p& x)
{
    long n = x.length();
    long i;
    for (i = 0; i < n; i++)
        clear(x[i]);
}
void InnerProduct(ZZ_pX& x, const vec_ZZ_p& v, long low, long high, 
                   const vec_ZZ_pX& H, long n, ZZVec& t)
{
   NTL_ZZRegister(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_p& h = H[i-low].rep;
      long m = h.length();
      const ZZ& 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();
}
static
void ComputeTraceVec(vec_ZZ_p& S, const ZZ_pXModulus& F)
{
   if (!F.UseFFT) {
      PlainTraceVec(S, F.f);
      return;
   }

   long i;
   long n = F.n;

   FFTRep R;
   ZZ_pX P, g;

   g.rep.SetLength(n-1);
   for (i = 1; i < n; i++)
      mul(g.rep[n-i-1], F.f.rep[n-i], i); 
   g.normalize();

   ToFFTRep(R, g, F.l);
   mul(R, R, F.HRep);
   FromFFTRep(P, R, n-2, 2*n-4);

   S.SetLength(n);

   S[0] = n;
   for (i = 1; i < n; i++)
      negate(S[i], coeff(P, n-1-i));
}
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 PlainTraceVec(vec_ZZ_p& S, const ZZ_pX& ff)
{
   if (deg(ff) <= 0)
      LogicError("TraceVec: bad args");

   ZZ_pX f;
   f = ff;

   MakeMonic(f);

   long n = deg(f);

   S.SetLength(n);

   if (n == 0)
      return;

   long k, i;
   ZZ acc, t;
   ZZ_p t1;

   S[0] = n;

   for (k = 1; k < n; k++) {
      mul(acc, rep(f.rep[n-k]), k);

      for (i = 1; i < k; i++) {
         mul(t, rep(f.rep[n-i]), rep(S[k-i]));
         add(acc, acc, t);
      }

      conv(t1, acc);
      negate(S[k], t1);
   }
}
void conv(vec_ZZ& x, const vec_ZZ_p& a)
{
   long n = a.length();
   x.SetLength(n);
   long i;
   for (i = 0; i < n; i++)
      x[i] = rep(a[i]);
}
Example #16
0
void VectorCopy(vec_ZZ_p& x, const vec_ZZ_p& a, long n)
{
    if (n < 0) LogicError("VectorCopy: negative length");
    if (NTL_OVERFLOW(n, 1, 0)) ResourceError("overflow in VectorCopy");

    long m = min(n, a.length());

    x.SetLength(n);

    long i;

    for (i = 0; i < m; i++)
        x[i] = a[i];

    for (i = m; i < n; i++)
        clear(x[i]);
}
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) LogicError("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 FastTraceVec(vec_ZZ_p& S, const ZZ_pX& f)
{
   long n = deg(f);

   if (n <= 0) 
      LogicError("FastTraceVec: bad args");

   if (n == 0) {
      S.SetLength(0);
      return;
   }

   if (n == 1) {
      S.SetLength(1);
      set(S[0]);
      return;
   }
   
   long i;
   ZZ_pX f1;

   f1.rep.SetLength(n-1);
   for (i = 0; i <= n-2; i++)
      f1.rep[i] = f.rep[n-i];
   f1.normalize();

   ZZ_pX f2;
   f2.rep.SetLength(n-1);
   for (i = 0; i <= n-2; i++)
      mul(f2.rep[i], f.rep[n-1-i], i+1);
   f2.normalize();

   ZZ_pX f3;
   InvTrunc(f3, f1, n-1);
   MulTrunc(f3, f3, f2, n-1);

   S.SetLength(n);

   S[0] = n;
   for (i = 1; i < n; i++)
      negate(S[i], coeff(f3, i-1));
}
Example #19
0
long IsZero(const vec_ZZ_p& a)
{
    long n = a.length();
    long i;

    for (i = 0; i < n; i++)
        if (!IsZero(a[i]))
            return 0;

    return 1;
}
void MinPolySeq(ZZ_pX& h, const vec_ZZ_p& a, long m)
{
   if (m < 0) LogicError("MinPoly: bad args");
   if (NTL_OVERFLOW(m, 1, 0)) LogicError("MinPoly: bad args");
   if (a.length() < 2*m) LogicError("MinPoly: sequence too short");

   if (m > NTL_ZZ_pX_BERMASS_CROSSOVER)
      GCDMinPolySeq(h, a, m);
   else
      BerlekampMassey(h, a, m);
}
Example #21
0
static
void FindFactors(vec_ZZ_pX& factors, const ZZ_pX& f, const ZZ_pX& g,
                 const vec_ZZ_p& roots)
{
   long r = roots.length();

   factors.SetMaxLength(r);
   factors.SetLength(0);

   RecFindFactors(factors, f, g, roots, 0, r-1);
}
Example #22
0
void InnerProduct(ZZ_p& x, const vec_ZZ_p& a, const vec_ZZ_p& b,
                  long offset)
{
    if (offset < 0) LogicError("InnerProduct: negative offset");
    if (NTL_OVERFLOW(offset, 1, 0))
        ResourceError("InnerProduct: offset too big");

    long n = min(a.length(), b.length()+offset);
    long i;
    NTL_ZZRegister(accum);
    NTL_ZZRegister(t);

    clear(accum);
    for (i = offset; i < n; i++) {
        mul(t, rep(a[i]), rep(b[i-offset]));
        add(accum, accum, t);
    }

    conv(x, accum);
}
Example #23
0
// inner product (svec_ZZ and svec_ZZ_p)
inline void InnerProduct(ZZ_p& result, const svec_ZZ& a, const vec_ZZ_p& b) {
  if (a.length()!=b.length()) {
    cerr<<"InnerProduct() length mismatch\n";
    exit(1);
  }
  clear(result);
  long an = a.nvalues();
  const svec_ZZ::index_t* ai = a.indices();
  const svec_ZZ::value_t* av = a.values();
  for (long i=0; i<an; ++i)
    result += to_ZZ_p(av[i])*b[ai[i]];
}
static
void mul_aux(vec_ZZ_p& x, const vec_ZZ_p& a, const mat_ZZ_p& B)  
{  
   long n = B.NumRows();  
   long l = B.NumCols();  
  
   if (n != a.length())  
      Error("matrix mul: dimension mismatch");  
  
   x.SetLength(l);  
  
   long i, k;  
   ZZ acc, tmp;  
  
   for (i = 1; i <= l; i++) {  
      clear(acc);  
      for (k = 1; k <= n; k++) {  
         mul(tmp, rep(a(k)), rep(B(k,i)));
         add(acc, acc, tmp);  
      }  
      conv(x(i), acc);  
   }  
}  
static
void mul_aux(vec_ZZ_p& x, const mat_ZZ_p& A, const vec_ZZ_p& b)  
{  
   long n = A.NumRows();  
   long l = A.NumCols();  
  
   if (l != b.length())  
      Error("matrix mul: dimension mismatch");  
  
   x.SetLength(n);  
  
   long i, k;  
   ZZ acc, tmp;  
  
   for (i = 1; i <= n; i++) {  
      clear(acc);  
      for (k = 1; k <= l; k++) {  
         mul(tmp, rep(A(i,k)), rep(b(k)));  
         add(acc, acc, tmp);  
      }  
      conv(x(i), acc);  
   }  
}  
Example #26
0
static
void IterFindFactors(vec_ZZ_pX& factors, const ZZ_pX& f,
                     const ZZ_pX& g, const vec_ZZ_p& roots)
{
   long r = roots.length();
   long i;
   ZZ_pX h;

   factors.SetLength(r);

   for (i = 0; i < r; i++) {
      sub(h, g, roots[i]);
      GCD(factors[i], f, h);
   }
}
Example #27
0
static
void RecFindRoots(vec_ZZ_p& x, const ZZ_pX& f)
{
   if (deg(f) == 0) return;

   if (deg(f) == 1) {
      long k = x.length();
      x.SetLength(k+1);
      negate(x[k], ConstTerm(f));
      return;
   }
      
   ZZ_pX h;

   ZZ_p r;
   ZZ p1;


   RightShift(p1, ZZ_p::modulus(), 1);
   
   {
      ZZ_pXModulus F;
      build(F, f);

      do {
         random(r);
         PowerXPlusAMod(h, r, p1, F);
         add(h, h, -1);
         GCD(h, h, f);
      } while (deg(h) <= 0 || deg(h) == deg(f));
   }

   RecFindRoots(x, h);
   div(h, f, h); 
   RecFindRoots(x, h);
}
void solve(ZZ_p& d, vec_ZZ_p& X, 
           const mat_ZZ_p& A, const vec_ZZ_p& b)

{
   long n = A.NumRows();
   if (A.NumCols() != n)
      Error("solve: nonsquare matrix");

   if (b.length() != n)
      Error("solve: dimension mismatch");

   if (n == 0) {
      set(d);
      X.SetLength(0);
      return;
   }

   long i, j, k, pos;
   ZZ t1, t2;
   ZZ *x, *y;

   const ZZ& p = ZZ_p::modulus();

   vec_ZZVec M;
   sqr(t1, p);
   mul(t1, t1, n);

   M.SetLength(n);

   for (i = 0; i < n; i++) {
      M[i].SetSize(n+1, t1.size());
      for (j = 0; j < n; j++) 
         M[i][j] = rep(A[j][i]);
      M[i][n] = rep(b[i]);
   }

   ZZ det;
   set(det);

   for (k = 0; k < n; k++) {
      pos = -1;
      for (i = k; i < n; i++) {
         rem(t1, M[i][k], p);
         M[i][k] = t1;
         if (pos == -1 && !IsZero(t1)) {
            pos = i;
         }
      }

      if (pos != -1) {
         if (k != pos) {
            swap(M[pos], M[k]);
            NegateMod(det, det, p);
         }

         MulMod(det, det, M[k][k], p);

         // make M[k, k] == -1 mod p, and make row k reduced

         InvMod(t1, M[k][k], p);
         NegateMod(t1, t1, p);
         for (j = k+1; j <= n; j++) {
            rem(t2, M[k][j], p);
            MulMod(M[k][j], t2, t1, p);
         }

         for (i = k+1; i < n; i++) {
            // M[i] = M[i] + M[k]*M[i,k]

            t1 = M[i][k];   // this is already reduced

            x = M[i].elts() + (k+1);
            y = M[k].elts() + (k+1);

            for (j = k+1; j <= n; j++, x++, y++) {
               // *x = *x + (*y)*t1

               mul(t2, *y, t1);
               add(*x, *x, t2);
            }
         }
      }
      else {
         clear(d);
         return;
      }
   }

   X.SetLength(n);
   for (i = n-1; i >= 0; i--) {
      clear(t1);
      for (j = i+1; j < n; j++) {
         mul(t2, rep(X[j]), M[i][j]);
         add(t1, t1, t2);
      }
      sub(t1, t1, M[i][n]);
      conv(X[i], t1);
   }

   conv(d, det);
}
void interpolate(ZZ_pX& f, const vec_ZZ_p& a, const vec_ZZ_p& b)
{
   long m = a.length();
   if (b.length() != m) LogicError("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;
}
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_FFT_CROSSOVER);
   long crossover = 1L << k0;

   if (n <= 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
}