Skip to content

Commit 763fed1

Browse files
Optimize residue trial division
1 parent 6d66612 commit 763fed1

File tree

3 files changed

+16
-10
lines changed

3 files changed

+16
-10
lines changed

FindAFactor/_find_a_factor.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <iostream>
2020
#include <memory>
2121
#include <mutex>
22+
#include <numeric>
2223
#include <stdlib.h>
2324
#include <string>
2425

@@ -643,6 +644,10 @@ struct Factorizer {
643644
x *= smoothNumberKeys[idx];
644645
}
645646
const BigInteger y = sqrt((x * x) % toFactor);
647+
// Uncomment to validate our math, overall
648+
// if ((y * y) != ((x * x) % toFactor)) {
649+
// throw std::runtime_error("Math is not self-consistent!");
650+
// }
646651

647652
// Check x + y
648653
BigInteger factor = gcd(toFactor, x + y);
@@ -685,7 +690,8 @@ struct Factorizer {
685690
// Compute the prime factorization modulo 2
686691
boost::dynamic_bitset<size_t> factorizationParityVector(BigInteger num) {
687692
boost::dynamic_bitset<size_t> vec(smoothPrimes.size(), 0U);
688-
size_t piStart = 0U;
693+
std::vector<size_t> spids(smoothPrimes.size());
694+
std::iota(spids.begin(), spids.end(), 0);
689695
while (true) {
690696
// Proceed in steps of the GCD with the smooth prime wheel radius.
691697
BigInteger factor = gcd(num, smoothWheelRadius);
@@ -695,30 +701,30 @@ struct Factorizer {
695701
num /= factor;
696702
// Remove smooth primes from factor.
697703
// (The GCD is necessarily smooth.)
698-
bool isPreamble = true;
699-
for (size_t pi = piStart; pi < smoothPrimes.size(); ++pi) {
700-
const size_t& p = smoothPrimes[pi];
704+
std::vector<size_t> nspids(spids);
705+
for (size_t pi = 0; pi < spids.size(); ++pi) {
706+
const size_t& p = smoothPrimes[spids[pi]];
701707
if (factor % p) {
702708
// Once a preamble factor is found not to be present,
703709
// there's no longer use trying for it on the next iteration.
704-
if (isPreamble && (pi == piStart)) {
705-
++piStart;
706-
}
710+
nspids.erase(nspids.begin() + pi);
707711
continue;
708712
}
709-
isPreamble = false;
710713
factor /= p;
711714
vec.flip(pi);
712715
if (factor == 1U) {
713716
// The step is fully factored.
714717
// (This case is always reached.)
718+
nspids.erase(nspids.begin() + pi + 1U, nspids.end());
715719
break;
716720
}
717721
}
718722
if (num == 1U) {
719723
// The number is fully factored and smooth.
720724
return vec;
721725
}
726+
// Update smoothPrimes IDs
727+
spids = nspids;
722728
}
723729
if (num != 1U) {
724730
// The number was not fully factored, because it is not smooth.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
88

99
[project]
1010
name = "FindAFactor"
11-
version = "6.5.2"
11+
version = "6.5.3"
1212
requires-python = ">=3.8"
1313
description = "Find any nontrivial factor of a number"
1414
readme = {file = "README.txt", content-type = "text/markdown"}

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def build_extension(self, ext):
4040

4141
setup(
4242
name='FindAFactor',
43-
version='6.5.2',
43+
version='6.5.3',
4444
author='Dan Strano',
4545
author_email='stranoj@gmail.com',
4646
description='Find any nontrivial factor of a number',

0 commit comments

Comments
 (0)