Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-08-23 22:39:53

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