Primes.
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.

sieve.c 1.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "sieve.h"
  2. #include <stdlib.h>
  3. #include <math.h>
  4. static int isprime(sieve *s, int64_t num);
  5. static void setnotprime(sieve *s, int64_t num);
  6. static void setnotprimes(sieve *s, int64_t min, int64_t max);
  7. void sieve_init(sieve *s, int64_t max)
  8. {
  9. s->nbytes = (max / 16) + 1;
  10. s->bytes = calloc(s->nbytes, 1);
  11. s->maxNum = max;
  12. s->primes = NULL;
  13. s->nprimes = 0;
  14. }
  15. void sieve_free(sieve *s)
  16. {
  17. free(s->bytes);
  18. if (s->primes != NULL)
  19. free(s->primes);
  20. }
  21. void sieve_generate(sieve *s)
  22. {
  23. // Generate primes
  24. int64_t max = s->maxNum;
  25. int64_t sqrtnum = sqrt(max);
  26. for (int64_t i = 3; i <= sqrtnum; i += 2)
  27. {
  28. if (isprime(s, i)) {
  29. setnotprimes(s, i, max);
  30. }
  31. }
  32. // Generate primes array
  33. s->nprimes = max / ((int)log(max) - 1) + 1;
  34. s->primes = calloc(s->nprimes, sizeof(int64_t));
  35. int i = 0;
  36. s->primes[i++] = 2;
  37. for (int64_t p = 3; p < max; p += 2) {
  38. if (isprime(s, p))
  39. s->primes[i++] = p;
  40. }
  41. }
  42. void sieve_factor(sieve *s, int64_t num, int64_t *buf)
  43. {
  44. int j = 0;
  45. int64_t sqrtnum = sqrt(num);
  46. for (int i = 0; i < s->nprimes; ++i)
  47. {
  48. int64_t p = s->primes[i];
  49. if (p == 0)
  50. break;
  51. if (p > sqrtnum)
  52. break;
  53. if (num % p == 0)
  54. {
  55. do
  56. {
  57. buf[j++] = p;
  58. num /= p;
  59. } while (num % p == 0);
  60. sqrtnum = sqrt(num);
  61. }
  62. }
  63. if (num != 1 || j == 0)
  64. buf[j++] = num;
  65. buf[j++] = 0;
  66. }
  67. /*
  68. * See whether a number is prime or not
  69. */
  70. static int isprime(sieve *s, int64_t num)
  71. {
  72. if (num == 2)
  73. return 1;
  74. if ((num & 1) == 0)
  75. return 0;
  76. unsigned char c = s->bytes[num >> 4];
  77. return (c & (1 << ((num % 16) >> 1))) == 0;
  78. }
  79. /*
  80. * Set number to be not prime (aka set its bit to 1)
  81. */
  82. static void setnotprime(sieve *s, int64_t num)
  83. {
  84. if ((num & 1) == 0)
  85. return;
  86. int bi = num >> 4;
  87. s->bytes[bi] = s->bytes[bi] | (1 << ((num % 16) >> 1));
  88. }
  89. static void setnotprimes(sieve *s, int64_t min, int64_t max)
  90. {
  91. int64_t j = min;
  92. min *= 2;
  93. int64_t mul = 3;
  94. while (min <= max) {
  95. setnotprime(s, min);
  96. min = j * mul;
  97. mul += 2;
  98. }
  99. }