From 43316242f7f94fed5c4575f9d8495218038c0249 Mon Sep 17 00:00:00 2001 From: Sebastian Turner Date: Tue, 20 Oct 2026 08:47:37 -0700 Subject: [PATCH] Fix reading of RNTuple std::bitset with 32 to 48 bits Signed-off-by: Sebastian Turner --- .github/workflows/jsroot-ci.yml | 3 ++ demo/node/rntuple_bitset_test.cxx | 30 +++++++++++++++++ demo/node/rntuple_bitset_test.js | 50 +++++++++++++++++++++++++++++ demo/node/rntuple_bitset_test.root | Bin 0 -> 1579 bytes modules/rntuple.mjs | 2 +- 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 demo/node/rntuple_bitset_test.cxx create mode 100644 demo/node/rntuple_bitset_test.js create mode 100644 demo/node/rntuple_bitset_test.root diff --git a/.github/workflows/jsroot-ci.yml b/.github/workflows/jsroot-ci.yml index d968e4969..c6f68b19a 100644 --- a/.github/workflows/jsroot-ci.yml +++ b/.github/workflows/jsroot-ci.yml @@ -67,6 +67,7 @@ jobs: node demo/node/file_proxy.js buffer ./hsimple.root node demo/node/rntuple_buffer_test.js node demo/node/rntuple_test.js demo/node/rntuple_test.root + node demo/node/rntuple_bitset_test.js demo/node/rntuple_bitset_test.root node demo/node/tree_int64_test.js demo/node/tree_int64_test.root node demo/node/tree_draw_range.js demo/node/rntuple_test.root node demo/node/rntuple_test32.js demo/node/rntuple_test32.root demo/node/rntuple_test32.json @@ -187,6 +188,7 @@ jobs: node demo/node/file_proxy.js buffer ./hsimple.root node demo/node/rntuple_buffer_test.js node demo/node/rntuple_test.js demo/node/rntuple_test.root + node demo/node/rntuple_bitset_test.js demo/node/rntuple_bitset_test.root node demo/node/tree_int64_test.js demo/node/tree_int64_test.root node demo/node/tree_draw_range.js demo/node/rntuple_test.root node demo/node/rntuple_test32.js demo/node/rntuple_test32.root demo/node/rntuple_test32.json @@ -242,6 +244,7 @@ jobs: node demo/node/file_proxy.js buffer ./hsimple.root node demo/node/rntuple_buffer_test.js node demo/node/rntuple_test.js demo/node/rntuple_test.root + node demo/node/rntuple_bitset_test.js demo/node/rntuple_bitset_test.root node demo/node/tree_int64_test.js demo/node/tree_int64_test.root node demo/node/tree_draw_range.js demo/node/rntuple_test.root node demo/node/rntuple_test32.js demo/node/rntuple_test32.root demo/node/rntuple_test32.json diff --git a/demo/node/rntuple_bitset_test.cxx b/demo/node/rntuple_bitset_test.cxx new file mode 100644 index 000000000..d1a47e7db --- /dev/null +++ b/demo/node/rntuple_bitset_test.cxx @@ -0,0 +1,30 @@ +// macro to create rntuple_bitset_test.root used by rntuple_bitset_test.js +// root -l -b -q rntuple_bitset_test.cxx + +#include +#include + +#include + +void rntuple_bitset_test() +{ + auto model = ROOT::RNTupleModel::Create(); + + auto Bitset32 = model->MakeField>("Bitset32"); + auto Bitset48 = model->MakeField>("Bitset48"); + + auto writer = ROOT::RNTupleWriter::Recreate(std::move(model), "Data", "rntuple_bitset_test.root"); + + for (int i = 0; i < 10; i++) { + Bitset32->reset(); + Bitset32->set(i); + Bitset32->set(31 - i); + + Bitset48->reset(); + Bitset48->set(i); + Bitset48->set(30 + i); + Bitset48->set(47); + + writer->Fill(); + } +} diff --git a/demo/node/rntuple_bitset_test.js b/demo/node/rntuple_bitset_test.js new file mode 100644 index 000000000..e00dcc61c --- /dev/null +++ b/demo/node/rntuple_bitset_test.js @@ -0,0 +1,50 @@ +import { version, openFile, TSelector } from 'jsroot'; +import { rntupleProcess } from 'jsroot/rntuple'; + +// check reading of std::bitset fields with more than 31 bits, file created with rntuple_bitset_test.cxx + +console.log(`JSROOT version ${version}`); + +let filename = './rntuple_bitset_test.root', + any_error = false; + +if (process?.argv && process.argv[2]) + filename = process.argv[2]; + +const file = await openFile(filename), + rntuple = await file.readObject('Data'), + selector = new TSelector(); + +let nentries = 0; + +selector.addBranch('Bitset32'); +selector.addBranch('Bitset48'); + +selector.Process = function(entry) { + nentries++; + const expected = { + Bitset32: 2 ** entry + 2 ** (31 - entry), + Bitset48: 2 ** entry + 2 ** (30 + entry) + 2 ** 47 + }; + for (const name in expected) { + const value = this.tgtobj[name]; + if (value !== expected[name]) { + any_error = true; + console.error(`FAILURE: ${name} at entry ${entry} expected ${expected[name]} but got ${value}`); + } else + console.log(`OK: ${name} at entry ${entry} = ${value}`); + } +}; + +await rntupleProcess(rntuple, selector); + +if (nentries !== 10) { + any_error = true; + console.error(`FAILURE: expected 10 entries but got ${nentries}`); +} + +if (any_error) { + console.error('\nFAILURE when reading std::bitset values'); + process.exit(1); +} else + console.log('\nTest OK'); diff --git a/demo/node/rntuple_bitset_test.root b/demo/node/rntuple_bitset_test.root new file mode 100644 index 0000000000000000000000000000000000000000..623cf19b22e98ee13cff2f840b87a3e0f3b1791b GIT binary patch literal 1579 zcmbVMeN0helL}eSBl5IGkp8Hyen7BW7l6%j2_uO;N z?|j^6x7m1rIW+*70air=NG_tBj*G&T&mx}#U`@!KcyNcbm$`(NxwVJ1>p&-ZCXO(o zmn6otQmZAzUe52Xuv!XDrM$z!7xESdA8RK7|6cFCoBxlYU|UbPx!2X9VJHl@U?HgHse zIzg=*37Tz->t26zQCS(pU3DsU+%>Aa`^KC~AKvgW9H@P_;iRrktBj9+DrvO2PBj~v zR^+;FO}G+&1d;?TpdGLRhr6Gk!Cfv0xN`z}0F3|`LJ%e<&*UldzbBcti0Ira z(b0LRA+(GRtNQ|g8^r2z?j9Q441?cGMfuT#?jZzZd)*iT&JQhmJW(i2QF9cBatg}9 zbp6?w(I$k4oslzpF6Uc4i5lC+z4rA6&GC_a?dHDtH+oG4I@yK4OQ@d?uTw->(I)qlPxX0z7is*ge{_eo&^hu!(7A*o&Idm~RAzdw;ES01daDDK z!xQez>9gTqkM<4AUW#4oKgFtw-;sZmTd9lLsccCvF{M0#RZbThFI(Ao@lQ`$aNEY? MpF literal 0 HcmV?d00001 diff --git a/modules/rntuple.mjs b/modules/rntuple.mjs index dac1ded4b..6bdab8bc5 100644 --- a/modules/rntuple.mjs +++ b/modules/rntuple.mjs @@ -1210,7 +1210,7 @@ class BitsetReaderItem extends ReaderItem { if (this.bigint) res |= (1n << BigInt(len)); else - res |= 1 << len; + res += 2 ** len; } len++; }