#include <stddef.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
bool bit_read(uint64_t const* const buf, size_t const idx)
{
size_t const offset = idx >> 6; // log2(64)
uint64_t const shift = idx & 63; // 64 - 1
return buf[offset] >> shift & 0x01;
}
void bit_set(uint64_t* const buf, size_t const idx)
{
size_t const offset = idx >> 6; // log2(64)
uint64_t const shift = idx & 63; // 64 - 1
buf[offset] = buf[offset] ^ (1ull << shift);
}
void bit_unset(uint64_t* const buf, size_t const idx)
{
size_t const offset = idx >> 6; // log2(64)
uint64_t const shift = idx & 63; // 64 - 1
buf[offset] = buf[offset] & ~(1ull << shift);
}
/**
* in: bit-buffer with len many bits.
* out: bit-buffer is sieved with prime bit-indexes 2n+1 set.
*/
void eratosthenes(uint64_t* buf, size_t len)
{
memset(buf, 0xAA, len >> 3); // log2(8) from bits->bytes
bit_unset(buf, 0);
bit_unset(buf, 1);
bit_unset(buf, 2);
for(size_t i = 3; i < len; i += 2)
{
if(bit_read(buf, i))
{
for(size_t j = i * 2; j < len; j += i)
{
bit_unset(buf, j);
}
}
}
}
typedef struct
{
size_t* list;
size_t len;
size_t cap;
} List;
void list_init(List* const list)
{
list->list = malloc(8 * sizeof(size_t));
list->len = 0;
list->cap = 8;
}
void list_append(List* const list, size_t const item)
{
if(list->len + 1 > list->cap)
{
list->cap = list->cap + (list->cap >> 2); // growth by 1.5
list->list = realloc(list->list, list->cap * sizeof(size_t));
}
list->list[list->len] = item;
list->len++;
}
void list_print(List const* const list)
{
char const* comma = "";
for(size_t i = 0; i < list->len; i++)
{
printf("%s%zu", comma, list->list[i]);
comma = ", ";
}
}
void factorize(size_t const num, List* const factors, List const* const primes)
{
size_t prime_idx = 0;
size_t n = num;
while(n > 1)
{
size_t const prime = primes->list[prime_idx];
if(n % prime == 0)
{
n = n / prime;
list_append(factors, prime);
}
else
{
prime_idx++;
}
if(prime_idx > primes->len)
{
printf("out of primes\n");
abort();
}
}
}
int main()
{
size_t const NUMBER = 1000;
uint64_t* buf = malloc(NUMBER >> 3);
eratosthenes(buf, NUMBER);
List factors; list_init(&factors);
List primes; list_init(&primes);
for(size_t i = 0; i < NUMBER; i++)
{
if(bit_read(buf, i))
{
printf("prime: %zu", i);
list_append(&primes, i);
size_t const square = i * i;
printf(", square: %zu", square);
factors.len = 0;
factorize(square, &factors, &primes);
printf(", square factors: ");
list_print(&factors);
printf("\n");
}
}
return 0;
}