sieve of eratosthenes

This commit is contained in:
Barrett Ruth 2025-08-30 20:28:31 -05:00
parent 8f191a7e3f
commit 3c091551f5
4 changed files with 103 additions and 10 deletions

View file

@ -1,6 +1,60 @@
#ifndef BMATH_SIEVE_HH
#define BMATH_SIEVE_HH
namespace bmath {};
#include <bitset>
#include <cstdint>
#include <format>
#include <stdexcept>
namespace bmath {
template <typename Derived, size_t Limit>
requires(Limit > 0)
class Sieve {
public:
constexpr explicit Sieve() { static_cast<Derived *>(this)->build(); }
protected:
std::bitset<Limit + 1> sieve;
};
template <size_t Limit>
requires(Limit > 0)
class Eratosthenes : public Sieve<Eratosthenes<Limit>, Limit> {
public:
constexpr void build() noexcept {
this->sieve.set();
this->sieve[0] = false;
this->sieve[1] = false;
for (size_t x = 2; x * x <= Limit; ++x) {
if (!this->sieve[x]) {
continue;
}
for (size_t current = x + x; current <= Limit; current += x) {
this->sieve[current] = false;
}
}
}
[[nodiscard]] constexpr bool operator[](size_t const number) const {
if consteval {
if (number > Limit) {
throw std::out_of_range(std::format(
"cannot determine primality of {} > LIMIT={}", number, Limit));
}
} else {
if (number > Limit) {
throw std::out_of_range(std::format(
"cannot determine primality of {} > LIMIT={}", number, Limit));
}
}
return this->sieve[number];
};
};
} // namespace bmath
#endif

View file

@ -4,6 +4,7 @@ header-only c++ 23 math library
## todo
[] sieves
[] factorization
[x] `std::unsigned_integral` as modulus type
- sieves (pritchard, eratosthenes)
- factorization (pollard-rho, rabin-miller)
- profiling
- saturating arithmetic operations

View file

@ -2,16 +2,19 @@ include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.14.0
)
GIT_TAG v1.14.0)
set(gtest_force_shared_crt
ON
CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
add_executable(test_bmath test_bmath.cc)
file(GLOB TEST_SOURCES "*.cc")
target_link_libraries(test_bmath PRIVATE bmath::bmath gtest_main)
foreach(TEST_SOURCE ${TEST_SOURCES})
get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE)
add_executable(${TEST_NAME} ${TEST_SOURCE})
target_link_libraries(${TEST_NAME} PRIVATE bmath::bmath gtest_main)
include(GoogleTest)
gtest_discover_tests(test_bmath)
include(GoogleTest)
gtest_discover_tests(${TEST_NAME})
endforeach()

35
tests/test_sieve.cc Normal file
View file

@ -0,0 +1,35 @@
#include <gtest/gtest.h>
#include <cstdint>
#include <format>
#include "../include/bmath/bmath.hh"
using namespace bmath;
bool naive_prime(size_t n) {
if (n < 2) {
return false;
}
if (n == 2) {
return true;
}
if (n % 2 == 0) {
return false;
}
for (size_t i = 3; i * i <= n; i += 2) {
if (n % i == 0) return false;
}
return true;
}
TEST(SieveTest, BasicConstruction) { Eratosthenes<100> sieve; }
TEST(SieveTest, ValidateAgainstNaive) {
Eratosthenes<1000> sieve;
for (size_t i = 0; i <= 1000; ++i) {
EXPECT_EQ(sieve[i], naive_prime(i))
<< "Sieve disagrees with naive checker for " << i;
}
}