Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-05-04 22:50:31

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