Project
Loading...
Searching...
No Matches
GroupedCombinations.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#ifndef FRAMEWORK_GROUPEDCOMBINATIONS_H
13#define FRAMEWORK_GROUPEDCOMBINATIONS_H
14
17#include "Framework/Pack.h"
19#include <optional>
20
21namespace o2::framework
22{
23
24// Create an instance of a tuple interleaved from given tuples
25template <typename... T1s, typename... T2s, std::size_t... Is>
26auto interleaveTuplesImpl(std::tuple<T1s...>& t1, std::tuple<T2s...>& t2, std::index_sequence<Is...>)
27{
28 return std::tuple_cat(std::make_tuple(std::get<Is>(t1), std::get<Is>(t2))...);
29}
30
31template <typename... T1s, typename... T2s>
32auto interleaveTuples(std::tuple<T1s...>& t1, std::tuple<T2s...>& t2)
33{
34 return interleaveTuplesImpl(t1, t2, std::index_sequence_for<T1s...>());
35}
36
37template <typename T, typename G>
38using is_index_to_g_t = typename std::conditional<o2::soa::is_binding_compatible_v<G, typename T::binding_t>(), std::true_type, std::false_type>::type;
39
40template <typename G, typename A>
42{
43 using external_index_columns_pack = typename A::external_index_columns_t;
44 using selected_indices_t = selected_pack_multicondition<is_index_to_g_t, pack<G>, external_index_columns_pack>;
45 static_assert(pack_size(selected_indices_t{}) == 1, "No matching index column from associated to grouping");
46 using index_column_t = pack_head_t<selected_indices_t>;
47 return expressions::BindingNode{index_column_t::mLabel, o2::framework::TypeIdHelpers::uniqueId<typename index_column_t::column_t>(), expressions::selectArrowType<typename index_column_t::type>()};
48}
49
50template <typename T1, typename GroupingPolicy, typename BP, typename G, typename... As>
53 using g_t = G;
55
56 template <typename... Ts>
57 static consteval bool compatible(framework::pack<Ts...> p)
58 {
59 return (framework::has_type<As>(p) && ...);
60 }
61
63
65 public:
69 using iterator_category = std::forward_iterator_tag;
70
71 GroupedIterator(const GroupingPolicy& groupingPolicy, SliceCache* cache_)
72 : GroupingPolicy(groupingPolicy), mIndexColumns{getMatchingIndexNode<G, As>()...}, cache{cache_}
73 {
74 }
75 template <typename... T2s>
76 GroupedIterator(const GroupingPolicy& groupingPolicy, const G& grouping, const std::tuple<T2s...>& associated, SliceCache* cache_)
77 : GroupingPolicy(groupingPolicy),
78 mGrouping{std::make_shared<G>(std::vector{grouping.asArrowTable()})},
79 mAssociated{std::make_shared<std::tuple<As...>>(std::make_tuple(std::get<has_type_at<As>(pack<T2s...>{})>(associated)...))},
80 mIndexColumns{getMatchingIndexNode<G, As>()...},
81 cache{cache_}
82 {
83 if constexpr (soa::is_filtered_table<std::decay_t<G>>) {
84 mGrouping = std::make_shared<G>(std::vector{grouping.asArrowTable()}, grouping.getSelectedRows());
85 } else {
86 mGrouping = std::make_shared<G>(std::vector{grouping.asArrowTable()});
87 }
88 setMultipleGroupingTables<sizeof...(As)>(grouping);
89 if (!this->mIsEnd) {
90 setCurrentGroupedCombination();
91 }
92 }
93
96 ~GroupedIterator() = default;
97
98 template <typename... T2s>
99 void setTables(const G& grouping, const std::tuple<T2s...>& associated)
100 {
102 mGrouping = std::make_shared<G>(std::vector{grouping.asArrowTable()}, grouping.getSelectedRows());
103 } else {
104 mGrouping = std::make_shared<G>(std::vector{grouping.asArrowTable()});
105 }
106 mAssociated = std::make_shared<std::tuple<As...>>(std::make_tuple(std::get<has_type_at_v<As>(pack<T2s...>{})>(associated)...));
107 setMultipleGroupingTables<sizeof...(As)>(grouping);
108 if (!this->mIsEnd) {
109 setCurrentGroupedCombination();
110 }
111 }
112
113 template <std::size_t N, typename T, typename... Args>
114 void setMultipleGroupingTables(const T& param, const Args&... args)
115 {
116 if constexpr (N == 1) {
117 GroupingPolicy::setTables(param, args...);
118 } else {
119 setMultipleGroupingTables<N - 1>(param, param, args...);
120 }
121 }
122
124 {
125 GroupingPolicy::moveToEnd();
126 }
127
128 // prefix increment
130 {
131 if (!this->mIsEnd) {
132 this->addOne();
133 setCurrentGroupedCombination();
134 }
135 return *this;
136 }
137 // postfix increment
139 {
140 GroupedIterator copy(*this);
141 operator++();
142 return copy;
143 }
144 // return reference
146 {
147 return *mCurrentGrouped;
148 }
149 bool operator==(const GroupedIterator& rh) const
150 {
151 return (this->mIsEnd && rh.mIsEnd) || (this->mCurrent == rh.mCurrent);
152 }
153 bool operator!=(const GroupedIterator& rh) const
154 {
155 return !(*this == rh);
156 }
157
158 private:
159 std::tuple<As...> getAssociatedTables()
160 {
161 return doGetAssociatedTables(std::make_index_sequence<sizeof...(As)>());
162 }
163
164 template <std::size_t... Is>
165 std::tuple<As...> doGetAssociatedTables(std::index_sequence<Is...>)
166 {
167 return std::make_tuple(getAssociatedTable<Is>()...);
168 }
169
170 template <std::size_t I>
171 auto getAssociatedTable()
172 {
173 uint64_t ind = *std::get<0>(std::get<I>(this->mCurrent).getIndices());
174 if (std::get<I>(*mAssociated).size() == 0) {
175 return std::get<I>(*mAssociated);
176 }
177 return std::get<I>(*mAssociated).sliceByCached(mIndexColumns[I], ind, *cache);
178 }
179
180 void setCurrentGroupedCombination()
181 {
182 if (!this->mIsEnd) {
183 auto& currentGrouping = GroupingPolicy::mCurrent;
184 mSlices.emplace(getAssociatedTables());
185 mCurrentGrouped.emplace(interleaveTuples(currentGrouping, *mSlices));
186 }
187 }
188
189 std::array<expressions::BindingNode, sizeof...(As)> mIndexColumns;
190 std::shared_ptr<G> mGrouping;
191 std::shared_ptr<std::tuple<As...>> mAssociated;
192 std::optional<std::tuple<As...>> mSlices;
193 std::optional<GroupedIteratorType> mCurrentGrouped;
194 SliceCache* cache = nullptr;
195 };
196
199
201 {
202 return iterator(mBegin);
203 }
204 inline iterator end()
205 {
206 return iterator(mEnd);
207 }
208 inline const_iterator begin() const
209 {
210 return iterator(mBegin);
211 }
212 inline const_iterator end() const
213 {
214 return iterator(mEnd);
215 }
216
217 GroupedCombinationsGenerator(const BP& binningPolicy, int catNeighbours, const T1& outsider, SliceCache* cache)
218 : mBegin(GroupingPolicy(binningPolicy, catNeighbours, outsider), cache),
219 mEnd(GroupingPolicy(binningPolicy, catNeighbours, outsider), cache) {}
220 template <typename... T2s>
221 GroupedCombinationsGenerator(const BP& binningPolicy, int catNeighbours, const T1& outsider, const G& grouping, const std::tuple<T2s...>& associated, SliceCache* cache)
222 : GroupedCombinationsGenerator(binningPolicy, catNeighbours, outsider, cache)
223 {
224 setTables(grouping, associated);
225 }
229
230 template <typename... T2s>
231 void setTables(const G& grouping, const std::tuple<T2s...>& associated)
232 {
233 mBegin.setTables(grouping, associated);
234 mEnd.setTables(grouping, associated);
235 mEnd.moveToEnd();
236 }
237
238 private:
239 iterator mBegin;
240 iterator mEnd;
241};
242
243template <typename T>
244concept is_combinations_generator = requires(T t) {
245 typename T::GroupedIterator;
246 &T::begin;
247 &T::end;
248};
249
250// Aliases for 2-particle correlations
251// 'Pair' and 'Triple' can be used for same kind pair/triple, too, just specify the same type twice
252template <typename G, typename A1, typename A2, typename BP, typename T1 = int, typename GroupingPolicy = o2::soa::CombinationsBlockStrictlyUpperSameIndexPolicy<BP, T1, G, G>>
254template <typename G, typename A, typename BP, typename T1 = int, typename GroupingPolicy = o2::soa::CombinationsBlockStrictlyUpperSameIndexPolicy<BP, T1, G, G>>
256
257// Aliases for 3-particle correlations
258template <typename G, typename A1, typename A2, typename A3, typename BP, typename T1 = int, typename GroupingPolicy = o2::soa::CombinationsBlockStrictlyUpperSameIndexPolicy<BP, T1, G, G, G>>
260template <typename G, typename A, typename BP, typename T1 = int, typename GroupingPolicy = o2::soa::CombinationsBlockStrictlyUpperSameIndexPolicy<BP, T1, G, G, G>>
262
263} // namespace o2::framework
264#endif // FRAMEWORK_GROUPEDCOMBINATIONS_H_
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLenum GLfloat param
Definition glcorearb.h:271
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition glcorearb.h:5034
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
auto interleaveTuplesImpl(std::tuple< T1s... > &t1, std::tuple< T2s... > &t2, std::index_sequence< Is... >)
decltype(interleave_pack(P1{}, P2{})) interleaved_pack_t
Definition Pack.h:99
decltype(sequence_to_pack< T >(std::make_index_sequence< N >())) repeated_type_pack_t
Definition Pack.h:352
typename std::conditional< o2::soa::is_binding_compatible_v< G, typename T::binding_t >(), std::true_type, std::false_type >::type is_index_to_g_t
std::decay_t< decltype(select_pack< Condition >(pack<>{}, Pack{}, CondPack{}))> selected_pack_multicondition
Definition Pack.h:181
expressions::BindingNode getMatchingIndexNode()
auto interleaveTuples(std::tuple< T1s... > &t1, std::tuple< T2s... > &t2)
constexpr std::size_t pack_size(pack< Ts... > const &)
template function to determine number of types in a pack
Definition Pack.h:28
typename pack_element< 0, T >::type pack_head_t
Definition Pack.h:59
decltype(pack_to_tuple(P{})) pack_to_tuple_t
Definition Pack.h:343
Defining DataPointCompositeObject explicitly as copiable.
GroupedIterator(const GroupingPolicy &groupingPolicy, SliceCache *cache_)
void setTables(const G &grouping, const std::tuple< T2s... > &associated)
void setMultipleGroupingTables(const T &param, const Args &... args)
GroupedIterator & operator=(GroupedIterator const &)=default
GroupedIterator(const GroupingPolicy &groupingPolicy, const G &grouping, const std::tuple< T2s... > &associated, SliceCache *cache_)
GroupedCombinationsGenerator(const BP &binningPolicy, int catNeighbours, const T1 &outsider, const G &grouping, const std::tuple< T2s... > &associated, SliceCache *cache)
GroupedCombinationsGenerator(GroupedCombinationsGenerator const &)=default
GroupedCombinationsGenerator & operator=(GroupedCombinationsGenerator const &)=default
GroupedCombinationsGenerator(const BP &binningPolicy, int catNeighbours, const T1 &outsider, SliceCache *cache)
void setTables(const G &grouping, const std::tuple< T2s... > &associated)
pack_to_tuple_t< interleaved_pack_t< repeated_type_pack_t< typename G::iterator, sizeof...(As)>, pack< As... > > > GroupedIteratorType
static consteval bool compatible(framework::pack< Ts... > p)
An expression tree node corresponding to a column binding.