diff --git a/roottest/root/tree/index/CMakeLists.txt b/roottest/root/tree/index/CMakeLists.txt index 6cb71de9fa99f..31901e0e37505 100644 --- a/roottest/root/tree/index/CMakeLists.txt +++ b/roottest/root/tree/index/CMakeLists.txt @@ -15,3 +15,6 @@ ROOTTEST_ADD_TEST(index64 MACRO runindex64.C OUTREF index64.ref) +ROOTTEST_ADD_TEST(varsizearr + MACRO runvarsizearr.C + OUTREF varsizearr.ref) diff --git a/roottest/root/tree/index/runvarsizearr.C b/roottest/root/tree/index/runvarsizearr.C new file mode 100644 index 0000000000000..55033e6476d4c --- /dev/null +++ b/roottest/root/tree/index/runvarsizearr.C @@ -0,0 +1,30 @@ +#include "TTree.h" +#include "TTreeIndex.h" +#include +#include + +int runvarsizearr() +{ + const Long64_t nEvents = 2; + const size_t nElements = 3; + std::vector otherNumbers(nElements); + Long64_t eventNumber; + TTree t("tree", "tree"); + t.Branch("eventNumber", &eventNumber); + t.Branch("otherNumbers", &otherNumbers); + for (Long64_t i = 0; i < nEvents; i++) { + eventNumber = i; + for (size_t j = 0; j < nElements; ++j) + otherNumbers[j] = -2. * eventNumber + 3500 * j; + t.Fill(); + } + std::cout << t.GetEntries() << std::endl; + // use Scan to show what otherNumbers[2] contains + t.Scan("eventNumber:otherNumbers", "", "", nEvents); + + TTreeIndex firstIndex(&t, "otherNumbers[2]", "eventNumber"); + firstIndex.Print("2"); // wasn't working before: major was always a garbage value + TTreeIndex secondIndex(&t, "otherNumbers", "eventNumber"); + secondIndex.Print("2"); // major is always otherNumbers[0] since index not specified (before and after fix) + return 0; +} diff --git a/roottest/root/tree/index/varsizearr.ref b/roottest/root/tree/index/varsizearr.ref new file mode 100644 index 0000000000000..6b71cc3f6a42a --- /dev/null +++ b/roottest/root/tree/index/varsizearr.ref @@ -0,0 +1,30 @@ + +Processing runvarsizearr.C... +2 +*********************************************** +* Row * Instance * eventNumb * otherNumb * +*********************************************** +* 0 * 0 * 0 * 0 * +* 0 * 1 * 0 * 3500 * +* 0 * 2 * 0 * 7000 * +* 1 * 0 * 1 * -2 * +* 1 * 1 * 1 * 3498 * +* 1 * 2 * 1 * 6998 * +*********************************************** + +********************************************** +* Index of Tree: tree/tree +********************************************** + serial : otherNumbers[2] : eventNumber +********************************************** + 0 : 6998 : 1 + 1 : 7000 : 0 + +********************************************** +* Index of Tree: tree/tree +********************************************** + serial : otherNumbers : eventNumber +********************************************** + 0 : -2 : 1 + 1 : 0 : 0 +(int) 0 diff --git a/tree/treeplayer/src/TTreeIndex.cxx b/tree/treeplayer/src/TTreeIndex.cxx index 5e840188b2bb6..28645d392ce0a 100644 --- a/tree/treeplayer/src/TTreeIndex.cxx +++ b/tree/treeplayer/src/TTreeIndex.cxx @@ -11,6 +11,8 @@ /** \class TTreeIndex A Tree Index with majorname and minorname. + +If minorname is "0", just majorname will be used. */ #include "TTreeIndex.h" @@ -181,6 +183,14 @@ TTreeIndex::TTreeIndex(const TTree *T, const char *majorname, const char *minorn fMajorFormula->UpdateFormulaLeaves(); fMinorFormula->UpdateFormulaLeaves(); } + if ((fMajorFormula->GetNdata() + fMinorFormula->GetNdata()) <= 0) { + // Calling GetNdata is essential before calling EvalInstance, otherwise a wrong + // result is silently returned by EvalInstance below if formula is value from a variable-sized array + // We raise an error to prevent the if clause being optimized-out if we do not use the return + Error("TTreeIndex", + "In tree entry %lld, Ndata in formula is zero for both '%s' and '%s'", i, + fMajorName.Data(), fMinorName.Data()); + } auto GetAndRangeCheck = [this](bool isMajor, Long64_t entry) { LongDouble_t ret = (isMajor ? fMajorFormula : fMinorFormula)->EvalInstance(); // Check whether the value (vs significant bits) of ldRet can represent