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); } }
void setHyperColumn(const Vec<T>& v, const CubeSlice<T>& s, long pos) { long m = s.getProd(1); long n = s.getDim(0); assert(pos >= 0 && pos < m); if (v.length() < n) n = v.length(); for (long i = 0; i < n; i++) s[pos + i*m] = v[i]; }
void setHyperColumn(const Vec<T>& v, const CubeSlice<T>& s, long pos, const T& val) { long m = s.getProd(1); long n = s.getDim(0); long n1 = n; assert(pos >= 0 && pos < m); if (v.length() < n) n1 = v.length(); const T* vp = &v[0]; T* sp = &s[0]; for (long i = 0; i < n1; i++) sp[pos + i*m] = vp[i]; for (long i = n1; i < n; i++) sp[pos + i*m] = val; }
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); } }