Esempio n. 1
0
// powVec[d] = p_d^{e_d}
// cycVec[d] = Phi_{p_d^{e_d}}(X) mod p
void computeCycVec(Vec<zz_pX>& cycVec, const Vec<long>& powVec)
{
  long k = powVec.length();
  cycVec.SetLength(k);

  for (long d = 0; d < k; d++) {
    ZZX PhimX = Cyclotomic(powVec[d]);
    cycVec[d] = conv<zz_pX>(PhimX);
  }
}
Esempio n. 2
0
PowerfulTranslationIndexes::PowerfulTranslationIndexes(const Vec<long>& mv):
  mvec(mv) // copy the vector of factors
{
  // mvec contains the prime-power factorization of m = \prod_{i=1}^k mi
  long nfactors = mvec.length();  // = k
  m = computeProd(mvec);          // compute m itself

  // phivec holds phi(mi) for all factors mi
  phivec.SetLength(nfactors);
  for (long i = 0; i < nfactors; i++) phivec[i] = phi_N(mvec[i]);
  phim = computeProd(phivec);     // phi(m) = prod_i phi(mi)

  computeDivVec(divvec, m, mvec); // divvec[i] = m/mi

  computeInvVec(invvec, divvec, mvec); // invvec[i] = (m/mi)^{-1} mod mi

  // Let (i_1,...,i_k) be the representation of i in base
  // (m/m1,...,m/mk), namely i = i_1 (m/m_1)+...+i_k (m/m_k) mod m.
  // Then polyToCubeMap[i] is the lexicographic index of the tuple
  // (i_1,...,i_k) in the cube with dimensions (m_1, ..., m_k).
  // cubeToPolyMap is the inverse map, polyToCubeMap[cubeToPolyMap[j]]=j.
  longSig.initSignature(mvec);
  shortSig.initSignature(phivec);
  computePowerToCubeMap(polyToCubeMap, cubeToPolyMap, m, mvec, invvec, longSig);

  // shortSig is a CubeSignature for (phi(m_1),..., phi(m_k)), and longSig
  // is a CubeSignature for (m_1, ..., m_k). shortToLongMap[i] maps an
  // index i wrt shortSig to an index i' wrt longSig so that both indexes
  // correspond to the same tuple (i_1,...,i_k).
  computeShortToLongMap(shortToLongMap, shortSig, longSig);

  cycVec.SetLength(nfactors);
  for (long d = 0; d < nfactors; d++) cycVec[d] = Cyclotomic(mvec[d]);

  phimX = Cyclotomic(m);
}
Esempio n. 3
0
FFTHelper::FFTHelper(long _m, zz_p x)
{
  m = _m;
  m_inv = 1/conv<zz_p>(m);
  root = conv<zz_p>( SqrRootMod( conv<ZZ>(x), conv<ZZ>(zz_p::modulus())) );
    // NOTE: the previous line is a pain because NTL does not have
    // a single-precision variant of SqrRootMod...
  iroot = 1/root;

  phim = 0;
  coprime.SetLength(m);
  for (long i = 0; i < m; i++) {
    coprime[i] = (GCD(i, m) == 1); 
    if (coprime[i]) phim++;
  }

  build(phimx, conv<zz_pX>( Cyclotomic(m) ));
}
Esempio n. 4
0
PAlgebra::PAlgebra(unsigned long mm, unsigned long pp,  
                   const vector<long>& _gens, const vector<long>& _ords )
{
  assert( ProbPrime(pp) );
  assert( (mm % pp) != 0 );
  assert( mm < NTL_SP_BOUND );
  assert( mm > 1 );

  cM  = 1.0; // default value for the ring constant
  m = mm;
  p = pp;

  long k = NextPowerOfTwo(m);
  if (mm == (1UL << k))
    pow2 = k;
  else
    pow2 = 0;

   

  // For dry-run, use a tiny m value for the PAlgebra tables
  if (isDryRun()) mm = (p==3)? 4 : 3;

  // Compute the generators for (Z/mZ)^* (defined in NumbTh.cpp)

  if (_gens.size() == 0 || isDryRun()) 
      ordP = findGenerators(this->gens, this->ords, mm, pp);
  else {
    assert(_gens.size() == _ords.size());
    gens = _gens;
    ords = _ords;
    ordP = multOrd(pp, mm);
  }
  nSlots = qGrpOrd();
  phiM = ordP * nSlots;

  // Allocate space for the various arrays
  T.resize(nSlots);
  dLogT.resize(nSlots*gens.size());
  Tidx.assign(mm,-1);    // allocate m slots, initialize them to -1
  zmsIdx.assign(mm,-1);  // allocate m slots, initialize them to -1
  long i, idx;
  for (i=idx=0; i<(long)mm; i++) if (GCD(i,mm)==1) zmsIdx[i] = idx++;

  // Now fill the Tidx and dLogT translation tables. We identify an element
  // t\in T with its representation t = \prod_{i=0}^n gi^{ei} mod m (where
  // the gi's are the generators in gens[]) , represent t by the vector of
  // exponents *in reverse order* (en,...,e1,e0), and order these vectors
  // in lexicographic order.

  // FIXME: is the comment above about reverse order true? It doesn't 
  // seem like it to me.  VJS.

  // buffer is initialized to all-zero, which represents 1=\prod_i gi^0
  vector<unsigned long> buffer(gens.size()); // temporaty holds exponents
  i = idx = 0;
  long ctr = 0;
  do {
    ctr++;
    unsigned long t = exponentiate(buffer);
    for (unsigned long j=0; j<buffer.size(); j++) dLogT[idx++] = buffer[j];

    assert(GCD(t,mm) == 1); // sanity check for user-supplied gens
    assert(Tidx[t] == -1);

    T[i] = t;       // The i'th element in T it t
    Tidx[t] = i++;  // the index of t in T is i

    // increment buffer by one (in lexigoraphic order)
  } while (nextExpVector(buffer)); // until we cover all the group

  assert(ctr == long(nSlots)); // sanity check for user-supplied gens

  PhimX = Cyclotomic(mm); // compute and store Phi_m(X)

  // initialize prods array
  long ndims = gens.size();
  prods.resize(ndims+1);
  prods[ndims] = 1;
  for (long j = ndims-1; j >= 0; j--) {
    prods[j] = OrderOf(j) * prods[j+1];
  }
  //  pp_factorize(mFactors,mm); // prime-power factorization from NumbTh.cpp
}
Esempio n. 5
0
// Generate the representation of Z_m^* for a given odd integer m
// and plaintext base p
PAlgebra::PAlgebra(unsigned long mm, unsigned long pp)
{
    m = mm;
    p = pp;

    assert( (m&1) == 1 );
    assert( ProbPrime(p) );
    // replaced by Mahdi after a conversation with Shai
    // assert( m > p && (m % p) != 0 );	// original line
    assert( (m % p) != 0 );
    // end of replace by Mahdi
    assert( m < NTL_SP_BOUND );

    // Compute the generators for (Z/mZ)^*
    vector<unsigned long> classes(m);
    vector<long> orders(m);

    unsigned long i;
    for (i=0; i<m; i++) { // initially each element in its own class
        if (GCD(i,m)!=1)
            classes[i] = 0; // i is not in (Z/mZ)^*
        else
            classes[i] = i;
    }

    // Start building a representation of (Z/mZ)^*, first use the generator p
    conjClasses(classes,p,m);  // merge classes that have a factor of 2

    // The order of p is the size of the equivalence class of 1
    ordP = (unsigned long) count (classes.begin(), classes.end(), 1);

    // Compute orders in (Z/mZ)^*/<p> while comparing to (Z/mZ)^*
    long idx, largest;
    while (true) {
        compOrder(orders,classes,true,m);
        idx = argmax(orders);      // find the element with largest order
        largest = orders[idx];

        if (largest <= 0) break;   // stop comparing to order in (Z/mZ)^*

        // store generator with same order as in (Z/mZ)^*
        gens.push_back(idx);
        ords.push_back(largest);
        conjClasses(classes,idx,m); // merge classes that have a factor of idx
    }
    // Compute orders in (Z/mZ)^*/<p> without comparing to (Z/mZ)^*
    while (true) {
        compOrder(orders,classes,false,m);
        idx = argmax(orders);      // find the element with largest order
        largest = orders[idx];

        if (largest <= 0) break;   // we have the trivial group, we are done

        // store generator with different order than (Z/mZ)^*
        gens.push_back(idx);
        ords.push_back(-largest);  // store with negative sign
        conjClasses(classes,idx,m);  // merge classes that have a factor of idx
    }

    nSlots = qGrpOrd();
    phiM = ordP * nSlots;

    // Allocate space for the various arrays
    T.resize(nSlots);
    dLogT.resize(nSlots*gens.size());
    Tidx.assign(m,-1);    // allocate m slots, initialize them to -1
    zmsIdx.assign(m,-1);  // allocate m slots, initialize them to -1
    for (i=idx=0; i<m; i++) if (GCD(i,m)==1) zmsIdx[i] = idx++;

    // Now fill the Tidx and dLogT translation tables. We identify an element
    // t\in T with its representation t = \prod_{i=0}^n gi^{ei} mod m (where
    // the gi's are the generators in gens[]) , represent t by the vector of
    // exponents *in reverse order* (en,...,e1,e0), and order these vectors
    // in lexicographic order.

    // buffer is initialized to all-zero, which represents 1=\prod_i gi^0
    vector<unsigned long> buffer(gens.size()); // temporaty holds exponents
    i = idx = 0;
    do {
        unsigned long t = exponentiate(buffer);
        for (unsigned long j=0; j<buffer.size(); j++) dLogT[idx++] = buffer[j];
        T[i] = t;       // The i'th element in T it t
        Tidx[t] = i++;  // the index of t in T is i

        // increment buffer by one (in lexigoraphic order)
    } while (nextExpVector(buffer)); // until we cover all the group

    PhimX = Cyclotomic(m); // compute and store Phi_m(X)

    // initialize prods array
    long ndims = gens.size();
    prods.resize(ndims+1);
    prods[ndims] = 1;
    for (long j = ndims-1; j >= 0; j--) {
        prods[j] = OrderOf(j) * prods[j+1];
    }
}
Esempio n. 6
0
int main(int argc, char *argv[])
{
   argmap_t argmap;
   argmap["p"] = "5";
   argmap["m"] = "101";
   argmap["r"] = "1";

   if (!parseArgs(argc, argv, argmap)) usage(argv[0]);

   long p = atoi(argmap["p"]);
   long m = atoi(argmap["m"]);
   long r = atoi(argmap["r"]);

   cout << "p=" << p << ", m=" << m << ", r=" << r << "\n";

   ZZX phimx = Cyclotomic(m);

   zz_p::init(p);
   zz_pX phimx_modp = to_zz_pX(phimx);

   

   vec_zz_pX factors = SFCanZass(phimx_modp);


   vec_ZZX FFactors;
   MultiLift(FFactors, factors, phimx, r);

   zz_p::init(power_long(p, r));

   vec_zz_pX Factors;
   Factors.SetLength(FFactors.length());
   for (long i = 0; i < Factors.length(); i++)
      conv(Factors[i], FFactors[i]);

   zz_pX G = Factors[0];
   long d = deg(G);
   cout << "d=" << d << "\n";

   zz_pE::init(G);

   // L selects the even coefficients
   vec_zz_pE L;
   L.SetLength(d);
   for (long j = 0; j < d; j++) {
      if (j % 2 == 0)
         L[j] = to_zz_pE(zz_pX(j, 1));
   }

   vec_zz_pE C;
   buildLinPolyCoeffs(C, L, p, r);

   zz_pE alpha, beta;
   random(alpha);

   applyLinPoly(beta, C, alpha, p);

   cout << alpha << "\n";
   cout << beta << "\n";

}