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.

239 lines
6.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. namespace PrimesHelpers
  18. {
  19. static void createSmallSieve (const int numBits, BigInteger& result)
  20. {
  21. result.setBit (numBits);
  22. result.clearBit (numBits); // to enlarge the array
  23. result.setBit (0);
  24. int n = 2;
  25. do
  26. {
  27. for (int i = n + n; i < numBits; i += n)
  28. result.setBit (i);
  29. n = result.findNextClearBit (n + 1);
  30. }
  31. while (n <= (numBits >> 1));
  32. }
  33. static void bigSieve (const BigInteger& base, const int numBits, BigInteger& result,
  34. const BigInteger& smallSieve, const int smallSieveSize)
  35. {
  36. jassert (! base[0]); // must be even!
  37. result.setBit (numBits);
  38. result.clearBit (numBits); // to enlarge the array
  39. int index = smallSieve.findNextClearBit (0);
  40. do
  41. {
  42. const unsigned int prime = ((unsigned int) index << 1) + 1;
  43. BigInteger r (base), remainder;
  44. r.divideBy (prime, remainder);
  45. unsigned int i = prime - remainder.getBitRangeAsInt (0, 32);
  46. if (r.isZero())
  47. i += prime;
  48. if ((i & 1) == 0)
  49. i += prime;
  50. i = (i - 1) >> 1;
  51. while (i < (unsigned int) numBits)
  52. {
  53. result.setBit ((int) i);
  54. i += prime;
  55. }
  56. index = smallSieve.findNextClearBit (index + 1);
  57. }
  58. while (index < smallSieveSize);
  59. }
  60. static bool findCandidate (const BigInteger& base, const BigInteger& sieve,
  61. const int numBits, BigInteger& result, const int certainty)
  62. {
  63. for (int i = 0; i < numBits; ++i)
  64. {
  65. if (! sieve[i])
  66. {
  67. result = base + (unsigned int) ((i << 1) + 1);
  68. if (Primes::isProbablyPrime (result, certainty))
  69. return true;
  70. }
  71. }
  72. return false;
  73. }
  74. static bool passesMillerRabin (const BigInteger& n, int iterations)
  75. {
  76. const BigInteger one (1), two (2);
  77. const BigInteger nMinusOne (n - one);
  78. BigInteger d (nMinusOne);
  79. const int s = d.findNextSetBit (0);
  80. d >>= s;
  81. BigInteger smallPrimes;
  82. int numBitsInSmallPrimes = 0;
  83. for (;;)
  84. {
  85. numBitsInSmallPrimes += 256;
  86. createSmallSieve (numBitsInSmallPrimes, smallPrimes);
  87. const int numPrimesFound = numBitsInSmallPrimes - smallPrimes.countNumberOfSetBits();
  88. if (numPrimesFound > iterations + 1)
  89. break;
  90. }
  91. int smallPrime = 2;
  92. while (--iterations >= 0)
  93. {
  94. smallPrime = smallPrimes.findNextClearBit (smallPrime + 1);
  95. BigInteger r (smallPrime);
  96. r.exponentModulo (d, n);
  97. if (r != one && r != nMinusOne)
  98. {
  99. for (int j = 0; j < s; ++j)
  100. {
  101. r.exponentModulo (two, n);
  102. if (r == nMinusOne)
  103. break;
  104. }
  105. if (r != nMinusOne)
  106. return false;
  107. }
  108. }
  109. return true;
  110. }
  111. }
  112. //==============================================================================
  113. BigInteger Primes::createProbablePrime (const int bitLength,
  114. const int certainty,
  115. const int* randomSeeds,
  116. int numRandomSeeds)
  117. {
  118. using namespace PrimesHelpers;
  119. int defaultSeeds [16];
  120. if (numRandomSeeds <= 0)
  121. {
  122. randomSeeds = defaultSeeds;
  123. numRandomSeeds = numElementsInArray (defaultSeeds);
  124. Random r1, r2;
  125. for (int j = 10; --j >= 0;)
  126. {
  127. r1.setSeedRandomly();
  128. for (int i = numRandomSeeds; --i >= 0;)
  129. defaultSeeds[i] ^= r1.nextInt() ^ r2.nextInt();
  130. }
  131. }
  132. BigInteger smallSieve;
  133. const int smallSieveSize = 15000;
  134. createSmallSieve (smallSieveSize, smallSieve);
  135. BigInteger p;
  136. for (int i = numRandomSeeds; --i >= 0;)
  137. {
  138. BigInteger p2;
  139. Random r (randomSeeds[i]);
  140. r.fillBitsRandomly (p2, 0, bitLength);
  141. p ^= p2;
  142. }
  143. p.setBit (bitLength - 1);
  144. p.clearBit (0);
  145. const int searchLen = jmax (1024, (bitLength / 20) * 64);
  146. while (p.getHighestBit() < bitLength)
  147. {
  148. p += 2 * searchLen;
  149. BigInteger sieve;
  150. bigSieve (p, searchLen, sieve,
  151. smallSieve, smallSieveSize);
  152. BigInteger candidate;
  153. if (findCandidate (p, sieve, searchLen, candidate, certainty))
  154. return candidate;
  155. }
  156. jassertfalse;
  157. return BigInteger();
  158. }
  159. bool Primes::isProbablyPrime (const BigInteger& number, const int certainty)
  160. {
  161. using namespace PrimesHelpers;
  162. if (! number[0])
  163. return false;
  164. if (number.getHighestBit() <= 10)
  165. {
  166. const unsigned int num = number.getBitRangeAsInt (0, 10);
  167. for (unsigned int i = num / 2; --i > 1;)
  168. if (num % i == 0)
  169. return false;
  170. return true;
  171. }
  172. else
  173. {
  174. if (number.findGreatestCommonDivisor (2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23) != 1)
  175. return false;
  176. return passesMillerRabin (number, certainty);
  177. }
  178. }