14#ifndef OR_TOOLS_UTIL_SATURATED_ARITHMETIC_H_
15#define OR_TOOLS_UTIL_SATURATED_ARITHMETIC_H_
21#include "absl/base/casts.h"
22#include "absl/log/check.h"
54 return x == std::numeric_limits<int64_t>::min() ||
55 x == std::numeric_limits<int64_t>::max();
62 return v ==
kint64min ? std::numeric_limits<int64_t>::max()
83 static_assert(
static_cast<uint64_t
>(-1LL) == ~0ULL,
84 "The target architecture does not use two's complement.");
85 return absl::bit_cast<int64_t>(
static_cast<uint64_t
>(
x) +
86 static_cast<uint64_t
>(
y));
90 static_assert(
static_cast<uint64_t
>(-1LL) == ~0ULL,
91 "The target architecture does not use two's complement.");
92 return absl::bit_cast<int64_t>(
static_cast<uint64_t
>(
x) -
93 static_cast<uint64_t
>(
y));
104 return ((
x ^ sum) & (
y ^ sum)) < 0;
132template <
typename IntegerType>
134 const int64_t
x =
a.value();
135 const int64_t
y =
b->value();
152#if defined(__GNUC__) && !defined(__clang_) && defined(__x86_64__)
153inline int64_t CapAddAsm(int64_t
x, int64_t
y) {
158 "\t" "addq %[y],%[result]"
159 "\n\t" "cmovoq %[cap],%[result]"
160 : [result]
"=r"(result)
161 :
"[result]" (result), [
y]
"r"(
y), [cap]
"r"(cap)
167inline int64_t CapSubAsm(int64_t
x, int64_t
y) {
172 "\t" "subq %[y],%[result]"
173 "\n\t" "cmovoq %[cap],%[result]"
174 : [result]
"=r"(result)
175 :
"[result]" (result), [
y]
"r"(
y), [cap]
"r"(cap)
183inline int64_t CapProdAsm(int64_t
x, int64_t
y) {
194 "\n\t" "imulq %[y],%[result]"
195 "\n\t" "cmovcq %[cap],%[result]"
196 : [result]
"=r"(result)
197 :
"[result]" (result), [
y]
"r"(
y), [cap]
"r"(cap)
207#if defined(__clang__)
208inline int64_t CapAddBuiltIn(int64_t
x, int64_t
y) {
211 const bool overflowed = __builtin_add_overflow(
x,
y, &result);
212 return overflowed ? cap : result;
215inline int64_t CapSubBuiltIn(int64_t
x, int64_t
y) {
218 const bool overflowed = __builtin_sub_overflow(
x,
y, &result);
219 return overflowed ? cap : result;
223inline int64_t CapProdBuiltIn(int64_t
x, int64_t
y) {
226 const bool overflowed = __builtin_mul_overflow(
x,
y, &result);
227 return overflowed ? cap : result;
243namespace cap_prod_util {
247 return n < 0 ? ~static_cast<uint64_t>(n) + 1 :
static_cast<uint64_t
>(n);
265 const int kMaxBitIndexInInt64 = 63;
266 if (msb_sum <= kMaxBitIndexInInt64 - 2)
return x *
y;
269 if (
a == 0 ||
b == 0)
return 0;
271 if (msb_sum >= kMaxBitIndexInInt64)
return cap;
275 const uint64_t u_prod =
a *
b;
281 if (u_prod >=
static_cast<uint64_t
>(cap))
return cap;
282 const int64_t abs_result = absl::bit_cast<int64_t>(u_prod);
283 return cap < 0 ? -abs_result : abs_result;
293#if defined(__GNUC__) && !defined(__clang__) && defined(__x86_64__)
294 return CapAddAsm(
x,
y);
295#elif defined(__clang__)
296 return CapAddBuiltIn(
x,
y);
305#if defined(__GNUC__) && !defined(__clang__) && defined(__x86_64__)
306 return CapSubAsm(
x,
y);
307#elif defined(__clang__)
308 return CapSubBuiltIn(
x,
y);
315#if defined(__GNUC__) && defined(__x86_64__)
320 return CapProdAsm(
x,
y);
321#elif defined(__clang__)
322 return CapProdBuiltIn(
x,
y);
330 static_assert(std::is_floating_point_v<T> || std::is_integral_v<T>);
331 if constexpr (std::is_integral_v<T>) {
332 if constexpr (std::is_same_v<T, int64_t>) {
336 std::is_same_v<T, int32_t>,
337 "CapOrFloatAdd() on integers only works for int and int64_t");
338 const int64_t sum = int64_t{
x} +
y;
uint64_t uint_abs(int64_t n)
In SWIG mode, we don't want anything besides these top-level includes.
int64_t SubOverflows(int64_t x, int64_t y)
bool AtMinOrMaxInt64(int64_t x)
Checks if x is equal to the min or the max value of an int64_t.
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)
Returns kint64max if x >= 0 and kint64min if x < 0.
int64_t TwosComplementAddition(int64_t x, int64_t y)
-------— Overflow utility functions -------—
int64_t CapSub(int64_t x, int64_t y)
int64_t CapAddGeneric(int64_t x, int64_t y)
T CapOrFloatAdd(T x, 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)
Note(user): -kint64min != kint64max, but kint64max == ~kint64min.
int MostSignificantBitPosition64(uint64_t n)
static const int32_t kint32min
static const int64_t kint64max
static const int32_t kint32max
static const int64_t kint64min