1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#include <memory>
#include <tuple>
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include "DataFormats/SoATemplate/interface/SoALayout.h"
// clang-format off
GENERATE_SOA_LAYOUT(SimpleLayoutTemplate,
SOA_COLUMN(float, x),
SOA_COLUMN(float, y),
SOA_COLUMN(float, z),
SOA_COLUMN(float, t))
// clang-format on
using SimpleLayout = SimpleLayoutTemplate<>;
TEST_CASE("SoATemplate") {
// number of elements
const std::size_t slSize = 10;
// size in bytes
const std::size_t slBufferSize = SimpleLayout::computeDataSize(slSize);
// memory buffer aligned according to the layout requirements
std::unique_ptr<std::byte, decltype(std::free) *> slBuffer{
reinterpret_cast<std::byte *>(aligned_alloc(SimpleLayout::alignment, slBufferSize)), std::free};
// SoA layout
SimpleLayout sl{slBuffer.get(), slSize};
SECTION("Row wide copies, row") {
SimpleLayout::View slv{sl};
SimpleLayout::ConstView slcv{sl};
auto slv0 = slv[0];
slv0.x() = 1;
slv0.y() = 2;
slv0.z() = 3;
slv0.t() = 5;
// Fill up
for (SimpleLayout::View::size_type i = 1; i < slv.metadata().size(); ++i) {
auto slvi = slv[i];
slvi = slv[i - 1];
auto slvix = slvi.x();
slvi.x() += slvi.y();
slvi.y() += slvi.z();
slvi.z() += slvi.t();
slvi.t() += slvix;
}
// Verification and const view access
float x = 1, y = 2, z = 3, t = 5;
for (SimpleLayout::View::size_type i = 0; i < slv.metadata().size(); ++i) {
auto slvi = slv[i];
auto slcvi = slcv[i];
REQUIRE(slvi.x() == x);
REQUIRE(slvi.y() == y);
REQUIRE(slvi.z() == z);
REQUIRE(slvi.t() == t);
REQUIRE(slcvi.x() == x);
REQUIRE(slcvi.y() == y);
REQUIRE(slcvi.z() == z);
REQUIRE(slcvi.t() == t);
auto tx = x;
x += y;
y += z;
z += t;
t += tx;
}
}
SECTION("Row initializer, const view access, restrict disabling") {
// With two views, we are creating (artificially) aliasing and should warn the compiler by turning restrict qualifiers off.
using View = SimpleLayout::ViewTemplate<cms::soa::RestrictQualify::disabled, cms::soa::RangeChecking::Default>;
using ConstView =
SimpleLayout::ConstViewTemplate<cms::soa::RestrictQualify::disabled, cms::soa::RangeChecking::Default>;
View slv{sl};
ConstView slcv{sl};
auto slv0 = slv[0];
slv0 = {7, 11, 13, 17};
// Fill up
for (SimpleLayout::View::size_type i = 1; i < slv.metadata().size(); ++i) {
auto slvi = slv[i];
// Copy the const view
slvi = slcv[i - 1];
auto slvix = slvi.x();
slvi.x() += slvi.y();
slvi.y() += slvi.z();
slvi.z() += slvi.t();
slvi.t() += slvix;
}
// Verification and const view access
auto [x, y, z, t] = std::make_tuple(7.0, 11.0, 13.0, 17.0);
for (SimpleLayout::View::size_type i = 0; i < slv.metadata().size(); ++i) {
auto slvi = slv[i];
auto slcvi = slcv[i];
REQUIRE(slvi.x() == x);
REQUIRE(slvi.y() == y);
REQUIRE(slvi.z() == z);
REQUIRE(slvi.t() == t);
REQUIRE(slcvi.x() == x);
REQUIRE(slcvi.y() == y);
REQUIRE(slcvi.z() == z);
REQUIRE(slcvi.t() == t);
auto tx = x;
x += y;
y += z;
z += t;
t += tx;
}
}
SECTION("Range checking View") {
// Enable range checking
using View = SimpleLayout::ViewTemplate<cms::soa::RestrictQualify::Default, cms::soa::RangeChecking::enabled>;
View slv{sl};
int underflow = -1;
int overflow = slv.metadata().size();
// Check for under-and overflow in the row accessor
REQUIRE_THROWS_AS(slv[underflow], std::out_of_range);
REQUIRE_THROWS_AS(slv[overflow], std::out_of_range);
// Check for under-and overflow in the element accessors
REQUIRE_THROWS_AS(slv.x(underflow), std::out_of_range);
REQUIRE_THROWS_AS(slv.x(overflow), std::out_of_range);
}
SECTION("Range checking ConstView") {
// Enable range checking
using ConstView =
SimpleLayout::ConstViewTemplate<cms::soa::RestrictQualify::Default, cms::soa::RangeChecking::enabled>;
ConstView slcv{sl};
int underflow = -1;
int overflow = slcv.metadata().size();
// Check for under-and overflow in the row accessor
REQUIRE_THROWS_AS(slcv[underflow], std::out_of_range);
REQUIRE_THROWS_AS(slcv[overflow], std::out_of_range);
// Check for under-and overflow in the element accessors
REQUIRE_THROWS_AS(slcv.x(underflow), std::out_of_range);
REQUIRE_THROWS_AS(slcv.x(overflow), std::out_of_range);
}
}
|