blob: 5482cec6e5a8255db7a6dd83d8fd50ae5f17d14f [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2005 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Artem Titov9d777622020-09-18 18:23:08 +020011#ifndef API_NUMERICS_MATH_UTILS_H_
12#define API_NUMERICS_MATH_UTILS_H_
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000013
Yves Gerey14696c22019-04-11 13:51:10 +020014#include <limits>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020015#include <type_traits>
tereliusd802b5b2016-03-01 11:07:34 -080016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/checks.h"
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020018
Artem Titov9d777622020-09-18 18:23:08 +020019namespace webrtc {
20namespace webrtc_impl {
Artem Titov96e3b992021-07-26 16:03:14 +020021// Given two numbers `x` and `y` such that x >= y, computes the difference
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020022// x - y without causing undefined behavior due to signed overflow.
23template <typename T>
24typename std::make_unsigned<T>::type unsigned_difference(T x, T y) {
25 static_assert(
26 std::is_signed<T>::value,
27 "Function unsigned_difference is only meaningful for signed types.");
28 RTC_DCHECK_GE(x, y);
29 typedef typename std::make_unsigned<T>::type unsigned_type;
30 // int -> unsigned conversion repeatedly adds UINT_MAX + 1 until the number
31 // can be represented as an unsigned. Since we know that the actual
32 // difference x - y can be represented as an unsigned, it is sufficient to
33 // compute the difference modulo UINT_MAX + 1, i.e using unsigned arithmetic.
34 return static_cast<unsigned_type>(x) - static_cast<unsigned_type>(y);
35}
tereliusd802b5b2016-03-01 11:07:34 -080036
Yves Gerey890f62b2019-04-10 17:18:48 +020037// Provide neutral element with respect to min().
38// Typically used as an initial value for running minimum.
39template <typename T,
40 typename std::enable_if<std::numeric_limits<T>::has_infinity>::type* =
41 nullptr>
42constexpr T infinity_or_max() {
43 return std::numeric_limits<T>::infinity();
44}
45
46template <typename T,
47 typename std::enable_if<
48 !std::numeric_limits<T>::has_infinity>::type* = nullptr>
49constexpr T infinity_or_max() {
50 // Fallback to max().
51 return std::numeric_limits<T>::max();
52}
53
54// Provide neutral element with respect to max().
55// Typically used as an initial value for running maximum.
56template <typename T,
57 typename std::enable_if<std::numeric_limits<T>::has_infinity>::type* =
58 nullptr>
59constexpr T minus_infinity_or_min() {
60 static_assert(std::is_signed<T>::value, "Unsupported. Please open a bug.");
61 return -std::numeric_limits<T>::infinity();
62}
63
64template <typename T,
65 typename std::enable_if<
66 !std::numeric_limits<T>::has_infinity>::type* = nullptr>
67constexpr T minus_infinity_or_min() {
68 // Fallback to min().
69 return std::numeric_limits<T>::min();
70}
71
Artem Titov9d777622020-09-18 18:23:08 +020072} // namespace webrtc_impl
73} // namespace webrtc
74
75#endif // API_NUMERICS_MATH_UTILS_H_