static long ZZ_remove(struct ZZ &dest, const struct ZZ &src, const struct ZZ &f) { // Based on the code for mpz_remove ZZ fpow[40]; // inexaustible...until year 2020 or so ZZ x, rem; long pwr; int p; if (compare(f, 1) <= 0 && compare(f, -1) >= 0) Error("Division by zero"); if (compare(src, 0) == 0) { if (src != dest) dest = src; return 0; } if (compare(f, 2) == 0) { dest = src; return MakeOdd(dest); } /* We could perhaps compute mpz_scan1(src,0)/mpz_scan1(f,0). It is an upper bound of the result we're seeking. We could also shift down the operands so that they become odd, to make intermediate values smaller. */ pwr = 0; fpow[0] = ZZ(f); dest = src; rem = ZZ(); x = ZZ(); /* Divide by f, f^2, ..., f^(2^k) until we get a remainder for f^(2^k). */ for (p = 0;;p++) { DivRem(x, rem, dest, fpow[p]); if (compare(rem, 0) != 0) break; fpow[p+1] = ZZ(); NTL::mul(fpow[p+1], fpow[p], fpow[p]); dest = x; } pwr = (1 << p) - 1; /* Divide by f^(2^(k-1)), f^(2^(k-2)), ..., f for all divisors that give a zero remainder. */ while (--p >= 0) { DivRem(x, rem, dest, fpow[p]); if (compare(rem, 0) == 0) { pwr += 1 << p; dest = x; } } return pwr; }
// trial division primitive void TrialDivision(vec_pair_ZZ_long& factors, ZZ& q, const ZZ& n, long bnd) { factors.SetLength(0); if (&q!=&n) q=n; if (bnd==0) { bnd=10000; // should probably be higher } PrimeSeq s; ZZ d; for (long p=s.next(); (p>0 && p<=bnd); p=s.next()) { if (DivRem(d,q,p)==0) { long e=1; q=d; while (DivRem(d,q,p)==0) { ++e; q=d; } addFactor(factors,to_ZZ(p),e); if (IsOne(q)) return; } if (d<=p) { // q must be prime addFactor(factors,q); set(q); return; } } }
bool BPMiniGame_JewelFlip::GemMatches(BPMiniGame_JewelFlip_Jewel* gem1, BPMiniGame_JewelFlip_Jewel* gem2) { int type = gem1->GemType; int position = Gems.IndexOf(gem2); int Row; int Col = DivRem(position, 7, Row); // try searching horizontally if (Col > 0) { // gem to the left if (AutoSubstituteGem(position - 7, gem1, gem2)->GemType == type) return true; } if (Col < 5) { // one to the right if (AutoSubstituteGem(position + 7, gem1, gem2)->GemType == type) return true; } // try searching vertically if (Row > 0) { // gem above if (AutoSubstituteGem(position - 1, gem1, gem2)->GemType == type) return true; } if (Row < 6) { // gem below if (AutoSubstituteGem(position + 1, gem1, gem2)->GemType == type) return true; } return false; }
void YASHE::roundMultiply(NTL::ZZ_pX& output, const NTL::ZZ_pX& a, const NTL::ZZ_pX& b) { // maximum is q^2 * (maxDegree + 1) NTL::ZZ_pPush push((cModulus * cModulus)/pModulus); NTL::ZZ_pX product; NTL::MulMod(product, a, b, bigCycloMod); output.SetLength(maxDegree + 1); NTL::ZZ quotient, remainder; for (long i = 0; i <= maxDegree; i++) { DivRem(quotient, remainder, pModulus * rep(product[i]), cModulus); // Rounding using remainder if (remainder * 2 > cModulus) { quotient += 1; } output[i] = NTL::conv<NTL::ZZ_p>(quotient); } }
void YASHE::roundMultiply(NTL::ZZ_pX& output, const NTL::ZZ_pXMultiplier& a, const NTL::ZZ_pXMultiplier& b) { // maximum is q^2 * (maxDegree + 1) NTL::ZZ_pPush push((cModulus * cModulus)/pModulus); long n = bigCycloMod.n; NTL::ZZ_pX product, P1(NTL::INIT_SIZE, n), P2(NTL::INIT_SIZE, n); NTL::FFTRep R1(NTL::INIT_SIZE, bigCycloMod.l), R2(NTL::INIT_SIZE, bigCycloMod.l); ToFFTRep(R1, a.val(), bigCycloMod.l); mul(R2, R1, b.B1); FromFFTRep(P1, R2, n-1, 2*n-3); mul(R1, a.B2, b.B2); ToFFTRep(R2, P1, bigCycloMod.k); mul(R2, R2, bigCycloMod.FRep); sub(R1, R1, R2); FromFFTRep(product, R1, 0, n-1); output.SetLength(maxDegree + 1); NTL::ZZ quotient, remainder; for (long i = 0; i <= maxDegree; i++) { DivRem(quotient, remainder, pModulus * rep(product[i]), cModulus); // Rounding using remainder if (remainder * 2 > cModulus) { quotient += 1; } output[i] = NTL::conv<NTL::ZZ_p>(quotient); } }
void div(RR& z, const RR& a, const RR& b) { if (IsZero(b)) Error("RR: division by zero"); if (IsZero(a)) { clear(z); return; } long la = NumBits(a.x); long lb = NumBits(b.x); long neg = (sign(a) != sign(b)); long k = RR::prec - la + lb + 1; if (k < 0) k = 0; static RR t; static ZZ A, B, R; abs(A, a.x); LeftShift(A, A, k); abs(B, b.x); DivRem(t.x, R, A, B); t.e = a.e - b.e - k; normalize(z, t, !IsZero(R)); if (neg) negate(z.x, z.x); }
long divide(const zz_pX& a, const zz_pX& b) { if (IsZero(b)) return IsZero(a); zz_pX lq, r; DivRem(lq, r, a, b); if (!IsZero(r)) return 0; return 1; }
void XGCD(zz_pX& d, zz_pX& s, zz_pX& t, const zz_pX& a, const zz_pX& b) { zz_p w; if (IsZero(a) && IsZero(b)) { clear(d); set(s); clear(t); return; } zz_pX U, V, Q; U = a; V = b; long flag = 0; if (deg(U) == deg(V)) { DivRem(Q, U, U, V); swap(U, V); flag = 1; } else if (deg(U) < deg(V)) { swap(U, V); flag = 2; } zz_pXMatrix M; XHalfGCD(M, U, V, deg(U)+1); d = U; if (flag == 0) { s = M(0,0); t = M(0,1); } else if (flag == 1) { s = M(0,1); mul(t, Q, M(0,1)); sub(t, M(0,0), t); } else { /* flag == 2 */ s = M(0,1); t = M(0,0); } // normalize inv(w, LeadCoeff(d)); mul(d, d, w); mul(s, s, w); mul(t, t, w); }
NTL_START_IMPL static void ExactDiv(ZZ& qq, const ZZ& a, const ZZ& b) { static ZZ q, r; DivRem(q, r, a, b); if (!IsZero(r)) { Error("ExactDiv: nonzero remainder"); } qq = q; }
void YASHE::roundDecrypt(NTL::ZZ& output, const NTL::ZZ_pX& a, const NTL::ZZ_pX& b) { NTL::ZZ_pX product = MulMod(a, b, cycloMod); NTL::ZZ quotient, remainder; DivRem(output, remainder, pModulus * rep(product[0]), cModulus); // Rounding using remainder if (remainder * 2 > cModulus) { output += 1; } }
void YASHE::radixDecomp(std::vector<NTL::ZZ> & output, const NTL::ZZ & input) { output.resize(decompSize); NTL::ZZ remainder; NTL::ZZ quotient, numerator; numerator = input; for (long i = 0; i < decompSize; i++) { DivRem(quotient, remainder, numerator, radix); output[i] = remainder; numerator = quotient; } }
static void BalDiv(ZZ& q, const ZZ& a, const ZZ& d) // rounds a/d to nearest integer, breaking ties // by rounding towards zero. Assumes d > 0. { static ZZ r; DivRem(q, r, a, d); add(r, r, r); long cmp = compare(r, d); if (cmp > 0 || (cmp == 0 && q < 0)) add(q, q, 1); }
void ResHalfGCD(zz_pX& U, zz_pX& V, vec_zz_p& cvec, vec_long& dvec) { long d_red = (deg(U)+1)/2; if (IsZero(V) || deg(V) <= deg(U) - d_red) { return; } long du = deg(U); long d1 = (d_red + 1)/2; if (d1 < 1) d1 = 1; if (d1 >= d_red) d1 = d_red - 1; zz_pXMatrix M1; ResHalfGCD(M1, U, V, d1, cvec, dvec); mul(U, V, M1); long d2 = deg(V) - du + d_red; if (IsZero(V) || d2 <= 0) { return; } M1(0,0).kill(); M1(0,1).kill(); M1(1,0).kill(); M1(1,1).kill(); zz_pX Q; append(cvec, LeadCoeff(V)); append(dvec, dvec[dvec.length()-1]-deg(U)+deg(V)); DivRem(Q, U, U, V); swap(U, V); ResHalfGCD(M1, U, V, d2, cvec, dvec); mul(U, V, M1); }
xdouble PowerOf10(const ZZ& e) { static NTL_CHEAP_THREAD_LOCAL long init = 0; static NTL_CHEAP_THREAD_LOCAL long k = 0; NTL_TLS_LOCAL(xdouble, v10k); if (!init) { k = ComputeMax10Power(); RRPush push; RR::SetPrecision(NTL_DOUBLE_PRECISION); v10k = to_xdouble(power(to_RR(10), k)); init = 1; } ZZ e1; long neg; if (e < 0) { e1 = -e; neg = 1; } else { e1 = e; neg = 0; } long r; ZZ q; r = DivRem(q, e1, k); RRPush push; RR::SetPrecision(NTL_DOUBLE_PRECISION); xdouble x1 = to_xdouble(power(to_RR(10), r)); xdouble x2 = power(v10k, q); xdouble x3 = x1*x2; if (neg) x3 = 1/x3; return x3; }
void YASHE::roundDecryptVec(NTL::ZZ_pX& output, const NTL::ZZ_pX& a, const NTL::ZZ_pX& b) { NTL::ZZ_pX product = MulMod(a, b, cycloMod); output.SetLength(maxDegree + 1); NTL::ZZ quotient, remainder; for (long i = 0; i <= maxDegree; i++) { DivRem(quotient, remainder, pModulus * rep(product[i]), cModulus); // Rounding using remainder if (remainder * 2 > cModulus) { quotient += 1; } output[i] = NTL::conv<NTL::ZZ_p>(quotient); } }
void HalfGCD(zz_pX& U, zz_pX& V) { long d_red = (deg(U)+1)/2; if (IsZero(V) || deg(V) <= deg(U) - d_red) { return; } long du = deg(U); long d1 = (d_red + 1)/2; if (d1 < 1) d1 = 1; if (d1 >= d_red) d1 = d_red - 1; zz_pXMatrix M1; HalfGCD(M1, U, V, d1); mul(U, V, M1); long d2 = deg(V) - du + d_red; if (IsZero(V) || d2 <= 0) { return; } M1(0,0).kill(); M1(0,1).kill(); M1(1,0).kill(); M1(1,1).kill(); zz_pX Q; DivRem(Q, U, U, V); swap(U, V); HalfGCD(M1, U, V, d2); mul(U, V, M1); }
NTL_START_IMPL long divide(zz_pX& q, const zz_pX& a, const zz_pX& b) { if (IsZero(b)) { if (IsZero(a)) { clear(q); return 1; } else return 0; } zz_pX lq, r; DivRem(lq, r, a, b); if (!IsZero(r)) return 0; q = lq; return 1; }
void myCRT::ComputeFactors(int f_degree, int f_size){ factors.SetLength(f_size); int s = 1<<f_degree; ZZ_pX list[s]; for(int i=0; i<s; i++) list[i] = to_ZZ_pX(num2ZZX(i+s)); int j=0; ZZ_pX t1 = modulus; ZZ_pX comp, remin, quo; SetCoeff(comp, 0, 0); for(int i=0; i<s; i++){ DivRem(quo, remin, t1, list[i]); if(remin == comp){ t1 = quo; factors[j] = list[i]; j++; } } size = factors.length(); }
// The recursive procedure in the Paterson-Stockmeyer // polynomial-evaluation algorithm from SIAM J. on Computing, 1973. // This procedure assumes that poly is monic, deg(poly)=k*(2t-1)+delta // with t=2^e, and that babyStep contains >= k+delta powers static void PatersonStockmeyer(Ctxt& ret, const ZZX& poly, long k, long t, long delta, DynamicCtxtPowers& babyStep, DynamicCtxtPowers& giantStep) { if (deg(poly)<=babyStep.size()) { // Edge condition, use simple eval simplePolyEval(ret, poly, babyStep); return; } ZZX r = trunc(poly, k*t); // degree <= k*2^e-1 ZZX q = RightShift(poly, k*t); // degree == k(2^e-1) +delta const ZZ p = to_ZZ(babyStep[0].getPtxtSpace()); const ZZ& coef = coeff(r,deg(q)); SetCoeff(r, deg(q), coef-1); // r' = r - X^{deg(q)} ZZX c,s; DivRem(c,s,r,q); // r' = c*q + s // deg(s)<deg(q), and if c!= 0 then deg(c)<k-delta assert(deg(s)<deg(q)); assert(IsZero(c) || deg(c)<k-delta); SetCoeff(s,deg(q)); // s' = s + X^{deg(q)}, deg(s)==deg(q) // reduce the coefficients modulo p for (long i=0; i<=deg(c); i++) rem(c[i],c[i], p); c.normalize(); for (long i=0; i<=deg(s); i++) rem(s[i],s[i], p); s.normalize(); // Evaluate recursively poly = (c+X^{kt})*q + s' PatersonStockmeyer(ret, q, k, t/2, delta, babyStep, giantStep); Ctxt tmp(ret.getPubKey(), ret.getPtxtSpace()); simplePolyEval(tmp, c, babyStep); tmp += giantStep.getPower(t); ret.multiplyBy(tmp); PatersonStockmeyer(tmp, s, k, t/2, delta, babyStep, giantStep); ret += tmp; }
void div(RR& z, const RR& a, const RR& b) { if (IsZero(b)) ArithmeticError("RR: division by zero"); if (IsZero(a)) { clear(z); return; } long la = NumBits(a.x); long lb = NumBits(b.x); long neg = (sign(a) != sign(b)); long k = RR::prec - la + lb + 1; if (k < 0) k = 0; NTL_TLS_LOCAL(RR, t); NTL_ZZRegister(A); NTL_ZZRegister(B); NTL_ZZRegister(R); abs(A, a.x); LeftShift(A, A, k); abs(B, b.x); DivRem(t.x, R, A, B); t.e = a.e - b.e - k; normalize(z, t, !IsZero(R)); if (neg) negate(z.x, z.x); }
int BPMiniGame_JewelFlip::RemoveGem(BPMiniGame_JewelFlip_Jewel* gem) { // remove this gem, then remove any others that touch it if (gem->Removed) return 0; // this has been removed already! gem->Removed = true; if (SelectedGem == gem) SelectedGem = NULL; int position = Gems.IndexOf(gem); int Row; int Col = DivRem(position, 7, Row); int num_removed = 1; // we've removed ourselves // remove the one above if (Row > 0) { if (Gems[position - 1]->GemType == gem->GemType) num_removed += RemoveGem(Gems[position - 1]); } // remove the one below if (Row < 6) { if (Gems[position + 1]->GemType == gem->GemType) num_removed += RemoveGem(Gems[position + 1]); } // remove the one to the left if (Col > 0) { if (Gems[position - 7]->GemType == gem->GemType) num_removed += RemoveGem(Gems[position - 7]); } // remove the one to the right if (Col < 5) { if (Gems[position + 7]->GemType == gem->GemType) num_removed += RemoveGem(Gems[position + 7]); } return num_removed; }
void ZZ_p::DoInstall() { SmartPtr<ZZ_pTmpSpaceT> tmps = 0; do { // NOTE: thread safe lazy init Lazy<ZZ_pFFTInfoT>::Builder builder(ZZ_pInfo->FFTInfo); if (!builder()) break; UniquePtr<ZZ_pFFTInfoT> FFTInfo; FFTInfo.make(); ZZ B, M, M1, M2, M3; long n, i; long q, t; mulmod_t qinv; sqr(B, ZZ_pInfo->p); LeftShift(B, B, NTL_FFTMaxRoot+NTL_FFTFudge); // FIXME: the following is quadratic time...would // be nice to get a faster solution... // One could estimate the # of primes by summing logs, // then multiply using a tree-based multiply, then // adjust up or down... // Assuming IEEE floating point, the worst case estimate // for error guarantees a correct answer +/- 1 for // numprimes up to 2^25...for sure we won't be // using that many primes...we can certainly put in // a sanity check, though. // If I want a more accuaruate summation (with using Kahan, // which has some portability issues), I could represent // numbers as x = a + f, where a is integer and f is the fractional // part. Summing in this representation introduces an *absolute* // error of 2 epsilon n, which is just as good as Kahan // for this application. // same strategy could also be used in the ZZX HomMul routine, // if we ever want to make that subquadratic set(M); n = 0; while (M <= B) { UseFFTPrime(n); q = GetFFTPrime(n); n++; mul(M, M, q); } FFTInfo->NumPrimes = n; FFTInfo->MaxRoot = CalcMaxRoot(q); double fn = double(n); if (8.0*fn*(fn+48) > NTL_FDOUBLE_PRECISION) ResourceError("modulus too big"); if (8.0*fn*(fn+48) <= NTL_FDOUBLE_PRECISION/double(NTL_SP_BOUND)) FFTInfo->QuickCRT = true; else FFTInfo->QuickCRT = false; // FIXME: some of this stuff does not need to be initialized // at all if FFTInfo->crt_struct.special() FFTInfo->x.SetLength(n); FFTInfo->u.SetLength(n); FFTInfo->uqinv.SetLength(n); FFTInfo->rem_struct.init(n, ZZ_pInfo->p, GetFFTPrime); FFTInfo->crt_struct.init(n, ZZ_pInfo->p, GetFFTPrime); if (!FFTInfo->crt_struct.special()) { ZZ qq, rr; DivRem(qq, rr, M, ZZ_pInfo->p); NegateMod(FFTInfo->MinusMModP, rr, ZZ_pInfo->p); for (i = 0; i < n; i++) { q = GetFFTPrime(i); qinv = GetFFTPrimeInv(i); long tt = rem(qq, q); mul(M2, ZZ_pInfo->p, tt); add(M2, M2, rr); div(M2, M2, q); // = (M/q) rem p div(M1, M, q); t = rem(M1, q); t = InvMod(t, q); mul(M3, M2, t); rem(M3, M3, ZZ_pInfo->p); FFTInfo->crt_struct.insert(i, M3); FFTInfo->x[i] = ((double) t)/((double) q); FFTInfo->u[i] = t; FFTInfo->uqinv[i] = PrepMulModPrecon(FFTInfo->u[i], q, qinv); } } tmps = MakeSmart<ZZ_pTmpSpaceT>(); tmps->crt_tmp_vec.fetch(FFTInfo->crt_struct); tmps->rem_tmp_vec.fetch(FFTInfo->rem_struct); builder.move(FFTInfo); } while (0); if (!tmps) { const ZZ_pFFTInfoT *FFTInfo = ZZ_pInfo->FFTInfo.get(); tmps = MakeSmart<ZZ_pTmpSpaceT>(); tmps->crt_tmp_vec.fetch(FFTInfo->crt_struct); tmps->rem_tmp_vec.fetch(FFTInfo->rem_struct); } ZZ_pTmpSpace = tmps; }
// This procedure assumes that poly is monic, deg(poly)=k*(2t-1)+delta // with t=2^e, and that babyStep contains k+delta powers static long PatersonStockmeyer(const ZZX& poly, long k, long t, long delta, DynamicPtxtPowers& babyStep, DynamicPtxtPowers& giantStep, long mod, long& recursiveDepth) { if (verbose) cerr << "PatersonStockmeyer("<<poly<<"), k="<<k<<", t="<<t<<endl; if (deg(poly)<=babyStep.size()) { // Edge condition, use simple eval long ret = simplePolyEval(poly, babyStep, mod); recursiveDepth = babyStep.getDepth(deg(poly)); return ret; } long subDepth1=0, subDepth2=0; long ret, tmp; ZZX r = trunc(poly, k*t); // degree <= k*2^e-1 ZZX q = RightShift(poly, k*t); // degree == k(2^e-1) +delta if (verbose) cerr << " r ="<<r<< ", q="<<q; const ZZ& coef = coeff(r,deg(q)); SetCoeff(r, deg(q), coef-1); // r' = r - X^{deg(q)} if (verbose) cerr << ", r'="<<r; ZZX c,s; DivRem(c,s,r,q); // r' = c*q + s // deg(s)<deg(q), and if c!= 0 then deg(c)<k-delta if (verbose) cerr << ", c="<<c<< ", s ="<<s<<endl; assert(deg(s)<deg(q)); assert(IsZero(c) || deg(c)<k-delta); SetCoeff(s,deg(q)); // s' = s + X^{deg(q)}, deg(s)==deg(q) // reduce the coefficients modulo mod for (long i=0; i<=deg(c); i++) rem(c[i],c[i], to_ZZ(mod)); c.normalize(); for (long i=0; i<=deg(s); i++) rem(s[i],s[i], to_ZZ(mod)); s.normalize(); if (verbose) cerr << " {t==n+1} recursing on "<<s<<" + (X^"<<t*k<<"+"<<c<<")*"<<q<<endl; // Evaluate recursively poly = (c+X^{kt})*q + s' tmp = simplePolyEval(c, babyStep, mod); tmp = AddMod(tmp, giantStep.getPower(t), mod); subDepth1 = max(babyStep.getDepth(deg(c)), giantStep.getDepth(t)); ret = PatersonStockmeyer(q, k, t/2, delta, babyStep, giantStep, mod, subDepth2); if (verbose) { cerr << " PatersonStockmeyer("<<q<<") returns "<<ret << ", depth="<<subDepth2<<endl; if (ret != polyEvalMod(q,babyStep[0], mod)) { cerr << " **1st recursive call failed, q="<<q<<endl; exit(0); } } ret = MulMod(ret, tmp, mod); nMults++; subDepth1 = max(subDepth1, subDepth2)+1; tmp = PatersonStockmeyer(s, k, t/2, delta, babyStep, giantStep, mod, subDepth2); if (verbose) { cerr << " PatersonStockmeyer("<<s<<") returns "<<tmp << ", depth="<<subDepth2<<endl; if (tmp != polyEvalMod(s,babyStep[0], mod)) { cerr << " **2nd recursive call failed, s="<<s<<endl; exit(0); } } ret = AddMod(ret,tmp,mod); recursiveDepth = max(subDepth1, subDepth2); return ret; }
void ZZ_pInfoT::init() { ZZ B, M, M1, M2, M3; long n, i; long q, t; initialized = 1; sqr(B, p); LeftShift(B, B, NTL_FFTMaxRoot+NTL_FFTFudge); set(M); n = 0; while (M <= B) { UseFFTPrime(n); q = FFTPrime[n]; n++; mul(M, M, q); } NumPrimes = n; MaxRoot = CalcMaxRoot(q); double fn = double(n); if (8.0*fn*(fn+32) > NTL_FDOUBLE_PRECISION) Error("modulus too big"); if (8.0*fn*(fn+32) > NTL_FDOUBLE_PRECISION/double(NTL_SP_BOUND)) QuickCRT = 0; else QuickCRT = 1; if (!(x = (double *) NTL_MALLOC(n, sizeof(double), 0))) Error("out of space"); if (!(u = (long *) NTL_MALLOC(n, sizeof(long), 0))) Error("out of space"); ZZ_p_rem_struct_init(&rem_struct, n, p, FFTPrime); ZZ_p_crt_struct_init(&crt_struct, n, p, FFTPrime); if (ZZ_p_crt_struct_special(crt_struct)) return; ZZ qq, rr; DivRem(qq, rr, M, p); NegateMod(MinusMModP, rr, p); for (i = 0; i < n; i++) { q = FFTPrime[i]; long tt = rem(qq, q); mul(M2, p, tt); add(M2, M2, rr); div(M2, M2, q); // = (M/q) rem p div(M1, M, q); t = rem(M1, q); t = InvMod(t, q); mul(M3, M2, t); rem(M3, M3, p); ZZ_p_crt_struct_insert(crt_struct, i, M3); x[i] = ((double) t)/((double) q); u[i] = t; } }
ostream& operator<<(ostream& s, const xdouble& a) { if (a == 0) { s << "0"; return s; } RRPush push; long temp_p = long(log(fabs(log(fabs(a))) + 1.0)/log(2.0)) + 10; RR::SetPrecision(temp_p); RR ln2, ln10, log_2_10; ComputeLn2(ln2); ComputeLn10(ln10); log_2_10 = ln10/ln2; ZZ log_10_a = to_ZZ( (to_RR(a.e)*to_RR(2*NTL_XD_HBOUND_LOG) + log(fabs(a.x))/log(2.0))/log_2_10); xdouble b; long neg; if (a < 0) { b = -a; neg = 1; } else { b = a; neg = 0; } ZZ k = xdouble::OutputPrecision() - log_10_a; xdouble c, d; c = PowerOf10(to_ZZ(xdouble::OutputPrecision())); d = PowerOf10(log_10_a); b = b / d; b = b * c; while (b < c) { b = b * 10.0; k++; } while (b >= c) { b = b / 10.0; k--; } b = b + 0.5; k = -k; ZZ B; conv(B, b); long bp_len = xdouble::OutputPrecision()+10; UniqueArray<char> bp_store; bp_store.SetLength(bp_len); char *bp = bp_store.get(); long len, i; len = 0; do { if (len >= bp_len) LogicError("xdouble output: buffer overflow"); bp[len] = IntValToChar(DivRem(B, B, 10)); len++; } while (B > 0); for (i = 0; i < len/2; i++) { char tmp; tmp = bp[i]; bp[i] = bp[len-1-i]; bp[len-1-i] = tmp; } i = len-1; while (bp[i] == '0') i--; k += (len-1-i); len = i+1; bp[len] = '\0'; if (k > 3 || k < -len - 3) { // use scientific notation if (neg) s << "-"; s << "0." << bp << "e" << (k + len); } else { long kk = to_long(k); if (kk >= 0) { if (neg) s << "-"; s << bp; for (i = 0; i < kk; i++) s << "0"; } else if (kk <= -len) { if (neg) s << "-"; s << "0."; for (i = 0; i < -len-kk; i++) s << "0"; s << bp; } else { if (neg) s << "-"; for (i = 0; i < len+kk; i++) s << bp[i]; s << "."; for (i = len+kk; i < len; i++) s << bp[i]; } } return s; }
bitstring Extractor::extract(bitstring w, bitstring x) { // cout <<"Extractor :: w.size = "<< w.size() <<" n size"<< n<<endl; // cout <<"Extractor :: x.size = "<< x.size() <<" d size"<< d<<endl; /*if (w.size() < (size_t)n) { throw invalid_argument("W has wrong size"); }*/ /*if (x.size() != (size_t)d) { //cout << "(extractor.cpp:215) TO_REMOVE:X has wrong size (Extractor) x="<< x.size() << "d="<< (size_t)d <<"\n" ; throw invalid_argument("X has wrong size (Extractor) "); }*/ // X to poly ZZ_pE xpoly; PolyFromBstr(xpoly,x,0); // W ZZ_pEX wpoly; ZZ_pE wpp[32]; for(int i=0; i<32; i++) { PolyFromBstr(wpp[i],w,32*i); ZZ_pEX temp(i,wpp[i]); wpoly += temp; } // geracao dos 4 f ZZ_pEX lixo; ZZ_pEX f1, f2, f4, f8; f1 = wpoly; DivRem(lixo, f1, f1, mod3232); f2 = f1 * f1; DivRem(lixo, f2, f2, mod3232); f4 = f2 * f2; DivRem(lixo, f4, f4, mod3232); f8 = f4 * f4; DivRem(lixo, f8, f8, mod3232); // f(y) ZZ_pE res0,res1,res2,res3; res0 = coeff(f1,0); res1 = coeff(f2,0); res2 = coeff(f4,0); res3 = coeff(f8,0); ZZ_pE aux = xpoly; for(int i=1; i<32; i++) { res0 += aux * coeff(f1,i); res1 += aux * coeff(f2,i); res2 += aux * coeff(f4,i); res3 += aux * coeff(f8,i); aux *= xpoly; } //cout << "RES: " << res0 << "(res0) " << res1 << "(res1) " << res2 << "(res2) " << res2 << "(res2) " << "\n"; bitstring result(128); ZZ_p one; one=1; for(int i = 0; i<32; i++) { if(coeff(rep(res0),i) == one) result.set(i); if(coeff(rep(res1),i) == one) result.set(i+32); if(coeff(rep(res2),i) == one) result.set(i+64); if(coeff(rep(res3),i) == one) result.set(i+96); } /*cout << "Result: "; result.print(); cout << "\n";*/ // retornar algo de tamanho 32, porque senao da erro de tamanho errado na entrada do extractor.. provavelmente devido a realimentacao //bitstring bla = x; //cout <<"bitstring output result = "<< result.to_string()<< endl; return result; }
void HalfGCD(zz_pXMatrix& M_out, const zz_pX& U, const zz_pX& V, long d_red) { if (IsZero(V) || deg(V) <= deg(U) - d_red) { set(M_out(0,0)); clear(M_out(0,1)); clear(M_out(1,0)); set(M_out(1,1)); return; } long n = deg(U) - 2*d_red + 2; if (n < 0) n = 0; zz_pX U1, V1; RightShift(U1, U, n); RightShift(V1, V, n); if (d_red <= NTL_zz_pX_HalfGCD_CROSSOVER) { IterHalfGCD(M_out, U1, V1, d_red); return; } long d1 = (d_red + 1)/2; if (d1 < 1) d1 = 1; if (d1 >= d_red) d1 = d_red - 1; zz_pXMatrix M1; HalfGCD(M1, U1, V1, d1); mul(U1, V1, M1); long d2 = deg(V1) - deg(U) + n + d_red; if (IsZero(V1) || d2 <= 0) { M_out = M1; return; } zz_pX Q; zz_pXMatrix M2; DivRem(Q, U1, U1, V1); swap(U1, V1); HalfGCD(M2, U1, V1, d2); zz_pX t(INIT_SIZE, deg(M1(1,1))+deg(Q)+1); mul(t, Q, M1(1,0)); sub(t, M1(0,0), t); swap(M1(0,0), M1(1,0)); swap(M1(1,0), t); t.kill(); t.SetMaxLength(deg(M1(1,1))+deg(Q)+1); mul(t, Q, M1(1,1)); sub(t, M1(0,1), t); swap(M1(0,1), M1(1,1)); swap(M1(1,1), t); t.kill(); mul(M_out, M2, M1); }
void XHalfGCD(zz_pXMatrix& M_out, zz_pX& U, zz_pX& V, long d_red) { if (IsZero(V) || deg(V) <= deg(U) - d_red) { set(M_out(0,0)); clear(M_out(0,1)); clear(M_out(1,0)); set(M_out(1,1)); return; } long du = deg(U); if (d_red <= NTL_zz_pX_HalfGCD_CROSSOVER) { IterHalfGCD(M_out, U, V, d_red); return; } long d1 = (d_red + 1)/2; if (d1 < 1) d1 = 1; if (d1 >= d_red) d1 = d_red - 1; zz_pXMatrix M1; HalfGCD(M1, U, V, d1); mul(U, V, M1); long d2 = deg(V) - du + d_red; if (IsZero(V) || d2 <= 0) { M_out = M1; return; } zz_pX Q; zz_pXMatrix M2; DivRem(Q, U, U, V); swap(U, V); XHalfGCD(M2, U, V, d2); zz_pX t(INIT_SIZE, deg(M1(1,1))+deg(Q)+1); mul(t, Q, M1(1,0)); sub(t, M1(0,0), t); swap(M1(0,0), M1(1,0)); swap(M1(1,0), t); t.kill(); t.SetMaxLength(deg(M1(1,1))+deg(Q)+1); mul(t, Q, M1(1,1)); sub(t, M1(0,1), t); swap(M1(0,1), M1(1,1)); swap(M1(1,1), t); t.kill(); mul(M_out, M2, M1); }
static CYTHON_INLINE void ZZX_quo_rem(struct ZZX* x, struct ZZX* other, struct ZZX** r, struct ZZX** q) { struct ZZX *qq = new ZZX(), *rr = new ZZX(); DivRem(*qq, *rr, *x, *other); *r = rr; *q = qq; }
void ResHalfGCD(ZZ_pXMatrix& M_out, const ZZ_pX& U, const ZZ_pX& V, long d_red, vec_ZZ_p& cvec, vec_long& dvec) { if (IsZero(V) || deg(V) <= deg(U) - d_red) { set(M_out(0,0)); clear(M_out(0,1)); clear(M_out(1,0)); set(M_out(1,1)); return; } long n = deg(U) - 2*d_red + 2; if (n < 0) n = 0; ZZ_pX U1, V1; RightShift(U1, U, n); RightShift(V1, V, n); if (d_red <= NTL_ZZ_pX_HalfGCD_CROSSOVER) { ResIterHalfGCD(M_out, U1, V1, d_red, cvec, dvec); return; } long d1 = (d_red + 1)/2; if (d1 < 1) d1 = 1; if (d1 >= d_red) d1 = d_red - 1; ZZ_pXMatrix M1; ResHalfGCD(M1, U1, V1, d1, cvec, dvec); mul(U1, V1, M1); long d2 = deg(V1) - deg(U) + n + d_red; if (IsZero(V1) || d2 <= 0) { M_out = M1; return; } ZZ_pX Q; ZZ_pXMatrix M2; append(cvec, LeadCoeff(V1)); append(dvec, dvec[dvec.length()-1]-deg(U1)+deg(V1)); DivRem(Q, U1, U1, V1); swap(U1, V1); ResHalfGCD(M2, U1, V1, d2, cvec, dvec); ZZ_pX t(INIT_SIZE, deg(M1(1,1))+deg(Q)+1); mul(t, Q, M1(1,0)); sub(t, M1(0,0), t); swap(M1(0,0), M1(1,0)); swap(M1(1,0), t); t.kill(); t.SetMaxLength(deg(M1(1,1))+deg(Q)+1); mul(t, Q, M1(1,1)); sub(t, M1(0,1), t); swap(M1(0,1), M1(1,1)); swap(M1(1,1), t); t.kill(); mul(M_out, M2, M1); }