Skip to content

Commit

Permalink
update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
i80287 committed Jun 3, 2024
1 parent dc69e37 commit a334dd1
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 176 deletions.
66 changes: 30 additions & 36 deletions number_theory/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,36 +1,16 @@
cmake_minimum_required(VERSION 3.5)

project(math_tests VERSION 0.1.0 LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(TestExecutables)

add_executable(eratosthene_sieve_test test_eratosthene_sieve.cpp)
list(APPEND TestExecutables eratosthene_sieve_test)

add_executable(fibonacci_num_test test_fibonacci_num.cpp)
list(APPEND TestExecutables fibonacci_num_test)

add_executable(gosper_algorithm_test test_gosper_algorithm.cpp)
list(APPEND TestExecutables gosper_algorithm_test)

add_executable(integers_128_bit_test test_integers_128_bit.cpp)
list(APPEND TestExecutables integers_128_bit_test)

add_executable(is_prime_bpsw_test test_is_prime_bpsw.cpp)
list(APPEND TestExecutables is_prime_bpsw_test)

add_executable(kronecker_symbol_test test_kronecker_symbol.cpp)
list(APPEND TestExecutables kronecker_symbol_test)

add_executable(long_int_test test_long_int.cpp)
list(APPEND TestExecutables long_int_test)

add_executable(math_functions_test test_math_functions.cpp)
list(APPEND TestExecutables math_functions_test)
project(math_tests VERSION 0.1.0 LANGUAGES CXX)

set(TestFilenames)
list(APPEND TestFilenames test_eratosthene_sieve)
list(APPEND TestFilenames test_fibonacci_num)
list(APPEND TestFilenames test_gosper_algorithm)
list(APPEND TestFilenames test_integers_128_bit)
list(APPEND TestFilenames test_is_prime_bpsw)
list(APPEND TestFilenames test_kronecker_symbol)
list(APPEND TestFilenames test_long_int)
list(APPEND TestFilenames test_math_functions)

# Empty by default
set(TEST_COMPILE_OPTIONS)
Expand Down Expand Up @@ -86,11 +66,25 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
endif()

foreach(target ${TestExecutables})
add_test(NAME ${target} COMMAND $<TARGET_FILE:${target}>)
target_link_libraries(${target} gmp gmpxx mpfr)
target_compile_options(${target} PRIVATE ${TEST_COMPILE_OPTIONS})
target_compile_definitions(${target} PRIVATE ${TEST_COMPILE_DEFINITIONS})
foreach(target_filename ${TestFilenames})
string(CONCAT target_cpp_filename ${target_filename} ".cpp")
string(CONCAT target_cxx_17 "target_cxx_17_" ${target_filename})
string(CONCAT target_cxx_20 "target_cxx_20_" ${target_filename})

add_executable(${target_cxx_17} ${target_cpp_filename})
target_link_libraries(${target_cxx_17} gmp gmpxx mpfr)
target_compile_options(${target_cxx_17} PRIVATE ${TEST_COMPILE_OPTIONS})
target_compile_definitions(${target_cxx_17} PRIVATE ${TEST_COMPILE_DEFINITIONS})
set_target_properties(${target_cxx_17} PROPERTIES CXX_STANDARD 17 CXX_EXTENSIONS OFF CXX_STANDARD_REQUIRED ON)
add_test(NAME ${target_cxx_17} COMMAND $<TARGET_FILE:${target_cxx_17}>)

add_executable(${target_cxx_20} ${target_cpp_filename})
target_link_libraries(${target_cxx_20} gmp gmpxx mpfr)
target_compile_options(${target_cxx_20} PRIVATE ${TEST_COMPILE_OPTIONS})
target_compile_definitions(${target_cxx_20} PRIVATE ${TEST_COMPILE_DEFINITIONS})
set_target_properties(${target_cxx_20} PROPERTIES CXX_STANDARD 20 CXX_EXTENSIONS OFF CXX_STANDARD_REQUIRED ON)
add_test(NAME ${target_cxx_20} COMMAND $<TARGET_FILE:${target_cxx_20}>)

endforeach()

enable_testing()
141 changes: 73 additions & 68 deletions number_theory/LongInt.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// #define NDEBUG 1

#include <algorithm>
#include <cassert>
#include <cinttypes>
#include <cmath>
Expand All @@ -11,6 +12,7 @@
#include <new>
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>

#include "fft.hpp"
Expand Down Expand Up @@ -536,10 +538,7 @@ struct LongInt {
} else {
k_ptr = other.nums_;
m_ptr = nums_;
// let compiler decide whether it is faster then 3 xors or not
size_t tmp = m;
m = k;
k = tmp;
std::swap(m, k);
}

if (unlikely(m == 0)) {
Expand Down Expand Up @@ -895,16 +894,28 @@ struct LongInt {
#endif

constexpr bool operator==(const LongInt& other) const noexcept {
return size_ == other.size_ &&
std::char_traits<char>::compare(reinterpret_cast<const char*>(nums_),
reinterpret_cast<const char*>(other.nums_),
USize() * sizeof(uint32_t)) == 0;
return size_ == other.size_ && std::equal(nums_, nums_ + USize(), other.nums_);
}

constexpr bool operator!=(const LongInt& other) const noexcept {
return !(*this == other);
}
#if CONFIG_HAS_AT_LEAST_CXX_20
constexpr std::strong_ordering operator<=>(const LongInt& other) const noexcept {
if (size_ != other.size_) {
return size_ <=> other.size_;
}

size_t usize = USize();
const uint32_t* r_end = nums_ - 1;
const uint32_t* r_nums = r_end + usize;
const uint32_t* r_other_nums = other.nums_ - 1 + usize;
for (; r_nums != r_end; r_nums--, r_other_nums--) {
if (*r_nums != *r_other_nums) {
return int64_t(*r_nums) * sign() <=> int64_t(*r_other_nums) * other.sign();
}
}

return std::strong_ordering::equivalent;
}
#else
constexpr bool operator<(const LongInt& other) const noexcept {
if (size_ != other.size_) {
return size_ < other.size_;
Expand All @@ -916,7 +927,7 @@ struct LongInt {
const uint32_t* r_other_nums = other.nums_ - 1 + usize;
for (; r_nums != r_end; r_nums--, r_other_nums--) {
if (*r_nums != *r_other_nums) {
return ssize_t(*r_nums) * sign() < ssize_t(*r_other_nums) * other.sign();
return int64_t(*r_nums) * sign() < int64_t(*r_other_nums) * other.sign();
}
}

Expand All @@ -928,12 +939,13 @@ struct LongInt {
}

constexpr bool operator<=(const LongInt& other) const noexcept {
return !(other < *this);
return !(*this > other);
}

constexpr bool operator>=(const LongInt& other) const noexcept {
return !(*this < other);
}
#endif

LongInt& operator+=(uint32_t n) {
if (unlikely(size_ == 0)) {
Expand Down Expand Up @@ -964,7 +976,7 @@ struct LongInt {
capacity_ = 2;
}

nums_[0] = -n;
nums_[0] = n;
size_ = -int32_t(n != 0);
return *this;
}
Expand Down Expand Up @@ -1098,55 +1110,65 @@ struct LongInt {
constexpr bool iszero() const noexcept {
return size_ == 0;
}

constexpr bool empty() const noexcept {
return iszero();
}

constexpr operator bool() noexcept {
return !iszero();
}

constexpr int32_t size() const noexcept {
return size_;
}

constexpr uint32_t* begin() noexcept {
return nums_;
}

constexpr uint32_t* end() noexcept {
return nums_ + USize();
}

constexpr const uint32_t* begin() const noexcept {
return nums_;
}

constexpr const uint32_t* end() const noexcept {
return nums_ + USize();
}

constexpr const uint32_t* cbegin() const noexcept {
return begin();
}
constexpr const uint32_t* cend() const noexcept {
return end();
}
constexpr std::reverse_iterator<uint32_t*> rbegin() noexcept {
return std::make_reverse_iterator(end());
}
constexpr std::reverse_iterator<uint32_t*> rend() noexcept {
return std::make_reverse_iterator(begin());
}
constexpr std::reverse_iterator<const uint32_t*> rbegin() const noexcept {
return std::make_reverse_iterator(end());
}
constexpr std::reverse_iterator<const uint32_t*> rend() const noexcept {
return std::make_reverse_iterator(begin());
}
constexpr size_t USize() const noexcept {
/**
* cast to uint32_t to force zero extension when casting to size_t
* std::abs is not used in order to make method constexpr and avoid ub
*/
// std::abs is not used in order to make method constexpr
return size_t(math_functions::uabs(size_));
}

constexpr int32_t sign() const noexcept {
return int32_t(size_ > 0) - int32_t(size_ < 0);
}

constexpr void change_sign() noexcept {
size_ = -size_;
}

void set_string(std::string_view s) {
#if CONFIG_HAS_AT_LEAST_CXX_20
const unsigned char* str_iter = std::bit_cast<const unsigned char*>(s.begin());
const unsigned char* str_end = std::bit_cast<const unsigned char*>(s.end());
#else
const unsigned char* str_iter = reinterpret_cast<const unsigned char*>(s.begin());
const unsigned char* str_end = reinterpret_cast<const unsigned char*>(s.end());
int32_t sgn = 1;
#endif
int32_t sgn = 1;
while (str_iter != str_end && !std::isdigit(*str_iter)) {
sgn = 1 - int32_t(uint32_t(*str_iter == '-') << 1);
++str_iter;
Expand Down Expand Up @@ -1373,42 +1395,31 @@ struct LongInt {
this->size_ = hi != 0 ? 3 : (mid != 0 ? 2 : low != 0);
}

Decimal(const Decimal& other) : digits_(nullptr), size_(0) {
if (other.size_) {
this->digits_ = static_cast<uint32_t*>(
longint_allocator::Allocate(other.size_ * sizeof(uint32_t)));

this->size_ = other.size_;
std::memcpy(this->digits_, other.digits_, other.size_ * sizeof(uint32_t));
Decimal(const Decimal& other) : digits_(nullptr), size_(other.size_) {
if (size_) {
digits_ =
static_cast<uint32_t*>(longint_allocator::Allocate(size_ * sizeof(uint32_t)));
std::copy_n(other.digits_, other.size_, digits_);
}
}

Decimal& operator=(const Decimal& other) {
longint_allocator::Deallocate(this->digits_);
this->digits_ = nullptr;
this->size_ = 0;
if (other.size_) {
this->digits_ = static_cast<uint32_t*>(
longint_allocator::Allocate(other.size_ * sizeof(uint32_t)));

size_ = other.size_;
std::memcpy(this->digits_, other.digits_, other.size_ * sizeof(uint32_t));
}
return *this;
return *this = Decimal(other);
}

constexpr Decimal(Decimal&& other) noexcept : size_(other.size_) {
digits_ = other.digits_;
constexpr Decimal(Decimal&& other) noexcept : digits_(other.digits_), size_(other.size_) {
other.digits_ = nullptr;
other.size_ = 0;
}

Decimal& operator=(Decimal&& other) noexcept {
longint_allocator::Deallocate(this->digits_);
this->digits_ = other.digits_;
this->size_ = other.size_;
other.digits_ = nullptr;
other.size_ = 0;
const auto tmp_other_digits = other.digits_;
const auto tmp_other_size = other.size_;
other.digits_ = nullptr;
other.size_ = 0;
longint_allocator::Deallocate(digits_);
digits_ = tmp_other_digits;
size_ = tmp_other_size;
return *this;
}

Expand Down Expand Up @@ -1455,10 +1466,7 @@ struct LongInt {
} else {
k_ptr = other.digits_;
m_ptr = this->digits_;
// let compiler decide whether it is faster then 3 xors or not
size_t tmp = m;
m = k;
k = tmp;
std::swap(m, k);
}

if (unlikely(m == 0)) {
Expand Down Expand Up @@ -1732,18 +1740,12 @@ struct LongInt {
}

constexpr bool operator==(const Decimal& other) const noexcept {
return size_ == other.size_ &&
std::char_traits<char>::compare(reinterpret_cast<const char*>(digits_),
reinterpret_cast<const char*>(other.digits_),
size_ * sizeof(uint32_t)) == 0;
}

constexpr bool operator!=(const Decimal& other) const noexcept {
return !(*this == other);
return size_ == other.size_ && std::equal(digits_, digits_ + size_, other.digits_);
}

constexpr void PopLeadingZeros() noexcept {
size_t usize = size_;
// std::find_first_of(std::make_reverse_iterator(begin))
while (usize != 0 && digits_[usize - 1] == 0) {
usize--;
}
Expand Down Expand Up @@ -1905,7 +1907,8 @@ struct LongInt {
}

static Decimal ConvertBinBase(const uint32_t* nums, size_t size) {
assert((size != 0) & ((size & (size - 1)) == 0));
assert(math_functions::is_pow2(size));
ATTRIBUTE_ASSUME(math_functions::is_pow2(size));
switch (size) {
case 0:
case 1:
Expand All @@ -1917,7 +1920,9 @@ struct LongInt {
Decimal low_dec = ConvertBinBase(nums, size / 2);
Decimal high_dec = ConvertBinBase(nums + size / 2, size / 2);

high_dec *= conv_bin_base_pows.at(math_functions::log2_floor(size) - 1);
const std::size_t idx = math_functions::log2_floor(size) - 1;
assert(idx < conv_bin_base_pows.size());
high_dec *= conv_bin_base_pows[idx];
high_dec += low_dec;
return high_dec;
}
Expand Down
2 changes: 1 addition & 1 deletion number_theory/config_macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
#define FUNCTION_MACRO __func__
#endif

#if CONFIG_HAS_CPP_ATTRIBUTE(assume)
#if CONFIG_HAS_AT_LEAST_CXX_23 && CONFIG_HAS_CPP_ATTRIBUTE(assume)
#define ATTRIBUTE_ASSUME(expr) [[assume(expr)]]
#elif CONFIG_GNUC_PREREQ(13, 0) && !defined(__clang__)
#define ATTRIBUTE_ASSUME(expr) __attribute__((assume(expr)))
Expand Down
Loading

0 comments on commit a334dd1

Please sign in to comment.