22#ifndef R__LITTLE_ENDIAN
25#define R__LITTLE_ENDIAN 1
27#define R__LITTLE_ENDIAN 0
39constexpr std::size_t
MinBufSize(std::size_t count, std::size_t nDstBits)
41 return (count * nDstBits + 7) / 8;
49void PackBits(
void *dst,
const void *
src, std::size_t count, std::size_t sizeofSrc, std::size_t nDstBits);
55void UnpackBits(
void *dst,
const void *
src, std::size_t count, std::size_t sizeofDst, std::size_t nSrcBits);
87template <std::
size_t N>
88inline void CopyBswap(
void *destination,
const void *source, std::size_t count)
92 for (std::size_t i = 0; i < count; ++i) {
97template <std::
size_t N>
98void InPlaceBswap(
void *array, std::size_t count)
101 for (std::size_t i = 0; i < count; ++i) {
107#if R__LITTLE_ENDIAN == 0
109inline void ByteSwapIfNecessary(T &
value)
111 constexpr auto N =
sizeof(
T);
113 void *valuePtr = &
value;
115 *
reinterpret_cast<bswap_value_type *
>(valuePtr) = swapped;
118inline void ByteSwapIfNecessary<char>(
char &)
122inline void ByteSwapIfNecessary<signed char>(
signed char &)
126inline void ByteSwapIfNecessary<unsigned char>(
unsigned char &)
130#define ByteSwapIfNecessary(x) ((void)0)
134template <
typename DestT,
typename SourceT>
135inline void EnsureValidRange(SourceT val [[maybe_unused]])
139 if constexpr (!std::is_integral_v<DestT> || !std::is_integral_v<SourceT>)
142 if constexpr (
static_cast<double>(std::numeric_limits<SourceT>::min()) <
143 static_cast<double>(std::numeric_limits<DestT>::min())) {
144 if constexpr (!std::is_signed_v<DestT>) {
146 throw RException(
R__FAIL(std::string(
"value out of range: ") + std::to_string(val) +
" for type " +
147 typeid(DestT).
name()));
149 }
else if (val < std::numeric_limits<DestT>::min()) {
151 R__FAIL(std::string(
"value out of range: ") + std::to_string(val) +
" for type " +
typeid(DestT).
name()));
155 if constexpr (
static_cast<double>(std::numeric_limits<SourceT>::max()) >
156 static_cast<double>(std::numeric_limits<DestT>::max())) {
157 if (val > std::numeric_limits<DestT>::max()) {
159 R__FAIL(std::string(
"value out of range: ") + std::to_string(val) +
" for type " +
typeid(DestT).
name()));
168template <
typename DestT,
typename SourceT>
169inline void CastPack(
void *destination,
const void *source, std::size_t count)
171 static_assert(std::is_convertible_v<SourceT, DestT>);
172 auto dst =
reinterpret_cast<DestT *
>(destination);
173 auto src =
reinterpret_cast<const SourceT *
>(source);
174 for (std::size_t i = 0; i < count; ++i) {
176 ByteSwapIfNecessary(dst[i]);
184template <
typename DestT,
typename SourceT>
185inline void CastUnpack(
void *destination,
const void *source, std::size_t count)
187 auto dst =
reinterpret_cast<DestT *
>(destination);
188 auto src =
reinterpret_cast<const SourceT *
>(source);
189 for (std::size_t i = 0; i < count; ++i) {
190 SourceT val =
src[i];
191 ByteSwapIfNecessary(val);
192 EnsureValidRange<DestT, SourceT>(val);
200template <
typename DestT,
typename SourceT>
201inline void CastSplitPack(
void *destination,
const void *source, std::size_t count)
203 constexpr std::size_t
N =
sizeof(DestT);
204 auto splitArray =
reinterpret_cast<char *
>(destination);
205 auto src =
reinterpret_cast<const SourceT *
>(source);
206 for (std::size_t i = 0; i < count; ++i) {
208 ByteSwapIfNecessary(val);
209 for (std::size_t
b = 0;
b <
N; ++
b) {
210 splitArray[
b * count + i] =
reinterpret_cast<const char *
>(&val)[
b];
218template <
typename DestT,
typename SourceT>
219inline void CastSplitUnpack(
void *destination,
const void *source, std::size_t count)
221 constexpr std::size_t
N =
sizeof(SourceT);
222 auto dst =
reinterpret_cast<DestT *
>(destination);
223 auto splitArray =
reinterpret_cast<const char *
>(source);
224 for (std::size_t i = 0; i < count; ++i) {
226 for (std::size_t
b = 0;
b <
N; ++
b) {
227 reinterpret_cast<char *
>(&val)[
b] = splitArray[
b * count + i];
229 ByteSwapIfNecessary(val);
230 EnsureValidRange<DestT, SourceT>(val);
238template <
typename DestT,
typename SourceT>
239inline void CastDeltaSplitPack(
void *destination,
const void *source, std::size_t count)
241 constexpr std::size_t
N =
sizeof(DestT);
242 auto src =
reinterpret_cast<const SourceT *
>(source);
243 auto splitArray =
reinterpret_cast<char *
>(destination);
244 for (std::size_t i = 0; i < count; ++i) {
245 DestT val = (i == 0) ?
src[0] :
src[i] -
src[i - 1];
246 ByteSwapIfNecessary(val);
247 for (std::size_t
b = 0;
b <
N; ++
b) {
248 splitArray[
b * count + i] =
reinterpret_cast<char *
>(&val)[
b];
256template <
typename DestT,
typename SourceT>
257inline void CastDeltaSplitUnpack(
void *destination,
const void *source, std::size_t count)
259 constexpr std::size_t
N =
sizeof(SourceT);
260 auto splitArray =
reinterpret_cast<const char *
>(source);
261 auto dst =
reinterpret_cast<DestT *
>(destination);
262 for (std::size_t i = 0; i < count; ++i) {
264 for (std::size_t
b = 0;
b <
N; ++
b) {
265 reinterpret_cast<char *
>(&val)[
b] = splitArray[
b * count + i];
267 ByteSwapIfNecessary(val);
268 val = (i == 0) ? val : val + dst[i - 1];
269 EnsureValidRange<DestT, SourceT>(val);
277template <
typename DestT,
typename SourceT>
278inline void CastZigzagSplitPack(
void *destination,
const void *source, std::size_t count)
280 using UDestT = std::make_unsigned_t<DestT>;
281 constexpr std::size_t kNBitsDestT =
sizeof(DestT) * 8;
282 constexpr std::size_t
N =
sizeof(DestT);
283 auto src =
reinterpret_cast<const SourceT *
>(source);
284 auto splitArray =
reinterpret_cast<char *
>(destination);
285 for (std::size_t i = 0; i < count; ++i) {
286 UDestT val = (
static_cast<DestT
>(
src[i]) << 1) ^ (
static_cast<DestT
>(
src[i]) >> (kNBitsDestT - 1));
287 ByteSwapIfNecessary(val);
288 for (std::size_t
b = 0;
b <
N; ++
b) {
289 splitArray[
b * count + i] =
reinterpret_cast<char *
>(&val)[
b];
297template <
typename DestT,
typename SourceT>
298inline void CastZigzagSplitUnpack(
void *destination,
const void *source, std::size_t count)
300 using USourceT = std::make_unsigned_t<SourceT>;
301 constexpr std::size_t
N =
sizeof(SourceT);
302 auto splitArray =
reinterpret_cast<const char *
>(source);
303 auto dst =
reinterpret_cast<DestT *
>(destination);
304 for (std::size_t i = 0; i < count; ++i) {
306 for (std::size_t
b = 0;
b <
N; ++
b) {
307 reinterpret_cast<char *
>(&val)[
b] = splitArray[
b * count + i];
309 ByteSwapIfNecessary(val);
310 SourceT sval =
static_cast<SourceT
>((val >> 1) ^ -(
static_cast<SourceT
>(val) & 1));
311 EnsureValidRange<DestT, SourceT>(sval);
325template <
typename CppT, EColumnType>
328template <
typename CppT>
329std::unique_ptr<RColumnElementBase> GenerateColumnElementInternal(
EColumnType onDiskType)
331 switch (onDiskType) {
332 case EColumnType::kIndex64:
return std::make_unique<RColumnElement<CppT, EColumnType::kIndex64>>();
333 case EColumnType::kIndex32:
return std::make_unique<RColumnElement<CppT, EColumnType::kIndex32>>();
334 case EColumnType::kSwitch:
return std::make_unique<RColumnElement<CppT, EColumnType::kSwitch>>();
335 case EColumnType::kByte:
return std::make_unique<RColumnElement<CppT, EColumnType::kByte>>();
336 case EColumnType::kChar:
return std::make_unique<RColumnElement<CppT, EColumnType::kChar>>();
337 case EColumnType::kBit:
return std::make_unique<RColumnElement<CppT, EColumnType::kBit>>();
338 case EColumnType::kReal64:
return std::make_unique<RColumnElement<CppT, EColumnType::kReal64>>();
339 case EColumnType::kReal32:
return std::make_unique<RColumnElement<CppT, EColumnType::kReal32>>();
340 case EColumnType::kReal16:
return std::make_unique<RColumnElement<CppT, EColumnType::kReal16>>();
341 case EColumnType::kInt64:
return std::make_unique<RColumnElement<CppT, EColumnType::kInt64>>();
342 case EColumnType::kUInt64:
return std::make_unique<RColumnElement<CppT, EColumnType::kUInt64>>();
343 case EColumnType::kInt32:
return std::make_unique<RColumnElement<CppT, EColumnType::kInt32>>();
344 case EColumnType::kUInt32:
return std::make_unique<RColumnElement<CppT, EColumnType::kUInt32>>();
345 case EColumnType::kInt16:
return std::make_unique<RColumnElement<CppT, EColumnType::kInt16>>();
346 case EColumnType::kUInt16:
return std::make_unique<RColumnElement<CppT, EColumnType::kUInt16>>();
347 case EColumnType::kInt8:
return std::make_unique<RColumnElement<CppT, EColumnType::kInt8>>();
348 case EColumnType::kUInt8:
return std::make_unique<RColumnElement<CppT, EColumnType::kUInt8>>();
349 case EColumnType::kSplitIndex64:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitIndex64>>();
350 case EColumnType::kSplitIndex32:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitIndex32>>();
351 case EColumnType::kSplitReal64:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitReal64>>();
352 case EColumnType::kSplitReal32:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitReal32>>();
353 case EColumnType::kSplitInt64:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt64>>();
354 case EColumnType::kSplitUInt64:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitUInt64>>();
355 case EColumnType::kSplitInt32:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt32>>();
356 case EColumnType::kSplitUInt32:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitUInt32>>();
357 case EColumnType::kSplitInt16:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt16>>();
358 case EColumnType::kSplitUInt16:
return std::make_unique<RColumnElement<CppT, EColumnType::kSplitUInt16>>();
359 case EColumnType::kReal32Trunc:
return std::make_unique<RColumnElement<CppT, EColumnType::kReal32Trunc>>();
360 case EColumnType::kReal32Quant:
return std::make_unique<RColumnElement<CppT, EColumnType::kReal32Quant>>();
362 if (onDiskType == kTestFutureType)
363 return std::make_unique<RColumnElement<CppT, kTestFutureType>>();
374template <
typename CppT>
375class RColumnElementLE :
public RColumnElementBase {
377 explicit RColumnElementLE(std::size_t
size, std::size_t bitsOnStorage) : RColumnElementBase(
size, bitsOnStorage) {}
382 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
384#if R__LITTLE_ENDIAN == 1
385 RColumnElementBase::Pack(dst,
src, count);
387 CopyBswap<sizeof(CppT)>(dst,
src, count);
390 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
392#if R__LITTLE_ENDIAN == 1
393 RColumnElementBase::Unpack(dst,
src, count);
395 CopyBswap<sizeof(CppT)>(dst,
src, count);
404template <
typename CppT,
typename NarrowT>
405class RColumnElementCastLE :
public RColumnElementBase {
407 explicit RColumnElementCastLE(std::size_t
size, std::size_t bitsOnStorage) : RColumnElementBase(
size, bitsOnStorage)
412 static constexpr bool kIsMappable =
false;
414 void Pack(
void *dst,
const void *
src, std::size_t count)
const final { CastPack<NarrowT, CppT>(dst,
src, count); }
415 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
417 CastUnpack<CppT, NarrowT>(dst,
src, count);
426template <
typename CppT,
typename NarrowT>
427class RColumnElementSplitLE :
public RColumnElementBase {
429 explicit RColumnElementSplitLE(std::size_t
size, std::size_t bitsOnStorage) : RColumnElementBase(
size, bitsOnStorage)
434 static constexpr bool kIsMappable =
false;
436 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
438 CastSplitPack<NarrowT, CppT>(dst,
src, count);
440 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
442 CastSplitUnpack<CppT, NarrowT>(dst,
src, count);
451template <
typename CppT,
typename NarrowT>
452class RColumnElementDeltaSplitLE :
public RColumnElementBase {
454 explicit RColumnElementDeltaSplitLE(std::size_t
size, std::size_t bitsOnStorage)
455 : RColumnElementBase(
size, bitsOnStorage)
460 static constexpr bool kIsMappable =
false;
462 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
464 CastDeltaSplitPack<NarrowT, CppT>(dst,
src, count);
466 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
468 CastDeltaSplitUnpack<CppT, NarrowT>(dst,
src, count);
473template <
typename CppIntT>
474class RColumnElementBoolAsUnsplitInt :
public RColumnElementBase {
476 explicit RColumnElementBoolAsUnsplitInt(std::size_t
size, std::size_t bitsOnStorage)
477 : RColumnElementBase(
size, bitsOnStorage)
482 static constexpr bool kIsMappable =
false;
485 void Pack(
void *,
const void *, std::size_t)
const final {
R__ASSERT(
false); }
487 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
489 auto *boolArray =
reinterpret_cast<bool *
>(dst);
490 auto *intArray =
reinterpret_cast<const CppIntT *
>(
src);
491 for (std::size_t i = 0; i < count; ++i) {
492 boolArray[i] = intArray[i] != 0;
498template <
typename CppIntT>
499class RColumnElementBoolAsSplitInt :
public RColumnElementBase {
501 explicit RColumnElementBoolAsSplitInt(std::size_t
size, std::size_t bitsOnStorage)
502 : RColumnElementBase(
size, bitsOnStorage)
507 static constexpr bool kIsMappable =
false;
510 void Pack(
void *,
const void *, std::size_t)
const final {
R__ASSERT(
false); }
512 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
514 constexpr std::size_t
N =
sizeof(CppIntT);
515 auto *boolArray =
reinterpret_cast<bool *
>(dst);
516 auto *splitArray =
reinterpret_cast<const char *
>(
src);
517 for (std::size_t i = 0; i < count; ++i) {
518 boolArray[i] =
false;
519 for (std::size_t
b = 0;
b <
N; ++
b) {
520 if (splitArray[
b * count + i]) {
530template <
typename CppIntT>
531class RColumnElementIntAsBool :
public RColumnElementBase {
533 explicit RColumnElementIntAsBool(std::size_t
size, std::size_t bitsOnStorage)
534 : RColumnElementBase(
size, bitsOnStorage)
539 static constexpr bool kIsMappable =
false;
542 void Pack(
void *,
const void *, std::size_t)
const final {
R__ASSERT(
false); }
544 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
546 auto *intArray =
reinterpret_cast<CppIntT *
>(dst);
547 const char *charArray =
reinterpret_cast<const char *
>(
src);
548 std::bitset<8> bitSet;
549 for (std::size_t i = 0; i < count; i += 8) {
550 bitSet = charArray[i / 8];
551 for (std::size_t j = i; j < std::min(count, i + 8); ++j) {
552 intArray[j] = bitSet[j % 8];
563template <
typename CppT,
typename NarrowT>
564class RColumnElementZigzagSplitLE :
public RColumnElementBase {
566 explicit RColumnElementZigzagSplitLE(std::size_t
size, std::size_t bitsOnStorage)
567 : RColumnElementBase(
size, bitsOnStorage)
572 static constexpr bool kIsMappable =
false;
574 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
576 CastZigzagSplitPack<NarrowT, CppT>(dst,
src, count);
578 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
580 CastZigzagSplitUnpack<CppT, NarrowT>(dst,
src, count);
592template <
typename CppT, EColumnType ColumnT = EColumnType::kUnknown>
593class RColumnElement :
public RColumnElementBase {
595 RColumnElement() : RColumnElementBase(sizeof(CppT))
598 R__FAIL(std::string(
"internal error: no column mapping for this C++ type: ") +
typeid(CppT).
name() +
" --> " +
599 GetColumnTypeName(ColumnT)));
602 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(CppT), EColumnType::kUnknown}; }
608 static constexpr std::size_t
kSize =
sizeof(
bool);
609 RColumnElement() : RColumnElementBase(
kSize) {}
610 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
bool), EColumnType::kUnknown}; }
614class RColumnElement<std::
byte, EColumnType::kUnknown> :
public RColumnElementBase {
616 static constexpr std::size_t
kSize =
sizeof(std::byte);
617 RColumnElement() : RColumnElementBase(
kSize) {}
618 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::byte), EColumnType::kUnknown}; }
624 static constexpr std::size_t
kSize =
sizeof(char);
625 RColumnElement() : RColumnElementBase(
kSize) {}
626 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(char), EColumnType::kUnknown}; }
630class RColumnElement<std::int8_t, EColumnType::kUnknown> :
public RColumnElementBase {
632 static constexpr std::size_t
kSize =
sizeof(std::int8_t);
633 RColumnElement() : RColumnElementBase(
kSize) {}
634 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::int8_t), EColumnType::kUnknown}; }
638class RColumnElement<std::uint8_t, EColumnType::kUnknown> :
public RColumnElementBase {
640 static constexpr std::size_t
kSize =
sizeof(std::uint8_t);
641 RColumnElement() : RColumnElementBase(
kSize) {}
642 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::uint8_t), EColumnType::kUnknown}; }
646class RColumnElement<std::int16_t, EColumnType::kUnknown> :
public RColumnElementBase {
648 static constexpr std::size_t
kSize =
sizeof(std::int16_t);
649 RColumnElement() : RColumnElementBase(
kSize) {}
650 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::int16_t), EColumnType::kUnknown}; }
654class RColumnElement<std::uint16_t, EColumnType::kUnknown> :
public RColumnElementBase {
656 static constexpr std::size_t
kSize =
sizeof(std::uint16_t);
657 RColumnElement() : RColumnElementBase(
kSize) {}
658 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::uint16_t), EColumnType::kUnknown}; }
662class RColumnElement<std::int32_t, EColumnType::kUnknown> :
public RColumnElementBase {
664 static constexpr std::size_t
kSize =
sizeof(std::int32_t);
665 RColumnElement() : RColumnElementBase(
kSize) {}
666 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::int32_t), EColumnType::kUnknown}; }
670class RColumnElement<std::uint32_t, EColumnType::kUnknown> :
public RColumnElementBase {
672 static constexpr std::size_t
kSize =
sizeof(std::uint32_t);
673 RColumnElement() : RColumnElementBase(
kSize) {}
674 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::uint32_t), EColumnType::kUnknown}; }
678class RColumnElement<std::int64_t, EColumnType::kUnknown> :
public RColumnElementBase {
680 static constexpr std::size_t
kSize =
sizeof(std::int64_t);
681 RColumnElement() : RColumnElementBase(
kSize) {}
682 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::int64_t), EColumnType::kUnknown}; }
686class RColumnElement<std::uint64_t, EColumnType::kUnknown> :
public RColumnElementBase {
688 static constexpr std::size_t
kSize =
sizeof(std::uint64_t);
689 RColumnElement() : RColumnElementBase(
kSize) {}
690 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(std::uint64_t), EColumnType::kUnknown}; }
696 static constexpr std::size_t
kSize =
sizeof(float);
697 RColumnElement() : RColumnElementBase(
kSize) {}
698 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(float), EColumnType::kUnknown}; }
704 static constexpr std::size_t
kSize =
sizeof(
double);
705 RColumnElement() : RColumnElementBase(
kSize) {}
706 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
double), EColumnType::kUnknown}; }
710class RColumnElement<
ROOT::Experimental::ClusterSize_t, EColumnType::kUnknown> :
public RColumnElementBase {
713 RColumnElement() : RColumnElementBase(
kSize) {}
714 RIdentifier GetIdentifier() const final
721class RColumnElement<
ROOT::Experimental::RColumnSwitch, EColumnType::kUnknown> :
public RColumnElementBase {
724 RColumnElement() : RColumnElementBase(
kSize) {}
725 RIdentifier GetIdentifier() const final
737class RColumnElement<
ROOT::Experimental::RColumnSwitch, EColumnType::kSwitch> :
public RColumnElementBase {
739 struct RSwitchElement {
740 std::uint64_t fIndex;
745 static constexpr bool kIsMappable =
false;
747 static constexpr std::size_t kBitsOnStorage = 96;
748 RColumnElement() : RColumnElementBase(
kSize, kBitsOnStorage) {}
749 bool IsMappable() const final {
return kIsMappable; }
751 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
754 auto dstArray =
reinterpret_cast<unsigned char *
>(dst);
755 for (std::size_t i = 0; i < count; ++i) {
756 RSwitchElement element{srcArray[i].
GetIndex(), srcArray[i].GetTag()};
757#if R__LITTLE_ENDIAN == 0
761 memcpy(dstArray + i * 12, &element, 12);
765 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
767 auto srcArray =
reinterpret_cast<const unsigned char *
>(
src);
769 for (std::size_t i = 0; i < count; ++i) {
770 RSwitchElement element;
771 memcpy(&element, srcArray + i * 12, 12);
772#if R__LITTLE_ENDIAN == 0
781 RIdentifier GetIdentifier() const final
790 static constexpr bool kIsMappable =
false;
791 static constexpr std::size_t
kSize =
sizeof(
bool);
792 static constexpr std::size_t kBitsOnStorage = 1;
793 RColumnElement() : RColumnElementBase(
kSize, kBitsOnStorage) {}
794 bool IsMappable() const final {
return kIsMappable; }
796 void Pack(
void *dst,
const void *
src, std::size_t count)
const final;
797 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final;
799 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
bool), EColumnType::kBit}; }
805 static constexpr bool kIsMappable =
false;
806 static constexpr std::size_t
kSize =
sizeof(float);
807 static constexpr std::size_t kBitsOnStorage = 16;
808 RColumnElement() : RColumnElementBase(
kSize, kBitsOnStorage) {}
809 bool IsMappable() const final {
return kIsMappable; }
811 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
813 const float *floatArray =
reinterpret_cast<const float *
>(
src);
814 std::uint16_t *uint16Array =
reinterpret_cast<std::uint16_t *
>(dst);
816 for (std::size_t i = 0; i < count; ++i) {
818 ByteSwapIfNecessary(uint16Array[i]);
822 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
824 float *floatArray =
reinterpret_cast<float *
>(dst);
825 const std::uint16_t *uint16Array =
reinterpret_cast<const std::uint16_t *
>(
src);
827 for (std::size_t i = 0; i < count; ++i) {
828 std::uint16_t val = uint16Array[i];
829 ByteSwapIfNecessary(val);
834 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(float), EColumnType::kReal16}; }
840 static constexpr bool kIsMappable =
false;
841 static constexpr std::size_t
kSize =
sizeof(
double);
842 static constexpr std::size_t kBitsOnStorage = 16;
843 RColumnElement() : RColumnElementBase(
kSize, kBitsOnStorage) {}
844 bool IsMappable() const final {
return kIsMappable; }
846 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
848 const double *doubleArray =
reinterpret_cast<const double *
>(
src);
849 std::uint16_t *uint16Array =
reinterpret_cast<std::uint16_t *
>(dst);
851 for (std::size_t i = 0; i < count; ++i) {
853 ByteSwapIfNecessary(uint16Array[i]);
857 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
859 double *doubleArray =
reinterpret_cast<double *
>(dst);
860 const std::uint16_t *uint16Array =
reinterpret_cast<const std::uint16_t *
>(
src);
862 for (std::size_t i = 0; i < count; ++i) {
863 std::uint16_t val = uint16Array[i];
864 ByteSwapIfNecessary(val);
869 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
double), EColumnType::kReal16}; }
873class RColumnElementTrunc :
public RColumnElementBase {
875 static_assert(std::is_floating_point_v<T>);
876 static constexpr bool kIsMappable =
false;
877 static constexpr std::size_t
kSize =
sizeof(
T);
882 RColumnElementTrunc() : RColumnElementBase(
kSize, 0) {}
884 void SetBitsOnStorage(std::size_t bitsOnStorage)
final
886 const auto &[minBits, maxBits] = GetValidBitRange(EColumnType::kReal32Trunc);
887 R__ASSERT(bitsOnStorage >= minBits && bitsOnStorage <= maxBits);
888 fBitsOnStorage = bitsOnStorage;
891 bool IsMappable() const final {
return kIsMappable; }
893 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
T), EColumnType::kReal32Trunc}; }
899 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
905#if R__LITTLE_ENDIAN == 0
908 auto bswapped = MakeUninitArray<float>(count);
909 CopyBswap<sizeof(float)>(bswapped.get(),
src, count);
910 const auto *srcLe = bswapped.get();
912 const auto *srcLe =
reinterpret_cast<const float *
>(
src);
914 PackBits(dst, srcLe, count,
sizeof(
float), fBitsOnStorage);
917 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
924#if R__LITTLE_ENDIAN == 0
925 InPlaceBswap<sizeof(float)>(dst, count);
933 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
941 auto srcFloat = MakeUninitArray<float>(count);
942 const double *srcDouble =
reinterpret_cast<const double *
>(
src);
943 for (std::size_t i = 0; i < count; ++i)
944 srcFloat[i] =
static_cast<float>(srcDouble[i]);
946#if R__LITTLE_ENDIAN == 0
949 auto bswapped = MakeUninitArray<float>(count);
950 CopyBswap<sizeof(float)>(bswapped.get(), srcFloat.get(), count);
951 const float *srcLe = bswapped.get();
953 const float *srcLe =
reinterpret_cast<const float *
>(srcFloat.get());
955 PackBits(dst, srcLe, count,
sizeof(
float), fBitsOnStorage);
958 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
965 auto dstFloat = MakeUninitArray<float>(count);
966 UnpackBits(dstFloat.get(),
src, count,
sizeof(
float), fBitsOnStorage);
967#if R__LITTLE_ENDIAN == 0
968 InPlaceBswap<sizeof(float)>(dstFloat.get(), count);
971 double *dstDouble =
reinterpret_cast<double *
>(dst);
972 for (std::size_t i = 0; i < count; ++i)
973 dstDouble[i] =
static_cast<double>(dstFloat[i]);
979using Quantized_t = std::uint32_t;
981[[maybe_unused]]
inline std::size_t LeadingZeroes(std::uint32_t
x)
987 unsigned long idx = 0;
988 if (_BitScanReverse(&idx,
x))
989 return static_cast<std::size_t
>(31 - 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 if (_BitScanForward(&idx,
x))
1004 return static_cast<std::size_t
>(idx);
1007 return static_cast<std::size_t
>(__builtin_ctzl(
x));
1017template <
typename T>
1018int QuantizeReals(Quantized_t *dst,
const T *
src, std::size_t count,
double min,
double max, std::size_t nQuantBits)
1020 static_assert(std::is_floating_point_v<T>);
1021 static_assert(
sizeof(T) <=
sizeof(
double));
1022 assert(1 <= nQuantBits && nQuantBits <= 8 *
sizeof(Quantized_t));
1024 const std::size_t quantMax = (1ull << nQuantBits) - 1;
1025 const double scale = quantMax / (max - min);
1026 const std::size_t unusedBits =
sizeof(Quantized_t) * 8 - nQuantBits;
1028 int nOutOfRange = 0;
1030 for (std::size_t i = 0; i < count; ++i) {
1031 const T elem =
src[i];
1033 nOutOfRange += !(min <= elem && elem <= max);
1035 const double e = 0.5 + (elem - min) * scale;
1036 Quantized_t
q =
static_cast<Quantized_t
>(
e);
1037 ByteSwapIfNecessary(
q);
1040 assert(LeadingZeroes(
q) >= unusedBits);
1044 dst[i] =
q << unusedBits;
1052template <
typename T>
1053int UnquantizeReals(T *dst,
const Quantized_t *
src, std::size_t count,
double min,
double max, std::size_t nQuantBits)
1055 static_assert(std::is_floating_point_v<T>);
1056 static_assert(
sizeof(T) <=
sizeof(
double));
1057 assert(1 <= nQuantBits && nQuantBits <= 8 *
sizeof(Quantized_t));
1059 const std::size_t quantMax = (1ull << nQuantBits) - 1;
1060 const double scale = (max - min) / quantMax;
1061 const std::size_t unusedBits =
sizeof(Quantized_t) * 8 - nQuantBits;
1062 const double eps = std::numeric_limits<double>::epsilon();
1063 const double emin = min - std::abs(min) * eps;
1064 const double emax = max + std::abs(max) * eps;
1066 int nOutOfRange = 0;
1068 for (std::size_t i = 0; i < count; ++i) {
1069 Quantized_t elem =
src[i];
1071 assert(TrailingZeroes(elem) >= unusedBits);
1072 elem >>= unusedBits;
1073 ByteSwapIfNecessary(elem);
1075 const double fq =
static_cast<double>(elem);
1076 const double e = fq * scale + min;
1077 dst[i] =
static_cast<T
>(
e);
1079 nOutOfRange += !(emin <= dst[i] && dst[i] <= emax);
1086template <
typename T>
1088 static_assert(std::is_floating_point_v<T>);
1091 static constexpr bool kIsMappable =
false;
1092 static constexpr std::size_t
kSize =
sizeof(T);
1096 void SetBitsOnStorage(std::size_t bitsOnStorage)
final
1098 const auto [minBits, maxBits] = GetValidBitRange(EColumnType::kReal32Quant);
1099 R__ASSERT(bitsOnStorage >= minBits && bitsOnStorage <= maxBits);
1100 fBitsOnStorage = bitsOnStorage;
1103 void SetValueRange(
double min,
double max)
final
1105 R__ASSERT(min >= std::numeric_limits<T>::lowest());
1106 R__ASSERT(max <= std::numeric_limits<T>::max());
1108 R__ASSERT(std::isnormal(min) || min == 0.0);
1109 R__ASSERT(std::isnormal(max) || max == 0.0);
1110 fValueRange = {min,
max};
1113 bool IsMappable() const final {
return kIsMappable; }
1115 void Pack(
void *dst,
const void *
src, std::size_t count)
const final
1120 auto quantized = MakeUninitArray<Quantize::Quantized_t>(count);
1121 assert(fValueRange);
1122 const auto [min,
max] = *fValueRange;
1123 const int nOutOfRange =
1124 Quantize::QuantizeReals(quantized.get(),
reinterpret_cast<const T *
>(
src), count, min, max, fBitsOnStorage);
1127 " values were found of of range for quantization while packing (range is [" +
1128 std::to_string(min) +
", " + std::to_string(max) +
"])"));
1130 Internal::BitPacking::PackBits(dst, quantized.get(), count,
sizeof(Quantize::Quantized_t), fBitsOnStorage);
1133 void Unpack(
void *dst,
const void *
src, std::size_t count)
const final
1138 auto quantized = MakeUninitArray<Quantize::Quantized_t>(count);
1139 assert(fValueRange);
1140 const auto [min,
max] = *fValueRange;
1141 Internal::BitPacking::UnpackBits(quantized.get(),
src, count,
sizeof(Quantize::Quantized_t), fBitsOnStorage);
1142 [[maybe_unused]]
const int nOutOfRange =
1143 Quantize::UnquantizeReals(
reinterpret_cast<T *
>(dst), quantized.get(), count, min, max, fBitsOnStorage);
1147 assert(nOutOfRange == 0);
1150 RIdentifier GetIdentifier() const final {
return RIdentifier{
typeid(
T), EColumnType::kReal32Quant}; }
1159#define __RCOLUMNELEMENT_SPEC_BODY(CppT, ColumnT, BaseT, BitsOnStorage) \
1160 static constexpr std::size_t kSize = sizeof(CppT); \
1161 static constexpr std::size_t kBitsOnStorage = BitsOnStorage; \
1162 RColumnElement() : BaseT(kSize, kBitsOnStorage) {} \
1163 bool IsMappable() const final \
1165 return kIsMappable; \
1167 RIdentifier GetIdentifier() const final \
1169 return RIdentifier{typeid(CppT), ColumnT}; \
1177#define DECLARE_RCOLUMNELEMENT_SPEC(CppT, ColumnT, BitsOnStorage, BaseT, ...) \
1179 class RColumnElement<CppT, ColumnT> : public BaseT __VA_ARGS__ { \
1181 __RCOLUMNELEMENT_SPEC_BODY(CppT, ColumnT, BaseT, BitsOnStorage) \
1183#define DECLARE_RCOLUMNELEMENT_SPEC_SIMPLE(CppT, ColumnT, BitsOnStorage) \
1185 class RColumnElement<CppT, ColumnT> : public RColumnElementBase { \
1187 static constexpr bool kIsMappable = true; \
1188 __RCOLUMNELEMENT_SPEC_BODY(CppT, ColumnT, RColumnElementBase, BitsOnStorage) \
1236 <std::int8_t, std::int16_t>);
1238 <std::int8_t, std::uint16_t>);
1240 <std::int8_t, std::int32_t>);
1242 <std::int8_t, std::uint32_t>);
1244 <std::int8_t, std::int64_t>);
1246 <std::int8_t, std::uint64_t>);
1254 <std::uint8_t, std::uint16_t>);
1257 <std::uint8_t, std::uint32_t>);
1260 <std::uint8_t, std::uint64_t>);
1262 <std::uint8_t, std::int16_t>);
1264 <std::uint8_t, std::uint16_t>);
1266 <std::uint8_t, std::int32_t>);
1268 <std::uint8_t, std::uint32_t>);
1270 <std::uint8_t, std::int64_t>);
1272 <std::uint8_t, std::uint64_t>);
1277 <std::int16_t, std::int16_t>);
1282 <std::int16_t, std::uint16_t>);
1285 <std::int16_t, std::uint32_t>);
1288 <std::int16_t, std::uint64_t>);
1290 <std::int16_t, std::uint16_t>);
1292 <std::int16_t, std::int32_t>);
1294 <std::int16_t, std::uint32_t>);
1296 <std::int16_t, std::int64_t>);
1298 <std::int16_t, std::uint64_t>);
1303 <std::uint16_t, std::uint16_t>);
1308 <std::uint16_t, std::int16_t>);
1310 <std::uint16_t, std::int32_t>);
1312 <std::uint16_t, std::uint32_t>);
1314 <std::uint16_t, std::int64_t>);
1316 <std::uint16_t, std::uint64_t>);
1318 <std::uint16_t, std::int16_t>);
1320 <std::uint16_t, std::int32_t>);
1322 <std::uint16_t, std::uint32_t>);
1324 <std::uint16_t, std::int64_t>);
1326 <std::uint16_t, std::uint64_t>);
1331 <std::int32_t, std::int32_t>);
1337 <std::int32_t, std::uint16_t>);
1339 <std::int32_t, std::uint32_t>);
1342 <std::int32_t, std::uint64_t>);
1344 <std::int32_t, std::int16_t>);
1346 <std::int32_t, std::uint16_t>);
1348 <std::int32_t, std::uint32_t>);
1350 <std::int32_t, std::int64_t>);
1352 <std::int32_t, std::uint64_t>);
1357 <std::uint32_t, std::uint32_t>);
1362 <std::uint32_t, std::int16_t>);
1364 <std::uint32_t, std::uint16_t>);
1366 <std::uint32_t, std::int32_t>);
1368 <std::uint32_t, std::int64_t>);
1370 <std::uint32_t, std::uint64_t>);
1372 <std::uint32_t, std::int16_t>);
1374 <std::uint32_t, std::uint16_t>);
1376 <std::uint32_t, std::int32_t>);
1378 <std::uint32_t, std::int64_t>);
1380 <std::uint32_t, std::uint64_t>);
1385 <std::int64_t, std::int64_t>);
1391 <std::int64_t, std::uint16_t>);
1394 <std::int64_t, std::uint32_t>);
1396 <std::int64_t, std::uint64_t>);
1398 <std::int64_t, std::int16_t>);
1400 <std::int64_t, std::uint16_t>);
1402 <std::int64_t, std::int32_t>);
1404 <std::int64_t, std::uint32_t>);
1406 <std::int64_t, std::uint64_t>);
1411 <std::uint64_t, std::uint64_t>);
1416 <std::uint64_t, std::int16_t>);
1418 <std::uint64_t, std::uint16_t>);
1420 <std::uint64_t, std::int32_t>);
1422 <std::uint64_t, std::uint32_t>);
1424 <std::uint64_t, std::int64_t>);
1426 <std::uint64_t, std::int16_t>);
1428 <std::uint64_t, std::uint16_t>);
1430 <std::uint64_t, std::int32_t>);
1432 <std::uint64_t, std::uint32_t>);
1434 <std::uint64_t, std::int64_t>);
1450 <std::uint64_t, std::uint32_t>);
1452 RColumnElementDeltaSplitLE, <std::uint64_t, std::uint64_t>);
1454 RColumnElementDeltaSplitLE, <std::uint64_t, std::uint32_t>);
1460 static constexpr bool kIsMappable =
false;
1462 static constexpr std::size_t kBitsOnStorage =
kSize * 8;
1465 bool IsMappable()
const {
return kIsMappable; }
1466 void Pack(
void *,
const void *, std::size_t)
const {}
1467 void Unpack(
void *,
const void *, std::size_t)
const {}
1469 RIdentifier GetIdentifier() const final
1476RColumnElement<bool, ROOT::Experimental::EColumnType::kBit>::Pack(
void *dst,
const void *
src, std::size_t count)
const
1478 const bool *boolArray =
reinterpret_cast<const bool *
>(
src);
1479 char *charArray =
reinterpret_cast<char *
>(dst);
1480 std::bitset<8> bitSet;
1482 for (; i < count; ++i) {
1483 bitSet.set(i % 8, boolArray[i]);
1485 char packed = bitSet.to_ulong();
1486 charArray[i / 8] = packed;
1490 char packed = bitSet.to_ulong();
1491 charArray[i / 8] = packed;
1496RColumnElement<bool, ROOT::Experimental::EColumnType::kBit>::Unpack(
void *dst,
const void *
src, std::size_t count)
const
1498 bool *boolArray =
reinterpret_cast<bool *
>(dst);
1499 const char *charArray =
reinterpret_cast<const char *
>(
src);
1500 std::bitset<8> bitSet;
1501 for (std::size_t i = 0; i < count; i += 8) {
1502 bitSet = charArray[i / 8];
1503 for (std::size_t j = i; j < std::min(count, i + 8); ++j) {
1504 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::unique_ptr< T[]> MakeUninitArray(std::size_t size)
Make an array of default-initialized elements.
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.
constexpr EColumnType kTestFutureType
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.