FindAFactor 3.6.5__tar.gz → 3.6.7__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 BigInteger forward2(const size_t &p) { return (p << 1U) | 1U; }
180
+ inline size_t forward2(const size_t &p) { return (p << 1U) | 1U; }
156
181
 
157
- inline size_t backward2(const BigInteger &p) { return (size_t)(p >> 1U); }
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 BigInteger forward3(const size_t &p) { return (p << 1U) + (~(~p | 1U)) - 1U; }
185
+ inline size_t forward3(const size_t &p) { return (p << 1U) + (~(~p | 1U)) - 1U; }
161
186
 
162
- inline size_t backward3(const BigInteger &n) { return (size_t)((~(~n | 1U)) / 3U) + 1U; }
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
- BigInteger forward5(const size_t &p) { return wheel5[p % 8U] + (p / 8U) * 30U; }
192
+ size_t forward5(const size_t &p) { return wheel5[p % 8U] + (p / 8U) * 30U; }
168
193
 
169
- size_t backward5(const BigInteger &n) { return std::distance(wheel5, std::lower_bound(wheel5, wheel5 + 8U, (size_t)(n % 30U))) + 8U * (size_t)(n / 30U) + 1U; }
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
- BigInteger forward7(const size_t &p) { return wheel7[p % 48U] + (p / 48U) * 210U; }
201
+ size_t forward7(const size_t &p) { return wheel7[p % 48U] + (p / 48U) * 210U; }
177
202
 
178
- size_t backward7(const BigInteger &n) { return std::distance(wheel7, std::lower_bound(wheel7, wheel7 + 48U, (size_t)(n % 210U))) + 48U * (size_t)(n / 210U) + 1U; }
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
- BigInteger forward11(const size_t &p) { return wheel11[p % 480U] + (p / 480U) * 2310U; }
228
+ size_t forward11(const size_t &p) { return wheel11[p % 480U] + (p / 480U) * 2310U; }
204
229
 
205
- size_t backward11(const BigInteger &n) { return std::distance(wheel11, std::lower_bound(wheel11, wheel11 + 480U, (size_t)(n % 2310U))) + 480U * (size_t)(n / 2310U) + 1U; }
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
- BigInteger forward13(const size_t &p) { return wheel13[p % 5760U] + (p / 5760U) * 30030U; }
477
+ size_t forward13(const size_t &p) { return wheel13[p % 5760U] + (p / 5760U) * 30030U; }
453
478
 
454
- size_t backward13(const BigInteger &n) { return std::distance(wheel13, std::lower_bound(wheel13, wheel13 + 5760U, (size_t)(n % 30030U))) + 5760U * (size_t)(n / 30030U) + 1U; }
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<BigInteger> SieveOfEratosthenes(const BigInteger &n) {
547
- std::vector<BigInteger> knownPrimes = {2U, 3U, 5U, 7U};
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<BigInteger>();
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<BigInteger>(knownPrimes.begin(), highestPrimeIt);
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 BigInteger p = forward3(o);
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 BigInteger p2 = p << 1U;
594
- const BigInteger p4 = p << 2U;
595
- BigInteger i = p * p;
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 BigInteger p = forward3(o);
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<BigInteger> &knownPrimes) {
649
- for (const BigInteger &prime : knownPrimes) {
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<BigInteger> primes) {
683
+ boost::dynamic_bitset<size_t> wheel_inc(std::vector<size_t> primes) {
659
684
  BigInteger radius = 1U;
660
- for (const BigInteger &i : primes) {
685
+ for (const size_t &i : primes) {
661
686
  radius *= i;
662
687
  }
663
- const BigInteger prime = primes.back();
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<BigInteger> &primes) {
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<BigInteger> wheelPrimes;
679
- for (const BigInteger &p : primes) {
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,19 +768,19 @@ struct Factorizer {
743
768
  size_t smoothPartsLimit;
744
769
  size_t rowOffset;
745
770
  bool isIncomplete;
746
- std::vector<BigInteger> primes;
747
- std::vector<BigInteger> sqrPrimes;
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<BigInteger> &p, ForwardFn fn)
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 BigInteger& p = primes[i];
783
+ const size_t& p = primes[i];
759
784
  wheelRadius *= p;
760
785
  sqrPrimes.push_back(p * p);
761
786
  smoothNumberKeys.push_back(p);
@@ -837,7 +862,7 @@ struct Factorizer {
837
862
  num /= factor;
838
863
  // Remove smooth primes from factor
839
864
  for (size_t pi = 0U; pi < primes.size(); ++pi) {
840
- const BigInteger& p = primes[pi];
865
+ const size_t& p = primes[pi];
841
866
  if (factor % p) {
842
867
  continue;
843
868
  }
@@ -1127,10 +1152,10 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
1127
1152
  }
1128
1153
 
1129
1154
  // We only need to try trial division about as high as would be necessary for 4096 bits of semiprime.
1130
- const BigInteger primeCeiling = (trialDivisionLevel < fullMaxBase) ? (BigInteger)trialDivisionLevel : fullMaxBase;
1155
+ const size_t primeCeiling = (trialDivisionLevel < fullMaxBase) ? trialDivisionLevel : (size_t)fullMaxBase;
1131
1156
  BigInteger result = 1U;
1132
1157
  // This uses very little memory and time, to find primes.
1133
- std::vector<BigInteger> primes = SieveOfEratosthenes(primeCeiling);
1158
+ std::vector<size_t> primes = SieveOfEratosthenes(primeCeiling);
1134
1159
  // "it" is the end-of-list iterator for a list up-to-and-including wheelFactorizationLevel.
1135
1160
  const auto itw = std::upper_bound(primes.begin(), primes.end(), wheelFactorizationLevel);
1136
1161
  const auto itg = std::upper_bound(primes.begin(), primes.end(), gearFactorizationLevel);
@@ -1142,7 +1167,7 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
1142
1167
  dispatch.dispatch([&toFactor, &primes, &result, &trialDivisionMutex, primeIndex]() -> bool {
1143
1168
  const size_t maxLcv = std::min(primeIndex + 64U, primes.size());
1144
1169
  for (size_t pi = primeIndex; pi < maxLcv; ++pi) {
1145
- const BigInteger& currentPrime = primes[pi];
1170
+ const size_t& currentPrime = primes[pi];
1146
1171
  if (!(toFactor % currentPrime)) {
1147
1172
  std::lock_guard<std::mutex> lock(trialDivisionMutex);
1148
1173
  result = currentPrime;
@@ -1159,8 +1184,8 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
1159
1184
  }
1160
1185
 
1161
1186
  // Set up wheel factorization (or "gear" factorization)
1162
- std::vector<BigInteger> gearFactorizationPrimes(primes.begin(), itg);
1163
- std::vector<BigInteger> wheelFactorizationPrimes(primes.begin(), itw);
1187
+ std::vector<size_t> gearFactorizationPrimes(primes.begin(), itg);
1188
+ std::vector<size_t> wheelFactorizationPrimes(primes.begin(), itw);
1164
1189
  // Keep as many "smooth" primes as bits in number to factor.
1165
1190
  const size_t toFactorBits = (size_t)log2(toFactor);
1166
1191
  size_t smoothPrimeCount = (size_t)(smoothnessBoundMultiplier * toFactorBits);
@@ -1171,10 +1196,10 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
1171
1196
  // Primes are only present in range above wheel factorization level
1172
1197
  primes.erase(primes.begin(), itg);
1173
1198
  const size_t maxPrimeCount = std::min(primes.size(), smoothPrimeCount);
1174
- std::vector<BigInteger> smoothPrimes;
1199
+ std::vector<size_t> smoothPrimes;
1175
1200
  for (size_t primeId = 0U; (primeId < primes.size()) && (smoothPrimes.size() < maxPrimeCount); ++primeId) {
1176
- const BigInteger residue = toFactor % primes[primeId];
1177
- const BigInteger sr = sqrt(residue);
1201
+ const size_t residue = (size_t)(toFactor % primes[primeId]);
1202
+ const size_t sr = _sqrt(residue);
1178
1203
  if ((sr * sr) == residue) {
1179
1204
  smoothPrimes.push_back(primes[primeId]);
1180
1205
  }
@@ -1184,7 +1209,7 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
1184
1209
  }
1185
1210
  // From 1, this is a period for wheel factorization
1186
1211
  size_t biggestWheel = 1ULL;
1187
- for (const BigInteger &wp : gearFactorizationPrimes) {
1212
+ for (const size_t &wp : gearFactorizationPrimes) {
1188
1213
  biggestWheel *= (size_t)wp;
1189
1214
  }
1190
1215
  // Wheel entry count per largest "gear" scales our brute-force range.
@@ -1206,8 +1231,6 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
1206
1231
 
1207
1232
  // Range per parallel node
1208
1233
  const BigInteger nodeRange = (((backward(SMALLEST_WHEEL)(fullMaxBase) + nodeCount - 1U) / nodeCount) + wheelEntryCount - 1U) / wheelEntryCount;
1209
- // This is used by all threads:
1210
- std::vector<std::vector<BigInteger>> semiSmoothParts(CpuCount);
1211
1234
  // This manages the work of all threads.
1212
1235
  Factorizer worker(toFactor * toFactor, toFactor, fullMaxBase,
1213
1236
  nodeRange, nodeCount, nodeId,
@@ -1244,7 +1267,7 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
1244
1267
  return boost::lexical_cast<std::string>(result);
1245
1268
  }
1246
1269
 
1247
- const auto smoothNumberFn = [&inc_seqs, &wheelEntryCount, &semiSmoothParts, &worker, &isGaussElim] (unsigned cpu) {
1270
+ const auto smoothNumberFn = [&inc_seqs, &wheelEntryCount, &batchSizeMultiplier, &worker, &isGaussElim] {
1248
1271
  // inc_seq needs to be independent per thread.
1249
1272
  std::vector<boost::dynamic_bitset<size_t>> inc_seqs_clone;
1250
1273
  inc_seqs_clone.reserve(inc_seqs.size());
@@ -1253,10 +1276,11 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
1253
1276
  }
1254
1277
 
1255
1278
  // Different collections per thread;
1256
- semiSmoothParts.reserve(wheelEntryCount << 1U);
1279
+ std::vector<BigInteger> semiSmoothParts;
1280
+ semiSmoothParts.reserve((size_t)((wheelEntryCount << 1U) * batchSizeMultiplier));
1257
1281
 
1258
1282
  // While brute-forcing, use the "exhaust" to feed "smooth" number generation and check conguence of squares.
1259
- return worker.smoothCongruences(&inc_seqs_clone, &(semiSmoothParts[cpu]), isGaussElim);
1283
+ return worker.smoothCongruences(&inc_seqs_clone, &semiSmoothParts, isGaussElim);
1260
1284
  };
1261
1285
 
1262
1286
  std::vector<std::future<BigInteger>> futures;
@@ -1264,7 +1288,7 @@ std::string find_a_factor(const std::string &toFactorStr, const bool &isConOfSqr
1264
1288
 
1265
1289
  do {
1266
1290
  for (unsigned cpu = 0U; cpu < CpuCount; ++cpu) {
1267
- futures.push_back(std::async(std::launch::async, smoothNumberFn, cpu));
1291
+ futures.push_back(std::async(std::launch::async, smoothNumberFn));
1268
1292
  }
1269
1293
 
1270
1294
  for (unsigned cpu = 0U; cpu < futures.size(); ++cpu) {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: FindAFactor
3
- Version: 3.6.5
3
+ Version: 3.6.7
4
4
  Summary: Find any nontrivial factor of a number
5
5
  Home-page: https://github.com/vm6502q/FindAFactor
6
6
  Author: Dan Strano
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: FindAFactor
3
- Version: 3.6.5
3
+ Version: 3.6.7
4
4
  Summary: Find any nontrivial factor of a number
5
5
  Home-page: https://github.com/vm6502q/FindAFactor
6
6
  Author: Dan Strano
@@ -26,7 +26,7 @@ ext_modules = [
26
26
 
27
27
  setup(
28
28
  name='FindAFactor',
29
- version='3.6.5',
29
+ version='3.6.7',
30
30
  author='Dan Strano',
31
31
  author_email='dan@unitary.fund',
32
32
  description='Find any nontrivial factor of a number',
File without changes
File without changes
File without changes