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; } } }
// Euclid's algorithm int GCD(int x, int y) { if (y == 0) return x; return GCD(y, x%y); }
LL LCM(LL a, LL b) { return a * b / GCD(a, b); }
static int LCMDenoCalculator( int n, int m ) { int gcd = GCD( n, m ); return m/gcd; }
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; }
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; }
unsigned int LCM( unsigned int a, unsigned int b ) { unsigned int tmp=a/GCD(a,b); return tmp*b; }
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; }
// 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]; } }
/************************** //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); }
int GCD(int a, int b) { //printf(">> %d %d\n", a, b); if (b==0) return a; else return GCD(b, a%b); };
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; }
// 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; } }
// 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; }
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; }
// 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; }
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; } }
int GCD(int num1, int num2) { if ( num1 % num2 == 0) return num2; else return GCD( num2, num1 % num2); }
static int LCMNomiCalculator( int n, int m ) { int gcd = GCD( n, m ); return n/gcd; }
void CRational::Normalize() { const int gcd = GCD(abs(m_numerator), m_denominator); m_numerator /= gcd; m_denominator /= gcd; }
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 }
int GCD(int a,int b) { if(b==0)return a; else return GCD(b,a%b); }
static CYTHON_INLINE struct ZZX* ZZX_gcd(struct ZZX* x, struct ZZX* y) { struct ZZX* g = new ZZX(); GCD(*g, *x, *y); return g; }
ll GCD(ll a, ll b) { return b == 0 ? a : GCD(b, a%b); }
int main() { int a, b; printf("Input two numbers:\n"); scanf("%d %d", &a, &b); printf("Greatest common divisor: %d\n", GCD(a, b)); }
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); }
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; }