OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #ifndef WEBRTC_BASE_MOD_OPS_H_ | 11 #ifndef WEBRTC_BASE_MOD_OPS_H_ |
12 #define WEBRTC_BASE_MOD_OPS_H_ | 12 #define WEBRTC_BASE_MOD_OPS_H_ |
13 | 13 |
14 #include <limits> | 14 #include <limits> |
15 #include <type_traits> | 15 #include <type_traits> |
16 | 16 |
17 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
18 | 18 |
19 #define MOD_OPS_ASSERT_TYPE_IS_UNSIGNED(T) \ | |
20 static_assert(std::numeric_limits<T>::is_integer && \ | |
21 !std::numeric_limits<T>::is_signed, \ | |
22 "Type must be of unsigned integer.") | |
23 | |
24 namespace webrtc { | 19 namespace webrtc { |
25 | 20 |
26 template <unsigned long M> // NOLINT | 21 template <unsigned long M> // NOLINT |
27 inline unsigned long Add(unsigned long a, unsigned long b) { // NOLINT | 22 inline unsigned long Add(unsigned long a, unsigned long b) { // NOLINT |
28 RTC_DCHECK_LT(a, M); | 23 RTC_DCHECK_LT(a, M); |
29 unsigned long t = M - b % M; // NOLINT | 24 unsigned long t = M - b % M; // NOLINT |
30 unsigned long res = a - t; // NOLINT | 25 unsigned long res = a - t; // NOLINT |
31 if (t > a) | 26 if (t > a) |
32 return res + M; | 27 return res + M; |
33 return res; | 28 return res; |
34 } | 29 } |
35 | 30 |
36 template <unsigned long M> // NOLINT | 31 template <unsigned long M> // NOLINT |
37 inline unsigned long Subtract(unsigned long a, unsigned long b) { // NOLINT | 32 inline unsigned long Subtract(unsigned long a, unsigned long b) { // NOLINT |
38 RTC_DCHECK_LT(a, M); | 33 RTC_DCHECK_LT(a, M); |
39 unsigned long sub = b % M; // NOLINT | 34 unsigned long sub = b % M; // NOLINT |
40 if (a < sub) | 35 if (a < sub) |
41 return M - (sub - a); | 36 return M - (sub - a); |
42 return a - sub; | 37 return a - sub; |
43 } | 38 } |
44 | 39 |
45 // Calculates the forward difference between two numbers. | 40 // Calculates the forward difference between two wrapping numbers. |
46 // | 41 // |
47 // Example: | 42 // Example: |
48 // uint8_t x = 253; | 43 // uint8_t x = 253; |
49 // uint8_t y = 2; | 44 // uint8_t y = 2; |
50 // | 45 // |
51 // ForwardDiff(x, y) == 4 | 46 // ForwardDiff(x, y) == 4 |
52 // | 47 // |
53 // 252 253 254 255 0 1 2 3 | 48 // 252 253 254 255 0 1 2 3 |
54 // ################################################# | 49 // ################################################# |
55 // | | x | | | | | y | | | 50 // | | x | | | | | y | | |
56 // ################################################# | 51 // ################################################# |
57 // |----->----->----->----->-----> | 52 // |----->----->----->----->-----> |
58 // | 53 // |
59 // ForwardDiff(y, x) == 251 | 54 // ForwardDiff(y, x) == 251 |
60 // | 55 // |
61 // 252 253 254 255 0 1 2 3 | 56 // 252 253 254 255 0 1 2 3 |
62 // ################################################# | 57 // ################################################# |
63 // | | x | | | | | y | | | 58 // | | x | | | | | y | | |
64 // ################################################# | 59 // ################################################# |
65 // -->-----> |----->--- | 60 // -->-----> |----->--- |
66 // | 61 // |
62 template <typename T, T M> | |
torbjorng (webrtc)
2016/03/11 14:54:22
Do we want these functions to work for e.g., T=uin
philipel
2016/03/11 16:04:38
The other version is still available so you can do
| |
63 inline T ForwardDiff(T a, T b) { | |
64 static_assert(std::is_unsigned<T>::value, | |
65 "Type must be of unsigned integer."); | |
torbjorng (webrtc)
2016/03/11 14:54:22
Please make more idiomatic, e.g., "Type must be an
philipel
2016/03/11 16:04:38
Done.
| |
66 RTC_DCHECK_LT(a, M); | |
67 RTC_DCHECK_LT(b, M); | |
68 return a <= b ? b - a : M - (a - b); | |
69 } | |
70 | |
67 template <typename T> | 71 template <typename T> |
68 inline T ForwardDiff(T a, T b) { | 72 inline T ForwardDiff(T a, T b) { |
69 MOD_OPS_ASSERT_TYPE_IS_UNSIGNED(T); | 73 static_assert(std::is_unsigned<T>::value, |
74 "Type must be of unsigned integer."); | |
70 return b - a; | 75 return b - a; |
71 } | 76 } |
72 | 77 |
73 // Calculates the reverse difference between two numbers. | 78 // Calculates the reverse difference between two wrapping numbers. |
74 // | 79 // |
75 // Example: | 80 // Example: |
76 // uint8_t x = 253; | 81 // uint8_t x = 253; |
77 // uint8_t y = 2; | 82 // uint8_t y = 2; |
78 // | 83 // |
79 // ReverseDiff(y, x) == 5 | 84 // ReverseDiff(y, x) == 5 |
80 // | 85 // |
81 // 252 253 254 255 0 1 2 3 | 86 // 252 253 254 255 0 1 2 3 |
82 // ################################################# | 87 // ################################################# |
83 // | | x | | | | | y | | | 88 // | | x | | | | | y | | |
84 // ################################################# | 89 // ################################################# |
85 // <-----<-----<-----<-----<-----| | 90 // <-----<-----<-----<-----<-----| |
86 // | 91 // |
87 // ReverseDiff(x, y) == 251 | 92 // ReverseDiff(x, y) == 251 |
88 // | 93 // |
89 // 252 253 254 255 0 1 2 3 | 94 // 252 253 254 255 0 1 2 3 |
90 // ################################################# | 95 // ################################################# |
91 // | | x | | | | | y | | | 96 // | | x | | | | | y | | |
92 // ################################################# | 97 // ################################################# |
93 // ---<-----| |<-----<-- | 98 // ---<-----| |<-----<-- |
94 // | 99 // |
100 template <typename T, T M> | |
101 inline T ReverseDiff(T a, T b) { | |
102 static_assert(std::is_unsigned<T>::value, | |
103 "Type must be of unsigned integer."); | |
104 RTC_DCHECK_LT(a, M); | |
105 RTC_DCHECK_LT(b, M); | |
106 return b <= a ? a - b : M - (b - a); | |
107 } | |
108 | |
95 template <typename T> | 109 template <typename T> |
96 inline T ReverseDiff(T a, T b) { | 110 inline T ReverseDiff(T a, T b) { |
97 MOD_OPS_ASSERT_TYPE_IS_UNSIGNED(T); | 111 static_assert(std::is_unsigned<T>::value, |
112 "Type must be of unsigned integer."); | |
98 return a - b; | 113 return a - b; |
99 } | 114 } |
100 | 115 |
101 // Test if the sequence number a is ahead or at sequence number b. | 116 // Test if the sequence number a is ahead or at sequence number b. |
102 // If the two sequence numbers are at max distance from each other | 117 // If the two sequence numbers are at max distance from each other |
103 // then the sequence number with highest value is considered to | 118 // then the sequence number with highest value is considered to |
104 // be ahead. | 119 // be ahead. |
105 template <typename T> | 120 template <typename T> |
106 inline bool AheadOrAt(T a, T b) { | 121 inline bool AheadOrAt(T a, T b) { |
107 MOD_OPS_ASSERT_TYPE_IS_UNSIGNED(T); | 122 static_assert(std::is_unsigned<T>::value, |
123 "Type must be of unsigned integer."); | |
108 const T maxDist = std::numeric_limits<T>::max() / 2 + T(1); | 124 const T maxDist = std::numeric_limits<T>::max() / 2 + T(1); |
109 if (a - b == maxDist) | 125 if (a - b == maxDist) |
110 return b < a; | 126 return b < a; |
111 return ForwardDiff(b, a) < maxDist; | 127 return ForwardDiff(b, a) < maxDist; |
112 } | 128 } |
113 | 129 |
114 // Test if sequence number a is ahead of sequence number b. | 130 // Test if sequence number a is ahead of sequence number b. |
115 template <typename T> | 131 template <typename T> |
116 inline bool AheadOf(T a, T b) { | 132 inline bool AheadOf(T a, T b) { |
117 MOD_OPS_ASSERT_TYPE_IS_UNSIGNED(T); | 133 static_assert(std::is_unsigned<T>::value, |
134 "Type must be of unsigned integer."); | |
118 return a != b && AheadOrAt(a, b); | 135 return a != b && AheadOrAt(a, b); |
119 } | 136 } |
120 | 137 |
121 } // namespace webrtc | 138 } // namespace webrtc |
122 | 139 |
123 #endif // WEBRTC_BASE_MOD_OPS_H_ | 140 #endif // WEBRTC_BASE_MOD_OPS_H_ |
OLD | NEW |