8#include "architecture.hpp"
15#if TT_PROCESSOR == TT_CPU_X64
19#if TT_OPERATING_SYSTEM == TT_OS_WINDOWS
21#pragma intrinsic(_mul128)
26template<
typename T,
typename U>
27inline bool convert_overflow(T x, U *r)
29 static_assert(std::is_integral_v<U>,
"convert_overflow() requires integral return type.");
30 static_assert(std::is_integral_v<T> || std::is_floating_point_v<T>,
"convert_overflow() requires float or integral argument type.");
32 if constexpr (std::is_integral_v<T>) {
34 *r =
static_cast<U
>(x);
43inline bool add_overflow(T lhs, T rhs, T *r)
45 static_assert(std::is_integral_v<T>,
"add_overflow() requires integral arguments.");
47 if constexpr (compiler::current == compiler::gcc || compiler::current == compiler::clang) {
49 return __builtin_add_overflow(lhs, rhs, r);
51 }
else if constexpr (std::is_unsigned_v<T>) {
58 ttlet lhs_ =
static_cast<std::make_unsigned_t<T>
>(lhs);
59 ttlet rhs_ =
static_cast<std::make_unsigned_t<T>
>(rhs);
60 ttlet r_ = lhs_ + rhs_;
61 *r =
static_cast<T
>(r_);
62 return ((lhs ^ *r) & (rhs ^ *r)) < 0;
67inline bool sub_overflow(T lhs, T rhs, T *r)
69 static_assert(std::is_integral_v<T>,
"sub_overflow() requires integral arguments.");
71 if constexpr (compiler::current == compiler::gcc || compiler::current == compiler::clang) {
73 return __builtin_sub_overflow(lhs, rhs, r);
75 }
else if constexpr (std::is_unsigned_v<T>) {
82 ttlet lhs_ =
static_cast<std::make_unsigned_t<T>
>(lhs);
83 ttlet rhs_ =
static_cast<std::make_unsigned_t<T>
>(rhs);
84 ttlet r_ = lhs_ - rhs_;
85 *r =
static_cast<T
>(r_);
86 return ((lhs ^ rhs) & (~rhs ^ *r)) < 0;
94inline bool mul_overflow(T lhs, T rhs, T *r)
96 static_assert(std::is_integral_v<T>,
"mul_overflow() requires integral arguments.");
98 if constexpr (compiler::current == compiler::gcc || compiler::current == compiler::clang) {
99 return __builtin_mul_overflow(lhs, rhs, r);
101 }
else if constexpr (std::is_signed_v<T> && compiler::current == compiler::msvc &&
sizeof(T) ==
sizeof(
long long)) {
104 *r = _mul128(lhs, rhs, &hi);
107 return (hi ^ (*r >> 63)) != 0;
109 }
else if constexpr (
110 std::is_unsigned_v<T> && compiler::current == compiler::msvc &&
sizeof(T) ==
sizeof(
unsigned long long)) {
111 unsigned long long hi = 0;
112 *r = _umul128(lhs, rhs, &hi);
115 }
else if constexpr (
sizeof(T) <= (
sizeof(make_intmax_t<T>)/2)) {
117 ttlet lhs_ =
static_cast<make_intmax_t<T>
>(lhs);
118 ttlet rhs_ =
static_cast<make_intmax_t<T>
>(rhs);
119 ttlet r_ = lhs_ * rhs_;
120 *r =
static_cast<T
>(r_);
124 tt_not_implemented();