nCine 2025.06.r503-ff15d8d
A cross-platform 2D game engine
Loading...
Searching...
No Matches
algorithms.h
1#ifndef NCTL_ALGORITHMS
2#define NCTL_ALGORITHMS
3
4#include <cmath>
5#include "iterator.h"
6#include "utility.h"
7
8namespace nctl {
9
11// TEMPLATE FUNCTIONS (non modifying)
13
15template <class T>
16inline const T &min(const T &a, const T &b)
17{
18 return !(b < a) ? a : b;
19}
20
22template <class T>
23inline const T &max(const T &a, const T &b)
24{
25 return (a < b) ? b : a;
26}
27
29template <class T>
30inline const T &clamp(const T &value, const T &minValue, const T &maxValue)
31{
32 return min(max(value, minValue), maxValue);
33}
34
36// UNARY PREDICATES
38
40template <class T>
42{
43 public:
44 explicit IsEqualTo(T refValue)
45 : refValue_(refValue) {}
46 inline bool operator()(T value) const { return value == refValue_; }
47
48 private:
49 T refValue_;
50};
51
53template <class T>
55{
56 public:
57 explicit IsNotEqualTo(T refValue)
58 : refValue_(refValue) {}
59 inline bool operator()(T value) const { return !(value == refValue_); }
60
61 private:
62 T refValue_;
63};
64
66template <class T>
68{
69 public:
70 explicit IsGreaterThan(T refValue)
71 : refValue_(refValue) {}
72 inline bool operator()(T value) const { return value > refValue_; }
73
74 private:
75 T refValue_;
76};
77
79template <class T>
81{
82 public:
83 explicit IsNotGreaterThan(T refValue)
84 : refValue_(refValue) {}
85 inline bool operator()(T value) const { return !(value > refValue_); }
86
87 private:
88 T refValue_;
89};
90
92template <class T>
94{
95 public:
96 explicit IsLessThan(T refValue)
97 : refValue_(refValue) {}
98 inline bool operator()(T value) const { return value < refValue_; }
99
100 private:
101 T refValue_;
102};
103
105template <class T>
107{
108 public:
109 explicit IsNotLessThan(T refValue)
110 : refValue_(refValue) {}
111 inline bool operator()(T value) const { return !(value < refValue_); }
112
113 private:
114 T refValue_;
115};
116
118// BINARY PREDICATES
120
121template <class T>
122inline bool IsEqual(const T &a, const T &b)
123{
124 return a == b;
125}
126
127template <class T>
128inline bool IsNotEqual(const T &a, const T &b)
129{
130 return !(a == b);
131}
132
133template <class T>
134inline bool IsGreater(const T &a, const T &b)
135{
136 return a > b;
137}
138
139template <class T>
140inline bool IsNotGreater(const T &a, const T &b)
141{
142 return !(a > b);
143}
144
145template <class T>
146inline bool IsLess(const T &a, const T &b)
147{
148 return a < b;
149}
150
151template <class T>
152inline bool IsNotLess(const T &a, const T &b)
153{
154 return !(a < b);
155}
156
158// ARITHMETIC OPERATIONS
160
161template <class T>
162inline T Plus(const T &a, const T &b)
163{
164 return a + b;
165}
166
167template <class T>
168inline T Minus(const T &a, const T &b)
169{
170 return a - b;
171}
172
173template <class T>
174inline T Multiplies(const T &a, const T &b)
175{
176 return a * b;
177}
178
179template <class T>
180inline T Divides(const T &a, const T &b)
181{
182 return a / b;
183}
184
185template <class T>
186inline T Modulus(const T &a, const T &b)
187{
188 return a % b;
189}
190
191template <class T>
192inline T Negate(const T &a)
193{
194 return -a;
195}
196
198// LOGICAL OPERATIONS
200
201template <class T>
202inline T LogicalAnd(const T &a, const T &b)
203{
204 return a && b;
205}
206
207template <class T>
208inline T LogicalOr(const T &a, const T &b)
209{
210 return a || b;
211}
212
213template <class T>
214inline T LogicalNot(const T &a)
215{
216 return !a;
217}
218
220// TEMPLATE FUNCTIONS WITH ITERATORS (non-modifying)
222
224template <class Iterator, class UnaryPredicate>
225inline bool allOf(Iterator first, const Iterator last, UnaryPredicate pred)
226{
227 for (; first != last; ++first)
228 {
229 if (!pred(*first))
230 return false;
231 }
232
233 return true;
234}
235
237template <class Iterator, class UnaryPredicate>
238inline bool noneOf(Iterator first, const Iterator last, UnaryPredicate pred)
239{
240 for (; first != last; ++first)
241 {
242 if (pred(*first))
243 return false;
244 }
245
246 return true;
247}
248
250template <class Iterator, class UnaryPredicate>
251inline bool anyOf(Iterator first, const Iterator last, UnaryPredicate pred)
252{
253 for (; first != last; ++first)
254 {
255 if (pred(*first))
256 return true;
257 }
258
259 return false;
260}
261
263template <class Iterator, class Function>
264inline Function forEach(Iterator first, const Iterator last, Function fn)
265{
266 for (; first != last; ++first)
267 fn(*first);
268
269 return fn;
270}
271
273template <class Iterator, class T>
274inline Iterator find(Iterator first, const Iterator last, const T &value)
275{
276 for (; first != last; ++first)
277 {
278 if (*first == value)
279 return first;
280 }
281
282 return last;
283}
284
286template <class Iterator, class UnaryPredicate>
287inline Iterator findIf(Iterator first, const Iterator last, UnaryPredicate pred)
288{
289 for (; first != last; ++first)
290 {
291 if (pred(*first))
292 return first;
293 }
294
295 return last;
296}
297
299template <class Iterator, class UnaryPredicate>
300inline Iterator findIfNot(Iterator first, const Iterator last, UnaryPredicate pred)
301{
302 for (; first != last; ++first)
303 {
304 if (!pred(*first))
305 return first;
306 }
307
308 return last;
309}
310
312template <class Iterator, class T>
313inline int count(Iterator first, const Iterator last, const T &value)
314{
315 int counter = 0;
316
317 for (; first != last; ++first)
318 {
319 if (*first == value)
320 counter++;
321 }
322
323 return counter;
324}
325
327template <class Iterator, class UnaryPredicate>
328inline int countIf(Iterator first, const Iterator last, UnaryPredicate pred)
329{
330 int counter = 0;
331
332 for (; first != last; ++first)
333 {
334 if (pred(*first))
335 counter++;
336 }
337
338 return counter;
339}
340
342template <class Iterator1, class Iterator2>
343inline bool equal(Iterator1 first1, const Iterator1 last1, Iterator2 first2)
344{
345 while (first1 != last1)
346 {
347 if (*first1 != *first2)
348 return false;
349 ++first1;
350 ++first2;
351 }
352
353 return true;
354}
355
357template <class Iterator>
358inline Iterator minElement(Iterator first, const Iterator last)
359{
360 if (first == last)
361 return last;
362
363 Iterator smallest = first;
364 ++first;
365
366 for (; first != last; ++first)
367 {
368 if (*first < *smallest)
369 smallest = first;
370 }
371
372 return smallest;
373}
374
376template <class Iterator>
377inline Iterator maxElement(Iterator first, const Iterator last)
378{
379 if (first == last)
380 return last;
381
382 Iterator largest = first;
383 ++first;
384
385 for (; first != last; ++first)
386 {
387 if (*first > *largest)
388 largest = first;
389 }
390
391 return largest;
392}
393
395template <class Iterator, class T>
396inline void clampElements(Iterator first, const Iterator last, const T &minValue, const T &maxValue)
397{
398 for (; first != last; ++first)
399 *first = min(max(*first, minValue), maxValue);
400}
401
403// TEMPLATE FUNCTIONS WITH ITERATORS (modifying)
405
406template <class Iterator1, class Iterator2>
407inline void iterSwap(Iterator1 a, Iterator2 b)
408{
409 swap(*a, *b);
410}
411
413template <class IteratorIn, class IteratorOut>
414inline IteratorOut copy(IteratorIn first, const IteratorIn last, IteratorOut result)
415{
416 while (first != last)
417 {
418 *result = *first;
419 ++result;
420 ++first;
421 }
422
423 return result;
424}
425
427template <class IteratorIn, class IteratorOut>
428inline IteratorOut copyN(IteratorIn first, unsigned int n, IteratorOut result)
429{
430 while (n > 0)
431 {
432 *result = *first;
433 ++result;
434 ++first;
435 --n;
436 }
437
438 return result;
439}
440
442template <class IteratorIn, class IteratorOut, class UnaryPredicate>
443inline IteratorOut copyIf(IteratorIn first, const IteratorIn last, IteratorOut result, UnaryPredicate pred)
444{
445 while (first != last)
446 {
447 if (pred(*first))
448 {
449 *result = *first;
450 ++result;
451 }
452 ++first;
453 }
454
455 return result;
456}
457
459template <class IteratorIn, class IteratorOut, class UnaryOperation>
460inline IteratorOut transform(IteratorIn first1, const IteratorIn last1, IteratorOut result, UnaryOperation op)
461{
462 while (first1 != last1)
463 {
464 *result = op(*first1);
465 ++result;
466 ++first1;
467 }
468
469 return result;
470}
471
473template <class IteratorIn1, class IteratorIn2, class IteratorOut, class BinaryOperation>
474inline IteratorOut transform(IteratorIn1 first1, const IteratorIn1 last1, IteratorIn2 first2,
475 IteratorOut result, BinaryOperation binaryOp)
476{
477 while (first1 != last1)
478 {
479 *result = binaryOp(*first1, *first2++);
480 ++result;
481 ++first1;
482 }
483
484 return result;
485}
486
488template <class Iterator, class T>
489inline void replace(Iterator first, const Iterator last, const T &oldValue, const T &newValue)
490{
491 while (first != last)
492 {
493 if (*first == oldValue)
494 *first = newValue;
495 ++first;
496 }
497}
498
500template <class Iterator, class UnaryPredicate, class T>
501inline void replaceIf(Iterator first, const Iterator last, UnaryPredicate pred, const T &newValue)
502{
503 while (first != last)
504 {
505 if (pred(*first))
506 *first = newValue;
507 ++first;
508 }
509}
510
512template <class IteratorIn, class IteratorOut, class T>
513inline IteratorOut replaceCopy(IteratorIn first, const IteratorIn last, IteratorOut result, const T &oldValue, const T &newValue)
514{
515 while (first != last)
516 {
517 *result = (*first == oldValue) ? newValue : *first;
518 ++first;
519 ++result;
520 }
521
522 return result;
523}
524
526template <class IteratorIn, class IteratorOut, class UnaryPredicate, class T>
527inline IteratorOut replaceCopyIf(IteratorIn first, const IteratorIn last, IteratorOut result, UnaryPredicate pred, const T &newValue)
528{
529 while (first != last)
530 {
531 *result = (pred(*first)) ? newValue : *first;
532 ++first;
533 ++result;
534 }
535
536 return result;
537}
538
540template <class Iterator, class T>
541inline void fill(Iterator first, const Iterator last, const T &value)
542{
543 for (; first != last; ++first)
544 *first = value;
545}
546
548template <class Iterator, class T>
549inline void fillN(Iterator first, unsigned int n, const T &value)
550{
551 for (unsigned int i = 0; i < n; i++, ++first)
552 *first = value;
553}
554
556template <class Iterator, class Generator>
557inline void generate(Iterator first, const Iterator last, Generator gen)
558{
559 while (first != last)
560 {
561 *first = gen();
562 ++first;
563 }
564}
565
567template <class Iterator, class Generator>
568inline void generateN(Iterator first, unsigned int n, Generator gen)
569{
570 while (n > 0)
571 {
572 *first = gen();
573 ++first;
574 --n;
575 }
576}
577
579template <class Iterator, class T>
580inline Iterator remove(Iterator first, const Iterator last, const T &val)
581{
582 Iterator result = first;
583
584 while (first != last)
585 {
586 if (!(*first == val))
587 {
588 *result = *first;
589 ++result;
590 }
591 ++first;
592 }
593
594 return result;
595}
596
598template <class Iterator, class UnaryPredicate>
599inline Iterator removeIf(Iterator first, const Iterator last, UnaryPredicate pred)
600{
601 Iterator result = first;
602
603 while (first != last)
604 {
605 if (!pred(*first))
606 {
607 *result = *first;
608 ++result;
609 }
610 ++first;
611 }
612
613 return result;
614}
615
617template <class Iterator>
618inline void reverse(Iterator first, Iterator last)
619{
620 while ((first != last) && (first != --last))
621 {
622 iterSwap(first, last);
623 ++first;
624 }
625}
626
628template <class IteratorIn, class IteratorOut>
629inline IteratorOut reverseCopy(IteratorIn first, IteratorIn last, IteratorOut result)
630{
631 while (first != last)
632 {
633 --last;
634 *result = *last;
635 ++result;
636 }
637
638 return result;
639}
640
642template <class Iterator>
643inline bool isSorted(Iterator first, const Iterator last)
644{
645 if (first == last)
646 return true;
647
648 Iterator next = first;
649 while (++next != last)
650 {
651 if (*next < *first)
652 return false;
653 ++first;
654 }
655
656 return true;
657}
658
660template <class Iterator, class Compare>
661inline bool isSorted(Iterator first, const Iterator last, Compare comp)
662{
663 if (first == last)
664 return true;
665
666 Iterator next = first;
667 while (++next != last)
668 {
669 if (comp(*next, *first))
670 return false;
671 ++first;
672 }
673
674 return true;
675}
676
678template <class Iterator>
679inline const Iterator isSortedUntil(Iterator first, const Iterator last)
680{
681 if (first == last)
682 return first;
683
684 Iterator next = first;
685 while (++next != last)
686 {
687 if (*next < *first)
688 return next;
689 ++first;
690 }
691
692 return last;
693}
694
696template <class Iterator, class Compare>
697inline const Iterator isSortedUntil(Iterator first, const Iterator last, Compare comp)
698{
699 if (first == last)
700 return first;
701
702 Iterator next = first;
703 while (++next != last)
704 {
705 if (comp(*next, *first))
706 return next;
707 ++first;
708 }
709
710 return last;
711}
712
713namespace {
714
716 template <class Iterator, class Compare>
717 inline Iterator partition(Iterator first, Iterator last, Compare comp)
718 {
719 const Iterator pivot = last;
720
721 while (first != last)
722 {
723 while (comp(*first, *pivot))
724 {
725 ++first;
726 if (first == last)
727 return first;
728 }
729
730 do
731 {
732 --last;
733 if (first == last)
734 return first;
735 } while (!comp(*last, *pivot));
736
737 swap(*first, *last);
738 ++first;
739 }
740
741 return first;
742 }
743
745 template <class Iterator, class Compare>
746 inline void quicksort(Iterator first, Iterator last, RandomAccessIteratorTag, Compare comp)
747 {
748 const int size = distance(first, last);
749 if (size > 1)
750 {
751 Iterator p = prev(last);
752 swap(*next(first, size / 2), *p);
753 Iterator q = partition(first, p, comp);
754 swap(*q, *p);
755 quicksort(first, q, RandomAccessIteratorTag(), comp);
756 quicksort(next(q), last, RandomAccessIteratorTag(), comp);
757 }
758 }
759
761 template <class Iterator, class Compare>
762 inline void quicksort(Iterator first, Iterator last, BidirectionalIteratorTag, Compare comp)
763 {
764 if (first != last)
765 {
766 Iterator p = prev(last);
767 swap(*first, *p);
768 Iterator q = partition(first, p, comp);
769 swap(*q, *p);
770 quicksort(first, q, BidirectionalIteratorTag(), comp);
771 quicksort(next(q), last, BidirectionalIteratorTag(), comp);
772 }
773 }
774
775}
776
778template <class Iterator, class Compare>
779inline void quicksort(Iterator first, Iterator last, Compare comp)
780{
781 quicksort(first, last, IteratorTraits<Iterator>::IteratorCategory(), comp);
782}
783
785template <class Iterator>
786inline void quicksort(Iterator first, Iterator last)
787{
788 quicksort(first, last, IteratorTraits<Iterator>::IteratorCategory(), IsLess<typename IteratorTraits<Iterator>::ValueType>);
789}
790
792template <class Iterator>
793inline void quicksortDesc(Iterator first, Iterator last)
794{
795 quicksort(first, last, IteratorTraits<Iterator>::IteratorCategory(), IsNotLess<typename IteratorTraits<Iterator>::ValueType>);
796}
797
798namespace {
799
801 inline int iLeftChild(int i)
802 {
803 return (2 * i + 1);
804 }
805
806}
807
809template <class Iterator, class Compare>
810inline void heapsort(Iterator first, Iterator last, Compare comp)
811{
812 const int size = distance(first, last);
813 int start = floor(size / 2);
814 int end = size;
815
816 while (end > 1)
817 {
818 if (start > 0)
819 start--;
820 else
821 {
822 end--;
823 swap(*(first + end), *first);
824 }
825
826 int root = start;
827 while (iLeftChild(root) < end)
828 {
829 int child = iLeftChild(root);
830 if (child + 1 < end && comp(*(first + child), *(first + child + 1)))
831 child++;
832
833 if (comp(*(first + root), *(first + child)))
834 {
835 swap(*(first + root), *(first + child));
836 root = child;
837 }
838 else
839 break;
840 }
841 }
842}
843
845template <class Iterator>
846inline void heapsort(Iterator first, Iterator last)
847{
848 heapsort(first, last, IsLess<typename IteratorTraits<Iterator>::ValueType>);
849}
850
852template <class Iterator>
853inline void heapsortDesc(Iterator first, Iterator last)
854{
855 heapsort(first, last, IsNotLess<typename IteratorTraits<Iterator>::ValueType>);
856}
857
859template <class Iterator, class Compare>
860inline void insertionsort(Iterator first, Iterator last, Compare comp)
861{
862 const int size = distance(first, last);
863
864 int i = 1;
865 while (i < size)
866 {
867 auto x = *(first + i);
868 int j = i;
869 while (j > 0 && comp(x, *(first + j - 1)))
870 {
871 *(first + j) = *(first + j - 1);
872 j--;
873 }
874 *(first + j) = x;
875 i++;
876 }
877}
878
880template <class Iterator>
881inline void insertionsort(Iterator first, Iterator last)
882{
883 insertionsort(first, last, IsLess<typename IteratorTraits<Iterator>::ValueType>);
884}
885
887template <class Iterator>
888inline void insertionsortDesc(Iterator first, Iterator last)
889{
890 insertionsort(first, last, IsNotLess<typename IteratorTraits<Iterator>::ValueType>);
891}
892
893namespace {
894
896 template <class Iterator, class Compare>
897 inline void introsort(Iterator first, Iterator last, Compare comp, unsigned int maxDepth)
898 {
899 const int size = distance(first, last);
900 if (size < 16)
901 insertionsort(first, last, comp);
902 else if (maxDepth == 0)
903 heapsort(first, last, comp);
904 else
905 {
906 Iterator p = prev(last);
907 swap(*next(first, size / 2), *p);
908 Iterator q = partition(first, p, comp);
909 swap(*q, *p);
910 introsort(first, q, comp, maxDepth - 1);
911 introsort(next(q), last, comp, maxDepth - 1);
912 }
913 }
914
915}
916
918template <class Iterator, class Compare>
919inline void sort(Iterator first, Iterator last, Compare comp)
920{
921 const unsigned int maxDepth = log(distance(first, last)) * 2;
922 introsort(first, last, comp, maxDepth);
923}
924
926template <class Iterator>
927inline void sort(Iterator first, Iterator last)
928{
929 const unsigned int maxDepth = log(distance(first, last)) * 2;
930 introsort(first, last, IsLess<typename IteratorTraits<Iterator>::ValueType>, maxDepth);
931}
932
934template <class Iterator>
935inline void sortDesc(Iterator first, Iterator last)
936{
937 const unsigned int maxDepth = log(distance(first, last)) * 2;
938 introsort(first, last, IsNotLess<typename IteratorTraits<Iterator>::ValueType>, maxDepth);
939}
940
941}
942
943#endif
A function object returning true if its argument is equal to a reference value sets upon object const...
Definition algorithms.h:42
A function object returning true if its argument is greater than a reference value sets upon object c...
Definition algorithms.h:68
A function object returning true if its argument is less than a reference value sets upon object cons...
Definition algorithms.h:94
A function object returning true if its argument is not equal to a reference value sets upon object c...
Definition algorithms.h:55
A function object returning true if its argument is not greater than a reference value sets upon obje...
Definition algorithms.h:81
A function object returning true if its argument is not less than a reference value sets upon object ...
Definition algorithms.h:107
A unique pointer implementation.
Definition UniquePtr.h:118