Add SafeClamp(), which accepts args of different types
Specifically, just like SafeMin() and SafeMax() it handles all
combinations of integer and all
combinations of floating-point arguments by picking a
result type that is guaranteed to be able to hold the result.
This CL also replaces a bunch of std::min + std:max call pairs with
calls to SafeClamp()---the ones that could easily be found by grep
because "min" and "max" were on the same line. :-)
BUG=webrtc:7459
Review-Url: https://codereview.webrtc.org/2808513003
Cr-Commit-Position: refs/heads/master@{#18542}
diff --git a/webrtc/base/safe_minmax.h b/webrtc/base/safe_minmax.h
index 16638ef..5d6a7d0 100644
--- a/webrtc/base/safe_minmax.h
+++ b/webrtc/base/safe_minmax.h
@@ -14,6 +14,8 @@
// rtc::SafeMin(x, y)
// rtc::SafeMax(x, y)
//
+// (These are both constexpr.)
+//
// Accept two arguments of either any two integral or any two floating-point
// types, and return the smaller and larger value, respectively, with no
// truncation or wrap-around. If only one of the input types is statically
@@ -21,14 +23,48 @@
// if either one would do, the result type is the smaller type. (One of these
// two cases always applies.)
//
-// (The case with one floating-point and one integral type is not allowed,
-// because the floating-point type will have greater range, but may not have
-// sufficient precision to represent the integer value exactly.)
+// * The case with one floating-point and one integral type is not allowed,
+// because the floating-point type will have greater range, but may not
+// have sufficient precision to represent the integer value exactly.)
+//
+// Clamp (a.k.a. constrain to a given interval)
+// ============================================
+//
+// rtc::SafeClamp(x, a, b)
+//
+// Accepts three arguments of any mix of integral types or any mix of
+// floating-point types, and returns the value in the closed interval [a, b]
+// that is closest to x (that is, if x < a it returns a; if x > b it returns b;
+// and if a <= x <= b it returns x). As for SafeMin() and SafeMax(), there is
+// no truncation or wrap-around. The result type
+//
+// 1. is statically guaranteed to be able to represent the result;
+//
+// 2. is no larger than the largest of the three argument types; and
+//
+// 3. has the same signedness as the type of the third argument, if this is
+// possible without violating the First or Second Law.
+//
+// There is always at least one type that meets criteria 1 and 2. If more than
+// one type meets these criteria equally well, the result type is one of the
+// types that is smallest. Note that unlike SafeMin() and SafeMax(),
+// SafeClamp() will sometimes pick a return type that isn't the type of any of
+// its arguments.
+//
+// * In this context, a type A is smaller than a type B if it has a smaller
+// range; that is, if A::max() - A::min() < B::max() - B::min(). For
+// example, int8_t < int16_t == uint16_t < int32_t, and all integral types
+// are smaller than all floating-point types.)
+//
+// * As for SafeMin and SafeMax, mixing integer and floating-point arguments
+// is not allowed, because floating-point types have greater range than
+// integer types, but do not have sufficient precision to represent the
+// values of most integer types exactly.
//
// Requesting a specific return type
// =================================
//
-// Both functions allow callers to explicitly specify the return type as a
+// All three functions allow callers to explicitly specify the return type as a
// template parameter, overriding the default return type. E.g.
//
// rtc::SafeMin<int>(x, y) // returns an int
@@ -187,6 +223,115 @@
return safe_cmp::Gt(a, b) ? static_cast<R2>(a) : static_cast<R2>(b);
}
+namespace safe_minmax_impl {
+
+// Given three types T, L, and H, let ::type be a suitable return value for
+// SafeClamp(T, L, H). See the docs at the top of this file for details.
+template <typename T,
+ typename L,
+ typename H,
+ bool int1 = IsIntlike<T>::value,
+ bool int2 = IsIntlike<L>::value,
+ bool int3 = IsIntlike<H>::value>
+struct ClampType {
+ static_assert(int1 == int2 && int1 == int3,
+ "You may not mix integral and floating-point arguments");
+};
+
+// Specialization for when all three types are floating-point.
+template <typename T, typename L, typename H>
+struct ClampType<T, L, H, false, false, false> {
+ using type = typename std::common_type<T, L, H>::type;
+};
+
+// Specialization for when all three types are integral.
+template <typename T, typename L, typename H>
+struct ClampType<T, L, H, true, true, true> {
+ private:
+ // Range of the return value. The return type must be able to represent this
+ // full range.
+ static constexpr auto r_min =
+ SafeMax(Limits<L>::lowest, SafeMin(Limits<H>::lowest, Limits<T>::lowest));
+ static constexpr auto r_max =
+ SafeMin(Limits<H>::max, SafeMax(Limits<L>::max, Limits<T>::max));
+
+ // Is the given type an acceptable return type? (That is, can it represent
+ // all possible return values, and is it no larger than the largest of the
+ // input types?)
+ template <typename A>
+ struct AcceptableType {
+ private:
+ static constexpr bool not_too_large = sizeof(A) <= sizeof(L) ||
+ sizeof(A) <= sizeof(H) ||
+ sizeof(A) <= sizeof(T);
+ static constexpr bool range_contained =
+ safe_cmp::Le(Limits<A>::lowest, r_min) &&
+ safe_cmp::Le(r_max, Limits<A>::max);
+
+ public:
+ static constexpr bool value = not_too_large && range_contained;
+ };
+
+ using best_signed_type = typename std::conditional<
+ AcceptableType<int8_t>::value,
+ int8_t,
+ typename std::conditional<
+ AcceptableType<int16_t>::value,
+ int16_t,
+ typename std::conditional<AcceptableType<int32_t>::value,
+ int32_t,
+ int64_t>::type>::type>::type;
+
+ using best_unsigned_type = typename std::conditional<
+ AcceptableType<uint8_t>::value,
+ uint8_t,
+ typename std::conditional<
+ AcceptableType<uint16_t>::value,
+ uint16_t,
+ typename std::conditional<AcceptableType<uint32_t>::value,
+ uint32_t,
+ uint64_t>::type>::type>::type;
+
+ public:
+ // Pick the best type, preferring the same signedness as T but falling back
+ // to the other one if necessary.
+ using type = typename std::conditional<
+ std::is_signed<T>::value,
+ typename std::conditional<AcceptableType<best_signed_type>::value,
+ best_signed_type,
+ best_unsigned_type>::type,
+ typename std::conditional<AcceptableType<best_unsigned_type>::value,
+ best_unsigned_type,
+ best_signed_type>::type>::type;
+ static_assert(AcceptableType<type>::value, "");
+};
+
+} // namespace safe_minmax_impl
+
+template <
+ typename R = safe_minmax_impl::DefaultType,
+ typename T = safe_minmax_impl::DefaultType,
+ typename L = safe_minmax_impl::DefaultType,
+ typename H = safe_minmax_impl::DefaultType,
+ typename R2 = typename safe_minmax_impl::TypeOr<
+ R,
+ typename safe_minmax_impl::ClampType<
+ typename safe_minmax_impl::UnderlyingType<T>::type,
+ typename safe_minmax_impl::UnderlyingType<L>::type,
+ typename safe_minmax_impl::UnderlyingType<H>::type>::type>::type>
+R2 SafeClamp(T x, L min, H max) {
+ static_assert(IsIntlike<H>::value || std::is_floating_point<H>::value,
+ "The first argument must be integral or floating-point");
+ static_assert(IsIntlike<T>::value || std::is_floating_point<T>::value,
+ "The second argument must be integral or floating-point");
+ static_assert(IsIntlike<L>::value || std::is_floating_point<L>::value,
+ "The third argument must be integral or floating-point");
+ RTC_DCHECK_LE(min, max);
+ return safe_cmp::Le(x, min)
+ ? static_cast<R2>(min)
+ : safe_cmp::Ge(x, max) ? static_cast<R2>(max) : static_cast<R2>(x);
+}
+
} // namespace rtc
#endif // WEBRTC_BASE_SAFE_MINMAX_H_
diff --git a/webrtc/base/safe_minmax_unittest.cc b/webrtc/base/safe_minmax_unittest.cc
index 519158b..eb0fe80 100644
--- a/webrtc/base/safe_minmax_unittest.cc
+++ b/webrtc/base/safe_minmax_unittest.cc
@@ -18,8 +18,9 @@
namespace {
-// Functions that check that SafeMin() and SafeMax() return the specified type.
-// The functions that end in "R" use an explicitly given return type.
+// Functions that check that SafeMin(), SafeMax(), and SafeClamp() return the
+// specified type. The functions that end in "R" use an explicitly given return
+// type.
template <typename T1, typename T2, typename Tmin, typename Tmax>
constexpr bool TypeCheckMinMax() {
@@ -41,6 +42,21 @@
decltype(SafeMax<R>(std::declval<T1>(), std::declval<T2>())), R>::value;
}
+template <typename T, typename L, typename H, typename R>
+constexpr bool TypeCheckClamp() {
+ return std::is_same<decltype(SafeClamp(std::declval<T>(), std::declval<L>(),
+ std::declval<H>())),
+ R>::value;
+}
+
+template <typename T, typename L, typename H, typename R>
+constexpr bool TypeCheckClampR() {
+ return std::is_same<decltype(SafeClamp<R>(std::declval<T>(),
+ std::declval<L>(),
+ std::declval<H>())),
+ R>::value;
+}
+
// clang-format off
// SafeMin/SafeMax: Check that all combinations of signed/unsigned 8/64 bits
@@ -62,6 +78,73 @@
static_assert(TypeCheckMinMax<uint64_t, int64_t, int64_t, uint64_t>(), "");
static_assert(TypeCheckMinMax<uint64_t, uint64_t, uint64_t, uint64_t>(), "");
+// SafeClamp: Check that all combinations of signed/unsigned 8/64 bits give the
+// correct result type.
+static_assert(TypeCheckClamp< int8_t, int8_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp< int8_t, int8_t, uint8_t, int8_t>(), "");
+static_assert(TypeCheckClamp< int8_t, int8_t, int64_t, int8_t>(), "");
+static_assert(TypeCheckClamp< int8_t, int8_t, uint64_t, int8_t>(), "");
+static_assert(TypeCheckClamp< int8_t, uint8_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp< int8_t, uint8_t, uint8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp< int8_t, uint8_t, int64_t, int16_t>(), "");
+static_assert(TypeCheckClamp< int8_t, uint8_t, uint64_t, int16_t>(), "");
+static_assert(TypeCheckClamp< int8_t, int64_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp< int8_t, int64_t, uint8_t, int16_t>(), "");
+static_assert(TypeCheckClamp< int8_t, int64_t, int64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int8_t, int64_t, uint64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int8_t, uint64_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp< int8_t, uint64_t, uint8_t, int16_t>(), "");
+static_assert(TypeCheckClamp< int8_t, uint64_t, int64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int8_t, uint64_t, uint64_t, uint64_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, int8_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, int8_t, uint8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, int8_t, int64_t, int16_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, int8_t, uint64_t, uint8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, uint8_t, int8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, uint8_t, uint8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, uint8_t, int64_t, uint8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, uint8_t, uint64_t, uint8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, int64_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, int64_t, uint8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, int64_t, int64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, int64_t, uint64_t, uint64_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, uint64_t, int8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, uint64_t, uint8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, uint64_t, int64_t, uint64_t>(), "");
+static_assert(TypeCheckClamp< uint8_t, uint64_t, uint64_t, uint64_t>(), "");
+static_assert(TypeCheckClamp< int64_t, int8_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp< int64_t, int8_t, uint8_t, int16_t>(), "");
+static_assert(TypeCheckClamp< int64_t, int8_t, int64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int64_t, int8_t, uint64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int64_t, uint8_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp< int64_t, uint8_t, uint8_t, int16_t>(), "");
+static_assert(TypeCheckClamp< int64_t, uint8_t, int64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int64_t, uint8_t, uint64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int64_t, int64_t, int8_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int64_t, int64_t, uint8_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int64_t, int64_t, int64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int64_t, int64_t, uint64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int64_t, uint64_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp< int64_t, uint64_t, uint8_t, int16_t>(), "");
+static_assert(TypeCheckClamp< int64_t, uint64_t, int64_t, int64_t>(), "");
+static_assert(TypeCheckClamp< int64_t, uint64_t, uint64_t, uint64_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, int8_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, int8_t, uint8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, int8_t, int64_t, int64_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, int8_t, uint64_t, uint64_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, uint8_t, int8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, uint8_t, uint8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, uint8_t, int64_t, uint64_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, uint8_t, uint64_t, uint64_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, int64_t, int8_t, int8_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, int64_t, uint8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, int64_t, int64_t, int64_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, int64_t, uint64_t, uint64_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, uint64_t, int8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, uint64_t, uint8_t, uint8_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, uint64_t, int64_t, uint64_t>(), "");
+static_assert(TypeCheckClamp<uint64_t, uint64_t, uint64_t, uint64_t>(), "");
+
enum DefaultE { kFoo = -17 };
enum UInt8E : uint8_t { kBar = 17 };
@@ -76,6 +159,35 @@
static_assert(TypeCheckMinMax< UInt8E, DefaultE, int, int>(), "");
static_assert(TypeCheckMinMax< UInt8E, UInt8E, uint8_t, uint8_t>(), "");
+// SafeClamp: Check that we can use enum types.
+static_assert(TypeCheckClamp<unsigned, unsigned, unsigned, unsigned>(), "");
+static_assert(TypeCheckClamp<unsigned, unsigned, DefaultE, unsigned>(), "");
+static_assert(TypeCheckClamp<unsigned, unsigned, UInt8E, uint8_t>(), "");
+static_assert(TypeCheckClamp<unsigned, DefaultE, unsigned, unsigned>(), "");
+static_assert(TypeCheckClamp<unsigned, DefaultE, DefaultE, int>(), "");
+static_assert(TypeCheckClamp<unsigned, DefaultE, UInt8E, uint8_t>(), "");
+static_assert(TypeCheckClamp<unsigned, UInt8E, unsigned, unsigned>(), "");
+static_assert(TypeCheckClamp<unsigned, UInt8E, DefaultE, unsigned>(), "");
+static_assert(TypeCheckClamp<unsigned, UInt8E, UInt8E, uint8_t>(), "");
+static_assert(TypeCheckClamp<DefaultE, unsigned, unsigned, unsigned>(), "");
+static_assert(TypeCheckClamp<DefaultE, unsigned, DefaultE, int>(), "");
+static_assert(TypeCheckClamp<DefaultE, unsigned, UInt8E, int16_t>(), "");
+static_assert(TypeCheckClamp<DefaultE, DefaultE, unsigned, int>(), "");
+static_assert(TypeCheckClamp<DefaultE, DefaultE, DefaultE, int>(), "");
+static_assert(TypeCheckClamp<DefaultE, DefaultE, UInt8E, int>(), "");
+static_assert(TypeCheckClamp<DefaultE, UInt8E, unsigned, int>(), "");
+static_assert(TypeCheckClamp<DefaultE, UInt8E, DefaultE, int>(), "");
+static_assert(TypeCheckClamp<DefaultE, UInt8E, UInt8E, int16_t>(), "");
+static_assert(TypeCheckClamp< UInt8E, unsigned, unsigned, unsigned>(), "");
+static_assert(TypeCheckClamp< UInt8E, unsigned, DefaultE, unsigned>(), "");
+static_assert(TypeCheckClamp< UInt8E, unsigned, UInt8E, uint8_t>(), "");
+static_assert(TypeCheckClamp< UInt8E, DefaultE, unsigned, unsigned>(), "");
+static_assert(TypeCheckClamp< UInt8E, DefaultE, DefaultE, int>(), "");
+static_assert(TypeCheckClamp< UInt8E, DefaultE, UInt8E, uint8_t>(), "");
+static_assert(TypeCheckClamp< UInt8E, UInt8E, unsigned, uint8_t>(), "");
+static_assert(TypeCheckClamp< UInt8E, UInt8E, DefaultE, uint8_t>(), "");
+static_assert(TypeCheckClamp< UInt8E, UInt8E, UInt8E, uint8_t>(), "");
+
using ld = long double;
// SafeMin/SafeMax: Check that all floating-point combinations give the
@@ -90,6 +202,36 @@
static_assert(TypeCheckMinMax< ld, double, ld, ld>(), "");
static_assert(TypeCheckMinMax< ld, ld, ld, ld>(), "");
+// SafeClamp: Check that all floating-point combinations give the correct
+// result type.
+static_assert(TypeCheckClamp< float, float, float, float>(), "");
+static_assert(TypeCheckClamp< float, float, double, double>(), "");
+static_assert(TypeCheckClamp< float, float, ld, ld>(), "");
+static_assert(TypeCheckClamp< float, double, float, double>(), "");
+static_assert(TypeCheckClamp< float, double, double, double>(), "");
+static_assert(TypeCheckClamp< float, double, ld, ld>(), "");
+static_assert(TypeCheckClamp< float, ld, float, ld>(), "");
+static_assert(TypeCheckClamp< float, ld, double, ld>(), "");
+static_assert(TypeCheckClamp< float, ld, ld, ld>(), "");
+static_assert(TypeCheckClamp<double, float, float, double>(), "");
+static_assert(TypeCheckClamp<double, float, double, double>(), "");
+static_assert(TypeCheckClamp<double, float, ld, ld>(), "");
+static_assert(TypeCheckClamp<double, double, float, double>(), "");
+static_assert(TypeCheckClamp<double, double, double, double>(), "");
+static_assert(TypeCheckClamp<double, double, ld, ld>(), "");
+static_assert(TypeCheckClamp<double, ld, float, ld>(), "");
+static_assert(TypeCheckClamp<double, ld, double, ld>(), "");
+static_assert(TypeCheckClamp<double, ld, ld, ld>(), "");
+static_assert(TypeCheckClamp< ld, float, float, ld>(), "");
+static_assert(TypeCheckClamp< ld, float, double, ld>(), "");
+static_assert(TypeCheckClamp< ld, float, ld, ld>(), "");
+static_assert(TypeCheckClamp< ld, double, float, ld>(), "");
+static_assert(TypeCheckClamp< ld, double, double, ld>(), "");
+static_assert(TypeCheckClamp< ld, double, ld, ld>(), "");
+static_assert(TypeCheckClamp< ld, ld, float, ld>(), "");
+static_assert(TypeCheckClamp< ld, ld, double, ld>(), "");
+static_assert(TypeCheckClamp< ld, ld, ld, ld>(), "");
+
// clang-format on
// SafeMin/SafeMax: Check some cases of explicitly specified return type. The
@@ -103,12 +245,24 @@
static_assert(TypeCheckMaxR<uint32_t, int32_t, uint32_t>(), "");
// static_assert(TypeCheckMaxR<uint32_t, int32_t, int32_t>(), "");
+// SafeClamp: Check some cases of explicitly specified return type. The
+// commented-out lines give compilation errors due to the requested return type
+// being too small.
+static_assert(TypeCheckClampR<int16_t, int8_t, uint8_t, int16_t>(), "");
+static_assert(TypeCheckClampR<int16_t, int8_t, uint8_t, int32_t>(), "");
+// static_assert(TypeCheckClampR<int16_t, int8_t, uint8_t, uint32_t>(), "");
+
template <typename T1, typename T2, typename Tmin, typename Tmax>
constexpr bool CheckMinMax(T1 a, T2 b, Tmin min, Tmax max) {
return TypeCheckMinMax<T1, T2, Tmin, Tmax>() && SafeMin(a, b) == min &&
SafeMax(a, b) == max;
}
+template <typename T, typename L, typename H, typename R>
+bool CheckClamp(T x, L min, H max, R clamped) {
+ return TypeCheckClamp<T, L, H, R>() && SafeClamp(x, min, max) == clamped;
+}
+
// SafeMin/SafeMax: Check a few values.
static_assert(CheckMinMax(int8_t{1}, int8_t{-1}, int8_t{-1}, int8_t{1}), "");
static_assert(CheckMinMax(uint8_t{1}, int8_t{-1}, int8_t{-1}, uint8_t{1}), "");
@@ -127,22 +281,64 @@
// static_assert(CheckMinMax(1.f, 2, 1.f, 2.f), "");
static_assert(CheckMinMax(1.f, 0.0, 0.0, 1.0), "");
+// SafeClamp: Check a few values.
+TEST(SafeMinmaxTest, Clamp) {
+ EXPECT_TRUE(CheckClamp(int32_t{-1000000}, std::numeric_limits<int16_t>::min(),
+ std::numeric_limits<int16_t>::max(),
+ std::numeric_limits<int16_t>::min()));
+ EXPECT_TRUE(CheckClamp(uint32_t{1000000}, std::numeric_limits<int16_t>::min(),
+ std::numeric_limits<int16_t>::max(),
+ std::numeric_limits<int16_t>::max()));
+ EXPECT_TRUE(CheckClamp(3.f, -1.0, 1.f, 1.0));
+ EXPECT_TRUE(CheckClamp(3.0, -1.f, 1.f, 1.0));
+}
+
} // namespace
-// clang-format off
-
// These functions aren't used in the tests, but it's useful to look at the
-// compiler output for them, and verify that (1) the same-signedness *Safe
-// functions result in exactly the same code as their *Ref counterparts, and
-// that (2) the mixed-signedness *Safe functions have just a few extra
+// compiler output for them, and verify that (1) the same-signedness Test*Safe
+// functions result in exactly the same code as their Test*Ref counterparts,
+// and that (2) the mixed-signedness Test*Safe functions have just a few extra
// arithmetic and logic instructions (but no extra control flow instructions).
+
+// clang-format off
int32_t TestMinRef( int32_t a, int32_t b) { return std::min(a, b); }
uint32_t TestMinRef( uint32_t a, uint32_t b) { return std::min(a, b); }
int32_t TestMinSafe( int32_t a, int32_t b) { return SafeMin(a, b); }
int32_t TestMinSafe( int32_t a, uint32_t b) { return SafeMin(a, b); }
int32_t TestMinSafe(uint32_t a, int32_t b) { return SafeMin(a, b); }
uint32_t TestMinSafe(uint32_t a, uint32_t b) { return SafeMin(a, b); }
-
// clang-format on
+int32_t TestClampRef(int32_t x, int32_t a, int32_t b) {
+ return std::max(a, std::min(x, b));
+}
+uint32_t TestClampRef(uint32_t x, uint32_t a, uint32_t b) {
+ return std::max(a, std::min(x, b));
+}
+int32_t TestClampSafe(int32_t x, int32_t a, int32_t b) {
+ return SafeClamp(x, a, b);
+}
+int32_t TestClampSafe(int32_t x, int32_t a, uint32_t b) {
+ return SafeClamp(x, a, b);
+}
+int32_t TestClampSafe(int32_t x, uint32_t a, int32_t b) {
+ return SafeClamp(x, a, b);
+}
+uint32_t TestClampSafe(int32_t x, uint32_t a, uint32_t b) {
+ return SafeClamp(x, a, b);
+}
+int32_t TestClampSafe(uint32_t x, int32_t a, int32_t b) {
+ return SafeClamp(x, a, b);
+}
+uint32_t TestClampSafe(uint32_t x, int32_t a, uint32_t b) {
+ return SafeClamp(x, a, b);
+}
+int32_t TestClampSafe(uint32_t x, uint32_t a, int32_t b) {
+ return SafeClamp(x, a, b);
+}
+uint32_t TestClampSafe(uint32_t x, uint32_t a, uint32_t b) {
+ return SafeClamp(x, a, b);
+}
+
} // namespace rtc
diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
index 64df679..be32aef 100644
--- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
@@ -20,6 +20,7 @@
#include "webrtc/base/numerics/exp_filter.h"
#include "webrtc/base/protobuf_utils.h"
#include "webrtc/base/safe_conversions.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/base/string_to_number.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/common_types.h"
@@ -690,8 +691,8 @@
}
void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) {
- config_.bitrate_bps = rtc::Optional<int>(std::max(
- std::min(bits_per_second, kOpusMaxBitrateBps), kOpusMinBitrateBps));
+ config_.bitrate_bps = rtc::Optional<int>(rtc::SafeClamp<int>(
+ bits_per_second, kOpusMinBitrateBps, kOpusMaxBitrateBps));
RTC_DCHECK(config_.IsOk());
RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.GetBitrateBps()));
const auto new_complexity = config_.GetNewComplexity();
diff --git a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
index 4560958..2402d91 100644
--- a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
+++ b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
@@ -20,6 +20,7 @@
#endif
#include "webrtc/base/arraysize.h"
#include "webrtc/base/random.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/modules/audio_processing/aec3/aec3_fft.h"
#include "webrtc/modules/audio_processing/aec3/aec_state.h"
#include "webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h"
@@ -350,9 +351,8 @@
fft.Ifft(S, &s);
std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2, e.begin(),
[&](float a, float b) { return a - b * kScale; });
- std::for_each(e.begin(), e.end(), [](float& a) {
- a = std::max(std::min(a, 32767.0f), -32768.0f);
- });
+ std::for_each(e.begin(), e.end(),
+ [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
fft.ZeroPaddedFft(e, &E);
gain.Compute(render_buffer, render_signal_analyzer, E,
diff --git a/webrtc/modules/audio_processing/aec3/echo_remover_metrics.cc b/webrtc/modules/audio_processing/aec3/echo_remover_metrics.cc
index ed11959..bc7e600 100644
--- a/webrtc/modules/audio_processing/aec3/echo_remover_metrics.cc
+++ b/webrtc/modules/audio_processing/aec3/echo_remover_metrics.cc
@@ -14,6 +14,7 @@
#include <algorithm>
#include <numeric>
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/system_wrappers/include/metrics.h"
namespace webrtc {
@@ -273,7 +274,7 @@
if (negate) {
new_value = -new_value;
}
- return static_cast<int>(std::max(min_value, std::min(max_value, new_value)));
+ return static_cast<int>(rtc::SafeClamp(new_value, min_value, max_value));
}
} // namespace aec3
diff --git a/webrtc/modules/audio_processing/aec3/erle_estimator.cc b/webrtc/modules/audio_processing/aec3/erle_estimator.cc
index c139412..7faf22c 100644
--- a/webrtc/modules/audio_processing/aec3/erle_estimator.cc
+++ b/webrtc/modules/audio_processing/aec3/erle_estimator.cc
@@ -12,6 +12,8 @@
#include <algorithm>
+#include "webrtc/base/safe_minmax.h"
+
namespace webrtc {
namespace {
@@ -48,7 +50,7 @@
if (new_erle > erle_[k]) {
hold_counters_[k - 1] = 100;
erle_[k] += 0.1f * (new_erle - erle_[k]);
- erle_[k] = std::max(kMinErle, std::min(erle_[k], max_erle));
+ erle_[k] = rtc::SafeClamp(erle_[k], kMinErle, max_erle);
}
}
}
diff --git a/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
index 2a4d4d6..581856b 100644
--- a/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
+++ b/webrtc/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
@@ -15,6 +15,7 @@
#include <string>
#include "webrtc/base/random.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/modules/audio_processing/aec3/adaptive_fir_filter.h"
#include "webrtc/modules/audio_processing/aec3/aec_state.h"
#include "webrtc/modules/audio_processing/aec3/render_buffer.h"
@@ -99,9 +100,8 @@
std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2,
e_main.begin(),
[&](float a, float b) { return a - b * kScale; });
- std::for_each(e_main.begin(), e_main.end(), [](float& a) {
- a = std::max(std::min(a, 32767.0f), -32768.0f);
- });
+ std::for_each(e_main.begin(), e_main.end(),
+ [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
fft.ZeroPaddedFft(e_main, &E_main);
// Apply the shadow filter.
@@ -110,9 +110,8 @@
std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2,
e_shadow.begin(),
[&](float a, float b) { return a - b * kScale; });
- std::for_each(e_shadow.begin(), e_shadow.end(), [](float& a) {
- a = std::max(std::min(a, 32767.0f), -32768.0f);
- });
+ std::for_each(e_shadow.begin(), e_shadow.end(),
+ [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
fft.ZeroPaddedFft(e_shadow, &E_shadow);
// Compute spectra for future use.
diff --git a/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc b/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
index 82850f8..40bee42 100644
--- a/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
+++ b/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
@@ -16,9 +16,10 @@
#include <vector>
#include "webrtc/base/random.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/modules/audio_processing/aec3/adaptive_fir_filter.h"
-#include "webrtc/modules/audio_processing/aec3/aec_state.h"
#include "webrtc/modules/audio_processing/aec3/aec3_common.h"
+#include "webrtc/modules/audio_processing/aec3/aec_state.h"
#include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h"
#include "webrtc/test/gtest.h"
@@ -75,9 +76,8 @@
std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2,
e_shadow.begin(),
[&](float a, float b) { return a - b * kScale; });
- std::for_each(e_shadow.begin(), e_shadow.end(), [](float& a) {
- a = std::max(std::min(a, 32767.0f), -32768.0f);
- });
+ std::for_each(e_shadow.begin(), e_shadow.end(),
+ [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
fft.ZeroPaddedFft(e_shadow, &E_shadow);
shadow_gain.Compute(render_buffer, render_signal_analyzer, E_shadow,
diff --git a/webrtc/modules/audio_processing/aec3/subtractor.cc b/webrtc/modules/audio_processing/aec3/subtractor.cc
index 3897d94..dc3ec06 100644
--- a/webrtc/modules/audio_processing/aec3/subtractor.cc
+++ b/webrtc/modules/audio_processing/aec3/subtractor.cc
@@ -14,6 +14,7 @@
#include "webrtc/base/array_view.h"
#include "webrtc/base/checks.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
namespace webrtc {
@@ -30,9 +31,8 @@
constexpr float kScale = 1.0f / kFftLengthBy2;
std::transform(y.begin(), y.end(), s.begin() + kFftLengthBy2, e->begin(),
[&](float a, float b) { return a - b * kScale; });
- std::for_each(e->begin(), e->end(), [](float& a) {
- a = std::max(std::min(a, 32767.0f), -32768.0f);
- });
+ std::for_each(e->begin(), e->end(),
+ [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
fft.ZeroPaddedFft(*e, E);
}
} // namespace
diff --git a/webrtc/modules/audio_processing/aec3/suppression_filter.cc b/webrtc/modules/audio_processing/aec3/suppression_filter.cc
index b172a1d..1121c74 100644
--- a/webrtc/modules/audio_processing/aec3/suppression_filter.cc
+++ b/webrtc/modules/audio_processing/aec3/suppression_filter.cc
@@ -16,6 +16,7 @@
#include <functional>
#include <numeric>
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/modules/audio_processing/utility/ooura_fft.h"
namespace webrtc {
@@ -122,7 +123,7 @@
std::transform((*e)[0].begin(), (*e)[0].end(), e_extended.begin(),
(*e)[0].begin(), std::plus<float>());
std::for_each((*e)[0].begin(), (*e)[0].end(), [](float& x_k) {
- x_k = std::max(std::min(x_k, 32767.0f), -32768.0f);
+ x_k = rtc::SafeClamp(x_k, -32768.f, 32767.f);
});
std::copy(e_extended.begin() + kFftLengthBy2, e_extended.begin() + kFftLength,
std::begin(e_output_old_[0]));
@@ -154,7 +155,7 @@
if (e->size() > 2) {
RTC_DCHECK_EQ(3, e->size());
std::for_each((*e)[2].begin(), (*e)[2].end(), [&](float& a) {
- a = std::max(std::min(a * high_bands_gain, 32767.0f), -32768.0f);
+ a = rtc::SafeClamp(a * high_bands_gain, -32768.f, 32767.f);
});
}
diff --git a/webrtc/modules/audio_processing/agc/agc_manager_direct.cc b/webrtc/modules/audio_processing/agc/agc_manager_direct.cc
index 5d1e7cd..6a19945 100644
--- a/webrtc/modules/audio_processing/agc/agc_manager_direct.cc
+++ b/webrtc/modules/audio_processing/agc/agc_manager_direct.cc
@@ -18,6 +18,7 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/modules/audio_processing/agc/gain_map_internal.h"
#include "webrtc/modules/audio_processing/gain_control_impl.h"
#include "webrtc/modules/include/module_common_types.h"
@@ -56,7 +57,7 @@
const int kSurplusCompressionGain = 6;
int ClampLevel(int mic_level) {
- return std::min(std::max(kMinMicLevel, mic_level), kMaxMicLevel);
+ return rtc::SafeClamp(mic_level, kMinMicLevel, kMaxMicLevel);
}
int LevelFromGainError(int gain_error, int level) {
@@ -380,8 +381,9 @@
rms_error += kMinCompressionGain;
// Handle as much error as possible with the compressor first.
- int raw_compression = std::max(std::min(rms_error, max_compression_gain_),
- kMinCompressionGain);
+ int raw_compression =
+ rtc::SafeClamp(rms_error, kMinCompressionGain, max_compression_gain_);
+
// Deemphasize the compression gain error. Move halfway between the current
// target and the newly received target. This serves to soften perceptible
// intra-talkspurt adjustments, at the cost of some adaptation speed.
@@ -400,9 +402,9 @@
// Residual error will be handled by adjusting the volume slider. Use the
// raw rather than deemphasized compression here as we would otherwise
// shrink the amount of slack the compressor provides.
- int residual_gain = rms_error - raw_compression;
- residual_gain = std::min(std::max(residual_gain, -kMaxResidualGainChange),
- kMaxResidualGainChange);
+ const int residual_gain =
+ rtc::SafeClamp(rms_error - raw_compression, -kMaxResidualGainChange,
+ kMaxResidualGainChange);
LOG(LS_INFO) << "[agc] rms_error=" << rms_error << ", "
<< "target_compression=" << target_compression_ << ", "
<< "residual_gain=" << residual_gain;
diff --git a/webrtc/modules/audio_processing/audio_processing_unittest.cc b/webrtc/modules/audio_processing/audio_processing_unittest.cc
index 4d97904..42cf418 100644
--- a/webrtc/modules/audio_processing/audio_processing_unittest.cc
+++ b/webrtc/modules/audio_processing/audio_processing_unittest.cc
@@ -680,15 +680,13 @@
// limit them w.r.t. AEC delay estimation support.
const size_t samples_per_ms =
rtc::SafeMin<size_t>(16u, frame_->samples_per_channel_ / 10);
- int expected_median = std::min(std::max(delay_ms - system_delay_ms,
- delay_min), delay_max);
- int expected_median_high = std::min(
- std::max(expected_median + static_cast<int>(96 / samples_per_ms),
- delay_min),
+ const int expected_median =
+ rtc::SafeClamp<int>(delay_ms - system_delay_ms, delay_min, delay_max);
+ const int expected_median_high = rtc::SafeClamp<int>(
+ expected_median + rtc::dchecked_cast<int>(96 / samples_per_ms), delay_min,
delay_max);
- int expected_median_low = std::min(
- std::max(expected_median - static_cast<int>(96 / samples_per_ms),
- delay_min),
+ const int expected_median_low = rtc::SafeClamp<int>(
+ expected_median - rtc::dchecked_cast<int>(96 / samples_per_ms), delay_min,
delay_max);
// Verify delay metrics.
int median;
diff --git a/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc b/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc
index 7ff2cf4..f5414aa 100644
--- a/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc
+++ b/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.cc
@@ -18,6 +18,7 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/common_audio/include/audio_util.h"
#include "webrtc/common_audio/window_generator.h"
@@ -287,23 +288,23 @@
}
for (size_t i = 1; i <= bank_size_; ++i) {
- static const size_t kOne = 1; // Avoids repeated static_cast<>s below.
- size_t lll =
- static_cast<size_t>(round(center_freqs_[std::max(kOne, i - lf) - 1] *
- num_freqs / (0.5f * sample_rate_hz_)));
- size_t ll = static_cast<size_t>(round(center_freqs_[std::max(kOne, i) - 1] *
- num_freqs / (0.5f * sample_rate_hz_)));
- lll = std::min(num_freqs, std::max(lll, kOne)) - 1;
- ll = std::min(num_freqs, std::max(ll, kOne)) - 1;
+ size_t lll = static_cast<size_t>(
+ round(center_freqs_[rtc::SafeMax<size_t>(1, i - lf) - 1] * num_freqs /
+ (0.5f * sample_rate_hz_)));
+ size_t ll = static_cast<size_t>(
+ round(center_freqs_[rtc::SafeMax<size_t>(1, i) - 1] * num_freqs /
+ (0.5f * sample_rate_hz_)));
+ lll = rtc::SafeClamp<size_t>(lll, 1, num_freqs) - 1;
+ ll = rtc::SafeClamp<size_t>(ll, 1, num_freqs) - 1;
size_t rrr = static_cast<size_t>(
- round(center_freqs_[std::min(bank_size_, i + rf) - 1] * num_freqs /
- (0.5f * sample_rate_hz_)));
+ round(center_freqs_[rtc::SafeMin<size_t>(bank_size_, i + rf) - 1] *
+ num_freqs / (0.5f * sample_rate_hz_)));
size_t rr = static_cast<size_t>(
- round(center_freqs_[std::min(bank_size_, i + 1) - 1] * num_freqs /
- (0.5f * sample_rate_hz_)));
- rrr = std::min(num_freqs, std::max(rrr, kOne)) - 1;
- rr = std::min(num_freqs, std::max(rr, kOne)) - 1;
+ round(center_freqs_[rtc::SafeMin<size_t>(bank_size_, i + 1) - 1] *
+ num_freqs / (0.5f * sample_rate_hz_)));
+ rrr = rtc::SafeClamp<size_t>(rrr, 1, num_freqs) - 1;
+ rr = rtc::SafeClamp<size_t>(rr, 1, num_freqs) - 1;
float step = ll == lll ? 0.f : 1.f / (ll - lll);
float element = 0.f;
diff --git a/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc b/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc
index fa8d170..deaeb27 100644
--- a/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc
+++ b/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.cc
@@ -16,6 +16,8 @@
#include <algorithm>
#include <limits>
+#include "webrtc/base/safe_minmax.h"
+
namespace webrtc {
namespace intelligibility {
@@ -28,9 +30,9 @@
// Return |current| changed towards |target|, with the relative change being at
// most |limit|.
float UpdateFactor(float target, float current, float limit) {
- float gain = target / (current + std::numeric_limits<float>::epsilon());
- gain = std::min(std::max(gain, 1.f - limit), 1.f + limit);
- return std::min(std::max(current * gain, kMinFactor), kMaxFactor);;
+ const float gain = target / (current + std::numeric_limits<float>::epsilon());
+ const float clamped_gain = rtc::SafeClamp(gain, 1 - limit, 1 + limit);
+ return rtc::SafeClamp(current * clamped_gain, kMinFactor, kMaxFactor);
}
} // namespace
diff --git a/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc
index d903cf9..4b9343c 100644
--- a/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc
+++ b/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc
@@ -62,11 +62,11 @@
// Estimate how often we can send RTCP if we allocate up to 5% of bandwidth
// to feedback.
static const int kRtcpSize = 80;
- int64_t interval = static_cast<int64_t>(
+ const int64_t interval = static_cast<int64_t>(
kRtcpSize * 8.0 * 1000.0 / (0.05 * current_bitrate_bps_) + 0.5);
const int64_t kMinFeedbackIntervalMs = 200;
- return std::min(std::max(interval, kMinFeedbackIntervalMs),
- kMaxFeedbackIntervalMs);
+ return rtc::SafeClamp(interval, kMinFeedbackIntervalMs,
+ kMaxFeedbackIntervalMs);
}
bool AimdRateControl::TimeToReduceFurther(int64_t time_now,
diff --git a/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc b/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc
index 399daf0..6b2b518 100644
--- a/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc
+++ b/webrtc/modules/remote_bitrate_estimator/overuse_detector.cc
@@ -19,6 +19,7 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
@@ -144,11 +145,7 @@
int64_t time_delta_ms = std::min(now_ms - last_update_ms_, kMaxTimeDeltaMs);
threshold_ +=
k * (fabs(modified_offset) - threshold_) * time_delta_ms;
-
- const double kMinThreshold = 6;
- const double kMaxThreshold = 600;
- threshold_ = std::min(std::max(threshold_, kMinThreshold), kMaxThreshold);
-
+ threshold_ = rtc::SafeClamp(threshold_, 6.f, 600.f);
last_update_ms_ = now_ms;
}
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.cc b/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.cc
index 3700fc4..35bc667 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.cc
+++ b/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.cc
@@ -15,10 +15,11 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
-#include "webrtc/system_wrappers/include/clock.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/modules/pacing/packet_router.h"
-#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
+#include "webrtc/system_wrappers/include/clock.h"
namespace webrtc {
@@ -104,8 +105,9 @@
// Let TWCC reports occupy 5% of total bandwidth.
rtc::CritScope cs(&lock_);
- send_interval_ms_ = static_cast<int>(0.5 + kTwccReportSize * 8.0 * 1000.0 /
- (std::max(std::min(0.05 * bitrate_bps, kMaxTwccRate), kMinTwccRate)));
+ send_interval_ms_ = static_cast<int>(
+ 0.5 + kTwccReportSize * 8.0 * 1000.0 /
+ rtc::SafeClamp(0.05 * bitrate_bps, kMinTwccRate, kMaxTwccRate));
}
void RemoteEstimatorProxy::OnPacketArrival(uint16_t sequence_number,
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
index 15e759b..1361277 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
@@ -15,6 +15,7 @@
#include <sstream>
#include "webrtc/base/constructormagic.h"
+#include "webrtc/base/safe_minmax.h"
namespace webrtc {
namespace testing {
@@ -406,8 +407,8 @@
inline int64_t TruncatedNSigmaGaussian(Random* const random,
int64_t mean,
int64_t std_dev) {
- int64_t gaussian_random = random->Gaussian(mean, std_dev);
- return std::max(std::min(gaussian_random, kN * std_dev), -kN * std_dev);
+ const int64_t gaussian_random = random->Gaussian(mean, std_dev);
+ return rtc::SafeClamp(gaussian_random, -kN * std_dev, kN * std_dev);
}
}
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
index 3cac419..1bdb804 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
@@ -17,8 +17,9 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/rate_limiter.h"
-#include "webrtc/base/trace_event.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/base/timeutils.h"
+#include "webrtc/base/trace_event.h"
#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h"
@@ -467,16 +468,16 @@
if (audio_configured_) {
// Allow smaller padding packets for audio.
- padding_bytes_in_packet =
- std::min(std::max(bytes, kMinAudioPaddingLength), max_payload_size);
- if (padding_bytes_in_packet > kMaxPaddingLength)
- padding_bytes_in_packet = kMaxPaddingLength;
+ padding_bytes_in_packet = rtc::SafeClamp<size_t>(
+ bytes, kMinAudioPaddingLength,
+ rtc::SafeMin(max_payload_size, kMaxPaddingLength));
} else {
// Always send full padding packets. This is accounted for by the
// RtpPacketSender, which will make sure we don't send too much padding even
// if a single packet is larger than requested.
// We do this to avoid frequently sending small packets on higher bitrates.
- padding_bytes_in_packet = std::min(max_payload_size, kMaxPaddingLength);
+ padding_bytes_in_packet =
+ rtc::SafeMin<size_t>(max_payload_size, kMaxPaddingLength);
}
size_t bytes_sent = 0;
while (bytes_sent < bytes) {
diff --git a/webrtc/p2p/base/port.cc b/webrtc/p2p/base/port.cc
index bf54924..e657125 100644
--- a/webrtc/p2p/base/port.cc
+++ b/webrtc/p2p/base/port.cc
@@ -21,6 +21,7 @@
#include "webrtc/base/messagedigest.h"
#include "webrtc/base/network.h"
#include "webrtc/base/ptr_util.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/base/stringencode.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/p2p/base/common.h"
@@ -69,7 +70,7 @@
// Computes our estimate of the RTT given the current estimate.
inline int ConservativeRTTEstimate(int rtt) {
- return std::max(MINIMUM_RTT, std::min(MAXIMUM_RTT, 2 * rtt));
+ return rtc::SafeClamp(2 * rtt, MINIMUM_RTT, MAXIMUM_RTT);
}
// Weighting of the old rtt value to new data.
diff --git a/webrtc/p2p/base/pseudotcp.cc b/webrtc/p2p/base/pseudotcp.cc
index 8257b92..d93f49e 100644
--- a/webrtc/p2p/base/pseudotcp.cc
+++ b/webrtc/p2p/base/pseudotcp.cc
@@ -23,6 +23,7 @@
#include "webrtc/base/byteorder.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/base/socket.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/base/timeutils.h"
@@ -155,10 +156,6 @@
return rtc::NetworkToHost16(*static_cast<const uint16_t*>(buf));
}
-uint32_t bound(uint32_t lower, uint32_t middle, uint32_t upper) {
- return std::min(std::max(lower, middle), upper);
-}
-
//////////////////////////////////////////////////////////////////////
// Debugging Statistics
//////////////////////////////////////////////////////////////////////
@@ -725,9 +722,8 @@
m_rx_rttvar = (3 * m_rx_rttvar + abs_err) / 4;
m_rx_srtt = (7 * m_rx_srtt + rtt) / 8;
}
- m_rx_rto =
- bound(MIN_RTO, m_rx_srtt + std::max<uint32_t>(1, 4 * m_rx_rttvar),
- MAX_RTO);
+ m_rx_rto = rtc::SafeClamp(m_rx_srtt + rtc::SafeMax(1, 4 * m_rx_rttvar),
+ MIN_RTO, MAX_RTO);
#if _DEBUGMSG >= _DBG_VERBOSE
LOG(LS_INFO) << "rtt: " << rtt
<< " srtt: " << m_rx_srtt
diff --git a/webrtc/tools/agc/activity_metric.cc b/webrtc/tools/agc/activity_metric.cc
index 599777c..9715d62 100644
--- a/webrtc/tools/agc/activity_metric.cc
+++ b/webrtc/tools/agc/activity_metric.cc
@@ -17,6 +17,7 @@
#include <memory>
#include "webrtc/base/flags.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/modules/audio_processing/agc/agc.h"
#include "webrtc/modules/audio_processing/agc/loudness_histogram.h"
#include "webrtc/modules/audio_processing/agc/utility.h"
@@ -121,9 +122,7 @@
for (size_t n = 0; n < features.num_frames; n++) {
double p_active = p[n] * video_vad_[n];
double p_passive = (1 - p[n]) * (1 - video_vad_[n]);
- p[n] = p_active / (p_active + p_passive);
- // Limit probabilities.
- p[n] = std::min(std::max(p[n], 0.01), 0.99);
+ p[n] = rtc::SafeClamp(p_active / (p_active + p_passive), 0.01, 0.99);
}
if (vad_->VoicingProbability(features, p) < 0)
return -1;
diff --git a/webrtc/voice_engine/channel_proxy.cc b/webrtc/voice_engine/channel_proxy.cc
index 46bcef9..4a0b3cc 100644
--- a/webrtc/voice_engine/channel_proxy.cc
+++ b/webrtc/voice_engine/channel_proxy.cc
@@ -15,6 +15,7 @@
#include "webrtc/api/call/audio_sink.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
+#include "webrtc/base/safe_minmax.h"
#include "webrtc/call/rtp_transport_controller_send_interface.h"
#include "webrtc/voice_engine/channel.h"
@@ -290,7 +291,7 @@
RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
// Limit to range accepted by both VoE and ACM, so we're at least getting as
// close as possible, instead of failing.
- delay_ms = std::max(0, std::min(delay_ms, 10000));
+ delay_ms = rtc::SafeClamp(delay_ms, 0, 10000);
int error = channel()->SetMinimumPlayoutDelay(delay_ms);
if (0 != error) {
LOG(LS_WARNING) << "Error setting minimum playout delay.";