Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-01-13 00:12:03

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