// Constructor: it is assumed that zms is already set with m>1 // If q == 0, then the current context is used template <class type> Cmod<type>:: Cmod(const PAlgebra &zms, const zz &qq, const zz &rt) { assert(zms.getM()>1); bool explicitModulus = true; if (qq == 0) { q = zp::modulus(); explicitModulus = false; } else q = qq; zMStar = &zms; root = rt; zz mm; mm = zms.getM(); m_inv = InvMod(mm, q); zz_pBak bak; if (explicitModulus) { bak.save(); // backup the current modulus context = BuildContext(q, NextPowerOfTwo(zms.getM()) + 1); context.restore(); // set NTL's current modulus to q } else context.save(); if (IsZero(root)) { // Find a 2m-th root of unity modulo q, if not given zp rtp; long e = 2*zms.getM(); FindPrimitiveRoot(rtp,e); // NTL routine, relative to current modulus if (IsZero(rtp)) // sanity check Error("Cmod::compRoots(): no 2m'th roots of unity mod q"); root = rep(rtp); } rInv = InvMod(root,q); // set rInv = root^{-1} mod q // Allocate memory (relative to current modulus that was defined above). // These objects will be initialized when anyone calls FFT/iFFT. zpx phimx_poly; conv(phimx_poly, zms.getPhimX()); powers = new zpx(); Rb = new fftrep(); Ra = new fftrep(); ipowers = new zpx(); iRb = new fftrep(); phimx = new zpxModulus(phimx_poly); scratch = new zpx(); }
// plaintextAutomorph: an auxilliary routine...maybe palce in NumbTh? // Compute b(X) = a(X^k) mod Phi_m(X). Result is calclated in the output b // "in place", so a should not alias b. template <class RX, class RXModulus> static void plaintextAutomorph(RX& b, const RX& a, long k, const PAlgebra& zMStar, const RXModulus& PhimX) { long m = zMStar.getM(); assert(zMStar.inZmStar(k)); b.SetLength(m); for (long j = 0; j < m; j++) b[j] = 0; long d = deg(a); // compute b(X) = a(X^k) mod (X^m-1) mulmod_precon_t precon = PrepMulModPrecon(k, m); for (long j = 0; j <= d; j++) b[MulModPrecon(j, k, m, precon)] = a[j]; // b[j*k mod m] = a[j] b.normalize(); rem(b, b, PhimX); // reduce modulo the m'th cyclotomic }
static void init_representatives(Vec<long>& representatives, long dim, const Vec<long>& mvec, const PAlgebra& zMStar) { assert(dim >= 0 && dim < mvec.length()); // special case if (dim >= LONG(zMStar.numOfGens())) { representatives.SetLength(1); representatives[0] = 1; return; } long m = mvec[dim]; long D = zMStar.OrderOf(dim); long g = InvMod(zMStar.ZmStarGen(dim) % m, m); representatives.SetLength(D); for (long i = 0; i < D; i++) representatives[i] = PowerMod(g, i, m); }
static void init_representatives(Vec<long>& representatives, long dim, const Vec<long>& mvec, const PAlgebra& zMStar) { //OLD: assert(dim >= 0 && dim < mvec.length()); helib::assertInRange(dim, 0l, mvec.length(), "Invalid argument: dim must be between 0 and mvec.length()"); // special case if (dim >= LONG(zMStar.numOfGens())) { representatives.SetLength(1); representatives[0] = 1; return; } long m = mvec[dim]; long D = zMStar.OrderOf(dim); long g = InvMod(zMStar.ZmStarGen(dim) % m, m); representatives.SetLength(D); for (long i = 0; i < D; i++) representatives[i] = PowerMod(g, i, m); }
// Constructor: it is assumed that zms is already set with m>1 // If q == 0, then the current context is used Cmodulus::Cmodulus(const PAlgebra &zms, long qq, long rt) { assert(zms.getM()>1); bool explicitModulus = true; if (qq == 0) { q = zz_p::modulus(); explicitModulus = false; } else q = qq; zMStar = &zms; root = rt; long mm; mm = zms.getM(); m_inv = InvMod(mm, q); zz_pBak bak; if (zms.getPow2()) { // special case when m is a power of 2 assert( explicitModulus ); bak.save(); RandomState state; SetSeed(conv<ZZ>("84547180875373941534287406458029")); // DIRT: this ensures the roots are deterministically generated // inside the zz_pContext constructor context = zz_pContext(INIT_USER_FFT, q); state.restore(); context.restore(); powers.set_ptr(new zz_pX); ipowers.set_ptr(new zz_pX); long k = zms.getPow2(); long phim = 1L << (k-1); assert(k <= zz_pInfo->MaxRoot); // rootTables get initialized 0..zz_pInfo->Maxroot #ifdef FHE_OPENCL altFFTInfo = MakeSmart<AltFFTPrimeInfo>(); InitAltFFTPrimeInfo(*altFFTInfo, *zz_pInfo->p_info, k-1); #endif long w0 = zz_pInfo->p_info->RootTable[0][k]; long w1 = zz_pInfo->p_info->RootTable[1][k]; powers->rep.SetLength(phim); powers_aux.SetLength(phim); for (long i = 0, w = 1; i < phim; i++) { powers->rep[i] = w; powers_aux[i] = PrepMulModPrecon(w, q); w = MulMod(w, w0, q); } ipowers->rep.SetLength(phim); ipowers_aux.SetLength(phim); for (long i = 0, w = 1; i < phim; i++) { ipowers->rep[i] = w; ipowers_aux[i] = PrepMulModPrecon(w, q); w = MulMod(w, w1, q); } return; } if (explicitModulus) { bak.save(); // backup the current modulus context = BuildContext(q, NextPowerOfTwo(zms.getM()) + 1); context.restore(); // set NTL's current modulus to q } else context.save(); if (root==0) { // Find a 2m-th root of unity modulo q, if not given zz_p rtp; long e = 2*zms.getM(); FindPrimitiveRoot(rtp,e); // NTL routine, relative to current modulus if (rtp==0) // sanity check Error("Cmod::compRoots(): no 2m'th roots of unity mod q"); root = rep(rtp); } rInv = InvMod(root,q); // set rInv = root^{-1} mod q // Allocate memory (relative to current modulus that was defined above). // These objects will be initialized when anyone calls FFT/iFFT. zz_pX phimx_poly; conv(phimx_poly, zms.getPhimX()); powers.set_ptr(new zz_pX); Rb.set_ptr(new fftRep); ipowers.set_ptr(new zz_pX); iRb.set_ptr(new fftRep); phimx.set_ptr(new zz_pXModulus1(zms.getM(), phimx_poly)); BluesteinInit(mm, conv<zz_p>(root), *powers, powers_aux, *Rb); BluesteinInit(mm, conv<zz_p>(rInv), *ipowers, ipowers_aux, *iRb); }
// Helper function CubeSignature::CubeSignature(const PAlgebra& alg): ndims(0) { Vec<long> _dims(INIT_SIZE, alg.numOfGens()); for (long i=0; i<(long)alg.numOfGens(); i++) _dims[i] = alg.OrderOf(i); initSignature(_dims); }
long coordinate(const PAlgebra& al, long i, long k) // returns ith coord of index k { return al.dLog(al.ith_rep(k))[i]; }