void sampleGaussian(ZZX &poly, long n, double stdev) { static double const Pi=4.0*atan(1.0); // Pi=3.1415.. static long const bignum = 0xfffffff; // THREADS: C++11 guarantees these are initialized only once if (n<=0) n=deg(poly)+1; if (n<=0) return; poly.SetMaxLength(n); // allocate space for degree-(n-1) polynomial for (long i=0; i<n; i++) SetCoeff(poly, i, ZZ::zero()); // Uses the Box-Muller method to get two Normal(0,stdev^2) variables for (long i=0; i<n; i+=2) { double r1 = (1+RandomBnd(bignum))/((double)bignum+1); double r2 = (1+RandomBnd(bignum))/((double)bignum+1); double theta=2*Pi*r1; double rr= sqrt(-2.0*log(r2))*stdev; assert(rr < 8*stdev); // sanity-check, no more than 8 standard deviations // Generate two Gaussians RV's, rounded to integers long x = (long) floor(rr*cos(theta) +0.5); SetCoeff(poly, i, x); if (i+1 < n) { x = (long) floor(rr*sin(theta) +0.5); SetCoeff(poly, i+1, x); } } poly.normalize(); // need to call this after we work on the coeffs }
ZZX RandPoly(long n,const ZZ& p) { ZZX F; F.SetMaxLength(n); ZZ p2; p2=p>>1; for (long i=0; i<n; i++) { SetCoeff(F,i,RandomBnd(p)-p2); } return F; }
// multiply the polynomial f by the integer a modulo q void MulMod(ZZX& out, const ZZX& f, long a, long q, bool abs/*default=true*/) { // ensure that out has the same degree as f out.SetMaxLength(deg(f)+1); // allocate space if needed if (deg(out)>deg(f)) trunc(out,out,deg(f)+1); // remove high degrees for (int i=0; i<=deg(f); i++) { int c = rem(coeff(f,i), q); c = MulMod(c, a, q); // returns c \in [0,q-1] if (!abs && c >= q/2) c -= q; SetCoeff(out,i,c); } }
void sampleSmall(ZZX &poly, long n) { if (n<=0) n=deg(poly)+1; if (n<=0) return; poly.SetMaxLength(n); // allocate space for degree-(n-1) polynomial for (long i=0; i<n; i++) { // Chosse coefficients, one by one long u = lrand48(); if (u&1) { // with prob. 1/2 choose between -1 and +1 u = (u & 2) -1; SetCoeff(poly, i, u); } else SetCoeff(poly, i, 0); // with ptob. 1/2 set to 0 } poly.normalize(); // need to call this after we work on the coeffs }
void sampleHWt(ZZX &poly, long Hwt, long n) { if (n<=0) n=deg(poly)+1; if (n<=0) return; clear(poly); // initialize to zero poly.SetMaxLength(n); // allocate space for degree-(n-1) polynomial long b,u,i=0; if (Hwt>n) Hwt=n; while (i<Hwt) { // continue until exactly Hwt nonzero coefficients u=lrand48()%n; // The next coefficient to choose if (IsZero(coeff(poly,u))) { // if we didn't choose it already b = lrand48()&2; // b random in {0,2} b--; // random in {-1,1} SetCoeff(poly,u,b); i++; // count another nonzero coefficient } } poly.normalize(); // need to call this after we work on the coeffs }
void PolyRed(ZZX& out, const ZZX& in, long q, bool abs) { // ensure that out has the same degree as in out.SetMaxLength(deg(in)+1); // allocate space if needed if (deg(out)>deg(in)) trunc(out,out,deg(in)+1); // remove high degrees long q2; q2=q>>1; for (long i=0; i<=deg(in); i++) { long c=coeff(in,i)%q; if (abs) { if (c<0) { c=c+q; } } else if (q==2) { if (coeff(in,i)<0) { c=-c; } } else { if (c>=q2) { c=c-q; } else if (c<-q2) { c=c+q; } } SetCoeff(out,i,c); } }
void sampleUniform(ZZX& poly, const ZZ& B, long n) { if (n<=0) n=deg(poly)+1; if (n<=0) return; if (B <= 0) { clear(poly); return; } poly.SetMaxLength(n); // allocate space for degree-(n-1) polynomial ZZ UB, tmp; UB = 2*B + 1; for (long i = 0; i < n; i++) { RandomBnd(tmp, UB); tmp -= B; poly.rep[i] = tmp; } poly.normalize(); }
/* When q=2 maintains the same sign as the input */ void PolyRed(ZZX& out, const ZZX& in, const ZZ& q, bool abs) { // ensure that out has the same degree as in out.SetMaxLength(deg(in)+1); // allocate space if needed if (deg(out)>deg(in)) trunc(out,out,deg(in)+1); // remove high degrees ZZ q2; q2=q>>1; for (long i=0; i<=deg(in); i++) { ZZ c=coeff(in,i); c %= q; if (abs) { if (c<0) c += q; } else if (q!=2) { if (c>q2) { c=c-q; } else if (c<-q2) { c=c+q; } } else // q=2 { if (sign(coeff(in,i))!=sign(c)) { c=-c; } } SetCoeff(out,i,c); } }