示例#1
0
// Returns a list of prime factors and their multiplicity, 
// N = \prod_i factors[i].first^{factors[i].second}
void factorize(Vec< Pair<long, long> > &factors, long N)
{
  factors.SetLength(0);

  if (N < 2) return;

  PrimeSeq s;
  long n = N;
  while (n > 1) {
    if (ProbPrime(n)) { // n itself is a prime, add (n,1) to the list
      append(factors, cons(n, 1L));
      return;
    }

    long p = s.next();
    if ((n % p) == 0) { // p divides n, find its multiplicity
      long e = 1;
      n = n/p;
      while ((n % p) == 0) {
        n = n/p;
        e++;
      }
      append(factors, cons(p, e)); // add (p,e) to the list
    }
  }
}
示例#2
0
// Find the next prime and add it to the chain
long FHEcontext::AddPrime(long initialP, long delta, bool special,
                          bool findRoot)
{
    // long twoM = 2 * zMStar.getM();
    // assert((initialP % twoM == 1) && (delta % twoM == 0));
    // NOTE: this assertion will fail for the half-prime in ALT_CRT

    long p = initialP;
    do {
        p += delta;    // delta could be positive or negative
    }
    while (p>initialP/16 && p<NTL_SP_BOUND && !(ProbPrime(p) && !inChain(p)));

    if (p<=initialP/16 || p>=NTL_SP_BOUND) return 0; // no prime found

    long i = moduli.size(); // The index of the new prime in the list
    moduli.push_back( Cmodulus(zMStar, p, findRoot ? 0 : 1) );

    if (special)
        specialPrimes.insert(i);
    else
        ctxtPrimes.insert(i);

    return p;
}
示例#3
0
// Генерация параметров ЭК
void genparams ( Qxy &P, ZZ &q, ZZ &bpn )
{
	ZZ i;
	ZZ x, y;
	ZZ f1, f2;

	for ( x = 0, i = 0; x < p; x++)
		for ( y = 0; y < p; y++)
		{
			f1 = PowerMod(y, 2, p);
			f2 = (PowerMod(x, 3, p) + a * x + b)%p;
			if ( f1 == f2 )
			{
				if ( i == bpn )
					P.getQxy(x,y);
				i++;
			}
		}
	q = i+1;
	long NumTrials = 10;
	if ( !ProbPrime( q, NumTrials) )
		cout << "\nq is not prime! Please, change params (p,a,b)." << endl;
	
	cout << "\nDomain parameters\n" << endl;
	cout << "\np = " << p;
	cout << "\na = " << a;
	cout << "\nb = " << b;
	cout << "\nbpn = " << bpn << endl;
	cout << "\nq = " << q << endl;
	cout << "\nP = "; P.putQxy(); cout << endl;
}
示例#4
0
bool ProvePrime(const ZZ& _n) {
  ZZ n(_n);
  if (n<0)
    abs(n,n);
  if (n<=1)
    return 0;

  if (n<=1000000) {
    // n is small so use trial division to check primality
    long ln = to_long(n);
    long end = to_long(SqrRoot(n));
    PrimeSeq s;
    for (long p=s.next(); p<=end; p=s.next())
      if ((ln%p)==0)
	return 0;
    return 1;
  }

  // check small primes
  PrimeSeq s;
  for (long p=s.next(); p<1000; p=s.next())
    if (divide(n,p))
      return 0;

  // obviously, something is missing here!

  return ProbPrime(n);
}
示例#5
0
// return a degree-d irreducible polynomial mod p
ZZX makeIrredPoly(long p, long d)
{
	assert(d >= 1);
  assert(ProbPrime(p));

  if (d == 1) return ZZX(1, 1); // the monomial X

  zz_pBak bak; bak.save();
  zz_p::init(p);
  return to_ZZX(BuildIrred_zz_pX(d));
}
示例#6
0
// Find the next prime and add it to the chain
long FHEcontext::AddPrime(long initialP, long delta, bool special)
{
  long p = initialP;
  do { p += delta; } // delta could be positive or negative
  while (p>initialP/16 && p<NTL_SP_BOUND && !(ProbPrime(p) && !inChain(p)));

  if (p<=initialP/16 || p>=NTL_SP_BOUND) return 0; // no prime found

  long i = moduli.size(); // The index of the new prime in the list
  moduli.push_back( Cmodulus(zMStar, p, 0) );

  if (special)
    specialPrimes.insert(i);
  else
    ctxtPrimes.insert(i);

  return p;
}
示例#7
0
void genparams( ZZ &p, ZZ &q, ZZ &a)
{

	long err = 80;	
	GenPrime(q, N, err);

	ZZ m;
	RandomLen(m, L-N);

	cout << "\nGenerating p, q and a...\n";
	long NumTrials = 20;
	for (long i = 0; i < 10000; i++, m++)
	{
		p = q * m + 1;
		
		if (ProbPrime(p, NumTrials))
		{
			// cout << "\ni = " << i << endl;
			// cout << "OK" << endl;
			break;
		}
	}

	ZZ d, f;
//	ZZ f1 = ((p-1) * InvMod(q, p)) % p;
	ZZ f1 = m;	// = (p-1)/q
	for( d = 2; a == 0; d++ )
	{
		f = PowerMod(d%p, f1%p, p);
		if ( f >  1 )
		{	
			a = f;
			// cout << a << " ";
			break;
		}
	}
	cout << "\np = \n"; show_dec_in_hex (p, L);	cout << endl;
	cout << "\nq = \n"; show_dec_in_hex (q, N);	cout << endl;
	cout << "\na = \n"; show_dec_in_hex (a, L);	cout << endl;
}
示例#8
0
// Factoring by trial division, only works for N<2^{60}.
// Only the primes are recorded, not their multiplicity
template<class zz> static void factorT(vector<zz> &factors, const zz &N)
{
  factors.resize(0); // reset the factors

  if (N<2) return;   // sanity check

  PrimeSeq s;
  zz n = N;
  while (true) {
    if (ProbPrime(n)) { // we are left with just a single prime
      factors.push_back(n);
      return;
    }
    // if n is a composite, check if the next prime divides it
    long p = s.next();
    if ((n%p)==0) {
      zz pp;
      conv(pp,p);
      factors.push_back(pp);
      do { n /= p; } while ((n%p)==0);
    }
    if (n==1) return;
  }
}
示例#9
0
// Генерация параметров ЭК
// Порядок ЭК q
void genparam_q ( Qxy &P, ZZ &q )
{
	ZZ i;
	ZZ x, y;
	ZZ f1, f2;

	for ( x = 0, i = 0; x < p; x++)
		for ( y = 0; y < p; y++)
		{
			f1 = PowerMod(y, 2, p);
			f2 = (PowerMod(x, 3, p) + a * x + b)%p;
			if ( f1 == f2 ) i++;	
		}
	q = i+1;

	long NumTrials = 10;
	if ( !ProbPrime( q, NumTrials) )
		cout << "\nq is not prime! Please, change params (p,a,b)." << endl;
	
	cout << "\np = " << p;
	cout << "\na = " << a;
	cout << "\nb = " << b;
	cout << "\nq = " << q << endl;
}
示例#10
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
}
示例#11
0
long IsFFTPrime(long n, long& w)
{
   long  m, x, y, z;
   long j, k;


   if (n <= 1 || n >= NTL_SP_BOUND) return 0;

   if (n % 2 == 0) return 0;

   if (n % 3 == 0) return 0;

   if (n % 5 == 0) return 0;

   if (n % 7 == 0) return 0;
   
   m = n - 1;
   k = 0;
   while ((m & 1) == 0) {
      m = m >> 1;
      k++;
   }

   for (;;) {
      x = RandomBnd(n);

      if (x == 0) continue;
      z = PowerMod(x, m, n);
      if (z == 1) continue;

      x = z;
      j = 0;
      do {
         y = z;
         z = MulMod(y, y, n);
         j++;
      } while (j != k && z != 1);

      if (z != 1 || y !=  n-1) return 0;

      if (j == k) 
         break;
   }

   /* x^{2^k} = 1 mod n, x^{2^{k-1}} = -1 mod n */

   long TrialBound;

   TrialBound = m >> k;
   if (TrialBound > 0) {
      if (!ProbPrime(n, 5)) return 0;
   
      /* we have to do trial division by special numbers */
   
      TrialBound = SqrRoot(TrialBound);
   
      long a, b;
   
      for (a = 1; a <= TrialBound; a++) {
         b = (a << k) + 1;
         if (n % b == 0) return 0; 
      }
   }

   /* n is an FFT prime */

   for (j = NTL_FFTMaxRoot; j < k; j++)
      x = MulMod(x, x, n);

   w = x;
   return 1;
}
示例#12
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];
    }
}
示例#13
0
    void main() {
        R = SqrRoot(m);
        int cnt = 0;
        for (long i = 1; m / i > R; ++i)
            basis[++cnt] = m / i;
        for (int i = R; i; --i)
            basis[++cnt] = i;
        // for (int i = 1; i <= cnt; ++i) {
        //     if (get_index(basis[i]) != i)
        //         print("!!! {} {}\n", get_index(basis[i]), i);
        // }

        for (int i = 1; i <= cnt; ++i) {
            num_primes[i] = basis[i] - 1;
        }
        // for (int i = 1; i < cnt; ++i) {
        //     for (int v = basis[i + 1] + 1; v <= basis[i]; ++v)
        //         if (v > R && ProbPrime(v))
        //             f[basis[i]] += 2;
        // }
        // f[1] = 1;
        // for (int i = cnt - 1; i; --i) {
        //     f[basis[i]] += f[basis[i + 1]];
        //     // print("init {} = {}\n", basis[i], f[basis[i]]);
        // }

        // long ans = 0;
        // for (int i = 1; i <= m; ++i) {
        //     ans += m / i;
        // }
        // print("bf = {}\n", ans);
        for (long x = 2; x <= R; ++x) {
            if (ProbPrime(x)) {
                print("current = {}\n", x);
                for (int i = 1; i <= cnt; ++i) {
                    long y = basis[i];
                    if (x * x > y)
                        break;
                    auto a = num_primes[get_index(y / x)];
                    auto b = num_primes[get_index(x - 1)];
                    num_primes[i] -= a - b;
                }
            }
        }
        for (int i = 1; i <= cnt; ++i) {
            num_primes[i] %= MOD;
            // print("{} {}\n", basis[i], num_primes[i]);
        }
        for (int i = 1; i <= cnt; ++i) {
            f[i] = 1;
            // if (basis[i] >= R) {
            //     f[i] += 2 * (num_primes[get_index(basis[i])] - num_primes[R]);
            // }
            // print("init {} {}\n", basis[i], f[i]);
        }

        for (long p = R; p; --p) {
            if (ProbPrime(p)) {
                print("current = {}\n", p);

                int t = p > n ? 0 : get_power(p, n);
                for (int e = 0; e <= 60; ++e)
                    g[e] = (e + 1) * (t + 1) + t * (t + 1) / 2;

                for (int i = 1; i <= cnt; ++i) {
                    long y = basis[i];
                    if (t == 0 && p * p > y)
                        break;
                    long v = 0; // 2 * (num_primes[get_index(y)] - num_primes[p]);
                    for (int e = 0; y; ++e) {
                        v += real_f(y, p) * g[e] % MOD;
                        y /= p;
                    }
                    if (basis[i] >= p)
                        v -= 2 * (num_primes[i] - num_primes[get_index(p)] + 1) % MOD;
                    f[i] = (v + MOD) % MOD;
                    // print("update {} = {}\n", basis[i], v);
                }
            }
        }
        print("ans = {}\n", real_f(m, 1));
    }