Advertisement
ijontichy

findprimes.c

Sep 29th, 2013
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.76 KB | None | 0 0
  1. #include <math.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <stdint.h>
  5.  
  6. #define PRIMESIZE sizeof(uint64_t)
  7.  
  8. static uint64_t * primes_found = NULL;
  9. static uint64_t   prime_count  = 0;
  10.  
  11. /*  
  12.  *   findPrimes(maxPrime, maxCount)
  13.  *
  14.  *  Either finds all primes up to maxPrime, or finds as many primes as
  15.  *  maxCount, whichever is reached first. 0 in one means "not a factor".
  16.  *  0 in both is disallowed, and returns 0.
  17.  *
  18.  *  Upon normal completion, it will return the amount of primes that
  19.  *  have been found in all executions.
  20.  */
  21.  
  22. uint64_t findPrimes(uint64_t maxPrime, uint64_t maxCount)
  23. {
  24.     if (maxPrime == 0 && maxCount == 0) { return 0; }
  25.  
  26.     char primeCond = maxPrime != 0;
  27.     char countCond = maxCount != 0;
  28.  
  29.     if (primes_found == NULL)
  30.     {
  31.         primes_found = malloc(PRIMESIZE);
  32.         primes_found[0] = 2;
  33.         prime_count     = 1;
  34.     }
  35.  
  36.     uint64_t prime = primes_found[prime_count-1] + 1;
  37.  
  38.     long double maxTestNum_f;
  39.     uint32_t    maxTestNum_i;
  40.  
  41.     uint64_t    curIndex;
  42.     uint64_t    curPrime;
  43.     uint8_t     isPrime;
  44.  
  45.     long double divResult_f;
  46.     uint64_t    divResult_i;
  47.  
  48.     while (1)
  49.     {
  50.         // Exit conditions
  51.         if (primeCond && maxPrime < prime)        { break; }
  52.         if (countCond && maxCount <= prime_count) { break; }
  53.  
  54.         // No number has a prime factor larger than the square root of it
  55.         maxTestNum_f = sqrtl((long double)prime);
  56.         maxTestNum_i = (uint32_t)maxTestNum_f;
  57.  
  58.         isPrime = 1;
  59.  
  60.         // Test against all previous primes
  61.        
  62.         for (curIndex = 0; curIndex < prime_count; curIndex++)
  63.         {
  64.             curPrime = primes_found[curIndex];
  65.             if (curPrime > maxTestNum_i) { break; }
  66.  
  67.             divResult_f = (long double)prime / (long double)curPrime;
  68.             divResult_i = prime / curPrime;
  69.  
  70.             if (divResult_f == (long double)divResult_i)
  71.             {
  72.                 isPrime = 0;
  73.                 break;
  74.             }
  75.         }
  76.  
  77.         if (isPrime)
  78.         {
  79.             // Extend by one prime
  80.             primes_found = realloc(primes_found, PRIMESIZE * (++prime_count));
  81.             primes_found[prime_count - 1] = prime;
  82.         }
  83.  
  84.         prime++;
  85.     }
  86.  
  87.     return prime_count;
  88. }
  89.  
  90. /*   nthPrime(index)
  91.  *
  92.  *  Finds the nth prime, assuming it's been calculated. If it hasn't
  93.  *  been calculated, return 0.
  94.  *
  95.  *  For reference: nthPrime(1) = 2, nthPrime(2) = 3, nthPrime(3) = 5
  96.  */
  97.  
  98. uint64_t nthPrime(uint64_t index)
  99. {
  100.     if (--index >= prime_count) { return 0; }
  101.     return primes_found[index];
  102. }
  103.  
  104. /*   primeIndex(checknum)
  105.  *
  106.  *  Returns the index of checknum in primes_found plus one.
  107.  *  A value of 0 means checknum is 0, 1, or composite.
  108.  */
  109.  
  110. uint64_t primeIndex(uint64_t checknum)
  111. {
  112.     // Already known cases - don't waste time on them
  113.     if (checknum <  2) { return 0; }
  114.     if (checknum == 2) { return 1; }
  115.     if (checknum == primes_found[prime_count-1]) { return prime_count; }
  116.  
  117.     if (checknum > primes_found[prime_count-1])
  118.     {
  119.         findPrimes(checknum, 0);
  120.         if (checknum != primes_found[prime_count-1]) { return 0; }
  121.     }
  122.  
  123.     uint64_t bottomSlice = 0;
  124.     uint64_t topSlice    = prime_count - 1;
  125.     uint64_t sliceRange;
  126.     uint64_t middle;
  127.     uint64_t middleItem;
  128.     uint64_t ret = 0;
  129.    
  130.     // Binary search for the index
  131.    
  132.     while (1)
  133.     {
  134.         // Once our range goes to 1, the only value left is either our check
  135.         // number or our check num is composite
  136.        
  137.         if (topSlice == bottomSlice)
  138.         {
  139.             if (primes_found[topSlice] == checknum) { ret = topSlice; break; }
  140.             else { return 0; }
  141.         }
  142.  
  143.         if (primes_found[topSlice] == checknum)    { ret = topSlice; break; }
  144.         if (primes_found[bottomSlice] == checknum) { ret = bottomSlice; break; }
  145.  
  146.         sliceRange = topSlice - bottomSlice;
  147.         middle = (topSlice + bottomSlice) / 2;
  148.         middleItem = primes_found[middle];
  149.  
  150.         if (middleItem == checknum) { ret = middle; break; }
  151.  
  152.         if (middleItem > checknum) { topSlice -= (sliceRange / 2); }
  153.         else { bottomSlice += (sliceRange / 2); }
  154.     }
  155.  
  156.     return ret + 1;
  157. }
  158.  
  159.  
  160. /*   primeFactors(tofactor, **retfactors)
  161.  *  
  162.  *  Returns a value equal to the amount of prime factors in the number
  163.  *  tofactor. The prime factors are stored in the uint64_t* address
  164.  *  given to us. The values in retfactors, when multiplied together,
  165.  *  will get you tofactor.
  166.  *
  167.  *  Example:
  168.  *
  169.  *  uint64_t * factors;
  170.  *  uint32_t factorcount = primeFactors(29374, &factors);
  171.  *
  172.  *  gets you:
  173.  *
  174.  *  factors     = {2, 19, 773}
  175.  *  factorcount = 3
  176.  */
  177.  
  178. uint32_t primeFactors(uint64_t tofactor, uint64_t ** retfactors)
  179. {
  180.     uint64_t * factors = NULL;
  181.     uint32_t factorcount = 0;
  182.     uint32_t i, curPrime;
  183.  
  184.     long double maxTestNum_f;
  185.     uint32_t    maxTestNum_i;
  186.  
  187.     long double divResult_f;
  188.     uint64_t    divResult_i;
  189.  
  190.     uint8_t     noMoreFactors = 0;
  191.  
  192.     while (1)
  193.     {
  194.         // No number has a prime factor larger than the square root of it
  195.         maxTestNum_f = sqrtl((long double)tofactor);
  196.         maxTestNum_i = (uint32_t)maxTestNum_f;
  197.        
  198.         i = 1;
  199.  
  200.         while (1)
  201.         {
  202.             curPrime = nthPrime(i);
  203.             if (curPrime == 0) { findPrimes(0, i); }
  204.  
  205.             // Once we're looking above the square root, we've exhausted all factors
  206.             if (curPrime > maxTestNum_i) { noMoreFactors = 1; break; }
  207.            
  208.             divResult_f = (long double)tofactor / (long double)curPrime;
  209.             divResult_i = tofactor / curPrime;
  210.  
  211.             if (divResult_f == (long double)divResult_i)
  212.             {
  213.                 tofactor = divResult_i;
  214.                 break;
  215.             }
  216.  
  217.             i++;
  218.         }
  219.            
  220.         if (noMoreFactors)
  221.         {
  222.             factors = realloc(factors, sizeof(uint64_t) * (++factorcount));
  223.             factors[factorcount-1] = tofactor;
  224.             break;
  225.         }
  226.         else
  227.         {
  228.             factors = realloc(factors, sizeof(uint64_t) * (++factorcount));
  229.             factors[factorcount-1] = curPrime;
  230.         }
  231.     }
  232.  
  233.     *retfactors = factors;
  234.     return factorcount;
  235. };
  236.  
  237. int main(void)
  238. {
  239.     uint64_t gotoPrime = 10001;
  240.     uint64_t testPrime = 1298909;  // known prime
  241.     uint64_t testNum   = 29374;  // known composite
  242.     uint64_t index;
  243.     uint64_t * factors;
  244.     uint32_t factorcount;
  245.  
  246.     printf("Found %lu primes\n", findPrimes(0, gotoPrime));
  247.     printf("Prime %lu is %lu\n", gotoPrime, nthPrime(gotoPrime));
  248.  
  249.     index = primeIndex(testPrime);
  250.     printf("Prime index of %lu is %lu\n", testPrime, index);
  251.     printf("Reverse lookup - %lu = nthPrime(%lu) = %lu\n", testPrime, index, nthPrime(index));
  252.  
  253.     factorcount = primeFactors(testNum, &factors);
  254.  
  255.     printf("%lu has %u prime factors:\n", testNum, factorcount);
  256.  
  257.     uint32_t i;
  258.  
  259.     for (i = 0; i < factorcount; i++)
  260.     {
  261.         printf(" * %lu\n", factors[i]);
  262.     }
  263.  
  264.     return 0;
  265. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement