예제 #1
0
static void recursiveInterpolateMod(ZZX& poly, const vec_long& x, vec_long& y,
				    const vec_zz_p& xmod, vec_zz_p& ymod,
				    long p, long p2e)
{
  if (p2e<=1) { // recursion edge condition, mod-1 poly = 0
    clear(poly);
    return;
  }

  // convert y input to zz_p
  for (long j=0; j<y.length(); j++) ymod[j] = to_zz_p(y[j] % p);

  // a polynomial p_i s.t. p_i(x[j]) = i'th p-base digit of poly(x[j])
  zz_pX polyMod;
  interpolate(polyMod, xmod, ymod);    // interpolation modulo p
  ZZX polyTmp; conv(polyTmp, polyMod); // convert to ZZX

  // update ytmp by subtracting the new digit, then dividing by p
  for (long j=0; j<y.length(); j++) {
    y[j] -= polyEvalMod(polyTmp,x[j],p2e); // mod p^e
    if (y[j]<0) y[j] += p2e;
// if (y[j] % p != 0) {
//   cerr << "@@error (p2^e="<<p2e<<"): y["<<j<<"] not divisible by "<<p<< endl;
//   exit(0);
// }
    y[j] /= p;
  } // maybe it's worth optimizing above by using multi-point evaluation

  // recursive call to get the solution of poly'(x)=y mod p^{e-1}
  recursiveInterpolateMod(poly, x, y, xmod, ymod, p, p2e/p);

  // return poly = p*poly' + polyTmp
  poly *= p;
  poly += polyTmp;
}
예제 #2
0
파일: PAlgebraMod.cpp 프로젝트: dwu4/fhe-si
NTL_CLIENT

#include <algorithm>   // defines count(...), min(...)
#include <iostream>

#include "NumbTh.h"
#include "PAlgebra.h"


// Generate the representation of Z[X]/(Phi_m(X),2) for the odd integer m
void PAlgebraModTwo::init(unsigned m)
{
  if (m == zmStar.M()) return; // nothign to do

  ((PAlgebra&)zmStar).init(m); // initialize the structure of (Z/mZ)*, if needed
  if (zmStar.M()==0 || zmStar.NSlots()==0) return; // error in zmStar
  unsigned nSlots = zmStar.NSlots();

  // Next compute the factors Ft of Phi_m(X) mod 2, for all t \in T

  //  GF2X PhimXmod = to_GF2X(zmStar.PhimX()); // Phi_m(X) mod 2
  PhimXmod = to_GF2X(zmStar.PhimX()); // Phi_m(X) mod 2

  EDF(factors, PhimXmod, zmStar.OrdTwo()); // equal-degree factorization

  // It is left to order the factors according to their representatives

  GF2XModulus F1(factors[0]); // We arbitrarily choose factors[0] as F1
  for (unsigned i=1; i<nSlots; i++) {
    unsigned t = zmStar.ith_rep(i); // Ft is minimal polynomial of x^{1/t} mod F1
    unsigned tInv = rep(inv(to_zz_p(t))); // tInv = t^{-1} mod m
    GF2X X2tInv = PowerXMod(tInv,F1);     // X2tInv = X^{1/t} mod F1
    IrredPolyMod(factors[i], X2tInv, F1);
  }
  /* Debugging sanity-check #1: we should have Ft= GCD(F1(X^t),Phi_m(X))
  GF2XModulus Pm2(PhimXmod);
  for (i=1; i<nSlots; i++) {
    unsigned t = T[i];
    GF2X X2t = PowerXMod(t,PhimXmod);  // X2t = X^t mod Phi_m(X)
    GF2X Ft = GCD(CompMod(F1,X2t,Pm2),Pm2);
    if (Ft != factors[i]) {
      cout << "Ft != F1(X^t) mod Phi_m(X), t=" << t << endl;
      exit(0);
    }
  }*******************************************************************/

  // Compute the CRT coefficients for the Ft's
  crtCoeffs.SetLength(nSlots);
  for (unsigned i=0; i<nSlots; i++) {
    GF2X te = PhimXmod / factors[i]; // \prod_{j\ne i} Fj
    te %= factors[i];              // \prod_{j\ne i} Fj mod Fi
    InvMod(crtCoeffs[i], te, factors[i]);// \prod_{j\ne i} Fj^{-1} mod Fi
  }
}
예제 #3
0
// Interpolate the integer polynomial such that poly(x[i] mod p)=y[i] (mod p^e)
// It is assumed that the points x[i] are all distinct modulo p
void interpolateMod(ZZX& poly, const vec_long& x, const vec_long& y,
		    long p, long e)
{
  poly = ZZX::zero();       // initialize to zero
  long p2e = power_long(p,e); // p^e

  vec_long ytmp(INIT_SIZE, y.length()); // A temporary writable copy
  for (long j=0; j<y.length(); j++) {
    ytmp[j] = y[j] % p2e;
    if (ytmp[j] < 0) ytmp[j] += p2e;
  }

  zz_pBak bak; bak.save();    // Set the current modulus to p
  zz_p::init(p);

  vec_zz_p xmod(INIT_SIZE, x.length()); // convert to zz_p
  for (long j=0; j<x.length(); j++) xmod[j] = to_zz_p(x[j] % p);

  vec_zz_p ymod(INIT_SIZE, y.length()); // scratch space
  recursiveInterpolateMod(poly, x, ytmp, xmod, ymod, p, p2e);
}