The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
6.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace PrimesHelpers
  20. {
  21. static void createSmallSieve (const int numBits, BigInteger& result)
  22. {
  23. result.setBit (numBits);
  24. result.clearBit (numBits); // to enlarge the array
  25. result.setBit (0);
  26. int n = 2;
  27. do
  28. {
  29. for (int i = n + n; i < numBits; i += n)
  30. result.setBit (i);
  31. n = result.findNextClearBit (n + 1);
  32. }
  33. while (n <= (numBits >> 1));
  34. }
  35. static void bigSieve (const BigInteger& base, const int numBits, BigInteger& result,
  36. const BigInteger& smallSieve, const int smallSieveSize)
  37. {
  38. jassert (! base[0]); // must be even!
  39. result.setBit (numBits);
  40. result.clearBit (numBits); // to enlarge the array
  41. int index = smallSieve.findNextClearBit (0);
  42. do
  43. {
  44. const unsigned int prime = ((unsigned int) index << 1) + 1;
  45. BigInteger r (base), remainder;
  46. r.divideBy (prime, remainder);
  47. unsigned int i = prime - remainder.getBitRangeAsInt (0, 32);
  48. if (r.isZero())
  49. i += prime;
  50. if ((i & 1) == 0)
  51. i += prime;
  52. i = (i - 1) >> 1;
  53. while (i < (unsigned int) numBits)
  54. {
  55. result.setBit ((int) i);
  56. i += prime;
  57. }
  58. index = smallSieve.findNextClearBit (index + 1);
  59. }
  60. while (index < smallSieveSize);
  61. }
  62. static bool findCandidate (const BigInteger& base, const BigInteger& sieve,
  63. const int numBits, BigInteger& result, const int certainty)
  64. {
  65. for (int i = 0; i < numBits; ++i)
  66. {
  67. if (! sieve[i])
  68. {
  69. result = base + (unsigned int) ((i << 1) + 1);
  70. if (Primes::isProbablyPrime (result, certainty))
  71. return true;
  72. }
  73. }
  74. return false;
  75. }
  76. static bool passesMillerRabin (const BigInteger& n, int iterations)
  77. {
  78. const BigInteger one (1), two (2);
  79. const BigInteger nMinusOne (n - one);
  80. BigInteger d (nMinusOne);
  81. const int s = d.findNextSetBit (0);
  82. d >>= s;
  83. BigInteger smallPrimes;
  84. int numBitsInSmallPrimes = 0;
  85. for (;;)
  86. {
  87. numBitsInSmallPrimes += 256;
  88. createSmallSieve (numBitsInSmallPrimes, smallPrimes);
  89. const int numPrimesFound = numBitsInSmallPrimes - smallPrimes.countNumberOfSetBits();
  90. if (numPrimesFound > iterations + 1)
  91. break;
  92. }
  93. int smallPrime = 2;
  94. while (--iterations >= 0)
  95. {
  96. smallPrime = smallPrimes.findNextClearBit (smallPrime + 1);
  97. BigInteger r (smallPrime);
  98. r.exponentModulo (d, n);
  99. if (r != one && r != nMinusOne)
  100. {
  101. for (int j = 0; j < s; ++j)
  102. {
  103. r.exponentModulo (two, n);
  104. if (r == nMinusOne)
  105. break;
  106. }
  107. if (r != nMinusOne)
  108. return false;
  109. }
  110. }
  111. return true;
  112. }
  113. }
  114. //==============================================================================
  115. BigInteger Primes::createProbablePrime (const int bitLength,
  116. const int certainty,
  117. const int* randomSeeds,
  118. int numRandomSeeds)
  119. {
  120. using namespace PrimesHelpers;
  121. int defaultSeeds [16];
  122. if (numRandomSeeds <= 0)
  123. {
  124. randomSeeds = defaultSeeds;
  125. numRandomSeeds = numElementsInArray (defaultSeeds);
  126. Random r1, r2;
  127. for (int j = 10; --j >= 0;)
  128. {
  129. r1.setSeedRandomly();
  130. for (int i = numRandomSeeds; --i >= 0;)
  131. defaultSeeds[i] ^= r1.nextInt() ^ r2.nextInt();
  132. }
  133. }
  134. BigInteger smallSieve;
  135. const int smallSieveSize = 15000;
  136. createSmallSieve (smallSieveSize, smallSieve);
  137. BigInteger p;
  138. for (int i = numRandomSeeds; --i >= 0;)
  139. {
  140. BigInteger p2;
  141. Random r (randomSeeds[i]);
  142. r.fillBitsRandomly (p2, 0, bitLength);
  143. p ^= p2;
  144. }
  145. p.setBit (bitLength - 1);
  146. p.clearBit (0);
  147. const int searchLen = jmax (1024, (bitLength / 20) * 64);
  148. while (p.getHighestBit() < bitLength)
  149. {
  150. p += 2 * searchLen;
  151. BigInteger sieve;
  152. bigSieve (p, searchLen, sieve,
  153. smallSieve, smallSieveSize);
  154. BigInteger candidate;
  155. if (findCandidate (p, sieve, searchLen, candidate, certainty))
  156. return candidate;
  157. }
  158. jassertfalse;
  159. return BigInteger();
  160. }
  161. bool Primes::isProbablyPrime (const BigInteger& number, const int certainty)
  162. {
  163. using namespace PrimesHelpers;
  164. if (! number[0])
  165. return false;
  166. if (number.getHighestBit() <= 10)
  167. {
  168. const unsigned int num = number.getBitRangeAsInt (0, 10);
  169. for (unsigned int i = num / 2; --i > 1;)
  170. if (num % i == 0)
  171. return false;
  172. return true;
  173. }
  174. else
  175. {
  176. if (number.findGreatestCommonDivisor (2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23) != 1)
  177. return false;
  178. return passesMillerRabin (number, certainty);
  179. }
  180. }