Advertisement
Guest User

Untitled

a guest
Aug 16th, 2015
237
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.18 KB | None | 0 0
  1. #define NOMINMAX     // due to conflict with max()
  2. #include <windows.h> // warning: no C++ standard!
  3.  
  4. #include "MyBigUnsigned.h" // http://henkessoft.de/Sonstiges/MyBigUnsigned.rar
  5.                            // based on https://mattmccutchen.net/bigint/
  6. #include <iostream>
  7. #include <cstdint>
  8. #include <vector>
  9. #include <cassert>
  10. #include <thread>
  11. #include <mutex>
  12.  
  13. ///#define DETAILS
  14. ///#define OUTPUT_OF_PRECHECKS
  15. ///#define NEGATIVE_LL
  16.  
  17. using namespace std;
  18.  
  19. const uint32_t numberOfThreads = 11;
  20. const uint32_t DIVISOR_PRECHECK_K_MAX = 600;
  21. uint64_t const primeLimit = 200000000;
  22. uint64_t frequency;
  23.  
  24. mutex mutex0;
  25. mutex mutex1;
  26. mutex mutex2;
  27. mutex mutex3;
  28.  
  29. void textcolor(unsigned short color = 15)
  30. {
  31.     SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), color);
  32. }
  33.  
  34. uint64_t convertBigToU64(BigUnsigned num)
  35. {
  36.     BigUnsigned ZweiHochVierUndSechzig = stringToBigUnsigned("18446744073709551616");
  37.     assert(num < ZweiHochVierUndSechzig);
  38.     uint64_t jHi = num.getBlock(1);
  39.     uint64_t jLo = num.getBlock(0);
  40.     return (jHi << 32 | jLo);
  41. }
  42.  
  43. void convertU64ToBig(uint64_t num, BigUnsigned& b)
  44. {
  45.     uint32_t numLo = (uint32_t)(num & 0xFFFFFFFF);
  46.     uint32_t numHi = (uint32_t)((num >> 32) & 0xFFFFFFFF);
  47.     b.setBlock(0, numLo);
  48.     b.setBlock(1, numHi);
  49. }
  50.  
  51. BigUnsigned calculateMersenneNumber(uint64_t p)
  52. {
  53.     BigUnsigned x = 2;
  54.  
  55.     for (uint64_t i = 1; i < p; ++i)
  56.     {
  57.         x <<= 1;
  58.     }
  59.     return (x - 1);
  60. }
  61.  
  62. bool LucasLehmerTest(BigUnsigned m, uint64_t p, uint64_t startCount, uint64_t lastCount)
  63. {
  64.     BigUnsigned s = 4;
  65.  
  66.     for (uint64_t i = 2; i < p; ++i)
  67.     {
  68.         s = (s*s - 2) % m;
  69.        
  70. #ifdef DETAILS
  71.         QueryPerformanceCounter((LARGE_INTEGER*)&lastCount);
  72.         uint64_t delta = lastCount - startCount;
  73.  
  74.         mutex1.lock();
  75.         cout << "p = " << p << " i = " << i << " s(len) = " << s.getLength();
  76.         cout << "\ttime: " << 1000 * delta / frequency << " ms" << endl;
  77.         mutex1.unlock();   
  78. #endif
  79.     }      
  80.  
  81.     return (s == 0);
  82. }
  83.  
  84. // division test with 2*k*p+1
  85. uint64_t divisionPrecheck(BigUnsigned m, uint64_t p, uint64_t startCount, uint64_t lastCount)
  86. {
  87.     for (uint64_t k = 1; k <= DIVISOR_PRECHECK_K_MAX; ++k)
  88.     {          
  89.         uint64_t Divisor = k * p;
  90.         Divisor <<= 1; // 2 * k * p
  91.         Divisor += 1; // 2 * k * p +1
  92.  
  93.         BigUnsigned BigDivisor(0);
  94.         convertU64ToBig(Divisor, BigDivisor);
  95.  
  96. #ifdef DETAILS
  97.         QueryPerformanceCounter((LARGE_INTEGER*)&lastCount);
  98.         uint64_t delta = lastCount - startCount;
  99.  
  100.         mutex2.lock();
  101.         cout << "check: p = " << p << "  k = " << k;
  102.         cout << "\ttime: " << 1000 * delta / frequency << " ms" << endl;
  103.         mutex2.unlock();
  104. #endif
  105.        
  106.         if (m % BigDivisor == 0)
  107.         {
  108.             return k;
  109.         }      
  110.     }
  111.  
  112.     return 0; // No divisor found
  113. }
  114.  
  115. bool precheck_mod4_is_3_and_2p_plus_1_isPrime (vector<bool>& primes, uint64_t p)
  116. {
  117.     return ((p % 4 == 3) && (primes[2 * p + 1]));
  118. }
  119.  
  120. void mersennePrimeCheck(vector<bool>& primes, uint64_t startCount, uint64_t lastCount, uint64_t startP, uint64_t limitP)
  121. {
  122.     for (uint64_t p = startP; p < limitP; ++p)
  123.     {
  124.         // primes lookup for p // In order for M(p) to be prime, p must itself be prime.
  125.         if (!primes[p])
  126.         {
  127. #ifdef DETAILS
  128.             mutex0.lock();
  129.             textcolor(3);
  130.             cout << ">>> p = " << p << " no prime! <<<" << endl;
  131.             mutex0.unlock();
  132. #endif
  133.             continue;
  134.         }  
  135.  
  136.         // precheck: P = 3 (mod 4) && isPrime (2*p+1) ?
  137.         if (precheck_mod4_is_3_and_2p_plus_1_isPrime (primes, p))
  138.         {
  139. #ifdef OUTPUT_OF_PRECHECKS
  140.             mutex3.lock();
  141.             textcolor(5);
  142.             cout << ">>> p = " << p << " p_mod4_is_3_and_2p_plus_1_isPrime! <<<" << endl;
  143.             mutex3.unlock();
  144. #endif
  145.             continue;
  146.         }
  147.                
  148.         // if p is prime, then we calculate the mersenne number
  149.         BigUnsigned m = calculateMersenneNumber(p);
  150.        
  151.         // mersenne numbers with (2*k*p+1) factors are no mersenne primes
  152.         if (p > 19)
  153.         {
  154.             uint64_t divisor = divisionPrecheck(m, p, startCount, lastCount);
  155.             if (divisor !=0)
  156.             {
  157. #ifdef OUTPUT_OF_PRECHECKS
  158.                 mutex0.lock();
  159.                 textcolor(3);
  160.                 cout << ">>> divisionPrecheck (2*k*p+1) finds k = " << divisor << " for p = " << p << " <<<" << endl;
  161.                 mutex0.unlock();
  162. #endif
  163.                 continue;          
  164.             }
  165.         }      
  166.        
  167.         if (LucasLehmerTest(m, p, startCount, lastCount))
  168.         {
  169.             QueryPerformanceCounter((LARGE_INTEGER*)&lastCount);
  170.             uint64_t delta = lastCount - startCount;
  171.  
  172.             mutex0.lock();
  173.             textcolor(15);
  174.             cout << "p: " << p;
  175.             textcolor(2);
  176.             cout << "\ttime: " << 1000 * delta / frequency << " ms" << endl;
  177.             mutex0.unlock();
  178.         }
  179. #ifdef NEGATIVE_LL
  180.         else
  181.         {
  182.             cout << ">>> p = " << p << " LucasLehmerTest negative! <<<" << endl;
  183.         }
  184. #endif
  185.     }
  186.    
  187.     mutex0.lock();
  188.     textcolor(11);
  189.     cout << "work is done for " << startP << " to " << limitP-1 << endl;
  190.     mutex0.unlock();
  191. }
  192.  
  193. int main()
  194. {
  195.     uint64_t startCount = 0, lastCount = 0, delta = 0;
  196.     QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
  197.     cout << "cpu frequency: " << frequency << " Hz" << endl;
  198.     cout << "DIVISOR_PRECHECK_K_MAX: " << DIVISOR_PRECHECK_K_MAX << endl;
  199.     cout << "number of threads: " << numberOfThreads << endl;
  200.    
  201.     ////////////////////////// Generate primes lookup table /////////////////////////////////////////////////////////////
  202.  
  203.     vector<bool> primes(primeLimit + 1); // calculated primes (low values)
  204.    
  205.     primes[0] = primes[1] = false;
  206.     for (uint64_t i = 2; i < primeLimit + 1; ++i) { primes[i] = true; }
  207.  
  208.     // Erastothenes sieving loop
  209.     uint64_t iMax = (uint64_t)sqrt((double)primeLimit) + 1;
  210.     for (uint64_t i = 2; i < iMax; ++i)
  211.     {
  212.         if (primes[i])
  213.         {
  214.             for (uint64_t j = 2 * i; j < primeLimit + 1; j += i)
  215.             {
  216.                 primes[j] = false;
  217.             }
  218.         }
  219.     }
  220.  
  221.     /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  222.  
  223.     cout << "Lucas Lehmer prime test for mersenne numbers" << endl; // https://de.wikipedia.org/wiki/Lucas-Lehmer-Test
  224.  
  225.     QueryPerformanceCounter((LARGE_INTEGER*)&startCount);
  226.  
  227.     vector<thread> t;
  228.     uint64_t deltaP = 2400;
  229.     uint64_t startP = 1;  // 57885160;
  230.     uint64_t limitP = startP + deltaP;
  231.  
  232.     for (int x = 0; x < numberOfThreads; ++x)
  233.     {
  234.         t.emplace_back(mersennePrimeCheck, primes, startCount, lastCount, startP + x * deltaP, limitP + x * deltaP);
  235.     }
  236.  
  237.     for (int x = 0; x < numberOfThreads; ++x)
  238.     {
  239.         t[x].join(); // main has to wait for the results of the threads.
  240.     }
  241. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement