2222
2323namespace o2 ::framework
2424{
25-
2625template <typename G, typename ... A>
2726struct GroupSlicer {
2827 using grouping_t = std::decay_t <G>;
@@ -46,34 +45,41 @@ struct GroupSlicer {
4645 GroupSlicerIterator& operator =(GroupSlicerIterator&&) = default ;
4746
4847 template <typename T>
48+ auto splittingFunction (T&&)
49+ {
50+ }
51+
52+ template <typename T>
53+ requires (o2::soa::relatedByIndex<std::decay_t <G>, std::decay_t <T>>())
4954 auto splittingFunction (T&& table)
5055 {
5156 constexpr auto index = framework::has_type_at_v<std::decay_t <T>>(associated_pack_t {});
52- if constexpr (o2::soa::relatedByIndex<std::decay_t <G>, std::decay_t <T>>()) {
53- auto binding = o2::soa::getLabelFromTypeForKey<std::decay_t <T>>(mIndexColumnName );
54- auto bk = std::make_pair (binding, mIndexColumnName );
55- if constexpr (!o2::soa::is_smallgroups<std::decay_t <T>>) {
56- if (table.size () == 0 ) {
57- return ;
58- }
59- sliceInfos[index] = mSlices ->getCacheFor (bk);
60- } else {
61- if (table.tableSize () == 0 ) {
62- return ;
63- }
64- sliceInfosUnsorted[index] = mSlices ->getCacheUnsortedFor (bk);
57+ auto binding = o2::soa::getLabelFromTypeForKey<std::decay_t <T>>(mIndexColumnName );
58+ auto bk = std::make_pair (binding, mIndexColumnName );
59+ if constexpr (!o2::soa::is_smallgroups<std::decay_t <T>>) {
60+ if (table.size () == 0 ) {
61+ return ;
6562 }
63+ sliceInfos[index] = mSlices ->getCacheFor (bk);
64+ } else {
65+ if (table.tableSize () == 0 ) {
66+ return ;
67+ }
68+ sliceInfosUnsorted[index] = mSlices ->getCacheUnsortedFor (bk);
6669 }
6770 }
6871
6972 template <typename T>
73+ auto extractingFunction (T&&)
74+ {
75+ }
76+
77+ template <soa::is_filtered_table T>
7078 auto extractingFunction (T&& table)
7179 {
72- if constexpr (soa::is_filtered_table<std::decay_t <T>>) {
73- constexpr auto index = framework::has_type_at_v<std::decay_t <T>>(associated_pack_t {});
74- selections[index] = &table.getSelectedRows ();
75- starts[index] = selections[index]->begin ();
76- }
80+ constexpr auto index = framework::has_type_at_v<std::decay_t <T>>(associated_pack_t {});
81+ selections[index] = &table.getSelectedRows ();
82+ starts[index] = selections[index]->begin ();
7783 }
7884
7985 GroupSlicerIterator (G& gt, std::tuple<A...>& at, ArrowTableSlicingCache& slices)
@@ -151,83 +157,108 @@ struct GroupSlicer {
151157 return std::make_tuple (prepareArgument<A>()...);
152158 }
153159
154- template <typename A1>
160+ template <soa::is_smallgroups A1>
161+ requires (o2::soa::relatedByIndex<std::decay_t <G>, std::decay_t <A1>>() && soa::is_filtered_table<A1>)
155162 auto prepareArgument ()
156163 {
157164 constexpr auto index = framework::has_type_at_v<A1>(associated_pack_t {});
158165 auto & originalTable = std::get<A1>(*mAt );
159-
160- if constexpr (o2::soa::relatedByIndex<std::decay_t <G>, std::decay_t <A1>>()) {
161- uint64_t pos;
162- if constexpr (soa::is_filtered_table<std::decay_t <G>>) {
163- pos = groupSelection[position];
164- } else {
165- pos = position;
166+ uint64_t pos;
167+ if constexpr (soa::is_filtered_table<std::decay_t <G>>) {
168+ pos = groupSelection[position];
169+ } else {
170+ pos = position;
171+ }
172+ // generic split
173+ auto selection = sliceInfosUnsorted[index].getSliceFor (pos);
174+ // intersect selections
175+ o2::soa::SelectionVector s;
176+ if (selections[index]->empty ()) {
177+ if (!selection.empty ()) {
178+ std::copy (selection.begin (), selection.end (), std::back_inserter (s));
166179 }
167-
168- if constexpr (!o2::soa::is_smallgroups<std::decay_t <A1>>) {
169- // optimized split
170- if (originalTable.size () == 0 ) {
171- return originalTable;
172- }
173- auto oc = sliceInfos[index].getSliceFor (pos);
174- uint64_t offset = oc.first ;
175- auto count = oc.second ;
176- if constexpr (soa::is_filtered_table<std::decay_t <A1>>) {
177- auto groupedElementsTable = originalTable.asArrowTable ()->Slice (offset, count);
178- if (count == 0 ) {
179- return std::decay_t <A1>{{groupedElementsTable}, soa::SelectionVector{}};
180- }
181-
182- // for each grouping element we need to slice the selection vector
183- auto start_iterator = std::lower_bound (starts[index], selections[index]->end (), offset);
184- auto stop_iterator = std::lower_bound (start_iterator, selections[index]->end (), offset + count);
185- starts[index] = stop_iterator;
186- soa::SelectionVector slicedSelection{start_iterator, stop_iterator};
187- std::transform (slicedSelection.begin (), slicedSelection.end (), slicedSelection.begin (),
188- [&offset](int64_t idx) {
189- return idx - static_cast <int64_t >(offset);
190- });
191-
192- std::decay_t <A1> typedTable{{groupedElementsTable}, std::move (slicedSelection), offset};
193- typedTable.bindInternalIndicesTo (&originalTable);
194- return typedTable;
195-
196- } else {
197- auto groupedElementsTable = originalTable.rawSlice (offset, offset + count - 1 );
198- groupedElementsTable.bindInternalIndicesTo (&originalTable);
199- return groupedElementsTable;
200- }
201- } else {
202- // generic split
203- if constexpr (soa::is_filtered_table<std::decay_t <A1>>) {
204- auto selection = sliceInfosUnsorted[index].getSliceFor (pos);
205- // intersect selections
206- o2::soa::SelectionVector s;
207- if (selections[index]->empty ()) {
208- if (!selection.empty ()) {
209- std::copy (selection.begin (), selection.end (), std::back_inserter (s));
210- }
211- } else {
212- if (!selection.empty ()) {
213- if constexpr (std::decay_t <A1>::applyFilters) {
214- std::set_intersection (selection.begin (), selection.end (), selections[index]->begin (), selections[index]->end (), std::back_inserter (s));
215- } else {
216- std::copy (selection.begin (), selection.end (), std::back_inserter (s));
217- }
218- }
219- }
220- std::decay_t <A1> typedTable{{originalTable.asArrowTable ()}, std::move (s)};
221- typedTable.bindInternalIndicesTo (&originalTable);
222- return typedTable;
180+ } else {
181+ if (!selection.empty ()) {
182+ if constexpr (std::decay_t <A1>::applyFilters) {
183+ std::set_intersection (selection.begin (), selection.end (), selections[index]->begin (), selections[index]->end (), std::back_inserter (s));
223184 } else {
224- throw runtime_error ( " Unsorted grouped table needs to be used with soa::SmallGroups<> " );
185+ std::copy (selection. begin (), selection. end (), std::back_inserter (s) );
225186 }
226187 }
188+ }
189+ std::decay_t <A1> typedTable{{originalTable.asArrowTable ()}, std::move (s)};
190+ typedTable.bindInternalIndicesTo (&originalTable);
191+ return typedTable;
192+ }
193+
194+ template <soa::is_filtered_table A1>
195+ requires (o2::soa::relatedByIndex<std::decay_t <G>, std::decay_t <A1>>() && !soa::is_smallgroups<A1>)
196+ auto prepareArgument ()
197+ {
198+ constexpr auto index = framework::has_type_at_v<A1>(associated_pack_t {});
199+ auto & originalTable = std::get<A1>(*mAt );
200+ if (originalTable.size () == 0 ) {
201+ return originalTable;
202+ }
203+ uint64_t pos;
204+ if constexpr (soa::is_filtered_table<std::decay_t <G>>) {
205+ pos = groupSelection[position];
227206 } else {
228- static_assert (!o2::soa::is_smallgroups<std::decay_t <A1>>, " SmallGroups used with a table that is not related by index to the gouping table" );
207+ pos = position;
208+ }
209+ // optimized split
210+ auto oc = sliceInfos[index].getSliceFor (pos);
211+ uint64_t offset = oc.first ;
212+ auto count = oc.second ;
213+ auto groupedElementsTable = originalTable.asArrowTable ()->Slice (offset, count);
214+ if (count == 0 ) {
215+ return std::decay_t <A1>{{groupedElementsTable}, soa::SelectionVector{}};
216+ }
217+
218+ // for each grouping element we need to slice the selection vector
219+ auto start_iterator = std::lower_bound (starts[index], selections[index]->end (), offset);
220+ auto stop_iterator = std::lower_bound (start_iterator, selections[index]->end (), offset + count);
221+ starts[index] = stop_iterator;
222+ soa::SelectionVector slicedSelection{start_iterator, stop_iterator};
223+ std::transform (slicedSelection.begin (), slicedSelection.end (), slicedSelection.begin (),
224+ [&offset](int64_t idx) {
225+ return idx - static_cast <int64_t >(offset);
226+ });
227+
228+ std::decay_t <A1> typedTable{{groupedElementsTable}, std::move (slicedSelection), offset};
229+ typedTable.bindInternalIndicesTo (&originalTable);
230+ return typedTable;
231+ }
232+
233+ template <soa::is_table A1>
234+ requires (o2::soa::relatedByIndex<std::decay_t <G>, std::decay_t <A1>>() && !soa::is_smallgroups<A1> && !soa::is_filtered_table<A1>)
235+ auto prepareArgument ()
236+ {
237+ constexpr auto index = framework::has_type_at_v<A1>(associated_pack_t {});
238+ auto & originalTable = std::get<A1>(*mAt );
239+ if (originalTable.size () == 0 ) {
229240 return originalTable;
230241 }
242+ uint64_t pos;
243+ if constexpr (soa::is_filtered_table<std::decay_t <G>>) {
244+ pos = groupSelection[position];
245+ } else {
246+ pos = position;
247+ }
248+ // optimized split
249+ auto oc = sliceInfos[index].getSliceFor (pos);
250+ uint64_t offset = oc.first ;
251+ auto count = oc.second ;
252+ auto groupedElementsTable = originalTable.rawSlice (offset, offset + count - 1 );
253+ groupedElementsTable.bindInternalIndicesTo (&originalTable);
254+ return groupedElementsTable;
255+ }
256+
257+ template <soa::is_table A1>
258+ requires (!o2::soa::relatedByIndex<std::decay_t <G>, std::decay_t <A1>>() && !soa::is_smallgroups<A1>)
259+ auto prepareArgument ()
260+ {
261+ return std::get<A1>(*mAt );
231262 }
232263
233264 std::string mIndexColumnName ;
0 commit comments