14 #ifndef OR_TOOLS_UTIL_SATURATED_ARITHMETIC_H_
15 #define OR_TOOLS_UTIL_SATURATED_ARITHMETIC_H_
20 #include "absl/base/casts.h"
81 static_assert(
static_cast<uint64_t
>(-1LL) == ~0ULL,
82 "The target architecture does not use two's complement.");
83 return absl::bit_cast<int64_t>(
static_cast<uint64_t
>(x) +
84 static_cast<uint64_t
>(y));
88 static_assert(
static_cast<uint64_t
>(-1LL) == ~0ULL,
89 "The target architecture does not use two's complement.");
90 return absl::bit_cast<int64_t>(
static_cast<uint64_t
>(x) -
91 static_cast<uint64_t
>(y));
102 return ((x ^ sum) & (y ^ sum)) < 0;
130 template <
typename IntegerType>
132 const int64_t x =
a.value();
133 const int64_t y =
b->value();
150 #if defined(__GNUC__) && !defined(__clang_) && defined(__x86_64__)
151 inline int64_t CapAddAsm(int64_t x, int64_t y) {
156 "\t" "addq %[y],%[result]"
157 "\n\t" "cmovoq %[cap],%[result]"
158 : [result]
"=r"(result)
159 :
"[result]" (result), [y]
"r"(y), [cap]
"r"(cap)
165 inline int64_t CapSubAsm(int64_t x, int64_t y) {
170 "\t" "subq %[y],%[result]"
171 "\n\t" "cmovoq %[cap],%[result]"
172 : [result]
"=r"(result)
173 :
"[result]" (result), [y]
"r"(y), [cap]
"r"(cap)
181 inline int64_t CapProdAsm(int64_t x, int64_t y) {
192 "\n\t" "imulq %[y],%[result]"
193 "\n\t" "cmovcq %[cap],%[result]"
194 : [result]
"=r"(result)
195 :
"[result]" (result), [y]
"r"(y), [cap]
"r"(cap)
205 #if defined(__clang__)
206 inline int64_t CapAddBuiltIn(int64_t x, int64_t y) {
209 const bool overflowed = __builtin_add_overflow(x, y, &result);
210 return overflowed ? cap : result;
213 inline int64_t CapSubBuiltIn(int64_t x, int64_t y) {
216 const bool overflowed = __builtin_sub_overflow(x, y, &result);
217 return overflowed ? cap : result;
221 inline int64_t CapProdBuiltIn(int64_t x, int64_t y) {
224 const bool overflowed = __builtin_mul_overflow(x, y, &result);
225 return overflowed ? cap : result;
241 namespace cap_prod_util {
245 return n < 0 ? ~static_cast<uint64_t>(n) + 1 :
static_cast<uint64_t
>(n);
263 const int kMaxBitIndexInInt64 = 63;
264 if (msb_sum <= kMaxBitIndexInInt64 - 2)
return x * y;
267 if (
a == 0 ||
b == 0)
return 0;
269 if (msb_sum >= kMaxBitIndexInInt64)
return cap;
273 const uint64_t u_prod =
a *
b;
279 if (u_prod >=
static_cast<uint64_t
>(cap))
return cap;
280 const int64_t abs_result = absl::bit_cast<int64_t>(u_prod);
281 return cap < 0 ? -abs_result : abs_result;
284 inline int64_t
CapAdd(int64_t x, int64_t y) {
285 #if defined(__GNUC__) && !defined(__clang__) && defined(__x86_64__)
286 return CapAddAsm(x, y);
287 #elif defined(__clang__)
288 return CapAddBuiltIn(x, y);
296 inline int64_t
CapSub(int64_t x, int64_t y) {
297 #if defined(__GNUC__) && !defined(__clang__) && defined(__x86_64__)
298 return CapSubAsm(x, y);
299 #elif defined(__clang__)
300 return CapSubBuiltIn(x, y);
306 inline int64_t
CapProd(int64_t x, int64_t y) {
307 #if defined(__GNUC__) && defined(__x86_64__)
312 return CapProdAsm(x, y);
313 #elif defined(__clang__)
314 return CapProdBuiltIn(x, y);
static const int64_t kint64max
static const int64_t kint64min
uint64_t uint_abs(int64_t n)
Collection of objects used to extend the Constraint Solver library.
int64_t SubOverflows(int64_t x, int64_t y)
bool AtMinOrMaxInt64(int64_t x)
bool AddHadOverflow(int64_t x, int64_t y, int64_t sum)
int64_t CapAdd(int64_t x, int64_t y)
void CapAddTo(int64_t x, int64_t *y)
int64_t CapWithSignOf(int64_t x)
int64_t TwosComplementAddition(int64_t x, int64_t y)
int64_t CapSub(int64_t x, int64_t y)
int64_t CapAddGeneric(int64_t x, int64_t y)
bool AddOverflows(int64_t x, int64_t y)
int64_t CapProd(int64_t x, int64_t y)
bool SubHadOverflow(int64_t x, int64_t y, int64_t diff)
int64_t TwosComplementSubtraction(int64_t x, int64_t y)
int64_t CapAbs(int64_t v)
int64_t CapProdGeneric(int64_t x, int64_t y)
bool SafeAddInto(IntegerType a, IntegerType *b)
int64_t CapSubGeneric(int64_t x, int64_t y)
int64_t CapOpp(int64_t v)
int MostSignificantBitPosition64(uint64_t n)