void recursiveEval(const CubeSlice<zz_p>& s, const Vec< copied_ptr<FFTHelper> >& multiEvalPoints, long d, zz_pX& tmp1, Vec<zz_p>& tmp2) { long numDims = s.getNumDims(); //OLD: assert(numDims > 0); helib::assertTrue(numDims > 0, "CubeSlice s has negative dimension number"); if (numDims > 1) { long dim0 = s.getDim(0); for (long i = 0; i < dim0; i++) recursiveEval(CubeSlice<zz_p>(s, i), multiEvalPoints, d+1, tmp1, tmp2); } long posBnd = s.getProd(1); for (long pos = 0; pos < posBnd; pos++) { getHyperColumn(tmp1.rep, s, pos); tmp1.normalize(); multiEvalPoints[d]->FFT(tmp1, tmp2); setHyperColumn(tmp2, s, pos); } }
// Get multiple layers of a Benes permutation network. Returns in out[i][j] // the shift amount to move item j in the i'th layer. Also isID[i]=true if // the i'th layer is the identity (i.e., contains only 0 shift amounts). void ColPerm::getBenesShiftAmounts(Vec<Permut>& out, Vec<bool>& isID, const Vec<long>& benesLvls) const { // Go over the columns one by one. For each column extract the columns // permutation, prepare a Benes network for it, and then for every layer // compute the shift amounts for this columns. long n = getDim(dim); // the permutations are over [0,n-1] // Allocate space out.SetLength(benesLvls.length()); isID.SetLength(benesLvls.length()); for (long k=0; k<benesLvls.length(); k++) { out[k].SetLength(getSize()); isID[k] = true; } Vec<long> col; col.SetLength(n); for (long slice_index = 0; slice_index < numSlices(dim); slice_index++) { ConstCubeSlice<long> slice(*this, slice_index, dim); for (long col_index = 0; col_index < slice.numCols(); col_index++) { getHyperColumn(col, slice, col_index); GeneralBenesNetwork net(col); // build a Benes network for this column // Sanity checks: width of network == n, // and sum of benesLvls entries == # of levels assert(net.getSize()==n); {long sum=0; for (long k=0; k<benesLvls.length(); k++) sum+=benesLvls[k]; assert(net.getNumLevels()==sum); } // Compute the layers of the collapased network for this column for (long lvl=0,k=0; k<benesLvls.length(); lvl += benesLvls[k], k++) { // Returns in col the shift amounts for this layer in the network, // restricted to this column. Also returns true if the returned // permutation is the idendity, false otherwise. bool id = collapseBenesLevels(col, net, lvl, benesLvls[k]); isID[k] = isID[k] && id; CubeSlice<long> oslice(out[k], getSig()); CubeSlice<long> osubslice(oslice, slice_index, dim); setHyperColumn(col, osubslice, col_index); } // next collapsed layer } // next column } // next slice }
void recursiveInterp(const CubeSlice<zz_p>& s, const Vec< copied_ptr<FFTHelper> >& multiEvalPoints, long d, zz_pX& tmp1, Vec<zz_p>& tmp2) { long numDims = s.getNumDims(); assert(numDims > 0); long posBnd = s.getProd(1); for (long pos = 0; pos < posBnd; pos++) { getHyperColumn(tmp2, s, pos); multiEvalPoints[d]->iFFT(tmp1, tmp2, false); // do not normalize setHyperColumn(tmp1.rep, s, pos, zz_p::zero()); } if (numDims > 1) { long dim0 = s.getDim(0); for (long i = 0; i < dim0; i++) recursiveInterp(CubeSlice<zz_p>(s, i), multiEvalPoints, d+1, tmp1, tmp2); } }
// 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); }
void recursiveEval(const CubeSlice<zz_p>& s, const Vec< Vec<zz_p> >& multiEvalPoints, long d, zz_pX& tmp1, Vec<zz_p>& tmp2) { long numDims = s.getNumDims(); assert(numDims > 0); if (numDims > 1) { long dim0 = s.getDim(0); for (long i = 0; i < dim0; i++) recursiveEval(CubeSlice<zz_p>(s, i), multiEvalPoints, d+1, tmp1, tmp2); } long posBnd = s.getProd(1); for (long pos = 0; pos < posBnd; pos++) { getHyperColumn(tmp1.rep, s, pos); tmp1.normalize(); eval(tmp2, tmp1, multiEvalPoints[d]); setHyperColumn(tmp2, s, pos); } }