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.

246 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 juce
  20. {
  21. namespace PrimesHelpers
  22. {
  23. static void createSmallSieve (const int numBits, BigInteger& result)
  24. {
  25. result.setBit (numBits);
  26. result.clearBit (numBits); // to enlarge the array
  27. result.setBit (0);
  28. int n = 2;
  29. do
  30. {
  31. for (int i = n + n; i < numBits; i += n)
  32. result.setBit (i);
  33. n = result.findNextClearBit (n + 1);
  34. }
  35. while (n <= (numBits >> 1));
  36. }
  37. static void bigSieve (const BigInteger& base, const int numBits, BigInteger& result,
  38. const BigInteger& smallSieve, const int smallSieveSize)
  39. {
  40. jassert (! base[0]); // must be even!
  41. result.setBit (numBits);
  42. result.clearBit (numBits); // to enlarge the array
  43. int index = smallSieve.findNextClearBit (0);
  44. do
  45. {
  46. const unsigned int prime = ((unsigned int) index << 1) + 1;
  47. BigInteger r (base), remainder;
  48. r.divideBy (prime, remainder);
  49. unsigned int i = prime - remainder.getBitRangeAsInt (0, 32);
  50. if (r.isZero())
  51. i += prime;
  52. if ((i & 1) == 0)
  53. i += prime;
  54. i = (i - 1) >> 1;
  55. while (i < (unsigned int) numBits)
  56. {
  57. result.setBit ((int) i);
  58. i += prime;
  59. }
  60. index = smallSieve.findNextClearBit (index + 1);
  61. }
  62. while (index < smallSieveSize);
  63. }
  64. static bool findCandidate (const BigInteger& base, const BigInteger& sieve,
  65. const int numBits, BigInteger& result, const int certainty)
  66. {
  67. for (int i = 0; i < numBits; ++i)
  68. {
  69. if (! sieve[i])
  70. {
  71. result = base + (unsigned int) ((i << 1) + 1);
  72. if (Primes::isProbablyPrime (result, certainty))
  73. return true;
  74. }
  75. }
  76. return false;
  77. }
  78. static bool passesMillerRabin (const BigInteger& n, int iterations)
  79. {
  80. const BigInteger one (1), two (2);
  81. const BigInteger nMinusOne (n - one);
  82. BigInteger d (nMinusOne);
  83. const int s = d.findNextSetBit (0);
  84. d >>= s;
  85. BigInteger smallPrimes;
  86. int numBitsInSmallPrimes = 0;
  87. for (;;)
  88. {
  89. numBitsInSmallPrimes += 256;
  90. createSmallSieve (numBitsInSmallPrimes, smallPrimes);
  91. const int numPrimesFound = numBitsInSmallPrimes - smallPrimes.countNumberOfSetBits();
  92. if (numPrimesFound > iterations + 1)
  93. break;
  94. }
  95. int smallPrime = 2;
  96. while (--iterations >= 0)
  97. {
  98. smallPrime = smallPrimes.findNextClearBit (smallPrime + 1);
  99. BigInteger r (smallPrime);
  100. r.exponentModulo (d, n);
  101. if (r != one && r != nMinusOne)
  102. {
  103. for (int j = 0; j < s; ++j)
  104. {
  105. r.exponentModulo (two, n);
  106. if (r == nMinusOne)
  107. break;
  108. }
  109. if (r != nMinusOne)
  110. return false;
  111. }
  112. }
  113. return true;
  114. }
  115. }
  116. //==============================================================================
  117. BigInteger Primes::createProbablePrime (const int bitLength,
  118. const int certainty,
  119. const int* randomSeeds,
  120. int numRandomSeeds)
  121. {
  122. using namespace PrimesHelpers;
  123. int defaultSeeds [16];
  124. if (numRandomSeeds <= 0)
  125. {
  126. randomSeeds = defaultSeeds;
  127. numRandomSeeds = numElementsInArray (defaultSeeds);
  128. Random r1, r2;
  129. for (int j = 10; --j >= 0;)
  130. {
  131. r1.setSeedRandomly();
  132. for (int i = numRandomSeeds; --i >= 0;)
  133. defaultSeeds[i] ^= r1.nextInt() ^ r2.nextInt();
  134. }
  135. }
  136. BigInteger smallSieve;
  137. const int smallSieveSize = 15000;
  138. createSmallSieve (smallSieveSize, smallSieve);
  139. BigInteger p;
  140. for (int i = numRandomSeeds; --i >= 0;)
  141. {
  142. BigInteger p2;
  143. Random r (randomSeeds[i]);
  144. r.fillBitsRandomly (p2, 0, bitLength);
  145. p ^= p2;
  146. }
  147. p.setBit (bitLength - 1);
  148. p.clearBit (0);
  149. const int searchLen = jmax (1024, (bitLength / 20) * 64);
  150. while (p.getHighestBit() < bitLength)
  151. {
  152. p += 2 * searchLen;
  153. BigInteger sieve;
  154. bigSieve (p, searchLen, sieve,
  155. smallSieve, smallSieveSize);
  156. BigInteger candidate;
  157. if (findCandidate (p, sieve, searchLen, candidate, certainty))
  158. return candidate;
  159. }
  160. jassertfalse;
  161. return BigInteger();
  162. }
  163. bool Primes::isProbablyPrime (const BigInteger& number, const int certainty)
  164. {
  165. using namespace PrimesHelpers;
  166. if (! number[0])
  167. return false;
  168. if (number.getHighestBit() <= 10)
  169. {
  170. const unsigned int num = number.getBitRangeAsInt (0, 10);
  171. for (unsigned int i = num / 2; --i > 1;)
  172. if (num % i == 0)
  173. return false;
  174. return true;
  175. }
  176. else
  177. {
  178. if (number.findGreatestCommonDivisor (2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23) != 1)
  179. return false;
  180. return passesMillerRabin (number, certainty);
  181. }
  182. }
  183. } // namespace juce