7#include "utility/module.hpp"
12#if HI_PROCESSOR == HI_CPU_X64
16#if HI_OPERATING_SYSTEM == HI_OS_WINDOWS
18#pragma intrinsic(_mul128)
21namespace hi::inline
v1 {
23template<
typename T,
typename U>
24inline bool convert_overflow(T x, U *r)
26 static_assert(std::is_integral_v<U>,
"convert_overflow() requires integral return type.");
28 std::is_integral_v<T> || std::is_floating_point_v<T>,
"convert_overflow() requires float or integral argument type.");
30 if constexpr (std::is_integral_v<T>) {
32 *r =
static_cast<U
>(x);
41inline bool add_overflow(T lhs, T rhs, T *r)
43 static_assert(std::is_integral_v<T>,
"add_overflow() requires integral arguments.");
45 if constexpr (compiler::current == compiler::gcc || compiler::current == compiler::clang) {
47 return __builtin_add_overflow(lhs, rhs, r);
49 }
else if constexpr (std::is_unsigned_v<T>) {
56 hilet lhs_ =
static_cast<std::make_unsigned_t<T>
>(lhs);
57 hilet rhs_ =
static_cast<std::make_unsigned_t<T>
>(rhs);
58 hilet r_ = lhs_ + rhs_;
59 *r =
static_cast<T
>(r_);
60 return ((lhs ^ *r) & (rhs ^ *r)) < 0;
65inline bool sub_overflow(T lhs, T rhs, T *r)
67 static_assert(std::is_integral_v<T>,
"sub_overflow() requires integral arguments.");
69 if constexpr (compiler::current == compiler::gcc || compiler::current == compiler::clang) {
71 return __builtin_sub_overflow(lhs, rhs, r);
73 }
else if constexpr (std::is_unsigned_v<T>) {
80 hilet lhs_ =
static_cast<std::make_unsigned_t<T>
>(lhs);
81 hilet rhs_ =
static_cast<std::make_unsigned_t<T>
>(rhs);
82 hilet r_ = lhs_ - rhs_;
83 *r =
static_cast<T
>(r_);
84 return ((lhs ^ rhs) & (~rhs ^ *r)) < 0;
94 static_assert(std::is_integral_v<T>,
"mul_overflow() requires integral arguments.");
96 if constexpr (compiler::current == compiler::gcc || compiler::current == compiler::clang) {
97 return __builtin_mul_overflow(lhs, rhs, r);
99 }
else if constexpr (std::is_signed_v<T> && compiler::current == compiler::msvc &&
sizeof(T) ==
sizeof(
long long)) {
102 *r = _mul128(lhs, rhs, &
hi);
105 return (
hi ^ (*r >> 63)) != 0;
107 }
else if constexpr (
108 std::is_unsigned_v<T> && compiler::current == compiler::msvc &&
sizeof(T) ==
sizeof(
unsigned long long)) {
109 unsigned long long hi = 0;
110 *r = _umul128(lhs, rhs, &
hi);
113 }
else if constexpr (
sizeof(T) <= (
sizeof(make_intmax_t<T>) / 2)) {
115 hilet lhs_ =
static_cast<make_intmax_t<T>
>(lhs);
116 hilet rhs_ =
static_cast<make_intmax_t<T>
>(rhs);
117 hilet r_ = lhs_ * rhs_;
118 *r =
static_cast<T
>(r_);
#define hi_not_implemented(...)
This part of the code has not been implemented yet.
Definition assert.hpp:335
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
bool mul_overflow(T lhs, T rhs, T *r) noexcept
Multiply with overflow detection.
Definition int_overflow.hpp:92
geometry/margins.hpp
Definition cache.hpp:11