// // SizedCounter.hpp // Clock Signal // // Created by Thomas Harte on 22/09/2025. // Copyright © 2025 Thomas Harte. All rights reserved. // #pragma once #include "Sizes.hpp" #include namespace Numeric { /*! Provides a counter that is strictly limited to the requested of bits but attempts otherwise to act like a standard C++ numeric type. */ template struct SizedInt { using IntT = MinIntForValue<1 << bits>::type; inline static constexpr IntT Mask = (1 << bits) - 1; template constexpr SizedInt(const ConstructionT start_value) noexcept : value_(IntT(start_value & Mask)) {} SizedInt() = default; template IntT get() const { return value_ >> begin; } SizedInt operator +(const SizedInt offset) const { return SizedInt(value_ + offset.value_); } SizedInt operator -(const SizedInt offset) const { return SizedInt(value_ - offset.value_); } SizedInt operator &(const SizedInt offset) const { return SizedInt(value_ & offset.value_); } SizedInt operator |(const SizedInt offset) const { return SizedInt(value_ | offset.value_); } SizedInt operator ^(const SizedInt offset) const { return SizedInt(value_ ^ offset.value_); } SizedInt operator >>(const int shift) const { return SizedInt(value_ >> shift); } SizedInt operator <<(const int shift) const { return SizedInt(value_ << shift); } SizedInt &operator &=(const SizedInt offset) { value_ &= offset.value_; return *this; } SizedInt &operator |=(const SizedInt offset) { value_ |= offset.value_; return *this; } SizedInt &operator ^=(const SizedInt offset) { value_ ^= offset.value_; return *this; } SizedInt &operator <<=(const int shift) { value_ = (value_ << shift) & Mask; return *this; } SizedInt &operator >>=(const int shift) { value_ >>= shift; return *this; } SizedInt &operator ++(int) { ++(*this); return *this; } SizedInt &operator ++() { value_ = (value_ + 1) & Mask; return *this; } SizedInt &operator +=(const IntT rhs) { value_ = (value_ + rhs) & Mask; return *this; } bool operator!() const { return !value_; } auto operator <=>(const SizedInt &) const = default; /// Replaces the bits in the range [begin, end) with those in the low-order bits of @c vlaue. template void load(const MinIntForValue<1 << (end - begin)>::type value) { const auto mask = (1 << end) - (1 << begin); value_ &= ~mask; value_ |= IntT((value << begin) & mask); } template void load(const IntT value) { load(value); } template requires (index < bits) bool bit() const { return value_ & (1 << index); } private: IntT value_{}; }; }