Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
saturating_arithmetic.h
1// Copyright 2025 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#if __has_include(<version>)
17#include <version>
18#endif // __has_include(<version>)
19
20#ifdef __cpp_lib_saturation_arithmetic
21
22#include <numeric>
23
24namespace pw {
25
26using std::add_sat;
27using std::mul_sat;
28
29} // namespace pw
30
31#else
32
33#include <limits>
34#include <type_traits>
35
36#include "pw_preprocessor/compiler.h"
37
38// Polyfills of C++26's saturating arithmetic operations in <numeric>.
39
40namespace pw {
41
48template <typename T>
49constexpr T add_sat(T lhs, T rhs) noexcept {
50 static_assert(std::is_integral_v<T>);
51 if (T sum = 0; !PW_ADD_OVERFLOW(lhs, rhs, &sum)) {
52 return sum;
53 }
54 if constexpr (std::is_unsigned_v<T>) {
55 return std::numeric_limits<T>::max();
56 } else { // since it overflowed, the operands had the same sign
57 if (lhs < 0) {
58 return std::numeric_limits<T>::min();
59 }
60 return std::numeric_limits<T>::max();
61 }
62}
63
70template <typename T>
71constexpr T mul_sat(T lhs, T rhs) noexcept {
72 static_assert(std::is_integral_v<T>);
73 if (T product = 0; !PW_MUL_OVERFLOW(lhs, rhs, &product)) {
74 return product;
75 }
76 if constexpr (std::is_unsigned_v<T>) {
77 return std::numeric_limits<T>::max();
78 } else { // determine sign of result by comparing signs of the factors
79 if ((lhs < 0) == (rhs < 0)) {
80 return std::numeric_limits<T>::max();
81 }
82 return std::numeric_limits<T>::min();
83 }
84}
85
86} // namespace pw
87
88#endif // __cpp_lib_saturation_arithmetic
#define PW_ADD_OVERFLOW(a, b, out)
Definition: compiler.h:282
#define PW_MUL_OVERFLOW(a, b, out)
Definition: compiler.h:304
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
constexpr T mul_sat(T lhs, T rhs) noexcept
Definition: saturating_arithmetic.h:71
constexpr T add_sat(T lhs, T rhs) noexcept
Definition: saturating_arithmetic.h:49