// recursive factoring (precondition: n composite) // currently only uses ECM void factor_r(vec_pair_ZZ_long& factors, const ZZ& _n, const ZZ& bnd, double failure_prob, bool verbose) { ZZ q; ZZ n(_n); do { // attempt to factor n if (bnd>0) ECM(q,n,bnd,failure_prob,verbose); else ECM(q,n,ZZ::zero(),0,verbose); if (IsOne(q)) { // give up addFactor(factors,n); return; } // compute other factor div(n,n,q); if (n<q) swap(n,q); // q is small factor, n is large factor if (ProbPrime_notd(q)) addFactor(factors,q); else factor_r(factors,q,bnd,failure_prob,verbose); // check if n is still composite if (ProbPrime_notd(n)) { addFactor(factors,n); return; } } while (true); }
// 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; } } }
// general purpose factoring method void factor(vec_pair_ZZ_long& factors, const ZZ& _n, const ZZ& bnd, double failure_prob, bool verbose) { ZZ n(_n); if (n<=1) { abs(n,n); if (n<=1) { factors.SetLength(0); return; } } // upper bound on size of smallest prime factor ZZ upper_bound; SqrRoot(upper_bound,n); if (bnd>0 && bnd<upper_bound) upper_bound=bnd; // figure out appropriate lower_bound for trial division long B1,B2,D; double prob; ECM_parameters(B1,B2,prob,D,NumBits(upper_bound),NumBits(n)); ZZ lower_bound; conv(lower_bound,max(B2,1<<14)); if (lower_bound>upper_bound) lower_bound=upper_bound; // start factoring with trial division TrialDivision(factors,n,n,to_long(lower_bound)); if (IsOne(n)) return; if (upper_bound<=lower_bound || ProbPrime_notd(n)) { addFactor(factors,n); return; } /* n is composite and smallest prime factor is assumed to be such that * lower_bound < factor <= upper_bound * * Ramp-up to searching for factors of size upper_bound. This is a good * idea in cases where we have no idea what size factors N might have, * but we don't want to spend too much time doing this. */ for(lower_bound<<=4; lower_bound<upper_bound; lower_bound<<=4) { ZZ q; ECM(q,n,lower_bound,1,verbose); // one curve only if (!IsOne(q)) { div(n,n,q); if (n<q) swap(n,q); // q is small factor, n is large factor if (ProbPrime_notd(q)) addFactor(factors,q); else factor_r(factors,q,bnd,failure_prob,verbose); if (ProbPrime_notd(n)) { addFactor(factors,n); return; } // new upper_bound SqrRoot(upper_bound,n); if (bnd>0 && bnd<upper_bound) upper_bound=bnd; } } // search for factors of size bnd factor_r(factors,n,bnd,failure_prob,verbose); }
void ExerciseFactorize::slotFactor19ButtonClicked() { addFactor(19); return; }
void ExerciseFactorize::slotFactor7ButtonClicked() { addFactor(7); return; }