Skip to content

Commit 3603a2d

Browse files
Debugging
1 parent 58fadb9 commit 3603a2d

File tree

1 file changed

+29
-36
lines changed

1 file changed

+29
-36
lines changed

FindAFactor/_find_a_factor.cpp

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ struct Factorizer {
734734
size_t rowLimit;
735735
bool isIncomplete;
736736
std::vector<size_t> smoothPrimes;
737-
std::set<BigInteger> smoothNumberSet;
737+
std::vector<BigInteger> residueKeys;
738738
std::vector<BigInteger> smoothNumberKeys;
739739
std::vector<boost::dynamic_bitset<size_t>> smoothNumberValues;
740740
ForwardFn forwardFn;
@@ -798,11 +798,11 @@ struct Factorizer {
798798
// Make the candidate NOT a multiple on the wheels.
799799
const BigInteger z = forwardFn(y);
800800
// Make the candidate a perfect square.
801-
const BigInteger candidate = (z * z);
802801
// The residue (mod N) needs to be smooth (but not a perfect square).
803802
// The candidate is guaranteed to be between toFactor and its square,
804803
// so subtracting toFactor is equivalent to % toFactor.
805-
const boost::dynamic_bitset<size_t> rfv = factorizationParityVector(candidate - toFactor);
804+
const BigInteger residue = (z * z) - toFactor;
805+
const boost::dynamic_bitset<size_t> rfv = factorizationParityVector(residue);
806806
if (rfv.empty()) {
807807
// The number is useless to us.
808808
continue;
@@ -812,27 +812,23 @@ struct Factorizer {
812812
// If the candidate is already a perfect square,
813813
// we got lucky, and we might be done already.
814814
if (rfv.none()) {
815-
const BigInteger factor = solveCongruence(candidate);
816-
if ((factor > 1U) && (factor < toFactor)) {
817-
// Success
818-
isIncomplete = false;
819-
820-
return candidate;
815+
// x^2 = y^2 % toFactor
816+
const BigInteger x = z;
817+
const BigInteger y = sqrt(residue);
818+
const BigInteger factor = gcd(this->toFactor, x - y);
819+
if ((factor > 1U) && (factor < this->toFactor)) {
820+
return factor;
821821
}
822822
}
823823

824824
std::lock_guard<std::mutex> lock(batchMutex);
825-
// Insert the number if it isn't found (in a binary search) of the accepted set.
826-
if (smoothNumberSet.find(candidate) == smoothNumberSet.end()) {
827-
smoothNumberSet.insert(candidate);
828-
smoothNumberKeys.push_back(candidate);
829-
smoothNumberValues.push_back(rfv);
830-
// If we have enough rows for Gaussian elimination already,
831-
// so there's no reason to sieve any further.
832-
if (smoothNumberKeys.size() > rowLimit) {
833-
isIncomplete = false;
834-
smoothNumberSet.clear();
835-
}
825+
smoothNumberKeys.push_back(z);
826+
residueKeys.push_back(residue);
827+
smoothNumberValues.push_back(rfv);
828+
// If we have enough rows for Gaussian elimination already,
829+
// there's no reason to sieve any further.
830+
if (smoothNumberKeys.size() > rowLimit) {
831+
isIncomplete = false;
836832
}
837833
}
838834

@@ -851,10 +847,10 @@ struct Factorizer {
851847
};
852848

853849
// Special thanks to https://github.com/NachiketUN/Quadratic-Sieve-Algorithm
854-
BigInteger solveDependentRows(const GaussianEliminationResult& ger, const size_t& solutionColumnId)
850+
std::vector<size_t> solveDependentRows(const GaussianEliminationResult& ger, const size_t& solutionColumnId)
855851
{
856852
// Add the chosen row from Gaussian elimination solution
857-
BigInteger solution = smoothNumberKeys[ger.solutionColumns[solutionColumnId].second];
853+
std::vector<size_t> solutionIds{ ger.solutionColumns[solutionColumnId].second };
858854
std::vector<size_t> indices;
859855

860856
// Get the first free row from Gaussian elimination results
@@ -874,33 +870,30 @@ struct Factorizer {
874870
}
875871
for (const size_t& i : indices) {
876872
if (smoothNumberValues[i][r]) {
877-
solution *= smoothNumberKeys[i];
873+
solutionIds.push_back(i);
878874
break;
879875
}
880876
}
881877
}
882878

883-
return solution;
879+
return solutionIds;
884880
}
885881

886-
BigInteger solveCongruence(const BigInteger& ySqr)
882+
BigInteger solveCongruence(const std::vector<size_t>& solutionIds)
887883
{
888884
// x^2 = y^2 % toFactor
889-
const BigInteger x = sqrt(ySqr % this->toFactor);
885+
BigInteger x = 1U;
886+
BigInteger ySqr = 1U;
887+
for (const size_t& id : solutionIds) {
888+
x *= smoothNumberKeys[id];
889+
ySqr *= residueKeys[id];
890+
}
890891
const BigInteger y = sqrt(ySqr);
891892
// Uncomment this to check our math:
892-
// if ((x * x) != (ySqr % this->toFactor)) {
893+
// if ((x * x) != ((y * y) % this->toFactor)) {
893894
// throw "Mistake!";
894895
// }
895-
896-
// Check congruence of squares
897-
BigInteger factor = gcd(this->toFactor, x + y);
898-
if ((factor > 1U) && (factor < this->toFactor)) {
899-
return factor;
900-
}
901-
902-
// Try x - y as well
903-
factor = gcd(this->toFactor, x - y);
896+
const BigInteger factor = gcd(this->toFactor, x - y);
904897
if ((factor > 1U) && (factor < this->toFactor)) {
905898
return factor;
906899
}

0 commit comments

Comments
 (0)