Skip to content

Commit 8eac2bf

Browse files
jblomerdpiparo
authored andcommitted
[ntuple] add fpclass check for double --> float conversion
1 parent 8276f72 commit 8eac2bf

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

tree/ntuple/src/RColumnElement.hxx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,18 @@ inline void EnsureValidRange(SourceT val [[maybe_unused]])
162162
}
163163
}
164164

165+
/// Currently ensures that the floating point class doesn't change in double --> float conversion
166+
template <typename DestT, typename SourceT>
167+
inline void EnsureValidConversion(DestT dst [[maybe_unused]], SourceT src [[maybe_unused]])
168+
{
169+
if constexpr (std::is_same_v<DestT, float> && std::is_same_v<SourceT, double>) {
170+
if (std::fpclassify(src) != std::fpclassify(dst)) {
171+
throw ROOT::RException(R__FAIL(std::string("floating point class mismatch: ") + std::to_string(src) +
172+
" on disk to " + std::to_string(dst) + " in memory"));
173+
}
174+
}
175+
}
176+
165177
/// \brief Pack `count` elements into narrower (or wider) type
166178
///
167179
/// Used to convert in-memory elements to smaller column types of comatible types
@@ -192,6 +204,7 @@ inline void CastUnpack(void *destination, const void *source, std::size_t count)
192204
ByteSwapIfNecessary(val);
193205
EnsureValidRange<DestT, SourceT>(val);
194206
dst[i] = val;
207+
EnsureValidConversion<DestT, SourceT>(dst[i], val);
195208
}
196209
}
197210

@@ -230,6 +243,7 @@ inline void CastSplitUnpack(void *destination, const void *source, std::size_t c
230243
ByteSwapIfNecessary(val);
231244
EnsureValidRange<DestT, SourceT>(val);
232245
dst[i] = val;
246+
EnsureValidConversion<DestT, SourceT>(dst[i], val);
233247
}
234248
}
235249

tree/ntuple/test/ntuple_cast.cxx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,30 @@ TEST(RNTuple, TypeCastReal)
266266
EXPECT_FLOAT_EQ(*ptrDouble32, -11.043);
267267
}
268268

269+
TEST(RNTuple, TypeCastRealFpClass)
270+
{
271+
FileRaii fileGuard("test_ntuple_type_cast_real_fpclass.root");
272+
273+
{
274+
auto model = RNTupleModel::Create();
275+
auto ptrDouble = model->MakeField<double>("double");
276+
277+
auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
278+
*ptrDouble = std::numeric_limits<double>::max();
279+
writer->Fill();
280+
}
281+
282+
auto castModel = RNTupleModel::Create();
283+
auto ptrDouble = castModel->MakeField<float>("double");
284+
auto reader = RNTupleReader::Open(std::move(castModel), "ntpl", fileGuard.GetPath());
285+
try {
286+
reader->LoadEntry(0);
287+
FAIL() << "floating point mismatch should throw";
288+
} catch (const ROOT::RException &err) {
289+
EXPECT_THAT(err.what(), testing::HasSubstr("floating point class mismatch"));
290+
}
291+
}
292+
269293
TEST(RNTuple, TypeCastChar)
270294
{
271295
FileRaii fileGuard("test_ntuple_type_cast_char.root");

0 commit comments

Comments
 (0)