mirror of
https://github.com/boostorg/math.git
synced 2026-01-24 18:12:09 +00:00
Tests and performance compairsons [WIP][CI SKIP]
This commit is contained in:
@@ -306,22 +306,13 @@ void sub_linear_wheel_sieve(Z upper_bound, Container &resultant_primes)
|
||||
Z Mk {2};
|
||||
Z k {3};
|
||||
resultant_primes.emplace_back(static_cast<Z>(2));
|
||||
for(; true; k += 2)
|
||||
{
|
||||
if(is_prime(k))
|
||||
{
|
||||
if(Mk * k > limit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Mk *= k;
|
||||
resultant_primes.emplace_back(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
while(Mk * k <= limit)
|
||||
{
|
||||
Mk *= k;
|
||||
resultant_primes.emplace_back(k);
|
||||
k += 2;
|
||||
}
|
||||
|
||||
// Initialze wheel wk
|
||||
std::vector<Z> wk;
|
||||
@@ -372,8 +363,9 @@ void sub_linear_wheel_sieve(Z upper_bound, Container &resultant_primes)
|
||||
}
|
||||
|
||||
// Step 3 - Run the linear algorithm starting with p := next(S, 1), which is p_k+1
|
||||
// next(S, 1) = S[1]
|
||||
// 4 - A linear Algorithm
|
||||
Z p {2};
|
||||
Z p {S[1]};
|
||||
|
||||
while(p * p <= upper_bound)
|
||||
{
|
||||
|
||||
@@ -5,9 +5,94 @@
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/math/special_functions/prime_sieve.hpp>
|
||||
#include "../../include/boost/math/special_functions/prime_sieve.hpp"
|
||||
//#include <boost/math/special_functions/prime_sieve.hpp>
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <primesieve.hpp>
|
||||
#include <vector>
|
||||
|
||||
// Individual Algos
|
||||
// Linear
|
||||
template<class Z>
|
||||
inline auto linear_sieve_helper(Z upper_bound, std::vector<Z> c) -> std::vector<Z>
|
||||
{
|
||||
boost::math::detail::linear_sieve(upper_bound, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
template<class Z>
|
||||
void linear_sieve(benchmark::State& state)
|
||||
{
|
||||
Z upper = static_cast<Z>(state.range(0));
|
||||
for(auto _ : state)
|
||||
{
|
||||
std::vector<Z> primes;
|
||||
benchmark::DoNotOptimize(linear_sieve_helper(upper, primes));
|
||||
}
|
||||
state.SetComplexityN(state.range(0));
|
||||
}
|
||||
|
||||
template<class Z>
|
||||
inline auto sub_linear_sieve_helper(Z upper_bound, std::vector<Z> c) -> std::vector<Z>
|
||||
{
|
||||
boost::math::detail::sub_linear_wheel_sieve(upper_bound, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
template<class Z>
|
||||
void sub_linear_sieve(benchmark::State& state)
|
||||
{
|
||||
Z upper = static_cast<Z>(state.range(0));
|
||||
for(auto _ : state)
|
||||
{
|
||||
std::vector<Z> primes;
|
||||
benchmark::DoNotOptimize(sub_linear_sieve_helper(upper, primes));
|
||||
}
|
||||
state.SetComplexityN(state.range(0));
|
||||
}
|
||||
|
||||
// Segmented
|
||||
template<class Z>
|
||||
inline auto mask_sieve_helper(Z lower_bound, Z upper_bound, std::vector<Z> c) -> std::vector<Z>
|
||||
{
|
||||
boost::math::detail::mask_sieve(lower_bound, upper_bound, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
template<class Z>
|
||||
void mask_sieve(benchmark::State& state)
|
||||
{
|
||||
Z lower = static_cast<Z>(2);
|
||||
Z upper = static_cast<Z>(state.range(0));
|
||||
for(auto _ : state)
|
||||
{
|
||||
std::vector<Z> primes;
|
||||
benchmark::DoNotOptimize(mask_sieve_helper(lower, upper, primes));
|
||||
}
|
||||
state.SetComplexityN(state.range(0));
|
||||
}
|
||||
|
||||
template<class Z>
|
||||
inline auto segmented_wheel_sieve_helper(Z lower_bound, Z upper_bound, std::vector<Z> c) -> std::vector<Z>
|
||||
{
|
||||
boost::math::detail::linear_segmented_wheel_sieve(lower_bound, upper_bound, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
template<class Z>
|
||||
void segmented_wheel_sieve(benchmark::State& state)
|
||||
{
|
||||
Z lower = static_cast<Z>(2);
|
||||
Z upper = static_cast<Z>(state.range(0));
|
||||
for(auto _ : state)
|
||||
{
|
||||
std::vector<Z> primes;
|
||||
benchmark::DoNotOptimize(segmented_wheel_sieve_helper(lower, upper, primes));
|
||||
}
|
||||
state.SetComplexityN(state.range(0));
|
||||
}
|
||||
|
||||
// Complete Implementations
|
||||
template <class Z>
|
||||
void prime_sieve(benchmark::State& state)
|
||||
{
|
||||
@@ -33,11 +118,39 @@ void prime_sieve_partial_range(benchmark::State& state)
|
||||
state.SetComplexityN(state.range(0));
|
||||
}
|
||||
|
||||
template <class Z>
|
||||
void kimwalish_primes(benchmark::State& state)
|
||||
{
|
||||
|
||||
Z upper = static_cast<Z>(state.range(0));
|
||||
for (auto _ : state)
|
||||
{
|
||||
std::vector<Z> primes;
|
||||
primesieve::generate_primes(upper, &primes);
|
||||
benchmark::DoNotOptimize(primes.back());
|
||||
}
|
||||
state.SetComplexityN(state.range(0));
|
||||
}
|
||||
|
||||
// Individual Algos
|
||||
|
||||
// Linear
|
||||
BENCHMARK_TEMPLATE(linear_sieve, int64_t)->RangeMultiplier(2)->Range(1 << 1, 1 << 16)->Complexity(benchmark::oN);
|
||||
BENCHMARK_TEMPLATE(sub_linear_sieve, int64_t)->RangeMultiplier(2)->Range(1 << 1, 1 << 16)->Complexity();
|
||||
|
||||
|
||||
// Segmented
|
||||
BENCHMARK_TEMPLATE(mask_sieve, int64_t)->RangeMultiplier(2)->Range(1 << 2, 2 << 22)->Complexity(benchmark::oNLogN);
|
||||
BENCHMARK_TEMPLATE(segmented_wheel_sieve, int64_t)->RangeMultiplier(2)->Range(1 << 2, 2 << 22)->Complexity();
|
||||
|
||||
/*
|
||||
// Complete Implementations
|
||||
BENCHMARK_TEMPLATE(prime_sieve, int32_t)->RangeMultiplier(2)->Range(1 << 1, 1 << 22)->Complexity()->UseRealTime();
|
||||
BENCHMARK_TEMPLATE(prime_sieve, int64_t)->RangeMultiplier(2)->Range(1 << 1, 1 << 30)->Complexity()->UseRealTime();
|
||||
BENCHMARK_TEMPLATE(prime_sieve, int64_t)->RangeMultiplier(2)->Range(1 << 1, 1 << 30)->Complexity(benchmark::oN)->UseRealTime();
|
||||
BENCHMARK_TEMPLATE(kimwalish_primes, int64_t)->RangeMultiplier(2)->Range(1 << 1, 1 << 30)->Complexity(benchmark::oN)->UseRealTime();
|
||||
BENCHMARK_TEMPLATE(prime_sieve, uint32_t)->RangeMultiplier(2)->Range(1 << 1, 1 << 22)->Complexity()->UseRealTime();
|
||||
BENCHMARK_TEMPLATE(prime_sieve_partial_range, int32_t)->RangeMultiplier(2)->Range(1 << 1, 1 << 22)->Complexity()->UseRealTime();
|
||||
BENCHMARK_TEMPLATE(prime_sieve_partial_range, int64_t)->RangeMultiplier(2)->Range(1 << 1, 1 << 22)->Complexity()->UseRealTime();
|
||||
BENCHMARK_TEMPLATE(prime_sieve_partial_range, uint32_t)->RangeMultiplier(2)->Range(1 << 1, 1 << 22)->Complexity()->UseRealTime();
|
||||
|
||||
*/
|
||||
BENCHMARK_MAIN();
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/math/special_functions/prime_sieve.hpp>
|
||||
#include "../include/boost/math/special_functions/prime_sieve.hpp"
|
||||
//#include <boost/math/special_functions/prime_sieve.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
#include <list>
|
||||
@@ -23,6 +24,11 @@ void test_prime_sieve()
|
||||
BOOST_TEST_EQ(primes.size(), ref);
|
||||
|
||||
// Tests for correctness
|
||||
// 2
|
||||
primes.clear();
|
||||
boost::math::prime_sieve(2, std::back_inserter(primes));
|
||||
BOOST_TEST_EQ(primes.size(), 0);
|
||||
|
||||
// 100
|
||||
primes.clear();
|
||||
boost::math::prime_sieve(100, std::back_inserter(primes));
|
||||
@@ -92,6 +98,51 @@ void test_prime_range()
|
||||
BOOST_TEST_EQ(primes.size(), ref);
|
||||
}
|
||||
|
||||
template<typename Z>
|
||||
void test_sub_linear_prime_sieve()
|
||||
{
|
||||
std::vector<Z> primes;
|
||||
|
||||
// Does the function work with a vector
|
||||
boost::math::detail::sub_linear_wheel_sieve(100, primes);
|
||||
BOOST_TEST_EQ(primes.size(), 25);
|
||||
|
||||
// 1'000
|
||||
primes.clear();
|
||||
boost::math::detail::sub_linear_wheel_sieve(1'000, primes);
|
||||
BOOST_TEST_EQ(primes.size(), 168);
|
||||
|
||||
// 10'000
|
||||
primes.clear();
|
||||
boost::math::detail::sub_linear_wheel_sieve(10'000, primes);
|
||||
BOOST_TEST_EQ(primes.size(), 1229);
|
||||
}
|
||||
|
||||
template<typename Z>
|
||||
void test_linear_segmented_sieve()
|
||||
{
|
||||
std::vector<Z> primes;
|
||||
|
||||
// 10 - 20: Tests only step 1
|
||||
boost::math::detail::linear_segmented_wheel_sieve(10, 20, primes);
|
||||
BOOST_TEST_EQ(primes.size(), 4);
|
||||
|
||||
// 100 - 200: Tests step 2
|
||||
primes.clear();
|
||||
boost::math::detail::linear_segmented_wheel_sieve(100, 200, primes);
|
||||
BOOST_TEST_EQ(primes.size(), 21);
|
||||
|
||||
// 100 - 1'000
|
||||
primes.clear();
|
||||
boost::math::detail::linear_segmented_wheel_sieve(100, 1'000, primes);
|
||||
BOOST_TEST_EQ(primes.size(), 143);
|
||||
|
||||
// 1'000 - 10'000
|
||||
primes.clear();
|
||||
boost::math::detail::linear_segmented_wheel_sieve(1'000, 10'000, primes);
|
||||
BOOST_TEST_EQ(primes.size(), 1061);
|
||||
}
|
||||
|
||||
template<typename Z>
|
||||
void test_prime_sieve_overflow()
|
||||
{
|
||||
@@ -159,6 +210,17 @@ void test_par_prime_sieve_large()
|
||||
|
||||
int main()
|
||||
{
|
||||
test_sub_linear_prime_sieve<int>();
|
||||
test_sub_linear_prime_sieve<int32_t>();
|
||||
test_sub_linear_prime_sieve<int64_t>();
|
||||
test_sub_linear_prime_sieve<uint32_t>();
|
||||
|
||||
test_linear_segmented_sieve<int>();
|
||||
test_linear_segmented_sieve<int32_t>();
|
||||
test_linear_segmented_sieve<int64_t>();
|
||||
test_linear_segmented_sieve<uint32_t>();
|
||||
|
||||
/*
|
||||
test_prime_sieve<int>();
|
||||
test_prime_sieve<int32_t>();
|
||||
test_prime_sieve<int64_t>();
|
||||
@@ -181,6 +243,6 @@ int main()
|
||||
|
||||
//test_par_prime_sieve_large<int64_t>();
|
||||
#endif
|
||||
|
||||
*/
|
||||
boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user