File indexing completed on 2025-05-04 22:50:31
0001 #ifndef DataFormats_SoATemplate_interface_SoACommon_h
0002 #define DataFormats_SoATemplate_interface_SoACommon_h
0003
0004
0005
0006
0007
0008 #include <cstdint>
0009 #include <cassert>
0010 #include <cstring>
0011 #include <memory>
0012 #include <ostream>
0013 #include <tuple>
0014 #include <type_traits>
0015
0016 #include <boost/preprocessor.hpp>
0017
0018 #include "FWCore/Utilities/interface/typedefs.h"
0019
0020
0021 #if defined(__CUDACC__) || defined(__HIPCC__)
0022 #define SOA_HOST_ONLY __host__
0023 #define SOA_DEVICE_ONLY __device__
0024 #define SOA_HOST_DEVICE __host__ __device__
0025 #define SOA_INLINE __forceinline__
0026 #else
0027 #define SOA_HOST_ONLY
0028 #define SOA_DEVICE_ONLY
0029 #define SOA_HOST_DEVICE
0030 #define SOA_INLINE inline __attribute__((always_inline))
0031 #endif
0032
0033
0034 #if defined(__CUDACC__) && defined(__CUDA_ARCH__)
0035 #define SOA_THROW_OUT_OF_RANGE(A) \
0036 { \
0037 printf("%s\n", (A)); \
0038 __trap(); \
0039 }
0040 #elif defined(__HIPCC__) && defined(__HIP_DEVICE_COMPILE__)
0041 #define SOA_THROW_OUT_OF_RANGE(A) \
0042 { \
0043 printf("%s\n", (A)); \
0044 abort(); \
0045 }
0046 #else
0047 #define SOA_THROW_OUT_OF_RANGE(A) \
0048 { throw std::out_of_range(A); }
0049 #endif
0050
0051
0052 #define _VALUE_TYPE_SCALAR 0
0053 #define _VALUE_TYPE_COLUMN 1
0054 #define _VALUE_TYPE_EIGEN_COLUMN 2
0055 #define _VALUE_TYPE_METHOD 3
0056 #define _VALUE_TYPE_CONST_METHOD 4
0057
0058
0059 #define _VALUE_LAST_COLUMN_TYPE _VALUE_TYPE_EIGEN_COLUMN
0060
0061
0062 #define _VALUE_TYPE_UNUSED BOOST_PP_LIMIT_MAG
0063
0064
0065
0066
0067 #define CMS_SOA_BYTE_SIZE_TYPE std::size_t
0068
0069 namespace cms::soa {
0070
0071
0072 using size_type = cms_int32_t;
0073
0074 using byte_size_type = CMS_SOA_BYTE_SIZE_TYPE;
0075
0076 enum class SoAColumnType {
0077 scalar = _VALUE_TYPE_SCALAR,
0078 column = _VALUE_TYPE_COLUMN,
0079 eigen = _VALUE_TYPE_EIGEN_COLUMN
0080 };
0081
0082 namespace RestrictQualify {
0083 constexpr bool enabled = true;
0084 constexpr bool disabled = false;
0085 constexpr bool Default = enabled;
0086 }
0087
0088 namespace RangeChecking {
0089 constexpr bool enabled = true;
0090 constexpr bool disabled = false;
0091 constexpr bool Default = enabled;
0092 }
0093
0094 template <typename T, bool RESTRICT_QUALIFY>
0095 struct add_restrict {};
0096
0097 template <typename T>
0098 struct add_restrict<T, RestrictQualify::enabled> {
0099 using Value = T;
0100 using Pointer = T* __restrict__;
0101 using Reference = T& __restrict__;
0102 using ConstValue = const T;
0103 using PointerToConst = const T* __restrict__;
0104 using ReferenceToConst = const T& __restrict__;
0105 };
0106
0107 template <typename T>
0108 struct add_restrict<T, RestrictQualify::disabled> {
0109 using Value = T;
0110 using Pointer = T*;
0111 using Reference = T&;
0112 using ConstValue = const T;
0113 using PointerToConst = const T*;
0114 using ReferenceToConst = const T&;
0115 };
0116
0117
0118 template <SoAColumnType COLUMN_TYPE, typename T>
0119 struct SoAConstParametersImpl;
0120
0121 template <SoAColumnType COLUMN_TYPE, typename T>
0122 struct SoAParametersImpl;
0123
0124
0125 template <SoAColumnType COLUMN_TYPE, typename T>
0126 struct SoAConstParametersImpl {
0127 static constexpr SoAColumnType columnType = COLUMN_TYPE;
0128
0129 using ValueType = T;
0130 using ScalarType = T;
0131 using TupleOrPointerType = const ValueType*;
0132
0133
0134 SoAConstParametersImpl() = default;
0135
0136
0137 SOA_HOST_DEVICE SOA_INLINE constexpr SoAConstParametersImpl(ValueType const* addr, size_type size)
0138 : addr_(addr), size_{size} {}
0139
0140
0141 SOA_HOST_DEVICE SOA_INLINE constexpr SoAConstParametersImpl(SoAParametersImpl<columnType, ValueType> const& o)
0142 : addr_{o.addr_}, size_{o.size_} {}
0143
0144 static constexpr bool checkAlignment(ValueType* addr, byte_size_type alignment) {
0145 return reinterpret_cast<intptr_t>(addr) % alignment;
0146 }
0147
0148 TupleOrPointerType tupleOrPointer() { return addr_; }
0149
0150 public:
0151
0152 ValueType const* addr_ = nullptr;
0153 size_type size_ = 0;
0154 };
0155
0156
0157 template <typename T>
0158 struct SoAConstParametersImpl<SoAColumnType::eigen, T> {
0159 static constexpr SoAColumnType columnType = SoAColumnType::eigen;
0160
0161 using ValueType = T;
0162 using ScalarType = typename T::Scalar;
0163 using TupleOrPointerType = std::tuple<ScalarType*, byte_size_type>;
0164
0165
0166 SoAConstParametersImpl() = default;
0167
0168
0169 SOA_HOST_DEVICE SOA_INLINE constexpr SoAConstParametersImpl(ScalarType const* addr,
0170 byte_size_type stride,
0171 size_type size)
0172 : addr_(addr), stride_(stride), size_{size} {}
0173
0174
0175 SOA_HOST_DEVICE SOA_INLINE constexpr SoAConstParametersImpl(TupleOrPointerType const& tuple)
0176 : addr_(std::get<0>(tuple)), stride_(std::get<1>(tuple)) {}
0177
0178
0179 SOA_HOST_DEVICE SOA_INLINE constexpr SoAConstParametersImpl(SoAParametersImpl<columnType, ValueType> const& o)
0180 : addr_{o.addr_}, stride_{o.stride_}, size_{o.size_} {}
0181
0182 static constexpr bool checkAlignment(TupleOrPointerType const& tuple, byte_size_type alignment) {
0183 const auto& [addr, stride] = tuple;
0184 return reinterpret_cast<intptr_t>(addr) % alignment;
0185 }
0186
0187 TupleOrPointerType tupleOrPointer() { return {addr_, stride_}; }
0188
0189 public:
0190
0191 ScalarType const* addr_ = nullptr;
0192 byte_size_type stride_ = 0;
0193 size_type size_ = 0;
0194 };
0195
0196
0197 template <SoAColumnType COLUMN_TYPE>
0198 struct SoAConstParameters_ColumnType {
0199 template <typename T>
0200 using DataType = SoAConstParametersImpl<COLUMN_TYPE, T>;
0201 };
0202
0203
0204 template <SoAColumnType COLUMN_TYPE, typename T>
0205 struct SoAParametersImpl {
0206 static constexpr SoAColumnType columnType = COLUMN_TYPE;
0207
0208 using ValueType = T;
0209 using ScalarType = T;
0210 using TupleOrPointerType = ValueType*;
0211
0212 using ConstType = SoAConstParametersImpl<columnType, ValueType>;
0213 friend ConstType;
0214
0215
0216 SoAParametersImpl() = default;
0217
0218
0219 SOA_HOST_DEVICE SOA_INLINE constexpr SoAParametersImpl(ValueType* addr, size_type size)
0220 : addr_(addr), size_{size} {}
0221
0222 static constexpr bool checkAlignment(ValueType* addr, byte_size_type alignment) {
0223 return reinterpret_cast<intptr_t>(addr) % alignment;
0224 }
0225
0226 TupleOrPointerType tupleOrPointer() { return addr_; }
0227
0228 public:
0229
0230 ValueType* addr_ = nullptr;
0231 size_type size_ = 0;
0232 };
0233
0234
0235 template <typename T>
0236 struct SoAParametersImpl<SoAColumnType::eigen, T> {
0237 static constexpr SoAColumnType columnType = SoAColumnType::eigen;
0238
0239 using ValueType = T;
0240 using ScalarType = typename T::Scalar;
0241 using TupleOrPointerType = std::tuple<ScalarType*, byte_size_type>;
0242
0243 using ConstType = SoAConstParametersImpl<columnType, ValueType>;
0244 friend ConstType;
0245
0246
0247 SoAParametersImpl() = default;
0248
0249
0250 SOA_HOST_DEVICE SOA_INLINE constexpr SoAParametersImpl(ScalarType* addr, byte_size_type stride, size_type size)
0251 : addr_(addr), stride_(stride), size_(size) {}
0252
0253
0254 SOA_HOST_DEVICE SOA_INLINE constexpr SoAParametersImpl(TupleOrPointerType const& tuple)
0255 : addr_(std::get<0>(tuple)), stride_(std::get<1>(tuple)) {}
0256
0257 static constexpr bool checkAlignment(TupleOrPointerType const& tuple, byte_size_type alignment) {
0258 const auto& [addr, stride] = tuple;
0259 return reinterpret_cast<intptr_t>(addr) % alignment;
0260 }
0261
0262 TupleOrPointerType tupleOrPointer() { return {addr_, stride_}; }
0263
0264 public:
0265
0266 ScalarType* addr_ = nullptr;
0267 byte_size_type stride_ = 0;
0268 size_type size_ = 0;
0269 };
0270
0271
0272 template <SoAColumnType COLUMN_TYPE>
0273 struct SoAParameters_ColumnType {
0274 template <typename T>
0275 using DataType = SoAParametersImpl<COLUMN_TYPE, T>;
0276 };
0277
0278
0279 namespace {
0280 template <typename T>
0281 constexpr inline std::remove_const_t<T>* non_const_ptr(T* p) {
0282 return const_cast<std::remove_const_t<T>*>(p);
0283 }
0284 }
0285
0286 template <SoAColumnType COLUMN_TYPE, typename T>
0287 SOA_HOST_DEVICE SOA_INLINE constexpr SoAParametersImpl<COLUMN_TYPE, T> const_cast_SoAParametersImpl(
0288 SoAConstParametersImpl<COLUMN_TYPE, T> const& o) {
0289 return SoAParametersImpl<COLUMN_TYPE, T>{non_const_ptr(o.addr_), o.size_};
0290 }
0291
0292 template <typename T>
0293 SOA_HOST_DEVICE SOA_INLINE constexpr SoAParametersImpl<SoAColumnType::eigen, T> const_cast_SoAParametersImpl(
0294 SoAConstParametersImpl<SoAColumnType::eigen, T> const& o) {
0295 return SoAParametersImpl<SoAColumnType::eigen, T>{non_const_ptr(o.addr_), o.stride_, o.size_};
0296 }
0297
0298
0299
0300
0301 template <SoAColumnType COLUMN_TYPE,
0302 typename T,
0303 byte_size_type ALIGNMENT,
0304 bool RESTRICT_QUALIFY = RestrictQualify::disabled>
0305 class SoAValue {
0306
0307 static_assert(COLUMN_TYPE != SoAColumnType::eigen);
0308
0309 public:
0310 using Restr = add_restrict<T, RESTRICT_QUALIFY>;
0311 using Val = typename Restr::Value;
0312 using Ptr = typename Restr::Pointer;
0313 using Ref = typename Restr::Reference;
0314 using PtrToConst = typename Restr::PointerToConst;
0315 using RefToConst = typename Restr::ReferenceToConst;
0316
0317 SOA_HOST_DEVICE SOA_INLINE SoAValue(size_type i, T* col) : idx_(i), col_(col) {}
0318
0319 SOA_HOST_DEVICE SOA_INLINE SoAValue(size_type i, SoAParametersImpl<COLUMN_TYPE, T> params)
0320 : idx_(i), col_(params.addr_) {}
0321
0322 SOA_HOST_DEVICE SOA_INLINE Ref operator()() {
0323
0324 Ptr col = col_;
0325 return col[idx_];
0326 }
0327
0328 SOA_HOST_DEVICE SOA_INLINE RefToConst operator()() const {
0329
0330 PtrToConst col = col_;
0331 return col[idx_];
0332 }
0333
0334 SOA_HOST_DEVICE SOA_INLINE Ptr operator&() { return &col_[idx_]; }
0335
0336 SOA_HOST_DEVICE SOA_INLINE PtrToConst operator&() const { return &col_[idx_]; }
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359 using valueType = Val;
0360
0361 static constexpr auto valueSize = sizeof(T);
0362
0363 private:
0364 size_type idx_;
0365 T* col_;
0366 };
0367
0368
0369 #ifdef EIGEN_WORLD_VERSION
0370
0371 template <class C, byte_size_type ALIGNMENT, bool RESTRICT_QUALIFY>
0372 class SoAValue<SoAColumnType::eigen, C, ALIGNMENT, RESTRICT_QUALIFY> {
0373 public:
0374 using Type = C;
0375 using MapType = Eigen::Map<C, 0, Eigen::InnerStride<Eigen::Dynamic>>;
0376 using CMapType = const Eigen::Map<const C, 0, Eigen::InnerStride<Eigen::Dynamic>>;
0377 using Restr = add_restrict<typename C::Scalar, RESTRICT_QUALIFY>;
0378 using Val = typename Restr::Value;
0379 using Ptr = typename Restr::Pointer;
0380 using Ref = typename Restr::Reference;
0381 using PtrToConst = typename Restr::PointerToConst;
0382 using RefToConst = typename Restr::ReferenceToConst;
0383
0384 SOA_HOST_DEVICE SOA_INLINE SoAValue(size_type i, typename C::Scalar* col, byte_size_type stride)
0385 : val_(col + i, C::RowsAtCompileTime, C::ColsAtCompileTime, Eigen::InnerStride<Eigen::Dynamic>(stride)),
0386 crCol_(col),
0387 cVal_(crCol_ + i, C::RowsAtCompileTime, C::ColsAtCompileTime, Eigen::InnerStride<Eigen::Dynamic>(stride)),
0388 stride_(stride) {}
0389
0390 SOA_HOST_DEVICE SOA_INLINE SoAValue(size_type i, SoAParametersImpl<SoAColumnType::eigen, C> params)
0391 : val_(params.addr_ + i,
0392 C::RowsAtCompileTime,
0393 C::ColsAtCompileTime,
0394 Eigen::InnerStride<Eigen::Dynamic>(params.stride_)),
0395 crCol_(params.addr_),
0396 cVal_(crCol_ + i,
0397 C::RowsAtCompileTime,
0398 C::ColsAtCompileTime,
0399 Eigen::InnerStride<Eigen::Dynamic>(params.stride_)),
0400 stride_(params.stride_) {}
0401
0402 SOA_HOST_DEVICE SOA_INLINE MapType& operator()() { return val_; }
0403
0404 SOA_HOST_DEVICE SOA_INLINE const CMapType& operator()() const { return cVal_; }
0405
0406 SOA_HOST_DEVICE SOA_INLINE operator C() { return val_; }
0407
0408 SOA_HOST_DEVICE SOA_INLINE operator const C() const { return cVal_; }
0409
0410 SOA_HOST_DEVICE SOA_INLINE C* operator&() { return &val_; }
0411
0412 SOA_HOST_DEVICE SOA_INLINE const C* operator&() const { return &cVal_; }
0413
0414 template <class C2>
0415 SOA_HOST_DEVICE SOA_INLINE MapType& operator=(const C2& v) {
0416 return val_ = v;
0417 }
0418
0419 using ValueType = typename C::Scalar;
0420 static constexpr auto valueSize = sizeof(typename C::Scalar);
0421 SOA_HOST_DEVICE SOA_INLINE byte_size_type stride() const { return stride_; }
0422
0423 private:
0424 MapType val_;
0425 const Ptr crCol_;
0426 CMapType cVal_;
0427 byte_size_type stride_;
0428 };
0429 #else
0430
0431 template <class C, byte_size_type ALIGNMENT, bool RESTRICT_QUALIFY>
0432 class SoAValue<SoAColumnType::eigen, C, ALIGNMENT, RESTRICT_QUALIFY> {
0433 static_assert(!sizeof(C),
0434 "Eigen/Core should be pre-included before the SoA headers to enable support for Eigen columns.");
0435 };
0436 #endif
0437
0438
0439 template <SoAColumnType COLUMN_TYPE,
0440 typename T,
0441 byte_size_type ALIGNMENT,
0442 bool RESTRICT_QUALIFY = RestrictQualify::disabled>
0443 class SoAConstValue {
0444
0445 static_assert(COLUMN_TYPE != SoAColumnType::eigen);
0446
0447 public:
0448 using Restr = add_restrict<T, RESTRICT_QUALIFY>;
0449 using Val = typename Restr::Value;
0450 using Ptr = typename Restr::Pointer;
0451 using Ref = typename Restr::Reference;
0452 using PtrToConst = typename Restr::PointerToConst;
0453 using RefToConst = typename Restr::ReferenceToConst;
0454 using Params = SoAParametersImpl<COLUMN_TYPE, T>;
0455 using ConstParams = SoAConstParametersImpl<COLUMN_TYPE, T>;
0456
0457 SOA_HOST_DEVICE SOA_INLINE SoAConstValue(size_type i, const T* col) : idx_(i), col_(col) {}
0458
0459 SOA_HOST_DEVICE SOA_INLINE SoAConstValue(size_type i, SoAParametersImpl<COLUMN_TYPE, T> params)
0460 : idx_(i), col_(params.addr_) {}
0461
0462 SOA_HOST_DEVICE SOA_INLINE SoAConstValue(size_type i, SoAConstParametersImpl<COLUMN_TYPE, T> params)
0463 : idx_(i), col_(params.addr_) {}
0464
0465 SOA_HOST_DEVICE SOA_INLINE RefToConst operator()() const {
0466
0467 PtrToConst col = col_;
0468 return col[idx_];
0469 }
0470
0471 SOA_HOST_DEVICE SOA_INLINE const T* operator&() const { return &col_[idx_]; }
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487 using valueType = T;
0488 static constexpr auto valueSize = sizeof(T);
0489
0490 private:
0491 size_type idx_;
0492 const T* col_;
0493 };
0494
0495
0496 #ifdef EIGEN_WORLD_VERSION
0497
0498 template <class C, byte_size_type ALIGNMENT, bool RESTRICT_QUALIFY>
0499 class SoAConstValue<SoAColumnType::eigen, C, ALIGNMENT, RESTRICT_QUALIFY> {
0500 public:
0501 using Type = C;
0502 using CMapType = Eigen::Map<const C, 0, Eigen::InnerStride<Eigen::Dynamic>>;
0503 using RefToConst = const CMapType&;
0504 using ConstParams = SoAConstParametersImpl<SoAColumnType::eigen, C>;
0505
0506 SOA_HOST_DEVICE SOA_INLINE SoAConstValue(size_type i, typename C::Scalar* col, byte_size_type stride)
0507 : crCol_(col),
0508 cVal_(crCol_ + i, C::RowsAtCompileTime, C::ColsAtCompileTime, Eigen::InnerStride<Eigen::Dynamic>(stride)),
0509 stride_(stride) {}
0510
0511 SOA_HOST_DEVICE SOA_INLINE SoAConstValue(size_type i, SoAConstParametersImpl<SoAColumnType::eigen, C> params)
0512 : crCol_(params.addr_),
0513 cVal_(crCol_ + i,
0514 C::RowsAtCompileTime,
0515 C::ColsAtCompileTime,
0516 Eigen::InnerStride<Eigen::Dynamic>(params.stride_)),
0517 stride_(params.stride_) {}
0518
0519 SOA_HOST_DEVICE SOA_INLINE const CMapType& operator()() const { return cVal_; }
0520
0521 SOA_HOST_DEVICE SOA_INLINE operator const C() const { return cVal_; }
0522
0523 SOA_HOST_DEVICE SOA_INLINE const C* operator&() const { return &cVal_; }
0524
0525 using ValueType = typename C::Scalar;
0526 static constexpr auto valueSize = sizeof(typename C::Scalar);
0527
0528 SOA_HOST_DEVICE SOA_INLINE byte_size_type stride() const { return stride_; }
0529
0530 private:
0531 const typename C::Scalar* __restrict__ crCol_;
0532 CMapType cVal_;
0533 byte_size_type stride_;
0534 };
0535 #else
0536
0537 template <class C, byte_size_type ALIGNMENT, bool RESTRICT_QUALIFY>
0538 class SoAConstValue<SoAColumnType::eigen, C, ALIGNMENT, RESTRICT_QUALIFY> {
0539 static_assert(!sizeof(C),
0540 "Eigen/Core should be pre-included before the SoA headers to enable support for Eigen columns.");
0541 };
0542 #endif
0543
0544
0545 #ifdef EIGEN_WORLD_VERSION
0546 template <class C>
0547 struct EigenConstMapMaker {
0548 using Type = Eigen::Map<const C, Eigen::AlignmentType::Unaligned, Eigen::InnerStride<Eigen::Dynamic>>;
0549
0550 class DataHolder {
0551 public:
0552 DataHolder(const typename C::Scalar* data) : data_(data) {}
0553
0554 EigenConstMapMaker::Type withStride(byte_size_type stride) {
0555 return EigenConstMapMaker::Type(
0556 data_, C::RowsAtCompileTime, C::ColsAtCompileTime, Eigen::InnerStride<Eigen::Dynamic>(stride));
0557 }
0558
0559 private:
0560 const typename C::Scalar* const data_;
0561 };
0562
0563 static DataHolder withData(const typename C::Scalar* data) { return DataHolder(data); }
0564 };
0565 #else
0566 template <class C>
0567 struct EigenConstMapMaker {
0568
0569 static_assert(!sizeof(C),
0570 "Eigen/Core should be pre-included before the SoA headers to enable support for Eigen columns.");
0571 };
0572 #endif
0573
0574
0575
0576 constexpr inline byte_size_type alignSize(byte_size_type size, byte_size_type alignment) {
0577 return ((size + alignment - 1) / alignment) * alignment;
0578 }
0579
0580 }
0581
0582 #define SOA_SCALAR(TYPE, NAME) (_VALUE_TYPE_SCALAR, TYPE, NAME, ~)
0583 #define SOA_COLUMN(TYPE, NAME) (_VALUE_TYPE_COLUMN, TYPE, NAME, ~)
0584 #define SOA_EIGEN_COLUMN(TYPE, NAME) (_VALUE_TYPE_EIGEN_COLUMN, TYPE, NAME, ~)
0585 #define SOA_ELEMENT_METHODS(...) (_VALUE_TYPE_METHOD, _, _, (__VA_ARGS__))
0586 #define SOA_CONST_ELEMENT_METHODS(...) (_VALUE_TYPE_CONST_METHOD, _, _, (__VA_ARGS__))
0587
0588
0589 #define GENERATE_METHODS(R, DATA, FIELD) \
0590 BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_ELEM(0, FIELD), _VALUE_TYPE_METHOD), \
0591 BOOST_PP_TUPLE_ELEM(3, FIELD), \
0592 BOOST_PP_EMPTY())
0593
0594
0595 #define GENERATE_CONST_METHODS(R, DATA, FIELD) \
0596 BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_ELEM(0, FIELD), _VALUE_TYPE_CONST_METHOD), \
0597 BOOST_PP_TUPLE_ELEM(3, FIELD), \
0598 BOOST_PP_EMPTY())
0599
0600
0601 #define ENUM_FOR_PRED(R, STATE) BOOST_PP_LESS(BOOST_PP_TUPLE_ELEM(0, STATE), BOOST_PP_TUPLE_ELEM(1, STATE))
0602
0603 #define ENUM_FOR_OP(R, STATE) \
0604 (BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(0, STATE)), BOOST_PP_TUPLE_ELEM(1, STATE), BOOST_PP_TUPLE_ELEM(2, STATE))
0605
0606 #define ENUM_FOR_MACRO(R, STATE) \
0607 BOOST_PP_TUPLE_ENUM(BOOST_PP_SEQ_ELEM(BOOST_PP_TUPLE_ELEM(0, STATE), BOOST_PP_TUPLE_ELEM(2, STATE)))
0608
0609 #define ENUM_IF_VALID(...) \
0610 BOOST_PP_FOR((0, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)), \
0611 ENUM_FOR_PRED, \
0612 ENUM_FOR_OP, \
0613 ENUM_FOR_MACRO)
0614
0615
0616
0617 #define _ITERATE_ON_ALL_COMMA(MACRO, DATA, ...) \
0618 BOOST_PP_TUPLE_ENUM(BOOST_PP_SEQ_TO_TUPLE(_ITERATE_ON_ALL(MACRO, DATA, __VA_ARGS__)))
0619
0620
0621 #define _ITERATE_ON_ALL(MACRO, DATA, ...) BOOST_PP_SEQ_FOR_EACH(MACRO, DATA, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
0622
0623
0624 #define _SWITCH_ON_TYPE(VALUE_TYPE, IF_SCALAR, IF_COLUMN, IF_EIGEN_COLUMN) \
0625 BOOST_PP_IF( \
0626 BOOST_PP_EQUAL(VALUE_TYPE, _VALUE_TYPE_SCALAR), \
0627 IF_SCALAR, \
0628 BOOST_PP_IF( \
0629 BOOST_PP_EQUAL(VALUE_TYPE, _VALUE_TYPE_COLUMN), \
0630 IF_COLUMN, \
0631 BOOST_PP_IF(BOOST_PP_EQUAL(VALUE_TYPE, _VALUE_TYPE_EIGEN_COLUMN), IF_EIGEN_COLUMN, BOOST_PP_EMPTY())))
0632
0633 namespace cms::soa {
0634
0635
0636 enum class SoAAccessType : bool { mutableAccess, constAccess };
0637
0638 template <typename, SoAColumnType, SoAAccessType, byte_size_type, bool>
0639 struct SoAColumnAccessorsImpl {};
0640
0641
0642
0643
0644
0645
0646 template <typename T, byte_size_type alignment, bool restrictQualify>
0647 struct SoAColumnAccessorsImpl<T, SoAColumnType::column, SoAAccessType::mutableAccess, alignment, restrictQualify> {
0648 SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAParametersImpl<SoAColumnType::column, T>& params)
0649 : params_(params) {}
0650 SOA_HOST_DEVICE SOA_INLINE T* operator()() { return params_.addr_; }
0651
0652 using NoParamReturnType = T*;
0653 using ParamReturnType = T&;
0654 SOA_HOST_DEVICE SOA_INLINE T& operator()(size_type index) { return params_.addr_[index]; }
0655
0656 private:
0657 SoAParametersImpl<SoAColumnType::column, T> params_;
0658 };
0659
0660
0661 template <typename T, byte_size_type alignment, bool restrictQualify>
0662 struct SoAColumnAccessorsImpl<T, SoAColumnType::column, SoAAccessType::constAccess, alignment, restrictQualify> {
0663 SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAConstParametersImpl<SoAColumnType::column, T>& params)
0664 : params_(params) {}
0665 SOA_HOST_DEVICE SOA_INLINE const T* operator()() const { return params_.addr_; }
0666 using NoParamReturnType = const T*;
0667 using ParamReturnType = const T&;
0668 SOA_HOST_DEVICE SOA_INLINE T const& operator()(size_type index) const { return params_.addr_[index]; }
0669
0670 private:
0671 SoAConstParametersImpl<SoAColumnType::column, T> params_;
0672 };
0673
0674
0675 template <typename T, byte_size_type alignment, bool restrictQualify>
0676 struct SoAColumnAccessorsImpl<T, SoAColumnType::scalar, SoAAccessType::mutableAccess, alignment, restrictQualify> {
0677 SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAParametersImpl<SoAColumnType::scalar, T>& params)
0678 : params_(params) {}
0679 SOA_HOST_DEVICE SOA_INLINE T& operator()() { return *params_.addr_; }
0680 using NoParamReturnType = T&;
0681 using ParamReturnType = void;
0682 SOA_HOST_DEVICE SOA_INLINE void operator()(size_type index) const {
0683 assert(false && "Indexed access impossible for SoA scalars.");
0684 }
0685
0686 private:
0687 SoAParametersImpl<SoAColumnType::scalar, T> params_;
0688 };
0689
0690
0691 template <typename T, byte_size_type alignment, bool restrictQualify>
0692 struct SoAColumnAccessorsImpl<T, SoAColumnType::scalar, SoAAccessType::constAccess, alignment, restrictQualify> {
0693 SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAConstParametersImpl<SoAColumnType::scalar, T>& params)
0694 : params_(params) {}
0695 SOA_HOST_DEVICE SOA_INLINE T const& operator()() const { return *params_.addr_; }
0696 using NoParamReturnType = T const&;
0697 using ParamReturnType = void;
0698 SOA_HOST_DEVICE SOA_INLINE void operator()(size_type index) const {
0699 assert(false && "Indexed access impossible for SoA scalars.");
0700 }
0701
0702 private:
0703 SoAConstParametersImpl<SoAColumnType::scalar, T> params_;
0704 };
0705
0706
0707 template <typename T, byte_size_type alignment, bool restrictQualify>
0708 struct SoAColumnAccessorsImpl<T, SoAColumnType::eigen, SoAAccessType::mutableAccess, alignment, restrictQualify> {
0709 SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAParametersImpl<SoAColumnType::eigen, T>& params)
0710 : params_(params) {}
0711 SOA_HOST_DEVICE SOA_INLINE typename T::Scalar* operator()() { return params_.addr_; }
0712 using NoParamReturnType = typename T::Scalar*;
0713 using ParamReturnType = typename SoAValue<SoAColumnType::eigen, T, alignment, restrictQualify>::MapType;
0714 SOA_HOST_DEVICE SOA_INLINE ParamReturnType operator()(size_type index) {
0715 return SoAValue<SoAColumnType::eigen, T, alignment, restrictQualify>(index, params_)();
0716 }
0717
0718 private:
0719 SoAParametersImpl<SoAColumnType::eigen, T> params_;
0720 };
0721
0722
0723 template <typename T, byte_size_type alignment, bool restrictQualify>
0724 struct SoAColumnAccessorsImpl<T, SoAColumnType::eigen, SoAAccessType::constAccess, alignment, restrictQualify> {
0725 SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAConstParametersImpl<SoAColumnType::eigen, T>& params)
0726 : params_(params) {}
0727 SOA_HOST_DEVICE SOA_INLINE typename T::Scalar const* operator()() const { return params_.addr_; }
0728 using NoParamReturnType = typename T::Scalar const*;
0729 using ParamReturnType = typename SoAValue<SoAColumnType::eigen, T, alignment, restrictQualify>::CMapType;
0730 SOA_HOST_DEVICE SOA_INLINE ParamReturnType operator()(size_type index) const {
0731 return SoAConstValue<SoAColumnType::eigen, T, alignment, restrictQualify>(index, params_)();
0732 }
0733
0734 private:
0735 SoAConstParametersImpl<SoAColumnType::eigen, T> params_;
0736 };
0737
0738
0739 template <typename T>
0740 struct SoAAccessors {
0741 template <auto columnType>
0742 struct ColumnType {
0743 template <auto accessType>
0744 struct AccessType {
0745 template <auto alignment>
0746 struct Alignment {
0747 template <auto restrictQualify>
0748 struct RestrictQualifier
0749 : public SoAColumnAccessorsImpl<T, columnType, accessType, alignment, restrictQualify> {
0750 using SoAColumnAccessorsImpl<T, columnType, accessType, alignment, restrictQualify>::SoAColumnAccessorsImpl;
0751 };
0752 };
0753 };
0754 };
0755 };
0756
0757
0758
0759
0760 struct AlignmentEnforcement {
0761 static constexpr bool relaxed = false;
0762 static constexpr bool enforced = true;
0763 };
0764
0765 struct CacheLineSize {
0766 static constexpr byte_size_type NvidiaGPU = 128;
0767 static constexpr byte_size_type IntelCPU = 64;
0768 static constexpr byte_size_type AMDCPU = 64;
0769 static constexpr byte_size_type ARMCPU = 64;
0770 static constexpr byte_size_type defaultSize = NvidiaGPU;
0771 };
0772
0773 }
0774
0775
0776 template <typename SOA,
0777 typename SFINAE =
0778 typename std::enable_if_t<std::is_invocable_v<decltype(&SOA::soaToStreamInternal), SOA&, std::ostream&>>>
0779 SOA_HOST_ONLY std::ostream& operator<<(std::ostream& os, const SOA& soa) {
0780 soa.soaToStreamInternal(os);
0781 return os;
0782 }
0783
0784 #endif