Example #1
0
static
void LocalCopyReverse(zz_pX& x, const zz_pX& a, long lo, long hi)

   // x[0..hi-lo] = reverse(a[lo..hi]), with zero fill
   // input may not alias output

{
   long i, j, n, m;

   n = hi-lo+1;
   m = a.rep.length();

   x.rep.SetLength(n);

   const zz_p* ap = a.rep.elts();
   zz_p* xp = x.rep.elts();

   for (i = 0; i < n; i++) {
      j = hi-i;
      if (j < 0 || j >= m)
         clear(xp[i]);
      else
         xp[i] = ap[j];
   }

   x.normalize();
} 
Example #2
0
static
void LocalCyclicReduce(zz_pX& x, const zz_pX& a, long m)

// computes x = a mod X^m-1

{
   long n = deg(a);
   long i, j;
   zz_p accum;

   if (n < m) {
      x = a;
      return;
   }

   if (&x != &a)
      x.rep.SetLength(m);

   for (i = 0; i < m; i++) {
      accum = a.rep[i];
      for (j = i + m; j <= n; j += m)
         add(accum, accum, a.rep[j]);
      x.rep[i] = accum;
   }

   if (&x == &a)
      x.rep.SetLength(m);

   x.normalize();
}
void diff(zz_pX& x, const zz_pX& a)
{
   long n = deg(a);
   long i;

   if (n <= 0) {
      clear(x);
      return;
   }

   if (&x != &a)
      x.rep.SetLength(n);

   for (i = 0; i <= n-1; i++) {
      mul(x.rep[i], a.rep[i+1], i+1);
   }

   if (&x == &a)
      x.rep.SetLength(n);

   x.normalize();
}
void ShiftSub(zz_pX& U, const zz_pX& V, long n)
// assumes input does not alias output
{
   if (IsZero(V))
      return;

   long du = deg(U);
   long dv = deg(V);

   long d = max(du, n+dv);

   U.rep.SetLength(d+1);
   long i;

   for (i = du+1; i <= d; i++)
      clear(U.rep[i]);

   for (i = 0; i <= dv; i++)
      sub(U.rep[i+n], U.rep[i+n], V.rep[i]);

   U.normalize();
}
Example #5
0
// 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);

}
Example #6
0
void BluesteinInit(long n, const zz_p& root, zz_pX& powers, 
                   Vec<mulmod_precon_t>& powers_aux, fftRep& Rb)
{
  long p = zz_p::modulus();

  zz_p one; one=1;
  powers.SetMaxLength(n);

  SetCoeff(powers,0,one);
  for (long i=1; i<n; i++) {
    long iSqr = MulMod(i, i, 2*n); // i^2 mod 2n
    SetCoeff(powers,i, power(root,iSqr)); // powers[i] = root^{i^2}
  }

  // powers_aux tracks powers
  powers_aux.SetLength(n);
  for (long i = 0; i < n; i++)
    powers_aux[i] = PrepMulModPrecon(rep(powers[i]), p);


  long k = NextPowerOfTwo(2*n-1);
  long k2 = 1L << k; // k2 = 2^k

  Rb.SetSize(k);
  zz_pX b(INIT_SIZE, k2);

  zz_p rInv = inv(root);
  SetCoeff(b,n-1,one); // b[n-1] = 1
  for (long i=1; i<n; i++) {
    long iSqr = MulMod(i, i, 2*n); // i^2 mod 2n
    zz_p bi = power(rInv,iSqr);
    SetCoeff(b,n-1+i, bi); // b[n-1+i] = b[n-1-i] = root^{-i^2}
    SetCoeff(b,n-1-i,bi);              
  }

  TofftRep(Rb, b, k);
}
Example #7
0
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();
   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();
      multiEvalPoints[d]->FFT(tmp1, tmp2);
      setHyperColumn(tmp2, s, pos);
   }

}
Example #8
0
void Cmodulus::iFFT(zz_pX &x, const vec_long& y)const
{
  FHE_TIMER_START;
  zz_pBak bak; bak.save();
  context.restore();

  if (zMStar->getPow2()) {
    // special case when m is a power of 2

    long k = zMStar->getPow2();
    long phim = (1L << (k-1));
    long p = zz_p::modulus();

    const zz_p *ipowers_p = (*ipowers).rep.elts();
    const mulmod_precon_t *ipowers_aux_p = ipowers_aux.elts();

    const long *yp = y.elts();

    vec_long& tmp = Cmodulus::getScratch_vec_long();
    tmp.SetLength(phim);
    long *tmp_p = tmp.elts();

#ifdef FHE_OPENCL
    AltFFTRev1(tmp_p, yp, k-1, *altFFTInfo);
#else
    FFTRev1(tmp_p, yp, k-1, *zz_pInfo->p_info);
#endif

    x.rep.SetLength(phim);
    zz_p *xp = x.rep.elts();

    for (long i = 0; i < phim; i++)
      xp[i].LoopHole() = MulModPrecon(tmp_p[i], rep(ipowers_p[i]), p, ipowers_aux_p[i]);


    x.normalize();

    return;
  }



  zz_p rt;
  long m = getM();

  // convert input to zpx format, initializing only the coeffs i s.t. (i,m)=1
  x.rep.SetLength(m);
  long i,j;
  for (i=j=0; i<m; i++)
    if (zMStar->inZmStar(i)) x.rep[i].LoopHole() = y[j++]; // DIRT: y[j] already reduced
  x.normalize();
  conv(rt, rInv);  // convert rInv to zp format

  BluesteinFFT(x, m, rt, *ipowers, ipowers_aux, *iRb); // call the FFT routine

  // reduce the result mod (Phi_m(X),q) and copy to the output polynomial x
  { FHE_NTIMER_START(iFFT_division);
    rem(x, x, *phimx); // out %= (Phi_m(X),q)
  }

  // normalize
  zz_p mm_inv;
  conv(mm_inv, m_inv);
  x *= mm_inv; 
}