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);
   }
}
Esempio n. 2
0
void CharPolyMod(zz_pX& g, const zz_pX& a, const zz_pX& ff)
{
   zz_pX f = ff;
   MakeMonic(f);
   long n = deg(f);

   if (n <= 0 || deg(a) >= n) 
      Error("CharPoly: bad args");

   if (IsZero(a)) {
      clear(g);
      SetCoeff(g, n);
      return;
   }

   if (n > 90 || (zz_p::PrimeCnt() <= 1 && n > 45)) {
      zz_pX h;
      MinPolyMod(h, a, f);
      if (deg(h) == n) {
         g = h;
         return;
      }
   }

   if (zz_p::modulus() < n+1) {
      HessCharPoly(g, a, f);
      return;
   }

   vec_zz_p u(INIT_SIZE, n+1), v(INIT_SIZE, n+1);

   zz_pX h, h1;
   negate(h, a);
   long i;

   for (i = 0; i <= n; i++) {
      u[i] = i;
      add(h1, h, u[i]);
      resultant(v[i], f, h1);
   }

   interpolate(g, u, v);
}
void PlainTraceVec(vec_zz_p& S, const zz_pX& ff)
{
   if (deg(ff) <= 0)
      Error("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_p acc, t;

   const zz_p *fp = f.rep.elts();;
   zz_p *sp = S.elts();

   sp[0] = n;

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

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

      negate(sp[k], acc);
   }
}
Esempio n. 4
0
///////////////////////////////////////////////////////////////////////////
// PURPOSE:
// Given syndrome ssWithoutEvens of BCH code with design distance d,
// finds sparse vector (with no more than
// (d-1)/2 ones) with that syndrome
// (note that syndrome as well sparse vector
// representation are defined at BCHSyndromeCompute above).
// 'answer' returns positions of ones in the resulting vector.
// These positions are elements of GF2E (i.e., we view the vector
// as a vector whose positions are indexed by elements of GF2E).
// Returns false if no such vector exists, true otherwise
// The input syndrome is assumed to not have even powers, i.e., 
// has (d-1)/2 elements, such as the syndrome computed by BCHSyndromeCompute.
// 
// ASSUMPTIONS:
// Let m=GF2E::degree() (i.e., the field is GF(2^m)).
// This algorithm assumes that d is odd, greater than 1, and less than 2^m.
// (else BCH codes don't make sense).
// Assumes input is of length (d-1)/2. 
//
// ALGORITHM USED:
// Implements BCH decoding based on Euclidean algorithm;
// For the explanation of the algorithm, see
// Syndrome Encoding and Decoding of BCH Codes in Sublinear Time
// (Excerpted from Fuzzy Extractors:
//    How to Generate Strong Keys from Biometrics and Other Noisy Data)
// by Yevgeniy Dodis, Rafail Ostrovsky, Leonid Reyzin and Adam Smith
// or Theorem 18.7 of Victor Shoup's "A Computational Introduction to 
// Number Theory and Algebra" (first edition, 2005), or
// pp. 170-173 of "Introduction to Coding Theory" by Jurgen Bierbrauer.
//
//
// RUNNING TIME:
// If the output has e elements (i.e., the length of the output vector
// is e; note that e <= (d-1)/2), then
// the running time is O(d^2 + e^2 + e^{\log_2 3} m) operations in GF(2^m),
// each of which takes time O(m^{\log_2 3}) in NTL.  Note that 
// \log_2 3 is approximately 1.585.
//
bool BCHSyndromeDecode(vec_GF2E &answer, const vec_GF2E & ssWithoutEvens, long d)
{
        long i;	
	vec_GF2E ss;


	// This takes O(d) operation in GF(2^m)
	InterpolateEvens(ss, ssWithoutEvens);

	GF2EX r1, r2, r3, v1, v2, v3,  q, temp;
	GF2EX *Rold, *Rcur, *Rnew, *Vold, *Vcur, *Vnew, *tempPointer;

        // Use pointers to avoid moving polynomials around
        // An assignment of polynomials requires copying the coefficient vector;
        // we will not assign polynomials, but will swap pointers instead
	Rold = &r1;
	Rcur = &r2;
	Rnew = &r3;

	Vold = &v1;
	Vcur = &v2;
	Vnew = &v3;


	SetCoeff(*Rold, d-1, 1); // Rold holds z^{d-1}

	// Rcur=S(z)/z where S is the syndrome poly, Rcur = \sum S_j z^{j-1}
        // Note that because we index arrays from 0, S_j is stored in ss[j-1]
	for (i=0; i<d-1; i++) 
	  SetCoeff (*Rcur, i, ss[i]);

	// Vold is already 0 -- no need to initialize
	// Initialize Vcur to 1
	SetCoeff(*Vcur, 0, 1); // Vcur = 1

	// Now run Euclid, but stop as soon as degree of Rcur drops below
	// (d-1)/2
	// This will take O(d^2) operations in GF(2^m)

	long t = (d-1)/2;



	while (deg(*Rcur) >=  t) {
	  // Rold = Rcur*q + Rnew
	  DivRem(q, *Rnew, *Rold, *Rcur);

	  // Vnew = Vold - qVcur)
	  mul(temp, q, *Vcur);
	  sub (*Vnew, *Vold, temp);


          // swap everything
	  tempPointer = Rold;	
	  Rold = Rcur;
	  Rcur = Rnew;
	  Rnew = tempPointer;

	  tempPointer = Vold;
	  Vold = Vcur;
	  Vcur = Vnew;
	  Vnew = tempPointer;
	}



	// At the end of the loop, sigma(z) is Vcur
	// (up to a constant factor, which doesn't matter,
	// since we care about roots of sigma).
	// The roots of sigma(z) are inverses of the points we
	// are interested in.  


	// We will check that 0 is not
        // a root of Vcur (else its inverse won't exist, and hence
	// the right polynomial doesn't exist).
	if (IsZero(ConstTerm(*Vcur)))
	  return false;

	// Need sigma to be monic for FindRoots
	MakeMonic(*Vcur);

        // check if sigma(z) has distinct roots if not, return false
	// this will take O(e^{\log_2 3} m) operations in GF(2^m),
	// where e is the degree of sigma(z)
	if (CheckIfDistinctRoots(*Vcur) == false)
	  return false;

        // find roots of sigma(z)
	// this will take O(e^2 + e^{\log_2 3} m) operations in GF(2^m),
	// where e is the degree of sigma(z)
	answer = FindRoots(*Vcur);

        // take inverses of roots of sigma(z)
	for (i = 0; i < answer.length(); ++i)
		answer[i] = inv(answer[i]);


	// It is now necessary to verify if the resulting vector
	// has the correct syndrome: it is possible that it does
	// not even though the polynomial sigma(z) factors
	// completely
	// This takes O(de) operations in GF(2^m)
	vec_GF2E test;
	BCHSyndromeCompute (test, answer, d);

	return (test==ssWithoutEvens);
}