21#ifndef R__LITTLE_ENDIAN
24#define R__LITTLE_ENDIAN 1
26#define R__LITTLE_ENDIAN 0
38constexpr std::size_t
MinBufSize(std::size_t count, std::size_t nDstBits)
40 return (count * nDstBits + 7) / 8;
48void PackBits(
void *dst,
const void *
src, std::size_t count, std::size_t sizeofSrc, std::size_t nDstBits);
54void UnpackBits(
void *dst,
const void *
src, std::size_t count, std::size_t sizeofDst, std::size_t nSrcBits);
86template <std::
size_t N>
87inline void CopyBswap(
void *destination,
const void *source, std::size_t count)
91 for (std::size_t i = 0; i < count; ++i) {
96template <std::
size_t N>
97void InPlaceBswap(
void *array, std::size_t count)
100 for (std::size_t i = 0; i < count; ++i) {
106#if R__LITTLE_ENDIAN == 0
108inline void ByteSwapIfNecessary(T &
value)
110 constexpr auto N =
sizeof(
T);
112 void *valuePtr = &
value;
114 *
reinterpret_cast<bswap_value_type *
>(valuePtr) = swapped;
117inline void ByteSwapIfNecessary<char>(
char &)
121inline void ByteSwapIfNecessary<signed char>(
signed char &)
125inline void ByteSwapIfNecessary<unsigned char>(
unsigned char &)
129#define ByteSwapIfNecessary(x) ((void)0)
133template <
typename DestT,
typename SourceT>
134inline void EnsureValidRange(SourceT val [[maybe_unused]])
138 if constexpr (!std::is_integral_v<DestT> || !std::is_integral_v<SourceT>)
141 if constexpr (
static_cast<double>(std::numeric_limits<SourceT>::min()) <
142 static_cast<double>(std::numeric_limits<DestT>::min())) {
143 if constexpr (!std::is_signed_v<DestT>) {
145 throw RException(
R__FAIL(std::string(
"value out of range: ") + std::to_string(val) +
" for type " +
146 typeid(DestT).
name()));
148 }
else if (val < std::numeric_limits<DestT>::min()) {
150 R__FAIL(std::string(
"value out of range: ") + std::to_string(val) +
" for type " +
typeid(DestT).
name()));
154 if constexpr (
static_cast<double>(std::numeric_limits<SourceT>::max()) >
155 static_cast<double>(std::numeric_limits<DestT>::max())) {
156 if (val > std::numeric_limits<DestT>::max()) {
158 R__FAIL(std::string(
"value out of range: ") + std::to_string(val) +
" for type " +
typeid(DestT).
name()));
167template <
typename DestT,
typename SourceT>
168inline void CastPack(
void *destination,
const void *source, std::size_t count)
170 static_assert(std::is_convertible_v<SourceT, DestT>);
171 auto dst =
reinterpret_cast<DestT *
>(destination);
172 auto src =
reinterpret_cast<const SourceT *
>(source);
173 for (std::size_t i = 0; i < count; ++i) {
175 ByteSwapIfNecessary(dst[i]);
183template <
typename DestT,
typename SourceT>
184inline void CastUnpack(
void *destination,
const void *source, std::size_t count)
186 auto dst =
reinterpret_cast<DestT *
>(destination);
187 auto src =
reinterpret_cast<const SourceT *
>(source);
188 for (std::size_t i = 0; i < count; ++i) {
189 SourceT val =
src[i];
190 ByteSwapIfNecessary(val);
191 EnsureValidRange<DestT, SourceT>(val);
199template <
typename DestT,
typename SourceT>
200inline void CastSplitPack(
void *destination,
const void *source, std::size_t count)
202 constexpr std::size_t
N =
sizeof(DestT);
203 auto splitArray =
reinterpret_cast<char *
>(destination);
204 auto src =
reinterpret_cast<const SourceT *
>(source);
205 for (std::size_t i = 0; i < count; ++i) {
207 ByteSwapIfNecessary(val);
208 for (std::size_t
b = 0;
b <
N; ++
b) {
209 splitArray[
b * count + i] =
reinterpret_cast<const char *
>(&val)[
b];
217template <
typename DestT,
typename SourceT>
218inline void CastSplitUnpack(
void *destination,
const void *source, std::size_t count)
220 constexpr std::size_t
N =
sizeof(SourceT);
221 auto dst =
reinterpret_cast<DestT *
>(destination);
222 auto splitArray =
reinterpret_cast<const char *
>(source);
223 for (std::size_t i = 0; i < count; ++i) {
225 for (std::size_t
b = 0;
b <
N; ++
b) {
226 reinterpret_cast<char *
>(&val)[
b] = splitArray[
b * count + i];
228 ByteSwapIfNecessary(val);
229 EnsureValidRange<DestT, SourceT>(val);
237template <
typename DestT,
typename SourceT>
238inline void CastDeltaSplitPack(
void *destination,
const void *source, std::size_t count)
240 constexpr std::size_t
N =
sizeof(DestT);
241 auto src =
reinterpret_cast<const SourceT *
>(source);
242 auto splitArray =
reinterpret_cast<char *
>(destination);
243 for (std::size_t i = 0; i < count; ++i) {
244 DestT val = (i == 0) ?
src[0] :
src[i] -
src[i - 1];
245 ByteSwapIfNecessary(val);
246 for (std::size_t
b = 0;
b <
N; ++
b) {
247 splitArray[
b * count + i] =
reinterpret_cast<char *
>(&val)[
b];
255template <
typename DestT,
typename SourceT>
256inline void CastDeltaSplitUnpack(
void *destination,
const void *source, std::size_t count)
258 constexpr std::size_t
N =
sizeof(SourceT);
259 auto splitArray =
reinterpret_cast<const char *
>(source);
260 auto dst =
reinterpret_cast<DestT *
>(destination);
261 for (std::size_t i = 0; i < count; ++i) {
263 for (std::size_t
b = 0;
b <
N; ++
b) {
264 reinterpret_cast<char *
>(&val)[
b] = splitArray[
b * count + i];
266 ByteSwapIfNecessary(val);
267 val = (i == 0) ? val : val + dst[i - 1];
268 EnsureValidRange<DestT, SourceT>(val);
276template <
typename DestT,
typename SourceT>
277inline void CastZigzagSplitPack(
void *destination,
const void *source, std::size_t count)
279 using UDestT = std::make_unsigned_t<DestT>;
280 constexpr std::size_t kNBitsDestT =
sizeof(DestT) * 8;
281 constexpr std::size_t
N =
sizeof(DestT);
282 auto src =
reinterpret_cast<const SourceT *
>(source);
283 auto splitArray =
reinterpret_cast<char *
>(destination);
284 for (std::size_t i = 0; i < count; ++i) {
285 UDestT val = (
static_cast<DestT
>(
src[i]) << 1) ^ (
static_cast<DestT
>(
src[i]) >> (kNBitsDestT - 1));
286 ByteSwapIfNecessary(val);
287 for (std::size_t
b = 0;
b <
N; ++
b) {
288 splitArray[
b * count + i] =
reinterpret_cast<char *
>(&val)[
b];
296template <
typename DestT,
typename SourceT>
297inline void CastZigzagSplitUnpack(
void *destination,
const void *source, std::size_t count)
299 using USourceT = std::make_unsigned_t<SourceT>;
300 constexpr std::size_t
N =
sizeof(SourceT);
301 auto splitArray =
reinterpret_cast<const char *
>(source);
302 auto dst =
reinterpret_cast<DestT *
>(destination);
303 for (std::size_t i = 0; i < count; ++i) {
305 for (std::size_t
b = 0;
b <
N; ++
b) {
306 reinterpret_cast<char *
>(&val)[
b] = splitArray[
b * count + i];
308 ByteSwapIfNecessary(val);
309 SourceT sval =
static_cast<SourceT
>((val >> 1) ^ -(
static_cast<SourceT
>(val) & 1));
310 EnsureValidRange<DestT, SourceT>(sval);
324 static_cast<EColumnType>(std::numeric_limits<std::underlying_type_t<EColumnType>>::max() - 1);
326template <
typename CppT, EColumnType>
329template <
typename CppT>
330std::unique_ptr<RColumnElementBase> GenerateColumnElementInternal(
EColumnType onDiskType)
332 switch (onDiskType) {
333 case EColumnType::kIndex64:
return std::make_unique<RColumnElement<CppT, EColumnType::kIndex64>>();
334 case EColumnType::kIndex32:
return std::make_unique<RColumnElement<CppT, EColumnType::kIndex32>>();
335 case EColumnType::kSwitch:
return std::make_unique<RColumnElement<CppT, EColumnType::kSwitch>>();
336 case EColumnType::kByte:
return std::make_unique<RColumnElement<CppT, EColumnType::kByte>>();
337 case EColumnType::kChar:
return std::make_unique<RColumnElement<CppT, EColumnType::kChar>>();
338 case EColumnType::kBit:
return std::make_unique<RColumnElement<CppT, EColumnType::kBit>>();
339 case EColumnType::kReal64:
return std::make_unique<RColumnElement<CppT, EColumnType::kReal64>>();
340 case EColumnType::kReal32:
return std::make_unique<RColumnElement<CppT, EColumnType::kReal32>>();
341 case EColumnType::kReal16:
return std::make_unique<RColumnElement<CppT, EColumnType::kReal16>>();
342 case EColumnType::kInt64:
return std::make_unique<RColumnElement<CppT, EColumnType::kInt64>>();
343 case EColumnType::kUInt64:
return std::make_unique<RColumnElement<CppT, EColumnType::kUInt64>>();
344 case EColumnType::kInt32:
return std::make_unique<RColumnElement<CppT, EColumnType::kInt32>>();
345 case EColumnType::kUInt32:
return std::make_unique<RColumnElement<CppT, EColumnType::kUInt32>>();
346 case EColumnType::kInt16:
return std::make_unique<RColumnElement<CppT, EColumnType::kInt16>>();
347 case EColumnType::kUInt16:
return std::make_unique<RColumnElement<CppT, EColumnType::kUInt16>>();
348 case EColumnType::kInt8:
return std::make_unique<RColumnElement<CppT, EColumnType::kInt8>>();
349 case EColumnType::kUInt8:
return std::make_unique<RColumnElement<CppT, EColumnType::kUInt8>>();
350 case EColumnType::kSplitIndex64:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitIndex64>>();
351 case EColumnType::kSplitIndex32:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitIndex32>>();
352 case EColumnType::kSplitReal64:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitReal64>>();
353 case EColumnType::kSplitReal32:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitReal32>>();
354 case EColumnType::kSplitInt64:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt64>>();
355 case EColumnType::kSplitUInt64:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitUInt64>>();
356 case EColumnType::kSplitInt32:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt32>>();
357 case EColumnType::kSplitUInt32:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitUInt32>>();
358 case EColumnType::kSplitInt16:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt16>>();
359 case EColumnType::kSplitUInt16:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitUInt16>>();
360 case EColumnType::kReal32Trunc:
return std::make_unique<RColumnElement<CppT, EColumnType::kReal32Trunc>>();
361 case EColumnType::kReal32Quant:
return std::make_unique<RColumnElement<CppT, EColumnType::kReal32Quant>>();
363 if (onDiskType == kTestFutureType)
364 return std::make_unique<RColumnElement<CppT, kTestFutureType>>();
375template <
typename CppT>
376class RColumnElementLE :
public RColumnElementBase {
378 explicit RColumnElementLE(std::size_t
size, std::size_t bitsOnStorage) : RColumnElementBase(
size, bitsOnStorage) {}
383 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
385#if R__LITTLE_ENDIAN == 1
386 RColumnElementBase::Pack(dst,
src, count);
388 CopyBswap<sizeof(CppT)>(dst,
src, count);
391 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
393#if R__LITTLE_ENDIAN == 1
394 RColumnElementBase::Unpack(dst,
src, count);
396 CopyBswap<sizeof(CppT)>(dst,
src, count);
405template <
typename CppT,
typename NarrowT>
406class RColumnElementCastLE :
public RColumnElementBase {
408 explicit RColumnElementCastLE(std::size_t
size, std::size_t bitsOnStorage) : RColumnElementBase(
size, bitsOnStorage)
413 static constexpr bool kIsMappable =
false;
415 void Pack(
void *dst,
const void *
src, std::size_t count)
const final { CastPack<NarrowT, CppT>(dst,
src, count); }
416 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
418 CastUnpack<CppT, NarrowT>(dst,
src, count);
427template <
typename CppT,
typename NarrowT>
428class RColumnElementSplitLE :
public RColumnElementBase {
430 explicit RColumnElementSplitLE(std::size_t
size, std::size_t bitsOnStorage) : RColumnElementBase(
size, bitsOnStorage)
435 static constexpr bool kIsMappable =
false;
437 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
439 CastSplitPack<NarrowT, CppT>(dst,
src, count);
441 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
443 CastSplitUnpack<CppT, NarrowT>(dst,
src, count);
452template <
typename CppT,
typename NarrowT>
453class RColumnElementDeltaSplitLE :
public RColumnElementBase {
455 explicit RColumnElementDeltaSplitLE(std::size_t
size, std::size_t bitsOnStorage)
456 : RColumnElementBase(
size, bitsOnStorage)
461 static constexpr bool kIsMappable =
false;
463 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
465 CastDeltaSplitPack<NarrowT, CppT>(dst,
src, count);
467 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
469 CastDeltaSplitUnpack<CppT, NarrowT>(dst,
src, count);
474template <
typename CppIntT>
475class RColumnElementBoolAsUnsplitInt :
public RColumnElementBase {
477 explicit RColumnElementBoolAsUnsplitInt(std::size_t
size, std::size_t bitsOnStorage)
478 : RColumnElementBase(
size, bitsOnStorage)
483 static constexpr bool kIsMappable =
false;
486 void Pack(
void *,
const void *, std::size_t)
const final {
R__ASSERT(
false); }
488 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
490 auto *boolArray =
reinterpret_cast<bool *
>(dst);
491 auto *intArray =
reinterpret_cast<const CppIntT *
>(
src);
492 for (std::size_t i = 0; i < count; ++i) {
493 boolArray[i] = intArray[i] != 0;
499template <
typename CppIntT>
500class RColumnElementBoolAsSplitInt :
public RColumnElementBase {
502 explicit RColumnElementBoolAsSplitInt(std::size_t
size, std::size_t bitsOnStorage)
503 : RColumnElementBase(
size, bitsOnStorage)
508 static constexpr bool kIsMappable =
false;
511 void Pack(
void *,
const void *, std::size_t)
const final {
R__ASSERT(
false); }
513 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
515 constexpr std::size_t
N =
sizeof(CppIntT);
516 auto *boolArray =
reinterpret_cast<bool *
>(dst);
517 auto *splitArray =
reinterpret_cast<const char *
>(
src);
518 for (std::size_t i = 0; i < count; ++i) {
519 boolArray[i] =
false;
520 for (std::size_t
b = 0;
b <
N; ++
b) {
521 if (splitArray[
b * count + i]) {
531template <
typename CppIntT>
532class RColumnElementIntAsBool :
public RColumnElementBase {
534 explicit RColumnElementIntAsBool(std::size_t
size, std::size_t bitsOnStorage)
535 : RColumnElementBase(
size, bitsOnStorage)
540 static constexpr bool kIsMappable =
false;
543 void Pack(
void *,
const void *, std::size_t)
const final {
R__ASSERT(
false); }
545 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
547 auto *intArray =
reinterpret_cast<CppIntT *
>(dst);
548 const char *charArray =
reinterpret_cast<const char *
>(
src);
549 std::bitset<8> bitSet;
550 for (std::size_t i = 0; i < count; i += 8) {
551 bitSet = charArray[i / 8];
552 for (std::size_t j = i; j < std::min(count, i + 8); ++j) {
553 intArray[j] = bitSet[j % 8];
564template <
typename CppT,
typename NarrowT>
565class RColumnElementZigzagSplitLE :
public RColumnElementBase {
567 explicit RColumnElementZigzagSplitLE(std::size_t
size, std::size_t bitsOnStorage)
568 : RColumnElementBase(
size, bitsOnStorage)
573 static constexpr bool kIsMappable =
false;
575 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
577 CastZigzagSplitPack<NarrowT, CppT>(dst,
src, count);
579 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
581 CastZigzagSplitUnpack<CppT, NarrowT>(dst,
src, count);
593template <
typename CppT, EColumnType ColumnT = EColumnType::kUnknown>
594class RColumnElement :
public RColumnElementBase {
596 RColumnElement() : RColumnElementBase(sizeof(CppT))
599 R__FAIL(std::string(
"internal error: no column mapping for this C++ type: ") +
typeid(CppT).
name() +
" --> " +
600 GetColumnTypeName(ColumnT)));
603 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(CppT), EColumnType::kUnknown}; }
609 static constexpr std::size_t
kSize =
sizeof(
bool);
610 RColumnElement() : RColumnElementBase(
kSize) {}
611 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
bool), EColumnType::kUnknown}; }
615class RColumnElement<std::
byte, EColumnType::kUnknown> :
public RColumnElementBase {
617 static constexpr std::size_t
kSize =
sizeof(std::byte);
618 RColumnElement() : RColumnElementBase(
kSize) {}
619 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::byte), EColumnType::kUnknown}; }
625 static constexpr std::size_t
kSize =
sizeof(char);
626 RColumnElement() : RColumnElementBase(
kSize) {}
627 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(char), EColumnType::kUnknown}; }
631class RColumnElement<std::int8_t, EColumnType::kUnknown> :
public RColumnElementBase {
633 static constexpr std::size_t
kSize =
sizeof(std::int8_t);
634 RColumnElement() : RColumnElementBase(
kSize) {}
635 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::int8_t), EColumnType::kUnknown}; }
639class RColumnElement<std::uint8_t, EColumnType::kUnknown> :
public RColumnElementBase {
641 static constexpr std::size_t
kSize =
sizeof(std::uint8_t);
642 RColumnElement() : RColumnElementBase(
kSize) {}
643 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::uint8_t), EColumnType::kUnknown}; }
647class RColumnElement<std::int16_t, EColumnType::kUnknown> :
public RColumnElementBase {
649 static constexpr std::size_t
kSize =
sizeof(std::int16_t);
650 RColumnElement() : RColumnElementBase(
kSize) {}
651 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::int16_t), EColumnType::kUnknown}; }
655class RColumnElement<std::uint16_t, EColumnType::kUnknown> :
public RColumnElementBase {
657 static constexpr std::size_t
kSize =
sizeof(std::uint16_t);
658 RColumnElement() : RColumnElementBase(
kSize) {}
659 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::uint16_t), EColumnType::kUnknown}; }
663class RColumnElement<std::int32_t, EColumnType::kUnknown> :
public RColumnElementBase {
665 static constexpr std::size_t
kSize =
sizeof(std::int32_t);
666 RColumnElement() : RColumnElementBase(
kSize) {}
667 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::int32_t), EColumnType::kUnknown}; }
671class RColumnElement<std::uint32_t, EColumnType::kUnknown> :
public RColumnElementBase {
673 static constexpr std::size_t
kSize =
sizeof(std::uint32_t);
674 RColumnElement() : RColumnElementBase(
kSize) {}
675 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::uint32_t), EColumnType::kUnknown}; }
679class RColumnElement<std::int64_t, EColumnType::kUnknown> :
public RColumnElementBase {
681 static constexpr std::size_t
kSize =
sizeof(std::int64_t);
682 RColumnElement() : RColumnElementBase(
kSize) {}
683 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::int64_t), EColumnType::kUnknown}; }
687class RColumnElement<std::uint64_t, EColumnType::kUnknown> :
public RColumnElementBase {
689 static constexpr std::size_t
kSize =
sizeof(std::uint64_t);
690 RColumnElement() : RColumnElementBase(
kSize) {}
691 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::uint64_t), EColumnType::kUnknown}; }
697 static constexpr std::size_t
kSize =
sizeof(float);
698 RColumnElement() : RColumnElementBase(
kSize) {}
699 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(float), EColumnType::kUnknown}; }
705 static constexpr std::size_t
kSize =
sizeof(
double);
706 RColumnElement() : RColumnElementBase(
kSize) {}
707 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
double), EColumnType::kUnknown}; }
711class RColumnElement<
ROOT::Experimental::ClusterSize_t, EColumnType::kUnknown> :
public RColumnElementBase {
714 RColumnElement() : RColumnElementBase(
kSize) {}
715 RIdentifier GetIdentifier() const final
722class RColumnElement<
ROOT::Experimental::RColumnSwitch, EColumnType::kUnknown> :
public RColumnElementBase {
725 RColumnElement() : RColumnElementBase(
kSize) {}
726 RIdentifier GetIdentifier() const final
738class RColumnElement<
ROOT::Experimental::RColumnSwitch, EColumnType::kSwitch> :
public RColumnElementBase {
740 struct RSwitchElement {
741 std::uint64_t fIndex;
746 static constexpr bool kIsMappable =
false;
748 static constexpr std::size_t kBitsOnStorage = 96;
749 RColumnElement() : RColumnElementBase(
kSize, kBitsOnStorage) {}
750 bool IsMappable() const final {
return kIsMappable; }
752 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
755 auto dstArray =
reinterpret_cast<unsigned char *
>(dst);
756 for (std::size_t i = 0; i < count; ++i) {
757 RSwitchElement element{srcArray[i].
GetIndex(), srcArray[i].GetTag()};
758#if R__LITTLE_ENDIAN == 0
762 memcpy(dstArray + i * 12, &element, 12);
766 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
768 auto srcArray =
reinterpret_cast<const unsigned char *
>(
src);
770 for (std::size_t i = 0; i < count; ++i) {
771 RSwitchElement element;
772 memcpy(&element, srcArray + i * 12, 12);
773#if R__LITTLE_ENDIAN == 0
782 RIdentifier GetIdentifier() const final
791 static constexpr bool kIsMappable =
false;
792 static constexpr std::size_t
kSize =
sizeof(
bool);
793 static constexpr std::size_t kBitsOnStorage = 1;
794 RColumnElement() : RColumnElementBase(
kSize, kBitsOnStorage) {}
795 bool IsMappable() const final {
return kIsMappable; }
797 void Pack(
void *dst,
const void *
src, std::size_t count)
const final;
798 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final;
800 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
bool), EColumnType::kBit}; }
806 static constexpr bool kIsMappable =
false;
807 static constexpr std::size_t
kSize =
sizeof(float);
808 static constexpr std::size_t kBitsOnStorage = 16;
809 RColumnElement() : RColumnElementBase(
kSize, kBitsOnStorage) {}
810 bool IsMappable() const final {
return kIsMappable; }
812 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
814 const float *floatArray =
reinterpret_cast<const float *
>(
src);
815 std::uint16_t *uint16Array =
reinterpret_cast<std::uint16_t *
>(dst);
817 for (std::size_t i = 0; i < count; ++i) {
819 ByteSwapIfNecessary(uint16Array[i]);
823 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
825 float *floatArray =
reinterpret_cast<float *
>(dst);
826 const std::uint16_t *uint16Array =
reinterpret_cast<const std::uint16_t *
>(
src);
828 for (std::size_t i = 0; i < count; ++i) {
829 std::uint16_t val = uint16Array[i];
830 ByteSwapIfNecessary(val);
835 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(float), EColumnType::kReal16}; }
841 static constexpr bool kIsMappable =
false;
842 static constexpr std::size_t
kSize =
sizeof(
double);
843 static constexpr std::size_t kBitsOnStorage = 16;
844 RColumnElement() : RColumnElementBase(
kSize, kBitsOnStorage) {}
845 bool IsMappable() const final {
return kIsMappable; }
847 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
849 const double *doubleArray =
reinterpret_cast<const double *
>(
src);
850 std::uint16_t *uint16Array =
reinterpret_cast<std::uint16_t *
>(dst);
852 for (std::size_t i = 0; i < count; ++i) {
854 ByteSwapIfNecessary(uint16Array[i]);
858 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
860 double *doubleArray =
reinterpret_cast<double *
>(dst);
861 const std::uint16_t *uint16Array =
reinterpret_cast<const std::uint16_t *
>(
src);
863 for (std::size_t i = 0; i < count; ++i) {
864 std::uint16_t val = uint16Array[i];
865 ByteSwapIfNecessary(val);
870 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
double), EColumnType::kReal16}; }
874class RColumnElementTrunc :
public RColumnElementBase {
876 static_assert(std::is_floating_point_v<T>);
877 static constexpr bool kIsMappable =
false;
878 static constexpr std::size_t
kSize =
sizeof(
T);
883 RColumnElementTrunc() : RColumnElementBase(
kSize, 0) {}
885 void SetBitsOnStorage(std::size_t bitsOnStorage)
final
887 const auto &[minBits, maxBits] = GetValidBitRange(EColumnType::kReal32Trunc);
888 R__ASSERT(bitsOnStorage >= minBits && bitsOnStorage <= maxBits);
889 fBitsOnStorage = bitsOnStorage;
892 bool IsMappable() const final {
return kIsMappable; }
894 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
T), EColumnType::kReal32Trunc}; }
900 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
906#if R__LITTLE_ENDIAN == 0
909 auto bswapped = std::make_unique<float[]>(count);
910 CopyBswap<sizeof(float)>(bswapped.get(),
src, count);
911 const auto *srcLe = bswapped.get();
913 const auto *srcLe =
reinterpret_cast<const float *
>(
src);
915 PackBits(dst, srcLe, count,
sizeof(
float), fBitsOnStorage);
918 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
925#if R__LITTLE_ENDIAN == 0
926 InPlaceBswap<sizeof(float)>(dst, count);
934 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
942 auto srcFloat = std::make_unique<float[]>(count);
943 const double *srcDouble =
reinterpret_cast<const double *
>(
src);
944 for (std::size_t i = 0; i < count; ++i)
945 srcFloat[i] =
static_cast<float>(srcDouble[i]);
947#if R__LITTLE_ENDIAN == 0
950 auto bswapped = std::make_unique<float[]>(count);
951 CopyBswap<sizeof(float)>(bswapped.get(), srcFloat.get(), count);
952 const float *srcLe = bswapped.get();
954 const float *srcLe =
reinterpret_cast<const float *
>(srcFloat.get());
956 PackBits(dst, srcLe, count,
sizeof(
float), fBitsOnStorage);
959 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
966 auto dstFloat = std::make_unique<float[]>(count);
967 UnpackBits(dstFloat.get(),
src, count,
sizeof(
float), fBitsOnStorage);
968#if R__LITTLE_ENDIAN == 0
969 InPlaceBswap<sizeof(float)>(dstFloat.get(), count);
972 double *dstDouble =
reinterpret_cast<double *
>(dst);
973 for (std::size_t i = 0; i < count; ++i)
974 dstDouble[i] =
static_cast<double>(dstFloat[i]);
980using Quantized_t = std::uint32_t;
982[[maybe_unused]]
inline std::size_t LeadingZeroes(std::uint32_t
x)
988 unsigned long idx = 0;
989 _BitScanForward(&idx,
x);
990 return static_cast<std::size_t
>(idx);
992 return static_cast<std::size_t
>(__builtin_clzl(
x));
996[[maybe_unused]]
inline std::size_t TrailingZeroes(std::uint32_t
x)
1002 unsigned long idx = 0;
1003 _BitScanReverse(&idx,
x);
1004 return static_cast<std::size_t
>(idx);
1006 return static_cast<std::size_t
>(__builtin_ctzl(
x));
1016template <
typename T>
1017int QuantizeReals(Quantized_t *dst,
const T *
src, std::size_t count,
double min,
double max, std::size_t nQuantBits)
1019 static_assert(std::is_floating_point_v<T>);
1020 static_assert(
sizeof(T) <=
sizeof(
double));
1021 assert(1 <= nQuantBits && nQuantBits <= 8 *
sizeof(Quantized_t));
1023 const std::size_t quantMax = (1ull << nQuantBits) - 1;
1024 const double scale = quantMax / (max - min);
1025 const std::size_t unusedBits =
sizeof(Quantized_t) * 8 - nQuantBits;
1027 int nOutOfRange = 0;
1029 for (std::size_t i = 0; i < count; ++i) {
1030 const T elem =
src[i];
1032 nOutOfRange += !(min <= elem && elem <= max);
1034 const double e = 0.5 + (elem - min) * scale;
1035 Quantized_t
q =
static_cast<Quantized_t
>(
e);
1036 ByteSwapIfNecessary(
q);
1039 assert(LeadingZeroes(
q) >= unusedBits);
1043 dst[i] =
q << unusedBits;
1051template <
typename T>
1052int UnquantizeReals(T *dst,
const Quantized_t *
src, std::size_t count,
double min,
double max, std::size_t nQuantBits)
1054 static_assert(std::is_floating_point_v<T>);
1055 static_assert(
sizeof(T) <=
sizeof(
double));
1056 assert(1 <= nQuantBits && nQuantBits <= 8 *
sizeof(Quantized_t));
1058 const std::size_t quantMax = (1ull << nQuantBits) - 1;
1059 const double scale = (max - min) / quantMax;
1060 const std::size_t unusedBits =
sizeof(Quantized_t) * 8 - nQuantBits;
1061 const double eps = std::numeric_limits<double>::epsilon();
1062 const double emin = -eps * scale + min;
1063 const double emax = (
static_cast<double>(quantMax) + eps) * scale + min;
1065 int nOutOfRange = 0;
1067 for (std::size_t i = 0; i < count; ++i) {
1068 Quantized_t elem =
src[i];
1070 assert(TrailingZeroes(elem) >= unusedBits);
1071 elem >>= unusedBits;
1072 ByteSwapIfNecessary(elem);
1074 const double fq =
static_cast<double>(elem);
1075 const double e = fq * scale + min;
1076 dst[i] =
static_cast<T
>(
e);
1078 nOutOfRange += !(emin <= dst[i] && dst[i] <= emax);
1085template <
typename T>
1087 static_assert(std::is_floating_point_v<T>);
1090 static constexpr bool kIsMappable =
false;
1091 static constexpr std::size_t
kSize =
sizeof(T);
1095 void SetBitsOnStorage(std::size_t bitsOnStorage)
final
1097 const auto [minBits, maxBits] = GetValidBitRange(EColumnType::kReal32Quant);
1098 R__ASSERT(bitsOnStorage >= minBits && bitsOnStorage <= maxBits);
1099 fBitsOnStorage = bitsOnStorage;
1102 void SetValueRange(
double min,
double max)
final
1104 R__ASSERT(min >= std::numeric_limits<T>::lowest());
1105 R__ASSERT(max <= std::numeric_limits<T>::max());
1106 fValueRange = {min,
max};
1109 bool IsMappable() const final {
return kIsMappable; }
1111 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
1116 auto quantized = std::make_unique<Quantize::Quantized_t[]>(count);
1117 assert(fValueRange);
1118 const auto [min,
max] = *fValueRange;
1119 const int nOutOfRange =
1120 Quantize::QuantizeReals(quantized.get(),
reinterpret_cast<const T *
>(
src), count, min, max, fBitsOnStorage);
1123 " values were found of of range for quantization while packing (range is [" +
1124 std::to_string(min) +
", " + std::to_string(max) +
"])"));
1126 Internal::BitPacking::PackBits(dst, quantized.get(), count,
sizeof(Quantize::Quantized_t), fBitsOnStorage);
1129 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
1134 auto quantized = std::make_unique<Quantize::Quantized_t[]>(count);
1135 assert(fValueRange);
1136 const auto [min,
max] = *fValueRange;
1137 Internal::BitPacking::UnpackBits(quantized.get(),
src, count,
sizeof(Quantize::Quantized_t), fBitsOnStorage);
1138 [[maybe_unused]]
const int nOutOfRange =
1139 Quantize::UnquantizeReals(
reinterpret_cast<T *
>(dst), quantized.get(), count, min, max, fBitsOnStorage);
1143 assert(nOutOfRange == 0);
1146 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
T), EColumnType::kReal32Quant}; }
1155#define __RCOLUMNELEMENT_SPEC_BODY(CppT, ColumnT, BaseT, BitsOnStorage) \
1156 static constexpr std::size_t kSize = sizeof(CppT); \
1157 static constexpr std::size_t kBitsOnStorage = BitsOnStorage; \
1158 RColumnElement() : BaseT(kSize, kBitsOnStorage) {} \
1159 bool IsMappable() const final \
1161 return kIsMappable; \
1163 RIdentifier GetIdentifier() const final \
1165 return RIdentifier{typeid(CppT), ColumnT}; \
1173#define DECLARE_RCOLUMNELEMENT_SPEC(CppT, ColumnT, BitsOnStorage, BaseT, ...) \
1175 class RColumnElement<CppT, ColumnT> : public BaseT __VA_ARGS__ { \
1177 __RCOLUMNELEMENT_SPEC_BODY(CppT, ColumnT, BaseT, BitsOnStorage) \
1179#define DECLARE_RCOLUMNELEMENT_SPEC_SIMPLE(CppT, ColumnT, BitsOnStorage) \
1181 class RColumnElement<CppT, ColumnT> : public RColumnElementBase { \
1183 static constexpr bool kIsMappable = true; \
1184 __RCOLUMNELEMENT_SPEC_BODY(CppT, ColumnT, RColumnElementBase, BitsOnStorage) \
1232 <std::int8_t, std::int16_t>);
1234 <std::int8_t, std::uint16_t>);
1236 <std::int8_t, std::int32_t>);
1238 <std::int8_t, std::uint32_t>);
1240 <std::int8_t, std::int64_t>);
1242 <std::int8_t, std::uint64_t>);
1250 <std::uint8_t, std::uint16_t>);
1253 <std::uint8_t, std::uint32_t>);
1256 <std::uint8_t, std::uint64_t>);
1258 <std::uint8_t, std::int16_t>);
1260 <std::uint8_t, std::uint16_t>);
1262 <std::uint8_t, std::int32_t>);
1264 <std::uint8_t, std::uint32_t>);
1266 <std::uint8_t, std::int64_t>);
1268 <std::uint8_t, std::uint64_t>);
1273 <std::int16_t, std::int16_t>);
1278 <std::int16_t, std::uint16_t>);
1281 <std::int16_t, std::uint32_t>);
1284 <std::int16_t, std::uint64_t>);
1286 <std::int16_t, std::uint16_t>);
1288 <std::int16_t, std::int32_t>);
1290 <std::int16_t, std::uint32_t>);
1292 <std::int16_t, std::int64_t>);
1294 <std::int16_t, std::uint64_t>);
1299 <std::uint16_t, std::uint16_t>);
1304 <std::uint16_t, std::int16_t>);
1306 <std::uint16_t, std::int32_t>);
1308 <std::uint16_t, std::uint32_t>);
1310 <std::uint16_t, std::int64_t>);
1312 <std::uint16_t, std::uint64_t>);
1314 <std::uint16_t, std::int16_t>);
1316 <std::uint16_t, std::int32_t>);
1318 <std::uint16_t, std::uint32_t>);
1320 <std::uint16_t, std::int64_t>);
1322 <std::uint16_t, std::uint64_t>);
1327 <std::int32_t, std::int32_t>);
1333 <std::int32_t, std::uint16_t>);
1335 <std::int32_t, std::uint32_t>);
1338 <std::int32_t, std::uint64_t>);
1340 <std::int32_t, std::int16_t>);
1342 <std::int32_t, std::uint16_t>);
1344 <std::int32_t, std::uint32_t>);
1346 <std::int32_t, std::int64_t>);
1348 <std::int32_t, std::uint64_t>);
1353 <std::uint32_t, std::uint32_t>);
1358 <std::uint32_t, std::int16_t>);
1360 <std::uint32_t, std::uint16_t>);
1362 <std::uint32_t, std::int32_t>);
1364 <std::uint32_t, std::int64_t>);
1366 <std::uint32_t, std::uint64_t>);
1368 <std::uint32_t, std::int16_t>);
1370 <std::uint32_t, std::uint16_t>);
1372 <std::uint32_t, std::int32_t>);
1374 <std::uint32_t, std::int64_t>);
1376 <std::uint32_t, std::uint64_t>);
1381 <std::int64_t, std::int64_t>);
1387 <std::int64_t, std::uint16_t>);
1390 <std::int64_t, std::uint32_t>);
1392 <std::int64_t, std::uint64_t>);
1394 <std::int64_t, std::int16_t>);
1396 <std::int64_t, std::uint16_t>);
1398 <std::int64_t, std::int32_t>);
1400 <std::int64_t, std::uint32_t>);
1402 <std::int64_t, std::uint64_t>);
1407 <std::uint64_t, std::uint64_t>);
1412 <std::uint64_t, std::int16_t>);
1414 <std::uint64_t, std::uint16_t>);
1416 <std::uint64_t, std::int32_t>);
1418 <std::uint64_t, std::uint32_t>);
1420 <std::uint64_t, std::int64_t>);
1422 <std::uint64_t, std::int16_t>);
1424 <std::uint64_t, std::uint16_t>);
1426 <std::uint64_t, std::int32_t>);
1428 <std::uint64_t, std::uint32_t>);
1430 <std::uint64_t, std::int64_t>);
1446 <std::uint64_t, std::uint32_t>);
1448 RColumnElementDeltaSplitLE, <std::uint64_t, std::uint64_t>);
1450 RColumnElementDeltaSplitLE, <std::uint64_t, std::uint32_t>);
1456 static constexpr bool kIsMappable =
false;
1458 static constexpr std::size_t kBitsOnStorage =
kSize * 8;
1461 bool IsMappable()
const {
return kIsMappable; }
1462 void Pack(
void *,
const void *, std::size_t)
const {}
1463 void Unpack(
void *,
const void *, std::size_t)
const {}
1465 RIdentifier GetIdentifier() const final
1472RColumnElement<bool, ROOT::Experimental::EColumnType::kBit>::Pack(
void *dst,
const void *
src, std::size_t count)
const
1474 const bool *boolArray =
reinterpret_cast<const bool *
>(
src);
1475 char *charArray =
reinterpret_cast<char *
>(dst);
1476 std::bitset<8> bitSet;
1478 for (; i < count; ++i) {
1479 bitSet.set(i % 8, boolArray[i]);
1481 char packed = bitSet.to_ulong();
1482 charArray[i / 8] = packed;
1486 char packed = bitSet.to_ulong();
1487 charArray[i / 8] = packed;
1492RColumnElement<bool, ROOT::Experimental::EColumnType::kBit>::Unpack(
void *dst,
const void *
src, std::size_t count)
const
1494 bool *boolArray =
reinterpret_cast<bool *
>(dst);
1495 const char *charArray =
reinterpret_cast<const char *
>(
src);
1496 std::bitset<8> bitSet;
1497 for (std::size_t i = 0; i < count; i += 8) {
1498 bitSet = charArray[i / 8];
1499 for (std::size_t j = i; j < std::min(count, i + 8); ++j) {
1500 boolArray[j] = bitSet[j % 8];
#define DECLARE_RCOLUMNELEMENT_SPEC_SIMPLE(CppT, ColumnT, BitsOnStorage)
#define DECLARE_RCOLUMNELEMENT_SPEC(CppT, ColumnT, BitsOnStorage, BaseT,...)
These macros are used to declare RColumnElement template specializations below.
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
The available trivial, native content types of a column.
A column element encapsulates the translation between basic C++ types and their column representation...
Holds the index and the tag of a kSwitch column.
ClusterSize_t GetIndex() const
Base class for all ROOT issued exceptions.
constexpr std::size_t kBitsPerWord
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.
constexpr std::size_t MinBufSize(std::size_t count, std::size_t nDstBits)
Returns the minimum safe size (in bytes) of a buffer that is intended to be used as a destination for...
void UnpackBits(void *dst, const void *src, std::size_t count, std::size_t sizeofDst, std::size_t nSrcBits)
Undoes the effect of PackBits.
std::uint16_t FloatToHalf(float value)
Convert an IEEE single-precision float to half-precision.
float HalfToFloat(std::uint16_t value)
Convert an IEEE half-precision float to single-precision.
RClusterSize ClusterSize_t
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
__device__ AFloat max(AFloat x, AFloat y)
Helper templated class for swapping bytes; specializations for N={2,4,8} are provided below.
Wrap the integer in a struct in order to avoid template specialization clash with std::uint64_t.