From 0a8f81697922d45e38703eaa361915b87bfc8c69 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Wed, 13 Aug 2025 10:57:31 +0200 Subject: [PATCH 1/2] [test] fix l64 test was not running --- roottest/root/tree/index/CMakeLists.txt | 4 ++++ roottest/root/tree/index/runindexl64.C | 5 ++--- 2 files changed, 6 insertions(+), 3 deletions(-) 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() { From 4626182d651cfa21b6f4d77bd579db094c2d8e61 Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Sat, 13 Jun 2026 18:15:00 +0200 Subject: [PATCH 2/2] [tree] Fix long64 tree index losing precision on 64-bit long double platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The conditional `long64major ? GetLong64() : GetAndRangeCheck()` mixes Long64_t and LongDouble_t, so the exact value was promoted through long double regardless of branch. This rounded large values where long double is 64-bit (macOS arm64, Windows), making roottest-root-tree-index-indexl64 fail there while passing on Linux. Fix this with an explicit `static_cast(ret)`. 🤖 Done with the help of [Claude Code](https://claude.com/claude-code) (Claude Opus 4.8) --- tree/treeplayer/src/TTreeIndex.cxx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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); }