From 2305d71d4ac7b0a339d5aefdf395631f0f38d6d0 Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Wed, 14 May 2025 21:35:58 -0400 Subject: [PATCH] Sketching out bit_integer class --- include/bitlib/bit-containers/bit_integer.hpp | 174 ++++++++++++++++++ test/CMakeLists.txt | 1 + test/src/test-integer.cpp | 28 +++ 3 files changed, 203 insertions(+) create mode 100644 include/bitlib/bit-containers/bit_integer.hpp create mode 100644 test/src/test-integer.cpp diff --git a/include/bitlib/bit-containers/bit_integer.hpp b/include/bitlib/bit-containers/bit_integer.hpp new file mode 100644 index 00000000..f8a81a88 --- /dev/null +++ b/include/bitlib/bit-containers/bit_integer.hpp @@ -0,0 +1,174 @@ +// ================================= BIT_ARRAY_BASE =================================== // +// Project: The Experimental Bit Algorithms Library +// \file bit_integer.hpp +// Description: Base implementation for bit_array variants +// Creator: Vincent Reverdy +// Contributor: Peter McLean [2025] +// License: BSD 3-Clause License +// ========================================================================== // +#ifndef _BIT_INTEGER_HPP_INCLUDED +#define _BIT_INTEGER_HPP_INCLUDED + +// C++ standard library +#include +#include +#include +#include // memcpy +#include +#include +#include +#include + +// Project sources +#include "bitlib/bit-algorithms/bit_algorithm.hpp" +#include "bitlib/bit-containers/bit_array.hpp" +#include "bitlib/bit-containers/bit_bitsof.hpp" +#include "bitlib/bit-iterator/bit.hpp" + +namespace bit { + +template +class bit_integer : public bit_array { + public: + using base_class = bit_array; + + private: + // Hide bit_array methods specific to containerization + // so that this type is focused on arithmetic and native-like look and feel. + // The type can still be downcasted to get a bit_array; + using base_class::at; + using base_class::begin; + using base_class::cbegin; + using base_class::cend; + using base_class::data; + using base_class::empty; + using base_class::end; + using base_class::max_size; + using base_class::size; + using base_class::operator[]; + using base_class::operator(); + using base_class::debug_string; + using base_class::fill; + + public: + // Use select type + using typename base_class::size_type; + using typename base_class::word_type; + + // Use all of bit_array constructors + using bit_array::bit_array; + + // Must define some of our own constructors + constexpr bit_integer(const base_class& other) : base_class(other) {} + + constexpr bool operator==(const base_class& other) const { + return static_cast(*this) == other; + } + + constexpr bool operator==(const bit_sized_range auto& other) const { + return static_cast(*this) == other; + } + + constexpr bit_integer& operator++() { + unsigned char carry = 1; + ::bit::transform(begin(), end(), begin(), + [&carry](const word_type& a) -> word_type { + word_type result; + carry = ::bit::add_carry(carry, a, static_cast(0), &result); + return result; + }); + return *this; + } + + constexpr bit_integer operator++(int) { + bit_integer old = *this; + ++(*this); + return old; + } + + constexpr bit_integer& operator--() { + unsigned char carry = 1; + ::bit::transform(begin(), end(), begin(), + [&carry](const word_type& a) -> word_type { + word_type result; + carry = ::bit::sub_borrow(carry, a, static_cast(0), &result); + return result; + }); + return *this; + } + + constexpr bit_integer operator--(int) { + bit_integer old = *this; + --(*this); + return old; + } + + constexpr bit_integer operator+(const bit_integer& other) const { + bit_integer result; + + unsigned char carry = 0; + ::bit::transform(begin(), end(), other.begin(), result.begin(), + [&carry](const word_type& a, const word_type& b) -> word_type { + word_type result; + carry = ::bit::add_carry(carry, a, b, &result); + return result; + }); + return result; + } + + constexpr bit_integer& operator+=(const bit_integer& other) { + unsigned char carry = 0; + ::bit::transform(begin(), end(), other.begin(), begin(), + [&carry](const word_type& a, const word_type& b) -> word_type { + word_type result; + carry = ::bit::add_carry(carry, a, b, &result); + return result; + }); + return *this; + } + + constexpr bit_integer& operator-(const bit_integer& other) const { + bit_integer result; + + unsigned char carry = 0; + ::bit::transform(begin(), end(), other.begin(), result.begin(), + [&carry](const word_type& a, const word_type& b) -> word_type { + word_type result; + carry = ::bit::sub_borrow(carry, a, b, &result); + return result; + }); + return result; + } + + constexpr bit_integer& operator-=(const bit_integer& other) { + unsigned char carry = 0; + ::bit::transform(begin(), end(), other.begin(), begin(), + [&carry](const word_type& a, const word_type& b) -> word_type { + word_type result; + carry = ::bit::sub_borrow(carry, a, b, &result); + return result; + }); + return *this; + } + + constexpr bit_integer operator*(const bit_integer& other) const { return {}; } + constexpr bit_integer& operator*=(const bit_integer& other) { return *this; } + constexpr bit_integer operator/(const bit_integer& other) const { return {}; } + constexpr bit_integer& operator/=(const bit_integer& other) { return *this; } + constexpr bit_integer operator%(const bit_integer& other) const { return {}; } + constexpr bit_integer& operator%=(const bit_integer& other) { return *this; } + + constexpr bool operator>(const bit_integer& other) const { return false; } + constexpr bool operator>=(const bit_integer& other) const { return false; } + constexpr bool operator<(const bit_integer& other) const { return false; } + constexpr bool operator<=(const bit_integer& other) const { return false; } + + constexpr bit_integer operator>>(const size_type shift) const { return {}; } + constexpr bit_integer& operator>>=(const size_type shift) { return *this; } + constexpr bit_integer operator<<(const size_type shift) const { return {}; } + constexpr bit_integer& operator<<=(const size_type shift) { return *this; } +}; + +} // namespace bit + +#endif // _BIT_INTEGER_HPP_INCLUDED diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d08332da..ef9c7c2c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -32,6 +32,7 @@ target_sources(bitlib-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/test-equal.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/test-fill.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/test-find.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/test-integer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/test-literal.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/test-move.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/test-reverse.cpp diff --git a/test/src/test-integer.cpp b/test/src/test-integer.cpp new file mode 100644 index 00000000..2bdbdf1d --- /dev/null +++ b/test/src/test-integer.cpp @@ -0,0 +1,28 @@ +#include +#include +#include + +#include "bitlib/bit-containers/bit_array.hpp" +#include "bitlib/bit-containers/bit_array_dynamic_extent.hpp" +#include "bitlib/bit-containers/bit_integer.hpp" +#include "fixtures.hpp" + +// Third-party libraries +#include "gtest/gtest.h" + +TEST(Integer, Constructors) { + bit::bit_integer<13, false, uint8_t> bitint; + using bitarray_t = typename bit::bit_integer<13, false, uint8_t>::base_class; + EXPECT_EQ(static_cast(bitint).size(), 13); + EXPECT_EQ(bit::bitsof(bitint), 13); +} + +TEST(Integer, Increment) { + auto bitliteral = 13'5894_b; + bit::bit_integer<13, false, uint8_t> bitint(bitliteral); + EXPECT_EQ(bitint, 13'5894_b); + EXPECT_EQ(++bitint, 13'5895_b); + EXPECT_EQ(bitint++, 13'5895_b); + EXPECT_EQ(bitint++, 13'5896_b); + EXPECT_EQ(bitint, 13'5897_b); +}