Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions include/bitlib/bit-containers/bit_integer.hpp
Original file line number Diff line number Diff line change
@@ -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 <algorithm>
#include <bit>
#include <cmath>
#include <cstring> // memcpy
#include <span>
#include <string>
#include <type_traits>
#include <vector>

// 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 <size_t N = std::dynamic_extent, bool issigned = true, typename W = uint8_t>
class bit_integer : public bit_array<bit_value, N, std::align_val_t(alignof(W)), W> {
public:
using base_class = bit_array<bit_value, N, std::align_val_t(alignof(W)), W>;

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_value, N, std::align_val_t(alignof(W)), W>::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<base_class>(*this) == other;
}

constexpr bool operator==(const bit_sized_range auto& other) const {
return static_cast<base_class>(*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<word_type>(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<word_type>(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;

Check warning on line 112 in include/bitlib/bit-containers/bit_integer.hpp

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, linux, gcc, gcc, g++, libstdcxx, warnings, bitlib-tests, Debug)

declaration of ‘result’ shadows a previous local [-Wshadow]
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;

Check warning on line 136 in include/bitlib/bit-containers/bit_integer.hpp

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, linux, gcc, gcc, g++, libstdcxx, warnings, bitlib-tests, Debug)

declaration of ‘result’ shadows a previous local [-Wshadow]
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
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 28 additions & 0 deletions test/src/test-integer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <stdexcept>
#include <string_view>
#include <utility>

#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<bitarray_t>(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);
}
Loading