From 67e83a5a04135bfecb167563b05dedb6e2758caa Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 5 Oct 2026 16:02:06 +0200 Subject: [PATCH] DPL Analysis: binning policies always drop out-of-range values BinningPolicyBase took an ignoreOverflows flag. With it false, values outside the outermost edges of an axis got bins of their own instead of being mapped to -1 and dropped by groupTable(). Nothing used it. Across O2 and O2Physics the only callers passing false were five sites in test_ASoAHelpers.cxx, i.e. the test of the feature itself; no analysis ever selected it. For event mixing it is the wrong behaviour anyway, since it pairs collisions that the vertex or centrality cut excluded on purpose. The path was also subtly inconsistent: once one axis overflowed, the remaining axes restarted their edge search one index too high, so an underflow on a later axis was binned as that axis's first real bin. Drop the flag. getBin() keeps a single path, getOverflowShift() and mIgnoreOverflows go away, and getBinsCount() is just the edge count minus the dummy VARIABLE_WIDTH entry and the dropped out-of-range bin. If per-axis overflow bins are ever genuinely wanted, a BinningPolicyWithOverflow subclass is the way to add them back: a separate type cannot be confused with this one at a call site, which a boolean could. In the test, the two policies that differed only in the flag collapse into one, and the expectations lose the rows that fall outside the axes (2, 3, 5, 8 and 9 of testA). The surviving categories [0, 4, 7] and [1, 6] are unchanged, so the remaining tuples are exactly the old ones restricted to those rows. The whole o2-test-framework-core suite passes, 258 cases. --- .../Core/include/Framework/BinningPolicy.h | 133 ++++++------------ Framework/Core/test/benchmark_EventMixing.cxx | 4 +- Framework/Core/test/test_ASoAHelpers.cxx | 66 ++++----- 3 files changed, 67 insertions(+), 136 deletions(-) diff --git a/Framework/Core/include/Framework/BinningPolicy.h b/Framework/Core/include/Framework/BinningPolicy.h index f4ea6885192e4..405eef0adf6ff 100644 --- a/Framework/Core/include/Framework/BinningPolicy.h +++ b/Framework/Core/include/Framework/BinningPolicy.h @@ -41,7 +41,14 @@ inline void expandConstantBinning(std::vector const& bins, std::vector struct BinningPolicyBase { - BinningPolicyBase(std::array, N> bins, bool ignoreOverflows = true) : mBins(bins), mIgnoreOverflows(ignoreOverflows) + /// Values outside the outermost edges of any axis are dropped: getBin() maps them + /// to -1, which groupTable() treats as the outsider category. Giving them bins of + /// their own used to be selectable per instance, but no analysis ever did, and for + /// event mixing it is the wrong default anyway -- it pairs collisions that the + /// vertex or centrality cut deliberately excluded. If it is ever genuinely wanted, + /// add a BinningPolicyWithOverflow rather than a flag, so the two numberings cannot + /// be confused at a call site. + BinningPolicyBase(std::array, N> bins) : mBins(bins) { static_assert(N <= 3, "No default binning for more than 3 columns, you need to implement a binning class yourself"); for (int i = 0; i < N; i++) { @@ -54,104 +61,54 @@ struct BinningPolicyBase { { static_assert(sizeof...(Ts) == N, "There must be the same number of binning axes and data values/columns"); + // mBins[d][0] is a dummy VARIABLE_WIDTH marker and mBins[d][1] is the lower edge, + // so the first candidate edge is 2. A value below the lower edge, or above the + // last one, puts the row outside the binning altogether. unsigned int i = 2, j = 2, k = 2; - if (this->mIgnoreOverflows) { - // underflow - if (std::get<0>(data) < this->mBins[0][1]) { // mBins[0][0] is a dummy VARIABLE_WIDTH + + if (std::get<0>(data) < this->mBins[0][1]) { + return -1; + } + if constexpr (N > 1) { + if (std::get<1>(data) < this->mBins[1][1]) { return -1; } - if constexpr (N > 1) { - if (std::get<1>(data) < this->mBins[1][1]) { // mBins[1][0] is a dummy VARIABLE_WIDTH - return -1; - } - } - if constexpr (N > 2) { - if (std::get<2>(data) < this->mBins[2][1]) { // mBins[2][0] is a dummy VARIABLE_WIDTH - return -1; - } + } + if constexpr (N > 2) { + if (std::get<2>(data) < this->mBins[2][1]) { + return -1; } - } else { - i = 1; - j = 1; - k = 1; } for (; i < this->mBins[0].size(); i++) { if (std::get<0>(data) < this->mBins[0][i]) { - - if constexpr (N > 1) { - for (; j < this->mBins[1].size(); j++) { - if (std::get<1>(data) < this->mBins[1][j]) { - - if constexpr (N > 2) { - for (; k < this->mBins[2].size(); k++) { - if (std::get<2>(data) < this->mBins[2][k]) { - return getBinAt(i, j, k); - } - } - if (this->mIgnoreOverflows) { - return -1; - } - } - - // overflow for mBins[2] only - return getBinAt(i, j, k); - } - } - - if (this->mIgnoreOverflows) { - return -1; - } - - // overflow for mBins[1] only - if constexpr (N > 2) { - for (k = 2; k < this->mBins[2].size(); k++) { - if (std::get<2>(data) < this->mBins[2][k]) { - return getBinAt(i, j, k); - } - } - } - } - - // overflow for mBins[2] and mBins[1] - return getBinAt(i, j, k); + break; } } - - if (this->mIgnoreOverflows) { - // overflow + if (i == this->mBins[0].size()) { return -1; } - - // overflow for mBins[0] only if constexpr (N > 1) { - for (j = 2; j < this->mBins[1].size(); j++) { + for (; j < this->mBins[1].size(); j++) { if (std::get<1>(data) < this->mBins[1][j]) { - - if constexpr (N > 2) { - for (k = 2; k < this->mBins[2].size(); k++) { - if (std::get<2>(data) < this->mBins[2][k]) { - return getBinAt(i, j, k); - } - } - } - - // overflow for mBins[0] and mBins[2] - return getBinAt(i, j, k); + break; } } + if (j == this->mBins[1].size()) { + return -1; + } } - - // overflow for mBins[0] and mBins[1] if constexpr (N > 2) { - for (k = 2; k < this->mBins[2].size(); k++) { + for (; k < this->mBins[2].size(); k++) { if (std::get<2>(data) < this->mBins[2][k]) { - return getBinAt(i, j, k); + break; } } + if (k == this->mBins[2].size()) { + return -1; + } } - // overflow for all bins return getBinAt(i, j, k); } @@ -195,18 +152,15 @@ struct BinningPolicyBase { } std::array, N> mBins; - bool mIgnoreOverflows; private: - // We substract 1 to account for VARIABLE_WIDTH in the bins vector - // We substract second 1 if we omit values below minima (underflow, mapped to -1) - // Otherwise we add 1 and we get the number of bins including those below and over the outer edges + // Two are subtracted: one for the dummy VARIABLE_WIDTH at mBins[d][0], one because + // values below the first edge are dropped rather than given a bin of their own. int getBinAt(unsigned int iRaw, unsigned int jRaw, unsigned int kRaw) const { - int shiftBinsWithoutOverflow = getOverflowShift(); - unsigned int i = iRaw - 1 - shiftBinsWithoutOverflow; - unsigned int j = jRaw - 1 - shiftBinsWithoutOverflow; - unsigned int k = kRaw - 1 - shiftBinsWithoutOverflow; + unsigned int i = iRaw - 2; + unsigned int j = jRaw - 2; + unsigned int k = kRaw - 2; auto xBinsCount = getXBinsCount(); if constexpr (N == 1) { return i; @@ -219,15 +173,10 @@ struct BinningPolicyBase { } } - int getOverflowShift() const - { - return mIgnoreOverflows ? 1 : -1; - } - // Note: Overflow / underflow bin -1 is not included int getBinsCount(std::vector const& bins) const { - return bins.size() - 1 - getOverflowShift(); + return bins.size() - 2; } }; @@ -236,7 +185,7 @@ struct FlexibleBinningPolicy; template struct FlexibleBinningPolicy, Ts...> : BinningPolicyBase { - FlexibleBinningPolicy(std::tuple const& lambdaPtrs, std::array, sizeof...(Ts)> bins, bool ignoreOverflows = true) : BinningPolicyBase(bins, ignoreOverflows), mBinningFunctions{lambdaPtrs} + FlexibleBinningPolicy(std::tuple const& lambdaPtrs, std::array, sizeof...(Ts)> bins) : BinningPolicyBase(bins), mBinningFunctions{lambdaPtrs} { } @@ -279,7 +228,7 @@ struct FlexibleBinningPolicy, Ts...> : BinningPolicyBase struct ColumnBinningPolicy : BinningPolicyBase { - ColumnBinningPolicy(std::array, sizeof...(Ts)> bins, bool ignoreOverflows = true) : BinningPolicyBase(bins, ignoreOverflows) + ColumnBinningPolicy(std::array, sizeof...(Ts)> bins) : BinningPolicyBase(bins) { } diff --git a/Framework/Core/test/benchmark_EventMixing.cxx b/Framework/Core/test/benchmark_EventMixing.cxx index 0e7e6839ee35e..6a26ae90b8d86 100644 --- a/Framework/Core/test/benchmark_EventMixing.cxx +++ b/Framework/Core/test/benchmark_EventMixing.cxx @@ -49,7 +49,7 @@ static void BM_EventMixingTraditional(benchmark::State& state) std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; using BinningType = ColumnBinningPolicy; - BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) + BinningType binningOnPositions{{xBins, yBins}}; TableBuilder colBuilder, trackBuilder; auto rowWriterCol = colBuilder.cursor(); @@ -141,7 +141,7 @@ static void BM_EventMixingCombinations(benchmark::State& state) std::vector xBins{VARIABLE_WIDTH, -0.064, -0.062, -0.060, 0.066, 0.068, 0.070, 0.072}; std::vector yBins{VARIABLE_WIDTH, -0.320, -0.301, -0.300, 0.330, 0.340, 0.350, 0.360}; using BinningType = ColumnBinningPolicy; - BinningType binningOnPositions{{xBins, yBins}, true}; // true is for 'ignore overflows' (true by default) + BinningType binningOnPositions{{xBins, yBins}}; TableBuilder colBuilder, trackBuilder; auto rowWriterCol = colBuilder.cursor(); diff --git a/Framework/Core/test/test_ASoAHelpers.cxx b/Framework/Core/test/test_ASoAHelpers.cxx index 701dc0bbced50..1664b72050ce1 100644 --- a/Framework/Core/test/test_ASoAHelpers.cxx +++ b/Framework/Core/test/test_ASoAHelpers.cxx @@ -129,7 +129,7 @@ TEST_CASE("CombinationsGeneratorConstruction") std::vector yBins{VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 101}; std::vector zBins{VARIABLE_WIDTH, -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0}; - ColumnBinningPolicy pairBinning{{yBins, zBins}, false}; + ColumnBinningPolicy pairBinning{{yBins, zBins}}; CombinationsGenerator>::CombinationsIterator combIt(CombinationsStrictlyUpperIndexPolicy(testsA, testsA)); REQUIRE(!(static_cast(std::get<0>(*(combIt))).getIterator().mCurrentPos == nullptr)); @@ -944,22 +944,19 @@ TEST_CASE("BlockCombinations") std::vector yBins{VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 101}; std::vector zBins{VARIABLE_WIDTH, -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0}; - ColumnBinningPolicy pairBinning{{yBins, zBins}, false}; - ColumnBinningPolicy pairBinningNoOverflows{{yBins, zBins}, true}; + ColumnBinningPolicy pairBinning{{yBins, zBins}}; // 2, 3, 5, 8, 9 have overflows in testA - std::vector> expectedFullPairsNoOverflows{ - {0, 0}, {0, 4}, {4, 0}, {4, 4}, {4, 7}, {7, 4}, {7, 7}, {1, 1}, {1, 6}, {6, 1}, {6, 6}}; + std::vector> expectedFullPairsNoOverflows{{0, 0}, {0, 4}, {4, 0}, {4, 4}, {4, 7}, {7, 4}, {7, 7}, {1, 1}, {1, 6}, {6, 1}, {6, 6}}; size_t count = 0; - for (auto& [c0, c1] : combinations(CombinationsBlockFullIndexPolicy(pairBinningNoOverflows, 1, -1, testA, testA))) { + for (auto& [c0, c1] : combinations(CombinationsBlockFullIndexPolicy(pairBinning, 1, -1, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedFullPairsNoOverflows[count])); REQUIRE(c1.x() == std::get<1>(expectedFullPairsNoOverflows[count])); count++; } REQUIRE(count == expectedFullPairsNoOverflows.size()); - std::vector> expectedFullPairs{ - {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}}; + std::vector> expectedFullPairs{{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}}; count = 0; for (auto& [c0, c1] : combinations(CombinationsBlockFullIndexPolicy(pairBinning, 2, -1, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedFullPairs[count])); @@ -968,8 +965,7 @@ TEST_CASE("BlockCombinations") } REQUIRE(count == expectedFullPairs.size()); - std::vector> expectedFullTriples{ - {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}}; + std::vector> expectedFullTriples{{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}}; count = 0; for (auto& [c0, c1, c2] : combinations(CombinationsBlockFullIndexPolicy(pairBinning, 2, -1, testA, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedFullTriples[count])); @@ -979,8 +975,7 @@ TEST_CASE("BlockCombinations") } REQUIRE(count == expectedFullTriples.size()); - std::vector> expectedUpperPairs{ - {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}}; + std::vector> expectedUpperPairs{{0, 0}, {0, 4}, {0, 7}, {4, 4}, {4, 7}, {7, 7}, {1, 1}, {1, 6}, {6, 6}}; count = 0; for (auto& [c0, c1] : combinations(CombinationsBlockUpperIndexPolicy(pairBinning, 2, -1, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedUpperPairs[count])); @@ -989,8 +984,7 @@ TEST_CASE("BlockCombinations") } REQUIRE(count == expectedUpperPairs.size()); - std::vector> expectedUpperTriples{ - {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}}; + std::vector> expectedUpperTriples{{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}}; count = 0; for (auto& [c0, c1, c2] : combinations(CombinationsBlockUpperIndexPolicy(pairBinning, 1, -1, testA, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedUpperTriples[count])); @@ -1000,7 +994,7 @@ TEST_CASE("BlockCombinations") } REQUIRE(count == expectedUpperTriples.size()); - std::vector> 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}}; + std::vector> 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}}; count = 0; for (auto& [c0, c1, c2, c3, c4] : combinations(CombinationsBlockUpperIndexPolicy(pairBinning, 2, -1, testA, testA, testA, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedUpperFives[count])); @@ -1012,8 +1006,7 @@ TEST_CASE("BlockCombinations") } REQUIRE(count == expectedUpperFives.size()); - std::vector> expectedStrictlyUpperPairsSmaller{ - {0, 4}, {4, 7}, {1, 6}, {3, 5}, {2, 8}, {8, 9}}; + std::vector> expectedStrictlyUpperPairsSmaller{{0, 4}, {4, 7}, {1, 6}}; count = 0; for (auto& [c0, c1] : combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 1, -1, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperPairsSmaller[count])); @@ -1022,8 +1015,7 @@ TEST_CASE("BlockCombinations") } REQUIRE(count == expectedStrictlyUpperPairsSmaller.size()); - std::vector> expectedStrictlyUpperPairs{ - {0, 4}, {0, 7}, {4, 7}, {1, 6}, {3, 5}, {2, 8}, {2, 9}, {8, 9}}; + std::vector> expectedStrictlyUpperPairs{{0, 4}, {0, 7}, {4, 7}, {1, 6}}; count = 0; for (auto& [c0, c1] : combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 2, -1, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperPairs[count])); @@ -1032,8 +1024,7 @@ TEST_CASE("BlockCombinations") } REQUIRE(count == expectedStrictlyUpperPairs.size()); - std::vector> expectedStrictlyUpperTriples{ - {0, 4, 7}, {2, 8, 9}}; + std::vector> expectedStrictlyUpperTriples{{0, 4, 7}}; count = 0; for (auto& [c0, c1, c2] : combinations(CombinationsBlockStrictlyUpperSameIndexPolicy(pairBinning, 2, -1, testA, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperTriples[count])); @@ -1050,8 +1041,7 @@ TEST_CASE("BlockCombinations") REQUIRE(count == 0); // Different tables of different size - std::vector> expectedFullPairsFirstSmaller{ - {0, 0}, {0, 4}, {4, 0}, {4, 4}, {4, 7}, {1, 1}, {1, 6}, {3, 3}, {3, 5}, {2, 2}, {2, 8}}; + std::vector> expectedFullPairsFirstSmaller{{0, 0}, {0, 4}, {4, 0}, {4, 4}, {4, 7}, {1, 1}, {1, 6}}; count = 0; for (auto& [x0, x1] : combinations(CombinationsBlockFullIndexPolicy(pairBinning, 1, -1, testAHalf, testA))) { REQUIRE(x0.x() == std::get<0>(expectedFullPairsFirstSmaller[count])); @@ -1061,8 +1051,7 @@ TEST_CASE("BlockCombinations") REQUIRE(count == expectedFullPairsFirstSmaller.size()); count = 0; - std::vector> expectedFullPairsSecondSmaller{ - {0, 0}, {0, 4}, {4, 0}, {4, 4}, {7, 4}, {1, 1}, {6, 1}, {3, 3}, {5, 3}, {2, 2}, {8, 2}}; + std::vector> expectedFullPairsSecondSmaller{{0, 0}, {0, 4}, {4, 0}, {4, 4}, {7, 4}, {1, 1}, {6, 1}}; for (auto& [x0, x1] : combinations(CombinationsBlockFullIndexPolicy(pairBinning, 1, -1, testA, testAHalf))) { REQUIRE(x0.x() == std::get<0>(expectedFullPairsSecondSmaller[count])); REQUIRE(x1.x() == std::get<1>(expectedFullPairsSecondSmaller[count])); @@ -1070,8 +1059,7 @@ TEST_CASE("BlockCombinations") } REQUIRE(count == expectedFullPairsSecondSmaller.size()); - std::vector> expectedUpperPairsFirstSmaller{ - {0, 0}, {0, 4}, {4, 4}, {4, 7}, {1, 1}, {1, 6}, {3, 3}, {3, 5}, {2, 2}, {2, 8}}; + std::vector> expectedUpperPairsFirstSmaller{{0, 0}, {0, 4}, {4, 4}, {4, 7}, {1, 1}, {1, 6}}; count = 0; for (auto& [x0, x1] : combinations(CombinationsBlockUpperIndexPolicy(pairBinning, 1, -1, testAHalf, testA))) { REQUIRE(x0.x() == std::get<0>(expectedUpperPairsFirstSmaller[count])); @@ -1081,8 +1069,7 @@ TEST_CASE("BlockCombinations") REQUIRE(count == expectedUpperPairsFirstSmaller.size()); count = 0; - std::vector> expectedUpperPairsSecondSmaller{ - {0, 0}, {0, 4}, {4, 4}, {1, 1}, {3, 3}, {2, 2}}; + std::vector> expectedUpperPairsSecondSmaller{{0, 0}, {0, 4}, {4, 4}, {1, 1}}; for (auto& [x0, x1] : combinations(CombinationsBlockUpperIndexPolicy(pairBinning, 1, -1, testA, testAHalf))) { REQUIRE(x0.x() == std::get<0>(expectedUpperPairsSecondSmaller[count])); REQUIRE(x1.x() == std::get<1>(expectedUpperPairsSecondSmaller[count])); @@ -1164,22 +1151,19 @@ TEST_CASE("BlockCombinations") // [3, 5] [0, 4], [7], [1, 6], [2], [8, 9] // Assuming bins intervals: [ , ) std::vector xBins{VARIABLE_WIDTH, 0, 7, 10}; - ColumnBinningPolicy tripleBinning{{xBins, yBins, zBins}, false}; - ColumnBinningPolicy tripleBinningNoOverflows{{xBins, yBins, zBins}, true}; + ColumnBinningPolicy tripleBinning{{xBins, yBins, zBins}}; // 2, 3, 5, 8, 9 have overflows in testA - std::vector> expectedFullPairsTripleBinningNoOverflows{ - {0, 0}, {0, 4}, {4, 0}, {4, 4}, {7, 7}, {1, 1}, {1, 6}, {6, 1}, {6, 6}}; + std::vector> expectedFullPairsTripleBinningNoOverflows{{0, 0}, {0, 4}, {4, 0}, {4, 4}, {7, 7}, {1, 1}, {1, 6}, {6, 1}, {6, 6}}; count = 0; - for (auto& [c0, c1] : combinations(CombinationsBlockFullIndexPolicy(tripleBinningNoOverflows, 1, -1, testA, testA))) { + for (auto& [c0, c1] : combinations(CombinationsBlockFullIndexPolicy(tripleBinning, 1, -1, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedFullPairsTripleBinningNoOverflows[count])); REQUIRE(c1.x() == std::get<1>(expectedFullPairsTripleBinningNoOverflows[count])); count++; } REQUIRE(count == expectedFullPairsTripleBinningNoOverflows.size()); - std::vector> expectedFullPairsTripleBinning{ - {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}}; + std::vector> expectedFullPairsTripleBinning{{0, 0}, {0, 4}, {4, 0}, {4, 4}, {7, 7}, {1, 1}, {1, 6}, {6, 1}, {6, 6}}; count = 0; for (auto& [c0, c1] : combinations(CombinationsBlockFullIndexPolicy(tripleBinning, 2, -1, testA, testA))) { REQUIRE(c0.x() == std::get<0>(expectedFullPairsTripleBinning[count])); @@ -1272,10 +1256,9 @@ TEST_CASE("CombinationsHelpers") std::vector yBins{VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 101}; std::vector zBins{VARIABLE_WIDTH, -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0}; - ColumnBinningPolicy pairBinning{{yBins, zBins}, false}; + ColumnBinningPolicy pairBinning{{yBins, zBins}}; - std::vector> expectedStrictlyUpperPairs{ - {0, 4}, {0, 7}, {4, 7}, {1, 6}, {3, 5}, {2, 8}, {2, 9}, {8, 9}}; + std::vector> expectedStrictlyUpperPairs{{0, 4}, {0, 7}, {4, 7}, {1, 6}}; count = 0; for (auto& [c0, c1] : selfPairCombinations(pairBinning, 2, -1, testB)) { REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperPairs[count])); @@ -1284,8 +1267,7 @@ TEST_CASE("CombinationsHelpers") } REQUIRE(count == expectedStrictlyUpperPairs.size()); - std::vector> expectedStrictlyUpperTriples{ - {0, 4, 7}, {2, 8, 9}}; + std::vector> expectedStrictlyUpperTriples{{0, 4, 7}}; count = 0; for (auto& [c0, c1, c2] : selfTripleCombinations(pairBinning, 2, -1, testB)) { REQUIRE(c0.x() == std::get<0>(expectedStrictlyUpperTriples[count])); @@ -1353,7 +1335,7 @@ TEST_CASE("BlockCombinationsCounters") std::vector yBins{VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 101}; std::vector zBins{VARIABLE_WIDTH, -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0}; - ColumnBinningPolicy pairBinning{{yBins, zBins}, false}; + ColumnBinningPolicy pairBinning{{yBins, zBins}}; // Window size < category size std::vector expectedCollisionsInBinSmallWindow{3, 3, 2, 1, 3, 3, 2, 1};