void CBitPatternTreeMethod::convertToIntegers(CMatrix< C_FLOAT64 > & values)
{
  bool Problems = false;

  static const C_FLOAT64 limit = 10.0 / std::numeric_limits< C_INT32 >::max();

  size_t Size = values.size();
  size_t Columns = values.numCols();

  C_FLOAT64 * pColumn = values.array();
  C_FLOAT64 * pColumnEnd = pColumn + Columns;
  C_FLOAT64 * pValue = values.array();
  C_FLOAT64 * pValueEnd = pColumn + Size;

  for (; pColumn < pColumnEnd; ++pColumn)
    {
      unsigned C_INT32 Multiplier = 1;
      unsigned C_INT32 m00, m01, m10, m11;
      unsigned C_INT32 maxden = 10000000;
      C_INT32 GCD1, GCD2;
      unsigned C_INT32 ai;

      C_FLOAT64 x;

      for (pValue = pColumn; pValue < pValueEnd; pValue += Columns)
        {
          x = fabs(*pValue);

          if (x < 100 * std::numeric_limits< C_FLOAT64 >::epsilon())
            {
              continue;
            }

          /*
           * Find rational approximation to given real number
           * David Eppstein / UC Irvine / 8 Aug 1993
           *
           * With corrections from:
           *   Arno Formella, May 2008
           *   Stefan Hoops, Sept 2009
           *
           * Based on the theory of continued fractions
           * if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
           * then best approximation is found by truncating this series
           * (with some adjustments in the last term).
           *
           * Note the fraction can be recovered as the first column of the matrix
           *  (a1 1 ) (a2 1 ) (a3 1 ) ...
           *  (1  0 ) (1  0 ) (1  0)
           * Instead of keeping the sequence of continued fraction terms,
           * we just keep the last partial product of these matrices.
           */

          /* initialize matrix */
          m00 = m11 = 1;
          m01 = m10 = 0;

          /* loop finding terms until denom gets too big */
          while (m10 *(ai = (unsigned C_INT32) x) + m11 <= maxden)
            {
              C_INT32 t;
              t = m00 * ai + m01;
              m01 = m00;
              m00 = t;

              t = m10 * ai + m11;
              m11 = m10;
              m10 = t;

              if (fabs(x - (C_FLOAT64) ai) < limit)
                break;     // SH: We reached the numerical precision of the machine;

              x = 1 / (x - (C_FLOAT64) ai);
            }

          if ((C_FLOAT64) m10 *(C_FLOAT64) ai + (C_FLOAT64) m11 > (C_FLOAT64) maxden)
            {
              Problems = true;
            }

          if (fabs(fabs(*pValue) - ((C_FLOAT64) m00) / ((C_FLOAT64) m10)) > 100.0 * std::numeric_limits< C_FLOAT64 >::epsilon())
            {
              ai = (maxden - m11) / m10;
              m00 = m00 * ai + m01;
              m10 = m10 * ai + m11;
            }

          // Find the greatest common divisor (GCD) of the multiplier and the current denominator.
          // Euclidean algorithm
          GCD1 = m10;
          GCD2 = Multiplier;

          GCD(GCD1, GCD2);

          // Calculate the least common multiplier: LCM = v1 * v2 / GCD(v1, v2)
          Multiplier *= m10 / GCD1;
        }

      for (pValue = pColumn; pValue < pValueEnd; pValue += Columns)
        {
          *pValue *= Multiplier;
        }
    }
}
Пример #2
0
// Euclid's algorithm
int GCD(int x, int y) {
    if (y == 0)
        return x;
    return GCD(y, x%y);
}
Пример #3
0
LL LCM(LL a, LL b)
{
    return a * b / GCD(a, b);
}
Пример #4
0
static int LCMDenoCalculator( int n, int m )
{
	int gcd = GCD( n, m );
	return m/gcd;
}
Пример #5
0
int main()
{
   long n;
   GF2X a, b, c, c1, ss, ss1, tt, tt1;
   double t;
   long iter, i;

   cout << WD(12,"n") << WD(12,"OldGCD") <<  WD(12,"GCD") << WD(12,"OldXGCD")
        << WD(12, "XGCD") << "\n";

   cout.precision(3);
   cout.setf(ios::scientific);


   for (n = 32; n <= (1L << 18); n = n << 3) {
      random(a, n);
      random(b, n);
      OldGCD(c, a, b);
      GCD(c1, a, b);
      OldXGCD(c, ss, tt, a, b);
      XGCD(c1, ss1, tt1, a, b);
      if (c1 != c || ss1 != ss || tt1 != tt) {
         cerr << "**** GF2XTest FAILED!\n";
         return 1;
      }

      cout << WD(12,n); 

      iter = 0;
      do {
         iter = iter ? (2*iter) : 1;
         t = GetTime();
         for (i = 0; i < iter; i++)
            OldGCD(c, a, b);
         t = GetTime()-t;
      } while (t < 0.5);

      cout << WD(12,t/iter);

      iter = 0;
      do {
         iter = iter ? (2*iter) : 1;
         t = GetTime();
         for (i = 0; i < iter; i++)
            GCD(c, a, b);
         t = GetTime()-t;
      } while (t < 0.5);

      cout << WD(12,t/iter);

      iter = 0;
      do {
         iter = iter ? (2*iter) : 1;
         t = GetTime();
         for (i = 0; i < iter; i++)
            OldXGCD(c, ss, tt, a, b);
         t = GetTime()-t;
      } while (t < 0.5);

      cout << WD(12,t/iter);

      iter = 0;
      do {
         iter = iter ? (2*iter) : 1;
         t = GetTime();
         for (i = 0; i < iter; i++)
            XGCD(c, ss, tt, a, b);
         t = GetTime()-t;
      } while (t < 0.5);

      cout << WD(12,t/iter);

      cout << "\n";
   }

   return 0;
}
Пример #6
0
int LCM(int x, int y){    
    return x * y / GCD(x, y);
}
long IterIrredTest(const ZZ_pEX& f)
{
   if (deg(f) <= 0) return 0;
   if (deg(f) == 1) return 1;

   ZZ_pEXModulus F;

   build(F, f);
   
   ZZ_pEX h;

   FrobeniusMap(h, F);

   long CompTableSize = 2*SqrRoot(deg(f));

   ZZ_pEXArgument H;

   build(H, h, F, CompTableSize);

   long i, d, limit, limit_sqr;
   ZZ_pEX g, X, t, prod;


   SetX(X);

   i = 0;
   g = h;
   d = 1;
   limit = 2;
   limit_sqr = limit*limit;

   set(prod);


   while (2*d <= deg(f)) {
      sub(t, g, X);
      MulMod(prod, prod, t, F);
      i++;
      if (i == limit_sqr) {
         GCD(t, f, prod);
         if (!IsOne(t)) return 0;

         set(prod);
         limit++;
         limit_sqr = limit*limit;
         i = 0;
      }

      d = d + 1;
      if (2*d <= deg(f)) {
         CompMod(g, g, H, F);
      }
   }

   if (i > 0) {
      GCD(t, f, prod);
      if (!IsOne(t)) return 0;
   }

   return 1;
}
Пример #8
0
unsigned int LCM( unsigned int a, unsigned int b ) {

  unsigned int tmp=a/GCD(a,b);
  return tmp*b;

}
Пример #9
0
int main(int argc, char *argv[]) 
{
  if (argc<2) {
    cout << "\nUsage: " << argv[0] << " L [c=2 w=64 k=80 d=1]" << endl;
    cout << "  L is the number of levels\n";
    cout << "  optional c is number of columns in the key-switching matrices (default=2)\n";
    cout << "  optional w is Hamming weight of the secret key (default=64)\n";
    cout << "  optional k is the security parameter (default=80)\n";
    cout << "  optional d specifies GF(2^d) arithmetic (default=1, must be <=16)\n";
    //    cout << "  k is the security parameter\n";
    //    cout << "  m determines the ring mod Phi_m(X)" << endl;
    cout << endl;
    exit(0);
  }
  cout.unsetf(ios::floatfield);
  cout.precision(4);

  long L = atoi(argv[1]);
  long c = 2;
  long w = 64;
  long k = 80;
  long d = 1;
  if (argc>2) c = atoi(argv[2]);
  if (argc>3) w = atoi(argv[3]);
  if (argc>4) k = atoi(argv[4]);
  if (argc>5) d = atoi(argv[5]);

  if (d>16) Error("d cannot be larger than 16\n");

  cout << "\nTesting FHE with parameters L="<<L
       << ", c="<<c<<", w="<<w<<", k="<<k<<", d="<<d<< endl;

  // get a lower-bound on the parameter N=phi(m):
  // 1. Empirically, we use ~20-bit small primes in the modulus chain (the main
  //    constraints is that 2m must divide p-1 for every prime p). The first
  //    prime is larger, a 40-bit prime. (If this is a 32-bit machine then we
  //    use two 20-bit primes instead.)
  // 2. With L levels, the largest modulus for "fresh ciphertexts" has size
  //          q0 ~ p0 * p^{L} ~ 2^{40+20L}
  // 3. We break each ciphertext into upto c digits, do each digit is as large
  //    as    D=2^{(40+20L)/c}
  // 4. The added noise variance term from the key-switching operation is
  //    c*N*sigma^2*D^2, and this must be mod-switched down to w*N (so it is
  //    on part with the added noise from modulus-switching). Hence the ratio
  //    P that we use for mod-switching must satisfy c*N*sigma^2*D^2/P^2<w*N,
  //    or    P > sqrt(c/w) * sigma * 2^{(40+20L)/c}
  // 5. With this extra P factor, the key-switching matrices are defined
  //    relative to a modulus of size
  //          Q0 = q0*P ~ sqrt{c/w} sigma 2^{(40+20L)(1+1/c)}
  // 6. To get k-bit security we need N>log(Q0/sigma)(k+110)/7.2, i.e. roughly
  //          N > (40+20L)(1+1/c)(k+110) / 7.2

  long ptxtSpace = 2;
  double cc = 1.0+(1.0/(double)c);
  long N = (long) ceil((pSize*L+p0Size)*cc*(k+110)/7.2);
  cout << "  bounding phi(m) > " << N << endl;

#if 0  // A small m for debugging purposes
  long m = 15;
#else
  // pre-computed values of [phi(m),m,d]
  long ms[][4] = {
    //phi(m)  m  ord(2) c_m*1000
    { 1176,  1247, 28,  3736},
    { 1936,  2047, 11,  3870},
    { 2880,  3133, 24,  3254},
    { 4096,  4369, 16,  3422},
    { 5292,  5461, 14,  4160},
    { 5760,  8435, 24,  8935},
    { 8190,  8191, 13,  1273},
    {10584, 16383, 14,  8358},
    {10752, 11441, 48,  3607},
    {12000, 13981, 20,  2467},
    {11520, 15665, 24, 14916},
    {14112, 18415, 28, 11278},
    {15004, 15709, 22,  3867},
    {15360, 20485, 24, 12767},
 // {16384, 21845, 16, 12798},
    {17208 ,21931, 24, 18387},
    {18000, 18631, 25,  4208},
    {18816, 24295, 28, 16360},
    {19200, 21607, 40, 35633},
    {21168, 27305, 28, 15407},
    {23040, 23377, 48,  5292},
    {24576, 24929, 48,  5612},
    {27000, 32767, 15, 20021},
    {31104, 31609, 71,  5149},
    {42336, 42799, 21,  5952},
    {46080, 53261, 24, 33409},
    {49140, 57337, 39,  2608},
    {51840, 59527, 72, 21128},
    {61680, 61681, 40,  1273},
    {65536, 65537, 32,  1273},
    {75264, 82603, 56, 36484},
    {84672, 92837, 56, 38520}
  };

#if 0

  for (long i = 0; i < 25; i++) {
    long m = ms[i][1];
    PAlgebra alg(m);
    alg.printout();
    cout << "\n";
    // compute phi(m) directly
    long phim = 0;
    for (long j = 0; j < m; j++)
      if (GCD(j, m) == 1) phim++;

    if (phim != alg.phiM()) cout << "ERROR\n";
  }

  exit(0);


#endif



  // find the first m satisfying phi(m)>=N and d | ord(2) in Z_m^*
  long m = 0;
  for (unsigned i=0; i<sizeof(ms)/sizeof(long[3]); i++) 
    if (ms[i][0]>=N && (ms[i][2] % d) == 0) {
      m = ms[i][1];
      c_m = 0.001 * (double) ms[i][3];
      break;
    }
  if (m==0) Error("Cannot support this L,d combination");
#endif
  //  m = 257;
  FHEcontext context(m);
#if 0
  context.stdev = to_xdouble(0.5); // very low error
#endif
  activeContext = &context; // Mark this as the "current" context

  context.zMstar.printout();
  cout << endl;


  // Set the modulus chain

#if 1
  // The first 1-2 primes of total p0size bits
  #if (NTL_SP_NBITS > p0Size)
    AddPrimesByNumber(context, 1, 1UL<<p0Size); // add a single prime
  #else
    AddPrimesByNumber(context, 2, 1UL<<(p0Size/2)); // add two primes
  #endif
#endif

  // The next L primes, as small as possible
  AddPrimesByNumber(context, L);

  ZZ productOfCtxtPrimes = context.productOfPrimes(context.ctxtPrimes);
  double productSize = context.logOfProduct(context.ctxtPrimes);

  // might as well test that the answer is roughly correct
  cout << "  context.logOfProduct(...)-log(context.productOfPrimes(...)) = "
       << productSize-log(productOfCtxtPrimes) << endl;

  // calculate the size of the digits

  context.digits.resize(c);
  IndexSet s1;
#if 0
  for (long i=0; i<c-1; i++) context.digits[i] = IndexSet(i,i);
  context.digits[c-1] = context.ctxtPrimes / IndexSet(0,c-2);
  AddPrimesByNumber(context, 2, 1, true);
#else
  double sizeSoFar = 0.0;
  double maxDigitSize = 0.0;
  if (c>1) {   // break ciphetext into a few digits
    double dsize = productSize/c;  // initial estimate
    double target = dsize-(pSize/3.0);
    long idx = context.ctxtPrimes.first();
    for (long i=0; i<c-1; i++) { // compute next digit
      IndexSet s;
      while (idx <= context.ctxtPrimes.last() && sizeSoFar < target) {
        s.insert(idx);
	sizeSoFar += log((double)context.ithPrime(idx));
	idx = context.ctxtPrimes.next(idx);
      }
      context.digits[i] = s;
      s1.insert(s);
      double thisDigitSize = context.logOfProduct(s);
      if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
      cout << "  digit #"<<i+1<< " " <<s << ": size " << thisDigitSize << endl;
      target += dsize;
    }
    IndexSet s = context.ctxtPrimes / s1; // all the remaining primes
    context.digits[c-1] = s;
    double thisDigitSize = context.logOfProduct(s);
    if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
    cout << "  digit #"<<c<< " " <<s << ": size " << thisDigitSize << endl;
  }
  else { 
    maxDigitSize = context.logOfProduct(context.ctxtPrimes);
    context.digits[0] = context.ctxtPrimes;
  }

  // Add primes to the chain for the P factor of key-switching
  double sizeOfSpecialPrimes 
    = maxDigitSize + log(c/(double)w)/2 + log(context.stdev *2);

  AddPrimesBySize(context, sizeOfSpecialPrimes, true);
#endif

  cout << "* ctxtPrimes: " << context.ctxtPrimes 
       << ", log(q0)=" << context.logOfProduct(context.ctxtPrimes) << endl;
  cout << "* specialPrimes: " << context.specialPrimes
       << ", log(P)=" << context.logOfProduct(context.specialPrimes) << endl;

  for (long i=0; i<context.numPrimes(); i++) {
    cout << "  modulus #" << i << " " << context.ithPrime(i) << endl;
  }
  cout << endl;

  setTimersOn();
  const ZZX& PhimX = context.zMstar.PhimX(); // The polynomial Phi_m(X)
  long phim = context.zMstar.phiM();         // The integer phi(m)
  FHESecKey secretKey(context);
  const FHEPubKey& publicKey = secretKey;

#if 0 // Debug mode: use sk=1,2
  DoubleCRT newSk(to_ZZX(2), context);
  long id1 = secretKey.ImportSecKey(newSk, 64, ptxtSpace);
  newSk -= 1;
  long id2 = secretKey.ImportSecKey(newSk, 64, ptxtSpace);
#else
  long id1 = secretKey.GenSecKey(w,ptxtSpace); // A Hamming-weight-w secret key
  long id2 = secretKey.GenSecKey(w,ptxtSpace); // A second Hamming-weight-w secret key
#endif

  ZZX zero = to_ZZX(0);
//  Ctxt zeroCtxt(publicKey);

  /******************************************************************/
  /**                      TESTS BEGIN HERE                       ***/
  /******************************************************************/


  cout << "ptxtSpace = " << ptxtSpace << endl;

  GF2X G;          // G is the AES polynomial, G(X)= X^8 +X^4 +X^3 +X +1
  SetCoeff(G,8); SetCoeff(G,4); SetCoeff(G,3); SetCoeff(G,1); SetCoeff(G,0);
  GF2X X;
  SetX(X);
  
#if 1
  // code for rotations...

  {
    GF2X::HexOutput = 1;
    
    const PAlgebra& al = context.zMstar;
    const PAlgebraModTwo& al2 = context.modTwo;

    long ngens = al.numOfGens();
    long nslots = al.NSlots();
    DoubleCRT tmp(context);

    vector< vector< DoubleCRT > > maskTable;

    maskTable.resize(ngens);
    for (long i = 0; i < ngens; i++) {
      if (i==0 && al.SameOrd(i)) continue;
      long ord = al.OrderOf(i);
      maskTable[i].resize(ord+1, tmp);
      for (long j = 0; j <= ord; j++) {
        // initialize the mask that is 1 whenever
        // the ith coordinate is at least j

        vector<GF2X> maps, alphas, betas;

        al2.mapToSlots(maps, G); // Change G to X to get bits in the slots
        alphas.resize(nslots);

        for (long k = 0; k < nslots; k++) 
          if (coordinate(al, i, k) >= j)
               alphas[k] = 1;
          else alphas[k] = 0;

       GF2X ptxt;
       al2.embedInSlots(ptxt, alphas, maps);

       // Sanity-check, make sure that encode/decode works as expected
       al2.decodePlaintext(betas, ptxt, G, maps);
       for (long k = 0; k < nslots; k++) {
	 if (alphas[k] != betas[k]) {
	   cout << " Mask computation failed, i="<<i<<", j="<<j<<"\n";
	   return 0;
	 }
       }
       maskTable[i][j] = to_ZZX(ptxt);
      }
    }

  vector<GF2X> maps;
  al2.mapToSlots(maps, G);

  vector<GF2X> alphas(nslots);
  for (long i=0; i < nslots; i++) 
    random(alphas[i], 8); // random degree-7 polynomial mod 2

  for (long amt = 0; amt < 20; amt++) {

    cout << ".";

     GF2X ptxt;
     al2.embedInSlots(ptxt, alphas, maps);

     DoubleCRT pp(context);
     pp = to_ZZX(ptxt);

     rotate(pp, amt, maskTable);

     GF2X ptxt1 = to_GF2X(to_ZZX(pp));

     vector<GF2X> betas;
     al2.decodePlaintext(betas, ptxt1, G, maps);

     for (long i = 0; i < nslots; i++) {
       if (alphas[i] != betas[(i+amt)%nslots]) {
	 cout << " amt="<<amt<<" oops\n";
          return 0;
       }
     }
   }

   cout << "\n";

#if 0
  long ord0 = al.OrderOf(0);

  for (long i = 0; i < nslots; i++) {
    cout << alphas[i] << " ";
    if ((i+1) % (nslots/ord0) == 0) cout << "\n";
  }
 
  cout << "\n\n";
  cout << betas.size() << "\n";

  for (long i = 0; i < nslots; i++) {
    cout << betas[i] << " ";
    if ((i+1) % (nslots/ord0) == 0) cout << "\n";
  }
#endif


  return 0;
  

  }


#endif

  // an initial sanity check on noise estimates,
  // comparing the estimated variance to the actual average
  cout << "pk:"; checkCiphertext(publicKey.pubEncrKey, zero, secretKey);

  ZZX ptxt[6]; // first four are plaintext, last two are constants
  std::vector<Ctxt> ctxt(4, Ctxt(publicKey));

  // Initialize the plaintext and constants to random 0-1 polynomials
  for (size_t j=0; j<6; j++) {
    ptxt[j].rep.SetLength(phim);
    for (long i = 0; i < phim; i++)
      ptxt[j].rep[i] = RandomBnd(ptxtSpace);
    ptxt[j].normalize();

    if (j<4) { 
      publicKey.Encrypt(ctxt[j], ptxt[j], ptxtSpace);
      cout << "c"<<j<<":"; checkCiphertext(ctxt[j], ptxt[j], secretKey);
    }
  }

  // perform upto 2L levels of computation, each level computing:
  //    1. c0 += c1
  //    2. c1 *= c2            // L1' = max(L1,L2)+1
  //    3. c1.reLinearlize
  //    4. c2 *= p4
  //    5. c2.automorph(k)     // k is the first generator of Zm^* /(2)
  //    6. c2.reLinearlize
  //    7. c3 += p5
  //    8. c3 *= c0            // L3' = max(L3,L0,L1)+1
  //    9. c2 *= c3            // L2' = max(L2,L0+1,L1+1,L3+1)+1
  //   10. c0 *= c0            // L0' = max(L0,L1)+1
  //   11. c0.reLinearlize
  //   12. c2.reLinearlize
  //   13. c3.reLinearlize
  //
  // The levels of the four ciphertexts behave as follows:
  // 0, 0, 0, 0  =>  1, 1, 2, 1  =>  2, 3, 3, 2
  //             =>  4, 4, 5, 4  =>  5, 6, 6, 5
  //             =>  7, 7, 8, 7  =>  8,,9, 9, 10  => [...]
  //
  // We perform the same operations on the plaintext, and after each operation
  // we check that decryption still works, and print the curretn modulus and
  // noise estimate. We stop when we get the first decryption error, or when
  // we reach 2L levels (which really should not happen).

  zz_pContext zzpc;
  zz_p::init(ptxtSpace);
  zzpc.save();
  const zz_pXModulus F = to_zz_pX(PhimX);
  long g = context.zMstar.ZmStarGen(0); // the first generator in Zm*
  zz_pX x2g(g, 1);
  zz_pX p2;

  // generate a key-switching matrix from s(X^g) to s(X)
  secretKey.GenKeySWmatrix(/*powerOfS= */  1,
			   /*powerOfX= */  g,
			   0, 0,
			   /*ptxtSpace=*/  ptxtSpace);

  // generate a key-switching matrix from s^2 to s
  secretKey.GenKeySWmatrix(/*powerOfS= */  2,
			   /*powerOfX= */  1,
			   0, 0,
			   /*ptxtSpace=*/  ptxtSpace);

  // generate a key-switching matrix from s^3 to s
  secretKey.GenKeySWmatrix(/*powerOfS= */  3,
			   /*powerOfX= */  1,
			   0, 0,
			   /*ptxtSpace=*/  ptxtSpace);

  for (long lvl=0; lvl<2*L; lvl++) {
    cout << "=======================================================\n";
    ctxt[0] += ctxt[1];
    ptxt[0] += ptxt[1];
    PolyRed(ptxt[0], ptxtSpace, true);
    cout << "c0+=c1:  "; checkCiphertext(ctxt[0], ptxt[0], secretKey);

    ctxt[1].multiplyBy(ctxt[2]);
    ptxt[1] = (ptxt[1] * ptxt[2]) % PhimX;
    PolyRed(ptxt[1], ptxtSpace, true);
    cout << "c1*=c2:  "; checkCiphertext(ctxt[1], ptxt[1], secretKey);

    ctxt[2].multByConstant(ptxt[4]);
    ptxt[2] = (ptxt[2] * ptxt[4]) % PhimX;
    PolyRed(ptxt[2], ptxtSpace, true);
    cout <<  "c2*=p4:  "; checkCiphertext(ctxt[2], ptxt[2], secretKey);

    ctxt[2] >>= g;
    zzpc.restore();
    p2 = to_zz_pX(ptxt[2]);
    CompMod(p2, p2, x2g, F);
    ptxt[2] = to_ZZX(p2);
    cout << "c2>>="<<g<<":"; checkCiphertext(ctxt[2], ptxt[2], secretKey);

    ctxt[2].reLinearize();
    cout << "c2.relin:"; checkCiphertext(ctxt[2], ptxt[2], secretKey);

    ctxt[3].addConstant(ptxt[5]);
    ptxt[3] += ptxt[5];
    PolyRed(ptxt[3], ptxtSpace, true);
    cout << "c3+=p5:  "; checkCiphertext(ctxt[3], ptxt[3], secretKey);

    ctxt[3].multiplyBy(ctxt[0]);
    ptxt[3] = (ptxt[3] * ptxt[0]) % PhimX;
    PolyRed(ptxt[3], ptxtSpace, true);
    cout << "c3*=c0:  ";    checkCiphertext(ctxt[3], ptxt[3], secretKey);

    ctxt[0].square();
    ptxt[0] = (ptxt[0] * ptxt[0]) % PhimX;
    PolyRed(ptxt[0], ptxtSpace, true);
    cout << "c0*=c0:  ";    checkCiphertext(ctxt[0], ptxt[0], secretKey);

    ctxt[2].multiplyBy(ctxt[3]);
    ptxt[2] = (ptxt[2] * ptxt[3]) % PhimX;
    PolyRed(ptxt[2], ptxtSpace, true);
    cout << "c2*=c3:  ";    checkCiphertext(ctxt[2], ptxt[2], secretKey);
  }
  /******************************************************************/
  /**                       TESTS END HERE                        ***/
  /******************************************************************/
  cout << endl;
  return 0;
}
Пример #10
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];
    }
}
Пример #11
0
/**************************
//Paillier HE system
//len: length of params p,q
**************************/
void Paillier(int len=512){
  ZZ n, n2, p, q, g, lamda;
  ZZ p1, q1, p1q1;
  ZZ miu;
  
  ZZ m1, m2;
  ZZ BSm, HEm; //baseline and HE result
  ZZ c, c1, c2, cm1, cm2, r;

  //key gen
  start = std::clock();

  GenPrime(p, len);
  GenPrime(q, len);
  mul(n, p, q);
  mul(n2, n, n);

  sub(p1,p,1);
  sub(q1,q,1);
  GCD(lamda,p1,q1);
  mul(p1q1,p1,q1);
  div(lamda, p1q1, lamda);

  RandomBnd(g, n2);

  PowerMod(miu,g,lamda,n2);
  sub(miu, miu, 1);
  div(miu,miu,n); //should add 1?
  InvMod(miu, miu, n);
  
  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"Pailler Setup:"<< duration <<'\n';

  //Enc
  start = std::clock();
  RandomBnd(m1,n);
  RandomBnd(m2,n);

  RandomBnd(r,n); //enc m1
  PowerMod(c1, g,m1,n2);
  PowerMod(c2, r,n,n2);
  MulMod(cm1, c1,c2, n2);

  RandomBnd(r,n); //enc m2
  PowerMod(c1, g,m2,n2);
  PowerMod(c2, r,n,n2);
  MulMod(cm2, c1,c2, n2);

  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"Pailler Enc:"<< duration/2 <<'\n';

  //Evaluation
  start = std::clock();
  c=cm1;
  for(int i=0; i<TIMES; i++)
  	MulMod(c,c,cm2,n2);
  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"Pailler Eval:"<< duration <<'\n';

  //c=cm2;
  //Dec  
  start = std::clock();
  PowerMod(c,c,lamda,n2);
  sub(c,c,1);
  div(c,c,n); //should add 1?
  MulMod(HEm, c, miu, n);  

  duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  cout<<"Pailler Dec:"<< duration <<'\n';

  //baseline
  BSm=m1;
  for(int i=0; i<TIMES; i++)
  	AddMod(BSm,BSm,m2,n);

  assert(BSm==HEm);
}
Пример #12
0
int GCD(int a, int b) {
	//printf(">> %d %d\n", a, b);
	if (b==0) return a;
	else return GCD(b, a%b);
};
Пример #13
0
void main(void){
  printf("%d\n",GCD(6,12));
}
// static
bool CBitPatternTreeMethod::CalculateKernel(CMatrix< C_INT64 > & matrix,
    CMatrix< C_INT64 > & kernel,
    CVector< size_t > & rowPivot)
{
  // std::cout << matrix << std::endl;

  // Gaussian elimination
  size_t NumRows = matrix.numRows();
  size_t NumCols = matrix.numCols();

  assert(NumRows > 0);
  assert(NumCols > 0);

  // Initialize row pivots
  rowPivot.resize(NumRows);
  size_t * pPivot = rowPivot.array();

  for (size_t i = 0; i < NumRows; i++, pPivot++)
    {
      *pPivot = i;
    }

  CVector< size_t > RowPivot(rowPivot);

  CVector< C_INT64 > Identity(NumRows);
  Identity = 1;

  C_INT64 * pColumn = matrix.array();
  C_INT64 * pColumnEnd = pColumn + NumCols;

  C_INT64 * pActiveRow;
  C_INT64 * pActiveRowStart = pColumn;
  C_INT64 * pActiveRowEnd = pColumnEnd;

  C_INT64 * pRow;
  C_INT64 * pRowEnd = pColumn + matrix.size();

  C_INT64 * pCurrent;
  C_INT64 * pIdentity;

  CVector< C_INT64 > SwapTmp(NumCols);

  size_t CurrentRowIndex = 0;
  size_t CurrentColumnIndex = 0;
  size_t NonZeroIndex = 0;

  CVector< bool > IgnoredColumns(NumCols);
  IgnoredColumns = false;
  bool * pIgnoredColumn = IgnoredColumns.array();
  size_t IgnoredColumnCount = 0;

  // For each column
  for (; pColumn < pColumnEnd; ++pColumn, ++CurrentColumnIndex, ++pIgnoredColumn)
    {
      assert(CurrentColumnIndex == CurrentRowIndex + IgnoredColumnCount);

      // Find non zero entry in current column.
      pRow = pActiveRowStart + CurrentColumnIndex;
      NonZeroIndex = CurrentRowIndex;

      for (; pRow < pRowEnd; pRow += NumCols, ++NonZeroIndex)
        {
          if (*pRow != 0)
            break;
        }

      if (NonZeroIndex >= NumRows)
        {
          *pIgnoredColumn = true;
          IgnoredColumnCount++;

          continue;
        }

      if (NonZeroIndex != CurrentRowIndex)
        {
          // Swap rows
          memcpy(SwapTmp.array(), matrix[CurrentRowIndex], NumCols * sizeof(C_INT64));
          memcpy(matrix[CurrentRowIndex], matrix[NonZeroIndex], NumCols * sizeof(C_INT64));
          memcpy(matrix[NonZeroIndex], SwapTmp.array(), NumCols * sizeof(C_INT64));

          // Record pivot
          size_t tmp = RowPivot[CurrentRowIndex];
          RowPivot[CurrentRowIndex] = RowPivot[NonZeroIndex];
          RowPivot[NonZeroIndex] = tmp;

          C_INT64 TMP = Identity[CurrentRowIndex];
          Identity[CurrentRowIndex]  = Identity[NonZeroIndex];
          Identity[NonZeroIndex] = TMP;
        }

      if (*(pActiveRowStart + CurrentColumnIndex) < 0)
        {
          for (pRow = pActiveRowStart; pRow < pActiveRowEnd; ++pRow)
            {
              *pRow *= -1;
            }

          Identity[CurrentRowIndex] *= -1;
        }

      // For each row
      pRow = pActiveRowStart + NumCols;
      pIdentity = Identity.array() + CurrentRowIndex + 1;

      C_INT64 ActiveRowValue = *(pActiveRowStart + CurrentColumnIndex);
      *(pActiveRowStart + CurrentColumnIndex) = Identity[CurrentRowIndex];

      for (; pRow < pRowEnd; pRow += NumCols, ++pIdentity)
        {
          C_INT64 RowValue = *(pRow + CurrentColumnIndex);

          if (RowValue == 0)
            continue;

          *(pRow + CurrentColumnIndex) = 0;

          // compute GCD(*pActiveRowStart, *pRow)
          C_INT64 GCD1 = abs64(ActiveRowValue);
          C_INT64 GCD2 = abs64(RowValue);

          GCD(GCD1, GCD2);

          C_INT64 alpha = ActiveRowValue / GCD1;
          C_INT64 beta = RowValue / GCD1;

          // update rest of row
          pActiveRow = pActiveRowStart;
          pCurrent = pRow;
          *pIdentity *= alpha;

          GCD1 = abs64(*pIdentity);

          for (; pActiveRow < pActiveRowEnd; ++pActiveRow, ++pCurrent)
            {
              // Assert that we do not have a numerical overflow.
              assert(fabs(((C_FLOAT64) alpha) *((C_FLOAT64) * pCurrent) - ((C_FLOAT64) beta) *((C_FLOAT64) * pActiveRow)) < std::numeric_limits< C_INT64 >::max());

              *pCurrent = alpha * *pCurrent - beta * *pActiveRow;

              // We check that the row values do not have any common divisor.
              if (GCD1 > 1 &&
                  (GCD2 = abs64(*pCurrent)) > 0)
                {
                  GCD(GCD1, GCD2);
                }
            }

          if (GCD1 > 1)
            {
              *pIdentity /= GCD1;

              pActiveRow = pActiveRowStart;
              pCurrent = pRow;

              for (; pActiveRow < pActiveRowEnd; ++pActiveRow, ++pCurrent)
                {
                  *pCurrent /= GCD1;
                }
            }
        }

      pActiveRowStart += NumCols;
      pActiveRowEnd += NumCols;
      CurrentRowIndex++;
    }

  assert(CurrentColumnIndex == CurrentRowIndex + IgnoredColumnCount);
  assert(CurrentColumnIndex == NumCols);

  // std::cout << matrix << std::endl;
  // std::cout << IgnoredColumns << std::endl;
  // std::cout << Identity << std::endl;
  // std::cout << RowPivot << std::endl << std::endl;

  size_t KernelRows = NumRows;
  size_t KernelCols = NumRows + IgnoredColumnCount - NumCols;

  assert(KernelCols > 0);

  kernel.resize(KernelRows, KernelCols);

  CMatrix< C_INT64 > Kernel(KernelRows, KernelCols);
  Kernel = 0;

  C_INT64 * pKernelInt = Kernel.array();
  C_INT64 * pKernelIntEnd = pKernelInt + Kernel.size();

  pActiveRowStart = matrix[CurrentRowIndex];
  pActiveRowEnd = matrix[NumRows];

  // Null space matrix identity part
  pIdentity = Identity.array() + CurrentRowIndex;
  C_INT64 * pKernelColumn = Kernel.array();

  for (; pActiveRowStart < pActiveRowEnd; pActiveRowStart += NumCols, ++pKernelColumn, ++pIdentity)
    {
      pKernelInt = pKernelColumn;
      pIgnoredColumn = IgnoredColumns.array();

      pRow = pActiveRowStart;
      pRowEnd = pRow + NumCols;

      if (*pIdentity < 0)
        {
          *pIdentity *= -1;

          for (; pRow < pRowEnd; ++pRow, ++pIgnoredColumn)
            {
              if (*pIgnoredColumn)
                {
                  continue;
                }

              *pKernelInt = - *pRow;
              pKernelInt += KernelCols;
            }
        }
      else
        {
          for (; pRow < pRowEnd; ++pRow, ++pIgnoredColumn)
            {
              if (*pIgnoredColumn)
                {
                  continue;
                }

              *pKernelInt = *pRow;
              pKernelInt += KernelCols;
            }
        }
    }

  pIdentity = Identity.array() + CurrentRowIndex;
  pKernelInt = Kernel[CurrentRowIndex];

  for (; pKernelInt < pKernelIntEnd; pKernelInt += KernelCols + 1, ++pIdentity)
    {
      *pKernelInt = *pIdentity;
    }

  // std::cout << Kernel << std::endl;
  // std::cout << RowPivot << std::endl << std::endl;

  // Undo the reordering introduced by Gaussian elimination to the kernel matrix.
  pPivot = RowPivot.array();
  pRow = Kernel.array();
  pRowEnd = pRow + Kernel.size();

  for (; pRow < pRowEnd; ++pPivot, pRow += KernelCols)
    {
      memcpy(kernel[*pPivot], pRow, KernelCols * sizeof(C_INT64));
    }

  // std::cout << kernel << std::endl << std::endl;
  // std::cout << rowPivot << std::endl << std::endl;

  return true;
}
Пример #15
0
// TODO: Add the ability to set a maximum number of iterations
inline BigInt FindFactor
( const BigInt& n,
  Int a,
  const PollardRhoCtrl& ctrl )
{
    if( a == 0 || a == -2 )
        Output("WARNING: Problematic choice of Pollard rho shift");
    BigInt tmp, gcd;
    BigInt one(1);

    auto xAdvance =
      [&]( BigInt& x )
      {
        if( ctrl.numSteps == 1 )
        {
            // TODO: Determine if there is a penalty to x *= x
            /*
            tmp = x;
            tmp *= x;
            tmp += a;
            x = tmp;
            x %= n;
            */
            x *= x;
            x += a;
            x %= n;
        }
        else
        {
            PowMod( x, 2*ctrl.numSteps, n, x );
            x += a;
            x %= n;
        }
      };

    auto QAdvance =
      [&]( const BigInt& x, const BigInt& x2, BigInt& Q )
      {
        tmp = x2;
        tmp -= x;
        Q *= tmp;
        Q %= n;
      };

    Int gcdDelay = ctrl.gcdDelay;
    BigInt xi=ctrl.x0;
    BigInt x2i(xi);
    BigInt xiSave=xi, x2iSave=x2i;
    BigInt Qi(1);
    Int k=1, i=1; // it is okay for i to overflow since it is just for printing
    while( true )
    {
        // Advance xi once
        xAdvance( xi );

        // Advance x2i twice
        xAdvance( x2i );
        xAdvance( x2i );

        // Advance Qi
        QAdvance( xi, x2i, Qi );

        if( k >= gcdDelay )
        {
            GCD( Qi, n, gcd );
            if( gcd > one )
            {
                // NOTE: This was not suggested by Pollard's original paper
                if( gcd == n )
                {
                    if( gcdDelay == 1 )
                    {
                        RuntimeError("(x) converged before (x mod p) at i=",i);
                    }
                    else
                    {
                        if( ctrl.progress )
                            Output("Backtracking at i=",i);
                        i = Max( i-(gcdDelay+1), 0 );
                        gcdDelay = 1;
                        xi = xiSave;
                        x2i = x2iSave;
                    }
                }
                else
                {
                    if( ctrl.progress )
                        Output("Found factor ",gcd," at i=",i); 
                    return gcd;
                }
            }

            // NOTE: This was not suggested by Pollard's original paper
            k = 0;
            xiSave = xi;
            x2iSave = x2i;
            Qi = 1;
        }
        ++k;
        ++i;
    }
}
Пример #16
0
// Reduce plaintext space to a divisor of the original plaintext space
void Ctxt::reducePtxtSpace(long newPtxtSpace)
{
  long g = GCD(ptxtSpace, newPtxtSpace);
  assert (g>1);
  ptxtSpace = g;
}
Пример #17
0
bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod)
{
	assert(!equiv.IsNegative() && equiv < mod);

	Integer gcd = GCD(equiv, mod);
	if (gcd != Integer::One())
	{
		// the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv)
		if (p <= gcd && gcd <= max && IsPrime(gcd))
		{
			p = gcd;
			return true;
		}
		else
			return false;
	}

	BuildPrimeTable();

	if (p <= primeTable[primeTableSize-1])
	{
		word *pItr;

		--p;
		if (p.IsPositive())
			pItr = std::upper_bound(primeTable, primeTable+primeTableSize, p.ConvertToLong());
		else
			pItr = primeTable;

		while (pItr < primeTable+primeTableSize && *pItr%mod != equiv)
			++pItr;

		if (pItr < primeTable+primeTableSize)
		{
			p = *pItr;
			return p <= max;
		}

		p = primeTable[primeTableSize-1]+1;
	}

	assert(p > primeTable[primeTableSize-1]);

	if (mod.IsOdd())
		return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1);

	p += (equiv-p)%mod;

	if (p>max)
		return false;

	PrimeSieve sieve(p, max, mod);

	while (sieve.NextCandidate(p))
	{
		if (FastProbablePrimeTest(p) && IsPrime(p))
			return true;
	}

	return false;
}
Пример #18
0
// Encrypts plaintext, result returned in the ciphertext argument. The
// returned value is the plaintext-space for that ciphertext. When called
// with highNoise=true, returns a ciphertext with noise level~q/8.
long FHEPubKey::Encrypt(Ctxt &ctxt, const ZZX& ptxt, long ptxtSpace,
			bool highNoise) const
{
  FHE_TIMER_START;
  assert(this == &ctxt.pubKey);

  if (ptxtSpace != pubEncrKey.ptxtSpace) { // plaintext-space mistamtch
    ptxtSpace = GCD(ptxtSpace, pubEncrKey.ptxtSpace);
    if (ptxtSpace <= 1) Error("Plaintext-space mismatch on encryption");
  }

  // generate a random encryption of zero from the public encryption key
  ctxt = pubEncrKey;  // already an encryption of zero, just not a random one

  // choose a random small scalar r and a small random error vector e,
  // then set ctxt = r*pubEncrKey + ptstSpace*e + (ptxt,0)
  DoubleCRT e(context, context.ctxtPrimes);
  DoubleCRT r(context, context.ctxtPrimes);
  r.sampleSmall();

  for (size_t i=0; i<ctxt.parts.size(); i++) {  // add noise to all the parts
    ctxt.parts[i] *= r;

    if (highNoise && i == 0) {
      // we sample e so that coefficients are uniform over 
      // [-Q/(8*ptxtSpace)..Q/(8*ptxtSpace)]

      ZZ B;
      B = context.productOfPrimes(context.ctxtPrimes);
      B /= ptxtSpace;
      B /= 8;
      e.sampleUniform(B);
    }
    else { 
      e.sampleGaussian();
    }

    e *= ptxtSpace;
    ctxt.parts[i] += e;
  }

  // add in the plaintext
  // FIXME: This relies on the first part, ctxt[0], to have handle to 1
  if (ptxtSpace==2) ctxt.parts[0] += ptxt;

  else { // The general case of ptxtSpace>2: for a ciphertext
         // relative to modulus Q, we add ptxt * Q mod ptxtSpace.
    long QmodP = rem(context.productOfPrimes(ctxt.primeSet), ptxtSpace);
    ctxt.parts[0] += MulMod(ptxt,QmodP,ptxtSpace); // MulMod from module NumbTh
  }

  // fill in the other ciphertext data members
  ctxt.ptxtSpace = ptxtSpace;

  if (highNoise) {
    // hack: we set noiseVar to Q^2/8, which is just below threshold 
    // that will signal an error

    ctxt.noiseVar = xexp(2*context.logOfProduct(context.ctxtPrimes) - log(8.0));

  }
  else {
    // We have <skey,ctxt>= r*<skey,pkey> +p*(e0+e1*s) +m, where VAR(<skey,pkey>)
    // is recorded in pubEncrKey.noiseVar, VAR(ei)=sigma^2*phi(m), and VAR(s) is
    // determined by the secret-key Hamming weight (skHwt). 
    // VAR(r)=phi(m)/2, hence the expected size squared is bounded by:
    // E(X^2) <= pubEncrKey.noiseVar *phi(m) *stdev^2
    //                               + p^2*sigma^2 *phi(m) *(skHwt+1) + p^2
  
    long hwt = skHwts[0];
    xdouble phim = to_xdouble(context.zMStar.getPhiM());
    xdouble sigma2 = context.stdev * context.stdev;
    xdouble p2 = to_xdouble(ptxtSpace) * to_xdouble(ptxtSpace);
    ctxt.noiseVar = pubEncrKey.noiseVar*phim*0.5 
                    + p2*sigma2*phim*(hwt+1)*context.zMStar.get_cM() + p2;
  }
  return ptxtSpace;
}
Пример #19
0
void TranslateBetweenGrids
( const DistMatrix<T,MC,MR>& A, DistMatrix<T,MC,MR>& B ) 
{
    DEBUG_ONLY(CSE cse("copy::TranslateBetweenGrids [MC,MR]"))

    B.Resize( A.Height(), A.Width() );
    // Just need to ensure that each viewing comm contains the other team's
    // owning comm. Congruence is too strong.

    // Compute the number of process rows and columns that each process
    // needs to send to.
    const Int colStride = B.ColStride();
    const Int rowStride = B.RowStride();
    const Int colRank = B.ColRank();
    const Int rowRank = B.RowRank();
    const Int colStrideA = A.ColStride();
    const Int rowStrideA = A.RowStride();
    const Int colGCD = GCD( colStride, colStrideA );
    const Int rowGCD = GCD( rowStride, rowStrideA );
    const Int colLCM = colStride*colStrideA / colGCD;
    const Int rowLCM = rowStride*rowStrideA / rowGCD;
    const Int numColSends = colStride / colGCD;
    const Int numRowSends = rowStride / rowGCD;

    const Int colAlign = B.ColAlign();
    const Int rowAlign = B.RowAlign();
    const Int colAlignA = A.ColAlign();
    const Int rowAlignA = A.RowAlign();

    const bool inBGrid = B.Participating();
    const bool inAGrid = A.Participating();
    if( !inBGrid && !inAGrid )
        return;

    const Int maxSendSize =
        (A.Height()/(colStrideA*numColSends)+1) *
        (A.Width()/(rowStrideA*numRowSends)+1);

    // Translate the ranks from A's VC communicator to B's viewing so that
    // we can match send/recv communicators. Since A's VC communicator is not
    // necessarily defined on every process, we instead work with A's owning
    // group and account for row-major ordering if necessary.
    const int sizeA = A.Grid().Size();
    vector<int> rankMap(sizeA), ranks(sizeA);
    if( A.Grid().Order() == COLUMN_MAJOR )
    {
        for( int j=0; j<sizeA; ++j )
            ranks[j] = j;
    }
    else
    {
        // The (i,j) = i + j*colStrideA rank in the column-major ordering is
        // equal to the j + i*rowStrideA rank in a row-major ordering.
        // Since we desire rankMap[i+j*colStrideA] to correspond to process
        // (i,j) in A's grid's rank in this viewing group, ranks[i+j*colStrideA]
        // should correspond to process (i,j) in A's owning group. Since the
        // owning group is ordered row-major in this case, its rank is
        // j+i*rowStrideA. Note that setting
        // ranks[j+i*rowStrideA] = i+j*colStrideA is *NOT* valid.
        for( int i=0; i<colStrideA; ++i )
            for( int j=0; j<rowStrideA; ++j )
                ranks[i+j*colStrideA] = j+i*rowStrideA;
    }
    mpi::Translate
    ( A.Grid().OwningGroup(), sizeA, &ranks[0],
      B.Grid().ViewingComm(), &rankMap[0] );

    // Have each member of A's grid individually send to all numRow x numCol
    // processes in order, while the members of this grid receive from all
    // necessary processes at each step.
    Int requiredMemory = 0;
    if( inAGrid )
        requiredMemory += maxSendSize;
    if( inBGrid )
        requiredMemory += maxSendSize;
    vector<T> auxBuf( requiredMemory );
    Int offset = 0;
    T* sendBuf = &auxBuf[offset];
    if( inAGrid )
        offset += maxSendSize;
    T* recvBuf = &auxBuf[offset];

    Int recvRow = 0; // avoid compiler warnings...
    if( inAGrid )
        recvRow = Mod(Mod(A.ColRank()-colAlignA,colStrideA)+colAlign,colStride);
    for( Int colSend=0; colSend<numColSends; ++colSend )
    {
        Int recvCol = 0; // avoid compiler warnings...
        if( inAGrid )
            recvCol=Mod(Mod(A.RowRank()-rowAlignA,rowStrideA)+rowAlign,
                        rowStride);
        for( Int rowSend=0; rowSend<numRowSends; ++rowSend )
        {
            mpi::Request sendRequest;
            // Fire off this round of non-blocking sends
            if( inAGrid )
            {
                // Pack the data
                Int sendHeight = Length(A.LocalHeight(),colSend,numColSends);
                Int sendWidth = Length(A.LocalWidth(),rowSend,numRowSends);
                copy::util::InterleaveMatrix
                ( sendHeight, sendWidth,
                  A.LockedBuffer(colSend,rowSend),
                 numColSends, numRowSends*A.LDim(),
                  sendBuf, 1, sendHeight );
                // Send data
                const Int recvVCRank = recvRow + recvCol*colStride;
                const Int recvViewingRank = B.Grid().VCToViewing( recvVCRank );
                mpi::ISend
                ( sendBuf, sendHeight*sendWidth, recvViewingRank,
                  B.Grid().ViewingComm(), sendRequest );
            }
            // Perform this round of recv's
            if( inBGrid )
            {
                const Int sendColOffset = colAlignA;
                const Int recvColOffset =
                    (colSend*colStrideA+colAlign) % colStride;
                const Int sendRowOffset = rowAlignA;
                const Int recvRowOffset =
                    (rowSend*rowStrideA+rowAlign) % rowStride;

                const Int firstSendRow =
                    Mod( Mod(colRank-recvColOffset,colStride)+sendColOffset,
                         colStrideA );
                const Int firstSendCol =
                    Mod( Mod(rowRank-recvRowOffset,rowStride)+sendRowOffset,
                         rowStrideA );

                const Int colShift = Mod( colRank-recvColOffset, colStride );
                const Int rowShift = Mod( rowRank-recvRowOffset, rowStride );
                const Int numColRecvs = Length( colStrideA, colShift, colStride );
                const Int numRowRecvs = Length( rowStrideA, rowShift, rowStride );

                // Recv data
                // For now, simply receive sequentially. Until we switch to
                // nonblocking recv's, we won't be using much of the
                // recvBuf
                Int sendRow = firstSendRow;
                for( Int colRecv=0; colRecv<numColRecvs; ++colRecv )
                {
                    const Int sendColShift = Shift( sendRow, colAlignA, colStrideA ) + colSend*colStrideA;
                    const Int sendHeight = Length( A.Height(), sendColShift, colLCM );
                    const Int localColOffset = (sendColShift-B.ColShift()) / colStride;

                    Int sendCol = firstSendCol;
                    for( Int rowRecv=0; rowRecv<numRowRecvs; ++rowRecv )
                    {
                        const Int sendRowShift = Shift( sendCol, rowAlignA, rowStrideA ) + rowSend*rowStrideA;
                        const Int sendWidth = Length( A.Width(), sendRowShift, rowLCM );
                        const Int localRowOffset = (sendRowShift-B.RowShift()) / rowStride;

                        const Int sendVCRank = sendRow+sendCol*colStrideA;
                        mpi::Recv
                        ( recvBuf, sendHeight*sendWidth, rankMap[sendVCRank],
                          B.Grid().ViewingComm() );

                        // Unpack the data
                        copy::util::InterleaveMatrix
                        ( sendHeight, sendWidth,
                          recvBuf, 1, sendHeight,
                          B.Buffer(localColOffset,localRowOffset),
                          colLCM/colStride, (rowLCM/rowStride)*B.LDim() );

                        // Set up the next send col
                        sendCol = (sendCol + rowStride) % rowStrideA;
                    }
                    // Set up the next send row
                    sendRow = (sendRow + colStride) % colStrideA;
                }
            }
            // Ensure that this round of non-blocking sends completes
            if( inAGrid )
            {
                mpi::Wait( sendRequest );
                recvCol = (recvCol + rowStrideA) % rowStride;
            }
        }
        if( inAGrid )
            recvRow = (recvRow + colStrideA) % colStride;
    }
}
Пример #20
0
int GCD(int num1, int num2) {
    if ( num1 % num2 == 0)
        return num2;
    else
        return GCD( num2, num1 % num2);
}
Пример #21
0
static int LCMNomiCalculator( int n, int m )
{
	int gcd = GCD( n, m );
	return n/gcd;
}
Пример #22
0
void CRational::Normalize()
{
	const int gcd = GCD(abs(m_numerator), m_denominator);
	m_numerator /= gcd;
	m_denominator /= gcd;
}
Пример #23
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
}
Пример #24
0
int GCD(int a,int b)
{
    if(b==0)return a;
    else return GCD(b,a%b);
}
Пример #25
0
static CYTHON_INLINE struct ZZX* ZZX_gcd(struct ZZX* x, struct ZZX* y)
{
    struct ZZX* g = new ZZX();
    GCD(*g, *x, *y);
    return g;
}
Пример #26
0
ll GCD(ll a, ll b) { return b == 0 ? a : GCD(b, a%b); }
Пример #27
0
int main() {
    int a, b;
    printf("Input two numbers:\n");
    scanf("%d %d", &a, &b);
    printf("Greatest common divisor: %d\n", GCD(a, b));
}
Пример #28
0
static int LCM( int a, int b )
{
    return a * b / GCD( a, b );
}
static unsigned long LCM(unsigned long x, unsigned long y)
{
	unsigned long gcd = GCD(x, y);

	return (gcd == 0) ? 0 : ((x / gcd) * y);
}
Пример #30
0
int main(void) {
	int num1, num2, denom1, denom2, num3, denom3, isLoop = 1;
	char op, input[3], charContinue;
	printf("Welcome to the fraction calculator program!\n");
	while (isLoop == 1) {
		printf("Please insert the first numerator:\n");
		scanf("%s", input);
		num1 = atoi(input);
		fflush(NULL);
		printf("Please insert the first denominator:\n");
		scanf("%s", input);
		denom1 = atoi(input);
		fflush(NULL);
		printf("This gives us a fraction of %i/%i.\n", num1,denom1);

                printf("Please insert the second numerator:\n");
                scanf("%s", input);
		num2 = atoi(input);
                fflush(NULL);
                printf("Please insert the second denominator:\n");
                scanf("%s", input);
		denom2 = atoi(input);
                fflush(NULL);
		printf("This gives us a second fraction of %i/%i.\n", num2,denom2);
		printf("Please insert the operand for the computation: [+ or - or * or /]\n");
		scanf("%s", &op);
		switch(op) {
			case '+':
				printf("You have chosen addition.\n");
				if (denom1 != denom2) {
					denom3 = denom1 * denom2;
					num1 = num1 * denom2;
					num2 = num2 * denom1;
					num3 = num1 + num2;
					denom1 = denom3;
					denom2 = denom3;
				}
				else {
					denom3 = denom1;
					num3 = num1 + num2;
				}
				break;
			case '-':
				printf("You have chosen substraction.\n");
				if (denom1 != denom2) {
					denom3 = denom1 * denom2;
					num1 = num1 * denom2;
					num2 = num2 * denom1;
					num3 = num1 - num2;
					denom1 = denom3;
					denom2 = denom3;
				}
				else {
					denom3 = denom1;
					num3 = num1 - num2;
				}
				break;
			case '*':
				printf("You have chosen multiplication.\n");
				num3 = num1 * num2;
				denom3 = denom1 * denom2;		
				break;
			case '/':
				printf("You have chosen division.\n");
				num3 = num1 * denom2;
				denom3 = denom1 * num2;
				break;
		}
		printf("Thus, we have %i/%i %c %i/%i = %i/%i.\n",num1,denom1,op,num2,denom2,num3,denom3);
		printf("Would you like a simplified answer? [y/n]\n");
		scanf("%s", &charContinue);
		if (charContinue == 'y') {	
			int gcd;  
			gcd = GCD(num3,denom3);
			if (gcd != 0) {
				if (num3 == (num3 / gcd)) {
					printf("Your fraction could not be simplified any further.\n");
				}
				else {
					num3 = num3 / gcd;
					denom3 = denom3 / gcd;
					printf("Your simplified fraction is %i/%i.\n", num3, denom3);
				}
			}
			else {
				printf("Your simplified fraction is 0.\n");	
			}
		}
		printf("Would you like to continue? [y/n]\n");
		scanf("%s", &charContinue);
		if (charContinue != 'y') {
			printf("Goodbye!\n");
			isLoop = 0;
		}
	}
	return 0;
}