Qx v0.5.8
Qt Extensions Library
Loading...
Searching...
No Matches
qx-algorithm.h
Go to the documentation of this file.
1#ifndef QX_ALGORITHM_H
2#define QX_ALGORITHM_H
3
4// Shared Lib Support
5#include "qx/core/qx_core_export.h"
6
7// Standard Library Includes
8#include <stdexcept>
9#include <unordered_set>
10
11// Qt Includes
12#include <QtGlobal>
13
14// Extra-component Includes
16
17namespace Qx
18{
19//-Namespace Functions----------------------------------------------------------------------------------------------------
20QX_CORE_EXPORT int abs(int n);
21QX_CORE_EXPORT unsigned int abs(unsigned int n);
22QX_CORE_EXPORT long abs(long n);
23QX_CORE_EXPORT unsigned long abs(unsigned long n);
24QX_CORE_EXPORT long long abs (long long n);
25QX_CORE_EXPORT unsigned long long abs(unsigned long long n);
26
27template<typename T>
28 requires std::integral<T>
29T length(T start, T end) { return (end - start) + 1; }
30
31template<typename T>
32 requires arithmetic<T>
33bool isOdd(T num) { return num % 2; }
34
35template<typename T>
36 requires arithmetic<T>
37bool isEven(T num) { return !isOdd(num); }
38
39template <class InputIt>
40 requires std::input_iterator<InputIt> && std::equality_comparable<InputIt>
41bool containsDuplicates(InputIt begin, InputIt end)
42{
43 // Get type that iterator is of
44 using T = typename std::iterator_traits<InputIt >::value_type;
45
46 // Place values into unordered set
47 std::unordered_set<T> values(begin, end);
48
49 // Count values in original container
50 std::size_t size = std::distance(begin,end);
51
52 // Container has duplicates if set size is smaller than the the original container,
53 // since sets don't allow for duplicates
54 return size != values.size();
55}
56
57template<typename T>
58 requires arithmetic<T>
59T distance(T x, T y) { return std::max(x,y) - std::min(x,y); }
60
61// Thanks to the following for all constrained arithmetic functions:
62// https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152052
63template <typename T>
64 requires std::signed_integral<T>
65T constrainedAdd(T a, T b, T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max())
66{
67 if((b >= 0) && (a > (max - b)))
68 return max; // Overflow
69 else if((b < 0) && (a < (min - b)))
70 return min; // Underflow
71 else
72 return a + b;
73}
74
75template <typename T>
76 requires std::unsigned_integral<T>
77T constrainedAdd(T a, T b, T max = std::numeric_limits<T>::max())
78{
79 if(max - a < b)
80 return max; // Overflow
81 else
82 return a + b;
83}
84
85template <typename T>
86 requires std::signed_integral<T>
87T constrainedSub(T a, T b, T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max())
88{
89 if(b >= 0 && a < min + b)
90 return min; // Underflow
91 else if(b < 0 && a > max + b)
92 return max; // Overflow
93 else
94 return a - b;
95}
96
97template <typename T>
98 requires std::unsigned_integral<T>
99T constrainedSub(T a, T b, T min = 0)
100{
101 if(a < b)
102 return min; // Underflow
103 else
104 return a - b;
105}
106
107template<typename T>
108 requires std::signed_integral<T>
109T constrainedMult(T a, T b, T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max())
110{
111 if(a > 0)
112 {
113 if(b > 0 && a > (max / b))
114 return max; // Overflow
115 else if(b < (min / a))
116 return min; // Underflow
117 }
118 else if(a < 0)
119 {
120 if(b > 0 && a < (min / b))
121 return min; // Underflow
122 else if(b < (max / a))
123 return max; // Overflow
124 }
125
126 return a * b;
127}
128
129template<typename T>
130 requires std::unsigned_integral<T>
131T constrainedMult(T a, T b, T max = std::numeric_limits<T>::max())
132{
133 if(a > max / b)
134 return max; // Overflow
135 else
136 return a * b;
137}
138
139template<typename T>
140 requires std::signed_integral<T>
141T constrainedDiv(T a, T b, T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max())
142{
143 if(b == 0)
144 qFatal("Divide by zero");
145
146 if((a == std::numeric_limits<T>::min()) && (b == -1))
147 return max; // True overflow
148 else
149 {
150 T result = a/b;
151
152 if(result > max)
153 return max; // Argument based overflow
154 else if(result < min)
155 return min; // Argument based underflow
156 else
157 return result;
158 }
159}
160
161template<typename T>
162 requires std::unsigned_integral<T>
163T constrainedDiv(T a, T b, T max = std::numeric_limits<T>::max())
164{
165 if(b == 0)
166 qFatal("Divide by zero");
167
168 T result = a/b;
169
170 if(result > max)
171 return max; // Argument based overflow
172 else
173 return result;
174}
175
176template<typename T>
177 requires std::integral<T>
178T ceilNearestMultiple(T num, T mult)
179{
180 // Ensure mult is positive
181 mult = Qx::abs(mult);
182
183 if(mult == 0)
184 return 0;
185
186 if(mult == 1 || mult == num)
187 return num;
188
189 if(num < 0)
190 return (num / mult) * mult;
191 else
192 {
193 T previousMultiple = (num / mult) * mult;
194 return previousMultiple == num ? num : constrainedAdd(previousMultiple, mult);
195 }
196}
197
198template<typename T>
199 requires std::integral<T>
200T floorNearestMultiple(T num, T mult)
201{
202 // Ensure mult is positive
203 mult = Qx::abs(mult);
204
205 if(mult == 0)
206 return 0;
207
208 if(mult == 1 || mult == num)
209 return num;
210
211 if(num > 0)
212 return (num / mult) * mult;
213 else
214 {
215 T nextMultiple = (num / mult) * mult;
216 return nextMultiple == num ? num : constrainedSub(nextMultiple, mult);
217 }
218}
219
220template<typename T>
221 requires std::integral<T>
223{
224 T above = ceilNearestMultiple(num, mult);
225 T below = floorNearestMultiple(num, mult);
226
227 // Return of closest the two directions
228 return above - num <= num - below ? above : below;
229}
230
231template <typename T>
232 requires std::integral<T>
234{
235 // Return if num already is power of 2
236 if (num && !(num & (num - 1)))
237 return num;
238
239 T powOfTwo = 1;
240
241 while(powOfTwo < num)
242 powOfTwo <<= 1;
243
244 return powOfTwo;
245}
246
247template <typename T>
248 requires std::integral<T>
250{
251 // Return if num already is power of 2
252 if (num && !(num & (num - 1)))
253 return num;
254
255 // Start with largest possible power of T type can hold
256 T powOfTwo = (std::numeric_limits<T>::max() >> 1) + 1;
257
258 while(powOfTwo > num)
259 powOfTwo >>= 1;
260
261 return powOfTwo;
262}
263
264template <typename T>
265 requires std::integral<T>
267{
268 T above = ceilPowOfTwo(num);
269 T below = floorPowOfTwo(num);
270
271 return above - num <= num - below ? above : below;
272}
273
274}
275
276#endif // QX_ALGORITHM_H
The Qx namespace is the main namespace through which all non-global functionality of the Qx library i...
Definition qx-processwaiter.cpp:5
bool isOdd(T num)
Definition qx-algorithm.h:33
T ceilPowOfTwo(T num)
Definition qx-algorithm.h:233
T constrainedAdd(T a, T b, T min=std::numeric_limits< T >::min(), T max=std::numeric_limits< T >::max())
Definition qx-algorithm.h:65
T floorNearestMultiple(T num, T mult)
Definition qx-algorithm.h:200
T constrainedDiv(T a, T b, T min=std::numeric_limits< T >::min(), T max=std::numeric_limits< T >::max())
Definition qx-algorithm.h:141
T roundPowOfTwo(T num)
Definition qx-algorithm.h:266
T constrainedSub(T a, T b, T min=std::numeric_limits< T >::min(), T max=std::numeric_limits< T >::max())
Definition qx-algorithm.h:87
T length(T start, T end)
Definition qx-algorithm.h:29
bool isEven(T num)
Definition qx-algorithm.h:37
T floorPowOfTwo(T num)
Definition qx-algorithm.h:249
bool containsDuplicates(InputIt begin, InputIt end)
Definition qx-algorithm.h:41
int abs(int n)
Definition qx-algorithm.cpp:20
T distance(T x, T y)
Definition qx-algorithm.h:59
T ceilNearestMultiple(T num, T mult)
Definition qx-algorithm.h:178
T constrainedMult(T a, T b, T min=std::numeric_limits< T >::min(), T max=std::numeric_limits< T >::max())
Definition qx-algorithm.h:109
T roundToNearestMultiple(T num, T mult)
Definition qx-algorithm.h:222
The qx-concepts header file provides a library of general purpose concepts as an extension of the sta...