@@ -705,27 +705,27 @@ struct Factorizer {
705705 BigInteger batchTotal;
706706 BigInteger smoothWheelRadius;
707707 BigInteger diffWheelRadius;
708- size_t firstGaussianElimPrimeId ;
708+ size_t afterGearPrimeId ;
709709 size_t wheelEntryCount;
710710 size_t rowLimit;
711711 bool isIncomplete;
712- std::vector<size_t > primes ;
712+ std::vector<size_t > smoothPrimes ;
713713 std::set<BigInteger> smoothNumberSet;
714714 std::vector<BigInteger> smoothNumberKeys;
715715 std::vector<boost::dynamic_bitset<size_t >> smoothNumberValues;
716716 ForwardFn forwardFn;
717717 ForwardFn backwardFn;
718718
719- Factorizer (const BigInteger &tf, const BigInteger &tfsqrt, const BigInteger &range, size_t nodeCount, size_t nodeId, size_t fgepi , size_t w, size_t rl, size_t bn,
720- const std::vector<size_t > &p , ForwardFn ffn, ForwardFn bfn)
719+ Factorizer (const BigInteger &tf, const BigInteger &tfsqrt, const BigInteger &range, size_t nodeCount, size_t nodeId, size_t agpi , size_t w, size_t rl, size_t bn,
720+ const std::vector<size_t > &sp , ForwardFn ffn, ForwardFn bfn)
721721 : toFactorSqr(tf * tf), toFactor(tf), toFactorSqrt(tfsqrt), batchRange(range), batchNumber(bn), batchOffset(nodeId * range), batchTotal(nodeCount * range),
722- firstGaussianElimPrimeId (fgepi ), smoothWheelRadius(1U ), diffWheelRadius(1U ), wheelEntryCount(w), rowLimit(rl), isIncomplete(true ), primes(p ), forwardFn(ffn), backwardFn(bfn)
722+ afterGearPrimeId (agpi ), smoothWheelRadius(1U ), diffWheelRadius(1U ), wheelEntryCount(w), rowLimit(rl), isIncomplete(true ), smoothPrimes(sp ), forwardFn(ffn), backwardFn(bfn)
723723 {
724- for (size_t i = 0U ; i < firstGaussianElimPrimeId ; ++i) {
725- smoothWheelRadius *= primes [i];
724+ for (size_t i = 0U ; i < afterGearPrimeId ; ++i) {
725+ smoothWheelRadius *= smoothPrimes [i];
726726 }
727- for (size_t i = firstGaussianElimPrimeId ; i < primes .size (); ++i) {
728- const size_t & p = primes [i];
727+ for (size_t i = afterGearPrimeId ; i < smoothPrimes .size (); ++i) {
728+ const size_t & p = smoothPrimes [i];
729729 smoothWheelRadius *= p;
730730 diffWheelRadius *= p;
731731 }
@@ -830,14 +830,14 @@ struct Factorizer {
830830 const boost::dynamic_bitset<size_t >& freeRow = ger.solutionColumns [solutionColumnId].first ;
831831
832832 // Find the indices where the free row has true values.
833- for (size_t i = 0 ; i < freeRow.size (); i++ ) {
833+ for (size_t i = 0U ; i < freeRow.size (); ++i ) {
834834 if (freeRow[i]) {
835835 indices.push_back (i);
836836 }
837837 }
838838
839839 // Find dependent rows from the original matrix
840- for (size_t r = 0 ; r < primes .size (); r++ ) {
840+ for (size_t r = 0U ; r < smoothPrimes .size (); ++r ) {
841841 for (size_t i : indices) {
842842 if (smoothNumberValues[i][r] && ger.marks [r]) {
843843 solutionVec.push_back (r);
@@ -885,9 +885,9 @@ struct Factorizer {
885885 auto mColIt = smoothNumberValues.begin ();
886886 auto nColIt = smoothNumberKeys.begin ();
887887 const size_t rows = smoothNumberValues.size ();
888- GaussianEliminationResult result (primes .size ());
888+ GaussianEliminationResult result (smoothPrimes .size ());
889889
890- for (size_t col = 0U ; col < primes .size (); ++col) {
890+ for (size_t col = 0U ; col < smoothPrimes .size (); ++col) {
891891 auto mRowIt = mColIt ;
892892 auto nRowIt = nColIt;
893893 const size_t colPlus1 = col + 1U ;
@@ -955,7 +955,7 @@ struct Factorizer {
955955 }
956956
957957 // Step 2: Identify free rows
958- for (size_t i = 0U ; i < primes .size (); i++ ) {
958+ for (size_t i = 0U ; i < smoothPrimes .size (); ++i ) {
959959 if (result.marks [i]) {
960960 continue ;
961961 }
@@ -1001,7 +1001,7 @@ struct Factorizer {
10011001 // Produce a smooth number with its factorization vector.
10021002 BigInteger makeSmooth (BigInteger num) {
10031003 BigInteger n = num;
1004- boost::dynamic_bitset<size_t > vec (primes .size (), 0 );
1004+ boost::dynamic_bitset<size_t > vec (smoothPrimes .size (), 0U );
10051005 while (true ) {
10061006 // Proceed in steps of the GCD with the smooth prime wheel radius.
10071007 BigInteger factor = gcd (n, diffWheelRadius);
@@ -1011,8 +1011,8 @@ struct Factorizer {
10111011 n /= factor;
10121012 // Remove smooth primes from factor.
10131013 // (The GCD is necessarily smooth.)
1014- for (size_t pi = firstGaussianElimPrimeId ; pi < primes .size (); ++pi) {
1015- const size_t & p = primes [pi];
1014+ for (size_t pi = afterGearPrimeId ; pi < smoothPrimes .size (); ++pi) {
1015+ const size_t & p = smoothPrimes [pi];
10161016 if (factor % p) {
10171017 continue ;
10181018 }
@@ -1044,11 +1044,11 @@ struct Factorizer {
10441044
10451045 // We actually want not just a smooth number,
10461046 // but a smooth perfect square.
1047- // for (size_t pi = 0U; pi < primes .size(); ++pi) {
1047+ // for (size_t pi = 0U; pi < smoothPrimes .size(); ++pi) {
10481048 // if (vec.test(pi)) {
10491049 // // If the prime factor component parity is odd,
10501050 // // multiply by the prime once to make it even.
1051- // num *= primes [pi];
1051+ // num *= smoothPrimes [pi];
10521052 // }
10531053 // // The parity is necessarily even in this factor, by now.
10541054 // }
@@ -1065,7 +1065,7 @@ struct Factorizer {
10651065
10661066 // Compute the prime factorization modulo 2
10671067 boost::dynamic_bitset<size_t > factorizationParityVector (BigInteger num) {
1068- boost::dynamic_bitset<size_t > vec (primes .size (), 0 );
1068+ boost::dynamic_bitset<size_t > vec (smoothPrimes .size (), 0U );
10691069 while (true ) {
10701070 // Proceed in steps of the GCD with the smooth prime wheel radius.
10711071 BigInteger factor = gcd (num, smoothWheelRadius);
@@ -1075,8 +1075,8 @@ struct Factorizer {
10751075 num /= factor;
10761076 // Remove smooth primes from factor.
10771077 // (The GCD is necessarily smooth.)
1078- for (size_t pi = 0U ; pi < primes .size (); ++pi) {
1079- const size_t & p = primes [pi];
1078+ for (size_t pi = 0U ; pi < smoothPrimes .size (); ++pi) {
1079+ const size_t & p = smoothPrimes [pi];
10801080 if (factor % p) {
10811081 continue ;
10821082 }
@@ -1110,7 +1110,7 @@ std::string find_a_factor(std::string toFactorStr, size_t method, size_t nodeCou
11101110 std::cout << " Mode number " << method << " not implemented. Defaulting to FACTOR_FINDER." << std::endl;
11111111 method = 1U ;
11121112 }
1113- const bool isFactorFinder = (method > 0 );
1113+ const bool isFactorFinder = (method > 0U );
11141114 if (!wheelFactorizationLevel) {
11151115 wheelFactorizationLevel = 1U ;
11161116 } else if (wheelFactorizationLevel > 13U ) {
@@ -1128,13 +1128,13 @@ std::string find_a_factor(std::string toFactorStr, size_t method, size_t nodeCou
11281128 const BigInteger toFactor (toFactorStr);
11291129
11301130 // The largest possible discrete factor of "toFactor" is its square root (as with any integer).
1131- const BigInteger fullMaxBase = sqrt (toFactor);
1132- if (fullMaxBase * fullMaxBase == toFactor) {
1133- return boost::lexical_cast<std::string>(fullMaxBase );
1131+ const BigInteger sqrtN = sqrt (toFactor);
1132+ if (sqrtN * sqrtN == toFactor) {
1133+ return boost::lexical_cast<std::string>(sqrtN );
11341134 }
11351135
11361136 // This level default (scaling) was suggested by Elara (OpenAI GPT).
1137- const double N = fullMaxBase .convert_to <double >();
1137+ const double N = sqrtN .convert_to <double >();
11381138 const double logN = log (N);
11391139 const BigInteger primeCeilingBigInt = (BigInteger)(smoothnessBoundMultiplier * exp (0.5 * std::sqrt (logN * log (logN))) + 0.5 );
11401140 const size_t primeCeiling = (size_t )primeCeilingBigInt;
@@ -1177,18 +1177,20 @@ std::string find_a_factor(std::string toFactorStr, size_t method, size_t nodeCou
11771177 std::vector<size_t > gearFactorizationPrimes (primes.begin (), itg);
11781178 std::vector<size_t > wheelFactorizationPrimes (primes.begin (), itw);
11791179 // Primes are only present in range above wheel factorization level
1180- const size_t firstGaussianElimPrimeId = std::distance (primes.begin (), itg);
1180+ const size_t afterGearPrimeId = isFactorFinder ? std::distance (primes.begin (), itg) : 0U ;
11811181 std::vector<size_t > smoothPrimes;
1182- for (size_t primeId = 0U ; primeId < primes.size (); ++primeId) {
1183- const size_t p = primes[primeId];
1184- const size_t residue = (size_t )(toFactor % p);
1185- const size_t sr = _sqrt (residue);
1186- if ((sr * sr) == residue) {
1187- smoothPrimes.push_back (p);
1182+ if (isFactorFinder) {
1183+ for (size_t primeId = 0U ; primeId < primes.size (); ++primeId) {
1184+ const size_t p = primes[primeId];
1185+ const size_t residue = (size_t )(toFactor % p);
1186+ const size_t sr = _sqrt (residue);
1187+ if ((sr * sr) == residue) {
1188+ smoothPrimes.push_back (p);
1189+ }
1190+ }
1191+ if (smoothPrimes.empty ()) {
1192+ throw std::runtime_error (" No smooth primes found under bound. (Increase the smoothness bound multiplier, unless this is not in range of check_small_factors=True.)" );
11881193 }
1189- }
1190- if (smoothPrimes.empty ()) {
1191- throw std::runtime_error (" No smooth primes found under bound. (Increase the smoothness bound multiplier, unless this is not in range of check_small_factors=True.)" );
11921194 }
11931195 // From 1, this is a period for wheel factorization
11941196 size_t biggestWheel = 1ULL ;
@@ -1214,18 +1216,17 @@ std::string find_a_factor(std::string toFactorStr, size_t method, size_t nodeCou
12141216
12151217 // Range per parallel node
12161218 const auto backwardFn = backward (SMALLEST_WHEEL);
1217- const BigInteger nodeRange = (((backwardFn (fullMaxBase ) + nodeCount - 1U ) / nodeCount) + wheelEntryCount - 1U ) / wheelEntryCount;
1219+ const BigInteger nodeRange = (((backwardFn (sqrtN ) + nodeCount - 1U ) / nodeCount) + wheelEntryCount - 1U ) / wheelEntryCount;
12181220 const size_t batchStart = ((size_t )backwardFn (primeCeiling)) / wheelEntryCount;
1221+ const size_t rowLimit = (size_t )(gaussianEliminationRowMultiplier * (smoothPrimes.size () + 1U ) + 0.5 );
12191222 // This manages the work of all threads.
1220- Factorizer worker (toFactor, fullMaxBase, nodeRange, nodeCount, nodeId, firstGaussianElimPrimeId,
1221- wheelEntryCount, (size_t )(gaussianEliminationRowMultiplier * (smoothPrimes.size () + 1U ) + 0.5 ),
1222- batchStart, smoothPrimes, forward (SMALLEST_WHEEL), backwardFn);
1223+ Factorizer worker (toFactor, sqrtN, nodeRange, nodeCount, nodeId, afterGearPrimeId, wheelEntryCount, rowLimit, batchStart, smoothPrimes, forward (SMALLEST_WHEEL), backwardFn);
12231224 // Square of count of smooth primes, for FACTOR_FINDER batch multiplier base unit, was suggested by Lyra (OpenAI GPT)
12241225
12251226 if (isFactorFinder) {
12261227 std::vector<std::future<void >> futures;
12271228 futures.reserve (CpuCount);
1228- const BigInteger sievingNodeRange = (BigInteger)(fullMaxBase .convert_to <double >() * sievingBoundMultiplier / nodeCount + 0.5 );
1229+ const BigInteger sievingNodeRange = (BigInteger)(sqrtN .convert_to <double >() * sievingBoundMultiplier / nodeCount + 0.5 );
12291230 const BigInteger sievingThreadRange = sievingNodeRange / CpuCount;
12301231 const BigInteger nodeOffset = nodeId * sievingNodeRange;
12311232 for (unsigned cpu = 0U ; cpu < CpuCount; ++cpu) {
0 commit comments