Skip to content

Commit b911554

Browse files
authored
Merge pull request #47625 from leobeltra/SOA_METHODS
Added macro for generating element-wise methods to the SoAs
2 parents 4e60b9e + 9415787 commit b911554

File tree

6 files changed

+371
-55
lines changed

6 files changed

+371
-55
lines changed

DataFormats/SoATemplate/README.md

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ function of a `View` or `ConstView`. Every object contains the address of the fi
6262
of elements per column, and the stride for the Eigen columns. These are used to validate the columns size at run time
6363
and to build a generic `View` as described in [View](#view).
6464

65+
## Customized methods
66+
67+
It is possible to generate methods inside the `element` and `const_element` nested structs using the `SOA_ELEMENT_METHODS` and `SOA_CONST_ELEMENT_METHODS` macros. Each of these macros can be called only once, and can define multiple methods. [An example is showed below.](#examples)
68+
6569
## ROOT serialization and de-serialization
6670

6771
Layouts can be serialized and de-serialized with ROOT. In order to generate the ROOT dictionary, separate
@@ -139,6 +143,40 @@ using SoA1Layout = SoA1LayoutTemplate<>;
139143
using SoA1LayoutAligned = SoA1LayoutTemplate<cms::soa::CacheLineSize::defaultSize, cms::soa::AlignmentEnforcement::enforced>;
140144
```
141145

146+
It is possible to declare methods that operate on the SoA elements:
147+
148+
```C++
149+
#include "DataFormats/SoALayout.h"
150+
151+
GENERATE_SOA_LAYOUT(SoATemplate,
152+
SOA_COLUMN(double, x),
153+
SOA_COLUMN(double, y),
154+
SOA_COLUMN(double, z),
155+
156+
// methods operating on const_element
157+
SOA_CONST_METHODS(
158+
auto norm() const {
159+
return sqrt(x()*x() + y()+y() + z()*z());
160+
}
161+
),
162+
163+
// methods operating on element
164+
SOA_METHODS(
165+
void scale(float arg) {
166+
x() *= arg;
167+
y() *= arg;
168+
z() *= arg;
169+
}
170+
),
171+
172+
SOA_SCALAR(int, detectorType)
173+
);
174+
175+
using SoA = SoATemplate<>;
176+
using SoAView = SoA::View;
177+
using SoAConstView = SoA::ConstView;
178+
```
179+
142180
The buffer of the proper size is allocated, and the layout is populated with:
143181

144182
```C++
@@ -212,8 +250,6 @@ template<size_t ALIGNMENT = cms::soa::CacheLineSize::defaultSize,
212250
struct SoA1Layout::ConstViewTemplateFreeParams;
213251
```
214252
215-
216-
217253
## Current status and further improvements
218254
219255
### Available features

DataFormats/SoATemplate/interface/SoACommon.h

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@
5252
#define _VALUE_TYPE_SCALAR 0
5353
#define _VALUE_TYPE_COLUMN 1
5454
#define _VALUE_TYPE_EIGEN_COLUMN 2
55+
#define _VALUE_TYPE_METHOD 3
56+
#define _VALUE_TYPE_CONST_METHOD 4
57+
58+
/* declare the value of last valid column */
59+
#define _VALUE_LAST_COLUMN_TYPE _VALUE_TYPE_EIGEN_COLUMN
60+
61+
/* declare a macro useful for passing a valid but not used value*/
62+
#define _VALUE_TYPE_UNUSED BOOST_PP_LIMIT_MAG
5563

5664
/* The size type need to be "hardcoded" in the template parameters for classes serialized by ROOT */
5765
/* In practice, using a typedef as a template parameter to the Layout or its ViewTemplateFreeParams member
@@ -571,9 +579,38 @@ namespace cms::soa {
571579

572580
} // namespace cms::soa
573581

574-
#define SOA_SCALAR(TYPE, NAME) (_VALUE_TYPE_SCALAR, TYPE, NAME)
575-
#define SOA_COLUMN(TYPE, NAME) (_VALUE_TYPE_COLUMN, TYPE, NAME)
576-
#define SOA_EIGEN_COLUMN(TYPE, NAME) (_VALUE_TYPE_EIGEN_COLUMN, TYPE, NAME)
582+
#define SOA_SCALAR(TYPE, NAME) (_VALUE_TYPE_SCALAR, TYPE, NAME, ~)
583+
#define SOA_COLUMN(TYPE, NAME) (_VALUE_TYPE_COLUMN, TYPE, NAME, ~)
584+
#define SOA_EIGEN_COLUMN(TYPE, NAME) (_VALUE_TYPE_EIGEN_COLUMN, TYPE, NAME, ~)
585+
#define SOA_ELEMENT_METHODS(...) (_VALUE_TYPE_METHOD, _, _, (__VA_ARGS__))
586+
#define SOA_CONST_ELEMENT_METHODS(...) (_VALUE_TYPE_CONST_METHOD, _, _, (__VA_ARGS__))
587+
588+
/* Macro generating customized methods for the element */
589+
#define GENERATE_METHODS(R, DATA, FIELD) \
590+
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_ELEM(0, FIELD), _VALUE_TYPE_METHOD), \
591+
BOOST_PP_TUPLE_ELEM(3, FIELD), \
592+
BOOST_PP_EMPTY())
593+
594+
/* Macro generating customized methods for the const element*/
595+
#define GENERATE_CONST_METHODS(R, DATA, FIELD) \
596+
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_ELEM(0, FIELD), _VALUE_TYPE_CONST_METHOD), \
597+
BOOST_PP_TUPLE_ELEM(3, FIELD), \
598+
BOOST_PP_EMPTY())
599+
600+
/* Preprocessing loop for managing functions generation: only macros containing valid content are expanded */
601+
#define ENUM_FOR_PRED(R, STATE) BOOST_PP_LESS(BOOST_PP_TUPLE_ELEM(0, STATE), BOOST_PP_TUPLE_ELEM(1, STATE))
602+
603+
#define ENUM_FOR_OP(R, STATE) \
604+
(BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(0, STATE)), BOOST_PP_TUPLE_ELEM(1, STATE), BOOST_PP_TUPLE_ELEM(2, STATE))
605+
606+
#define ENUM_FOR_MACRO(R, STATE) \
607+
BOOST_PP_TUPLE_ENUM(BOOST_PP_SEQ_ELEM(BOOST_PP_TUPLE_ELEM(0, STATE), BOOST_PP_TUPLE_ELEM(2, STATE)))
608+
609+
#define ENUM_IF_VALID(...) \
610+
BOOST_PP_FOR((0, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)), \
611+
ENUM_FOR_PRED, \
612+
ENUM_FOR_OP, \
613+
ENUM_FOR_MACRO)
577614

578615
/* Iterate on the macro MACRO and return the result as a comma separated list, converting
579616
the boost sequence into tuples and then into list */

0 commit comments

Comments
 (0)