Ocean
Loading...
Searching...
No Matches
base/Utilities.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_BASE_UTILITIES_H
9#define META_OCEAN_BASE_UTILITIES_H
10
11#include "ocean/base/Base.h"
12
13#include <climits>
14#include <cmath>
15#include <limits>
16
17namespace Ocean
18{
19
20/**
21 * This class implements basic utility functions.
22 * @ingroup base
23 */
24class OCEAN_BASE_EXPORT Utilities
25{
26 public:
27
28 /**
29 * Separates a set of given values.
30 * @param values Set of values to be separated
31 * @param delimiter The delimiter separating the individual values
32 * @param removeQuotes State determining whether the beginning and ending quotes are removed for each value
33 * @param trim State determining whether prefix and postfix blanks are removed for each value
34 * @return Resulting separated values
35 */
36 static std::vector<std::string> separateValues(const std::string& values, const char delimiter = ',', const bool removeQuotes = true, const bool trim = true);
37
38 /**
39 * Sorts two values so that the lowest value will finally be the first value.
40 * The sorting is not stable.
41 * @param value0 First value
42 * @param value1 Second value
43 * @tparam T Data type of the values to be sorted
44 */
45 template <typename T>
46 static void sortLowestToFront2(T& value0, T& value1);
47
48 /**
49 * Sorts three values so that the lowest value will finally be the first value.
50 * The sorting is not stable.
51 * @param value0 First value
52 * @param value1 Second value
53 * @param value2 Third value
54 * @tparam T Data type of the values to be sorted
55 */
56 template <typename T>
57 static void sortLowestToFront3(T& value0, T& value1, T& value2);
58
59 /**
60 * Sorts two values so that the lowest value will finally be the first value.
61 * Each value has a connected data value that will be sorted accordingly.<br>
62 * The sorting is not stable.
63 * @param value0 First value
64 * @param value1 Second value
65 * @param data0 First data value
66 * @param data1 Second data value
67 * @tparam T Data type of the values to be sorted
68 */
69 template <typename T, typename TData>
70 static void sortLowestToFront2(T& value0, T& value1, TData& data0, TData& data1);
71
72 /**
73 * Sorts three values so that the lowest value will finally be the first value.
74 * Each value has a connected data value that will be sorted accordingly.<br>
75 * The sorting is not stable.
76 * @param value0 First value
77 * @param value1 Second value
78 * @param value2 Third value
79 * @param data0 First data value
80 * @param data1 Second data value
81 * @param data2 Third data value
82 * @tparam T Data type of the values to be sorted
83 */
84 template <typename T, typename TData>
85 static void sortLowestToFront3(T& value0, T& value1, T& value2, TData& data0, TData& data1, TData& data2);
86
87 /**
88 * Sorts two values so that the highest value will finally be the first value.
89 * The sorting is not stable.
90 * @param value0 First value
91 * @param value1 Second value
92 * @tparam T Data type of the values to be sorted
93 */
94 template <typename T>
95 static void sortHighestToFront2(T& value0, T& value1);
96
97 /**
98 * Sorts three values so that the highest value will finally be the first value.
99 * The sorting is not stable.
100 * @param value0 First value
101 * @param value1 Second value
102 * @param value2 Third value
103 * @tparam T Data type of the values to be sorted
104 */
105 template <typename T>
106 static void sortHighestToFront3(T& value0, T& value1, T& value2);
107
108 /**
109 * Sorts four values so that the highest value will finally be the first value.
110 * The sorting is not stable.
111 * @param value0 First value
112 * @param value1 Second value
113 * @param value2 Third value
114 * @param value3 Fourth value
115 * @tparam T Data type of the values to be sorted
116 */
117 template <typename T>
118 static void sortHighestToFront4(T& value0, T& value1, T& value2, T& value3);
119
120 /**
121 * Sorts two values so that the highest value will finally be the first value.
122 * Each value has a connected payload data value that will be sorted accordingly.<br>
123 * The sorting is not stable.
124 * @param value0 First value
125 * @param value1 Second value
126 * @param data0 First data value
127 * @param data1 Second data value
128 * @tparam T Data type of the values to be sorted
129 * @tparam TData Data type of the payload data value
130 */
131 template <typename T, typename TData>
132 static void sortHighestToFront2(T& value0, T& value1, TData& data0, TData& data1);
133
134 /**
135 * Sorts three values so that the highest value will finally be the first value.
136 * Each value has a connected payload data value that will be sorted accordingly.<br>
137 * The sorting is not stable.
138 * @param value0 First value
139 * @param value1 Second value
140 * @param value2 Third value
141 * @param data0 First data value
142 * @param data1 Second data value
143 * @param data2 Third data value
144 * @tparam T Data type of the values to be sorted
145 * @tparam TData Data type of the payload data value
146 */
147 template <typename T, typename TData>
148 static void sortHighestToFront3(T& value0, T& value1, T& value2, TData& data0, TData& data1, TData& data2);
149
150 /**
151 * Returns the index of the lowest value, if two or more values have the lowest value the smallest index of the values will be returned.
152 * @param value0 The first value
153 * @param value1 The second value
154 * @param value2 The third value
155 * @return The resulting index with range [0, 2]
156 */
157 template <typename T>
158 static unsigned int lowestValue(const T& value0, const T& value1, const T& value2);
159
160 /**
161 * Returns the index of the highest value, if two or more values have the highest value the smallest index of the values will be returned.
162 * @param value0 The first value
163 * @param value1 The second value
164 * @param value2 The third value
165 * @return The resulting index with range [0, 2]
166 */
167 template <typename T>
168 static unsigned int highestValue(const T& value0, const T& value1, const T& value2);
169
170 /**
171 * Compares two pair objects and returns whether the first value of the first pair is lesser than the first value of the second pair.
172 * @param firstPair First pair object
173 * @param secondPair Second pair object
174 * @return True, if so
175 * @tparam T1 The data type of the first value of the pair objects
176 * @tparam T2 The data type of the second value of the pair objects
177 */
178 template <typename T1, typename T2>
179 static inline bool sortPairFirst(const std::pair<T1, T2>& firstPair, const std::pair<T1, T2>& secondPair);
180
181 /**
182 * Compares two pair objects and returns whether the first value of the first pair is lesser than the first value of the second pair.
183 * @param firstPair First pair object
184 * @param secondPair Second pair object
185 * @return True, if so
186 * @tparam T The data type of the std::pair object
187 */
188 template <typename T>
189 static inline bool sortPairFirst(const T& firstPair, const T& secondPair);
190
191 /**
192 * Compares two pair objects and returns whether the second value of the first pair is lesser than the second value of the second pair.
193 * @param firstPair First pair object
194 * @param secondPair Second pair object
195 * @return True, if so
196 * @tparam T1 The data type of the first value of the pair objects
197 * @tparam T2 The data type of the second value of the pair objects
198 */
199 template <typename T1, typename T2>
200 static inline bool sortPairSecond(const std::pair<T1, T2>& firstPair, const std::pair<T1, T2>& secondPair);
201
202 /**
203 * Compares two pair objects and returns whether the second value of the first pair is lesser than the second value of the second pair.
204 * @param firstPair First pair object
205 * @param secondPair Second pair object
206 * @return True, if so
207 * @tparam T The data type of the std::pair object
208 */
209 template <typename T>
210 static inline bool sortPairSecond(const T& firstPair, const T& secondPair);
211
212 /**
213 * This function divides a given value by two.
214 * Integer values are divided by two (bit shifting is no applied), floating point values are multiplied by 0.5.
215 * @param value The value to be divided
216 * @tparam T The data type of the value
217 * @return The resulting value
218 */
219 template <typename T>
220 static inline T divideBy2(const T& value);
221
222 /**
223 * This function applies a fast division by 255 for unsigned integer values.
224 * @param value The value that will be divided by 255, with range [0, 65534]
225 * @return Divided unsigned integer value
226 */
227 static inline unsigned char divideBy255(const unsigned int value);
228
229 /**
230 * Returns whether a given value is a power of two.
231 * Zero is not a power of two value.
232 * @param value The value to be checked, with range [0, infinity)
233 * @return True, if so
234 */
235 static inline bool isPowerOfTwo(const unsigned int value);
236
237 /**
238 * Returns the smallest power of two value that is equal or larger than a given value.
239 * @param value The value for that the smallest power of two value is determined, with range [0, 0x80000000]
240 * @return Smallest power of two value that is equal or larger
241 */
242 static inline unsigned int smallestPowerOfTwo(const unsigned int value);
243
244 /**
245 * Multiplies the specified 64 bit integers and stores the 128 bit integer result in resultHigh (64 most significant bits) and resultLow (64 least significant bits).
246 * @param left The left operand
247 * @param right The right operand
248 * @param resultHigh Receives the 64 most significant bits of the 128 bit result
249 * @param resultLow Receives the 64 least significant bits of the 128 bit result
250 */
251 static void multiply64(const uint64_t left, const uint64_t right, uint64_t& resultHigh, uint64_t& resultLow);
252
253 /**
254 * Compares the product specified by the first two factors with the product specified by the last two factors.
255 * @param leftFactor1 First factor of left operand
256 * @param leftFactor2 Second factor of left operand
257 * @param rightFactor1 First factor of right operand
258 * @param rightFactor2 Second factor of right operand
259 * @return 1 if the left product is greater than the right product, -1 if it is less and 0 if both are equal.
260 */
261 static inline int compareProducts(const uint64_t leftFactor1, const uint64_t leftFactor2, const uint64_t rightFactor1, const uint64_t rightFactor2);
262};
263
264/**
265 * This function fits a given parameter into a specified value range.
266 * If the given parameter is lesser the lower boundary, the lower boundary value is returned.
267 * If the given parameter is higher the upper boundary, the upper boundary value is returned.
268 * @param lowerBoundary Lower boundary value, with range (-infinity, upperBoundary]
269 * @param value The value to be fitted
270 * @param upperBoundary Upper boundary value, with range [lowerBoundary, infinity)
271 * @return Value fitting into the given range
272 * @tparam T Data type of the values
273 * @ingroup base
274 */
275template <typename T>
276inline T minmax(const T& lowerBoundary, const T& value, const T& upperBoundary);
277
278/**
279 * Returns the modulo value of a given parameter within a ring allowing positive and negative parameters.
280 * The function provides a modulo result for a ring size of 5 as below:<br>
281 * <pre>
282 * Original: -7 -6 | -5 -4 -3 -2 -1 | 0 1 2 3 4 | 5 6 7 9 ...
283 * Result: 3 4 | 0 1 2 3 4 | 0 1 2 3 4 | 0 1 2 3 ...
284 * </pre>
285 * @param value Parameter to return the module value for
286 * @param ring The ring size, must be positive with range [1, infinity)
287 * @return Resulting modulo value
288 * @tparam T Data type of the values
289 * @ingroup base
290 */
291template <typename T>
292inline T modulo(const T& value, const T& ring);
293
294/**
295 * Returns the distance between two values inside defined ring.
296 * @param value0 First value inside the ring, with range [0, ring)
297 * @param value1 Second value inside the ring, with range [0, ring)
298 * @param ring The ring size, must be positive
299 * @return Resulting distance
300 * @tparam T Data type of the values
301 * @ingroup base
302 */
303template <typename T>
304inline T ringDistance(const T& value0, const T& value1, const T& ring);
305
306/**
307 * Returns the square value of a given value.
308 * @param value The value to be squared
309 * @return Squared value
310 * @ingroup base
311 */
312inline unsigned int sqr(const char value);
313
314/**
315 * Returns the square value of a given value.
316 * @param value The value to be squared
317 * @return Squared value
318 * @ingroup base
319 */
320inline unsigned int sqr(const unsigned char value);
321
322/**
323 * Returns the square value of a given value.
324 * @param value The value to be squared
325 * @return Squared value
326 * @ingroup base
327 */
328inline unsigned int sqr(const short value);
329
330/**
331 * Returns the square value of a given value.
332 * @param value The value to be squared
333 * @return Squared value
334 * @ingroup base
335 */
336inline unsigned int sqr(const unsigned short value);
337
338/**
339 * Returns the square value of a given value.
340 * @param value The value to be squared
341 * @return Squared value
342 * @ingroup base
343 */
344inline unsigned int sqr(const int value);
345
346/**
347 * Returns the square value of a given value.
348 * @param value The value to be squared
349 * @return Squared value
350 * @ingroup base
351 */
352inline unsigned int sqr(const unsigned int value);
353
354/**
355 * Returns the square value of a given value.
356 * @param value The value to be squared
357 * @return Squared value
358 * @ingroup base
359 */
360inline unsigned long sqr(const long value);
361
362/**
363 * Returns the square value of a given value.
364 * @param value The value to be squared
365 * @return Squared value
366 * @ingroup base
367 */
368inline unsigned long sqr(const unsigned long value);
369
370/**
371 * Returns the square value of a given value.
372 * @param value The value to be squared
373 * @return Squared value
374 * @ingroup base
375 */
376inline unsigned long long sqr(const long long value);
377
378/**
379 * Returns the square value of a given value.
380 * @param value The value to be squared
381 * @return Squared value
382 * @ingroup base
383 */
384inline unsigned long long sqr(const unsigned long long value);
385
386/**
387 * Returns the square value of a given value.
388 * @param value The value to be squared
389 * @return Squared value
390 * @ingroup base
391 */
392inline float sqr(const float value);
393
394/**
395 * Returns the square value of a given value.
396 * @param value The value to be squared
397 * @return Squared value
398 * @ingroup base
399 */
400inline double sqr(const double value);
401
402/**
403 * Returns the square distance between two values.
404 * @param first The first value
405 * @param second The second value
406 * @return Square distance
407 * @ingroup base
408 */
409inline unsigned int sqrDistance(const char first, const char second);
410
411/**
412 * Returns the square distance between two values.
413 * @param first The first value
414 * @param second The second value
415 * @return Square distance
416 * @ingroup base
417 */
418inline unsigned int sqrDistance(const unsigned char first, const unsigned char second);
419
420/**
421 * Returns the square distance between two values.
422 * @param first The first value
423 * @param second The second value
424 * @return Square distance
425 * @ingroup base
426 */
427inline unsigned int sqrDistance(const short first, const short second);
428
429/**
430 * Returns the square distance between two values.
431 * @param first The first value
432 * @param second The second value
433 * @return Square distance
434 * @ingroup base
435 */
436inline unsigned int sqrDistance(const unsigned short first, const unsigned short second);
437
438/**
439 * Returns the square distance between two values.
440 * @param first The first value
441 * @param second The second value
442 * @return Square distance
443 * @ingroup base
444 */
445inline unsigned int sqrDistance(const int first, const int second);
446
447/**
448 * Returns the square distance between two values.
449 * @param first The first value
450 * @param second The second value
451 * @return Square distance
452 * @ingroup base
453 */
454inline unsigned int sqrDistance(const unsigned int first, const unsigned int second);
455
456/**
457 * Returns the square distance between two values.
458 * @param first The first value
459 * @param second The second value
460 * @return Square distance
461 * @ingroup base
462 */
463inline unsigned long long sqrDistance(const long long first, const long long second);
464
465/**
466 * Returns the square distance between two values.
467 * @param first The first value
468 * @param second The second value
469 * @return Square distance
470 * @ingroup base
471 */
472inline unsigned long long sqrDistance(const unsigned long long first, const unsigned long long second);
473
474/**
475 * Returns the square distance between two values.
476 * @param first The first value
477 * @param second The second value
478 * @return Square distance
479 * @ingroup base
480 */
481inline float sqrDistance(const float first, const float second);
482
483/**
484 * Returns the square distance between two values.
485 * @param first The first value
486 * @param second The second value
487 * @return Square distance
488 * @ingroup base
489 */
490inline double sqrDistance(const double first, const double second);
491
492/**
493 * Returns the absolute distance between two values.
494 * @param first The first value
495 * @param second The second value
496 * @return Square distance
497 * @ingroup base
498 */
499inline unsigned char absDistance(const char first, const char second);
500
501/**
502 * Returns the absolute distance between two values.
503 * @param first The first value
504 * @param second The second value
505 * @return Square distance
506 * @ingroup base
507 */
508inline unsigned char absDistance(const unsigned char first, const unsigned char second);
509
510/**
511 * Returns the absolute distance between two values.
512 * @param first The first value
513 * @param second The second value
514 * @return Square distance
515 * @ingroup base
516 */
517inline unsigned short absDistance(const short first, const short second);
518
519/**
520 * Returns the absolute distance between two values.
521 * @param first The first value
522 * @param second The second value
523 * @return Square distance
524 * @ingroup base
525 */
526inline unsigned short absDistance(const unsigned short first, const unsigned short second);
527
528/**
529 * Returns the absolute distance between two values.
530 * @param first The first value
531 * @param second The second value
532 * @return Square distance
533 * @ingroup base
534 */
535inline unsigned int absDistance(const int first, const int second);
536
537/**
538 * Returns the absolute distance between two values.
539 * @param first The first value
540 * @param second The second value
541 * @return Square distance
542 * @ingroup base
543 */
544inline unsigned int absDistance(const unsigned int first, const unsigned int second);
545
546/**
547 * Returns the absolute distance between two values.
548 * @param first The first value
549 * @param second The second value
550 * @return Square distance
551 * @ingroup base
552 */
553inline unsigned long long absDistance(const long long first, const long long second);
554
555/**
556 * Returns the absolute distance between two values.
557 * @param first The first value
558 * @param second The second value
559 * @return Square distance
560 * @ingroup base
561 */
562inline unsigned long long absDistance(const unsigned long long first, const unsigned long long second);
563
564/**
565 * Mirrors a given value if necessary.
566 * The values is mirrored according to a given size parameter.<br>
567 * The function provides a result as below:<br>
568 * <pre>
569 * Original: -3 -2 -1 | 0 1 2 3 4 5 6 ... s-2 s-1 | s s+1 s+2
570 * Result: 2 1 0 | 0 1 2 3 4 5 6 ... s-2 s-1 | s-1 s-2 s-3
571 * </pre>
572 * @param value The value to be mirrored, with range [-size, 2*size]
573 * @param size Specified size defining the upper mirror border, with range [1, 2147483647]
574 * @return Mirrored value
575 * @ingroup base
576 */
577static inline unsigned int mirrorValue(const int value, const unsigned int size);
578
579/**
580 * Determines the entire number of elements that are stored in a vector holding a vector of elements.
581 * @param vectors Set of given vector
582 * @return Resulting entire number of elements
583 * @tparam T Data type of the vector elements
584 * @ingroup base
585 */
586template <typename T>
587static inline size_t countElements(const std::vector<std::vector<T>>& vectors);
588
589/**
590 * Returns whether a vector holds a specified element.
591 * @param elements Vector to be checked
592 * @param element The element that has to be found
593 * @return True, if so
594 */
595template <typename T>
596static inline bool hasElement(const std::vector<T>& elements, const T& element);
597
598/**
599 * Concatenates a given set of vectors to one vector.
600 * @param vectors Set of given vectors
601 * @return Resulting unique vector
602 * @tparam T Data type of the vector elements
603 * @ingroup base
604 */
605template <typename T>
606static inline std::vector<T> concatenate(const std::vector<std::vector<T>>& vectors);
607
608/**
609 * Fills a vector with increasing index values.
610 * @param numberIndices Number of indices that will be created, with range [1, infinity)
611 * @param startIndex Start index value, successive indices will be incremented, with range [0, infinity)
612 * @param indices The vector receiving the indices
613 * @tparam T Data type of the index elements
614 * @ingroup base
615 */
616template <typename T>
617static inline void createIndices(const size_t numberIndices, const T& startIndex, std::vector<T>& indices);
618
619/**
620 * Returns a vector with increasing index values.
621 * @param numberIndices Number of indices that will be created, with range [1, infinity)
622 * @param startIndex Start index value, successive indices will be incremented, with range [0, infinity)
623 * @return The resulting index vector
624 * @tparam T Data type of the index elements
625 * @ingroup base
626 */
627template <typename T>
628[[nodiscard]] static inline std::vector<T> createIndices(const size_t numberIndices, const T& startIndex);
629
630/**
631 * Helper struct allowing to determine a hash value for a std::pair.
632 * This struct can be used in combination with the std::unordered_map or std::unordered_set.
633 * @ingroup base
634 */
636{
637 /**
638 * Returns the hash value for a std::pair.
639 * @param pair The pair for which the hash value will be returned
640 * @return The resulting hash value
641 * @tparam T1 The data type of the first pair value
642 * @tparam T2 The data type of the second pair value
643 */
644 template <typename T1, typename T2>
645 std::size_t operator()(const std::pair<T1, T2>& pair) const
646 {
647 size_t seed = std::hash<T1>{}(pair.first);
648 seed ^= std::hash<T2>{}(pair.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
649
650 return seed;
651 }
652};
653
654template <typename T>
655void Utilities::sortLowestToFront2(T& value0, T& value1)
656{
657 if (!(value0 < value1))
658 {
659 std::swap(value0, value1);
660 }
661
662 ocean_assert(value0 <= value1);
663}
664
665template <typename T>
666void Utilities::sortLowestToFront3(T& value0, T& value1, T& value2)
667{
668 if (!(value0 < value1))
669 {
670 std::swap(value0, value1);
671 }
672
673 if (!(value0 < value2))
674 {
675 std::swap(value0, value2);
676 }
677
678 if (!(value1 < value2))
679 {
680 std::swap(value1, value2);
681 }
682
683 ocean_assert(value0 <= value1);
684 ocean_assert(value1 <= value2);
685}
686
687template <typename T, typename TData>
688void Utilities::sortLowestToFront2(T& value0, T& value1, TData& data0, TData& data1)
689{
690 if (!(value0 < value1))
691 {
692 std::swap(value0, value1);
693 std::swap(data0, data1);
694 }
695
696 ocean_assert(value0 <= value1);
697}
698
699template <typename T, typename TData>
700void Utilities::sortLowestToFront3(T& value0, T& value1, T& value2, TData& data0, TData& data1, TData& data2)
701{
702 if (!(value0 < value1))
703 {
704 std::swap(value0, value1);
705 std::swap(data0, data1);
706 }
707
708 if (!(value0 < value2))
709 {
710 std::swap(value0, value2);
711 std::swap(data0, data2);
712 }
713
714 if (!(value1 < value2))
715 {
716 std::swap(value1, value2);
717 std::swap(data1, data2);
718 }
719
720 ocean_assert(value0 <= value1);
721 ocean_assert(value1 <= value2);
722}
723
724template <typename T>
725void Utilities::sortHighestToFront2(T& value0, T& value1)
726{
727 if (value0 < value1)
728 {
729 std::swap(value0, value1);
730 }
731
732 ocean_assert(value0 >= value1);
733}
734
735template <typename T>
736void Utilities::sortHighestToFront3(T& value0, T& value1, T& value2)
737{
738 if (value0 < value1)
739 {
740 std::swap(value0, value1);
741 }
742
743 if (value0 < value2)
744 {
745 std::swap(value0, value2);
746 }
747
748 if (value1 < value2)
749 {
750 std::swap(value1, value2);
751 }
752
753 ocean_assert(value0 >= value1);
754 ocean_assert(value1 >= value2);
755}
756
757template <typename T>
758void Utilities::sortHighestToFront4(T& value0, T& value1, T& value2, T& value3)
759{
760 if (value0 < value1)
761 {
762 std::swap(value0, value1);
763 }
764
765 if (value2 < value3)
766 {
767 std::swap(value2, value3);
768 }
769
770 if (value0 < value2)
771 {
772 std::swap(value0, value2);
773 }
774
775 if (value1 < value3)
776 {
777 std::swap(value1, value3);
778 }
779
780 if (value1 < value2)
781 {
782 std::swap(value1, value2);
783 }
784
785 ocean_assert(value0 >= value1);
786 ocean_assert(value1 >= value2);
787 ocean_assert(value2 >= value3);
788}
789
790
791template <typename T, typename TData>
792void Utilities::sortHighestToFront2(T& value0, T& value1, TData& data0, TData& data1)
793{
794 if (value0 < value1)
795 {
796 std::swap(value0, value1);
797 std::swap(data0, data1);
798 }
799
800 ocean_assert(value0 >= value1);
801}
802
803template <typename T, typename TData>
804void Utilities::sortHighestToFront3(T& value0, T& value1, T& value2, TData& data0, TData& data1, TData& data2)
805{
806 if (value0 < value1)
807 {
808 std::swap(value0, value1);
809 std::swap(data0, data1);
810 }
811
812 if (value0 < value2)
813 {
814 std::swap(value0, value2);
815 std::swap(data0, data2);
816 }
817
818 if (value1 < value2)
819 {
820 std::swap(value1, value2);
821 std::swap(data1, data2);
822 }
823
824 ocean_assert(value0 >= value1);
825 ocean_assert(value1 >= value2);
826}
827
828template <typename T>
829unsigned int Utilities::lowestValue(const T& value0, const T& value1, const T& value2)
830{
831 if (value0 <= value1)
832 {
833 if (value0 <= value2)
834 {
835 return 0u;
836 }
837 else
838 {
839 return 2u;
840 }
841 }
842 else
843 {
844 if (value1 <= value2)
845 {
846 return 1u;
847 }
848 else
849 {
850 return 2u;
851 }
852 }
853}
854
855template <typename T>
856unsigned int Utilities::highestValue(const T& value0, const T& value1, const T& value2)
857{
858 if (value0 >= value1)
859 {
860 if (value0 >= value2)
861 {
862 return 0u;
863 }
864 else
865 {
866 return 2u;
867 }
868 }
869 else
870 {
871 if (value1 >= value2)
872 {
873 return 1u;
874 }
875 else
876 {
877 return 2u;
878 }
879 }
880}
881
882template <typename T1, typename T2>
883inline bool Utilities::sortPairFirst(const std::pair<T1, T2>& firstPair, const std::pair<T1, T2>& secondPair)
884{
885 return firstPair.first < secondPair.first;
886}
887
888template <typename T>
889inline bool Utilities::sortPairFirst(const T& firstPair, const T& secondPair)
890{
891 return firstPair.first < secondPair.first;
892}
893
894template <typename T1, typename T2>
895inline bool Utilities::sortPairSecond(const std::pair<T1, T2>& firstPair, const std::pair<T1, T2>& secondPair)
896{
897 return firstPair.second < secondPair.second;
898}
899
900template <typename T>
901inline bool Utilities::sortPairSecond(const T& firstPair, const T& secondPair)
902{
903 return firstPair.second < secondPair.second;
904}
905
906template <typename T>
907inline T Utilities::divideBy2(const T& value)
908{
909 return value / T(2);
910}
911
912template <>
913inline float Utilities::divideBy2(const float& value)
914{
915 return value * 0.5f;
916}
917
918template <>
919inline double Utilities::divideBy2(const double& value)
920{
921 return value * 0.5;
922}
923
924inline unsigned char Utilities::divideBy255(const unsigned int value)
925{
926 ocean_assert(value < 65535u);
927 ocean_assert(value / 255u == (value + 1u + (value >> 8u)) >> 8u);
928
929 return (unsigned char)((value + 1u + (value >> 8u)) >> 8u);
930}
931
932inline bool Utilities::isPowerOfTwo(const unsigned int value)
933{
934 // we determine/extract the least significant bit and check whether the value is still equal:
935 // value: 11010011000
936 // value-1: 11010010111
937 // ~(value-1): 00101101000
938 // value & ~(value-1): 00000001000
939
940 // return value != 0u && (value == (value & ~(value - 1u)));
941
942 // an even faster way is to check (for all values larger than zero):
943 // (value & (value - 1u)) == 0
944
945 ocean_assert((value == 1u || value == 2u || value == 4u || value == 8u || value == 16u || value == 32u || value == 64u
946 || value == 128u || value == 256u || value == 512u || value == 1024u || value == 2048u
947 || value == 4096u || value == 8192 || value == 16384u || value == 32768u || value == 65536u
948 || value == 131072 || value == 262144u || value == 524288u || value == 1048576u || value == 2097152u
949 || value == 4194304u || value == 8388608u || value == 16777216u || value == 33554432u || value == 67108864u
950 || value == 134217728u || value == 268435456u || value == 536870912u || value == 1073741824u || value == 2147483648u) == (value != 0u && (value & (value - 1u)) == 0u));
951
952 return value != 0u && (value & (value - 1u)) == 0u;
953}
954
955inline unsigned int Utilities::smallestPowerOfTwo(const unsigned int value)
956{
957 ocean_assert(value <= 0x80000000u);
958
959 unsigned int powerOfTwoValue = 0x80000000u;
960
961 while (powerOfTwoValue != 0u && (powerOfTwoValue >> 1) >= value)
962 {
963 powerOfTwoValue >>= 1u;
964 }
965
966 return powerOfTwoValue;
967}
968
969#ifdef __GNUC__
970
971// The GCC compiler provides faster code with this minmax determination
972template <typename T>
973inline T minmax(const T& lowerBoundary, const T& value, const T& upperBoundary)
974{
975 ocean_assert(lowerBoundary <= upperBoundary);
976
977 ocean_assert((value < lowerBoundary ? lowerBoundary : (value > upperBoundary ? upperBoundary : value)) == (max(lowerBoundary, min(value, upperBoundary))));
978 return value < lowerBoundary ? lowerBoundary : (value > upperBoundary ? upperBoundary : value);
979}
980
981#else
982
983// The Microsoft VC compiler provides faster code with this minmax determination
984template <typename T>
985inline T minmax(const T& lowerBoundary, const T& value, const T& upperBoundary)
986{
987 ocean_assert(lowerBoundary <= upperBoundary);
988 return max(lowerBoundary, min(upperBoundary, value));
989}
990
991#endif // __GNUC__
992
993template <typename T>
994inline T modulo(const T& value, const T& ring)
995{
996 ocean_assert(ring > 0);
997
998 if (value >= 0)
999 {
1000 if (value < ring)
1001 {
1002 return value;
1003 }
1004
1005 ocean_assert(value % ring < ring);
1006 return value % ring;
1007 }
1008 else
1009 {
1010 const T result = (ring - 1) - (-(value + 1) % ring);
1011 ocean_assert(result >= 0 && result < ring);
1012
1013 return result;
1014 }
1015}
1016
1017template <>
1018inline unsigned char modulo(const unsigned char& value, const unsigned char& ring)
1019{
1020 return value % ring;
1021}
1022
1023template <>
1024inline unsigned short modulo(const unsigned short& value, const unsigned short& ring)
1025{
1026 return value % ring;
1027}
1028
1029template <>
1030inline unsigned int modulo(const unsigned int& value, const unsigned int& ring)
1031{
1032 return value % ring;
1033}
1034
1035template <>
1036inline unsigned long long modulo(const unsigned long long& value, const unsigned long long& ring)
1037{
1038 return value % ring;
1039}
1040
1041template <>
1042inline double modulo(const double& value, const double& ring)
1043{
1044 ocean_assert(ring > 0);
1045
1046 if (value >= 0)
1047 {
1048 if (value < ring)
1049 {
1050 return value;
1051 }
1052
1053 return fmod(value, ring);
1054 }
1055 else
1056 {
1057 const double intermediate = ring - (fmod(-value, ring));
1058 ocean_assert(intermediate >= 0.0 && intermediate <= ring);
1059
1060 return intermediate == ring ? 0.0 : intermediate;
1061 }
1062}
1063
1064template <>
1065inline float modulo(const float& value, const float& ring)
1066{
1067 ocean_assert(ring > 0);
1068
1069 if (value >= 0)
1070 {
1071 if (value < ring)
1072 {
1073 return value;
1074 }
1075
1076 return fmod(value, ring);
1077 }
1078 else
1079 {
1080 const float intermediate = ring - (fmod(-value, ring));
1081 ocean_assert(intermediate >= 0.0f && intermediate <= ring);
1082
1083 return intermediate == ring ? 0.0f : intermediate;
1084 }
1085}
1086
1087template <typename T>
1088inline T ringDistance(const T& value0, const T& value1, const T& ring)
1089{
1090 ocean_assert(value0 >= 0 && value0 < ring);
1091 ocean_assert(value1 >= 0 && value1 < ring);
1092
1093 const T low = min(value0, value1);
1094 const T high = max(value0, value1);
1095
1096 return min(high - low, low + ring - high);
1097}
1098
1099inline unsigned int sqr(const char value)
1100{
1101 return value * value;
1102}
1103
1104inline unsigned int sqr(const unsigned char value)
1105{
1106 return value * value;
1107}
1108
1109inline unsigned int sqr(const short value)
1110{
1111 return value * value;
1112}
1113
1114inline unsigned int sqr(const unsigned short value)
1115{
1116 return value * value;
1117}
1118
1119inline unsigned int sqr(const int value)
1120{
1121 return value * value;
1122}
1123
1124inline unsigned int sqr(const unsigned int value)
1125{
1126 return value * value;
1127}
1128
1129inline unsigned long sqr(const long value)
1130{
1131 return value * value;
1132}
1133
1134inline unsigned long sqr(const unsigned long value)
1135{
1136 return value * value;
1137}
1138
1139inline unsigned long long sqr(const long long value)
1140{
1141 return value * value;
1142}
1143
1144inline unsigned long long sqr(const unsigned long long value)
1145{
1146 return value * value;
1147}
1148
1149inline float sqr(const float value)
1150{
1151 return value * value;
1152}
1153
1154inline double sqr(const double value)
1155{
1156 return value * value;
1157}
1158
1159inline unsigned int sqrDistance(const char first, const char second)
1160{
1161 const int distance = int(first) - int(second);
1162 return distance * distance;
1163}
1164
1165inline unsigned int sqrDistance(const unsigned char first, const unsigned char second)
1166{
1167 const int distance = int(first) - int(second);
1168 return distance * distance;
1169}
1170
1171inline unsigned int sqrDistance(const short first, const short second)
1172{
1173 const int distance = int(first) - int(second);
1174 return distance * distance;
1175}
1176
1177inline unsigned int sqrDistance(const unsigned short first, const unsigned short second)
1178{
1179 const int distance = int(first) - int(second);
1180 return distance * distance;
1181}
1182
1183inline unsigned int sqrDistance(const int first, const int second)
1184{
1185 const int distance = first - second;
1186 return distance * distance;
1187}
1188
1189inline unsigned int sqrDistance(const unsigned int first, const unsigned int second)
1190{
1191 ocean_assert(first <= (unsigned int)INT_MAX);
1192 ocean_assert(second <= (unsigned int)INT_MAX);
1193
1194 const int distance = int(first) - int(second);
1195 return distance * distance;
1196}
1197
1198inline unsigned long long sqrDistance(const long long first, const long long second)
1199{
1200 const long long distance = first - second;
1201 return distance * distance;
1202}
1203
1204inline unsigned long long sqrDistance(const unsigned long long first, const unsigned long long second)
1205{
1206 ocean_assert(first <= (unsigned long long)LLONG_MAX);
1207 ocean_assert(second <= (unsigned long long)LLONG_MAX);
1208
1209 const long long distance = (long long)first - (long long)second;
1210 return distance * distance;
1211}
1212
1213inline float sqrDistance(const float first, const float second)
1214{
1215 const float distance = first - second;
1216 return distance * distance;
1217}
1218
1219inline double sqrDistance(const double first, const double second)
1220{
1221 const double distance = first - second;
1222 return distance * distance;
1223}
1224
1225inline unsigned char absDistance(const char first, const char second)
1226{
1227 return (unsigned char)(::abs(int(first) - int(second)));
1228}
1229
1230inline unsigned char absDistance(const unsigned char first, const unsigned char second)
1231{
1232 return (unsigned char)(::abs(int(first - second)));
1233}
1234
1235inline unsigned short absDistance(const short first, const short second)
1236{
1237 return (unsigned short)(::abs(int(first) - int(second)));
1238}
1239
1240inline unsigned short absDistance(const unsigned short first, const unsigned short second)
1241{
1242 return (unsigned short)(::abs(int(first - second)));
1243}
1244
1245inline unsigned int absDistance(const int first, const int second)
1246{
1247 return (unsigned int)(::abs(first - second));
1248}
1249
1250inline unsigned int absDistance(const unsigned int first, const unsigned int second)
1251{
1252 return (unsigned int)(::abs(int(first - second)));
1253}
1254
1255inline unsigned long long absDistance(const long long first, const long long second)
1256{
1257#if defined(__clang__)
1258 return (first > second) ? (first - second) : (second - first);
1259#elif (defined(OCEAN_COMPILER_MSC) && OCEAN_MSC_VERSION <= 1500)
1260 return (first > second) ? (first - second) : (second - first);
1261#else
1262 return ::abs(first - second);
1263#endif
1264}
1265
1266inline unsigned long long absDistance(const unsigned long long first, const unsigned long long second)
1267{
1268#if defined(__clang__)
1269 return (first > second) ? (first - second) : (second - first);
1270#elif (defined(OCEAN_COMPILER_MSC) && OCEAN_MSC_VERSION <= 1500)
1271 return (first > second) ? (first - second) : (second - first);
1272#else
1273 return ::abs((long long)(first - second));
1274#endif
1275}
1276
1277inline unsigned int mirrorValue(const int value, const unsigned int size)
1278{
1279 ocean_assert(size != 0u);
1280 ocean_assert(size <= 2147483647);
1281 ocean_assert(value >= -int(size) && value <= int(size * 2));
1282
1283#ifdef OCEAN_DEBUG
1284 const int result = (value < 0) ? (-value - 1) : (value >= int(size) ? (int(size + size) - value - 1) : value);
1285 ocean_assert(result >= 0 && result < int(size));
1286#endif // OCEAN_DEBUG
1287
1288 return (value < 0) ? (-value - 1) : (value >= int(size) ? (int(size + size) - value - 1) : value);
1289}
1290
1291template <typename T>
1292inline size_t countElements(const std::vector<std::vector<T>>& vectors)
1293{
1294 size_t size = 0;
1295
1296 for (size_t n = 0; n < vectors.size(); ++n)
1297 {
1298 size += vectors[n].size();
1299 }
1300
1301 return size;
1302}
1303
1304template <typename T>
1305inline bool hasElement(const std::vector<T>& elements, const T& element)
1306{
1307 for (const T& value : elements)
1308 {
1309 if (value == element)
1310 {
1311 return true;
1312 }
1313 }
1314
1315 return false;
1316}
1317
1318template <typename T>
1319inline std::vector<T> concatenate(const std::vector<std::vector<T>>& vectors)
1320{
1321 const size_t size = countElements(vectors);
1322
1323 std::vector<T> result;
1324 result.reserve(size);
1325
1326 for (size_t n = 0; n < vectors.size(); ++n)
1327 {
1328 result.insert(result.end(), vectors[n].begin(), vectors[n].end());
1329 }
1330
1331 return result;
1332}
1333
1334template <typename T>
1335inline void createIndices(const size_t numberIndices, const T& startIndex, std::vector<T>& indices)
1336{
1337 ocean_assert(numberIndices > 0);
1338
1339 indices.reserve(numberIndices);
1340 indices.clear();
1341
1342 T index = startIndex;
1343
1344 for (size_t n = 0; n < numberIndices; ++n)
1345 {
1346 indices.emplace_back(index++);
1347 }
1348}
1349
1350template <typename T>
1351inline std::vector<T> createIndices(const size_t numberIndices, const T& startIndex)
1352{
1353 std::vector<T> result;
1354 createIndices(numberIndices, startIndex, result);
1355
1356 return result;
1357}
1358
1359int Utilities::compareProducts(const uint64_t leftFactor1, const uint64_t leftFactor2, const uint64_t rightFactor1, const uint64_t rightFactor2)
1360{
1361 uint64_t leftProductHigh, leftProductLow;
1362 multiply64(leftFactor1, leftFactor2, leftProductHigh, leftProductLow);
1363
1364 uint64_t rightProductHigh, rightProductLow;
1365 multiply64(rightFactor1, rightFactor2, rightProductHigh, rightProductLow);
1366
1367 return leftProductHigh == rightProductHigh ? (leftProductLow > rightProductLow) - (leftProductLow < rightProductLow) : (leftProductHigh > rightProductHigh) - (leftProductHigh < rightProductHigh);
1368}
1369
1370
1371}
1372
1373#endif // META_OCEAN_BASE_UTILITIES_H
This class implements basic utility functions.
Definition base/Utilities.h:25
static bool sortPairSecond(const std::pair< T1, T2 > &firstPair, const std::pair< T1, T2 > &secondPair)
Compares two pair objects and returns whether the second value of the first pair is lesser than the s...
Definition base/Utilities.h:895
static void sortLowestToFront2(T &value0, T &value1)
Sorts two values so that the lowest value will finally be the first value.
Definition base/Utilities.h:655
static unsigned int smallestPowerOfTwo(const unsigned int value)
Returns the smallest power of two value that is equal or larger than a given value.
Definition base/Utilities.h:955
static std::vector< std::string > separateValues(const std::string &values, const char delimiter=',', const bool removeQuotes=true, const bool trim=true)
Separates a set of given values.
static void sortHighestToFront4(T &value0, T &value1, T &value2, T &value3)
Sorts four values so that the highest value will finally be the first value.
Definition base/Utilities.h:758
static bool isPowerOfTwo(const unsigned int value)
Returns whether a given value is a power of two.
Definition base/Utilities.h:932
static unsigned int highestValue(const T &value0, const T &value1, const T &value2)
Returns the index of the highest value, if two or more values have the highest value the smallest ind...
Definition base/Utilities.h:856
static T divideBy2(const T &value)
This function divides a given value by two.
Definition base/Utilities.h:907
static int compareProducts(const uint64_t leftFactor1, const uint64_t leftFactor2, const uint64_t rightFactor1, const uint64_t rightFactor2)
Compares the product specified by the first two factors with the product specified by the last two fa...
Definition base/Utilities.h:1359
static unsigned char divideBy255(const unsigned int value)
This function applies a fast division by 255 for unsigned integer values.
Definition base/Utilities.h:924
static unsigned int lowestValue(const T &value0, const T &value1, const T &value2)
Returns the index of the lowest value, if two or more values have the lowest value the smallest index...
Definition base/Utilities.h:829
static void sortLowestToFront3(T &value0, T &value1, T &value2)
Sorts three values so that the lowest value will finally be the first value.
Definition base/Utilities.h:666
static void sortHighestToFront3(T &value0, T &value1, T &value2)
Sorts three values so that the highest value will finally be the first value.
Definition base/Utilities.h:736
static bool sortPairFirst(const std::pair< T1, T2 > &firstPair, const std::pair< T1, T2 > &secondPair)
Compares two pair objects and returns whether the first value of the first pair is lesser than the fi...
Definition base/Utilities.h:883
static void sortHighestToFront2(T &value0, T &value1)
Sorts two values so that the highest value will finally be the first value.
Definition base/Utilities.h:725
static void multiply64(const uint64_t left, const uint64_t right, uint64_t &resultHigh, uint64_t &resultLow)
Multiplies the specified 64 bit integers and stores the 128 bit integer result in resultHigh (64 most...
T minmax(const T &lowerBoundary, const T &value, const T &upperBoundary)
This function fits a given parameter into a specified value range.
Definition base/Utilities.h:973
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition base/Utilities.h:1159
static std::vector< T > concatenate(const std::vector< std::vector< T > > &vectors)
Concatenates a given set of vectors to one vector.
Definition base/Utilities.h:1319
unsigned char absDistance(const char first, const char second)
Returns the absolute distance between two values.
Definition base/Utilities.h:1225
static void createIndices(const size_t numberIndices, const T &startIndex, std::vector< T > &indices)
Fills a vector with increasing index values.
Definition base/Utilities.h:1335
T modulo(const T &value, const T &ring)
Returns the modulo value of a given parameter within a ring allowing positive and negative parameters...
Definition base/Utilities.h:994
static size_t countElements(const std::vector< std::vector< T > > &vectors)
Determines the entire number of elements that are stored in a vector holding a vector of elements.
Definition base/Utilities.h:1292
T ringDistance(const T &value0, const T &value1, const T &ring)
Returns the distance between two values inside defined ring.
Definition base/Utilities.h:1088
unsigned int sqr(const char value)
Returns the square value of a given value.
Definition base/Utilities.h:1099
static unsigned int mirrorValue(const int value, const unsigned int size)
Mirrors a given value if necessary.
Definition base/Utilities.h:1277
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
static bool hasElement(const std::vector< T > &elements, const T &element)
Returns whether a vector holds a specified element.
Definition base/Utilities.h:1305
Helper struct allowing to determine a hash value for a std::pair.
Definition base/Utilities.h:636
std::size_t operator()(const std::pair< T1, T2 > &pair) const
Returns the hash value for a std::pair.
Definition base/Utilities.h:645