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