diff --git a/roottest/root/tree/index/CMakeLists.txt b/roottest/root/tree/index/CMakeLists.txt index 31901e0e37505..33dede9115064 100644 --- a/roottest/root/tree/index/CMakeLists.txt +++ b/roottest/root/tree/index/CMakeLists.txt @@ -15,6 +15,10 @@ ROOTTEST_ADD_TEST(index64 MACRO runindex64.C OUTREF index64.ref) +ROOTTEST_ADD_TEST(indexl64 + MACRO runindexl64.C + OUTREF indexl64.ref) + ROOTTEST_ADD_TEST(varsizearr MACRO runvarsizearr.C OUTREF varsizearr.ref) diff --git a/roottest/root/tree/index/runindexl64.C b/roottest/root/tree/index/runindexl64.C index 9617fde08fbce..b859e3cf1892c 100644 --- a/roottest/root/tree/index/runindexl64.C +++ b/roottest/root/tree/index/runindexl64.C @@ -5,9 +5,8 @@ bool test(TTree *); const char *fname = "indexl64.root"; -https : // github.com/root-project/root/pull/19561 - const Long64_t bigval = - 0x0FFFFFFFFFFFFFFF; // here we skip long double, so we can go higher than with runindex64.C +// https://github.com/root-project/root/pull/19561 +const Long64_t bigval = 0x0FFFFFFFFFFFFFFF; // here we skip long double, so we can go higher than with runindex64.C int runindexl64() { diff --git a/tree/treeplayer/src/TTreeIndex.cxx b/tree/treeplayer/src/TTreeIndex.cxx index 7058671657afb..027cd296e2655 100644 --- a/tree/treeplayer/src/TTreeIndex.cxx +++ b/tree/treeplayer/src/TTreeIndex.cxx @@ -189,7 +189,7 @@ TTreeIndex::TTreeIndex(const TTree *T, const char *majorname, const char *minorn 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) { + auto GetAndRangeCheck = [this](bool isMajor, Long64_t entry) -> Long64_t { LongDouble_t ret = (isMajor ? fMajorFormula : fMinorFormula)->EvalInstance(); // Check whether the value (vs significant bits) of ldRet can represent // the full precision of the returned value. If we return 10^60, the @@ -206,11 +206,16 @@ TTreeIndex::TTreeIndex(const TTree *T, const char *majorname, const char *minorn "In tree entry %lld, %s value %s=%Lf possibly out of range for internal `long double`", entry, isMajor ? "major" : "minor", isMajor ? fMajorName.Data() : fMinorName.Data(), ret); } - return ret; + return static_cast(ret); // static_cast necessary for use in ternary expression below }; auto GetLong64 = [this](bool isMajor) { return (isMajor ? fMajorFormula : fMinorFormula)->EvalInstance(); }; + // Note: in ternary expression ensure both branches have same return data type Long64_t. + // otherwise, with LongDouble_t, the expression is implicitly cast to their + // common type `long double` regardless of the branch taken. On platforms where + // `sizeof(long double) == sizeof(double)` (macOS arm64, Windows) this silently + // rounds the exact Long64_t value, defeating the purpose of the long64 flag. tmp_major[i] = long64major ? GetLong64(true) : GetAndRangeCheck(true, i); tmp_minor[i] = long64minor ? GetLong64(false) : GetAndRangeCheck(false, i); }