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