-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathahAlgo.H
More file actions
1726 lines (1394 loc) · 51.6 KB
/
ahAlgo.H
File metadata and controls
1726 lines (1394 loc) · 51.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
Aleph_w
Data structures & Algorithms
version 2.0.0b
https://github.com/lrleon/Aleph-w
This file is part of Aleph-w library
Copyright (c) 2002-2026 Leandro Rabindranath Leon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Aleph implementation of C++ standard algorithms
// Based on code from GNU ISO C++ Library, Hewlett-Packard and Silicon Graphics
#ifndef AHALGO_H
#define AHALGO_H
/** @file ahAlgo.H
@brief Aleph-w implementation of STL-like algorithms.
This file provides implementations of common STL algorithms adapted
for use with Aleph-w containers and iterators.
@ingroup Algorithms
* @author Leandro Rabindranath León
*/
#include <ahAssert.H>
#include <ahUtils.H>
namespace Aleph
{
using size_type = size_t;
// ============================================================================
// Non-Modifying Algorithms
// ============================================================================
/** @brief Apply an operation to each element in a range.
Iterates through all elements in the range [beg, end) and applies
the given operation to each one.
@tparam Itor Iterator type.
@tparam Operation Callable type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param op Operation to apply to each element.
@return A copy of the operation op.
@ingroup Algorithms
*/
template <class Itor, class Operation>
inline Operation for_each(Itor beg, const Itor & end, Operation op)
{
while (beg != end)
op(*beg++);
return op;
}
/** @brief Count elements satisfying a predicate.
Counts the number of elements in the range [beg, end) for which
the predicate op returns true.
@tparam Itor Iterator type.
@tparam Operation Predicate type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param op Unary predicate to test elements.
@return The number of elements satisfying the predicate.
@ingroup Algorithms
*/
template<class Itor, class Operation>
[[nodiscard]] inline typename Itor::difference_type
count_if(Itor beg, const Itor & end, Operation op)
{
typename Itor::difference_type n = 0;
while (beg != end)
if (op(*beg++))
++n;
return n;
}
/** @brief Count elements equal to a value.
Counts the number of elements in the range [beg, end) that are
equal to the specified value.
@tparam Itor Iterator type.
@tparam T Value type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param value Value to compare against.
@return The number of elements equal to value.
@ingroup Algorithms
*/
template <class Itor, class T>
[[nodiscard]] inline typename Itor::difference_type
count(const Itor & beg, const Itor & end, const T & value)
{
return Aleph::count_if(beg, end, Aleph::bind2nd(equal_to<T>(), value));
}
/** @brief Find the minimum element in a range.
Returns an iterator to the smallest element in the range [beg, end)
according to the comparison function.
@tparam Itor Iterator type.
@tparam CompFunc Comparison functor type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param op Comparison function (defaults to less-than).
@return Iterator to the minimum element.
@ingroup Algorithms
*/
template<class Itor,
class CompFunc = Aleph::less<typename Itor::value_type>>
[[nodiscard]] inline Itor min_element(Itor beg, const Itor & end,
CompFunc op = CompFunc())
{
if (beg == end)
return end;
Itor min = beg;
++beg;
while (beg != end)
{
if (op(*beg, *min))
min = beg;
++beg;
}
return min;
}
/** @brief Find the maximum element in a range.
Returns an iterator to the largest element in the range [beg, end)
according to the comparison function.
@tparam Itor Iterator type.
@tparam CompFunc Comparison functor type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param op Comparison function (defaults to greater-than).
@return Iterator to the maximum element.
@ingroup Algorithms
*/
template<class Itor,
class CompFunc = Aleph::greater<typename Itor::value_type>>
[[nodiscard]] inline Itor max_element(const Itor& beg, const Itor& end,
CompFunc op = CompFunc())
{
return Aleph::min_element(beg, end, op);
}
/** @brief Find the first element satisfying a predicate.
Searches the range [beg, end) for the first element for which
the predicate op returns true.
@tparam Itor Iterator type.
@tparam UnaryPredicate Predicate type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param op Unary predicate to test elements.
@return Iterator to the found element, or end if not found.
@ingroup Algorithms
*/
template<class Itor, class UnaryPredicate>
[[nodiscard]] inline Itor find_if(Itor beg, const Itor & end, UnaryPredicate op)
{
while (beg != end and not op(*beg))
++beg;
assert(beg == end or op(*beg));
return beg;
}
/** @brief Find the first element equal to a value.
Searches the range [beg, end) for the first element equal to
the specified value.
@tparam Itor Iterator type.
@tparam T Value type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param value Value to search for.
@return Iterator to the found element, or end if not found.
@ingroup Algorithms
*/
template<class Itor, class T>
[[nodiscard]] inline Itor find(const Itor & beg, const Itor & end, const T & value)
{
return Aleph::find_if(beg, end, Aleph::bind2nd(Aleph::equal_to<T>(), value));
}
/** @brief Find n consecutive elements equal to a value.
Searches for the first occurrence of count consecutive elements
equal to value in the range [beg, end).
@tparam Itor Iterator type.
@tparam Size Integer type for count.
@tparam T Value type.
@tparam BinaryPredicate Comparison predicate.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param count Number of consecutive elements to find.
@param value Value to compare against.
@param op Binary predicate for comparison (defaults to equality).
@return Iterator to the first of the consecutive elements, or end.
@ingroup Algorithms
*/
template<class Itor, class Size, class T,
class BinaryPredicate = Aleph::equal_to<T>>
[[nodiscard]] inline Itor search_n(Itor beg,
const Itor & end,
Size count,
const T & value,
BinaryPredicate op = BinaryPredicate())
{
if (count <= 0 or beg == end)
return end;
Size i = 0;
Itor first;
while (beg != end and i < count)
{
if (op(*beg, value))
{
if (i == 0)
first = beg;
++i;
}
else
i = 0;
++beg;
}
if (i == count)
return first;
return end;
}
/** @brief Search for a subrange within a range.
Searches for the first occurrence of the subrange [searchBeg, searchEnd)
within the range [beg, end).
@tparam Itor1 Main range iterator type.
@tparam Itor2 Subrange iterator type.
@tparam BinaryPredicate Comparison predicate.
@param beg Iterator to the first element of the main range.
@param end Iterator past the last element of the main range.
@param searchBeg Iterator to the first element of the subrange.
@param searchEnd Iterator past the last element of the subrange.
@param op Binary predicate for comparison (defaults to equality).
@return Iterator to the first element of the found subrange, or end.
@note The ranges can be of different container types as long as op
can compare their elements.
@ingroup Algorithms
*/
template<class Itor1, class Itor2,
class BinaryPredicate = Aleph::equal_to<typename Itor1::value_type>>
[[nodiscard]] inline Itor1 search(Itor1 beg, const Itor1 & end,
Itor2 searchBeg, const Itor2 & searchEnd,
BinaryPredicate op = BinaryPredicate())
{
if (beg == end or searchBeg == searchEnd)
return end;
Itor1 first;
Itor2 pivot = searchBeg;
int count = 0;
while (beg != end and pivot != searchEnd)
{
if (op(*beg, *pivot))
{
if (count == 0)
first = beg;
++pivot;
++count;
}
else
{
pivot = searchBeg;
count = 0;
}
++beg;
}
if (pivot == searchEnd)
return first;
return end;
}
/** @brief Find the last occurrence of a subrange.
Searches for the last occurrence of the subrange [searchBeg, searchEnd)
within the range [beg, end).
@tparam Itor1 Main range iterator type.
@tparam Itor2 Subrange iterator type.
@tparam BinaryPredicate Comparison predicate.
@param beg Iterator to the first element of the main range.
@param end Iterator past the last element of the main range.
@param searchBeg Iterator to the first element of the subrange.
@param searchEnd Iterator past the last element of the subrange.
@param op Binary predicate for comparison.
@return Iterator to the first element of the last occurrence, or end.
@ingroup Algorithms
*/
template<class Itor1, class Itor2,
class BinaryPredicate = Aleph::equal_to<typename Itor1::value_type>>
[[nodiscard]] inline Itor1 find_end(Itor1 beg, Itor1 end,
Itor2 searchBeg, Itor2 searchEnd,
BinaryPredicate op = BinaryPredicate())
{
if (beg == end or searchBeg == searchEnd)
return end;
Itor1 ret_val = end;
while (true)
{
Itor1 new_ret = search(beg, end, searchBeg, searchEnd, op);
if (new_ret == end)
return ret_val;
else
{
ret_val = new_ret;
beg = new_ret;
++beg;
}
}
}
/** @brief Find first element from a set.
Searches the range [beg, end) for the first element that matches
any element in [searchBeg, searchEnd).
@tparam Itor1 Main range iterator type.
@tparam Itor2 Search set iterator type.
@tparam BinaryPredicate Comparison predicate.
@param beg Iterator to the first element of the main range.
@param end Iterator past the last element of the main range.
@param searchBeg Iterator to the first element of the search set.
@param searchEnd Iterator past the last element of the search set.
@param op Binary predicate for comparison.
@return Iterator to the first matching element, or end.
@ingroup Algorithms
*/
template<class Itor1, class Itor2,
class BinaryPredicate = Aleph::equal_to<typename Itor1::value_type>>
[[nodiscard]] inline Itor1 find_first_of(const Itor1& beg, const Itor1& end,
Itor2 searchBeg, const Itor2& searchEnd,
BinaryPredicate op = BinaryPredicate())
{
while (searchBeg != searchEnd)
{
Itor1 current = beg;
while (current != end)
{
if (op(*current, *searchBeg))
return current;
++current;
}
++searchBeg;
}
return end;
}
/** @brief Find first pair of adjacent equal elements.
Searches the range [beg, end) for two consecutive elements that
are equal according to the predicate.
@tparam Itor Iterator type.
@tparam BinaryPredicate Comparison predicate.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param op Binary predicate for comparison.
@return Iterator to the first of the equal pair, or end.
@ingroup Algorithms
*/
template<class Itor,
class BinaryPredicate = Aleph::equal_to<typename Itor::value_type>>
[[nodiscard]] inline Itor adjacent_find(Itor beg, const Itor & end,
BinaryPredicate op = BinaryPredicate())
{
if (beg == end)
return end;
Itor next(beg);
++next;
while (next != end)
{
if (op(*beg, *next))
return beg;
++beg;
++next;
}
return end;
}
/** @brief Test if two ranges are equal.
Compares elements in the range [beg, end) with elements starting
at cmpBeg.
@tparam Itor1 First range iterator type.
@tparam Itor2 Second range iterator type.
@tparam BinaryPredicate Comparison predicate.
@param beg Iterator to the first element of the first range.
@param end Iterator past the last element of the first range.
@param cmpBeg Iterator to the first element of the second range.
@param op Binary predicate for comparison.
@return true if all corresponding elements are equal.
@ingroup Algorithms
*/
template <class Itor1, class Itor2,
class BinaryPredicate = Aleph::equal_to<typename Itor1::value_type>>
[[nodiscard]] inline bool equal(Itor1 beg, const Itor1 & end,
Itor2 cmpBeg, BinaryPredicate op = BinaryPredicate())
{
while (beg != end)
{
if (not op(*beg, *cmpBeg))
return false;
++beg;
++cmpBeg;
}
return true;
}
/** @brief Find the first mismatching elements in two ranges.
Compares elements in the range [beg, end) with elements starting
at cmpBeg and returns the first pair that differs.
@tparam Itor1 First range iterator type.
@tparam Itor2 Second range iterator type.
@tparam BinaryPredicate Comparison predicate.
@param beg Iterator to the first element of the first range.
@param end Iterator past the last element of the first range.
@param cmpBeg Iterator to the first element of the second range.
@param op Binary predicate for comparison.
@return Pair of iterators to the first mismatching elements.
@ingroup Algorithms
*/
template <class Itor1, class Itor2,
class BinaryPredicate = Aleph::equal_to<typename Itor1::value_type>>
[[nodiscard]] inline std::pair<Itor1, Itor2>
mismatch(Itor1 beg, const Itor1& end,
Itor2 cmpBeg,
BinaryPredicate op = BinaryPredicate())
{
while (beg != end and op(*beg, *cmpBeg))
{
++beg;
++cmpBeg;
}
return std::make_pair(beg, cmpBeg);
}
/** @brief Lexicographical comparison of two ranges.
Compares two ranges lexicographically.
@tparam Itor1 First range iterator type.
@tparam Itor2 Second range iterator type.
@tparam Comp Comparison functor.
@param beg1 Iterator to the first element of the first range.
@param end1 Iterator past the last element of the first range.
@param beg2 Iterator to the first element of the second range.
@param end2 Iterator past the last element of the second range.
@param op Comparison function.
@return true if the first range is lexicographically less than the second.
@ingroup Algorithms
*/
template <class Itor1, class Itor2,
class Comp = Aleph::less<typename Itor1::value_type>>
[[nodiscard]] inline bool lexicographical_compare(Itor1 beg1, const Itor1 & end1,
Itor2 beg2, const Itor2 & end2,
Comp op = Comp())
{
while (beg1 != end1 and beg2 != end2)
{
if (op(*beg1, *beg2))
return true;
else if (op(*beg2, *beg1))
return false;
++beg1;
++beg2;
}
return beg1 == end1 and beg2 != end2;
}
// ============================================================================
// Modifying Algorithms
// ============================================================================
/** @brief Copy elements from one range to another.
Copies elements from [sourceBeg, sourceEnd) to the range starting at destBeg.
@tparam Itor1 Source iterator type.
@tparam Itor2 Destination iterator type.
@param sourceBeg Iterator to the first source element.
@param sourceEnd Iterator past the last source element.
@param destBeg Iterator to the first destination position.
@return Iterator past the last copied element in destination.
@ingroup Algorithms
*/
template <class Itor1, class Itor2>
inline Itor2 copy(Itor1 sourceBeg, const Itor1& sourceEnd, Itor2 destBeg)
{
while (sourceBeg != sourceEnd)
*destBeg++ = *sourceBeg++;
return destBeg;
}
/** @brief Copy elements backward from one range to another.
Copies elements from [sourceBeg, sourceEnd) to the range ending at destEnd,
copying from back to front.
@tparam Itor1 Source iterator type.
@tparam Itor2 Destination iterator type.
@param sourceBeg Iterator to the first source element.
@param sourceEnd Iterator past the last source element.
@param destEnd Iterator past the last destination position.
@return Iterator to the first copied element in destination.
@ingroup Algorithms
*/
template <class Itor1, class Itor2>
inline Itor2 copy_backward(const Itor1 & sourceBeg, Itor1 sourceEnd, Itor2 destEnd)
{
while (sourceBeg != sourceEnd)
*--destEnd = *--sourceEnd;
return destEnd;
}
/** @brief Transform elements using a unary operation.
Applies op to each element in [sourceBeg, sourceEnd) and stores
the result in the range starting at destBeg.
@tparam Itor1 Source iterator type.
@tparam Itor2 Destination iterator type.
@tparam UnaryFunc Transformation function type.
@param sourceBeg Iterator to the first source element.
@param sourceEnd Iterator past the last source element.
@param destBeg Iterator to the first destination position.
@param op Unary operation to apply.
@return Iterator past the last transformed element in destination.
@ingroup Algorithms
*/
template <class Itor1, class Itor2, class UnaryFunc>
inline Itor2 transform(Itor1 sourceBeg, Itor1 sourceEnd,
Itor2 destBeg, UnaryFunc op)
{
while (sourceBeg != sourceEnd)
*destBeg++ = op(*sourceBeg++);
return destBeg;
}
/** @brief Transform elements using a binary operation.
Applies op to corresponding elements from two ranges and stores
the result starting at destBeg.
@tparam Itor1 First source iterator type.
@tparam Itor2 Second source iterator type.
@tparam Itor3 Destination iterator type.
@tparam BinaryFunc Transformation function type.
@param source1Beg Iterator to the first element of the first source.
@param source1End Iterator past the last element of the first source.
@param source2Beg Iterator to the first element of the second source.
@param destBeg Iterator to the first destination position.
@param op Binary operation to apply.
@return Iterator past the last transformed element in destination.
@ingroup Algorithms
*/
template <class Itor1, class Itor2, class Itor3, class BinaryFunc>
inline Itor3 transform(Itor1 source1Beg, Itor1 source1End,
Itor2 source2Beg,
Itor3 destBeg,
BinaryFunc op)
{
while (source1Beg != source1End)
*destBeg++ = op(*source1Beg++, *source2Beg++);
return destBeg;
}
/** @brief Swap elements between two ranges.
Swaps elements in the range [beg1, end1) with corresponding
elements starting at beg2.
@tparam Itor1 First range iterator type.
@tparam Itor2 Second range iterator type.
@param beg1 Iterator to the first element of the first range.
@param end1 Iterator past the last element of the first range.
@param beg2 Iterator to the first element of the second range.
@return Iterator past the last swapped element in the second range.
@ingroup Algorithms
*/
template <class Itor1, class Itor2>
inline Itor2 swap_ranges(Itor1 beg1, const Itor1& end1, Itor2 beg2)
{
while (beg1 != end1)
std::swap(*beg1++, *beg2++);
return beg2;
}
/** @brief Fill a range with a value.
Assigns the specified value to all elements in [beg, end).
@tparam Itor Iterator type.
@tparam T Value type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param value Value to assign.
@ingroup Algorithms
*/
template <class Itor, class T>
inline void fill(Itor beg, const Itor& end, const T & value)
{
while (beg != end)
*beg++ = value;
}
/** @brief Fill n elements with a value.
Assigns the specified value to the first n elements starting at beg.
@tparam Itor Iterator type.
@tparam T Value type.
@tparam Size Integer type.
@param beg Iterator to the first element.
@param num Number of elements to fill.
@param value Value to assign.
@ingroup Algorithms
*/
template <class Itor, class T, class Size>
inline void fill_n(Itor beg, Size num, const T & value)
{
while (num-- > 0)
*beg++ = value;
}
/** @brief Generate values for a range.
Assigns the result of successive calls to op to each element in [beg, end).
@tparam Itor Iterator type.
@tparam Func Generator function type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param op Generator function.
@ingroup Algorithms
*/
template <class Itor, class Func>
inline void generate(Itor beg, const Itor& end, Func op)
{
while (beg != end)
*beg++ = op();
}
/** @brief Generate values for n elements.
Assigns the result of successive calls to op to the first n elements.
@tparam Itor Iterator type.
@tparam Size Integer type.
@tparam Func Generator function type.
@param beg Iterator to the first element.
@param num Number of elements to generate.
@param op Generator function.
@ingroup Algorithms
*/
template <class Itor, class Size, class Func>
inline void generate_n(Itor beg, Size num, Func op)
{
while (num-- > 0)
*beg++ = op();
}
/** @brief Replace elements satisfying a predicate.
Replaces all elements in [beg, end) for which op returns true
with the specified value.
@tparam Itor Iterator type.
@tparam UnaryPredicate Predicate type.
@tparam T Value type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param op Unary predicate to test elements.
@param value Replacement value.
@ingroup Algorithms
*/
template <class Itor, class UnaryPredicate, class T>
inline void replace_if(Itor beg, const Itor& end,
UnaryPredicate op,
const T & value)
{
while (beg != end)
{
if (op(*beg))
*beg = value;
++beg;
}
}
/** @brief Replace elements equal to a value.
Replaces all elements in [beg, end) equal to old_value with new_value.
@tparam Itor Iterator type.
@tparam T Value type.
@param beg Iterator to the first element.
@param end Iterator past the last element.
@param old_value Value to be replaced.
@param new_value Replacement value.
@ingroup Algorithms
*/
template <class Itor, class T>
inline void replace(Itor beg, const Itor& end,
const T & old_value,
const T & new_value)
{
Aleph::replace_if(beg, end,
Aleph::bind2nd(equal_to<T>(), old_value), new_value);
}
/** @brief Copy and replace elements satisfying a predicate.
Copies elements from source to destination, replacing those
for which op returns true with the specified value.
@tparam Itor1 Source iterator type.
@tparam Itor2 Destination iterator type.
@tparam UnaryPredicate Predicate type.
@tparam T Value type.
@param sourceBeg Iterator to the first source element.
@param sourceEnd Iterator past the last source element.
@param destBeg Iterator to the first destination position.
@param op Unary predicate to test elements.
@param value Replacement value.
@return Iterator past the last copied element in destination.
@ingroup Algorithms
*/
template <class Itor1, class Itor2, class UnaryPredicate, class T>
inline Itor2 replace_copy_if(Itor1 sourceBeg, const Itor1& sourceEnd,
Itor2 destBeg,
UnaryPredicate op,
const T & value)
{
while (sourceBeg != sourceEnd)
{
if (op(*sourceBeg))
*destBeg++ = value;
else
*destBeg++ = *sourceBeg;
++sourceBeg;
}
return destBeg;
}
/** @brief Copy and replace elements equal to a value.
Copies elements from source to destination, replacing those
equal to old_value with new_value.
@tparam Itor1 Source iterator type.
@tparam Itor2 Destination iterator type.
@tparam T Value type.
@param sourceBeg Iterator to the first source element.
@param sourceEnd Iterator past the last source element.
@param destBeg Iterator to the first destination position.
@param old_value Value to be replaced.
@param new_value Replacement value.
@return Iterator past the last copied element in destination.
@ingroup Algorithms
*/
template <class Itor1, class Itor2, class T>
inline Itor2 replace_copy(const Itor1& sourceBeg, const Itor1& sourceEnd,
Itor2 destBeg,
const T & old_value,
const T & new_value)
{
return Aleph::replace_copy_if(sourceBeg, sourceEnd, destBeg,
Aleph::bind2nd(equal_to<T>(), old_value),
new_value);
}
/** @brief Copy elements not satisfying a predicate.
Copies elements from [first, last) to result, excluding those
for which pred returns true.
@tparam In_Itor Input iterator type.
@tparam Out_Itor Output iterator type.
@tparam Predicate Predicate type.
@param __first Iterator to the first source element.
@param __last Iterator past the last source element.
@param __result Iterator to the first destination position.
@param __pred Unary predicate to test elements.
@return Iterator past the last copied element in destination.
@ingroup Algorithms
*/
template <class In_Itor, class Out_Itor, class Predicate>
inline Out_Itor remove_copy_if(In_Itor __first, const In_Itor & __last,
Out_Itor __result,
Predicate __pred)
{
for ( ; __first != __last; ++__first)
if (not __pred(*__first))
{
*__result = *__first;
++__result;
}
return __result;
}
/** @brief Remove elements satisfying a predicate.
Removes all elements in [first, last) for which pred returns true
by moving the remaining elements forward.
@tparam Fw_Itor Forward iterator type.
@tparam Predicate Predicate type.
@param __first Iterator to the first element.
@param __last Iterator past the last element.
@param __pred Unary predicate to test elements.
@return Iterator to the new logical end of the range.
@ingroup Algorithms
*/
template<class Fw_Itor, class Predicate>
inline Fw_Itor remove_if(Fw_Itor __first, const Fw_Itor & __last,
Predicate __pred)
{
__first = Aleph::find_if(__first, __last, __pred);
Fw_Itor __i = __first;
if (__first == __last)
return __first;
else
return Aleph::remove_copy_if(++__i, __last, __first, __pred);
}
/** @brief Remove elements equal to a value.
Removes all elements in [first, last) equal to value by moving
the remaining elements forward.
@tparam Fw_Itor Forward iterator type.
@tparam T Value type.
@param __first Iterator to the first element.
@param __last Iterator past the last element.
@param __value Value to remove.
@return Iterator to the new logical end of the range.
@ingroup Algorithms
*/
template<class Fw_Itor, class T>
inline Fw_Itor remove(Fw_Itor __first, const Fw_Itor & __last,
const T & __value)
{
return Aleph::remove_if(__first, __last,
Aleph::bind2nd(Aleph::equal_to<T>(), __value));
}
/// @cond INTERNAL
template<class In_Itor, class Out_Itor,
class BinaryPredicate = Aleph::equal_to<typename In_Itor::value_type>>
static inline Out_Itor __unique_copy(In_Itor __first, In_Itor __last,
Out_Itor __result,
BinaryPredicate __binary_pred = BinaryPredicate())
{
typename In_Itor::value_type __value = *__first;
*__result = __value;
while (++__first != __last)
if (not __binary_pred(__value, *__first))
{
__value = *__first;
*++__result = __value;
}
return ++__result;
}
/// @endcond
/** @brief Copy unique elements.
Copies elements from [first, last) to result, eliminating
consecutive duplicates.
@tparam In_Itor Input iterator type.
@tparam Out_Itor Output iterator type.
@param __first Iterator to the first source element.
@param __last Iterator past the last source element.
@param __result Iterator to the first destination position.