Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:05:15

0001 #ifndef DataFormats_SoATemplate_interface_SoALayout_h
0002 #define DataFormats_SoATemplate_interface_SoALayout_h
0003 
0004 /*
0005  * Structure-of-Arrays template with "columns" and "scalars", defined through preprocessor macros,
0006  * with compile-time size and alignment, and accessors to the "rows" and "columns".
0007  */
0008 
0009 #include <cassert>
0010 
0011 #include "FWCore/Reflection/interface/reflex.h"
0012 
0013 #include "SoACommon.h"
0014 #include "SoAView.h"
0015 
0016 /* dump SoA fields information; these should expand to, for columns:
0017  * Example:
0018  * GENERATE_SOA_LAYOUT(SoA,
0019  *   // predefined static scalars
0020  *   // size_t size;
0021  *   // size_t alignment;
0022  *
0023  *   // columns: one value per element
0024  *   SOA_COLUMN(double, x),
0025  *   SOA_COLUMN(double, y),
0026  *   SOA_COLUMN(double, z),
0027  *   SOA_EIGEN_COLUMN(Eigen::Vector3d, a),
0028  *   SOA_EIGEN_COLUMN(Eigen::Vector3d, b),
0029  *   SOA_EIGEN_COLUMN(Eigen::Vector3d, r),
0030  *   SOA_COLUMN(uint16_t, colour),
0031  *   SOA_COLUMN(int32_t, value),
0032  *   SOA_COLUMN(double *, py),
0033  *   SOA_COLUMN(uint32_t, count),
0034  *   SOA_COLUMN(uint32_t, anotherCount),
0035  *
0036  *   // scalars: one value for the whole structure
0037  *   SOA_SCALAR(const char *, description), 
0038  *   SOA_SCALAR(uint32_t, someNumber)
0039  * );
0040  *
0041  * dumps as:
0042  * SoA(32, 64):
0043  *   sizeof(SoA): 152
0044  *  Column x_ at offset 0 has size 256 and padding 0
0045  *  Column y_ at offset 256 has size 256 and padding 0
0046  *  Column z_ at offset 512 has size 256 and padding 0
0047  *  Eigen value a_ at offset 768 has dimension (3 x 1) and per column size 256 and padding 0
0048  *  Eigen value b_ at offset 1536 has dimension (3 x 1) and per column size 256 and padding 0
0049  *  Eigen value r_ at offset 2304 has dimension (3 x 1) and per column size 256 and padding 0
0050  *  Column colour_ at offset 3072 has size 64 and padding 0
0051  *  Column value_ at offset 3136 has size 128 and padding 0
0052  *  Column py_ at offset 3264 has size 256 and padding 0
0053  *  Column count_ at offset 3520 has size 128 and padding 0
0054  *  Column anotherCount_ at offset 3648 has size 128 and padding 0
0055  *  Scalar description_ at offset 3776 has size 8 and padding 56
0056  *  Scalar someNumber_ at offset 3840 has size 4 and padding 60
0057  * Final offset = 3904 computeDataSize(...): 3904
0058  *
0059  */
0060 
0061 // clang-format off
0062 #define _DECLARE_SOA_STREAM_INFO_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                      \
0063   _SWITCH_ON_TYPE(                                                                                                     \
0064       VALUE_TYPE,                                                                                                      \
0065       /* Dump scalar */                                                                                                \
0066       _soa_impl_os << " Scalar " BOOST_PP_STRINGIZE(NAME) " at offset " << _soa_impl_offset                            \
0067          << " has size " << sizeof(CPP_TYPE)                                                                           \
0068          << " and padding " << ((sizeof(CPP_TYPE) - 1) / alignment + 1) * alignment - sizeof(CPP_TYPE)                 \
0069          << std::endl;                                                                                                 \
0070       _soa_impl_offset += ((sizeof(CPP_TYPE) - 1) / alignment + 1) * alignment;                                        \
0071       ,                                                                                                                \
0072       /* Dump column */                                                                                                \
0073       _soa_impl_os << " Column " BOOST_PP_STRINGIZE(NAME) " at offset " << _soa_impl_offset << " has size "            \
0074          << sizeof(CPP_TYPE) * elements_ << " and padding "                                                            \
0075          << cms::soa::alignSize(elements_ * sizeof(CPP_TYPE), alignment) - (elements_ * sizeof(CPP_TYPE))              \
0076          << std::endl;                                                                                                 \
0077       _soa_impl_offset += cms::soa::alignSize(elements_ * sizeof(CPP_TYPE), alignment);                                \
0078       ,                                                                                                                \
0079       /* Dump Eigen column */                                                                                          \
0080       _soa_impl_os << " Eigen value " BOOST_PP_STRINGIZE(NAME) " at offset " << _soa_impl_offset << " has dimension "  \
0081          << "(" << CPP_TYPE::RowsAtCompileTime << " x " << CPP_TYPE::ColsAtCompileTime << ")"                          \
0082          << " and per column size "                                                                                    \
0083          << sizeof(CPP_TYPE::Scalar) * elements_                                                                       \
0084          << " and padding "                                                                                            \
0085          << cms::soa::alignSize(elements_ * sizeof(CPP_TYPE::Scalar), alignment)                                       \
0086             - (elements_ * sizeof(CPP_TYPE::Scalar))                                                                   \
0087          << std::endl;                                                                                                 \
0088       _soa_impl_offset += cms::soa::alignSize(elements_ * sizeof(CPP_TYPE::Scalar), alignment)                         \
0089                 * CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime;                                           \
0090   )
0091 // clang-format on
0092 
0093 #define _DECLARE_SOA_STREAM_INFO(R, DATA, TYPE_NAME) BOOST_PP_EXPAND(_DECLARE_SOA_STREAM_INFO_IMPL TYPE_NAME)
0094 
0095 /**
0096  * Metadata member computing column pitch
0097  */
0098 // clang-format off
0099 #define _DEFINE_METADATA_MEMBERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                      \
0100   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0101       /* Scalar */                                                                                                     \
0102       byte_size_type BOOST_PP_CAT(NAME, Pitch()) const {                                                               \
0103         return cms::soa::alignSize(sizeof(CPP_TYPE), ParentClass::alignment);                                          \
0104       }                                                                                                                \
0105       using BOOST_PP_CAT(TypeOf_, NAME) = CPP_TYPE;                                                                    \
0106       constexpr static cms::soa::SoAColumnType BOOST_PP_CAT(ColumnTypeOf_, NAME) = cms::soa::SoAColumnType::scalar;    \
0107       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0108       CPP_TYPE const* BOOST_PP_CAT(addressOf_, NAME)() const {                                                         \
0109         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0110       }                                                                                                                \
0111       using BOOST_PP_CAT(ParametersTypeOf_, NAME) =                                                                    \
0112         cms::soa::SoAParameters_ColumnType<cms::soa::SoAColumnType::scalar>::DataType<CPP_TYPE>;                       \
0113       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0114       BOOST_PP_CAT(ParametersTypeOf_, NAME) BOOST_PP_CAT(parametersOf_, NAME)() const {                                \
0115         return  BOOST_PP_CAT(ParametersTypeOf_, NAME) (parent_.BOOST_PP_CAT(NAME, _));                                 \
0116       }                                                                                                                \
0117       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0118       CPP_TYPE* BOOST_PP_CAT(addressOf_, NAME)() {                                                                     \
0119         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0120       },                                                                                                               \
0121       /* Column */                                                                                                     \
0122       using BOOST_PP_CAT(ParametersTypeOf_, NAME) =                                                                    \
0123          cms::soa::SoAParameters_ColumnType<cms::soa::SoAColumnType::column>::DataType<CPP_TYPE>;                      \
0124       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0125       BOOST_PP_CAT(ParametersTypeOf_, NAME) BOOST_PP_CAT(parametersOf_, NAME)() const {                                \
0126         return  BOOST_PP_CAT(ParametersTypeOf_, NAME) (parent_.BOOST_PP_CAT(NAME, _));                                 \
0127       }                                                                                                                \
0128       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0129       CPP_TYPE const* BOOST_PP_CAT(addressOf_, NAME)() const {                                                         \
0130         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0131       }                                                                                                                \
0132       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0133       CPP_TYPE* BOOST_PP_CAT(addressOf_, NAME)() {                                                                     \
0134         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0135       }                                                                                                                \
0136       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0137       byte_size_type BOOST_PP_CAT(NAME, Pitch()) const {                                                               \
0138         return cms::soa::alignSize(parent_.elements_ * sizeof(CPP_TYPE), ParentClass::alignment);                      \
0139       }                                                                                                                \
0140       using BOOST_PP_CAT(TypeOf_, NAME) = CPP_TYPE;                                                                    \
0141       constexpr static cms::soa::SoAColumnType BOOST_PP_CAT(ColumnTypeOf_, NAME) = cms::soa::SoAColumnType::column;,   \
0142       /* Eigen column */                                                                                               \
0143       using BOOST_PP_CAT(ParametersTypeOf_, NAME) =                                                                    \
0144           cms::soa::SoAParameters_ColumnType<cms::soa::SoAColumnType::eigen>::DataType<CPP_TYPE>;                      \
0145       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0146       BOOST_PP_CAT(ParametersTypeOf_, NAME) BOOST_PP_CAT(parametersOf_, NAME)() const {                                \
0147         return BOOST_PP_CAT(ParametersTypeOf_, NAME) (                                                                 \
0148           parent_.BOOST_PP_CAT(NAME, _),                                                                               \
0149           parent_.BOOST_PP_CAT(NAME, Stride_));                                                                        \
0150       }                                                                                                                \
0151       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0152       byte_size_type BOOST_PP_CAT(NAME, Pitch()) const {                                                               \
0153         return cms::soa::alignSize(parent_.elements_ * sizeof(CPP_TYPE::Scalar), ParentClass::alignment)               \
0154                * CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime;                                            \
0155       }                                                                                                                \
0156       using BOOST_PP_CAT(TypeOf_, NAME) = CPP_TYPE ;                                                                   \
0157       constexpr static cms::soa::SoAColumnType BOOST_PP_CAT(ColumnTypeOf_, NAME) = cms::soa::SoAColumnType::eigen;     \
0158       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0159       CPP_TYPE::Scalar const* BOOST_PP_CAT(addressOf_, NAME)() const {                                                 \
0160         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0161       }                                                                                                                \
0162       SOA_HOST_DEVICE SOA_INLINE                                                                                       \
0163       CPP_TYPE::Scalar* BOOST_PP_CAT(addressOf_, NAME)() {                                                             \
0164         return parent_.metadata().BOOST_PP_CAT(parametersOf_, NAME)().addr_;                                           \
0165       }                                                                                                                \
0166 )
0167 // clang-format on
0168 #define _DEFINE_METADATA_MEMBERS(R, DATA, TYPE_NAME) _DEFINE_METADATA_MEMBERS_IMPL TYPE_NAME
0169 
0170 // clang-format off
0171 #define _DECLARE_MEMBER_TRIVIAL_CONSTRUCTION_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                          \
0172   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0173       /* Scalar */                                                                                                     \
0174       (BOOST_PP_CAT(NAME, _)(nullptr)),                                                                                \
0175       /* Column */                                                                                                     \
0176       (BOOST_PP_CAT(NAME, _)(nullptr)),                                                                                \
0177       /* Eigen column */                                                                                               \
0178       (BOOST_PP_CAT(NAME, ElementsWithPadding_)(0))                                                                    \
0179       (BOOST_PP_CAT(NAME, _)(nullptr))                                                                                 \
0180       (BOOST_PP_CAT(NAME, Stride_)(0))                                                                                 \
0181   )
0182 // clang-format on
0183 
0184 #define _DECLARE_MEMBER_TRIVIAL_CONSTRUCTION(R, DATA, TYPE_NAME) \
0185   BOOST_PP_EXPAND(_DECLARE_MEMBER_TRIVIAL_CONSTRUCTION_IMPL TYPE_NAME)
0186 
0187 // clang-format off
0188 #define _DECLARE_MEMBER_COPY_CONSTRUCTION_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                             \
0189   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0190       /* Scalar */                                                                                                     \
0191       (BOOST_PP_CAT(NAME, _){_soa_impl_other.BOOST_PP_CAT(NAME, _)}),                                                  \
0192       /* Column */                                                                                                     \
0193       (BOOST_PP_CAT(NAME, _){_soa_impl_other.BOOST_PP_CAT(NAME, _)}),                                                  \
0194       /* Eigen column */                                                                                               \
0195       (BOOST_PP_CAT(NAME, ElementsWithPadding_){_soa_impl_other.BOOST_PP_CAT(NAME, ElementsWithPadding_)})             \
0196       (BOOST_PP_CAT(NAME, _){_soa_impl_other.BOOST_PP_CAT(NAME, _)})                                                   \
0197       (BOOST_PP_CAT(NAME, Stride_){_soa_impl_other.BOOST_PP_CAT(NAME, Stride_)})                                       \
0198   )
0199 // clang-format on
0200 
0201 #define _DECLARE_MEMBER_COPY_CONSTRUCTION(R, DATA, TYPE_NAME) \
0202   BOOST_PP_EXPAND(_DECLARE_MEMBER_COPY_CONSTRUCTION_IMPL TYPE_NAME)
0203 
0204 // clang-format off
0205 #define _DECLARE_MEMBER_ASSIGNMENT_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                    \
0206   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0207       /* Scalar */                                                                                                     \
0208       BOOST_PP_CAT(NAME, _) = _soa_impl_other.BOOST_PP_CAT(NAME, _);,                                                  \
0209       /* Column */                                                                                                     \
0210       BOOST_PP_CAT(NAME, _) = _soa_impl_other.BOOST_PP_CAT(NAME, _);,                                                  \
0211       /* Eigen column */                                                                                               \
0212       BOOST_PP_CAT(NAME, ElementsWithPadding_) = _soa_impl_other.BOOST_PP_CAT(NAME, ElementsWithPadding_);             \
0213       BOOST_PP_CAT(NAME, _) = _soa_impl_other.BOOST_PP_CAT(NAME, _);                                                   \
0214       BOOST_PP_CAT(NAME, Stride_) = _soa_impl_other.BOOST_PP_CAT(NAME, Stride_);                                       \
0215   )
0216 // clang-format on
0217 
0218 #define _DECLARE_MEMBER_ASSIGNMENT(R, DATA, TYPE_NAME) BOOST_PP_EXPAND(_DECLARE_MEMBER_ASSIGNMENT_IMPL TYPE_NAME)
0219 
0220 /**
0221  * Declare the value_element data members
0222  */
0223 // clang-format off
0224 #define _DEFINE_VALUE_ELEMENT_MEMBERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                 \
0225   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0226       /* Scalar (empty) */                                                                                             \
0227       ,                                                                                                                \
0228       /* Column */                                                                                                     \
0229       CPP_TYPE NAME;                                                                                                   \
0230       ,                                                                                                                \
0231       /* Eigen column */                                                                                               \
0232       CPP_TYPE NAME;                                                                                                   \
0233   )
0234 // clang-format on
0235 
0236 #define _DEFINE_VALUE_ELEMENT_MEMBERS(R, DATA, TYPE_NAME) _DEFINE_VALUE_ELEMENT_MEMBERS_IMPL TYPE_NAME
0237 
0238 /**
0239  * List of data members in the value_element constructor arguments
0240  */
0241 // clang-format off
0242 #define _VALUE_ELEMENT_CTOR_ARGS_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                      \
0243   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0244       /* Scalar (empty) */                                                                                             \
0245       ,                                                                                                                \
0246       /* Column */                                                                                                     \
0247       (CPP_TYPE NAME),                                                                                                 \
0248       /* Eigen column */                                                                                               \
0249       (CPP_TYPE NAME)                                                                                                  \
0250   )
0251 // clang-format on
0252 
0253 #define _VALUE_ELEMENT_CTOR_ARGS(R, DATA, TYPE_NAME) BOOST_PP_EXPAND(_VALUE_ELEMENT_CTOR_ARGS_IMPL TYPE_NAME)
0254 
0255 /**
0256  * List-initalise the value_element data members
0257  */
0258 // clang-format off
0259 #define _VALUE_ELEMENT_INITIALIZERS_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                   \
0260   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0261       /* Scalar (empty) */                                                                                             \
0262       ,                                                                                                                \
0263       /* Column */                                                                                                     \
0264       (NAME{NAME}),                                                                                                    \
0265       /* Eigen column */                                                                                               \
0266       (NAME{NAME})                                                                                                     \
0267   )
0268 // clang-format on
0269 
0270 #define _VALUE_ELEMENT_INITIALIZERS(R, DATA, TYPE_NAME) BOOST_PP_EXPAND(_VALUE_ELEMENT_INITIALIZERS_IMPL TYPE_NAME)
0271 
0272 /**
0273  * Freeing of the ROOT-allocated column or scalar buffer
0274  */
0275 // clang-format off
0276 #define _ROOT_FREE_SOA_COLUMN_OR_SCALAR_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                  \
0277   delete[] BOOST_PP_CAT(NAME, _); \
0278   BOOST_PP_CAT(NAME, _) = nullptr; \
0279   // clang-format on
0280 
0281 #define _ROOT_FREE_SOA_COLUMN_OR_SCALAR(R, DATA, TYPE_NAME) _ROOT_FREE_SOA_COLUMN_OR_SCALAR_IMPL TYPE_NAME
0282 
0283 /**
0284  * Computation of the column or scalar pointer location in the memory layout (at SoA construction time)
0285  */
0286 // clang-format off
0287 #define _ASSIGN_SOA_COLUMN_OR_SCALAR_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                  \
0288   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0289       /* Scalar */                                                                                                     \
0290       BOOST_PP_CAT(NAME, _) = reinterpret_cast<CPP_TYPE*>(_soa_impl_curMem);                                           \
0291       _soa_impl_curMem += cms::soa::alignSize(sizeof(CPP_TYPE), alignment);                                            \
0292       ,                                                                                                                \
0293       /* Column */                                                                                                     \
0294       BOOST_PP_CAT(NAME, _) = reinterpret_cast<CPP_TYPE*>(_soa_impl_curMem);                                           \
0295       _soa_impl_curMem += cms::soa::alignSize(elements_ * sizeof(CPP_TYPE), alignment);                                \
0296       ,                                                                                                                \
0297       /* Eigen column */                                                                                               \
0298       BOOST_PP_CAT(NAME, Stride_) = cms::soa::alignSize(elements_ * sizeof(CPP_TYPE::Scalar), alignment)               \
0299         / sizeof(CPP_TYPE::Scalar);                                                                                    \
0300       BOOST_PP_CAT(NAME, ElementsWithPadding_) = BOOST_PP_CAT(NAME, Stride_)                                           \
0301         *  CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime;                                                  \
0302       BOOST_PP_CAT(NAME, _) = reinterpret_cast<CPP_TYPE::Scalar*>(_soa_impl_curMem);                                   \
0303       _soa_impl_curMem += cms::soa::alignSize(elements_ * sizeof(CPP_TYPE::Scalar), alignment)                         \
0304         * CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime;                                                   \
0305   )                                                                                                                    \
0306   if constexpr (alignmentEnforcement == AlignmentEnforcement::enforced)                                                \
0307     if (reinterpret_cast<intptr_t>(BOOST_PP_CAT(NAME, _)) % alignment)                                                 \
0308       throw std::runtime_error("In layout constructor: misaligned column: " #NAME);
0309 // clang-format on
0310 
0311 #define _ASSIGN_SOA_COLUMN_OR_SCALAR(R, DATA, TYPE_NAME) _ASSIGN_SOA_COLUMN_OR_SCALAR_IMPL TYPE_NAME
0312 
0313 /**
0314  * Computation of the column or scalar size for SoA size computation
0315  */
0316 // clang-format off
0317 #define _ACCUMULATE_SOA_ELEMENT_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                       \
0318   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0319       /* Scalar */                                                                                                     \
0320       _soa_impl_ret += cms::soa::alignSize(sizeof(CPP_TYPE), alignment);                                               \
0321       ,                                                                                                                \
0322       /* Column */                                                                                                     \
0323       _soa_impl_ret += cms::soa::alignSize(elements * sizeof(CPP_TYPE), alignment);                                    \
0324       ,                                                                                                                \
0325       /* Eigen column */                                                                                               \
0326       _soa_impl_ret += cms::soa::alignSize(elements * sizeof(CPP_TYPE::Scalar), alignment)                             \
0327              * CPP_TYPE::RowsAtCompileTime * CPP_TYPE::ColsAtCompileTime;                                              \
0328   )
0329 // clang-format on
0330 
0331 #define _ACCUMULATE_SOA_ELEMENT(R, DATA, TYPE_NAME) _ACCUMULATE_SOA_ELEMENT_IMPL TYPE_NAME
0332 
0333 /**
0334  * Direct access to column pointer and indexed access
0335  */
0336 // clang-format off
0337 #define _DECLARE_SOA_ACCESSOR_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                         \
0338   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0339       /* Scalar */                                                                                                     \
0340       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE& NAME() { return *BOOST_PP_CAT(NAME, _); }                                   \
0341       ,                                                                                                                \
0342       /* Column */                                                                                                     \
0343       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE* NAME() { return BOOST_PP_CAT(NAME, _); }                                    \
0344       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE& NAME(size_type _soa_impl_index) {                                           \
0345         return BOOST_PP_CAT(NAME, _)[_soa_impl_index];                                                                 \
0346       }                                                                                                                \
0347       ,                                                                                                                \
0348       /* Eigen column */                                                                                               \
0349       /* TODO: implement*/                                                                                             \
0350       BOOST_PP_EMPTY()                                                                                                 \
0351   )
0352 // clang-format on
0353 
0354 #define _DECLARE_SOA_ACCESSOR(R, DATA, TYPE_NAME) BOOST_PP_EXPAND(_DECLARE_SOA_ACCESSOR_IMPL TYPE_NAME)
0355 
0356 /**
0357  * Direct access to column pointer (const) and indexed access.
0358  */
0359 // clang-format off
0360 #define _DECLARE_SOA_CONST_ACCESSOR_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                   \
0361   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0362       /* Scalar */                                                                                                     \
0363       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE NAME() const { return *(BOOST_PP_CAT(NAME, _)); }                            \
0364       ,                                                                                                                \
0365       /* Column */                                                                                                     \
0366       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE const* NAME() const { return BOOST_PP_CAT(NAME, _); }                        \
0367       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE NAME(size_type _soa_impl_index) const {                                      \
0368         return *(BOOST_PP_CAT(NAME, _) + _soa_impl_index);                                                             \
0369       }                                                                                                                \
0370       ,                                                                                                                \
0371       /* Eigen column */                                                                                               \
0372       SOA_HOST_DEVICE SOA_INLINE CPP_TYPE::Scalar const* NAME() const { return BOOST_PP_CAT(NAME, _); }                \
0373       SOA_HOST_DEVICE SOA_INLINE size_type BOOST_PP_CAT(NAME, Stride)() { return BOOST_PP_CAT(NAME, Stride_); }        \
0374   )
0375 // clang-format on
0376 
0377 #define _DECLARE_SOA_CONST_ACCESSOR(R, DATA, TYPE_NAME) BOOST_PP_EXPAND(_DECLARE_SOA_CONST_ACCESSOR_IMPL TYPE_NAME)
0378 
0379 /**
0380  * SoA member ROOT streamer read (column pointers).
0381  */
0382 // clang-format off
0383 #define _STREAMER_READ_SOA_DATA_MEMBER_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                \
0384   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0385       /* Scalar */                                                                                                     \
0386       memcpy(BOOST_PP_CAT(NAME, _), onfile.BOOST_PP_CAT(NAME, _), sizeof(CPP_TYPE));                                   \
0387       ,                                                                                                                \
0388       /* Column */                                                                                                     \
0389       memcpy(BOOST_PP_CAT(NAME, _), onfile.BOOST_PP_CAT(NAME, _), sizeof(CPP_TYPE) * onfile.elements_);                \
0390       ,                                                                                                                \
0391       /* Eigen column */                                                                                               \
0392       memcpy(BOOST_PP_CAT(NAME, _), onfile.BOOST_PP_CAT(NAME, _),                                                      \
0393         sizeof(CPP_TYPE::Scalar) * BOOST_PP_CAT(NAME, ElementsWithPadding_));                                          \
0394   )
0395 // clang-format on
0396 
0397 #define _STREAMER_READ_SOA_DATA_MEMBER(R, DATA, TYPE_NAME) \
0398   BOOST_PP_EXPAND(_STREAMER_READ_SOA_DATA_MEMBER_IMPL TYPE_NAME)
0399 
0400 /**
0401  * SoA class member declaration (column pointers).
0402  */
0403 // clang-format off
0404 #define _DECLARE_SOA_DATA_MEMBER_IMPL(VALUE_TYPE, CPP_TYPE, NAME)                                                      \
0405   _SWITCH_ON_TYPE(VALUE_TYPE,                                                                                          \
0406       /* Scalar */                                                                                                     \
0407       CPP_TYPE* BOOST_PP_CAT(NAME, _) EDM_REFLEX_SIZE(scalar_) = nullptr;                                              \
0408       ,                                                                                                                \
0409       /* Column */                                                                                                     \
0410       CPP_TYPE * BOOST_PP_CAT(NAME, _) EDM_REFLEX_SIZE(elements_) = nullptr;                                           \
0411       ,                                                                                                                \
0412       /* Eigen column */                                                                                               \
0413       size_type BOOST_PP_CAT(NAME, ElementsWithPadding_) = 0; /* For ROOT serialization */                             \
0414       CPP_TYPE::Scalar * BOOST_PP_CAT(NAME, _) EDM_REFLEX_SIZE(BOOST_PP_CAT(NAME, ElementsWithPadding_)) = nullptr;    \
0415       byte_size_type BOOST_PP_CAT(NAME, Stride_) = 0;                                                                  \
0416   )
0417 // clang-format on
0418 
0419 #define _DECLARE_SOA_DATA_MEMBER(R, DATA, TYPE_NAME) BOOST_PP_EXPAND(_DECLARE_SOA_DATA_MEMBER_IMPL TYPE_NAME)
0420 
0421 #ifdef DEBUG
0422 #define _DO_RANGECHECK true
0423 #else
0424 #define _DO_RANGECHECK false
0425 #endif
0426 
0427 /*
0428  * A macro defining a SoA layout (collection of scalars and columns of equal lengths)
0429  */
0430 // clang-format off
0431 #define GENERATE_SOA_LAYOUT(CLASS, ...)                                                                                \
0432   template <CMS_SOA_BYTE_SIZE_TYPE ALIGNMENT = cms::soa::CacheLineSize::defaultSize,                                   \
0433             bool ALIGNMENT_ENFORCEMENT = cms::soa::AlignmentEnforcement::relaxed>                                      \
0434   struct CLASS {                                                                                                       \
0435     /* these could be moved to an external type trait to free up the symbol names */                                   \
0436     using self_type = CLASS;                                                                                           \
0437     using AlignmentEnforcement = cms::soa::AlignmentEnforcement;                                                       \
0438                                                                                                                        \
0439     /* For CUDA applications, we align to the 128 bytes of the cache lines.                                            \
0440      * See https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#global-memory-3-0 this is still valid      \
0441      * up to compute capability 8.X.                                                                                   \
0442      */                                                                                                                \
0443     using size_type = cms::soa::size_type;                                                                             \
0444     using byte_size_type = cms::soa::byte_size_type;                                                                   \
0445     constexpr static byte_size_type defaultAlignment = 128;                                                            \
0446     constexpr static byte_size_type alignment = ALIGNMENT;                                                             \
0447     constexpr static bool alignmentEnforcement = ALIGNMENT_ENFORCEMENT;                                                \
0448     constexpr static byte_size_type conditionalAlignment =                                                             \
0449         alignmentEnforcement == cms::soa::AlignmentEnforcement::enforced ? alignment : 0;                              \
0450     /* Those typedefs avoid having commas in macros (which is problematic) */                                          \
0451     template <cms::soa::SoAColumnType COLUMN_TYPE, class C>                                                            \
0452     using SoAValueWithConf = cms::soa::SoAValue<COLUMN_TYPE, C, conditionalAlignment>;                                 \
0453                                                                                                                        \
0454     template <cms::soa::SoAColumnType COLUMN_TYPE, class C>                                                            \
0455     using SoAConstValueWithConf = cms::soa::SoAConstValue<COLUMN_TYPE, C, conditionalAlignment>;                       \
0456                                                                                                                        \
0457     template <CMS_SOA_BYTE_SIZE_TYPE VIEW_ALIGNMENT = cms::soa::CacheLineSize::defaultSize,                            \
0458             bool VIEW_ALIGNMENT_ENFORCEMENT = cms::soa::AlignmentEnforcement::relaxed,                                 \
0459             bool RESTRICT_QUALIFY = cms::soa::RestrictQualify::enabled,                                                \
0460             bool RANGE_CHECKING = cms::soa::RangeChecking::disabled>                                                   \
0461     struct ViewTemplateFreeParams;                                                                                     \
0462                                                                                                                        \
0463     /* dump the SoA internal structure */                                                                              \
0464     SOA_HOST_ONLY                                                                                                      \
0465     void soaToStreamInternal(std::ostream & _soa_impl_os) const {                                                      \
0466       _soa_impl_os << #CLASS "(" << elements_ << " elements, byte alignement= " << alignment << ", @"<< mem_ <<"): "   \
0467          << std::endl;                                                                                                 \
0468       _soa_impl_os << "  sizeof(" #CLASS "): " << sizeof(CLASS) << std::endl;                                          \
0469       byte_size_type _soa_impl_offset = 0;                                                                             \
0470       _ITERATE_ON_ALL(_DECLARE_SOA_STREAM_INFO, ~, __VA_ARGS__)                                                        \
0471       _soa_impl_os << "Final offset = " << _soa_impl_offset << " computeDataSize(...): " << computeDataSize(elements_) \
0472               << std::endl;                                                                                            \
0473       _soa_impl_os << std::endl;                                                                                       \
0474     }                                                                                                                  \
0475                                                                                                                        \
0476     /* Helper function used by caller to externally allocate the storage */                                            \
0477     static constexpr byte_size_type computeDataSize(size_type elements) {                                              \
0478       byte_size_type _soa_impl_ret = 0;                                                                                \
0479       _ITERATE_ON_ALL(_ACCUMULATE_SOA_ELEMENT, ~, __VA_ARGS__)                                                         \
0480       return _soa_impl_ret;                                                                                            \
0481     }                                                                                                                  \
0482                                                                                                                        \
0483     /**                                                                                                                \
0484      * Helper/friend class allowing SoA introspection.                                                                 \
0485      */                                                                                                                \
0486     struct Metadata {                                                                                                  \
0487       friend CLASS;                                                                                                    \
0488       SOA_HOST_DEVICE SOA_INLINE size_type size() const { return parent_.elements_; }                                  \
0489       SOA_HOST_DEVICE SOA_INLINE byte_size_type byteSize() const { return parent_.byteSize_; }                         \
0490       SOA_HOST_DEVICE SOA_INLINE byte_size_type alignment() const { return CLASS::alignment; }                         \
0491       SOA_HOST_DEVICE SOA_INLINE std::byte* data() { return parent_.mem_; }                                            \
0492       SOA_HOST_DEVICE SOA_INLINE const std::byte* data() const { return parent_.mem_; }                                \
0493       SOA_HOST_DEVICE SOA_INLINE std::byte* nextByte() const { return parent_.mem_ + parent_.byteSize_; }              \
0494       SOA_HOST_DEVICE SOA_INLINE CLASS cloneToNewAddress(std::byte* _soa_impl_addr) const {                            \
0495         return CLASS(_soa_impl_addr, parent_.elements_);                                                               \
0496       }                                                                                                                \
0497                                                                                                                        \
0498       _ITERATE_ON_ALL(_DEFINE_METADATA_MEMBERS, ~, __VA_ARGS__)                                                        \
0499                                                                                                                        \
0500       struct value_element {                                                                                           \
0501         SOA_HOST_DEVICE SOA_INLINE value_element                                                                       \
0502           BOOST_PP_IF(                                                                                                 \
0503             BOOST_PP_SEQ_SIZE(_ITERATE_ON_ALL(_VALUE_ELEMENT_CTOR_ARGS, ~, __VA_ARGS__) ),                             \
0504             (_ITERATE_ON_ALL_COMMA(_VALUE_ELEMENT_CTOR_ARGS, ~, __VA_ARGS__)):,                                        \
0505             ())                                                                                                        \
0506           BOOST_PP_TUPLE_ENUM(BOOST_PP_IF(                                                                             \
0507             BOOST_PP_SEQ_SIZE(_ITERATE_ON_ALL(_VALUE_ELEMENT_CTOR_ARGS, ~, __VA_ARGS__)),                              \
0508             BOOST_PP_SEQ_TO_TUPLE(_ITERATE_ON_ALL(_VALUE_ELEMENT_INITIALIZERS, ~, __VA_ARGS__)),                       \
0509             ()                                                                                                         \
0510           )                                                                                                            \
0511         )                                                                                                              \
0512         {}                                                                                                             \
0513                                                                                                                        \
0514         _ITERATE_ON_ALL(_DEFINE_VALUE_ELEMENT_MEMBERS, ~, __VA_ARGS__)                                                 \
0515       };                                                                                                               \
0516                                                                                                                        \
0517       Metadata& operator=(const Metadata&) = delete;                                                                   \
0518       Metadata(const Metadata&) = delete;                                                                              \
0519                                                                                                                        \
0520     private:                                                                                                           \
0521       SOA_HOST_DEVICE SOA_INLINE Metadata(const CLASS& _soa_impl_parent) : parent_(_soa_impl_parent) {}                \
0522       const CLASS& parent_;                                                                                            \
0523       using ParentClass = CLASS;                                                                                       \
0524     };                                                                                                                 \
0525                                                                                                                        \
0526     friend Metadata;                                                                                                   \
0527                                                                                                                        \
0528     SOA_HOST_DEVICE SOA_INLINE const Metadata metadata() const { return Metadata(*this); }                             \
0529     SOA_HOST_DEVICE SOA_INLINE Metadata metadata() { return Metadata(*this); }                                         \
0530                                                                                                                        \
0531     /* Generate the ConstView template */                                                                              \
0532     _GENERATE_SOA_TRIVIAL_CONST_VIEW(CLASS,                                                                            \
0533                     SOA_VIEW_LAYOUT_LIST(                                                                              \
0534                         SOA_VIEW_LAYOUT(BOOST_PP_CAT(CLASS, _parametrized) , BOOST_PP_CAT(instance_, CLASS))),         \
0535                     SOA_VIEW_VALUE_LIST(_ITERATE_ON_ALL_COMMA(                                                         \
0536                     _VIEW_FIELD_FROM_LAYOUT, BOOST_PP_CAT(instance_, CLASS), __VA_ARGS__)))                            \
0537                                                                                                                        \
0538     template <bool RESTRICT_QUALIFY, bool RANGE_CHECKING>                                                              \
0539     using ConstViewTemplate = ConstViewTemplateFreeParams<ALIGNMENT, ALIGNMENT_ENFORCEMENT, RESTRICT_QUALIFY,          \
0540       RANGE_CHECKING>;                                                                                                 \
0541                                                                                                                        \
0542     using ConstView = ConstViewTemplate<cms::soa::RestrictQualify::enabled, cms::soa::RangeChecking::disabled>;        \
0543                                                                                                                        \
0544     /* Generate the mutable View template */                                                                           \
0545     _GENERATE_SOA_TRIVIAL_VIEW(CLASS,                                                                                  \
0546                     SOA_VIEW_LAYOUT_LIST(                                                                              \
0547                         SOA_VIEW_LAYOUT(BOOST_PP_CAT(CLASS, _parametrized), BOOST_PP_CAT(instance_, CLASS))),          \
0548                     SOA_VIEW_VALUE_LIST(_ITERATE_ON_ALL_COMMA(                                                         \
0549                     _VIEW_FIELD_FROM_LAYOUT, BOOST_PP_CAT(instance_, CLASS), __VA_ARGS__)),                            \
0550                     __VA_ARGS__)                                                                                       \
0551                                                                                                                        \
0552     template <bool RESTRICT_QUALIFY, bool RANGE_CHECKING>                                                              \
0553     using ViewTemplate = ViewTemplateFreeParams<ALIGNMENT, ALIGNMENT_ENFORCEMENT, RESTRICT_QUALIFY, RANGE_CHECKING>;   \
0554                                                                                                                        \
0555     using View = ViewTemplate<cms::soa::RestrictQualify::enabled, cms::soa::RangeChecking::disabled>;                  \
0556                                                                                                                        \
0557     /* Trivial constuctor */                                                                                           \
0558     CLASS()                                                                                                            \
0559         : mem_(nullptr),                                                                                               \
0560           elements_(0),                                                                                                \
0561           byteSize_(0),                                                                                                \
0562           _ITERATE_ON_ALL_COMMA(_DECLARE_MEMBER_TRIVIAL_CONSTRUCTION, ~, __VA_ARGS__) {}                               \
0563                                                                                                                        \
0564     /* Constructor relying on user provided storage (implementation shared with ROOT streamer) */                      \
0565     SOA_HOST_ONLY CLASS(std::byte* mem, size_type elements) : mem_(mem), elements_(elements), byteSize_(0) {           \
0566       organizeColumnsFromBuffer();                                                                                     \
0567     }                                                                                                                  \
0568                                                                                                                        \
0569     /* Explicit copy constructor and assignment operator */                                                            \
0570     SOA_HOST_ONLY CLASS(CLASS const& _soa_impl_other)                                                                  \
0571         : mem_(_soa_impl_other.mem_),                                                                                  \
0572           elements_(_soa_impl_other.elements_),                                                                        \
0573           byteSize_(_soa_impl_other.byteSize_),                                                                        \
0574           _ITERATE_ON_ALL_COMMA(_DECLARE_MEMBER_COPY_CONSTRUCTION, ~, __VA_ARGS__) {}                                  \
0575                                                                                                                        \
0576     SOA_HOST_ONLY CLASS& operator=(CLASS const& _soa_impl_other) {                                                     \
0577         mem_ = _soa_impl_other.mem_;                                                                                   \
0578         elements_ = _soa_impl_other.elements_;                                                                         \
0579         byteSize_ = _soa_impl_other.byteSize_;                                                                         \
0580         _ITERATE_ON_ALL(_DECLARE_MEMBER_ASSIGNMENT, ~, __VA_ARGS__)                                                    \
0581         return *this;                                                                                                  \
0582     }                                                                                                                  \
0583                                                                                                                        \
0584     /* ROOT read streamer */                                                                                           \
0585     template <typename T>                                                                                              \
0586     void ROOTReadStreamer(T & onfile) {                                                                                \
0587       _ITERATE_ON_ALL(_STREAMER_READ_SOA_DATA_MEMBER, ~, __VA_ARGS__)                                                  \
0588     }                                                                                                                  \
0589                                                                                                                        \
0590     /* ROOT allocation cleanup */                                                                                      \
0591     void ROOTStreamerCleaner() {                                                                                       \
0592       /* This function should only be called from the PortableCollection ROOT streamer */                              \
0593       _ITERATE_ON_ALL(_ROOT_FREE_SOA_COLUMN_OR_SCALAR, ~, __VA_ARGS__)                                                 \
0594     }                                                                                                                  \
0595                                                                                                                        \
0596     /* Dump the SoA internal structure */                                                                              \
0597     template <typename T>                                                                                              \
0598     SOA_HOST_ONLY friend void dump();                                                                                  \
0599                                                                                                                        \
0600   private:                                                                                                             \
0601     /* Helper method for the user provided storage constructor and ROOT streamer */                                    \
0602     void organizeColumnsFromBuffer() {                                                                                 \
0603       if constexpr (alignmentEnforcement == cms::soa::AlignmentEnforcement::enforced)                                  \
0604         if (reinterpret_cast<intptr_t>(mem_) % alignment)                                                              \
0605           throw std::runtime_error("In " #CLASS "::" #CLASS ": misaligned buffer");                                    \
0606       auto _soa_impl_curMem = mem_;                                                                                    \
0607       _ITERATE_ON_ALL(_ASSIGN_SOA_COLUMN_OR_SCALAR, ~, __VA_ARGS__)                                                    \
0608       /* Sanity check: we should have reached the computed size, only on host code */                                  \
0609       byteSize_ = computeDataSize(elements_);                                                                          \
0610       if (mem_ + byteSize_ != _soa_impl_curMem)                                                                        \
0611         throw std::runtime_error("In " #CLASS "::" #CLASS ": unexpected end pointer.");                                \
0612     }                                                                                                                  \
0613                                                                                                                        \
0614     /* Data members */                                                                                                 \
0615     std::byte* mem_ EDM_REFLEX_TRANSIENT;                                                                              \
0616     size_type elements_;                                                                                               \
0617     size_type const scalar_ = 1;                                                                                       \
0618     byte_size_type byteSize_ EDM_REFLEX_TRANSIENT;                                                                     \
0619     _ITERATE_ON_ALL(_DECLARE_SOA_DATA_MEMBER, ~, __VA_ARGS__)                                                          \
0620     /* Making the code conditional is problematic in macros as the commas will interfere with parameter lisings     */ \
0621     /* So instead we make the code unconditional with paceholder names which are protected by a private protection. */ \
0622     /* This will be handled later as we handle the integration of the view as a subclass of the layout.             */ \
0623                                                                                                                        \
0624   };
0625 // clang-format on
0626 
0627 #endif  // DataFormats_SoATemplate_interface_SoALayout_h