// This routine implements the isomorphism from // F_p[X]/(Phi_m(X)) to F_p[X_1, ..., X_k]/(Phi_{m_1}(X_1), ..., Phi_{m_k}(X_k)) // The input is poly, which must be of degree < m, and the // output is cube, which is a HyperCube of dimension (phi(m_1), ..., phi(m_k)). // The caller is responsible to supply "scratch space" in the // form of a HyperCube tmpCube of dimension (m_1, ..., m_k). void convertPolyToPowerful(HyperCube<zz_p>& cube, HyperCube<zz_p>& tmpCube, const zz_pX& poly, const Vec<zz_pX>& cycVec, const Vec<long>& polyToCubeMap, const Vec<long>& shortToLongMap) { long m = tmpCube.getSize(); long phim = cube.getSize(); long n = deg(poly); assert(n < m); for (long i = 0; i <= n; i++) tmpCube[polyToCubeMap[i]] = poly[i]; for (long i = n+1; i < m; i++) tmpCube[polyToCubeMap[i]] = 0; zz_pX tmp1, tmp2; recursiveReduce(CubeSlice<zz_p>(tmpCube), cycVec, 0, tmp1, tmp2); for (long i = 0; i < phim; i++) cube[i] = tmpCube[shortToLongMap[i]]; }
static void convertPolyToPowerful(HyperCube<zz_p>& cube, HyperCube<zz_p>& tmpCube, const zz_pX& poly, const Vec<zz_pXModulus>& cycVec, const Vec<long>& polyToCubeMap, const Vec<long>& shortToLongMap) { long m = tmpCube.getSize(); long phim = cube.getSize(); long n = deg(poly); //OLD: assert(n < m); helib::assertTrue(n < m, "Degree of polynomial poly must be less than size of the hypercube tmpCube"); for (long i = 0; i <= n; i++) tmpCube[polyToCubeMap[i]] = poly[i]; for (long i = n+1; i < m; i++) tmpCube[polyToCubeMap[i]] = 0; zz_pX tmp1, tmp2; recursiveReduce(CubeSlice<zz_p>(tmpCube), cycVec, 0, tmp1, tmp2); for (long i = 0; i < phim; i++) cube[i] = tmpCube[shortToLongMap[i]]; }
// This routine implements the isomorphism from F_p[X]/(Phi_m(X)) to // F_p[X_1, ..., X_k]/(Phi_{m_1}(X_1), ..., Phi_{m_k}(X_k)). The input // is a polynomial mod q, which must be of degree < m. The output is a // HyperCube of dimension (phi(m_1), ..., phi(m_k)). // // It is assumed that the current modulus is already set. // For convenience, this method returns the value of the modulus q. long PowerfulConversion::polyToPowerful(HyperCube<zz_p>& powerful, const zz_pX& poly) const { HyperCube<zz_p> tmpCube(getLongSig()); long n = deg(poly); //OLD: assert(n < indexes->m); helib::assertTrue(n < indexes->m, "Degree of polynomial poly is greater or equal than indexes->m"); for (long i = 0; i <= n; i++) tmpCube[indexes->polyToCubeMap[i]] = poly[i]; for (long i = n+1; i < indexes->m; i++) tmpCube[indexes->polyToCubeMap[i]] = 0; zz_pX tmp1, tmp2; recursiveReduce(CubeSlice<zz_p>(tmpCube), cycVec_p, 0, tmp1, tmp2); for (long i = 0; i < indexes->phim; i++) powerful[i] = tmpCube[indexes->shortToLongMap[i]]; return zz_p::modulus(); }
// This routine recursively reduces each hypercolumn // in dimension d (viewed as a coeff vector) by Phi_{m_d}(X) // If one starts with a cube of dimension (m_1, ..., m_k), // one ends up with a cube that is effectively of dimension // phi(m_1, ..., m_k). Viewed as an element of the ring // F_p[X_1,...,X_k]/(Phi_{m_1}(X_1), ..., Phi_{m_k}(X_k)), // the cube remains unchanged. static void recursiveReduce(const CubeSlice<zz_p>& s, const Vec<zz_pXModulus>& cycVec, long d, zz_pX& tmp1, zz_pX& tmp2) { long numDims = s.getNumDims(); //OLD: assert(numDims > 0); helib::assertTrue(numDims > 0l, "CubeSlice s has negative number of dimensions"); long deg0 = deg(cycVec[d]); long posBnd = s.getProd(1); for (long pos = 0; pos < posBnd; pos++) { getHyperColumn(tmp1.rep, s, pos); tmp1.normalize(); // tmp2 may not be normalized, so clear it first clear(tmp2); rem(tmp2, tmp1, cycVec[d]); // now pad tmp2.rep with zeros to length deg0... // tmp2 may not be normalized long len = tmp2.rep.length(); tmp2.rep.SetLength(deg0); for (long i = len; i < deg0; i++) tmp2.rep[i] = 0; setHyperColumn(tmp2.rep, s, pos); } if (numDims == 1) return; for (long i = 0; i < deg0; i++) recursiveReduce(CubeSlice<zz_p>(s, i), cycVec, d+1, tmp1, tmp2); }