DoubleCRT& DoubleCRT::Op(const DoubleCRT &other, Fun fun, bool matchIndexSets) { if (dryRun) return *this; if (&context != &other.context) Error("DoubleCRT::Op: incompatible objects"); // Match the index sets, if needed if (matchIndexSets && !(map.getIndexSet() >= other.map.getIndexSet())) addPrimes(other.map.getIndexSet() / map.getIndexSet()); // This is expensive // If you need to mod-up the other, do it on a temporary scratch copy DoubleCRT tmp(context, IndexSet()); const IndexMap<vec_long>* other_map = &other.map; if (!(map.getIndexSet() <= other.map.getIndexSet())){ // Even more expensive tmp = other; tmp.addPrimes(map.getIndexSet() / other.map.getIndexSet()); other_map = &tmp.map; } const IndexSet& s = map.getIndexSet(); long phim = context.zMStar.getPhiM(); // add/sub/mul the data, element by element, modulo the respective primes for (long i = s.first(); i <= s.last(); i = s.next(i)) { long pi = context.ithPrime(i); vec_long& row = map[i]; const vec_long& other_row = (*other_map)[i]; for (long j = 0; j < phim; j++) row[j] = fun.apply(row[j], other_row[j], pi); } return *this; }
// Uses the "active context", run-time error if it is NULL SingleCRT::SingleCRT(): context(*activeContext) { IndexSet s = IndexSet(0, context.numPrimes()-1); // FIXME: maybe the default index set should be determined by context? map.insert(s); // default constructor for ZZX creates the zero polynomial }
// Uses the "active context", run-time error if it is NULL SingleCRT::SingleCRT(const ZZX&poly) : context(*activeContext) { IndexSet s = IndexSet(0, context.numPrimes()-1); // FIXME: maybe the default index set should be determined by context? map.insert(s); *this = poly; // convert polynomial to singleCRT representation }
void IRRewriter::visit(const Length *op) { if (op->indexSet.getKind() == IndexSet::Set) { Expr set = rewrite(op->indexSet.getSet()); if (set == op->indexSet.getSet()) { expr = op; } else { expr = Length::make(IndexSet(set)); } } else { expr = op; } }
// Find the IndexSet such that modDown to that set of primes makes the // additive term due to rounding into the dominant noise term void Ctxt::findBaseSet(IndexSet& s) const { if (getNoiseVar()<=0.0) { // an empty ciphertext s = context.ctxtPrimes; return; } assert(verifyPrimeSet()); bool halfSize = context.containsSmallPrime(); double addedNoise = log(modSwitchAddedNoiseVar())/2; double curNoise = log(getNoiseVar())/2; double firstNoise = context.logOfPrime(0); // remove special primes, if they are included in this->primeSet s = getPrimeSet(); if (!s.disjointFrom(context.specialPrimes)) { // scale down noise curNoise -= context.logOfProduct(context.specialPrimes); s.remove(context.specialPrimes); } if (curNoise<=2*addedNoise) return; // no need to mod down // if the first prime in half size, begin by removing it if (halfSize && s.contains(0)) { curNoise -= firstNoise; s.remove(0); } // while noise is larger than added term, scale down by the next prime while (curNoise>addedNoise && card(s)>1) { curNoise -= context.logOfPrime(s.last()); s.remove(s.last()); } if (halfSize) { // If noise is still too big, drop last big prime and insert half-size prime if (curNoise>addedNoise) { curNoise = firstNoise; s = IndexSet(0); } // Otherwise check if you can add back the half-size prime else if (curNoise+firstNoise <= addedNoise) { curNoise += firstNoise; s.insert(0); } } if (curNoise>addedNoise && log_of_ratio()>-0.5) cerr << "Ctxt::findBaseSet warning: already at lowest level\n"; }
// Modulus-switching down void Ctxt::modDownToLevel(long lvl) { long currentLvl; IndexSet targetSet; IndexSet currentSet = primeSet & context.ctxtPrimes; if (context.containsSmallPrime()) { currentLvl = 2*card(currentSet); if (currentSet.contains(0)) currentLvl--; // first prime is half the size if (lvl & 1) { // odd level, includes the half-size prime targetSet = IndexSet(0,(lvl-1)/2); } else { targetSet = IndexSet(1,lvl/2); } } else { currentLvl = card(currentSet); targetSet = IndexSet(0,lvl-1); // one prime per level } // If target is not below the current level, nothing to do if (lvl >= currentLvl && currentSet==primeSet) return; if (lvl >= currentLvl) { // just remove the special primes targetSet = currentSet; } // sanity-check: interval does not contain special primes assert(targetSet.disjointFrom(context.specialPrimes)); // may need to mod-UP to include the smallest prime if (targetSet.contains(0) && !currentSet.contains(0)) modUpToSet(targetSet); // adds the primes in targetSet / primeSet modDownToSet(targetSet); // removes the primes in primeSet / targetSet }
DoubleCRT::DoubleCRT(const ZZX& poly) : context(*activeContext), map(new DoubleCRTHelper(*activeContext)) { IndexSet s = IndexSet(0, context.numPrimes()-1); // FIXME: maybe the default index set should be determined by context? map.insert(s); if (dryRun) return; // convert the integer polynomial to FFT representation modulo the primes for (long i = s.first(); i <= s.last(); i = s.next(i)) { const Cmodulus &pi = context.ithModulus(i); pi.FFT(map[i], poly); // reduce mod pi and store FFT image } }
DoubleCRT::DoubleCRT(const FHEcontext &_context) : context(_context), map(new DoubleCRTHelper(_context)) { IndexSet s = IndexSet(0, context.numPrimes()-1); // FIXME: maybe the default index set should be determined by context? map.insert(s); if (dryRun) return; long phim = context.zMStar.getPhiM(); for (long i = s.first(); i <= s.last(); i = s.next(i)) { vec_long& row = map[i]; for (long j = 0; j < phim; j++) row[j] = 0; } }
//FIXME: both the reduction from powerful to the individual primes and // the CRT back to poly can be made more efficient void PowerfulDCRT::powerfulToZZX(ZZX& poly, const Vec<ZZ>& powerful, IndexSet set) const { zz_pBak bak; bak.save(); // backup NTL's current modulus if (empty(set)) set = IndexSet(0, pConvVec.length()-1); clear(poly); // poly.SetLength(powerful.length()); ZZ product = conv<ZZ>(1L); for (long i = set.first(); i <= set.last(); i = set.next(i)) { pConvVec[i].restoreModulus(); // long newPrime = zz_p::modulus(); HyperCube<zz_p> oneRowPwrfl(indexes.shortSig); conv(oneRowPwrfl.getData(), powerful); // reduce and convert to Vec<zz_p> zz_pX oneRowPoly; pConvVec[i].powerfulToPoly(oneRowPoly, oneRowPwrfl); CRT(poly, product, oneRowPoly); // NTL :-) } poly.normalize(); }
// If the IndexSet is omitted, default to all the primes in the chain void PowerfulDCRT::ZZXtoPowerful(Vec<ZZ>& out, const ZZX& poly, IndexSet set) const { if (empty(set)) set = IndexSet(0, pConvVec.length()-1); zz_pBak bak; bak.save(); // backup NTL's current modulus ZZ product = conv<ZZ>(1L); for (long i = set.first(); i <= set.last(); i = set.next(i)) { pConvVec[i].restoreModulus(); long newPrime = zz_p::modulus(); zz_pX oneRowPoly; conv(oneRowPoly, poly); // reduce mod p and convert to zz_pX HyperCube<zz_p> oneRowPwrfl(indexes.shortSig); pConvVec[i].polyToPowerful(oneRowPwrfl, oneRowPoly); if (i == set.first()) // just copy conv(out, oneRowPwrfl.getData()); else // CRT intVecCRT(out, product, oneRowPwrfl.getData(), newPrime); // in NumbTh product *= newPrime; } }
#include "ExtraKnuckles.h" const IndexSet pinkyIndices = IndexSet() /IndexRange(21,41); const IndexSet ringIndices = IndexSet() /IndexRange(42,62); const IndexSet middleIndices = IndexSet() /IndexRange(63,83); const IndexSet indexIndices = IndexSet() /IndexRange(84,104); const IndexSet baseIndices = IndexSet() /IndexRange(0,5); const IndexSet knuckleIndices = IndexSet() /IndexRange(3,11); const IndexSet tipIndices = IndexSet() /IndexRange(9,20); const IndexSet lowerGapIndices = IndexSet() /IndexRange(0,5); const IndexSet upperGapIndices = IndexSet() /IndexRange(9,14); const IndexSet blendIndices = IndexSet() /IndexRange(0,5); const IndexSet allFingerIndices = IndexSet() /IndexRange(21,41) /IndexRange(42,62) /IndexRange(63,83) /IndexRange(84,104); string ExtraKnuckles::getName() const { return "ExtraKnuckles"; } void ExtraKnuckles::initialize(){ ExtraKnuckles::initializeGui(); this->gui->autoSizeToFitWidgets(); final.load("models/mesh_ExtraKnuckles_final.ply");
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; }
#include "SwellingFingers.h" const IndexSet pinkyIndices = IndexSet() /IndexRange(21,41); const IndexSet ringIndices = IndexSet() /IndexRange(42,62); const IndexSet middleIndices = IndexSet() /IndexRange(63,83); const IndexSet indexIndices = IndexSet() /IndexRange(84,104); const IndexSet thumbIndices = IndexSet() /IndexRange(0,20); const IndexSet allFingerIndices = IndexSet() /IndexRange(21,41) /IndexRange(42,62) /IndexRange(63,83) /IndexRange(84,104) /IndexRange(0,20); const IndexSet knuckeIndices = IndexSet() /IndexRange(3,11); string SwellingFingers::getName() const { return "SwellingFingers"; } void SwellingFingers::initialize(){ timer = 0.0f; pulseSpeed = 7.0f; pulseGapWidth = 0.7f; swellAmt = 0.0f; swellPower = 0.03f;
static void Sample(This *t, Region *region) { csize_t setsize = SetSize; creal vol = ldexp(1., -region->div); real *x = t->frame, *f = x + t->rule.n*t->ndim; Set *first = t->rule.first, *last = t->rule.last, *s; Bounds *b, *B = region->bounds + t->ndim; Result *result = RegionResult(region), *res, *Res = result + t->ncomp; creal *errcoeff = t->rule.errcoeff; creal ratio = Sq(IndexSet(first,2)->gen[0]/ IndexSet(first,1)->gen[0]); ccount offset = 2*t->ndim*t->ncomp; count dim, rul, n, maxdim = 0; real maxrange = 0; for( b = region->bounds, dim = 0; b < B; ++b, ++dim ) { creal range = b->upper - b->lower; if( range > maxrange ) { maxrange = range; maxdim = dim; } } for( s = first; s <= last; NextSet(s) ) if( s->n ) x = ExpandFS(t, region->bounds, s->gen, x); DoSample(t, t->rule.n, t->frame, f); for( res = result; res < Res; ++res ) { real sum[nrules]; creal *f1 = f; creal base = *f1*2*(1 - ratio); real maxdiff = 0; count bisectdim = maxdim; for( dim = 0; dim < t->ndim; ++dim ) { creal *fp = f1 + t->ncomp; creal *fm = fp + t->ncomp; creal fourthdiff = fabs(base + ratio*(fp[0] + fm[0]) - (fp[offset] + fm[offset])); f1 = fm; if( fourthdiff > maxdiff ) { maxdiff = fourthdiff; bisectdim = dim; } } res->bisectdim = bisectdim; f1 = f++; Zap(sum); for( s = first; s <= last; NextSet(s) ) for( n = s->n; n; --n ) { creal fun = *f1; f1 += t->ncomp; for( rul = 0; rul < nrules; ++rul ) sum[rul] += fun*s->weight[rul]; } /* Search for the null rule, in the linear space spanned by two successive null rules in our sequence, which gives the greatest error estimate among all normalized (1-norm) null rules in this space. */ for( rul = 1; rul < nrules - 1; ++rul ) { real maxerr = 0; for( s = first; s <= last; NextSet(s) ) maxerr = Max(maxerr, fabs(sum[rul + 1] + s->scale[rul]*sum[rul])*s->norm[rul]); sum[rul] = maxerr; } res->avg = vol*sum[0]; res->err = vol*( (errcoeff[0]*sum[1] <= sum[2] && errcoeff[0]*sum[2] <= sum[3]) ? errcoeff[1]*sum[1] : errcoeff[2]*Max(Max(sum[1], sum[2]), sum[3]) ); } if( VERBOSE > 2 ) { Vector(char, out, 64*NDIM + 128*NCOMP); char *oe = out; count comp; cchar *msg = "\nRegion (" REALF ") - (" REALF ")"; for( b = region->bounds; b < B; ++b ) { oe += sprintf(oe, msg, b->lower, b->upper); msg = "\n (" REALF ") - (" REALF ")"; } for( res = result, comp = 0; res < Res; ++res ) oe += sprintf(oe, "\n[" COUNT "] " REAL " +- " REAL, ++comp, res->avg, res->err); Print(out); }
void DMRecon::processFeatures() { progress.status = RECON_FEATURES; if (progress.cancelled) return; SingleViewPtr refV = views[settings.refViewNr]; mve::BundleFile::FeaturePoints const & features = bundle->get_points(); /* select features that should be processed: take features only from master view for the moment */ std::cout<<"Started to process "<<features.size()<<" features."<<std::endl; log<<"Started to process "<<features.size()<<" features."<<std::endl; size_t success = 0, processed = 0; for (size_t i = 0; i < features.size() && !progress.cancelled; ++i) { bool useFeature = false; if (features[i].contains_view_id(settings.refViewNr)) useFeature = true; else { IndexSet::const_iterator id = neighViews.begin(); while (id != neighViews.end()) { if (features[i].contains_view_id(*id)) { useFeature = true; break; } ++id; } } if (!useFeature) continue; math::Vec3f featPos(features[i].pos); if (!refV->pointInFrustum(featPos)) { continue; } math::Vec2f pixPosF = refV->worldToScreen(featPos); int x = round(pixPosF[0]); int y = round(pixPosF[1]); float initDepth = (featPos - refV->camPos).norm(); PatchOptimization patch(views, settings, x, y, initDepth, 0.f, 0.f, neighViews, IndexSet()); patch.doAutoOptimization(); ++processed; float conf = patch.computeConfidence(); size_t index = y * this->width + x; if (conf == 0) { continue; } // optimization was successful: ++success; float depth = patch.getDepth(); math::Vec3f normal = patch.getNormal(); if (refV->confImg->at(index) < conf) { if (refV->confImg->at(index) <= 0) { ++progress.filled; } refV->depthImg->at(index) = depth; refV->normalImg->at(index, 0) = normal[0]; refV->normalImg->at(index, 1) = normal[1]; refV->normalImg->at(index, 2) = normal[2]; refV->dzImg->at(index, 0) = patch.getDzI(); refV->dzImg->at(index, 1) = patch.getDzJ(); refV->confImg->at(index) = conf; QueueData tmpData; tmpData.confidence = conf; tmpData.depth = depth; tmpData.dz_i = patch.getDzI(); tmpData.dz_j = patch.getDzJ(); tmpData.localViewIDs = patch.getLocalViewIDs(); tmpData.x = x; tmpData.y = y; prQueue.push(tmpData); } } std::cout << "Processed " << processed << " features, from which " << success << " succeeded optimization." << std::endl; log << "Processed " << processed << " features, from which " << success << " succeeded optimization." << std::endl; }