Advertisement
Guest User

main.c

a guest
Feb 5th, 2022
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.71 KB | None | 0 0
  1. #include "prime.h"
  2.  
  3. typedef struct {
  4.     uint64_t p;
  5.     uint64_t sp;
  6. } np_t;
  7.  
  8. static np_t fillBase(uint32_t *p, np_t n, unsigned char *f, uint64_t st,
  9. uint64_t end, uint64_t lim) {
  10.     #define push(a) do {\
  11.         *p_ = st + i * 30 + a;\
  12.         if (*p_ < L1C / 8) ++n.sp;\
  13.         if (sq(*p_++) > lim) return (np_t){p_ - p + n.p, n.sp};\
  14.     } while (0)
  15.     p += n.p;
  16.     uint32_t *p_ = p;
  17.     unsigned i = 0;
  18.     do {
  19.         if (f[i] & 1 << 0) {
  20.             push(1);
  21.         }
  22.         if (f[i] & 1 << 1) {
  23.             push(7);
  24.         }
  25.         if (f[i] & 1 << 2) {
  26.             push(11);
  27.         }
  28.         if (f[i] & 1 << 3) {
  29.             push(13);
  30.         }
  31.         if (f[i] & 1 << 4) {
  32.             push(17);
  33.         }
  34.         if (f[i] & 1 << 5) {
  35.             push(19);
  36.         }
  37.         if (f[i] & 1 << 6) {
  38.             push(23);
  39.         }
  40.         if (f[i] & 1 << 7) {
  41.             push(29);
  42.         }
  43.     } while (st + ++i * 30 < end);
  44.     return (np_t){p_ - p + n.p, n.sp};
  45.     #undef push
  46. }
  47.  
  48. static void sieve(unsigned char *f, uint64_t st, uint32_t *p, unsigned nsp) {
  49.     memset(f, -1, BC);
  50.     unsigned i = 0;
  51.     do {
  52.         uint64_t sti30 = st + i * 30;
  53.         sieve_7_13(f + i, sti30);
  54.         sieve_17(f + i, sti30);
  55.         sieve_19(f + i, sti30);
  56.         sieve_23(f + i, sti30);
  57.         sieve_29(f + i, sti30);
  58.         sieve_31(f + i, sti30);
  59.         sieve_37(f + i, sti30);
  60.         sieve_41(f + i, sti30);
  61.         sieve_43(f + i, sti30);
  62.         sieve_47(f + i, sti30);
  63.         sieve_53(f + i, sti30);
  64.         sieve_59(f + i, sti30);
  65.         sieve_61(f + i, sti30);
  66.         sieve_67(f + i, sti30);
  67.         sieve_71(f + i, sti30);
  68.         sieve_73(f + i, sti30);
  69.         sieve_79(f + i, sti30);
  70.         sieve_83(f + i, sti30);
  71.         sieve_89(f + i, sti30);
  72.         sieve_93_(f + i, sti30, p, nsp);
  73.     } while ((i += L1C) < BC);
  74.     sieve_93_(f, st, p + nsp, -1);
  75. }
  76.  
  77. static unsigned count(unsigned char *f) {
  78.     unsigned c = 0;
  79.     unsigned i = 0;
  80.     do {
  81.         uint64_t qf;
  82.         memcpy(&qf, f + i + 8 * 0, sizeof(qf));
  83.         c += __builtin_popcountll(qf);
  84.         memcpy(&qf, f + i + 8 * 1, sizeof(qf));
  85.         c += __builtin_popcountll(qf);
  86.         memcpy(&qf, f + i + 8 * 2, sizeof(qf));
  87.         c += __builtin_popcountll(qf);
  88.         memcpy(&qf, f + i + 8 * 3, sizeof(qf));
  89.         c += __builtin_popcountll(qf);
  90.         memcpy(&qf, f + i + 8 * 4, sizeof(qf));
  91.         c += __builtin_popcountll(qf);
  92.         memcpy(&qf, f + i + 8 * 5, sizeof(qf));
  93.         c += __builtin_popcountll(qf);
  94.         memcpy(&qf, f + i + 8 * 6, sizeof(qf));
  95.         c += __builtin_popcountll(qf);
  96.         memcpy(&qf, f + i + 8 * 7, sizeof(qf));
  97.         c += __builtin_popcountll(qf);
  98.     } while ((i += 8 * 8) < BC);
  99.     return c;
  100. }
  101.  
  102. static uint64_t countPrimes(uint64_t lim) {
  103.     _Alignas(64) unsigned char f[BC + 256];
  104.     uint32_t *p = aligned_alloc(64, sqrt(lim));
  105.     unsigned bfsz = 256;
  106.     np_t n = fillBase(p, (np_t){0}, countPrimes_bf, 0, bfsz * 30, -1);
  107.     sieve(f, 0, p, n.sp);
  108.     uint64_t c = count(f);
  109.     unsigned r = lim % 30;
  110.     if (!r) {
  111.         --lim;
  112.     } else if (1 < r && r < 7) {
  113.         lim -= r - 1;
  114.     } else if (7 < r && r < 11) {
  115.         lim -= r - 7;
  116.     } else if (13 < r && r < 17) {
  117.         lim -= r - 13;
  118.     } else if (r == 18) {
  119.         --lim;
  120.     } else if (19 < r && r < 23) {
  121.         lim -= r - 19;
  122.     } else if (23 < r && r < 29) {
  123.         lim -= r - 23;
  124.     }
  125.     unsigned bc30 = BC * 30;
  126.     r = lim % bc30;
  127.     uint64_t lim_ = lim - r + bc30;
  128.     n = fillBase(p, n, f + bfsz, bfsz * 30, bc30, lim_);
  129.     uint64_t st = bc30;
  130.     for (; st + bc30 < lim_; st += bc30) {
  131.         sieve(f, st, p, n.sp);
  132.         if (sq(st + 1) < lim_) {
  133.             n = fillBase(p, n, f, st, st + bc30, lim_);
  134.         }
  135.         c += count(f);
  136.     }
  137.     sieve(f, st, p, n.sp);
  138.     unsigned q = r / 30;
  139.     memset(f + q + 1, 0, BC - q);
  140.     f[q] &= countPrimes_rm[r % 30 / 2];
  141.     c += count(f);
  142.     return c + 5;
  143. }
  144.  
  145. int main(int argc, char **argv) {
  146.     if (argc != 2) {
  147.         puts("must have 1 argument");
  148.         return 1;
  149.     }
  150.     L1C = sysconf(_SC_LEVEL1_DCACHE_SIZE) - (1 << 12);
  151.     BC = L1C * 8;
  152.     uint64_t lim = strtod(argv[1], 0);
  153.     if (lim < 100000000) {
  154.         puts("input < 1e8");
  155.         return 1;
  156.     }
  157.     printf("%"PRIu64"\n", countPrimes(lim));
  158.     return 0;
  159. }
  160.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement