diff --git a/src/core/math_func.hpp b/src/core/math_func.hpp index d473281176..5ddaf6b852 100644 --- a/src/core/math_func.hpp +++ b/src/core/math_func.hpp @@ -414,6 +414,26 @@ constexpr uint64_t PowerOfTen(int power) return result; } +/** + * Unsigned saturating add. + */ +template, int> = 0> +constexpr inline T SaturatingAdd(T a, T b) +{ +#ifdef WITH_OVERFLOW_BUILTINS + T c; + if (unlikely(__builtin_add_overflow(a, b, &c))) { + return std::numeric_limits::max(); + } + return c; +#else + T c = a + b; + if (c < a) return std::numeric_limits::max(); + return c; +#endif +} + + uint32_t IntSqrt(uint32_t num); uint32_t IntSqrt64(uint64_t num); uint32_t IntCbrt(uint64_t num); diff --git a/src/tests/math_func.cpp b/src/tests/math_func.cpp index 1f53d005b7..88af10eb4c 100644 --- a/src/tests/math_func.cpp +++ b/src/tests/math_func.cpp @@ -95,3 +95,13 @@ TEST_CASE("SoftClamp") CHECK(1250 * million == SoftClamp(0, 1500 * million, 1000 * million)); CHECK(0 == SoftClamp(0, 1500 * million, -1500 * million)); } + +TEST_CASE("SaturatingAdd") +{ + CHECK(SaturatingAdd(2, 3) == 5); + CHECK(SaturatingAdd(200, 200) == 255); + CHECK(SaturatingAdd(255, 255) == 255); + CHECK(SaturatingAdd(1, 255) == 255); + CHECK(SaturatingAdd(255, 1) == 255); + CHECK(SaturatingAdd(0, 254) == 254); +}