From 8f191a7e3f29a92035afbaced7dd9aa382ac7350 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Sat, 30 Aug 2025 19:53:50 -0500 Subject: [PATCH 1/4] bmath file --- include/bmath/bmath.hh | 1 + include/bmath/mint.hh | 4 ++-- include/bmath/sieve.hh | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 include/bmath/sieve.hh diff --git a/include/bmath/bmath.hh b/include/bmath/bmath.hh index 8c1b6d3..b297b6b 100644 --- a/include/bmath/bmath.hh +++ b/include/bmath/bmath.hh @@ -2,5 +2,6 @@ #define BMATH_BMATH_HH #include "bmath/mint.hh" +#include "bmath/sieve.hh" #endif diff --git a/include/bmath/mint.hh b/include/bmath/mint.hh index da50055..12356af 100644 --- a/include/bmath/mint.hh +++ b/include/bmath/mint.hh @@ -1,14 +1,14 @@ #ifndef BMATH_MINT_HH #define BMATH_MINT_HH -namespace bmath { - #include #include #include #include #include +namespace bmath { + inline constexpr uint64_t DEFAULT_MOD = 1'000'000'007; template (DEFAULT_MOD)> diff --git a/include/bmath/sieve.hh b/include/bmath/sieve.hh new file mode 100644 index 0000000..a0db78f --- /dev/null +++ b/include/bmath/sieve.hh @@ -0,0 +1,6 @@ +#ifndef BMATH_SIEVE_HH +#define BMATH_SIEVE_HH + +namespace bmath {}; + +#endif From 3c091551f504e314647e74d52e906187408c03af Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Sat, 30 Aug 2025 20:28:31 -0500 Subject: [PATCH 2/4] sieve of eratosthenes --- include/bmath/sieve.hh | 56 +++++++++++++++++++++++++++++++++++++++++- readme.md | 7 +++--- tests/CMakeLists.txt | 15 ++++++----- tests/test_sieve.cc | 35 ++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 tests/test_sieve.cc diff --git a/include/bmath/sieve.hh b/include/bmath/sieve.hh index a0db78f..d9886d7 100644 --- a/include/bmath/sieve.hh +++ b/include/bmath/sieve.hh @@ -1,6 +1,60 @@ #ifndef BMATH_SIEVE_HH #define BMATH_SIEVE_HH -namespace bmath {}; +#include +#include +#include +#include + +namespace bmath { + +template + requires(Limit > 0) +class Sieve { + public: + constexpr explicit Sieve() { static_cast(this)->build(); } + + protected: + std::bitset sieve; +}; + +template + requires(Limit > 0) +class Eratosthenes : public Sieve, 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 diff --git a/readme.md b/readme.md index 70350b5..9688ab3 100644 --- a/readme.md +++ b/readme.md @@ -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 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2fb3c98..822c9e4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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() diff --git a/tests/test_sieve.cc b/tests/test_sieve.cc new file mode 100644 index 0000000..19fa66d --- /dev/null +++ b/tests/test_sieve.cc @@ -0,0 +1,35 @@ +#include + +#include +#include + +#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; + } +} From 115ad715d5bb915864bfb83900f894880783d09c Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Sat, 30 Aug 2025 20:29:42 -0500 Subject: [PATCH 3/4] sieve constructor should not allocate --- include/bmath/sieve.hh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/include/bmath/sieve.hh b/include/bmath/sieve.hh index d9886d7..5df219e 100644 --- a/include/bmath/sieve.hh +++ b/include/bmath/sieve.hh @@ -12,7 +12,7 @@ template requires(Limit > 0) class Sieve { public: - constexpr explicit Sieve() { static_cast(this)->build(); } + constexpr explicit Sieve() noexcept { static_cast(this)->build(); } protected: std::bitset sieve; @@ -41,13 +41,15 @@ class Eratosthenes : public Sieve, Limit> { [[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)); + throw std::out_of_range( + std::format("cannot determine primality of {} > size of sieve {}", + number, Limit)); } } else { if (number > Limit) { - throw std::out_of_range(std::format( - "cannot determine primality of {} > LIMIT={}", number, Limit)); + throw std::out_of_range( + std::format("cannot determine primality of {} > size of sieve {}", + number, Limit)); } } From dd92d3820d6406f1c86e9083fafd40e9626c5c16 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Sat, 30 Aug 2025 20:30:57 -0500 Subject: [PATCH 4/4] update readme (sieve of e done) --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 9688ab3..32313fd 100644 --- a/readme.md +++ b/readme.md @@ -4,7 +4,7 @@ header-only c++ 23 math library ## todo -- sieves (pritchard, eratosthenes) +- sieves (pritchard) - factorization (pollard-rho, rabin-miller) - profiling - saturating arithmetic operations