16#if TT_COMPILER == TT_CC_MSVC
19#if TT_PROCESSOR == TT_CPU_X64
31template<
typename T>
requires (std::unsigned_integral<T>)
32constexpr std::pair<T, T> shift_left_carry(T lhs,
unsigned int rhs, T carry = 0)
noexcept
34 constexpr unsigned int nr_bits =
sizeof(T) * 8;
35 unsigned int reverse_count = nr_bits - rhs;
49template<
typename T>
requires (std::unsigned_integral<T>)
50constexpr std::pair<T, T> shift_right_carry(T lhs,
unsigned int rhs, T carry = 0)
noexcept
52 constexpr unsigned int nr_bits =
sizeof(T) * 8;
53 unsigned int reverse_count = nr_bits - rhs;
66template<
typename T>
requires (std::unsigned_integral<T>)
69 if constexpr (
sizeof(T) == 1) {
70 uint16_t r =
static_cast<uint16_t
>(a) +
static_cast<uint16_t
>(b) + carry;
71 return {
static_cast<uint8_t
>(r),
static_cast<uint8_t
>(r >> 8) };
73 }
else if constexpr (
sizeof(T) == 2) {
74 uint32_t r =
static_cast<uint32_t
>(a) +
static_cast<uint32_t
>(b) + carry;
75 return {
static_cast<uint16_t
>(r),
static_cast<uint16_t
>(r >> 16) };
77 }
else if constexpr (
sizeof(T) == 4) {
78 uint64_t r =
static_cast<uint64_t
>(a) +
static_cast<uint64_t
>(b) + carry;
79 return {
static_cast<uint32_t
>(r),
static_cast<uint32_t
>(r >> 32) };
81 }
else if constexpr (
sizeof(T) == 8) {
82#if TT_COMPILER == TT_CC_CLANG || TT_COMPILER == TT_CC_GCC
83 auto r =
static_cast<__uint128_t
>(a) +
static_cast<__uint128_t
>(b) + carry;
84 return {
static_cast<uint64_t
>(r),
static_cast<uint64_t
>(r >> 64) };
87 uint64_t c = (r1 < a) ? 1 : 0;
88 uint64_t r2 = r1 + carry;
89 c += (r2 < r1) ? 1 : 0;
95template<
typename T>
requires (std::unsigned_integral<T>)
98 if constexpr (
sizeof(T) == 1) {
99 uint16_t r =
static_cast<uint16_t
>(a) *
static_cast<uint16_t
>(b);
100 return {
static_cast<uint8_t
>(r),
static_cast<uint8_t
>(r >> 8) };
102 }
else if constexpr (
sizeof(T) == 2) {
103 uint32_t r =
static_cast<uint32_t
>(a) *
static_cast<uint32_t
>(b);
104 return {
static_cast<uint16_t
>(r),
static_cast<uint16_t
>(r >> 16) };
106 }
else if constexpr (
sizeof(T) == 4) {
107 uint64_t r =
static_cast<uint64_t
>(a) *
static_cast<uint64_t
>(b);
108 return {
static_cast<uint32_t
>(r),
static_cast<uint32_t
>(r >> 32) };
110 }
else if constexpr (
sizeof(T) == 8) {
111#if TT_COMPILER == TT_CC_MSVC
113 uint64_t lo = _umul128(a, b, &hi);
116#elif TT_COMPILER == TT_CC_CLANG || TT_COMPILER == TT_CC_GCC
117 auto r =
static_cast<__uint128_t
>(a) *
static_cast<__uint128_t
>(b);
118 return {
static_cast<uint64_t
>(r),
static_cast<uint64_t
>(r >> 64) };
120#error "Not implemented"
125template<
typename T>
requires (std::unsigned_integral<T>)
126constexpr std::pair<T, T> multiply_carry(T a, T b, T carry = 0, T accumulator = 0)
noexcept
128 if constexpr (
sizeof(T) == 1) {
129 uint16_t r =
static_cast<uint16_t
>(a) *
static_cast<uint16_t
>(b) + carry + accumulator;
130 return {
static_cast<uint8_t
>(r),
static_cast<uint8_t
>(r >> 8) };
132 }
else if constexpr (
sizeof(T) == 2) {
133 uint32_t r =
static_cast<uint32_t
>(a) *
static_cast<uint32_t
>(b) + carry + accumulator;
134 return {
static_cast<uint16_t
>(r),
static_cast<uint16_t
>(r >> 16) };
136 }
else if constexpr (
sizeof(T) == 4) {
137 uint64_t r =
static_cast<uint64_t
>(a) *
static_cast<uint64_t
>(b) + carry + accumulator;
138 return {
static_cast<uint32_t
>(r),
static_cast<uint32_t
>(r >> 32) };
140 }
else if constexpr (
sizeof(T) == 8) {
141#if TT_COMPILER == TT_CC_MSVC
143 uint64_t lo = _umul128(a, b, &hi);
145 std::tie(lo, c) = add_carry(lo, carry, uint64_t{0});
146 std::tie(hi, c) = add_carry(hi, uint64_t{0}, c);
147 std::tie(lo, c) = add_carry(lo, accumulator, uint64_t{0});
148 std::tie(hi, c) = add_carry(hi, uint64_t{0}, c);
151#elif TT_COMPILER == TT_CC_CLANG || TT_COMPILER == TT_CC_GCC
152 auto r =
static_cast<__uint128_t
>(a) *
static_cast<__uint128_t
>(b) + carry + accumulator;
153 return {
static_cast<uint64_t
>(r),
static_cast<uint64_t
>(r >> 64) };
155#error "Not implemented"