FindAFactor 3.6.4__tar.gz → 3.6.6__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {findafactor-3.6.4 → findafactor-3.6.6}/FindAFactor/_find_a_factor.cpp +82 -60
- {findafactor-3.6.4 → findafactor-3.6.6}/FindAFactor.egg-info/PKG-INFO +1 -1
- {findafactor-3.6.4 → findafactor-3.6.6}/PKG-INFO +1 -1
- {findafactor-3.6.4 → findafactor-3.6.6}/setup.py +1 -1
- {findafactor-3.6.4 → findafactor-3.6.6}/FindAFactor/__init__.py +0 -0
- {findafactor-3.6.4 → findafactor-3.6.6}/FindAFactor/dispatchqueue.cpp +0 -0
- {findafactor-3.6.4 → findafactor-3.6.6}/FindAFactor/find_a_factor.py +0 -0
- {findafactor-3.6.4 → findafactor-3.6.6}/FindAFactor/oclengine.cpp +0 -0
- {findafactor-3.6.4 → findafactor-3.6.6}/FindAFactor.egg-info/SOURCES.txt +0 -0
- {findafactor-3.6.4 → findafactor-3.6.6}/FindAFactor.egg-info/dependency_links.txt +0 -0
- {findafactor-3.6.4 → findafactor-3.6.6}/FindAFactor.egg-info/requires.txt +0 -0
- {findafactor-3.6.4 → findafactor-3.6.6}/FindAFactor.egg-info/top_level.txt +0 -0
- {findafactor-3.6.4 → findafactor-3.6.6}/LICENSE +0 -0
- {findafactor-3.6.4 → findafactor-3.6.6}/README.md +0 -0
- {findafactor-3.6.4 → findafactor-3.6.6}/setup.cfg +0 -0
@@ -149,33 +149,58 @@ BigInteger sqrt(const BigInteger &toTest) {
|
|
149
149
|
return ans;
|
150
150
|
}
|
151
151
|
|
152
|
+
size_t _sqrt(const size_t &toTest) {
|
153
|
+
// Otherwise, find b = sqrt(b^2).
|
154
|
+
size_t start = 1U, end = toTest >> 1U, ans = 0U;
|
155
|
+
do {
|
156
|
+
const size_t mid = (start + end) >> 1U;
|
157
|
+
|
158
|
+
// If toTest is a perfect square
|
159
|
+
const size_t sqr = mid * mid;
|
160
|
+
if (sqr == toTest) {
|
161
|
+
return mid;
|
162
|
+
}
|
163
|
+
|
164
|
+
if (sqr < toTest) {
|
165
|
+
// Since we need floor, we update answer when mid*mid is smaller than p, and move closer to sqrt(p).
|
166
|
+
start = mid + 1U;
|
167
|
+
ans = mid;
|
168
|
+
} else {
|
169
|
+
// If mid*mid is greater than p
|
170
|
+
end = mid - 1U;
|
171
|
+
}
|
172
|
+
} while (start <= end);
|
173
|
+
|
174
|
+
return ans;
|
175
|
+
}
|
176
|
+
|
152
177
|
// We are multiplying out the first distinct primes, below.
|
153
178
|
|
154
179
|
// Make this NOT a multiple of 2.
|
155
|
-
inline
|
180
|
+
inline size_t forward2(const size_t &p) { return (p << 1U) | 1U; }
|
156
181
|
|
157
|
-
inline size_t backward2(const
|
182
|
+
inline size_t backward2(const size_t &p) { return (size_t)(p >> 1U); }
|
158
183
|
|
159
184
|
// Make this NOT a multiple of 2 or 3.
|
160
|
-
inline
|
185
|
+
inline size_t forward3(const size_t &p) { return (p << 1U) + (~(~p | 1U)) - 1U; }
|
161
186
|
|
162
|
-
inline size_t backward3(const
|
187
|
+
inline size_t backward3(const size_t &n) { return (size_t)((~(~n | 1U)) / 3U) + 1U; }
|
163
188
|
|
164
189
|
constexpr unsigned char wheel5[8U] = {1U, 7U, 11U, 13U, 17U, 19U, 23U, 29U};
|
165
190
|
|
166
191
|
// Make this NOT a multiple of 2, 3, or 5.
|
167
|
-
|
192
|
+
size_t forward5(const size_t &p) { return wheel5[p % 8U] + (p / 8U) * 30U; }
|
168
193
|
|
169
|
-
size_t backward5(const
|
194
|
+
size_t backward5(const size_t &n) { return std::distance(wheel5, std::lower_bound(wheel5, wheel5 + 8U, (size_t)(n % 30U))) + 8U * (size_t)(n / 30U) + 1U; }
|
170
195
|
|
171
196
|
constexpr unsigned char wheel7[48U] = {1U, 11U, 13U, 17U, 19U, 23U, 29U, 31U, 37U, 41U, 43U, 47U, 53U, 59U, 61U, 67U,
|
172
197
|
71U, 73U, 79U, 83U, 89U, 97U, 101U, 103U, 107U, 109U, 113U, 121U, 127U, 131U, 137U, 139U,
|
173
198
|
143U, 149U, 151U, 157U, 163U, 167U, 169U, 173U, 179U, 181U, 187U, 191U, 193U, 197U, 199U, 209U};
|
174
199
|
|
175
200
|
// Make this NOT a multiple of 2, 3, 5, or 7.
|
176
|
-
|
201
|
+
size_t forward7(const size_t &p) { return wheel7[p % 48U] + (p / 48U) * 210U; }
|
177
202
|
|
178
|
-
size_t backward7(const
|
203
|
+
size_t backward7(const size_t &n) { return std::distance(wheel7, std::lower_bound(wheel7, wheel7 + 48U, (size_t)(n % 210U))) + 48U * (size_t)(n / 210U) + 1U; }
|
179
204
|
|
180
205
|
constexpr unsigned short wheel11[480U] = {
|
181
206
|
1U, 13U, 17U, 19U, 23U, 29U, 31U, 37U, 41U, 43U, 47U, 53U, 59U, 61U, 67U, 71U, 73U, 79U, 83U, 89U, 97U, 101U, 103U, 107U,
|
@@ -200,9 +225,9 @@ constexpr unsigned short wheel11[480U] = {
|
|
200
225
|
2203U, 2207U, 2209U, 2213U, 2221U, 2227U, 2231U, 2237U, 2239U, 2243U, 2249U, 2251U, 2257U, 2263U, 2267U, 2269U, 2273U, 2279U, 2281U, 2287U, 2291U, 2293U, 2297U, 2309U};
|
201
226
|
|
202
227
|
// Make this NOT a multiple of 2, 3, 5, 7, or 11.
|
203
|
-
|
228
|
+
size_t forward11(const size_t &p) { return wheel11[p % 480U] + (p / 480U) * 2310U; }
|
204
229
|
|
205
|
-
size_t backward11(const
|
230
|
+
size_t backward11(const size_t &n) { return std::distance(wheel11, std::lower_bound(wheel11, wheel11 + 480U, (size_t)(n % 2310U))) + 480U * (size_t)(n / 2310U) + 1U; }
|
206
231
|
|
207
232
|
constexpr unsigned short wheel13[5760U] =
|
208
233
|
{
|
@@ -449,9 +474,9 @@ constexpr unsigned short wheel13[5760U] =
|
|
449
474
|
};
|
450
475
|
|
451
476
|
// Make this NOT a multiple of 2, 3, 5, 7, 11, or 13.
|
452
|
-
|
477
|
+
size_t forward13(const size_t &p) { return wheel13[p % 5760U] + (p / 5760U) * 30030U; }
|
453
478
|
|
454
|
-
size_t backward13(const
|
479
|
+
size_t backward13(const size_t &n) { return std::distance(wheel13, std::lower_bound(wheel13, wheel13 + 5760U, (size_t)(n % 30030U))) + 5760U * (size_t)(n / 30030U) + 1U; }
|
455
480
|
|
456
481
|
inline BigInteger _forward2(const BigInteger &p) { return (p << 1U) | 1U; }
|
457
482
|
|
@@ -543,15 +568,15 @@ inline size_t GetWheel5and7Increment(unsigned short &wheel5, unsigned long long
|
|
543
568
|
return wheelIncrement;
|
544
569
|
}
|
545
570
|
|
546
|
-
std::vector<
|
547
|
-
std::vector<
|
571
|
+
std::vector<size_t> SieveOfEratosthenes(const size_t &n) {
|
572
|
+
std::vector<size_t> knownPrimes = {2U, 3U, 5U, 7U};
|
548
573
|
if (n < 2U) {
|
549
|
-
return std::vector<
|
574
|
+
return std::vector<size_t>();
|
550
575
|
}
|
551
576
|
|
552
577
|
if (n < (knownPrimes.back() + 2U)) {
|
553
578
|
const auto highestPrimeIt = std::upper_bound(knownPrimes.begin(), knownPrimes.end(), n);
|
554
|
-
return std::vector<
|
579
|
+
return std::vector<size_t>(knownPrimes.begin(), highestPrimeIt);
|
555
580
|
}
|
556
581
|
|
557
582
|
knownPrimes.reserve((size_t)(((double)n) / log((double)n)));
|
@@ -576,7 +601,7 @@ std::vector<BigInteger> SieveOfEratosthenes(const BigInteger &n) {
|
|
576
601
|
for (;;) {
|
577
602
|
o += GetWheel5and7Increment(wheel5, wheel7);
|
578
603
|
|
579
|
-
const
|
604
|
+
const size_t p = forward3(o);
|
580
605
|
if ((p * p) > n) {
|
581
606
|
break;
|
582
607
|
}
|
@@ -590,9 +615,9 @@ std::vector<BigInteger> SieveOfEratosthenes(const BigInteger &n) {
|
|
590
615
|
// We are skipping multiples of 2, 3, and 5
|
591
616
|
// for space complexity, for 4/15 the bits.
|
592
617
|
// More are skipped by the wheel for time.
|
593
|
-
const
|
594
|
-
const
|
595
|
-
|
618
|
+
const size_t p2 = p << 1U;
|
619
|
+
const size_t p4 = p << 2U;
|
620
|
+
size_t i = p * p;
|
596
621
|
|
597
622
|
// "p" already definitely not a multiple of 3.
|
598
623
|
// Its remainder when divided by 3 can be 1 or 2.
|
@@ -628,7 +653,7 @@ std::vector<BigInteger> SieveOfEratosthenes(const BigInteger &n) {
|
|
628
653
|
}
|
629
654
|
|
630
655
|
for (;;) {
|
631
|
-
const
|
656
|
+
const size_t p = forward3(o);
|
632
657
|
if (p > n) {
|
633
658
|
break;
|
634
659
|
}
|
@@ -645,8 +670,8 @@ std::vector<BigInteger> SieveOfEratosthenes(const BigInteger &n) {
|
|
645
670
|
return knownPrimes;
|
646
671
|
}
|
647
672
|
|
648
|
-
bool isMultiple(const BigInteger &p, const std::vector<
|
649
|
-
for (const
|
673
|
+
bool isMultiple(const BigInteger &p, const std::vector<size_t> &knownPrimes) {
|
674
|
+
for (const size_t &prime : knownPrimes) {
|
650
675
|
if (!(p % prime)) {
|
651
676
|
return true;
|
652
677
|
}
|
@@ -655,12 +680,12 @@ bool isMultiple(const BigInteger &p, const std::vector<BigInteger> &knownPrimes)
|
|
655
680
|
return false;
|
656
681
|
}
|
657
682
|
|
658
|
-
boost::dynamic_bitset<size_t> wheel_inc(std::vector<
|
683
|
+
boost::dynamic_bitset<size_t> wheel_inc(std::vector<size_t> primes) {
|
659
684
|
BigInteger radius = 1U;
|
660
685
|
for (const BigInteger &i : primes) {
|
661
686
|
radius *= i;
|
662
687
|
}
|
663
|
-
const
|
688
|
+
const size_t prime = primes.back();
|
664
689
|
primes.pop_back();
|
665
690
|
boost::dynamic_bitset<size_t> o;
|
666
691
|
for (BigInteger i = 1U; i <= radius; ++i) {
|
@@ -673,10 +698,10 @@ boost::dynamic_bitset<size_t> wheel_inc(std::vector<BigInteger> primes) {
|
|
673
698
|
return o;
|
674
699
|
}
|
675
700
|
|
676
|
-
std::vector<boost::dynamic_bitset<size_t>> wheel_gen(const std::vector<
|
701
|
+
std::vector<boost::dynamic_bitset<size_t>> wheel_gen(const std::vector<size_t> &primes) {
|
677
702
|
std::vector<boost::dynamic_bitset<size_t>> output;
|
678
|
-
std::vector<
|
679
|
-
for (const
|
703
|
+
std::vector<size_t> wheelPrimes;
|
704
|
+
for (const size_t &p : primes) {
|
680
705
|
wheelPrimes.push_back(p);
|
681
706
|
output.push_back(wheel_inc(wheelPrimes));
|
682
707
|
}
|
@@ -743,23 +768,23 @@ struct Factorizer {
|
|
743
768
|
size_t smoothPartsLimit;
|
744
769
|
size_t rowOffset;
|
745
770
|
bool isIncomplete;
|
746
|
-
std::vector<
|
747
|
-
std::vector<
|
771
|
+
std::vector<size_t> primes;
|
772
|
+
std::vector<size_t> sqrPrimes;
|
748
773
|
ForwardFn forwardFn;
|
749
774
|
std::vector<BigInteger> smoothNumberKeys;
|
750
775
|
std::vector<boost::dynamic_bitset<size_t>> smoothNumberValues;
|
751
776
|
|
752
777
|
Factorizer(const BigInteger &tfsqr, const BigInteger &tf, const BigInteger &tfsqrt, const BigInteger &range, size_t nodeCount, size_t nodeId, size_t w, size_t spl,
|
753
|
-
const std::vector<
|
778
|
+
const std::vector<size_t> &p, ForwardFn fn)
|
754
779
|
: rng({}), gen(rng()), dis(0U, p.size() - 1U), toFactorSqr(tfsqr), toFactor(tf), toFactorSqrt(tfsqrt), batchRange(range), batchNumber(0U), batchOffset(nodeId * range), batchTotal(nodeCount * range),
|
755
780
|
wheelRadius(1U), wheelEntryCount(w), smoothPartsLimit(spl), rowOffset(p.size()), isIncomplete(true), primes(p), forwardFn(fn)
|
756
781
|
{
|
757
782
|
for (size_t i = 0U; i < primes.size(); ++i) {
|
758
|
-
const
|
783
|
+
const size_t& p = primes[i];
|
759
784
|
wheelRadius *= p;
|
760
785
|
sqrPrimes.push_back(p * p);
|
761
786
|
smoothNumberKeys.push_back(p);
|
762
|
-
smoothNumberValues.emplace_back(primes.size(),
|
787
|
+
smoothNumberValues.emplace_back(primes.size(), 0);
|
763
788
|
smoothNumberValues.back()[i] = true;
|
764
789
|
}
|
765
790
|
}
|
@@ -828,32 +853,29 @@ struct Factorizer {
|
|
828
853
|
|
829
854
|
// Compute the prime factorization modulo 2
|
830
855
|
boost::dynamic_bitset<size_t> factorizationVector(BigInteger num) {
|
831
|
-
boost::dynamic_bitset<size_t> vec(primes.size(),
|
832
|
-
|
833
|
-
|
834
|
-
factor = gcd(num, wheelRadius);
|
856
|
+
boost::dynamic_bitset<size_t> vec(primes.size(), 0);
|
857
|
+
while (true) {
|
858
|
+
BigInteger factor = gcd(num, wheelRadius);
|
835
859
|
if (factor == 1U) {
|
836
860
|
break;
|
837
861
|
}
|
838
862
|
num /= factor;
|
839
863
|
// Remove smooth primes from factor
|
840
864
|
for (size_t pi = 0U; pi < primes.size(); ++pi) {
|
841
|
-
const
|
842
|
-
if (
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
865
|
+
const size_t& p = primes[pi];
|
866
|
+
if (factor % p) {
|
867
|
+
continue;
|
868
|
+
}
|
869
|
+
factor /= p;
|
870
|
+
vec[pi] = !vec[pi];
|
871
|
+
if (factor == 1U) {
|
872
|
+
break;
|
848
873
|
}
|
849
874
|
}
|
850
875
|
if (num == 1U) {
|
851
|
-
|
876
|
+
return vec;
|
852
877
|
}
|
853
|
-
|
854
|
-
// factor == 1U if the number is smooth.
|
855
|
-
} while (factor == 1U);
|
856
|
-
|
878
|
+
};
|
857
879
|
if (num != 1U) {
|
858
880
|
return boost::dynamic_bitset<size_t>();
|
859
881
|
}
|
@@ -882,7 +904,7 @@ struct Factorizer {
|
|
882
904
|
|
883
905
|
// Now that smooth parts have been shuffled, just multiply down the list until they are larger than square root of toFactor.
|
884
906
|
BigInteger smoothNumber = 1U;
|
885
|
-
boost::dynamic_bitset<size_t> fv(primes.size(),
|
907
|
+
boost::dynamic_bitset<size_t> fv(primes.size(), 0);
|
886
908
|
for (size_t spi = 0U; spi < smoothParts.size(); ++spi) {
|
887
909
|
const BigInteger &sp = smoothParts[spi];
|
888
910
|
// This multiplies together the factorizations of the smooth parts
|
@@ -900,7 +922,7 @@ struct Factorizer {
|
|
900
922
|
}
|
901
923
|
// Reset "smoothNumber" and its factorization vector.
|
902
924
|
smoothNumber = 1U;
|
903
|
-
fv = boost::dynamic_bitset<size_t>(primes.size(),
|
925
|
+
fv = boost::dynamic_bitset<size_t>(primes.size(), 0);
|
904
926
|
}
|
905
927
|
}
|
906
928
|
|
@@ -1130,10 +1152,10 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
|
|
1130
1152
|
}
|
1131
1153
|
|
1132
1154
|
// We only need to try trial division about as high as would be necessary for 4096 bits of semiprime.
|
1133
|
-
const
|
1155
|
+
const size_t primeCeiling = (trialDivisionLevel < fullMaxBase) ? trialDivisionLevel : (size_t)fullMaxBase;
|
1134
1156
|
BigInteger result = 1U;
|
1135
1157
|
// This uses very little memory and time, to find primes.
|
1136
|
-
std::vector<
|
1158
|
+
std::vector<size_t> primes = SieveOfEratosthenes(primeCeiling);
|
1137
1159
|
// "it" is the end-of-list iterator for a list up-to-and-including wheelFactorizationLevel.
|
1138
1160
|
const auto itw = std::upper_bound(primes.begin(), primes.end(), wheelFactorizationLevel);
|
1139
1161
|
const auto itg = std::upper_bound(primes.begin(), primes.end(), gearFactorizationLevel);
|
@@ -1145,7 +1167,7 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
|
|
1145
1167
|
dispatch.dispatch([&toFactor, &primes, &result, &trialDivisionMutex, primeIndex]() -> bool {
|
1146
1168
|
const size_t maxLcv = std::min(primeIndex + 64U, primes.size());
|
1147
1169
|
for (size_t pi = primeIndex; pi < maxLcv; ++pi) {
|
1148
|
-
const
|
1170
|
+
const size_t& currentPrime = primes[pi];
|
1149
1171
|
if (!(toFactor % currentPrime)) {
|
1150
1172
|
std::lock_guard<std::mutex> lock(trialDivisionMutex);
|
1151
1173
|
result = currentPrime;
|
@@ -1162,8 +1184,8 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
|
|
1162
1184
|
}
|
1163
1185
|
|
1164
1186
|
// Set up wheel factorization (or "gear" factorization)
|
1165
|
-
std::vector<
|
1166
|
-
std::vector<
|
1187
|
+
std::vector<size_t> gearFactorizationPrimes(primes.begin(), itg);
|
1188
|
+
std::vector<size_t> wheelFactorizationPrimes(primes.begin(), itw);
|
1167
1189
|
// Keep as many "smooth" primes as bits in number to factor.
|
1168
1190
|
const size_t toFactorBits = (size_t)log2(toFactor);
|
1169
1191
|
size_t smoothPrimeCount = (size_t)(smoothnessBoundMultiplier * toFactorBits);
|
@@ -1174,10 +1196,10 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
|
|
1174
1196
|
// Primes are only present in range above wheel factorization level
|
1175
1197
|
primes.erase(primes.begin(), itg);
|
1176
1198
|
const size_t maxPrimeCount = std::min(primes.size(), smoothPrimeCount);
|
1177
|
-
std::vector<
|
1199
|
+
std::vector<size_t> smoothPrimes;
|
1178
1200
|
for (size_t primeId = 0U; (primeId < primes.size()) && (smoothPrimes.size() < maxPrimeCount); ++primeId) {
|
1179
|
-
const
|
1180
|
-
const
|
1201
|
+
const size_t residue = (size_t)(toFactor % primes[primeId]);
|
1202
|
+
const size_t sr = _sqrt(residue);
|
1181
1203
|
if ((sr * sr) == residue) {
|
1182
1204
|
smoothPrimes.push_back(primes[primeId]);
|
1183
1205
|
}
|
@@ -1187,7 +1209,7 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
|
|
1187
1209
|
}
|
1188
1210
|
// From 1, this is a period for wheel factorization
|
1189
1211
|
size_t biggestWheel = 1ULL;
|
1190
|
-
for (const
|
1212
|
+
for (const size_t &wp : gearFactorizationPrimes) {
|
1191
1213
|
biggestWheel *= (size_t)wp;
|
1192
1214
|
}
|
1193
1215
|
// Wheel entry count per largest "gear" scales our brute-force range.
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|