#pragma once #include "bit.h" #include "register.h" namespace dark { using dark::concepts::bit_match; using dark::concepts::bit_type; using dark::concepts::int_type; template constexpr auto cast(const _Tp &value) { return static_cast(value); } template consteval auto get_common_length() -> std::size_t { static_assert(bit_match<_Tp, _Up>); if constexpr (bit_type<_Tp>) { return _Tp::_Bit_Len; } else { static_assert(bit_type<_Up>, "Invalid common length"); return _Up::_Bit_Len; } } template requires bit_match<_Tp, _Up> constexpr auto operator+(const _Tp &lhs, const _Up &rhs) { constexpr auto _Len = get_common_length<_Tp, _Up>(); return Bit<_Len>(cast(lhs) + cast(rhs)); } template requires bit_match<_Tp, _Up> constexpr auto operator-(const _Tp &lhs, const _Up &rhs) { constexpr auto _Len = get_common_length<_Tp, _Up>(); return Bit<_Len>(cast(lhs) - cast(rhs)); } template requires bit_match<_Tp, _Up> constexpr auto operator*(const _Tp &lhs, const _Up &rhs) { constexpr auto _Len = get_common_length<_Tp, _Up>(); return Bit<_Len>(cast(lhs) * cast(rhs)); } template requires bit_match<_Tp, _Up> constexpr auto operator/(const _Tp &lhs, const _Up &rhs) { constexpr auto _Len = get_common_length<_Tp, _Up>(); return Bit<_Len>(cast(lhs) / cast(rhs)); } template requires bit_match<_Tp, _Up> constexpr auto operator&(const _Tp &lhs, const _Up &rhs) { constexpr auto _Len = get_common_length<_Tp, _Up>(); return Bit<_Len>(cast(lhs) & cast(rhs)); } template requires bit_match<_Tp, _Up> constexpr auto operator|(const _Tp &lhs, const _Up &rhs) { constexpr auto _Len = get_common_length<_Tp, _Up>(); return Bit<_Len>(cast(lhs) | cast(rhs)); } template requires bit_match<_Tp, _Up> constexpr auto operator^(const _Tp &lhs, const _Up &rhs) { constexpr auto _Len = get_common_length<_Tp, _Up>(); return Bit<_Len>(cast(lhs) ^ cast(rhs)); } template concept int_or_bit = int_type<_Tp> || bit_type>; template constexpr auto operator<<(const _Tp &lhs, const _Up &rhs) { return Bit<_Tp::_Bit_Len>(cast(lhs) << (cast(rhs) & (kMaxLength - 1))); } template constexpr auto operator>>(const _Tp &lhs, const _Up &rhs) { return Bit<_Tp::_Bit_Len>(cast(lhs) >> (cast(rhs) & (kMaxLength - 1))); } template constexpr auto operator~(const _Tp &value) { return Bit<_Tp::_Bit_Len>(~cast(value)); } template constexpr auto operator!(const _Tp &value) { return ~value; } template constexpr auto operator+(const _Tp &value) { return Bit<_Tp::_Bit_Len>(+cast(value)); } template constexpr auto operator-(const _Tp &value) { return Bit<_Tp::_Bit_Len>(-cast(value)); } template constexpr bool operator==(const _Tp &lhs, const _Up &rhs) { return cast(lhs) == cast(rhs); } template inline constexpr bool is_reg_ref_v = false; template inline constexpr bool is_reg_ref_v &> = true; template constexpr auto operator <=> (const _Tp &lhs, const _Up &rhs) { return cast(lhs) <=> cast(rhs); } } // namespace dark