Project
Loading...
Searching...
No Matches
test_ASoAHelpers.cxx
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
16#include <catch_amalgamated.hpp>
17
18using namespace o2::framework;
19using namespace o2::soa;
20
21namespace test
22{
23DECLARE_SOA_COLUMN_FULL(X, x, int32_t, "x");
24DECLARE_SOA_COLUMN_FULL(Y, y, int32_t, "y");
25DECLARE_SOA_COLUMN_FULL(Z, z, int32_t, "z");
26DECLARE_SOA_COLUMN_FULL(FloatZ, floatZ, float, "floatZ");
27DECLARE_SOA_DYNAMIC_COLUMN(Sum, sum, [](int32_t x, int32_t y) { return x + y; });
28} // namespace test
29
30TEST_CASE("IteratorTuple")
31{
32 TableBuilder builderA;
33 auto rowWriterA = builderA.persist<int32_t, int32_t>({"x", "y"});
34 rowWriterA(0, 0, 0);
35 rowWriterA(0, 1, 0);
36 rowWriterA(0, 2, 0);
37 rowWriterA(0, 3, 0);
38 rowWriterA(0, 4, 0);
39 rowWriterA(0, 5, 0);
40 rowWriterA(0, 6, 0);
41 rowWriterA(0, 7, 0);
42 auto tableA = builderA.finalize();
43 REQUIRE(tableA->num_rows() == 8);
44
45 using TestA = InPlaceTable<0, o2::soa::Index<>, test::X, test::Y>;
46
47 TestA tests{tableA};
48
49 REQUIRE(8 == tests.size());
50
51 TestA::iterator beginIt = tests.begin();
52 REQUIRE(!(static_cast<test::X>(beginIt).getIterator().mCurrentPos == nullptr));
53 REQUIRE(*(static_cast<test::X>(beginIt).getIterator().mCurrentPos) == 0);
54 REQUIRE(beginIt.x() == 0);
55 REQUIRE(beginIt.mRowIndex == 0);
56
57 auto beginIterators = std::make_tuple(beginIt, beginIt);
58 REQUIRE(!(static_cast<test::X>(std::get<0>(beginIterators)).getIterator().mCurrentPos == nullptr));
59 REQUIRE(*(static_cast<test::X>(std::get<0>(beginIterators)).getIterator().mCurrentPos) == 0);
60 REQUIRE(std::get<0>(beginIterators).x() == 0);
61 REQUIRE(!(static_cast<test::X>(std::get<1>(beginIterators)).getIterator().mCurrentPos == nullptr));
62 REQUIRE(*(static_cast<test::X>(std::get<1>(beginIterators)).getIterator().mCurrentPos) == 0);
63 REQUIRE(std::get<1>(beginIterators).x() == 0);
64
65 auto maxIt0 = tests.begin() + 8 - 2 + 1;
66 auto maxIt1 = tests.begin() + 8 - 2 + 1 + 1;
67 auto maxOffset2 = std::make_tuple(maxIt0, maxIt1);
68 REQUIRE(!(static_cast<test::X>(std::get<0>(maxOffset2)).getIterator().mCurrentPos == nullptr));
69 REQUIRE(*(static_cast<test::X>(std::get<0>(maxOffset2)).getIterator().mCurrentPos) == 7);
70 REQUIRE(std::get<0>(maxOffset2).x() == 7);
71 REQUIRE(!(static_cast<test::X>(std::get<1>(maxOffset2)).getIterator().mCurrentPos == nullptr));
72 REQUIRE(*(static_cast<test::X>(std::get<1>(maxOffset2)).getIterator().mCurrentPos) == 8);
73
74 expressions::Filter filter = test::x > 3;
75 auto filtered = Filtered<TestA>{{tests.asArrowTable()}, o2::framework::expressions::createSelection(tests.asArrowTable(), filter)};
76 std::tuple<Filtered<TestA>, Filtered<TestA>> filteredTuple = std::make_tuple(filtered, filtered);
77
78 auto it1 = std::get<0>(filteredTuple).begin();
79 REQUIRE(!(static_cast<test::X>(it1).getIterator().mCurrentPos == nullptr));
80 REQUIRE(*(static_cast<test::X>(it1).getIterator().mCurrentPos) == 4);
81 REQUIRE(static_cast<test::X>(it1).getIterator().mCurrentChunk == 0);
82 auto it2(it1);
83 REQUIRE(!(static_cast<test::X>(it2).getIterator().mCurrentPos == nullptr));
84 REQUIRE(*(static_cast<test::X>(it2).getIterator().mCurrentPos) == 4);
85 REQUIRE(static_cast<test::X>(it2).getIterator().mCurrentChunk == 0);
86 auto it3 = std::get<1>(filteredTuple).begin();
87 REQUIRE(!(static_cast<test::X>(it3).getIterator().mCurrentPos == nullptr));
88 REQUIRE(*(static_cast<test::X>(it3).getIterator().mCurrentPos) == 4);
89 REQUIRE(static_cast<test::X>(it3).getIterator().mCurrentChunk == 0);
90}
91
92TEST_CASE("CombinationsGeneratorConstruction")
93{
94 TableBuilder builderA;
95 auto rowWriterA = builderA.persist<int32_t, int32_t, float>({"x", "y", "floatZ"});
96 rowWriterA(0, 0, 25, -6.0f);
97 rowWriterA(0, 1, 18, 0.0f);
98 rowWriterA(0, 2, 48, 8.0f);
99 rowWriterA(0, 3, 103, 2.0f);
100 rowWriterA(0, 4, 28, -6.0f);
101 rowWriterA(0, 5, 102, 2.0f);
102 rowWriterA(0, 6, 12, 0.0f);
103 rowWriterA(0, 7, 24, -7.0f);
104 auto tableA = builderA.finalize();
105 REQUIRE(tableA->num_rows() == 8);
106
107 TableBuilder builderB;
108 auto rowWriterB = builderB.persist<int32_t>({"x"});
109 rowWriterB(0, 8);
110 rowWriterB(0, 9);
111 rowWriterB(0, 10);
112 rowWriterB(0, 11);
113 auto tableB = builderB.finalize();
114 REQUIRE(tableB->num_rows() == 4);
115
116 using TestA = InPlaceTable<0, o2::soa::Index<>, test::X, test::Y, test::FloatZ>;
117 using TestB = InPlaceTable<0, o2::soa::Index<>, test::X>;
118 using ConcatTest = Concat<TestA, TestB>;
119
120 TestA testsA{tableA};
121 TestB testsB{tableB};
122 ConcatTest concatTests{tableA, tableB};
123 REQUIRE(8 == testsA.size());
124 REQUIRE(12 == concatTests.size());
125
126 // Grouped data:
127 // [3, 5] [0, 4, 7], [1, 6], [2]
128 // Assuming bins intervals: [ , )
129 std::vector<double> yBins{VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 101};
130 std::vector<double> zBins{VARIABLE_WIDTH, -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0};
131
132 ColumnBinningPolicy<test::Y, test::FloatZ> pairBinning{{yBins, zBins}, false};
133
135 REQUIRE(!(static_cast<test::X>(std::get<0>(*(combIt))).getIterator().mCurrentPos == nullptr));
136 REQUIRE(*(static_cast<test::X>(std::get<0>(*(combIt))).getIterator().mCurrentPos) == 0);
137 REQUIRE(static_cast<test::X>(std::get<0>(*(combIt))).getIterator().mCurrentChunk == 0);
138 REQUIRE(!(static_cast<test::X>(std::get<1>(*(combIt))).getIterator().mCurrentPos == nullptr));
139 REQUIRE(*(static_cast<test::X>(std::get<1>(*(combIt))).getIterator().mCurrentPos) == 1);
140 REQUIRE(static_cast<test::X>(std::get<1>(*(combIt))).getIterator().mCurrentChunk == 0);
141
142 auto comb2 = combinations(CombinationsStrictlyUpperIndexPolicy(testsA, testsA));
143
144 static_assert(std::same_as<decltype(comb2.begin()), CombinationsGenerator<CombinationsStrictlyUpperIndexPolicy<TestA, TestA>>::CombinationsIterator>, "Wrong iterator type");
145 static_assert(std::same_as<decltype(*(comb2.begin())), CombinationsStrictlyUpperIndexPolicy<TestA, TestA>::CombinationType&>, "Wrong combination type");
146
147 auto beginCombination = *(comb2.begin());
148 REQUIRE(!(static_cast<test::X>(std::get<0>(beginCombination)).getIterator().mCurrentPos == nullptr));
149 REQUIRE(*(static_cast<test::X>(std::get<0>(beginCombination)).getIterator().mCurrentPos) == 0);
150 REQUIRE(static_cast<test::X>(std::get<0>(beginCombination)).getIterator().mCurrentChunk == 0);
151 REQUIRE(!(static_cast<test::X>(std::get<1>(beginCombination)).getIterator().mCurrentPos == nullptr));
152 REQUIRE(*(static_cast<test::X>(std::get<1>(beginCombination)).getIterator().mCurrentPos) == 1);
153 REQUIRE(static_cast<test::X>(std::get<1>(beginCombination)).getIterator().mCurrentChunk == 0);
154
155 REQUIRE(!(comb2.begin() == comb2.end()));
156
157 auto endCombination = *(comb2.end());
158 REQUIRE(!(static_cast<test::X>(std::get<0>(endCombination)).getIterator().mCurrentPos == nullptr));
159 REQUIRE(*(static_cast<test::X>(std::get<0>(endCombination)).getIterator().mCurrentPos) == 8);
160 REQUIRE(static_cast<test::X>(std::get<0>(endCombination)).getIterator().mCurrentChunk == 0);
161 REQUIRE(!(static_cast<test::X>(std::get<1>(endCombination)).getIterator().mCurrentPos == nullptr));
162 REQUIRE(*(static_cast<test::X>(std::get<1>(endCombination)).getIterator().mCurrentPos) == 8);
163 REQUIRE(static_cast<test::X>(std::get<1>(endCombination)).getIterator().mCurrentChunk == 0);
164
166 auto s1 = o2::framework::expressions::createSelection(testsA.asArrowTable(), filter);
167 auto filtered = Filtered<TestA>{{testsA.asArrowTable()}, s1};
168
170 REQUIRE(!(static_cast<test::X>(std::get<0>(*(combItFiltered))).getIterator().mCurrentPos == nullptr));
171 REQUIRE(*(static_cast<test::X>(std::get<0>(*(combItFiltered))).getIterator().mCurrentPos) == 4);
172 REQUIRE(static_cast<test::X>(std::get<0>(*(combItFiltered))).getIterator().mCurrentChunk == 0);
173 REQUIRE(!(static_cast<test::X>(std::get<1>(*(combItFiltered))).getIterator().mCurrentPos == nullptr));
174 REQUIRE(*(static_cast<test::X>(std::get<1>(*(combItFiltered))).getIterator().mCurrentPos) == 5);
175 REQUIRE(static_cast<test::X>(std::get<1>(*(combItFiltered))).getIterator().mCurrentChunk == 0);
176
177 auto comb2Filter = combinations(CombinationsStrictlyUpperIndexPolicy<TestA, TestA>(), filter, testsA, testsA);
178
179 static_assert(std::same_as<decltype(comb2Filter.begin()), CombinationsGenerator<CombinationsStrictlyUpperIndexPolicy<Filtered<TestA>, Filtered<TestA>>>::CombinationsIterator>, "Wrong iterator type");
180 static_assert(std::same_as<decltype(*(comb2Filter.begin())), CombinationsStrictlyUpperIndexPolicy<Filtered<TestA>, Filtered<TestA>>::CombinationType&>, "Wrong combination type");
181
182 auto beginFilterCombination = *(comb2Filter.begin());
183 REQUIRE(!(static_cast<test::X>(std::get<0>(beginFilterCombination)).getIterator().mCurrentPos == nullptr));
184 REQUIRE(*(static_cast<test::X>(std::get<0>(beginFilterCombination)).getIterator().mCurrentPos) == 4);
185 REQUIRE(static_cast<test::X>(std::get<0>(beginFilterCombination)).getIterator().mCurrentChunk == 0);
186 REQUIRE(!(static_cast<test::X>(std::get<1>(beginFilterCombination)).getIterator().mCurrentPos == nullptr));
187 REQUIRE(*(static_cast<test::X>(std::get<1>(beginFilterCombination)).getIterator().mCurrentPos) == 5);
188 REQUIRE(static_cast<test::X>(std::get<1>(beginFilterCombination)).getIterator().mCurrentChunk == 0);
189
190 REQUIRE(!(comb2Filter.begin() == comb2Filter.end()));
191
192 auto endFilterCombination = *(comb2Filter.end());
193 REQUIRE(!(static_cast<test::X>(std::get<0>(endFilterCombination)).getIterator().mCurrentPos == nullptr));
194 REQUIRE(*(static_cast<test::X>(std::get<0>(endFilterCombination)).getIterator().mCurrentPos) == -1);
195 REQUIRE(static_cast<test::X>(std::get<0>(endFilterCombination)).getIterator().mCurrentChunk == 0);
196 REQUIRE(!(static_cast<test::X>(std::get<1>(endFilterCombination)).getIterator().mCurrentPos == nullptr));
197 REQUIRE(*(static_cast<test::X>(std::get<1>(endFilterCombination)).getIterator().mCurrentPos) == -1);
198 REQUIRE(static_cast<test::X>(std::get<1>(endFilterCombination)).getIterator().mCurrentChunk == 0);
199
200 auto comb2Concat = combinations(CombinationsStrictlyUpperIndexPolicy(concatTests, concatTests));
201
202 static_assert(std::same_as<decltype(comb2Concat.begin()), CombinationsGenerator<CombinationsStrictlyUpperIndexPolicy<ConcatTest, ConcatTest>>::CombinationsIterator>, "Wrong iterator type");
203 static_assert(std::same_as<decltype(*(comb2Concat.begin())), CombinationsStrictlyUpperIndexPolicy<ConcatTest, ConcatTest>::CombinationType&>, "Wrong combination type");
204
205 auto beginConcatCombination = *(comb2Concat.begin());
206 REQUIRE(!(static_cast<test::X>(std::get<0>(beginConcatCombination)).getIterator().mCurrentPos == nullptr));
207 REQUIRE(*(static_cast<test::X>(std::get<0>(beginConcatCombination)).getIterator().mCurrentPos) == 0);
208 REQUIRE(static_cast<test::X>(std::get<0>(beginConcatCombination)).getIterator().mCurrentChunk == 0);
209 REQUIRE(!(static_cast<test::X>(std::get<1>(beginConcatCombination)).getIterator().mCurrentPos == nullptr));
210 REQUIRE(*(static_cast<test::X>(std::get<1>(beginConcatCombination)).getIterator().mCurrentPos) == 1);
211 REQUIRE(static_cast<test::X>(std::get<1>(beginConcatCombination)).getIterator().mCurrentChunk == 0);
212
213 REQUIRE(!(comb2Concat.begin() == comb2Concat.end()));
214
215 // Looks that mCurrentChunk is reset to 0 if an iterator goes too far
216 // (the iterators before the end() have correct chunk numbers)
217 auto endConcatCombination = *(comb2Concat.end());
218 REQUIRE(!(static_cast<test::X>(std::get<0>(endConcatCombination)).getIterator().mCurrentPos == nullptr));
219 REQUIRE(*(static_cast<test::X>(std::get<0>(endConcatCombination)).getIterator().mCurrentPos) == 12);
220 REQUIRE(static_cast<test::X>(std::get<0>(endConcatCombination)).getIterator().mCurrentChunk == 0);
221 REQUIRE(!(static_cast<test::X>(std::get<1>(endConcatCombination)).getIterator().mCurrentPos == nullptr));
222 REQUIRE(*(static_cast<test::X>(std::get<1>(endConcatCombination)).getIterator().mCurrentPos) == 12);
223 REQUIRE(static_cast<test::X>(std::get<1>(endConcatCombination)).getIterator().mCurrentChunk == 0);
224
225 auto comb2Diff = combinations(CombinationsFullIndexPolicy(testsA, testsB));
226
227 static_assert(std::same_as<decltype(comb2Diff.begin()), CombinationsGenerator<CombinationsFullIndexPolicy<TestA, TestB>>::CombinationsIterator>, "Wrong iterator type");
228 static_assert(std::same_as<decltype(*(comb2Diff.begin())), CombinationsFullIndexPolicy<TestA, TestB>::CombinationType&>, "Wrong combination type");
229
230 auto beginDiffCombination = *(comb2Diff.begin());
231 REQUIRE(!(static_cast<test::X>(std::get<0>(beginDiffCombination)).getIterator().mCurrentPos == nullptr));
232 REQUIRE(*(static_cast<test::X>(std::get<0>(beginDiffCombination)).getIterator().mCurrentPos) == 0);
233 REQUIRE(static_cast<test::X>(std::get<0>(beginDiffCombination)).getIterator().mCurrentChunk == 0);
234 REQUIRE(!(static_cast<test::X>(std::get<1>(beginDiffCombination)).getIterator().mCurrentPos == nullptr));
235 REQUIRE(*(static_cast<test::X>(std::get<1>(beginDiffCombination)).getIterator().mCurrentPos) == 0);
236 REQUIRE(static_cast<test::X>(std::get<1>(beginDiffCombination)).getIterator().mCurrentChunk == 0);
237
238 REQUIRE(!(comb2Diff.begin() == comb2Diff.end()));
239
240 auto endDiffCombination = *(comb2Diff.end());
241 REQUIRE(!(static_cast<test::X>(std::get<0>(endDiffCombination)).getIterator().mCurrentPos == nullptr));
242 REQUIRE(*(static_cast<test::X>(std::get<0>(endDiffCombination)).getIterator().mCurrentPos) == 8);
243 REQUIRE(static_cast<test::X>(std::get<0>(endDiffCombination)).getIterator().mCurrentChunk == 0);
244 REQUIRE(!(static_cast<test::X>(std::get<1>(endDiffCombination)).getIterator().mCurrentPos == nullptr));
245 REQUIRE(*(static_cast<test::X>(std::get<1>(endDiffCombination)).getIterator().mCurrentPos) == 4);
246 REQUIRE(static_cast<test::X>(std::get<1>(endDiffCombination)).getIterator().mCurrentChunk == 0);
247
248 // More elements required for a combination than number of elements in the table
249 auto comb2Bad = combinations(CombinationsStrictlyUpperIndexPolicy(testsB, testsB, testsB, testsB, testsB));
250
251 static_assert(std::same_as<decltype(comb2Bad.begin()), CombinationsGenerator<CombinationsStrictlyUpperIndexPolicy<TestB, TestB, TestB, TestB, TestB>>::CombinationsIterator>, "Wrong iterator type");
252 static_assert(std::same_as<decltype(*(comb2Bad.begin())), CombinationsStrictlyUpperIndexPolicy<TestB, TestB, TestB, TestB, TestB>::CombinationType&>, "Wrong combination type");
253
254 auto beginBadCombination = *(comb2Bad.begin());
255 REQUIRE(!(static_cast<test::X>(std::get<0>(beginBadCombination)).getIterator().mCurrentPos == nullptr));
256 REQUIRE(*(static_cast<test::X>(std::get<0>(beginBadCombination)).getIterator().mCurrentPos) == 0);
257 REQUIRE(static_cast<test::X>(std::get<0>(beginBadCombination)).getIterator().mCurrentChunk == 0);
258 REQUIRE(!(static_cast<test::X>(std::get<1>(beginBadCombination)).getIterator().mCurrentPos == nullptr));
259 REQUIRE(*(static_cast<test::X>(std::get<1>(beginBadCombination)).getIterator().mCurrentPos) == 0);
260 REQUIRE(static_cast<test::X>(std::get<1>(beginBadCombination)).getIterator().mCurrentChunk == 0);
261 REQUIRE(!(static_cast<test::X>(std::get<2>(beginBadCombination)).getIterator().mCurrentPos == nullptr));
262 REQUIRE(*(static_cast<test::X>(std::get<2>(beginBadCombination)).getIterator().mCurrentPos) == 0);
263 REQUIRE(static_cast<test::X>(std::get<2>(beginBadCombination)).getIterator().mCurrentChunk == 0);
264 REQUIRE(!(static_cast<test::X>(std::get<3>(beginBadCombination)).getIterator().mCurrentPos == nullptr));
265 REQUIRE(*(static_cast<test::X>(std::get<3>(beginBadCombination)).getIterator().mCurrentPos) == 0);
266 REQUIRE(static_cast<test::X>(std::get<3>(beginBadCombination)).getIterator().mCurrentChunk == 0);
267 REQUIRE(!(static_cast<test::X>(std::get<4>(beginBadCombination)).getIterator().mCurrentPos == nullptr));
268 REQUIRE(*(static_cast<test::X>(std::get<4>(beginBadCombination)).getIterator().mCurrentPos) == 0);
269 REQUIRE(static_cast<test::X>(std::get<4>(beginBadCombination)).getIterator().mCurrentChunk == 0);
270
271 // REQUIRE(comb2Bad.begin() == comb2Bad.end());;
272
273 auto endBadCombination = *(comb2Bad.end());
274 REQUIRE(!(static_cast<test::X>(std::get<0>(endBadCombination)).getIterator().mCurrentPos == nullptr));
275 REQUIRE(*(static_cast<test::X>(std::get<0>(endBadCombination)).getIterator().mCurrentPos) == 4);
276 REQUIRE(static_cast<test::X>(std::get<0>(endBadCombination)).getIterator().mCurrentChunk == 0);
277 REQUIRE(!(static_cast<test::X>(std::get<1>(endBadCombination)).getIterator().mCurrentPos == nullptr));
278 REQUIRE(*(static_cast<test::X>(std::get<1>(endBadCombination)).getIterator().mCurrentPos) == 4);
279 REQUIRE(static_cast<test::X>(std::get<1>(endBadCombination)).getIterator().mCurrentChunk == 0);
280 REQUIRE(!(static_cast<test::X>(std::get<2>(endBadCombination)).getIterator().mCurrentPos == nullptr));
281 REQUIRE(*(static_cast<test::X>(std::get<2>(endBadCombination)).getIterator().mCurrentPos) == 4);
282 REQUIRE(static_cast<test::X>(std::get<2>(endBadCombination)).getIterator().mCurrentChunk == 0);
283 REQUIRE(!(static_cast<test::X>(std::get<3>(endBadCombination)).getIterator().mCurrentPos == nullptr));
284 REQUIRE(*(static_cast<test::X>(std::get<3>(endBadCombination)).getIterator().mCurrentPos) == 4);
285 REQUIRE(static_cast<test::X>(std::get<3>(endBadCombination)).getIterator().mCurrentChunk == 0);
286 REQUIRE(!(static_cast<test::X>(std::get<4>(endBadCombination)).getIterator().mCurrentPos == nullptr));
287 REQUIRE(*(static_cast<test::X>(std::get<4>(endBadCombination)).getIterator().mCurrentPos) == 4);
288 REQUIRE(static_cast<test::X>(std::get<4>(endBadCombination)).getIterator().mCurrentChunk == 0);
289
290 auto combBlock = combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 2, -1, testsA, testsA));
291
292 static_assert(std::same_as<decltype(combBlock.begin()), CombinationsGenerator<CombinationsBlockStrictlyUpperSameIndexPolicy<ColumnBinningPolicy<test::Y, test::FloatZ>, int32_t, TestA, TestA>>::CombinationsIterator>, "Wrong iterator type");
293 static_assert(std::same_as<decltype(*(combBlock.begin())), CombinationsBlockStrictlyUpperSameIndexPolicy<ColumnBinningPolicy<test::Y, test::FloatZ>, int32_t, TestA, TestA>::CombinationType&>, "Wrong combination type");
294
295 auto beginBlockCombination = *(combBlock.begin());
296 REQUIRE(!(static_cast<test::X>(std::get<0>(beginBlockCombination)).getIterator().mCurrentPos == nullptr));
297 REQUIRE(*(static_cast<test::X>(std::get<0>(beginBlockCombination)).getIterator().mCurrentPos) == 0);
298 REQUIRE(static_cast<test::X>(std::get<0>(beginBlockCombination)).getIterator().mCurrentChunk == 0);
299 REQUIRE(!(static_cast<test::X>(std::get<1>(beginBlockCombination)).getIterator().mCurrentPos == nullptr));
300 REQUIRE(*(static_cast<test::X>(std::get<1>(beginBlockCombination)).getIterator().mCurrentPos) == 4);
301 REQUIRE(static_cast<test::X>(std::get<1>(beginBlockCombination)).getIterator().mCurrentChunk == 0);
302
303 REQUIRE(!(combBlock.begin() == combBlock.end()));
304
305 auto endBlockCombination = *(combBlock.end());
306 REQUIRE(!(static_cast<test::X>(std::get<0>(endBlockCombination)).getIterator().mCurrentPos == nullptr));
307 REQUIRE(*(static_cast<test::X>(std::get<0>(endBlockCombination)).getIterator().mCurrentPos) == 8);
308 REQUIRE(static_cast<test::X>(std::get<0>(endBlockCombination)).getIterator().mCurrentChunk == 0);
309 REQUIRE(!(static_cast<test::X>(std::get<1>(endBlockCombination)).getIterator().mCurrentPos == nullptr));
310 REQUIRE(*(static_cast<test::X>(std::get<1>(endBlockCombination)).getIterator().mCurrentPos) == 8);
311 REQUIRE(static_cast<test::X>(std::get<1>(endBlockCombination)).getIterator().mCurrentChunk == 0);
312}
313
314TEST_CASE("Combinations")
315{
316 TableBuilder builderA;
317 auto rowWriterA = builderA.persist<int32_t, int32_t>({"x", "y"});
318 rowWriterA(0, 0, 0);
319 rowWriterA(0, 1, 0);
320 rowWriterA(0, 2, 0);
321 rowWriterA(0, 3, 0);
322 rowWriterA(0, 4, 0);
323 rowWriterA(0, 5, 0);
324 rowWriterA(0, 6, 0);
325 rowWriterA(0, 7, 0);
326 auto tableA = builderA.finalize();
327 REQUIRE(tableA->num_rows() == 8);
328
329 TableBuilder builderB;
330 auto rowWriterB = builderB.persist<int32_t>({"x"});
331 rowWriterB(0, 8);
332 rowWriterB(0, 9);
333 rowWriterB(0, 10);
334 rowWriterB(0, 11);
335 auto tableB = builderB.finalize();
336 REQUIRE(tableB->num_rows() == 4);
337
338 TableBuilder builderC;
339 auto rowWriterC = builderC.persist<int32_t, int32_t, int32_t>({"x", "y", "z"});
340 rowWriterC(0, 12, 0, 0);
341 rowWriterC(0, 13, 0, 0);
342 rowWriterC(0, 14, 0, 0);
343 rowWriterC(0, 15, 0, 0);
344 auto tableC = builderC.finalize();
345 REQUIRE(tableC->num_rows() == 4);
346
347 using TestA = InPlaceTable<0, o2::soa::Index<>, test::X, test::Y>;
348 using TestB = InPlaceTable<0, o2::soa::Index<>, test::X>;
349 using TestC = InPlaceTable<0, o2::soa::Index<>, test::X, test::Y, test::Z>;
350 using ConcatTest = Concat<TestA, TestB>;
351
352 TestA testsA{tableA};
353 TestB testsB{tableB};
354 TestC testsC{tableC};
355 ConcatTest concatTests{tableA, tableB};
356
357 REQUIRE(8 == testsA.size());
358 REQUIRE(4 == testsB.size());
359 REQUIRE(4 == testsC.size());
360 REQUIRE(12 == concatTests.size());
361 int nA = testsA.size();
362 int nB = testsB.size();
363 int nC = testsC.size();
364
365 int count = 0;
366 int i = 0;
367 int j = 1;
368 for (auto& [t0, t1] : combinations(CombinationsStrictlyUpperIndexPolicy(testsA, testsA))) {
369 REQUIRE(t0.x() == i);
370 REQUIRE(t1.x() == j);
371 count++;
372 j++;
373 if (j == nA) {
374 i++;
375 j = i + 1;
376 }
377 }
378 REQUIRE(count == 28);
379
380 expressions::Filter pairsFilter = test::x > 3;
381
382 count = 0;
383 i = 4;
384 j = 5;
385 for (auto& [t0, t1] : combinations(CombinationsStrictlyUpperIndexPolicy<TestA, TestA>(), pairsFilter, testsA, testsA)) {
386 REQUIRE(t0.x() == i);
387 REQUIRE(t1.x() == j);
388 count++;
389 j++;
390 if (j == nA) {
391 i++;
392 j = i + 1;
393 }
394 }
395 REQUIRE(count == 6);
396
397 count = 0;
398 i = 0;
399 j = 1;
400 int k = 2;
401 for (auto& [t0, t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(testsA, testsA, testsA))) {
402 REQUIRE(t0.x() == i);
403 REQUIRE(t1.x() == j);
404 REQUIRE(t2.x() == k);
405 count++;
406 k++;
407 if (k == nA) {
408 if (j == nA - 2) {
409 i++;
410 j = i;
411 }
412 j++;
413 k = j + 1;
414 }
415 }
416 REQUIRE(count == 56);
417
418 expressions::Filter triplesFilter = test::x < 4;
419
420 count = 0;
421 i = 0;
422 j = 1;
423 k = 2;
424 for (auto& [t0, t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(testsA, testsA, testsA), triplesFilter, testsA, testsA, testsA)) {
425 REQUIRE(t0.x() == i);
426 REQUIRE(t1.x() == j);
427 REQUIRE(t2.x() == k);
428 count++;
429 k++;
430 if (k == 4) {
431 if (j == 2) {
432 i++;
433 j = i;
434 }
435 j++;
436 k = j + 1;
437 }
438 }
439 REQUIRE(count == 4);
440
441 int nConcat = concatTests.size();
442
443 count = 0;
444 i = 0;
445 j = 1;
446 for (auto [t0, t1] : combinations(CombinationsStrictlyUpperIndexPolicy(concatTests, concatTests))) {
447 REQUIRE(t0.x() == i);
448 REQUIRE(t1.x() == j);
449 REQUIRE(static_cast<test::X>(t0).getIterator().mCurrentChunk == (i < nA ? 0 : 1));
450 REQUIRE(static_cast<test::X>(t1).getIterator().mCurrentChunk == (j < nA ? 0 : 1));
451 count++;
452 j++;
453 if (j == nConcat) {
454 i++;
455 j = i + 1;
456 }
457 }
458 REQUIRE(count == 66);
459
460 count = 0;
461 i = 0;
462 j = 1;
463 k = 2;
464 for (auto [t0, t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(concatTests, concatTests, concatTests))) {
465 REQUIRE(t0.x() == i);
466 REQUIRE(t1.x() == j);
467 REQUIRE(t2.x() == k);
468 REQUIRE(static_cast<test::X>(t0).getIterator().mCurrentChunk == (i < nA ? 0 : 1));
469 REQUIRE(static_cast<test::X>(t1).getIterator().mCurrentChunk == (j < nA ? 0 : 1));
470 REQUIRE(static_cast<test::X>(t2).getIterator().mCurrentChunk == (k < nA ? 0 : 1));
471 count++;
472 k++;
473 if (k == nConcat) {
474 if (j == nConcat - 2) {
475 i++;
476 j = i;
477 }
478 j++;
479 k = j + 1;
480 }
481 }
482 REQUIRE(count == 220);
483
484 count = 0;
485 i = 0;
486 j = 1;
487 k = 2;
488 int l = 3;
489 int m = 4;
490 for (auto& [t0, t1, t2, t3, t4] : combinations(CombinationsStrictlyUpperIndexPolicy(testsA, testsA, testsA, testsA, testsA))) {
491 REQUIRE(t0.x() == i);
492 REQUIRE(t1.x() == j);
493 REQUIRE(t2.x() == k);
494 REQUIRE(t3.x() == l);
495 REQUIRE(t4.x() == m);
496 count++;
497 m++;
498 if (m == nA) {
499 if (l == nA - 2) {
500 if (k == nA - 3) {
501 if (j == nA - 4) {
502 i++;
503 j = i;
504 }
505 j++;
506 k = j;
507 }
508 k++;
509 l = k;
510 }
511 l++;
512 m = l + 1;
513 }
514 }
515 REQUIRE(count == 56);
516
517 // Combinations shortcut
518 count = 0;
519 i = 0;
520 j = 1;
521 for (auto& [t0, t1] : combinations(testsA, testsA)) {
522 REQUIRE(t0.x() == i);
523 REQUIRE(t1.x() == j);
524 count++;
525 j++;
526 if (j == nA) {
527 i++;
528 j = i + 1;
529 }
530 }
531 REQUIRE(count == 28);
532
533 count = 0;
534 i = 4;
535 j = 5;
536 for (auto& [t0, t1] : combinations(pairsFilter, testsA, testsA)) {
537 REQUIRE(t0.x() == i);
538 REQUIRE(t1.x() == j);
539 count++;
540 j++;
541 if (j == nA) {
542 i++;
543 j = i + 1;
544 }
545 }
546 REQUIRE(count == 6);
547
548 count = 0;
549 i = 0;
550 j = 0 + nA;
551 for (auto& [t0, t1] : combinations(testsA, testsB)) {
552 REQUIRE(t0.x() == i);
553 REQUIRE(t1.x() == j);
554 count++;
555 j++;
556 if (j == nA + nB) {
557 i++;
558 j = nA + i;
559 }
560 }
561 REQUIRE(count == 10);
562
563 // Different tables of different size
564 count = 0;
565 i = 0;
566 j = 0 + nA;
567 for (auto& [t0, t1] : combinations(CombinationsFullIndexPolicy(testsA, testsB))) {
568 REQUIRE(t0.x() == i);
569 REQUIRE(t1.x() == j);
570 count++;
571 j++;
572 if (j == 0 + nA + nB) {
573 i++;
574 j = 0 + nA;
575 }
576 }
577 REQUIRE(count == 32);
578
579 count = 0;
580 i = 0 + nA;
581 j = 0;
582 for (auto& [t0, t1] : combinations(CombinationsFullIndexPolicy(testsB, testsA))) {
583 REQUIRE(t0.x() == i);
584 REQUIRE(t1.x() == j);
585 count++;
586 j++;
587 if (j == 0 + nA) {
588 i++;
589 j = 0;
590 }
591 }
592 REQUIRE(count == 32);
593
594 count = 0;
595 i = 0;
596 j = 0 + nA;
597 k = 0 + nA + nB;
598 for (auto& [t0, t1, t2] : combinations(CombinationsFullIndexPolicy(testsA, testsB, testsC))) {
599 REQUIRE(t0.x() == i);
600 REQUIRE(t1.x() == j);
601 REQUIRE(t2.x() == k);
602 count++;
603 k++;
604 if (k == nA + nB + nC) {
605 if (j == nA + nB - 1) {
606 i++;
607 j = 0 + nA;
608 } else {
609 j++;
610 }
611 k = 0 + nA + nB;
612 }
613 }
614 REQUIRE(count == 128);
615
616 count = 0;
617 i = 0 + nA + nB;
618 j = 0 + nA;
619 k = 0;
620 for (auto& [t0, t1, t2] : combinations(CombinationsFullIndexPolicy(testsC, testsB, testsA))) {
621 REQUIRE(t0.x() == i);
622 REQUIRE(t1.x() == j);
623 REQUIRE(t2.x() == k);
624 count++;
625 k++;
626 if (k == nA) {
627 if (j == nA + nB - 1) {
628 i++;
629 j = 0 + nA;
630 } else {
631 j++;
632 }
633 k = 0;
634 }
635 }
636 REQUIRE(count == 128);
637
638 count = 0;
639 i = 0;
640 j = 0 + nA;
641 for (auto& [t0, t1] : combinations(CombinationsUpperIndexPolicy(testsA, testsB))) {
642 REQUIRE(t0.x() == i);
643 REQUIRE(t1.x() == j);
644 count++;
645 j++;
646 if (j == 0 + nA + nB) {
647 i++;
648 j = nA + i;
649 }
650 }
651 REQUIRE(count == 10);
652
653 count = 0;
654 i = 0 + nA;
655 j = 0;
656 for (auto& [t0, t1] : combinations(CombinationsUpperIndexPolicy(testsB, testsA))) {
657 REQUIRE(t0.x() == i);
658 REQUIRE(t1.x() == j);
659 count++;
660 j++;
661 if (j == 0 + nA) {
662 i++;
663 j = -nA + i;
664 }
665 }
666 REQUIRE(count == 26);
667
668 count = 0;
669 i = 0;
670 j = 0 + nA;
671 k = 0 + nA + nB;
672 for (auto& [t0, t1, t2] : combinations(CombinationsUpperIndexPolicy(testsA, testsB, testsC))) {
673 REQUIRE(t0.x() == i);
674 REQUIRE(t1.x() == j);
675 REQUIRE(t2.x() == k);
676 count++;
677 k++;
678 if (k == nA + nB + nC) {
679 if (j == nA + nB - 1) {
680 i++;
681 j = nA + i;
682 } else {
683 j++;
684 }
685 k = nB + j;
686 }
687 }
688 REQUIRE(count == 20);
689
690 count = 0;
691 i = 0 + nA + nB;
692 j = 0 + nA;
693 k = 0;
694 for (auto& [t0, t1, t2] : combinations(CombinationsUpperIndexPolicy(testsC, testsB, testsA))) {
695 REQUIRE(t0.x() == i);
696 REQUIRE(t1.x() == j);
697 REQUIRE(t2.x() == k);
698 count++;
699 k++;
700 if (k == nA) {
701 if (j == nA + nB - 1) {
702 i++;
703 j = -nB + i;
704 } else {
705 j++;
706 }
707 k = -nA + j;
708 }
709 }
710 REQUIRE(count == 60);
711
712 count = 0;
713 i = 0;
714 j = 0 + nA + 1;
715 for (auto& [t0, t1] : combinations(CombinationsStrictlyUpperIndexPolicy(testsA, testsB))) {
716 REQUIRE(t0.x() == i);
717 REQUIRE(t1.x() == j);
718 count++;
719 j++;
720 if (j == 0 + nA + nB) {
721 i++;
722 j = nA + i + 1;
723 }
724 }
725 REQUIRE(count == 6);
726
727 count = 0;
728 i = 0 + nA;
729 j = 1;
730 for (auto& [t0, t1] : combinations(CombinationsStrictlyUpperIndexPolicy(testsB, testsA))) {
731 REQUIRE(t0.x() == i);
732 REQUIRE(t1.x() == j);
733 count++;
734 j++;
735 if (j == 0 + nA) {
736 i++;
737 j = -nA + i + 1;
738 }
739 }
740 REQUIRE(count == 18);
741
742 count = 0;
743 i = 0;
744 j = 0 + nA + 1;
745 k = 0 + nA + nB + 2;
746 for (auto& [t0, t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(testsA, testsB, testsC))) {
747 REQUIRE(t0.x() == i);
748 REQUIRE(t1.x() == j);
749 REQUIRE(t2.x() == k);
750 count++;
751 k++;
752 if (k == nA + nB + nC) {
753 if (j == nA + nB - 2) {
754 i++;
755 j = nA + i + 1;
756 } else {
757 j++;
758 }
759 k = nB + j + 1;
760 }
761 }
762 REQUIRE(count == 4);
763
764 count = 0;
765 i = 0 + nA + nB;
766 j = 0 + nA + 1;
767 k = 2;
768 for (auto& [t0, t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(testsC, testsB, testsA))) {
769 REQUIRE(t0.x() == i);
770 REQUIRE(t1.x() == j);
771 REQUIRE(t2.x() == k);
772 count++;
773 k++;
774 if (k == nA) {
775 if (j == nA + nB - 2) {
776 i++;
777 j = -nB + i + 1;
778 } else {
779 j++;
780 }
781 k = -nA + j + 1;
782 }
783 }
784 REQUIRE(count == 16);
785}
786
787TEST_CASE("BreakingCombinations")
788{
789 TableBuilder builderA;
790 auto rowWriterA = builderA.persist<int32_t, int32_t>({"x", "y"});
791 rowWriterA(0, 0, 0);
792 rowWriterA(0, 1, 0);
793 rowWriterA(0, 2, 0);
794 rowWriterA(0, 3, 0);
795 rowWriterA(0, 4, 0);
796 rowWriterA(0, 5, 0);
797 rowWriterA(0, 6, 0);
798 rowWriterA(0, 7, 0);
799 auto tableA = builderA.finalize();
800 REQUIRE(tableA->num_rows() == 8);
801
802 using TestA = InPlaceTable<0, o2::soa::Index<>, test::X, test::Y>;
803
804 TestA testsA{tableA};
805
806 REQUIRE(8 == testsA.size());
807 int nA = testsA.size();
808
809 int count = 0;
810 int i = 0;
811 int j = 1;
812 for (auto& [t0, t1] : combinations(testsA, testsA)) {
813 REQUIRE(t0.x() == i);
814 REQUIRE(t1.x() == j);
815 count++;
816 j++;
817 if (j == nA) {
818 i++;
819 j = i + 1;
820 }
821 if (t0.x() == 4) {
822 continue;
823 REQUIRE(!(true == true));
824 }
825 REQUIRE(!(t0.x() == 4));
826 }
827 REQUIRE(count == 28);
828
829 count = 0;
830 i = 0;
831 j = 1;
832 for (auto& [t0, t1] : combinations(testsA, testsA)) {
833 if (t0.x() == 4) {
834 break;
835 REQUIRE(!(true == true));
836 }
837 REQUIRE(t0.x() < 4);
838 REQUIRE(t0.x() == i);
839 REQUIRE(t1.x() == j);
840 count++;
841 j++;
842 if (j == nA) {
843 i++;
844 j = i + 1;
845 }
846 }
847 REQUIRE(count == 22);
848}
849
850TEST_CASE("SmallTableCombinations")
851{
852 TableBuilder builderA;
853 auto rowWriterA = builderA.persist<int32_t, int32_t>({"x", "y"});
854 rowWriterA(0, 0, 0);
855 rowWriterA(0, 1, 0);
856 auto tableA = builderA.finalize();
857 REQUIRE(tableA->num_rows() == 2);
858
859 TableBuilder builderB;
860 auto rowWriterB = builderB.persist<int32_t>({"x"});
861 rowWriterB(0, 8);
862 rowWriterB(0, 9);
863 rowWriterB(0, 10);
864 auto tableB = builderB.finalize();
865 REQUIRE(tableB->num_rows() == 3);
866
867 using TestA = InPlaceTable<0, o2::soa::Index<>, test::X, test::Y>;
868 using TestB = InPlaceTable<0, o2::soa::Index<>, test::X>;
869
870 TestA testsA{tableA};
871 TestB testsB{tableB};
872
873 REQUIRE(2 == testsA.size());
874 REQUIRE(3 == testsB.size());
875 [[maybe_unused]] int nA = testsA.size();
876 [[maybe_unused]] int nB = testsB.size();
877
878 int count = 0;
879 int i = 0;
880 int j = 1;
881 for (auto& [t0, t1] : combinations(testsA, testsA)) {
882 REQUIRE(t0.x() == i);
883 REQUIRE(t1.x() == j);
884 count++;
885 }
886 REQUIRE(count == 1);
887
888 count = 0;
889 i = 8;
890 j = 9;
891 int k = 10;
892 for (auto& [t0, t1, t2] : combinations(testsB, testsB, testsB)) {
893 REQUIRE(t0.x() == i);
894 REQUIRE(t1.x() == j);
895 REQUIRE(t2.x() == k);
896 count++;
897 }
898 REQUIRE(count == 1);
899
900 count = 0;
901 for (auto& [t0, t1, t2] : combinations(testsA, testsA, testsA)) {
902 count++;
903 }
904 REQUIRE(count == 0);
905}
906
907TEST_CASE("BlockCombinations")
908{
909 TableBuilder builderA;
910 auto rowWriterA = builderA.persist<int32_t, int32_t, float>({"x", "y", "floatZ"});
911 rowWriterA(0, 0, 25, -6.0f);
912 rowWriterA(0, 1, 18, 0.0f);
913 rowWriterA(0, 2, 48, 8.0f);
914 rowWriterA(0, 3, 103, 2.0f);
915 rowWriterA(0, 4, 28, -6.0f);
916 rowWriterA(0, 5, 102, 2.0f);
917 rowWriterA(0, 6, 12, 0.0f);
918 rowWriterA(0, 7, 24, -7.0f);
919 rowWriterA(0, 8, 41, 8.0f);
920 rowWriterA(0, 9, 49, 8.0f);
921 auto tableA = builderA.finalize();
922 REQUIRE(tableA->num_rows() == 10);
923
924 using TestA = InPlaceTable<0, o2::soa::Index<>, test::X, test::Y, test::FloatZ>;
925 TestA testA{tableA};
926 REQUIRE(10 == testA.size());
927
928 TableBuilder builderAHalf;
929 auto rowWriterAHalf = builderAHalf.persist<int32_t, int32_t, float>({"x", "y", "floatZ"});
930 rowWriterAHalf(0, 0, 25, -6.0f);
931 rowWriterAHalf(0, 1, 18, 0.0f);
932 rowWriterAHalf(0, 2, 48, 8.0f);
933 rowWriterAHalf(0, 3, 103, 2.0f);
934 rowWriterAHalf(0, 4, 28, -6.0f);
935 auto tableAHalf = builderAHalf.finalize();
936 REQUIRE(tableAHalf->num_rows() == 5);
937
938 TestA testAHalf{tableAHalf};
939 REQUIRE(5 == testAHalf.size());
940
941 // Grouped data:
942 // [3, 5] [0, 4, 7], [1, 6], [2, 8, 9]
943 // Assuming bins intervals: [ , )
944 std::vector<double> yBins{VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 101};
945 std::vector<double> zBins{VARIABLE_WIDTH, -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0};
946
947 ColumnBinningPolicy<test::Y, test::FloatZ> pairBinning{{yBins, zBins}, false};
948 ColumnBinningPolicy<test::Y, test::FloatZ> pairBinningNoOverflows{{yBins, zBins}, true};
949
950 // 2, 3, 5, 8, 9 have overflows in testA
951 std::vector<std::tuple<int32_t, int32_t>> expectedFullPairsNoOverflows{
952 {0, 0}, {0, 4}, {4, 0}, {4, 4}, {4, 7}, {7, 4}, {7, 7}, {1, 1}, {1, 6}, {6, 1}, {6, 6}};
953 size_t count = 0;
954 for (auto& [c0, c1] : combinations(CombinationsBlockFullIndexPolicy(pairBinningNoOverflows, 1, -1, testA, testA))) {
955 REQUIRE(c0.x() == std::get<0>(expectedFullPairsNoOverflows[count]));
956 REQUIRE(c1.x() == std::get<1>(expectedFullPairsNoOverflows[count]));
957 count++;
958 }
959 REQUIRE(count == expectedFullPairsNoOverflows.size());
960
961 std::vector<std::tuple<int32_t, int32_t>> expectedFullPairs{
962 {0, 0}, {0, 4}, {0, 7}, {4, 0}, {7, 0}, {4, 4}, {4, 7}, {7, 4}, {7, 7}, {1, 1}, {1, 6}, {6, 1}, {6, 6}, {3, 3}, {3, 5}, {5, 3}, {5, 5}, {2, 2}, {2, 8}, {2, 9}, {8, 2}, {9, 2}, {8, 8}, {8, 9}, {9, 8}, {9, 9}};
963 count = 0;
964 for (auto& [c0, c1] : combinations(CombinationsBlockFullIndexPolicy(pairBinning, 2, -1, testA, testA))) {
965 REQUIRE(c0.x() == std::get<0>(expectedFullPairs[count]));
966 REQUIRE(c1.x() == std::get<1>(expectedFullPairs[count]));
967 count++;
968 }
969 REQUIRE(count == expectedFullPairs.size());
970
971 std::vector<std::tuple<int32_t, int32_t, int32_t>> expectedFullTriples{
972 {0, 0, 0}, {0, 0, 4}, {0, 0, 7}, {0, 4, 0}, {0, 4, 4}, {0, 4, 7}, {0, 7, 0}, {0, 7, 4}, {0, 7, 7}, {4, 0, 0}, {4, 0, 4}, {4, 0, 7}, {7, 0, 0}, {7, 0, 4}, {7, 0, 7}, {4, 4, 0}, {4, 7, 0}, {7, 4, 0}, {7, 7, 0}, {4, 4, 4}, {4, 4, 7}, {4, 7, 4}, {4, 7, 7}, {7, 4, 4}, {7, 4, 7}, {7, 7, 4}, {7, 7, 7}, {1, 1, 1}, {1, 1, 6}, {1, 6, 1}, {1, 6, 6}, {6, 1, 1}, {6, 1, 6}, {6, 6, 1}, {6, 6, 6}, {3, 3, 3}, {3, 3, 5}, {3, 5, 3}, {3, 5, 5}, {5, 3, 3}, {5, 3, 5}, {5, 5, 3}, {5, 5, 5}, {2, 2, 2}, {2, 2, 8}, {2, 2, 9}, {2, 8, 2}, {2, 8, 8}, {2, 8, 9}, {2, 9, 2}, {2, 9, 8}, {2, 9, 9}, {8, 2, 2}, {8, 2, 8}, {8, 2, 9}, {9, 2, 2}, {9, 2, 8}, {9, 2, 9}, {8, 8, 2}, {8, 9, 2}, {9, 8, 2}, {9, 9, 2}, {8, 8, 8}, {8, 8, 9}, {8, 9, 8}, {8, 9, 9}, {9, 8, 8}, {9, 8, 9}, {9, 9, 8}, {9, 9, 9}};
973 count = 0;
974 for (auto& [c0, c1, c2] : combinations(CombinationsBlockFullIndexPolicy(pairBinning, 2, -1, testA, testA, testA))) {
975 REQUIRE(c0.x() == std::get<0>(expectedFullTriples[count]));
976 REQUIRE(c1.x() == std::get<1>(expectedFullTriples[count]));
977 REQUIRE(c2.x() == std::get<2>(expectedFullTriples[count]));
978 count++;
979 }
980 REQUIRE(count == expectedFullTriples.size());
981
982 std::vector<std::tuple<int32_t, int32_t>> expectedUpperPairs{
983 {0, 0}, {0, 4}, {0, 7}, {4, 4}, {4, 7}, {7, 7}, {1, 1}, {1, 6}, {6, 6}, {3, 3}, {3, 5}, {5, 5}, {2, 2}, {2, 8}, {2, 9}, {8, 8}, {8, 9}, {9, 9}};
984 count = 0;
985 for (auto& [c0, c1] : combinations(CombinationsBlockUpperIndexPolicy(pairBinning, 2, -1, testA, testA))) {
986 REQUIRE(c0.x() == std::get<0>(expectedUpperPairs[count]));
987 REQUIRE(c1.x() == std::get<1>(expectedUpperPairs[count]));
988 count++;
989 }
990 REQUIRE(count == expectedUpperPairs.size());
991
992 std::vector<std::tuple<int32_t, int32_t, int32_t>> expectedUpperTriples{
993 {0, 0, 0}, {0, 0, 4}, {0, 4, 4}, {4, 4, 4}, {4, 4, 7}, {4, 7, 7}, {7, 7, 7}, {1, 1, 1}, {1, 1, 6}, {1, 6, 6}, {6, 6, 6}, {3, 3, 3}, {3, 3, 5}, {3, 5, 5}, {5, 5, 5}, {2, 2, 2}, {2, 2, 8}, {2, 8, 8}, {8, 8, 8}, {8, 8, 9}, {8, 9, 9}, {9, 9, 9}};
994 count = 0;
995 for (auto& [c0, c1, c2] : combinations(CombinationsBlockUpperIndexPolicy(pairBinning, 1, -1, testA, testA, testA))) {
996 REQUIRE(c0.x() == std::get<0>(expectedUpperTriples[count]));
997 REQUIRE(c1.x() == std::get<1>(expectedUpperTriples[count]));
998 REQUIRE(c2.x() == std::get<2>(expectedUpperTriples[count]));
999 count++;
1000 }
1001 REQUIRE(count == expectedUpperTriples.size());
1002
1003 std::vector<std::tuple<int32_t, int32_t, int32_t, int32_t, int32_t>> expectedUpperFives{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 4}, {0, 0, 0, 0, 7}, {0, 0, 0, 4, 4}, {0, 0, 0, 4, 7}, {0, 0, 0, 7, 7}, {0, 0, 4, 4, 4}, {0, 0, 4, 4, 7}, {0, 0, 4, 7, 7}, {0, 0, 7, 7, 7}, {0, 4, 4, 4, 4}, {0, 4, 4, 4, 7}, {0, 4, 4, 7, 7}, {0, 4, 7, 7, 7}, {0, 7, 7, 7, 7}, {4, 4, 4, 4, 4}, {4, 4, 4, 4, 7}, {4, 4, 4, 7, 7}, {4, 4, 7, 7, 7}, {4, 7, 7, 7, 7}, {7, 7, 7, 7, 7}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 6}, {1, 1, 1, 6, 6}, {1, 1, 6, 6, 6}, {1, 6, 6, 6, 6}, {6, 6, 6, 6, 6}, {3, 3, 3, 3, 3}, {3, 3, 3, 3, 5}, {3, 3, 3, 5, 5}, {3, 3, 5, 5, 5}, {3, 5, 5, 5, 5}, {5, 5, 5, 5, 5}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 8}, {2, 2, 2, 2, 9}, {2, 2, 2, 8, 8}, {2, 2, 2, 8, 9}, {2, 2, 2, 9, 9}, {2, 2, 8, 8, 8}, {2, 2, 8, 8, 9}, {2, 2, 8, 9, 9}, {2, 2, 9, 9, 9}, {2, 8, 8, 8, 8}, {2, 8, 8, 8, 9}, {2, 8, 8, 9, 9}, {2, 8, 9, 9, 9}, {2, 9, 9, 9, 9}, {8, 8, 8, 8, 8}, {8, 8, 8, 8, 9}, {8, 8, 8, 9, 9}, {8, 8, 9, 9, 9}, {8, 9, 9, 9, 9}, {9, 9, 9, 9, 9}};
1004 count = 0;
1005 for (auto& [c0, c1, c2, c3, c4] : combinations(CombinationsBlockUpperIndexPolicy(pairBinning, 2, -1, testA, testA, testA, testA, testA))) {
1006 REQUIRE(c0.x() == std::get<0>(expectedUpperFives[count]));
1007 REQUIRE(c1.x() == std::get<1>(expectedUpperFives[count]));
1008 REQUIRE(c2.x() == std::get<2>(expectedUpperFives[count]));
1009 REQUIRE(c3.x() == std::get<3>(expectedUpperFives[count]));
1010 REQUIRE(c4.x() == std::get<4>(expectedUpperFives[count]));
1011 count++;
1012 }
1013 REQUIRE(count == expectedUpperFives.size());
1014
1015 std::vector<std::tuple<int32_t, int32_t>> expectedStrictlyUpperPairsSmaller{
1016 {0, 4}, {4, 7}, {1, 6}, {3, 5}, {2, 8}, {8, 9}};
1017 count = 0;
1018 for (auto& [c0, c1] : combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 1, -1, testA, testA))) {
1019 REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperPairsSmaller[count]));
1020 REQUIRE(c1.x() == std::get<1>(expectedStrictlyUpperPairsSmaller[count]));
1021 count++;
1022 }
1023 REQUIRE(count == expectedStrictlyUpperPairsSmaller.size());
1024
1025 std::vector<std::tuple<int32_t, int32_t>> expectedStrictlyUpperPairs{
1026 {0, 4}, {0, 7}, {4, 7}, {1, 6}, {3, 5}, {2, 8}, {2, 9}, {8, 9}};
1027 count = 0;
1028 for (auto& [c0, c1] : combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 2, -1, testA, testA))) {
1029 REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperPairs[count]));
1030 REQUIRE(c1.x() == std::get<1>(expectedStrictlyUpperPairs[count]));
1031 count++;
1032 }
1033 REQUIRE(count == expectedStrictlyUpperPairs.size());
1034
1035 std::vector<std::tuple<int32_t, int32_t, int32_t>> expectedStrictlyUpperTriples{
1036 {0, 4, 7}, {2, 8, 9}};
1037 count = 0;
1038 for (auto& [c0, c1, c2] : combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 2, -1, testA, testA, testA))) {
1039 REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperTriples[count]));
1040 REQUIRE(c1.x() == std::get<1>(expectedStrictlyUpperTriples[count]));
1041 REQUIRE(c2.x() == std::get<2>(expectedStrictlyUpperTriples[count]));
1042 count++;
1043 }
1044 REQUIRE(count == expectedStrictlyUpperTriples.size());
1045
1046 count = 0;
1047 for (auto& [c0, c1, c2, c3, c4] : combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 1, -1, testA, testA, testA, testA, testA))) {
1048 count++;
1049 }
1050 REQUIRE(count == 0);
1051
1052 // Different tables of different size
1053 std::vector<std::tuple<int32_t, int32_t>> expectedFullPairsFirstSmaller{
1054 {0, 0}, {0, 4}, {4, 0}, {4, 4}, {4, 7}, {1, 1}, {1, 6}, {3, 3}, {3, 5}, {2, 2}, {2, 8}};
1055 count = 0;
1056 for (auto& [x0, x1] : combinations(CombinationsBlockFullIndexPolicy(pairBinning, 1, -1, testAHalf, testA))) {
1057 REQUIRE(x0.x() == std::get<0>(expectedFullPairsFirstSmaller[count]));
1058 REQUIRE(x1.x() == std::get<1>(expectedFullPairsFirstSmaller[count]));
1059 count++;
1060 }
1061 REQUIRE(count == expectedFullPairsFirstSmaller.size());
1062
1063 count = 0;
1064 std::vector<std::tuple<int32_t, int32_t>> expectedFullPairsSecondSmaller{
1065 {0, 0}, {0, 4}, {4, 0}, {4, 4}, {7, 4}, {1, 1}, {6, 1}, {3, 3}, {5, 3}, {2, 2}, {8, 2}};
1066 for (auto& [x0, x1] : combinations(CombinationsBlockFullIndexPolicy(pairBinning, 1, -1, testA, testAHalf))) {
1067 REQUIRE(x0.x() == std::get<0>(expectedFullPairsSecondSmaller[count]));
1068 REQUIRE(x1.x() == std::get<1>(expectedFullPairsSecondSmaller[count]));
1069 count++;
1070 }
1071 REQUIRE(count == expectedFullPairsSecondSmaller.size());
1072
1073 std::vector<std::tuple<int32_t, int32_t>> expectedUpperPairsFirstSmaller{
1074 {0, 0}, {0, 4}, {4, 4}, {4, 7}, {1, 1}, {1, 6}, {3, 3}, {3, 5}, {2, 2}, {2, 8}};
1075 count = 0;
1076 for (auto& [x0, x1] : combinations(CombinationsBlockUpperIndexPolicy(pairBinning, 1, -1, testAHalf, testA))) {
1077 REQUIRE(x0.x() == std::get<0>(expectedUpperPairsFirstSmaller[count]));
1078 REQUIRE(x1.x() == std::get<1>(expectedUpperPairsFirstSmaller[count]));
1079 count++;
1080 }
1081 REQUIRE(count == expectedUpperPairsFirstSmaller.size());
1082
1083 count = 0;
1084 std::vector<std::tuple<int32_t, int32_t>> expectedUpperPairsSecondSmaller{
1085 {0, 0}, {0, 4}, {4, 4}, {1, 1}, {3, 3}, {2, 2}};
1086 for (auto& [x0, x1] : combinations(CombinationsBlockUpperIndexPolicy(pairBinning, 1, -1, testA, testAHalf))) {
1087 REQUIRE(x0.x() == std::get<0>(expectedUpperPairsSecondSmaller[count]));
1088 REQUIRE(x1.x() == std::get<1>(expectedUpperPairsSecondSmaller[count]));
1089 count++;
1090 }
1091 REQUIRE(count == expectedUpperPairsSecondSmaller.size());
1092
1093 // Using same index combinations for better performance
1094 count = 0;
1095 for (auto& [c0, c1] : combinations(CombinationsBlockFullSameIndexPolicy(pairBinning, 2, -1, testA, testA))) {
1096 REQUIRE(c0.x() == std::get<0>(expectedFullPairs[count]));
1097 REQUIRE(c1.x() == std::get<1>(expectedFullPairs[count]));
1098 count++;
1099 }
1100 REQUIRE(count == expectedFullPairs.size());
1101
1102 count = 0;
1103 for (auto& [c0, c1, c2] : combinations(CombinationsBlockFullSameIndexPolicy(pairBinning, 2, -1, testA, testA, testA))) {
1104 REQUIRE(c0.x() == std::get<0>(expectedFullTriples[count]));
1105 REQUIRE(c1.x() == std::get<1>(expectedFullTriples[count]));
1106 REQUIRE(c2.x() == std::get<2>(expectedFullTriples[count]));
1107 count++;
1108 }
1109 REQUIRE(count == expectedFullTriples.size());
1110
1111 count = 0;
1112 for (auto& [c0, c1] : combinations(CombinationsBlockUpperSameIndexPolicy(pairBinning, 2, -1, testA, testA))) {
1113 REQUIRE(c0.x() == std::get<0>(expectedUpperPairs[count]));
1114 REQUIRE(c1.x() == std::get<1>(expectedUpperPairs[count]));
1115 count++;
1116 }
1117 REQUIRE(count == expectedUpperPairs.size());
1118
1119 count = 0;
1120 for (auto& [c0, c1, c2] : combinations(CombinationsBlockUpperSameIndexPolicy(pairBinning, 1, -1, testA, testA, testA))) {
1121 REQUIRE(c0.x() == std::get<0>(expectedUpperTriples[count]));
1122 REQUIRE(c1.x() == std::get<1>(expectedUpperTriples[count]));
1123 REQUIRE(c2.x() == std::get<2>(expectedUpperTriples[count]));
1124 count++;
1125 }
1126 REQUIRE(count == expectedUpperTriples.size());
1127
1128 count = 0;
1129 for (auto& [c0, c1, c2, c3, c4] : combinations(CombinationsBlockUpperSameIndexPolicy(pairBinning, 2, -1, testA, testA, testA, testA, testA))) {
1130 REQUIRE(c0.x() == std::get<0>(expectedUpperFives[count]));
1131 REQUIRE(c1.x() == std::get<1>(expectedUpperFives[count]));
1132 REQUIRE(c2.x() == std::get<2>(expectedUpperFives[count]));
1133 REQUIRE(c3.x() == std::get<3>(expectedUpperFives[count]));
1134 REQUIRE(c4.x() == std::get<4>(expectedUpperFives[count]));
1135 count++;
1136 }
1137 REQUIRE(count == expectedUpperFives.size());
1138
1139 count = 0;
1140 for (auto& [c0, c1] : selfCombinations(pairBinning, 2, -1, testA, testA)) {
1141 REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperPairs[count]));
1142 REQUIRE(c1.x() == std::get<1>(expectedStrictlyUpperPairs[count]));
1143 count++;
1144 }
1145 REQUIRE(count == expectedStrictlyUpperPairs.size());
1146
1147 count = 0;
1148 for (auto& [c0, c1, c2] : selfCombinations(pairBinning, 2, -1, testA, testA, testA)) {
1149 REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperTriples[count]));
1150 REQUIRE(c1.x() == std::get<1>(expectedStrictlyUpperTriples[count]));
1151 REQUIRE(c2.x() == std::get<2>(expectedStrictlyUpperTriples[count]));
1152 count++;
1153 }
1154 REQUIRE(count == expectedStrictlyUpperTriples.size());
1155
1156 count = 0;
1157 for (auto& [c0, c1, c2, c3, c4] : selfCombinations(pairBinning, 2, -1, testA, testA, testA, testA, testA)) {
1158 count++;
1159 }
1160 REQUIRE(count == 0);
1161
1162 // Testing bin calculations for triple binning
1163 // Grouped data:
1164 // [3, 5] [0, 4], [7], [1, 6], [2], [8, 9]
1165 // Assuming bins intervals: [ , )
1166 std::vector<double> xBins{VARIABLE_WIDTH, 0, 7, 10};
1167 ColumnBinningPolicy<test::X, test::Y, test::FloatZ> tripleBinning{{xBins, yBins, zBins}, false};
1168 ColumnBinningPolicy<test::X, test::Y, test::FloatZ> tripleBinningNoOverflows{{xBins, yBins, zBins}, true};
1169
1170 // 2, 3, 5, 8, 9 have overflows in testA
1171 std::vector<std::tuple<int32_t, int32_t>> expectedFullPairsTripleBinningNoOverflows{
1172 {0, 0}, {0, 4}, {4, 0}, {4, 4}, {7, 7}, {1, 1}, {1, 6}, {6, 1}, {6, 6}};
1173 count = 0;
1174 for (auto& [c0, c1] : combinations(CombinationsBlockFullIndexPolicy(tripleBinningNoOverflows, 1, -1, testA, testA))) {
1175 REQUIRE(c0.x() == std::get<0>(expectedFullPairsTripleBinningNoOverflows[count]));
1176 REQUIRE(c1.x() == std::get<1>(expectedFullPairsTripleBinningNoOverflows[count]));
1177 count++;
1178 }
1179 REQUIRE(count == expectedFullPairsTripleBinningNoOverflows.size());
1180
1181 std::vector<std::tuple<int32_t, int32_t>> expectedFullPairsTripleBinning{
1182 {0, 0}, {0, 4}, {4, 0}, {4, 4}, {7, 7}, {1, 1}, {1, 6}, {6, 1}, {6, 6}, {3, 3}, {3, 5}, {5, 3}, {5, 5}, {2, 2}, {8, 8}, {8, 9}, {9, 8}, {9, 9}};
1183 count = 0;
1184 for (auto& [c0, c1] : combinations(CombinationsBlockFullIndexPolicy(tripleBinning, 2, -1, testA, testA))) {
1185 REQUIRE(c0.x() == std::get<0>(expectedFullPairsTripleBinning[count]));
1186 REQUIRE(c1.x() == std::get<1>(expectedFullPairsTripleBinning[count]));
1187 count++;
1188 }
1189 REQUIRE(count == expectedFullPairsTripleBinning.size());
1190}
1191
1192TEST_CASE("CombinationsHelpers")
1193{
1194 TableBuilder builderA;
1195 auto rowWriterA = builderA.persist<int32_t, int32_t>({"x", "y"});
1196 rowWriterA(0, 0, 0);
1197 rowWriterA(0, 1, 0);
1198 rowWriterA(0, 2, 0);
1199 rowWriterA(0, 3, 0);
1200 rowWriterA(0, 4, 0);
1201 rowWriterA(0, 5, 0);
1202 rowWriterA(0, 6, 0);
1203 rowWriterA(0, 7, 0);
1204 auto tableA = builderA.finalize();
1205 REQUIRE(tableA->num_rows() == 8);
1206
1207 using TestA = InPlaceTable<0, o2::soa::Index<>, test::X, test::Y>;
1208
1209 TestA testsA{tableA};
1210
1211 REQUIRE(8 == testsA.size());
1212 int nA = testsA.size();
1213
1214 size_t count = 0;
1215 int i = 0;
1216 int j = 1;
1217 for (auto& [t0, t1] : pairCombinations(testsA)) {
1218 REQUIRE(t0.x() == i);
1219 REQUIRE(t1.x() == j);
1220 count++;
1221 j++;
1222 if (j == nA) {
1223 i++;
1224 j = i + 1;
1225 }
1226 }
1227 REQUIRE(count == 28);
1228
1229 count = 0;
1230 i = 0;
1231 j = 1;
1232 int k = 2;
1233 for (auto& [t0, t1, t2] : tripleCombinations(testsA)) {
1234 REQUIRE(t0.x() == i);
1235 REQUIRE(t1.x() == j);
1236 REQUIRE(t2.x() == k);
1237 count++;
1238 k++;
1239 if (k == nA) {
1240 if (j == nA - 2) {
1241 i++;
1242 j = i;
1243 }
1244 j++;
1245 k = j + 1;
1246 }
1247 }
1248 REQUIRE(count == 56);
1249
1250 TableBuilder builderB;
1251 auto rowWriterB = builderB.persist<int32_t, int32_t, float>({"x", "y", "floatZ"});
1252 rowWriterB(0, 0, 25, -6.0f);
1253 rowWriterB(0, 1, 18, 0.0f);
1254 rowWriterB(0, 2, 48, 8.0f);
1255 rowWriterB(0, 3, 103, 2.0f);
1256 rowWriterB(0, 4, 28, -6.0f);
1257 rowWriterB(0, 5, 102, 2.0f);
1258 rowWriterB(0, 6, 12, 0.0f);
1259 rowWriterB(0, 7, 24, -7.0f);
1260 rowWriterB(0, 8, 41, 8.0f);
1261 rowWriterB(0, 9, 49, 8.0f);
1262 auto tableB = builderB.finalize();
1263 REQUIRE(tableB->num_rows() == 10);
1264
1265 using TestB = o2::soa::InPlaceTable<0, o2::soa::Index<>, test::X, test::Y, test::FloatZ>;
1266 TestB testB{tableB};
1267 REQUIRE(10 == testB.size());
1268
1269 // Grouped data:
1270 // [3, 5] [0, 4, 7], [1, 6], [2, 8, 9]
1271 // Assuming bins intervals: [ , )
1272 std::vector<double> yBins{VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 101};
1273 std::vector<double> zBins{VARIABLE_WIDTH, -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0};
1274
1275 ColumnBinningPolicy<test::Y, test::FloatZ> pairBinning{{yBins, zBins}, false};
1276
1277 std::vector<std::tuple<int32_t, int32_t>> expectedStrictlyUpperPairs{
1278 {0, 4}, {0, 7}, {4, 7}, {1, 6}, {3, 5}, {2, 8}, {2, 9}, {8, 9}};
1279 count = 0;
1280 for (auto& [c0, c1] : selfPairCombinations(pairBinning, 2, -1, testB)) {
1281 REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperPairs[count]));
1282 REQUIRE(c1.x() == std::get<1>(expectedStrictlyUpperPairs[count]));
1283 count++;
1284 }
1285 REQUIRE(count == expectedStrictlyUpperPairs.size());
1286
1287 std::vector<std::tuple<int32_t, int32_t, int32_t>> expectedStrictlyUpperTriples{
1288 {0, 4, 7}, {2, 8, 9}};
1289 count = 0;
1290 for (auto& [c0, c1, c2] : selfTripleCombinations(pairBinning, 2, -1, testB)) {
1291 REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperTriples[count]));
1292 REQUIRE(c1.x() == std::get<1>(expectedStrictlyUpperTriples[count]));
1293 REQUIRE(c2.x() == std::get<2>(expectedStrictlyUpperTriples[count]));
1294 count++;
1295 }
1296 REQUIRE(count == expectedStrictlyUpperTriples.size());
1297}
1298
1299TEST_CASE("ConstructorsWithoutTables")
1300{
1301 using TestA = InPlaceTable<0, o2::soa::Index<>, test::X, test::Y>;
1302 NoBinningPolicy<test::Y> noBinning;
1303
1304 size_t count = 0;
1305 for (auto& [t0, t1] : pairCombinations<TestA>()) {
1306 count++;
1307 }
1308 REQUIRE(count == 0);
1309
1310 count = 0;
1311 for (auto& [t0, t1, t2] : tripleCombinations<TestA>()) {
1312 count++;
1313 }
1314 REQUIRE(count == 0);
1315
1316 count = 0;
1317 for (auto& [c0, c1] : selfPairCombinations<NoBinningPolicy<test::Y>, int, TestA>(noBinning, 2, -1)) {
1318 count++;
1319 }
1320 REQUIRE(count == 0);
1321
1322 count = 0;
1323 for (auto& [c0, c1, c2] : selfTripleCombinations<NoBinningPolicy<test::Y>, int, TestA>(noBinning, 2, -1)) {
1324 count++;
1325 }
1326 REQUIRE(count == 0);
1327}
1328
1329TEST_CASE("BlockCombinationsCounters")
1330{
1331 TableBuilder builderA;
1332 auto rowWriterA = builderA.persist<int32_t, int32_t, float>({"x", "y", "floatZ"});
1333 rowWriterA(0, 0, 25, -1.3f);
1334 rowWriterA(0, 1, 21, -1.8f);
1335 rowWriterA(0, 2, 48, 2.0f);
1336 rowWriterA(0, 3, 26, -2.0f);
1337 rowWriterA(0, 4, 28, -1.5f);
1338 rowWriterA(0, 5, 42, 2.0f);
1339 rowWriterA(0, 6, 47, 2.5f);
1340 rowWriterA(0, 7, 24, -1.8f);
1341 rowWriterA(0, 8, 41, 1.3f);
1342 rowWriterA(0, 9, 49, 1.8f);
1343 auto tableA = builderA.finalize();
1344 REQUIRE(tableA->num_rows() == 10);
1345
1346 using TestA = InPlaceTable<0, o2::soa::Index<>, test::X, test::Y, test::FloatZ>;
1347 TestA testA{tableA};
1348 REQUIRE(10 == testA.size());
1349
1350 // Grouped data:
1351 // [0, 1, 3, 4, 7], [2, 5, 6, 8, 9]
1352 // Assuming bins intervals: [ , )
1353 std::vector<double> yBins{VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 101};
1354 std::vector<double> zBins{VARIABLE_WIDTH, -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0};
1355
1356 ColumnBinningPolicy<test::Y, test::FloatZ> pairBinning{{yBins, zBins}, false};
1357
1358 // Window size < category size
1359 std::vector<int> expectedCollisionsInBinSmallWindow{3, 3, 2, 1, 3, 3, 2, 1};
1360 int countFirst = 0;
1361 int previousEvent = -1;
1362 auto combGenSmallWindow = combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 3, -1, testA, testA));
1363 for (auto it = combGenSmallWindow.begin(); it != combGenSmallWindow.end(); it++) {
1364 auto& [c0, c1] = *it;
1365 REQUIRE(it.isNewWindow() == (previousEvent != c0.x()));
1366 if (it.isNewWindow()) {
1367 REQUIRE(it.currentWindowNeighbours() == expectedCollisionsInBinSmallWindow[countFirst]);
1368 countFirst++;
1369 }
1370 previousEvent = c0.index();
1371 }
1372
1373 // Window size = category size
1374 std::vector<int> expectedCollisionsInBinEqualWindow{4, 3, 2, 1, 4, 3, 2, 1};
1375 countFirst = 0;
1376 previousEvent = -1;
1377 auto combGenEqualWindow = combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 4, -1, testA, testA));
1378 for (auto it = combGenEqualWindow.begin(); it != combGenEqualWindow.end(); it++) {
1379 auto& [c0, c1] = *it;
1380 REQUIRE(it.isNewWindow() == (previousEvent != c0.x()));
1381 if (it.isNewWindow()) {
1382 REQUIRE(it.currentWindowNeighbours() == expectedCollisionsInBinEqualWindow[countFirst]);
1383 countFirst++;
1384 }
1385 previousEvent = c0.index();
1386 }
1387
1388 // Window size = category size
1389 std::vector<int> expectedCollisionsInBinBigWindow{4, 3, 2, 1, 4, 3, 2, 1};
1390 countFirst = 0;
1391 previousEvent = -1;
1392 auto combGenBigWindow = combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 5, -1, testA, testA));
1393 for (auto it = combGenBigWindow.begin(); it != combGenBigWindow.end(); it++) {
1394 auto& [c0, c1] = *it;
1395 REQUIRE(it.isNewWindow() == (previousEvent != c0.x()));
1396 if (it.isNewWindow()) {
1397 REQUIRE(it.currentWindowNeighbours() == expectedCollisionsInBinBigWindow[countFirst]);
1398 countFirst++;
1399 }
1400 previousEvent = c0.index();
1401 }
1402}
#define DECLARE_SOA_DYNAMIC_COLUMN(_Name_, _Getter_,...)
Definition ASoA.h:2967
#define DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_)
Definition ASoA.h:2285
int32_t i
bool const GPUTPCGMMerger::trackCluster * c1
bool const GPUTPCGMMerger::trackCluster const clcomparestruct * c2
uint32_t j
Definition RawData.h:0
auto persist(std::array< char const *, sizeof...(ARGS)+1 > const &columnNames)
std::shared_ptr< arrow::Table > finalize()
float sum(float s, o2::dcs::DataPointValue v)
Definition dcs-ccdb.cxx:39
GLint GLenum GLint x
Definition glcorearb.h:403
const GLfloat * m
Definition glcorearb.h:4066
GLint GLsizei count
Definition glcorearb.h:399
GLuint GLfloat GLfloat GLfloat x1
Definition glcorearb.h:5034
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition glcorearb.h:5034
GLint y
Definition glcorearb.h:270
GLuint GLfloat x0
Definition glcorearb.h:5034
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition glcorearb.h:1308
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
Definition glcorearb.h:5034
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition glcorearb.h:5034
gandiva::Selection createSelection(std::shared_ptr< arrow::Table > const &table, Filter const &expression)
Function for creating gandiva selection from our internal filter tree.
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
constexpr double VARIABLE_WIDTH
auto pairCombinations()
auto selfTripleCombinations(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider)
auto tripleCombinations()
auto combinations(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, const T2s &... tables)
auto selfCombinations(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider, const T2s &... tables)
auto selfPairCombinations(const BP &binningPolicy, int categoryNeighbours, const T1 &outsider)
FIXME: do not use data model tables.
A struct, containing the root of the expression tree.
typename CombinationsIndexPolicyBase< Ts... >::CombinationType CombinationType
typename CombinationsIndexPolicyBase< Ts... >::CombinationType CombinationType
TEST_CASE("IteratorTuple")