tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
add_sat.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2// SPDX-FileCopyrightText: Copyright (C) 2024 Tobias Hienzsch
3
4#ifndef TETL_NUMERIC_ADD_SAT_HPP
5#define TETL_NUMERIC_ADD_SAT_HPP
6
7#include <etl/_algorithm/clamp.hpp>
8#include <etl/_concepts/builtin_integer.hpp>
9#include <etl/_concepts/same_as.hpp>
10#include <etl/_cstdint/int_t.hpp>
11#include <etl/_cstdint/uint_t.hpp>
12#include <etl/_limits/numeric_limits.hpp>
13#include <etl/_type_traits/always_false.hpp>
14#include <etl/_type_traits/is_signed.hpp>
15#include <etl/_type_traits/is_unsigned.hpp>
16
17namespace etl {
18
19namespace detail {
20
21template <etl::builtin_integer Int>
22[[nodiscard]] constexpr auto add_sat_fallback(Int x, Int y) noexcept -> Int
23{
24 constexpr auto min = etl::numeric_limits<Int>::min();
25 constexpr auto max = etl::numeric_limits<Int>::max();
26
27 if constexpr (sizeof(Int) < sizeof(int) and etl::same_as<decltype(x + y), int>) {
28 return Int(etl::clamp(x + y, int(min), int(max)));
29 } else if constexpr (sizeof(Int) < sizeof(unsigned) and etl::same_as<decltype(x + y), unsigned>) {
30 return Int(etl::clamp(x + y, unsigned(min), unsigned(max)));
31 } else if constexpr (sizeof(Int) == 2 and is_signed_v<Int>) {
32 return Int(etl::clamp(etl::int32_t(x) + etl::int32_t(y), etl::int32_t(min), etl::int32_t(max)));
33 } else if constexpr (sizeof(Int) == 2 and is_unsigned_v<Int>) {
34 return Int(etl::clamp(etl::uint32_t(x) + etl::uint32_t(y), etl::uint32_t(min), etl::uint32_t(max)));
35 } else if constexpr (sizeof(Int) == 4 and is_signed_v<Int>) {
36 return Int(etl::clamp(etl::int64_t(x) + etl::int64_t(y), etl::int64_t(min), etl::int64_t(max)));
37 } else if constexpr (sizeof(Int) == 4 and is_unsigned_v<Int>) {
38 return Int(etl::clamp(etl::uint64_t(x) + etl::uint64_t(y), etl::uint64_t(min), etl::uint64_t(max)));
39 } else {
40 if (x >= 0) {
41 if (max - x < y) {
42 return max;
43 }
44 } else {
45 if (y < min - x) {
46 return min;
47 }
48 }
49 return x + y;
50 }
51}
52
53} // namespace detail
54
55/// \ingroup numeric
56template <etl::builtin_integer Int>
57[[nodiscard]] constexpr auto add_sat(Int x, Int y) noexcept -> Int
58{
59#if defined(__GNUC__) or defined(__clang__)
60 constexpr auto min = etl::numeric_limits<Int>::min();
61 constexpr auto max = etl::numeric_limits<Int>::max();
62
63 if (Int sum{0}; not __builtin_add_overflow(x, y, &sum)) {
64 return sum;
65 }
66 if constexpr (is_unsigned_v<Int>) {
67 return max;
68 } else {
69 if (x > Int(0)) {
70 return max;
71 }
72 return min;
73 }
74#else
75 return etl::detail::add_sat_fallback(x, y);
76#endif
77}
78
79} // namespace etl
80
81#endif // TETL_NUMERIC_ADD_SAT_HPP
constexpr auto clamp(Type const &v, Type const &lo, Type const &hi) noexcept -> Type const &
If v compares less than lo, returns lo; otherwise if hi compares less than v, returns hi; otherwise r...
Definition clamp.hpp:24
constexpr auto add_sat(Int x, Int y) noexcept -> Int
Definition add_sat.hpp:57
Definition adjacent_find.hpp:9
Definition numeric_limits.hpp:18