Line data Source code
1 : /*
2 : * Copyright (c) 2016 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 :
11 : #ifndef WEBRTC_BASE_MOD_OPS_H_
12 : #define WEBRTC_BASE_MOD_OPS_H_
13 :
14 : #include <limits>
15 : #include <type_traits>
16 :
17 : #include "webrtc/base/checks.h"
18 :
19 : namespace webrtc {
20 :
21 : template <unsigned long M> // NOLINT
22 0 : inline unsigned long Add(unsigned long a, unsigned long b) { // NOLINT
23 0 : RTC_DCHECK_LT(a, M);
24 0 : unsigned long t = M - b % M; // NOLINT
25 0 : unsigned long res = a - t; // NOLINT
26 0 : if (t > a)
27 0 : return res + M;
28 0 : return res;
29 : }
30 :
31 : template <unsigned long M> // NOLINT
32 0 : inline unsigned long Subtract(unsigned long a, unsigned long b) { // NOLINT
33 0 : RTC_DCHECK_LT(a, M);
34 0 : unsigned long sub = b % M; // NOLINT
35 0 : if (a < sub)
36 0 : return M - (sub - a);
37 0 : return a - sub;
38 : }
39 :
40 : // Calculates the forward difference between two wrapping numbers.
41 : //
42 : // Example:
43 : // uint8_t x = 253;
44 : // uint8_t y = 2;
45 : //
46 : // ForwardDiff(x, y) == 5
47 : //
48 : // 252 253 254 255 0 1 2 3
49 : // #################################################
50 : // | | x | | | | | y | |
51 : // #################################################
52 : // |----->----->----->----->----->
53 : //
54 : // ForwardDiff(y, x) == 251
55 : //
56 : // 252 253 254 255 0 1 2 3
57 : // #################################################
58 : // | | x | | | | | y | |
59 : // #################################################
60 : // -->-----> |----->---
61 : //
62 : template <typename T, T M>
63 0 : inline T ForwardDiff(T a, T b) {
64 : static_assert(std::is_unsigned<T>::value,
65 : "Type must be an unsigned integer.");
66 0 : RTC_DCHECK_LT(a, M);
67 0 : RTC_DCHECK_LT(b, M);
68 0 : return a <= b ? b - a : M - (a - b);
69 : }
70 :
71 : template <typename T>
72 0 : inline T ForwardDiff(T a, T b) {
73 : static_assert(std::is_unsigned<T>::value,
74 : "Type must be an unsigned integer.");
75 0 : return b - a;
76 : }
77 :
78 : // Calculates the reverse difference between two wrapping numbers.
79 : //
80 : // Example:
81 : // uint8_t x = 253;
82 : // uint8_t y = 2;
83 : //
84 : // ReverseDiff(y, x) == 5
85 : //
86 : // 252 253 254 255 0 1 2 3
87 : // #################################################
88 : // | | x | | | | | y | |
89 : // #################################################
90 : // <-----<-----<-----<-----<-----|
91 : //
92 : // ReverseDiff(x, y) == 251
93 : //
94 : // 252 253 254 255 0 1 2 3
95 : // #################################################
96 : // | | x | | | | | y | |
97 : // #################################################
98 : // ---<-----| |<-----<--
99 : //
100 : template <typename T, T M>
101 0 : inline T ReverseDiff(T a, T b) {
102 : static_assert(std::is_unsigned<T>::value,
103 : "Type must be an unsigned integer.");
104 0 : RTC_DCHECK_LT(a, M);
105 0 : RTC_DCHECK_LT(b, M);
106 0 : return b <= a ? a - b : M - (b - a);
107 : }
108 :
109 : template <typename T>
110 0 : inline T ReverseDiff(T a, T b) {
111 : static_assert(std::is_unsigned<T>::value,
112 : "Type must be an unsigned integer.");
113 0 : return a - b;
114 : }
115 :
116 : // Calculates the minimum distance between to wrapping numbers.
117 : //
118 : // The minimum distance is defined as min(ForwardDiff(a, b), ReverseDiff(a, b))
119 : template <typename T, T M>
120 0 : inline T MinDiff(T a, T b) {
121 : static_assert(std::is_unsigned<T>::value,
122 : "Type must be an unsigned integer.");
123 0 : return std::min(ForwardDiff<T, M>(a, b), ReverseDiff<T, M>(a, b));
124 : }
125 :
126 : template <typename T>
127 : inline T MinDiff(T a, T b) {
128 : static_assert(std::is_unsigned<T>::value,
129 : "Type must be an unsigned integer.");
130 : return std::min(ForwardDiff(a, b), ReverseDiff(a, b));
131 : }
132 :
133 : } // namespace webrtc
134 :
135 : #endif // WEBRTC_BASE_MOD_OPS_H_
|