diff --git a/types/fundamental/README.md b/types/fundamental/README.md index 9736f51..5da589c 100644 --- a/types/fundamental/README.md +++ b/types/fundamental/README.md @@ -3,11 +3,11 @@ * [`integer`](integer): `[U]Int{8,16,32,64}`, `Split[U]Int{16,32,64}` * [`misc`](misc): `Bit`, `Byte`, `Char` * [`real`](real): `Real{16,32,64}`, `SplitReal{32,64}` + * [`real32trunc`](real32trunc): `Real32Trunc` __Covered under a different category:__ * `[Split]Index{32,64}`: with [`std::string`](../string) and [`std::vector`](../vector) * `Switch`: with [`std::variant`](../variant) __Missing:__ - * `Real32Trunc` * `Real32Quant` diff --git a/types/fundamental/real32trunc/README.md b/types/fundamental/real32trunc/README.md new file mode 100644 index 0000000..ecf805b --- /dev/null +++ b/types/fundamental/real32trunc/README.md @@ -0,0 +1,21 @@ +# Real Column Types with variable width and truncated mantissa + +## Fields + + * `FloatReal32Trunc10` + * `FloatReal32Trunc16` + * `FloatReal32Trunc31` + * `DoubleReal32Trunc10` + * `DoubleReal32Trunc16` + * `DoubleReal32Trunc31` + +with the corresponding field, column types and bit width. + +## Entries + +1. Ascending values +2. All 1s in the mantissa +3. Lowest values with N bits +4. Smallest positive normal values with N bits +5. Smallest positive subnormal values with N bits +6. Maximum values with N bits diff --git a/types/fundamental/real32trunc/read.C b/types/fundamental/real32trunc/read.C new file mode 100644 index 0000000..16a7d94 --- /dev/null +++ b/types/fundamental/real32trunc/read.C @@ -0,0 +1,57 @@ +#include +#include + +using ROOT::Experimental::REntry; +using ROOT::Experimental::RNTupleReader; + +#include +#include +#include +#include +#include + +template +static void PrintRealValue(const REntry &entry, std::string_view name, + std::ostream &os, bool last = false) { + T value = *entry.GetPtr(name); + os << " \"" << name << "\": \"" << value << "\""; + if (!last) { + os << ","; + } + os << "\n"; +} + +void read(std::string_view input = "types.fundamental.real32trunc.root", + std::string_view output = "types.fundamental.real32trunc.json") { + std::ofstream os(std::string{output}); + // Print floating-point numbers as hexadecimal literals. + os << std::hexfloat; + os << "[\n"; + + auto reader = RNTupleReader::Open("ntpl", input); + auto &entry = reader->GetModel().GetDefaultEntry(); + bool first = true; + for (auto index : *reader) { + reader->LoadEntry(index); + + if (first) { + first = false; + } else { + os << ",\n"; + } + os << " {\n"; + + PrintRealValue(entry, "FloatReal32Trunc10", os); + PrintRealValue(entry, "FloatReal32Trunc16", os); + PrintRealValue(entry, "FloatReal32Trunc31", os); + PrintRealValue(entry, "DoubleReal32Trunc10", os); + PrintRealValue(entry, "DoubleReal32Trunc16", os); + PrintRealValue(entry, "DoubleReal32Trunc31", os, /*last=*/true); + + os << " }"; + // Newline is intentionally missing, may need to print a comma before the + // next entry. + } + os << "\n"; + os << "]\n"; +} diff --git a/types/fundamental/real32trunc/write.C b/types/fundamental/real32trunc/write.C new file mode 100644 index 0000000..de03250 --- /dev/null +++ b/types/fundamental/real32trunc/write.C @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include + +using ROOT::Experimental::EColumnType; +using ROOT::Experimental::RField; +using ROOT::Experimental::RNTupleModel; +using ROOT::Experimental::RNTupleWriteOptions; +using ROOT::Experimental::RNTupleWriter; + +#include +#include +#include + +template +static std::shared_ptr MakeFieldReal32Trunc(RNTupleModel &model, + std::string_view name, + int nBits) { + assert(nBits >= 10 && nBits < 32); + auto field = std::make_unique>(name); + field->SetTruncated(nBits); + model.AddField(std::move(field)); + return model.GetDefaultEntry().GetPtr(name); +} + +void write(std::string_view filename = "types.fundamental.real32trunc.root") { + auto model = RNTupleModel::Create(); + + auto FloatReal32Trunc10 = + MakeFieldReal32Trunc(*model, "FloatReal32Trunc10", 10); + auto FloatReal32Trunc16 = + MakeFieldReal32Trunc(*model, "FloatReal32Trunc16", 16); + auto FloatReal32Trunc31 = + MakeFieldReal32Trunc(*model, "FloatReal32Trunc31", 31); + auto DoubleReal32Trunc10 = + MakeFieldReal32Trunc(*model, "DoubleReal32Trunc10", 10); + auto DoubleReal32Trunc16 = + MakeFieldReal32Trunc(*model, "DoubleReal32Trunc16", 16); + auto DoubleReal32Trunc31 = + MakeFieldReal32Trunc(*model, "DoubleReal32Trunc31", 31); + + RNTupleWriteOptions options; + options.SetCompression(0); + auto writer = + RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options); + + // First entry: ascending values + *FloatReal32Trunc10 = 1.0f; + *FloatReal32Trunc16 = 2.0f; + *FloatReal32Trunc31 = 3.0f; + *DoubleReal32Trunc10 = 4.0f; + *DoubleReal32Trunc16 = 5.0f; + *DoubleReal32Trunc31 = 6.0f; + writer->Fill(); + + // Second entry: a value containing all 1s in the mantissa + static constexpr float Value32 = 3.9999997f; + *FloatReal32Trunc10 = Value32; + *FloatReal32Trunc16 = Value32; + *FloatReal32Trunc31 = Value32; + *DoubleReal32Trunc10 = Value32; + *DoubleReal32Trunc16 = Value32; + *DoubleReal32Trunc31 = Value32; + writer->Fill(); + + // Third entry: lowest values with N bits + *FloatReal32Trunc10 = -0x1.8p127f; + *FloatReal32Trunc16 = -0x1.FEp127f; + *FloatReal32Trunc31 = std::numeric_limits::lowest() + 0x1p-149f; + *DoubleReal32Trunc10 = -0x1.8p127f; + *DoubleReal32Trunc16 = -0x1.FEp127; + *DoubleReal32Trunc31 = std::numeric_limits::lowest() + 0x1p-149f; + writer->Fill(); + + // Fourth entry: min = smallest positive normal values + *FloatReal32Trunc10 = std::numeric_limits::min(); + *FloatReal32Trunc16 = std::numeric_limits::min(); + *FloatReal32Trunc31 = std::numeric_limits::min(); + *DoubleReal32Trunc10 = std::numeric_limits::min(); + *DoubleReal32Trunc16 = std::numeric_limits::min(); + *DoubleReal32Trunc31 = std::numeric_limits::min(); + writer->Fill(); + + // Fifth entry: smallest positive subnormal values with N bits + // (e.g. FloatReal32Trunc10 has a value with all 0s except a 1 in the 10th bit) + *FloatReal32Trunc10 = 0x1p-127f; + *FloatReal32Trunc16 = 0x1p-133f; + *FloatReal32Trunc31 = 0x1p-148f; + *DoubleReal32Trunc10 = 0x1p-127f; + *DoubleReal32Trunc16 = 0x1p-133f; + *DoubleReal32Trunc31 = 0x1p-148f; + writer->Fill(); + + // Sixth entry: maximum values + *FloatReal32Trunc10 = 0x1.8p127f; + *FloatReal32Trunc16 = 0x1.FEp127f; + *FloatReal32Trunc31 = std::numeric_limits::max() - 0x1p-149f; + *DoubleReal32Trunc10 = 0x1.8p127f; + *DoubleReal32Trunc16 = 0x1.FEp127; + *DoubleReal32Trunc31 = std::numeric_limits::max() - 0x1p-149f; + writer->Fill(); +}