@kimee kimee / prime_square_sieve.c
Created at Sun Aug 21 14:24:07 EDT 2022
A prime sieve and a prime-factorizer to find primes who's squares have only the prime as factors. Turns out its all of them.
prime_square_sieve.c
Raw
#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;
}