Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RColumnElement.cxx
Go to the documentation of this file.
1/// \file RColumnElement.cxx
2/// \ingroup NTuple
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2019-08-11
5
6/*************************************************************************
7 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14#include "ROOT/RColumn.hxx"
16
17#include "RColumnElement.hxx"
18
19#include <algorithm>
20#include <bitset>
21#include <cassert>
22#include <cstdint>
23#include <memory>
24#include <utility>
25
28
30{
31 switch (type) {
32 case ENTupleColumnType::kIndex64: return std::make_pair(64, 64);
33 case ENTupleColumnType::kIndex32: return std::make_pair(32, 32);
34 case ENTupleColumnType::kSwitch: return std::make_pair(96, 96);
35 case ENTupleColumnType::kByte: return std::make_pair(8, 8);
36 case ENTupleColumnType::kChar: return std::make_pair(8, 8);
37 case ENTupleColumnType::kBit: return std::make_pair(1, 1);
38 case ENTupleColumnType::kReal64: return std::make_pair(64, 64);
39 case ENTupleColumnType::kReal32: return std::make_pair(32, 32);
40 case ENTupleColumnType::kReal16: return std::make_pair(16, 16);
41 case ENTupleColumnType::kInt64: return std::make_pair(64, 64);
42 case ENTupleColumnType::kUInt64: return std::make_pair(64, 64);
43 case ENTupleColumnType::kInt32: return std::make_pair(32, 32);
44 case ENTupleColumnType::kUInt32: return std::make_pair(32, 32);
45 case ENTupleColumnType::kInt16: return std::make_pair(16, 16);
46 case ENTupleColumnType::kUInt16: return std::make_pair(16, 16);
47 case ENTupleColumnType::kInt8: return std::make_pair(8, 8);
48 case ENTupleColumnType::kUInt8: return std::make_pair(8, 8);
49 case ENTupleColumnType::kSplitIndex64: return std::make_pair(64, 64);
50 case ENTupleColumnType::kSplitIndex32: return std::make_pair(32, 32);
51 case ENTupleColumnType::kSplitReal64: return std::make_pair(64, 64);
52 case ENTupleColumnType::kSplitReal32: return std::make_pair(32, 32);
53 case ENTupleColumnType::kSplitInt64: return std::make_pair(64, 64);
54 case ENTupleColumnType::kSplitUInt64: return std::make_pair(64, 64);
55 case ENTupleColumnType::kSplitInt32: return std::make_pair(32, 32);
56 case ENTupleColumnType::kSplitUInt32: return std::make_pair(32, 32);
57 case ENTupleColumnType::kSplitInt16: return std::make_pair(16, 16);
58 case ENTupleColumnType::kSplitUInt16: return std::make_pair(16, 16);
59 case ENTupleColumnType::kReal32Trunc: return std::make_pair(10, 31);
60 case ENTupleColumnType::kReal32Quant: return std::make_pair(1, 32);
61 default:
62 if (type == kTestFutureColumnType)
63 return std::make_pair(32, 32);
64 assert(false);
65 }
66 // never here
67 return std::make_pair(0, 0);
68}
69
71{
72 switch (type) {
73 case ENTupleColumnType::kIndex64: return "Index64";
74 case ENTupleColumnType::kIndex32: return "Index32";
75 case ENTupleColumnType::kSwitch: return "Switch";
76 case ENTupleColumnType::kByte: return "Byte";
77 case ENTupleColumnType::kChar: return "Char";
78 case ENTupleColumnType::kBit: return "Bit";
79 case ENTupleColumnType::kReal64: return "Real64";
80 case ENTupleColumnType::kReal32: return "Real32";
81 case ENTupleColumnType::kReal16: return "Real16";
82 case ENTupleColumnType::kInt64: return "Int64";
83 case ENTupleColumnType::kUInt64: return "UInt64";
84 case ENTupleColumnType::kInt32: return "Int32";
85 case ENTupleColumnType::kUInt32: return "UInt32";
86 case ENTupleColumnType::kInt16: return "Int16";
87 case ENTupleColumnType::kUInt16: return "UInt16";
88 case ENTupleColumnType::kInt8: return "Int8";
89 case ENTupleColumnType::kUInt8: return "UInt8";
90 case ENTupleColumnType::kSplitIndex64: return "SplitIndex64";
91 case ENTupleColumnType::kSplitIndex32: return "SplitIndex32";
92 case ENTupleColumnType::kSplitReal64: return "SplitReal64";
93 case ENTupleColumnType::kSplitReal32: return "SplitReal32";
94 case ENTupleColumnType::kSplitInt64: return "SplitInt64";
95 case ENTupleColumnType::kSplitUInt64: return "SplitUInt64";
96 case ENTupleColumnType::kSplitInt32: return "SplitInt32";
97 case ENTupleColumnType::kSplitUInt32: return "SplitUInt32";
98 case ENTupleColumnType::kSplitInt16: return "SplitInt16";
99 case ENTupleColumnType::kSplitUInt16: return "SplitUInt16";
100 case ENTupleColumnType::kReal32Trunc: return "Real32Trunc";
101 case ENTupleColumnType::kReal32Quant: return "Real32Quant";
102 default:
103 if (type == kTestFutureColumnType)
104 return "TestFutureType";
105 return "UNKNOWN";
106 }
107}
108
109template <>
110std::unique_ptr<ROOT::Internal::RColumnElementBase>
111ROOT::Internal::RColumnElementBase::Generate<void>(ENTupleColumnType onDiskType)
112{
113 //clang-format off
114 switch (onDiskType) {
115 case ENTupleColumnType::kIndex64: return std::make_unique<RColumnElement<RColumnIndex, ENTupleColumnType::kIndex64>>();
116 case ENTupleColumnType::kIndex32: return std::make_unique<RColumnElement<RColumnIndex, ENTupleColumnType::kIndex32>>();
117 case ENTupleColumnType::kSwitch: return std::make_unique<RColumnElement<RColumnSwitch, ENTupleColumnType::kSwitch>>();
118 case ENTupleColumnType::kByte: return std::make_unique<RColumnElement<std::byte, ENTupleColumnType::kByte>>();
119 case ENTupleColumnType::kChar: return std::make_unique<RColumnElement<char, ENTupleColumnType::kChar>>();
120 case ENTupleColumnType::kBit: return std::make_unique<RColumnElement<bool, ENTupleColumnType::kBit>>();
121 case ENTupleColumnType::kReal64: return std::make_unique<RColumnElement<double, ENTupleColumnType::kReal64>>();
122 case ENTupleColumnType::kReal32: return std::make_unique<RColumnElement<float, ENTupleColumnType::kReal32>>();
123 // TODO: Change to std::float16_t in-memory type once available (from C++23).
124 case ENTupleColumnType::kReal16: return std::make_unique<RColumnElement<float, ENTupleColumnType::kReal16>>();
125 case ENTupleColumnType::kInt64: return std::make_unique<RColumnElement<std::int64_t, ENTupleColumnType::kInt64>>();
126 case ENTupleColumnType::kUInt64: return std::make_unique<RColumnElement<std::uint64_t, ENTupleColumnType::kUInt64>>();
127 case ENTupleColumnType::kInt32: return std::make_unique<RColumnElement<std::int32_t, ENTupleColumnType::kInt32>>();
128 case ENTupleColumnType::kUInt32: return std::make_unique<RColumnElement<std::uint32_t, ENTupleColumnType::kUInt32>>();
129 case ENTupleColumnType::kInt16: return std::make_unique<RColumnElement<std::int16_t, ENTupleColumnType::kInt16>>();
130 case ENTupleColumnType::kUInt16: return std::make_unique<RColumnElement<std::uint16_t, ENTupleColumnType::kUInt16>>();
131 case ENTupleColumnType::kInt8: return std::make_unique<RColumnElement<std::int8_t, ENTupleColumnType::kInt8>>();
132 case ENTupleColumnType::kUInt8: return std::make_unique<RColumnElement<std::uint8_t, ENTupleColumnType::kUInt8>>();
133 case ENTupleColumnType::kSplitIndex64: return std::make_unique<RColumnElement<RColumnIndex, ENTupleColumnType::kSplitIndex64>>();
134 case ENTupleColumnType::kSplitIndex32: return std::make_unique<RColumnElement<RColumnIndex, ENTupleColumnType::kSplitIndex32>>();
135 case ENTupleColumnType::kSplitReal64: return std::make_unique<RColumnElement<double, ENTupleColumnType::kSplitReal64>>();
136 case ENTupleColumnType::kSplitReal32: return std::make_unique<RColumnElement<float, ENTupleColumnType::kSplitReal32>>();
137 case ENTupleColumnType::kSplitInt64: return std::make_unique<RColumnElement<std::int64_t, ENTupleColumnType::kSplitInt64>>();
138 case ENTupleColumnType::kSplitUInt64: return std::make_unique<RColumnElement<std::uint64_t, ENTupleColumnType::kSplitUInt64>>();
139 case ENTupleColumnType::kSplitInt32: return std::make_unique<RColumnElement<std::int32_t, ENTupleColumnType::kSplitInt32>>();
140 case ENTupleColumnType::kSplitUInt32: return std::make_unique<RColumnElement<std::uint32_t, ENTupleColumnType::kSplitUInt32>>();
141 case ENTupleColumnType::kSplitInt16: return std::make_unique<RColumnElement<std::int16_t, ENTupleColumnType::kSplitInt16>>();
142 case ENTupleColumnType::kSplitUInt16: return std::make_unique<RColumnElement<std::uint16_t, ENTupleColumnType::kSplitUInt16>>();
143 case ENTupleColumnType::kReal32Trunc: return std::make_unique<RColumnElement<float, ENTupleColumnType::kReal32Trunc>>();
144 case ENTupleColumnType::kReal32Quant: return std::make_unique<RColumnElement<float, ENTupleColumnType::kReal32Quant>>();
145 default:
146 if (onDiskType == kTestFutureColumnType)
147 return std::make_unique<RColumnElement<Internal::RTestFutureColumn, kTestFutureColumnType>>();
148 assert(false);
149 }
150 //clang-format on
151 // never here
152 return nullptr;
153}
154
155std::unique_ptr<ROOT::Internal::RColumnElementBase>
157{
158 if (inMemoryType == std::type_index(typeid(char))) {
160 } else if (inMemoryType == std::type_index(typeid(bool))) {
162 } else if (inMemoryType == std::type_index(typeid(std::byte))) {
164 } else if (inMemoryType == std::type_index(typeid(std::uint8_t))) {
166 } else if (inMemoryType == std::type_index(typeid(std::uint16_t))) {
168 } else if (inMemoryType == std::type_index(typeid(std::uint32_t))) {
170 } else if (inMemoryType == std::type_index(typeid(std::uint64_t))) {
172 } else if (inMemoryType == std::type_index(typeid(std::int8_t))) {
174 } else if (inMemoryType == std::type_index(typeid(std::int16_t))) {
176 } else if (inMemoryType == std::type_index(typeid(std::int32_t))) {
178 } else if (inMemoryType == std::type_index(typeid(std::int64_t))) {
180 } else if (inMemoryType == std::type_index(typeid(float))) {
182 } else if (inMemoryType == std::type_index(typeid(double))) {
184 } else if (inMemoryType == std::type_index(typeid(RColumnIndex))) {
186 } else if (inMemoryType == std::type_index(typeid(RColumnSwitch))) {
188 } else if (inMemoryType == std::type_index(typeid(RTestFutureColumn))) {
190 } else {
191 R__ASSERT(!"Invalid memory type in GenerateColumnElement");
192 }
193 // never here
194 return nullptr;
195}
196
197std::unique_ptr<ROOT::Internal::RColumnElementBase>
202
203void ROOT::Internal::BitPacking::PackBits(void *dst, const void *src, std::size_t count, std::size_t sizeofSrc,
204 std::size_t nDstBits)
205{
206 assert(sizeofSrc <= sizeof(Word_t));
207 assert(0 < nDstBits && nDstBits <= sizeofSrc * 8);
208
209 const unsigned char *srcArray = reinterpret_cast<const unsigned char *>(src);
210 Word_t *dstArray = reinterpret_cast<Word_t *>(dst);
211 Word_t accum = 0;
212 std::size_t bitsUsed = 0;
213 std::size_t dstIdx = 0;
214 for (std::size_t i = 0; i < count; ++i) {
215 Word_t packedWord = 0;
217 // truncate the LSB of the item
218 packedWord >>= sizeofSrc * 8 - nDstBits;
219
220 const std::size_t bitsRem = kBitsPerWord - bitsUsed;
221 if (bitsRem >= nDstBits) {
222 // append the entire item to the accumulator
223 accum |= (packedWord << bitsUsed);
225 } else {
226 // chop up the item into its `bitsRem` LSB bits + `nDstBits - bitsRem` MSB bits.
227 // The LSB bits will be saved in the current word and the MSB will be saved in the next one.
228 if (bitsRem > 0) {
233 }
234
235 memcpy(&dstArray[dstIdx++], &accum, sizeof(accum));
236 accum = 0;
237 bitsUsed = 0;
238
239 if (bitsRem > 0) {
244 } else {
245 // we realigned to a word boundary: append the entire item
248 }
249 }
250 }
251
252 if (bitsUsed)
253 memcpy(&dstArray[dstIdx++], &accum, (bitsUsed + 7) / 8);
254
255 [[maybe_unused]] auto expDstCount = (count * nDstBits + kBitsPerWord - 1) / kBitsPerWord;
257}
258
259void ROOT::Internal::BitPacking::UnpackBits(void *dst, const void *src, std::size_t count, std::size_t sizeofDst,
260 std::size_t nSrcBits)
261{
262 assert(sizeofDst <= sizeof(Word_t));
263 assert(0 < nSrcBits && nSrcBits <= sizeofDst * 8);
264
265 unsigned char *dstArray = reinterpret_cast<unsigned char *>(dst);
266 const Word_t *srcArray = reinterpret_cast<const Word_t *>(src);
267 const auto nWordsToLoad = (count * nSrcBits + kBitsPerWord - 1) / kBitsPerWord;
268
269 // bit offset of the next packed item inside the currently loaded word
270 int offInWord = 0;
271 std::size_t dstIdx = 0;
273 std::size_t remBytesToLoad = (count * nSrcBits + 7) / 8;
274 for (std::size_t i = 0; i < nWordsToLoad; ++i) {
275 assert(dstIdx < count);
276
277 // load the next word, containing some packed items
279 std::size_t bytesLoaded = std::min(remBytesToLoad, sizeof(Word_t));
281
284
285 // If `offInWord` is negative, it means that the last item was split
286 // across 2 words and we need to recombine it.
287 if (offInWord < 0) {
288 std::size_t nMsb = nSrcBits + offInWord;
289 std::uint32_t msb = packedBytes << (8 * sizeofDst - nMsb);
291 prevWordLsb = 0;
293 ++dstIdx;
294 offInWord = nMsb;
295 }
296
297 // isolate each item in the loaded word
298 while (dstIdx < count) {
299 // Check if we need to load a split item or a full one
300 if (offInWord > static_cast<int>(kBitsPerWord - nSrcBits)) {
301 // save the LSB of the next item, next `for` loop will merge them with the MSB in the next word.
302 assert(offInWord <= static_cast<int>(kBitsPerWord));
303 std::size_t nLsbNext = kBitsPerWord - offInWord;
304 if (nLsbNext)
307 break;
308 }
309
313 packedWord <<= 8 * sizeofDst - nSrcBits;
315 ++dstIdx;
317 }
318 }
319
320 assert(prevWordLsb == 0);
321 assert(dstIdx == count);
322}
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
The available trivial, native content types of a column.
static const char * GetColumnTypeName(ROOT::ENTupleColumnType type)
static std::pair< std::uint16_t, std::uint16_t > GetValidBitRange(ROOT::ENTupleColumnType type)
Most types have a fixed on-disk bit width.
The in-memory representation of a 32bit or 64bit on-disk index column.
Holds the index and the tag of a kSwitch column.
void PackBits(void *dst, const void *src, std::size_t count, std::size_t sizeofSrc, std::size_t nDstBits)
Tightly packs count items of size sizeofSrc contained in src into dst using nDstBits per item.
void UnpackBits(void *dst, const void *src, std::size_t count, std::size_t sizeofDst, std::size_t nSrcBits)
Undoes the effect of PackBits.
constexpr std::size_t kBitsPerWord
std::unique_ptr< RColumnElementBase > GenerateColumnElement(std::type_index inMemoryType, ROOT::ENTupleColumnType onDiskType)
ENTupleColumnType
Every concrete RColumnElement type is identified by its on-disk type (column type) and the in-memory ...
static char accum[256]
Definition gifencode.c:210