Skip to content

Commit 186e42f

Browse files
committed
Add first tests for fundamental types
1 parent 741c38d commit 186e42f

File tree

12 files changed

+603
-0
lines changed

12 files changed

+603
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.json
2+
*.root

types/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Types
2+
3+
* [`fundamental`](fundamental): fundamental column types

types/fundamental/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Fundamental Column Types
2+
3+
* [`integer`](integer): `[U]Int{8,16,32,64}`, `Split[U]Int{16,32,64}`
4+
* [`misc`](misc): `Bit`, `Byte`, `Char`
5+
* [`real`](real): `Real{16,32,64}`, `SplitReal{32,64}`
6+
7+
__Covered under a different category:__
8+
* `[Split]Index{32,64}`
9+
* `Switch`
10+
11+
__Missing:__
12+
* `Real32Trunc`
13+
* `Real32Quant`

types/fundamental/integer/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Integer Column Types
2+
3+
## Fields
4+
5+
* `[U]Int{8,16,32,64}`
6+
* `Split[U]Int{16,32,64}`
7+
8+
with the corresponding column types.
9+
10+
## Entries
11+
12+
1. Ascending values
13+
2. Values in each byte (to validate split encoding)
14+
3. Negative values for signed integer types (to validate zigzag encoding)
15+
4. Minimum (lowest) values
16+
5. Maximum values

types/fundamental/integer/read.C

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#include <ROOT/REntry.hxx>
2+
#include <ROOT/RNTupleReader.hxx>
3+
4+
using ROOT::Experimental::REntry;
5+
using ROOT::Experimental::RNTupleReader;
6+
7+
#include <cstdint>
8+
#include <fstream>
9+
#include <ostream>
10+
#include <string>
11+
#include <string_view>
12+
13+
template <typename T>
14+
static void PrintIntegerValue(const REntry &entry, std::string_view name,
15+
std::ostream &os, bool last = false) {
16+
T value = *entry.GetPtr<T>(name);
17+
os << " \"" << name << "\": ";
18+
// We want to print the integer value even if it is a character; use the unary
19+
// + operator (https://stackoverflow.com/a/28414758).
20+
os << +value;
21+
if (!last) {
22+
os << ",";
23+
}
24+
os << "\n";
25+
}
26+
27+
void read(std::string_view input = "types.fundamental.integer.root",
28+
std::string_view output = "types.fundamental.integer.json") {
29+
std::ofstream os(std::string{output});
30+
os << "[\n";
31+
32+
auto reader = RNTupleReader::Open("ntpl", input);
33+
auto &entry = reader->GetModel().GetDefaultEntry();
34+
bool first = true;
35+
for (auto index : *reader) {
36+
reader->LoadEntry(index);
37+
38+
if (first) {
39+
first = false;
40+
} else {
41+
os << ",\n";
42+
}
43+
os << " {\n";
44+
45+
PrintIntegerValue<std::int8_t>(entry, "Int8", os);
46+
PrintIntegerValue<std::uint8_t>(entry, "UInt8", os);
47+
PrintIntegerValue<std::int16_t>(entry, "Int16", os);
48+
PrintIntegerValue<std::uint16_t>(entry, "UInt16", os);
49+
PrintIntegerValue<std::int32_t>(entry, "Int32", os);
50+
PrintIntegerValue<std::uint32_t>(entry, "UInt32", os);
51+
PrintIntegerValue<std::int64_t>(entry, "Int64", os);
52+
PrintIntegerValue<std::uint64_t>(entry, "UInt64", os);
53+
PrintIntegerValue<std::int16_t>(entry, "SplitInt16", os);
54+
PrintIntegerValue<std::uint16_t>(entry, "SplitUInt16", os);
55+
PrintIntegerValue<std::int32_t>(entry, "SplitInt32", os);
56+
PrintIntegerValue<std::uint32_t>(entry, "SplitUInt32", os);
57+
PrintIntegerValue<std::int64_t>(entry, "SplitInt64", os);
58+
PrintIntegerValue<std::uint64_t>(entry, "SplitUInt64", os, /*last=*/true);
59+
60+
os << " }";
61+
// Newline is intentionally missing, may need to print a comma before the
62+
// next entry.
63+
}
64+
os << "\n";
65+
os << "]\n";
66+
}

types/fundamental/integer/write.C

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#include <ROOT/RField.hxx>
2+
#include <ROOT/RNTupleModel.hxx>
3+
#include <ROOT/RNTupleUtil.hxx>
4+
#include <ROOT/RNTupleWriteOptions.hxx>
5+
#include <ROOT/RNTupleWriter.hxx>
6+
7+
using ROOT::Experimental::EColumnType;
8+
using ROOT::Experimental::RField;
9+
using ROOT::Experimental::RNTupleModel;
10+
using ROOT::Experimental::RNTupleWriteOptions;
11+
using ROOT::Experimental::RNTupleWriter;
12+
13+
#include <cstdint>
14+
#include <limits>
15+
#include <memory>
16+
#include <string_view>
17+
18+
template <typename T>
19+
static std::shared_ptr<T> MakeFundamentalField(RNTupleModel &model,
20+
std::string_view name,
21+
EColumnType type) {
22+
auto field = std::make_unique<RField<T>>(name);
23+
field->SetColumnRepresentatives({{type}});
24+
model.AddField(std::move(field));
25+
return model.GetDefaultEntry().GetPtr<T>(name);
26+
}
27+
28+
void write(std::string_view filename = "types.fundamental.integer.root") {
29+
auto model = RNTupleModel::Create();
30+
31+
auto Int8 =
32+
MakeFundamentalField<std::int8_t>(*model, "Int8", EColumnType::kInt8);
33+
auto UInt8 =
34+
MakeFundamentalField<std::uint8_t>(*model, "UInt8", EColumnType::kUInt8);
35+
36+
// Non-split integer encoding
37+
auto Int16 =
38+
MakeFundamentalField<std::int16_t>(*model, "Int16", EColumnType::kInt16);
39+
auto UInt16 = MakeFundamentalField<std::uint16_t>(*model, "UInt16",
40+
EColumnType::kUInt16);
41+
auto Int32 =
42+
MakeFundamentalField<std::int32_t>(*model, "Int32", EColumnType::kInt32);
43+
auto UInt32 = MakeFundamentalField<std::uint32_t>(*model, "UInt32",
44+
EColumnType::kUInt32);
45+
auto Int64 =
46+
MakeFundamentalField<std::int64_t>(*model, "Int64", EColumnType::kInt64);
47+
auto UInt64 = MakeFundamentalField<std::uint64_t>(*model, "UInt64",
48+
EColumnType::kUInt64);
49+
50+
// Split integer encoding
51+
auto SplitInt16 = MakeFundamentalField<std::int16_t>(
52+
*model, "SplitInt16", EColumnType::kSplitInt16);
53+
auto SplitUInt16 = MakeFundamentalField<std::uint16_t>(
54+
*model, "SplitUInt16", EColumnType::kSplitUInt16);
55+
auto SplitInt32 = MakeFundamentalField<std::int32_t>(
56+
*model, "SplitInt32", EColumnType::kSplitInt32);
57+
auto SplitUInt32 = MakeFundamentalField<std::uint32_t>(
58+
*model, "SplitUInt32", EColumnType::kSplitUInt32);
59+
auto SplitInt64 = MakeFundamentalField<std::int64_t>(
60+
*model, "SplitInt64", EColumnType::kSplitInt64);
61+
auto SplitUInt64 = MakeFundamentalField<std::uint64_t>(
62+
*model, "SplitUInt64", EColumnType::kSplitUInt64);
63+
64+
RNTupleWriteOptions options;
65+
options.SetCompression(0);
66+
auto writer =
67+
RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options);
68+
69+
// First entry: ascending values
70+
*Int8 = 1;
71+
*UInt8 = 2;
72+
*Int16 = 3;
73+
*UInt16 = 4;
74+
*Int32 = 5;
75+
*UInt32 = 6;
76+
*Int64 = 7;
77+
*UInt64 = 8;
78+
*SplitInt16 = 9;
79+
*SplitUInt16 = 10;
80+
*SplitInt32 = 11;
81+
*SplitUInt32 = 12;
82+
*SplitInt64 = 13;
83+
*SplitUInt64 = 14;
84+
writer->Fill();
85+
86+
// Second entry: values in each byte (to validate split encoding)
87+
static constexpr std::uint8_t Value8 = 0x12; // = 18
88+
static constexpr std::uint16_t Value16 = 0x1234; // = 4660
89+
static constexpr std::uint32_t Value32 = 0x12345678; // = 305419896
90+
static constexpr std::uint64_t Value64 =
91+
0x123456780112358c; // = 1311768464885691788
92+
*Int8 = Value8;
93+
*UInt8 = Value8;
94+
*Int16 = Value16;
95+
*UInt16 = Value16;
96+
*Int32 = Value32;
97+
*UInt32 = Value32;
98+
*Int64 = Value64;
99+
*UInt64 = Value64;
100+
*SplitInt16 = Value16;
101+
*SplitUInt16 = Value16;
102+
*SplitInt32 = Value32;
103+
*SplitUInt32 = Value32;
104+
*SplitInt64 = Value64;
105+
*SplitUInt64 = Value64;
106+
writer->Fill();
107+
108+
// Third entry: negative values for signed integer types (to validate zigzag
109+
// encoding)
110+
static constexpr std::int8_t NegativeValue8 = 0x92; // = -110
111+
static constexpr std::int16_t NegativeValue16 = 0x9234; // = -28108
112+
static constexpr std::int32_t NegativeValue32 = 0x92345678; // = -1842063752
113+
static constexpr std::int64_t NegativeValue64 =
114+
0x923456780112358c; // = -7911603571969084020
115+
*Int8 = NegativeValue8;
116+
*UInt8 = Value8;
117+
*Int16 = NegativeValue16;
118+
*UInt16 = Value16;
119+
*Int32 = NegativeValue32;
120+
*UInt32 = Value32;
121+
*Int64 = NegativeValue64;
122+
*UInt64 = Value64;
123+
*SplitInt16 = NegativeValue16;
124+
*SplitUInt16 = Value16;
125+
*SplitInt32 = NegativeValue32;
126+
*SplitUInt32 = Value32;
127+
*SplitInt64 = NegativeValue64;
128+
*SplitUInt64 = Value64;
129+
writer->Fill();
130+
131+
// Fourth entry: minimum (lowest) values
132+
*Int8 = std::numeric_limits<std::int8_t>::lowest();
133+
*UInt8 = std::numeric_limits<std::uint8_t>::lowest();
134+
*Int16 = std::numeric_limits<std::int16_t>::lowest();
135+
*UInt16 = std::numeric_limits<std::uint16_t>::lowest();
136+
*Int32 = std::numeric_limits<std::int32_t>::lowest();
137+
*UInt32 = std::numeric_limits<std::uint32_t>::lowest();
138+
*Int64 = std::numeric_limits<std::int64_t>::lowest();
139+
*UInt64 = std::numeric_limits<std::uint64_t>::lowest();
140+
*SplitInt16 = std::numeric_limits<std::int16_t>::lowest();
141+
*SplitUInt16 = std::numeric_limits<std::uint16_t>::lowest();
142+
*SplitInt32 = std::numeric_limits<std::int32_t>::lowest();
143+
*SplitUInt32 = std::numeric_limits<std::uint32_t>::lowest();
144+
*SplitInt64 = std::numeric_limits<std::int64_t>::lowest();
145+
*SplitUInt64 = std::numeric_limits<std::uint64_t>::lowest();
146+
writer->Fill();
147+
148+
// Fifth entry: maximum values
149+
*Int8 = std::numeric_limits<std::int8_t>::max();
150+
*UInt8 = std::numeric_limits<std::uint8_t>::max();
151+
*Int16 = std::numeric_limits<std::int16_t>::max();
152+
*UInt16 = std::numeric_limits<std::uint16_t>::max();
153+
*Int32 = std::numeric_limits<std::int32_t>::max();
154+
*UInt32 = std::numeric_limits<std::uint32_t>::max();
155+
*Int64 = std::numeric_limits<std::int64_t>::max();
156+
*UInt64 = std::numeric_limits<std::uint64_t>::max();
157+
*SplitInt16 = std::numeric_limits<std::int16_t>::max();
158+
*SplitUInt16 = std::numeric_limits<std::uint16_t>::max();
159+
*SplitInt32 = std::numeric_limits<std::int32_t>::max();
160+
*SplitUInt32 = std::numeric_limits<std::uint32_t>::max();
161+
*SplitInt64 = std::numeric_limits<std::int64_t>::max();
162+
*SplitUInt64 = std::numeric_limits<std::uint64_t>::max();
163+
writer->Fill();
164+
}

types/fundamental/misc/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Integer Column Types
2+
3+
## Fields
4+
5+
* `Bit`
6+
* `Byte`
7+
* `Char`
8+
9+
with the corresponding column types.
10+
11+
## Entries
12+
13+
1. Ascending values
14+
2. Low values
15+
3. High values

types/fundamental/misc/read.C

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include <ROOT/REntry.hxx>
2+
#include <ROOT/RNTupleReader.hxx>
3+
4+
using ROOT::Experimental::REntry;
5+
using ROOT::Experimental::RNTupleReader;
6+
7+
#include <cstddef> // for std::byte
8+
#include <fstream>
9+
#include <ostream>
10+
#include <string>
11+
#include <string_view>
12+
13+
template <typename T>
14+
static void PrintIntegerValue(const REntry &entry, std::string_view name,
15+
std::ostream &os, bool last = false) {
16+
T value = *entry.GetPtr<T>(name);
17+
os << " \"" << name << "\": ";
18+
// We want to print the integer value even if it is a character; use the unary
19+
// + operator (https://stackoverflow.com/a/28414758).
20+
os << +value;
21+
if (!last) {
22+
os << ",";
23+
}
24+
os << "\n";
25+
}
26+
27+
void read(std::string_view input = "types.fundamental.misc.root",
28+
std::string_view output = "types.fundamental.misc.json") {
29+
std::ofstream os(std::string{output});
30+
os << "[\n";
31+
32+
auto reader = RNTupleReader::Open("ntpl", input);
33+
auto &entry = reader->GetModel().GetDefaultEntry();
34+
bool first = true;
35+
for (auto index : *reader) {
36+
reader->LoadEntry(index);
37+
38+
if (first) {
39+
first = false;
40+
} else {
41+
os << ",\n";
42+
}
43+
os << " {\n";
44+
45+
PrintIntegerValue<bool>(entry, "Bit", os);
46+
os << " \"Byte\": ";
47+
os << std::to_integer<int>(*entry.GetPtr<std::byte>("Byte"));
48+
os << ",\n";
49+
PrintIntegerValue<char>(entry, "Char", os, /*last=*/true);
50+
51+
os << " }";
52+
// Newline is intentionally missing, may need to print a comma before the
53+
// next entry.
54+
}
55+
os << "\n";
56+
os << "]\n";
57+
}

0 commit comments

Comments
 (0)