blob: 9e649b75d21a78ff9de977167ed2cb0a3bf08253 [file] [log] [blame]
philipel5ab4c6d2016-03-08 03:36:15 -08001/*
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#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
24namespace webrtc {
25
26template <unsigned long M> // NOLINT
27inline unsigned long Add(unsigned long a, unsigned long b) { // NOLINT
28 RTC_DCHECK_LT(a, M);
29 unsigned long t = M - b % M; // NOLINT
30 unsigned long res = a - t; // NOLINT
31 if (t > a)
32 return res + M;
33 return res;
34}
35
36template <unsigned long M> // NOLINT
37inline unsigned long Subtract(unsigned long a, unsigned long b) { // NOLINT
38 RTC_DCHECK_LT(a, M);
39 unsigned long sub = b % M; // NOLINT
40 if (a < sub)
41 return M - (sub - a);
42 return a - sub;
43}
44
45// Calculates the forward difference between two numbers.
46//
47// Example:
48// uint8_t x = 253;
49// uint8_t y = 2;
50//
51// ForwardDiff(x, y) == 4
52//
53// 252 253 254 255 0 1 2 3
54// #################################################
55// | | x | | | | | y | |
56// #################################################
57// |----->----->----->----->----->
58//
59// ForwardDiff(y, x) == 251
60//
61// 252 253 254 255 0 1 2 3
62// #################################################
63// | | x | | | | | y | |
64// #################################################
65// -->-----> |----->---
66//
67template <typename T>
68inline T ForwardDiff(T a, T b) {
69 MOD_OPS_ASSERT_TYPE_IS_UNSIGNED(T);
70 return b - a;
71}
72
73// Calculates the reverse difference between two numbers.
74//
75// Example:
76// uint8_t x = 253;
77// uint8_t y = 2;
78//
79// ReverseDiff(y, x) == 5
80//
81// 252 253 254 255 0 1 2 3
82// #################################################
83// | | x | | | | | y | |
84// #################################################
85// <-----<-----<-----<-----<-----|
86//
87// ReverseDiff(x, y) == 251
88//
89// 252 253 254 255 0 1 2 3
90// #################################################
91// | | x | | | | | y | |
92// #################################################
93// ---<-----| |<-----<--
94//
95template <typename T>
96inline T ReverseDiff(T a, T b) {
97 MOD_OPS_ASSERT_TYPE_IS_UNSIGNED(T);
98 return a - b;
99}
100
101// 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
103// then the sequence number with highest value is considered to
104// be ahead.
105template <typename T>
106inline bool AheadOrAt(T a, T b) {
107 MOD_OPS_ASSERT_TYPE_IS_UNSIGNED(T);
108 const T maxDist = std::numeric_limits<T>::max() / 2 + T(1);
109 if (a - b == maxDist)
110 return b < a;
111 return ForwardDiff(b, a) < maxDist;
112}
113
114// Test if sequence number a is ahead of sequence number b.
115template <typename T>
116inline bool AheadOf(T a, T b) {
117 MOD_OPS_ASSERT_TYPE_IS_UNSIGNED(T);
118 return a != b && AheadOrAt(a, b);
119}
120
121} // namespace webrtc
122
123#endif // WEBRTC_BASE_MOD_OPS_H_