Skip to content

Commit

Permalink
Begin initial work on creating usable big_int type
Browse files Browse the repository at this point in the history
  • Loading branch information
Rinzii committed Apr 6, 2024
1 parent b6d07b8 commit 3d2bd0b
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 1 deletion.
1 change: 1 addition & 0 deletions ccmath_headers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ set(ccmath_internal_types_headers
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/types/number_pair.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/types/sign.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/types/float128.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/types/big_int.hpp
)


Expand Down
93 changes: 93 additions & 0 deletions include/ccmath/internal/types/big_int.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2024-Present Ian Pike
* Copyright (c) 2024-Present ccmath contributors
*
* This library is provided under the MIT License.
* See LICENSE for more information.
*/

#pragma once

#include <array>
#include <climits>
#include <cstddef>
#include <cstdint>
#include <type_traits>

namespace ccm
{

template <size_t Bits, bool Signed, typename WordType = std::uint64_t>
struct BigInt
{
private:
static_assert(std::is_integral_v<WordType> && std::is_unsigned_v<WordType>, "WordType must be unsigned integer.");

struct Division
{
BigInt quotient;
BigInt remainder;
};

public:
using word_type = WordType;
using unsigned_type = BigInt<Bits, false, word_type>;
using signed_type = BigInt<Bits, true, word_type>;

static constexpr bool is_signed = Signed;
static constexpr std::size_t bits = Bits;
static constexpr std::size_t word_size = sizeof(word_type) * CHAR_BIT;

static_assert(Bits > 0 && Bits % word_size == 0, "Number of bits in BigInt should be a multiple of word_size.");

static constexpr std::size_t word_count = Bits / word_size;

std::array<word_type, word_count> data{};

constexpr BigInt() = default;
constexpr BigInt(const BigInt & other) = default;

/**
* @brief Extend the internal representation of the big integer by filling remaining words with a specific value.
* @param index The starting index from where the extension should begin.
* @param is_negative Boolean flag indicating whether the big integer is negative.
* @return void
*/
constexpr void extend(std::size_t index, bool is_negative)
{
const word_type value = is_negative ? std::numeric_limits<word_type>::max() : std::numeric_limits<word_type>::min();
for (size_t i = index; i < word_count; ++i) { data[i] = value; }
}

template <std::size_t OtherBits, bool OtherSigned>
constexpr BigInt(const BigInt<OtherBits, OtherSigned, word_type> & other)
{
if constexpr (OtherBits > Bits) // truncate bits
{
for (std::size_t i = 0; i < word_count; ++i) { data[i] = other.data[i]; }
}
else // Will be zero or sign extended
{
size_t i = 0;
for (; i < OtherBits / word_size; ++i) { data[i] = other.data[i]; }
extend(i, Signed && other.is_neg());
}
}

/**
* @brief Construct a BigInt from a C-style array of words.
* @tparam N The size of the array.
* @param nums The C-style array of words.
*/
template <size_t N>
constexpr BigInt(const WordType (&nums)[N]) // NOLINT
{
static_assert(N == word_count);
for (size_t i = 0; i < word_count; ++i) { data[i] = nums[i]; }
}

constexpr explicit BigInt(const std::array<WordType, word_count> & words) : data(words) {}


};
} // namespace ccm
15 changes: 14 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,18 @@ target_link_libraries(${PROJECT_NAME}-misc PRIVATE
)


# Tests for internal items
add_executable(${PROJECT_NAME}-internal-types)
target_sources(${PROJECT_NAME}-internal-types PRIVATE
internal/types/big_int_test.cpp

)
target_link_libraries(${PROJECT_NAME}-internal-types PRIVATE
ccmath::test
gtest::gtest
)


if(CCMATH_OS_WINDOWS)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
Expand All @@ -159,5 +171,6 @@ add_test(NAME ${PROJECT_NAME}-nearest COMMAND ${PROJECT_NAME}-nearest)
add_test(NAME ${PROJECT_NAME}-power COMMAND ${PROJECT_NAME}-power)
add_test(NAME ${PROJECT_NAME}-misc COMMAND ${PROJECT_NAME}-misc)


# Internal tests
add_test(NAME ${PROJECT_NAME}-internal-types COMMAND ${PROJECT_NAME}-internal-types)

22 changes: 22 additions & 0 deletions test/internal/types/big_int_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2024-Present Ian Pike
* Copyright (c) 2024-Present ccmath contributors
*
* This library is provided under the MIT License.
* See LICENSE for more information.
*/

#include <gtest/gtest.h>

#include "ccmath/internal/types/big_int.hpp"

TEST(CcmathInternalTypesTests, BigIntTest)
{
ccm::BigInt<64, false> a;
auto t1 = ccm::BigInt<64, false>::bits;
auto t2 = ccm::BigInt<64, false>::is_signed;

EXPECT_EQ(t1, 64);
EXPECT_EQ(t2, false);
}

0 comments on commit 3d2bd0b

Please sign in to comment.