45 namespace suffix_sorting {
49 template <
typename AlphabetType>
54 return std::tie(ch[0], ch[1], ch[2], ch[3], ch[4], ch[5], ch[6])
55 == std::tie(b.ch[0], b.ch[1], b.ch[2], b.ch[3],
56 b.ch[4], b.ch[5], b.ch[6]);
60 return std::tie(ch[0], ch[1], ch[2], ch[3], ch[4], ch[5], ch[6])
61 < std::tie(b.ch[0], b.ch[1], b.ch[2], b.ch[3],
62 b.ch[4], b.ch[5], b.ch[6]);
65 friend std::ostream&
operator << (std::ostream& os,
const Chars& chars) {
66 return os <<
'[' << chars.ch[0] <<
',' << chars.ch[1]
67 <<
',' << chars.ch[2] <<
',' << chars.ch[3]
68 <<
',' << chars.ch[4] <<
',' << chars.ch[5]
69 <<
',' << chars.ch[6] <<
']';
72 static Chars Lowest() {
75 std::numeric_limits<AlphabetType>::lowest(),
76 std::numeric_limits<AlphabetType>::lowest(),
77 std::numeric_limits<AlphabetType>::lowest(),
78 std::numeric_limits<AlphabetType>::lowest(),
79 std::numeric_limits<AlphabetType>::lowest(),
80 std::numeric_limits<AlphabetType>::lowest(),
81 std::numeric_limits<AlphabetType>::lowest()
88 template <
typename Index,
typename AlphabetType>
91 Chars<AlphabetType> chars;
93 AlphabetType at_radix(
size_t depth)
const {
return chars.ch[depth]; }
95 friend std::ostream&
operator << (std::ostream& os,
const IndexChars& tc) {
96 return os <<
'[' << tc.index <<
'|' << tc.chars <<
']';
101 template <
typename Index>
106 friend std::ostream&
operator << (std::ostream& os,
const IndexRank& tr) {
107 return os <<
'(' << tr.index <<
'|' << tr.rank <<
')';
112 template <
typename Index,
typename AlphabetType>
113 struct StringFragmentMod0 {
118 friend std::ostream&
operator << (std::ostream& os,
119 const StringFragmentMod0& sf) {
120 return os <<
"i=" << sf.index
121 <<
" t0=" << sf.t[0] <<
" t1=" << sf.t[1] <<
" t2=" << sf.t[2]
122 <<
" r0=" << sf.r0 <<
" r1=" << sf.r1 <<
" r3=" << sf.r3;
127 template <
typename Index,
typename AlphabetType>
128 struct StringFragmentMod1 {
133 friend std::ostream&
operator << (std::ostream& os,
134 const StringFragmentMod1& sf) {
135 return os <<
"i=" << sf.index
136 <<
" t0=" << sf.t[0] <<
" t1=" << sf.t[1] <<
" t2=" << sf.t[2]
137 <<
" t3=" << sf.t[3] <<
" t4=" << sf.t[4] <<
" t5=" << sf.t[5]
138 <<
" r0=" << sf.r0 <<
" r2=" << sf.r2 <<
" r6=" << sf.r6;
143 template <
typename Index,
typename AlphabetType>
144 struct StringFragmentMod2 {
149 friend std::ostream&
operator << (std::ostream& os,
150 const StringFragmentMod2& sf) {
151 return os <<
"i=" << sf.index
152 <<
" t0=" << sf.t[0] <<
" t1=" << sf.t[1] <<
" t2=" << sf.t[2]
153 <<
" t3=" << sf.t[3] <<
" t4=" << sf.t[4] <<
" t5=" << sf.t[5]
154 <<
" r1=" << sf.r1 <<
" r5=" << sf.r5 <<
" r6=" << sf.r6;
159 template <
typename Index,
typename AlphabetType>
160 struct StringFragmentMod3 {
165 friend std::ostream&
operator << (std::ostream& os,
166 const StringFragmentMod3& sf) {
167 return os <<
"i=" << sf.index
168 <<
" t0=" << sf.t[0] <<
" t1=" << sf.t[1] <<
" t2=" << sf.t[2]
169 <<
" t3=" << sf.t[3] <<
" t4=" << sf.t[4]
170 <<
" r0=" << sf.r0 <<
" r4=" << sf.r4 <<
" r5=" << sf.r5;
175 template <
typename Index,
typename AlphabetType>
176 struct StringFragmentMod4 {
181 friend std::ostream&
operator << (std::ostream& os,
182 const StringFragmentMod4& sf) {
183 return os <<
"i=" << sf.index
184 <<
" t0=" << sf.t[0] <<
" t1=" << sf.t[1] <<
" t2=" << sf.t[2]
185 <<
" t3=" << sf.t[3] <<
" t4=" << sf.t[4] <<
" t5=" << sf.t[5]
186 <<
" r3=" << sf.r3 <<
" r4=" << sf.r4 <<
" r6=" << sf.r6;
191 template <
typename Index,
typename AlphabetType>
192 struct StringFragmentMod5 {
197 friend std::ostream&
operator << (std::ostream& os,
198 const StringFragmentMod5& sf) {
199 return os <<
"i=" << sf.index
200 <<
" t0=" << sf.t[0] <<
" t1=" << sf.t[1] <<
" t2=" << sf.t[2]
201 <<
" t3=" << sf.t[3] <<
" t4=" << sf.t[4]
202 <<
" r2=" << sf.r2 <<
" r3=" << sf.r3 <<
" r5=" << sf.r5;
207 template <
typename Index,
typename AlphabetType>
208 struct StringFragmentMod6 {
213 friend std::ostream&
operator << (std::ostream& os,
214 const StringFragmentMod6& sf) {
215 return os <<
"i=" << sf.index
216 <<
" t0=" << sf.t[0] <<
" t1=" << sf.t[1] <<
" t2=" << sf.t[2]
218 <<
" r1=" << sf.r1 <<
" r2=" << sf.r2 <<
" r4=" << sf.r4;
223 template <
typename Index,
typename AlphabetType>
224 struct StringFragment {
229 AlphabetType text[6];
235 StringFragmentMod0<Index, AlphabetType> mod0;
236 StringFragmentMod1<Index, AlphabetType> mod1;
237 StringFragmentMod2<Index, AlphabetType> mod2;
238 StringFragmentMod3<Index, AlphabetType> mod3;
239 StringFragmentMod4<Index, AlphabetType> mod4;
240 StringFragmentMod5<Index, AlphabetType> mod5;
241 StringFragmentMod6<Index, AlphabetType> mod6;
244 StringFragment() =
default;
247 explicit StringFragment(
248 const StringFragmentMod0<Index, AlphabetType>& _mod0) : mod0(_mod0) { }
251 explicit StringFragment(
252 const StringFragmentMod1<Index, AlphabetType>& _mod1) : mod1(_mod1) { }
255 explicit StringFragment(
256 const StringFragmentMod2<Index, AlphabetType>& _mod2) : mod2(_mod2) { }
259 explicit StringFragment(
260 const StringFragmentMod3<Index, AlphabetType>& _mod3) : mod3(_mod3) { }
263 explicit StringFragment(
264 const StringFragmentMod4<Index, AlphabetType>& _mod4) : mod4(_mod4) { }
267 explicit StringFragment(
268 const StringFragmentMod5<Index, AlphabetType>& _mod5) : mod5(_mod5) { }
271 explicit StringFragment(
272 const StringFragmentMod6<Index, AlphabetType>& _mod6) : mod6(_mod6) { }
274 friend std::ostream&
operator << (std::ostream& os,
275 const StringFragment& tc) {
277 if (tc.index % 7 == 0)
278 return os <<
"0|" << tc.mod0 <<
']';
279 else if (tc.index % 7 == 1)
280 return os <<
"1|" << tc.mod1 <<
']';
281 else if (tc.index % 7 == 2)
282 return os <<
"2|" << tc.mod2 <<
']';
283 else if (tc.index % 7 == 3)
284 return os <<
"3|" << tc.mod3 <<
']';
285 else if (tc.index % 7 == 4)
286 return os <<
"4|" << tc.mod4 <<
']';
287 else if (tc.index % 7 == 5)
288 return os <<
"5|" << tc.mod5 <<
']';
289 else if (tc.index % 7 == 6)
290 return os <<
"6|" << tc.mod6 <<
']';
294 AlphabetType at_radix(
size_t depth)
const {
return common.text[depth]; }
295 Index sort_rank()
const {
return common.ranks[0]; }
301 { 0, 0, 0 }, { 0, 0, 0 }, { 1, 1, 0 }, { 0, 0, 0 },
302 { 3, 2, 0 }, { 3, 2, 1 }, { 1, 1, 0 }
305 { 0, 0, 0 }, { 0, 0, 0 }, { 6, 2, 2 }, { 0, 0, 0 },
306 { 6, 2, 2 }, { 2, 1, 0 }, { 2, 1, 1 }
309 { 1, 0, 1 }, { 6, 2, 2 }, { 1, 0, 0 }, { 5, 1, 2 },
310 { 6, 2, 2 }, { 5, 1, 2 }, { 1, 0, 0 }
313 { 0, 0, 0 }, { 0, 0, 0 }, { 5, 2, 1 }, { 0, 0, 0 },
314 { 4, 1, 1 }, { 5, 2, 2 }, { 4, 1, 2 }
317 { 3, 0, 2 }, { 6, 2, 2 }, { 6, 2, 2 }, { 4, 1, 1 },
318 { 3, 0, 0 }, { 3, 0, 1 }, { 4, 1, 2 }
321 { 3, 1, 2 }, { 2, 0, 1 }, { 5, 2, 1 }, { 5, 2, 2 },
322 { 3, 1, 0 }, { 2, 0, 0 }, { 2, 0, 1 }
325 { 1, 0, 1 }, { 2, 1, 1 }, { 1, 0, 0 }, { 4, 2, 1 },
326 { 4, 2, 1 }, { 2, 1, 0 }, { 1, 0, 0 }
330 template <
typename StringFragment>
331 struct FragmentComparator {
333 bool operator () (
const StringFragment& a,
const StringFragment& b)
const {
335 unsigned ai = a.index % 7, bi = b.index % 7;
337 const size_t*
params = fragment_comparator_params[ai][bi];
339 for (
size_t d = 0; d < params[0]; ++d)
341 if (a.common.text[d] == b.common.text[d])
continue;
342 return (a.common.text[d] < b.common.text[d]);
345 return a.common.ranks[params[1]] < b.common.ranks[params[2]];
349 template <
typename Index,
typename Char>
350 struct CharsRanks013 {
356 friend std::ostream&
operator << (std::ostream& os,
357 const CharsRanks013& c) {
358 return os <<
"(ch=" << c.chars
359 <<
" r0=" << c.rank0 <<
" r1=" << c.rank1
360 <<
" r3=" << c.rank3 <<
")";
364 template <
typename Index,
typename Char>
365 struct IndexCR013Pair {
367 CharsRanks013<Index, Char> cr0;
368 CharsRanks013<Index, Char> cr1;
371 template <
typename Type,
size_t MaxDepth>
372 class RadixSortFragment
375 explicit RadixSortFragment(
size_t K) : K_(K) { }
376 template <
typename CompareFunction>
378 typename std::vector<Type>::iterator begin,
379 typename std::vector<Type>::iterator end,
380 const CompareFunction& cmp)
const {
382 thrill::common::radix_sort_CI<MaxDepth>(
383 begin, end, K_, cmp, [](
auto begin,
auto end,
auto) {
385 std::sort(begin, end, [](
const Type& a,
const Type& b) {
386 return a.sort_rank() < b.sort_rank();
391 std::sort(begin, end, cmp);
406 return m == 0 || m == 1 || m == 3;
409 template <
typename Index,
typename InputDIA>
413 using Char =
typename InputDIA::ValueType;
414 using IndexChars = dc7_local::IndexChars<Index, Char>;
415 using IndexRank = dc7_local::IndexRank<Index>;
416 using Chars = dc7_local::Chars<Char>;
418 Context& ctx = input_dia.context();
423 .template FlatWindow<IndexChars>(
429 { r[0], r[1], r[2], r[3], r[4], r[5], r[6] }
438 { r.size() >= 1 ? r[0] : Char(),
439 r.size() >= 2 ? r[1] : Char(),
440 r.size() >= 3 ? r[2] : Char(),
441 r.size() >= 4 ? r[3] : Char(),
442 r.size() >= 5 ? r[4] : Char(),
443 r.size() >= 6 ? r[5] : Char(),
449 if (index + 1 == input_size && input_size % 7 == 0) {
453 emit(IndexChars { Index(input_size), Chars::Lowest() });
455 if (index + 1 == input_size && input_size % 7 == 1) {
459 emit(IndexChars { Index(input_size), Chars::Lowest() });
463 .Sort([](
const IndexChars& a,
const IndexChars& b) {
464 return a.chars < b.chars;
468 tuple_sorted.Keep().Print(
"tuple_sorted");
471 auto tuple_index_sorted =
473 .Map([](
const IndexChars& tc) {
return tc.index; })
476 auto tuple_prerank_sums =
478 .template FlatWindow<Index>(
480 assert(rb.size() == 2);
483 if (index == 0) emit(0);
486 emit(rb[0].chars == rb[1].chars ? 0 : 1);
491 tuple_prerank_sums.Keep().Print(
"tuple_prerank_sums");
494 const Index max_lexname = tuple_prerank_sums.Keep().Max();
497 const Index size_mod0 = Index(input_size / 7 + 1);
500 const Index size_mod1 = Index(input_size / 7 + (input_size % 7 >= 1));
503 const Index size_mod3 = Index(input_size / 7 + (input_size % 7 >= 4));
506 const Index size_mod01 = size_mod0 + size_mod1;
509 const Index size_subp = size_mod01 + size_mod3;
512 sLOG1 <<
"max_lexname=" << max_lexname
513 <<
" size_subp=" << size_subp
514 <<
" size_mod0=" << size_mod0
515 <<
" size_mod1=" << size_mod1
516 <<
" size_mod3=" << size_mod3;
521 tuple_sorted.Keep().Filter([](
const IndexChars& a) {
522 return a.index % 7 == 0;
523 }).Size(), size_mod0);
526 tuple_sorted.Keep().Filter([](
const IndexChars& a) {
527 return a.index % 7 == 1;
528 }).Size(), size_mod1);
531 tuple_sorted.Keep().Filter([](
const IndexChars& a) {
532 return a.index % 7 == 3;
533 }).Size(), size_mod3);
536 assert_equal(tuple_index_sorted.Keep().Size(), size_subp);
540 if (max_lexname + Index(1) != size_subp) {
549 [](
const Index& tuple_index,
const Index& rank) {
554 tuple_ranks.Keep().Print(
"tuple_ranks");
561 if (a.index % 7 == b.index % 7)
562 return a.index < b.index;
564 return a.index % 7 < b.index % 7;
572 string_mod013.
Keep().Print(
"string_mod013");
576 using RecStringFragment = dc7_local::StringFragment<Index, Index>;
579 string_mod013, size_subp, max_lexname + Index(1));
585 suffix_array_rec.
Keep().Print(
"suffix_array_rec");
589 .
ZipWithIndex([](
const RecStringFragment& sa,
const size_t& i) {
594 .Sort([size_mod0, size_mod01](
597 Index ai = (a.index < size_mod0 ? a.index :
598 a.index < size_mod01 ? a.index - size_mod0 :
599 a.index - size_mod01);
601 Index bi = (b.index < size_mod0 ? b.index :
602 b.index < size_mod01 ? b.index - size_mod0 :
603 b.index - size_mod01);
606 return ai < bi || (ai == bi && a.index < b.index);
614 [size_mod0, size_mod01](
size_t,
const std::vector<IndexRank>& ir) {
616 die_unless(ir[1].index >= size_mod0 || ir[1].rank < size_mod01);
621 ranks_mod013.Keep().Print(
"ranks_rec");
626 sLOG1 <<
"*** recursion finished ***";
629 tuple_index_sorted.Keep().Print(
"tuple_index_sorted");
634 [](
const Index& sa,
const size_t& i) {
641 return a.index / 7 < b.index / 7 || (
642 a.index / 7 == b.index / 7 &&
651 [](
size_t,
const std::vector<IndexRank>& ir) {
658 ranks_mod013.Keep().Print(
"ranks_rec");
667 using StringFragmentMod0 = dc7_local::StringFragmentMod0<Index, Char>;
668 using StringFragmentMod1 = dc7_local::StringFragmentMod1<Index, Char>;
669 using StringFragmentMod2 = dc7_local::StringFragmentMod2<Index, Char>;
670 using StringFragmentMod3 = dc7_local::StringFragmentMod3<Index, Char>;
671 using StringFragmentMod4 = dc7_local::StringFragmentMod4<Index, Char>;
672 using StringFragmentMod5 = dc7_local::StringFragmentMod5<Index, Char>;
673 using StringFragmentMod6 = dc7_local::StringFragmentMod6<Index, Char>;
675 using CharsRanks013 = dc7_local::CharsRanks013<Index, Char>;
676 using IndexCR013Pair = dc7_local::IndexCR013Pair<Index, Char>;
678 auto zip_tuple_pairs1 =
683 [](
const std::array<Char, 7>& ch,
const std::array<IndexRank, 3>& mod013) {
684 return CharsRanks013 {
686 { ch[0], ch[1], ch[2], ch[3], ch[4], ch[5], ch[6] }
688 mod013[0].rank, mod013[1].rank, mod013[2].rank
691 std::make_tuple(std::numeric_limits<Char>::lowest(),
IndexRank { 0, 0 }),
692 input_dia, ranks_mod013);
695 zip_tuple_pairs1.Keep().Print(
"zip_tuple_pairs1");
697 auto zip_tuple_pairs =
699 .template FlatWindow<IndexCR013Pair>(
702 emit(IndexCR013Pair { Index(7 * index), rb[0], rb[1] });
703 if (index + 2 == size_mod0) {
705 emit(IndexCR013Pair {
706 Index(7 * (index + 1)), rb[1],
707 CharsRanks013 { Chars::Lowest(), 0, 0, 0 }
712 auto fragments_mod0 =
714 .Map([](
const IndexCR013Pair& ip) {
715 return StringFragmentMod0 {
717 ip.cr0.rank0, ip.cr0.rank1, ip.cr0.rank3,
718 { ip.cr0.chars.ch[0], ip.cr0.chars.ch[1],
722 .Filter([input_size](
const StringFragmentMod0& mod0) {
723 return mod0.index < Index(input_size);
726 auto fragments_mod1 =
728 .Map([](
const IndexCR013Pair& ip) {
729 return StringFragmentMod1 {
731 ip.cr0.rank1, ip.cr0.rank3, ip.cr1.rank0,
732 { ip.cr0.chars.ch[1], ip.cr0.chars.ch[2],
733 ip.cr0.chars.ch[3], ip.cr0.chars.ch[4],
734 ip.cr0.chars.ch[5], ip.cr0.chars.ch[6] }
737 .Filter([input_size](
const StringFragmentMod1& mod1) {
738 return mod1.index < Index(input_size);
741 auto fragments_mod2 =
743 .Map([](
const IndexCR013Pair& ip) {
744 return StringFragmentMod2 {
746 ip.cr0.rank3, ip.cr1.rank0, ip.cr1.rank1,
747 { ip.cr0.chars.ch[2], ip.cr0.chars.ch[3],
748 ip.cr0.chars.ch[4], ip.cr0.chars.ch[5],
749 ip.cr0.chars.ch[6], ip.cr1.chars.ch[0] }
752 .Filter([input_size](
const StringFragmentMod2& mod2) {
753 return mod2.index < Index(input_size);
756 auto fragments_mod3 =
758 .Map([](
const IndexCR013Pair& ip) {
759 return StringFragmentMod3 {
761 ip.cr0.rank3, ip.cr1.rank0, ip.cr1.rank1,
762 { ip.cr0.chars.ch[3], ip.cr0.chars.ch[4],
763 ip.cr0.chars.ch[5], ip.cr0.chars.ch[6],
767 .Filter([input_size](
const StringFragmentMod3& mod3) {
768 return mod3.index < Index(input_size);
771 auto fragments_mod4 =
773 .Map([](
const IndexCR013Pair& ip) {
774 return StringFragmentMod4 {
776 ip.cr1.rank0, ip.cr1.rank1, ip.cr1.rank3,
777 { ip.cr0.chars.ch[4], ip.cr0.chars.ch[5],
778 ip.cr0.chars.ch[6], ip.cr1.chars.ch[0],
779 ip.cr1.chars.ch[1], ip.cr1.chars.ch[2] }
782 .Filter([input_size](
const StringFragmentMod4& mod4) {
783 return mod4.index < Index(input_size);
786 auto fragments_mod5 =
788 .Map([](
const IndexCR013Pair& ip) {
789 return StringFragmentMod5 {
791 ip.cr1.rank0, ip.cr1.rank1, ip.cr1.rank3,
792 { ip.cr0.chars.ch[5], ip.cr0.chars.ch[6],
793 ip.cr1.chars.ch[0], ip.cr1.chars.ch[1],
797 .Filter([input_size](
const StringFragmentMod5& mod5) {
798 return mod5.index < Index(input_size);
801 auto fragments_mod6 =
803 .Map([](
const IndexCR013Pair& ip) {
804 return StringFragmentMod6 {
806 ip.cr1.rank0, ip.cr1.rank1, ip.cr1.rank3,
807 { ip.cr0.chars.ch[6], ip.cr1.chars.ch[0],
808 ip.cr1.chars.ch[1], ip.cr1.chars.ch[2] }
811 .Filter([input_size](
const StringFragmentMod6& mod6) {
812 return mod6.index < Index(input_size);
816 fragments_mod0.Keep().Print(
"fragments_mod0");
817 fragments_mod1.Keep().Print(
"fragments_mod1");
818 fragments_mod2.Keep().Print(
"fragments_mod2");
819 fragments_mod3.Keep().Print(
"fragments_mod3");
820 fragments_mod4.Keep().Print(
"fragments_mod4");
821 fragments_mod5.Keep().Print(
"fragments_mod5");
822 fragments_mod6.Keep().Print(
"fragments_mod6");
827 using StringFragment = dc7_local::StringFragment<Index, Char>;
829 auto string_fragments_mod0 =
831 .Map([](
const StringFragmentMod0& mod0)
832 {
return StringFragment(mod0); });
834 auto string_fragments_mod1 =
836 .Map([](
const StringFragmentMod1& mod1)
837 {
return StringFragment(mod1); });
839 auto string_fragments_mod2 =
841 .Map([](
const StringFragmentMod2& mod2)
842 {
return StringFragment(mod2); });
844 auto string_fragments_mod3 =
846 .Map([](
const StringFragmentMod3& mod3)
847 {
return StringFragment(mod3); });
849 auto string_fragments_mod4 =
851 .Map([](
const StringFragmentMod4& mod4)
852 {
return StringFragment(mod4); });
854 auto string_fragments_mod5 =
856 .Map([](
const StringFragmentMod5& mod5)
857 {
return StringFragment(mod5); });
859 auto string_fragments_mod6 =
861 .Map([](
const StringFragmentMod6& mod6)
862 {
return StringFragment(mod6); });
865 Union(string_fragments_mod0,
866 string_fragments_mod1,
867 string_fragments_mod2,
868 string_fragments_mod3,
869 string_fragments_mod4,
870 string_fragments_mod5,
871 string_fragments_mod6)
872 .Sort(dc7_local::FragmentComparator<StringFragment>())
878 std::vector<Char> input_vec = input_dia.Keep().Gather();
879 std::vector<Index> vec =
881 .Map([](
const StringFragment& a) {
return a.index; })
886 for (
const Index& index : vec) {
887 std::cout << std::setw(5) << p << std::setw(5) << index <<
" =";
888 for (Index i = index;
889 i < index + Index(64) && i < Index(input_size); ++i) {
890 std::cout <<
' ' << uint64_t(input_vec[i]);
901 return suffix_array.Collapse();
904 template <
typename Index,
typename InputDIA>
907 using Char =
typename InputDIA::ValueType;
908 using StringFragment = dc7_local::StringFragment<Index, Char>;
910 return DC7Recursive<Index>(input_dia, input_size,
K)
911 .Map([](
const StringFragment& a) {
return a.index; })
918 #if !THRILL_ON_TRAVIS
tlx::RingBuffer< Type, Allocator > RingBuffer
tag structure for ZipWindow()
DIA is the interface between the user and the Thrill framework.
auto Union(const FirstDIA &first_dia, const DIAs &... dias)
Union is a LOp, which creates the union of all items from any number of DIAs as a single DIA...
DIA< Index > DC7(const InputDIA &input_dia, size_t input_size, size_t K)
A ring (circular) buffer of static (non-growing) size.
auto ZipWindow(const std::array< size_t, 1+sizeof ...(DIAs)> &window_size, const ZipFunction &zip_function, const DIA< FirstDIAType, FirstDIAStack > &first_dia, const DIAs &... dias)
Zips two DIAs of equal size in style of functional programming by applying zip_function to the i-th f...
The Context of a job is a unique instance per worker which holds references to all underlying parts o...
template DIA< uint32_t > DC7< uint32_t >(const DIA< uint8_t > &input_dia, size_t input_size, size_t K)
static by_string to_string(int val)
convert to string
static constexpr size_t fragment_comparator_params[7][7][3]
#define assert_equal(X, Y)
template DIA< uint64_t > DC7< uint64_t >(const DIA< uint8_t > &input_dia, size_t input_size, size_t K)
auto Sort(const CompareFunction &compare_function=CompareFunction()) const
Sort is a DOp, which sorts a given DIA according to the given compare_function.
auto ZipWithIndex(const ZipFunction &zip_function) const
Zips each item of a DIA with its zero-based array index.
bool operator==(const uint_pair &b) const
equality checking operator
size_t my_rank() const
Global rank of this worker among all other workers in the system.
std::ostream & operator<<(std::ostream &os, const Status &s)
struct examples::suffix_sorting::dc7_local::Chars TLX_ATTRIBUTE_PACKED
static const uint64_t K[80]
DIA< dc7_local::StringFragment< Index, typename InputDIA::ValueType > > DC7Recursive(const InputDIA &input_dia, size_t input_size, size_t K)
auto Zip(const SecondDIA &second_dia, const ZipFunction &zip_function) const
Zips two DIAs of equal size in style of functional programming by applying zip_function to the i-th e...
tag structure for Window() and FlatWindow()
const DIA & Keep(size_t increase=1) const
Mark the referenced DIANode for keeping, which makes children not consume the data when executing...
bool operator<(const uint_pair &b) const
less-than comparison operator
static bool IsDiffCover7(size_t i)
SortAlgorithm class for use with api::Sort() which calls radix_sort_CI() if K is small enough...