File indexing completed on 2024-04-06 12:13:09
0001 #ifndef FWCore_SOA_Table_h
0002 #define FWCore_SOA_Table_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 #include <memory>
0118 #include <tuple>
0119 #include <array>
0120
0121
0122 #include "FWCore/SOA/interface/TableItr.h"
0123 #include "FWCore/SOA/interface/tablehelpers.h"
0124 #include "FWCore/SOA/interface/ColumnFillers.h"
0125 #include "FWCore/SOA/interface/ColumnValues.h"
0126 #include "FWCore/SOA/interface/RowView.h"
0127
0128
0129 #include "FWCore/SOA/interface/TableExaminer.h"
0130
0131
0132
0133 namespace edm {
0134 namespace soa {
0135
0136 template <typename... Args>
0137 class Table {
0138 public:
0139 static constexpr const unsigned int kNColumns = sizeof...(Args);
0140 using Layout = std::tuple<Args...>;
0141 using const_iterator = ConstTableItr<Args...>;
0142 using iterator = TableItr<Args...>;
0143
0144 template <typename T, typename... CArgs>
0145 Table(T const& iContainer, CArgs... iArgs) : m_size(iContainer.size()) {
0146 if constexpr (sizeof...(CArgs) == 0) {
0147 CtrFillerFromAOS::fill(m_values, iContainer);
0148 } else {
0149 CtrFillerFromContainers::fill(m_values, iContainer, std::forward<CArgs>(iArgs)...);
0150 }
0151 }
0152
0153 template <typename T, typename... CArgs>
0154 Table(T const& iContainer, ColumnFillers<CArgs...> iFiller) {
0155 m_size = iContainer.size();
0156 CtrFillerFromAOS::fillUsingFiller(iFiller, m_values, iContainer);
0157 }
0158
0159 Table(Table<Args...> const& iOther) : m_size(iOther.m_size), m_values{{nullptr}} {
0160 copyFromToWithResizeAll(m_size, iOther.m_values, m_values, std::make_index_sequence<sizeof...(Args)>{});
0161 }
0162
0163 Table(Table<Args...>&& iOther) : m_size(0), m_values{{nullptr}} {
0164 std::swap(m_size, iOther.m_size);
0165 std::swap(m_values, iOther.m_values);
0166 }
0167
0168 Table() : m_size(0) {}
0169
0170 ~Table() { dtr<0>(m_values); }
0171
0172 Table<Args...>& operator=(Table<Args...>&& iOther) {
0173 Table<Args...> cp(std::move(iOther));
0174 std::swap(m_size, cp.m_size);
0175 std::swap(m_values, cp.m_values);
0176 return *this;
0177 }
0178 Table<Args...>& operator=(Table<Args...> const& iOther) { return operator=(Table<Args...>(iOther)); }
0179
0180 unsigned int size() const { return m_size; }
0181
0182 void resize(unsigned int iNewSize) {
0183 if (m_size == iNewSize) {
0184 return;
0185 }
0186 resizeFromTo<0>(m_size, iNewSize, m_values);
0187 if (m_size < iNewSize) {
0188
0189 resetStartingAt<0>(m_size, iNewSize, m_values);
0190 }
0191 m_size = iNewSize;
0192 }
0193
0194 template <typename U>
0195 typename U::type const& get(size_t iRow) const {
0196 return *(static_cast<typename U::type const*>(columnAddress<U>()) + iRow);
0197 }
0198 template <typename U>
0199 typename U::type& get(size_t iRow) {
0200 return *(static_cast<typename U::type*>(columnAddress<U>()) + iRow);
0201 }
0202
0203 template <typename U>
0204 ColumnValues<typename U::type> column() const {
0205 return ColumnValues<typename U::type>{static_cast<typename U::type*>(columnAddress<U>()), m_size};
0206 }
0207 template <typename U>
0208 MutableColumnValues<typename U::type> column() {
0209 return MutableColumnValues<typename U::type>{static_cast<typename U::type*>(columnAddress<U>()), m_size};
0210 }
0211
0212 RowView<Args...> row(size_t iRow) const { return *(begin() + iRow); }
0213 MutableRowView<Args...> row(size_t iRow) { return *(begin() + iRow); }
0214
0215 const_iterator begin() const {
0216 std::array<void const*, sizeof...(Args)> t;
0217 for (size_t i = 0; i < t.size(); ++i) {
0218 t[i] = m_values[i];
0219 }
0220 return const_iterator{t};
0221 }
0222 const_iterator end() const {
0223 std::array<void const*, sizeof...(Args)> t;
0224 for (size_t i = 0; i < t.size(); ++i) {
0225 t[i] = m_values[i];
0226 }
0227 return const_iterator{t, size()};
0228 }
0229
0230 iterator begin() { return iterator{m_values}; }
0231 iterator end() { return iterator{m_values, size()}; }
0232
0233 template <typename U>
0234 void const* columnAddressWorkaround(U const*) const {
0235 return columnAddress<U>();
0236 }
0237
0238 void const* columnAddressByIndex(unsigned int iIndex) const { return m_values[iIndex]; }
0239
0240 private:
0241
0242 unsigned int m_size = 0;
0243 std::array<void*, sizeof...(Args)> m_values = {{nullptr}};
0244
0245 template <typename U>
0246 void const* columnAddress() const {
0247 return m_values[impl::GetIndex<0, U, Layout>::index];
0248 }
0249
0250 template <typename U>
0251 void* columnAddress() {
0252 return m_values[impl::GetIndex<0, U, Layout>::index];
0253 }
0254
0255
0256 template <int I>
0257 static void dtr(std::array<void*, sizeof...(Args)>& iArray) {
0258 if constexpr (I < sizeof...(Args)) {
0259 using Type = typename std::tuple_element<I, Layout>::type::type;
0260 delete[] static_cast<Type*>(iArray[I]);
0261 dtr<I + 1>(iArray);
0262 }
0263 }
0264
0265
0266 struct CtrFillerFromContainers {
0267 template <typename T, typename... U>
0268 static size_t fill(std::array<void*, sizeof...(Args)>& oValues, T const& iContainer, U... iArgs) {
0269 static_assert(sizeof...(Args) == sizeof...(U) + 1, "Wrong number of arguments passed to Table constructor");
0270 ctrFiller<0>(oValues, iContainer.size(), iContainer, std::forward<U>(iArgs)...);
0271 return iContainer.size();
0272 }
0273
0274 private:
0275 template <int I, typename T, typename... U>
0276 static void ctrFiller(std::array<void*, sizeof...(Args)>& oValues, size_t iSize, T const& iContainer, U... iU) {
0277 assert(iContainer.size() == iSize);
0278 using Type = typename std::tuple_element<I, Layout>::type::type;
0279 Type* temp = new Type[iSize];
0280 unsigned int index = 0;
0281 for (auto const& v : iContainer) {
0282 temp[index] = v;
0283 ++index;
0284 }
0285 oValues[I] = temp;
0286
0287 ctrFiller<I + 1>(oValues, iSize, std::forward<U>(iU)...);
0288 }
0289
0290 template <int I>
0291 static void ctrFiller(std::array<void*, sizeof...(Args)>&, size_t) {}
0292 };
0293
0294
0295 struct CtrFillerFromAOS {
0296 template <typename T>
0297 static size_t fill(std::array<void*, sizeof...(Args)>& oValues, T const& iContainer) {
0298 presize<0>(oValues, iContainer.size());
0299 unsigned index = 0;
0300 for (auto&& item : iContainer) {
0301 fillElement<0>(item, index, oValues);
0302 ++index;
0303 }
0304 return iContainer.size();
0305 }
0306
0307 template <typename T, typename F>
0308 static size_t fillUsingFiller(F& iFiller, std::array<void*, sizeof...(Args)>& oValues, T const& iContainer) {
0309 presize<0>(oValues, iContainer.size());
0310 unsigned index = 0;
0311 for (auto&& item : iContainer) {
0312 fillElementUsingFiller<0>(iFiller, item, index, oValues);
0313 ++index;
0314 }
0315 return iContainer.size();
0316 }
0317
0318 private:
0319 template <int I>
0320 static void presize(std::array<void*, sizeof...(Args)>& oValues, size_t iSize) {
0321 if constexpr (I < sizeof...(Args)) {
0322 using Layout = std::tuple<Args...>;
0323 using Type = typename std::tuple_element<I, Layout>::type::type;
0324 oValues[I] = new Type[iSize];
0325 presize<I + 1>(oValues, iSize);
0326 }
0327 }
0328
0329 template <int I, typename E>
0330 static void fillElement(E const& iItem, size_t iIndex, std::array<void*, sizeof...(Args)>& oValues) {
0331 if constexpr (I < sizeof...(Args)) {
0332 using Layout = std::tuple<Args...>;
0333 using ColumnType = typename std::tuple_element<I, Layout>::type;
0334 using Type = typename ColumnType::type;
0335 Type* pElement = static_cast<Type*>(oValues[I]) + iIndex;
0336 *pElement = value_for_column(iItem, static_cast<ColumnType*>(nullptr));
0337 fillElement<I + 1>(iItem, iIndex, oValues);
0338 }
0339 }
0340
0341 template <int I, typename E, typename F>
0342 static void fillElementUsingFiller(F& iFiller,
0343 E const& iItem,
0344 size_t iIndex,
0345 std::array<void*, sizeof...(Args)>& oValues) {
0346 if constexpr (I < sizeof...(Args)) {
0347 using Layout = std::tuple<Args...>;
0348 using ColumnType = typename std::tuple_element<I, Layout>::type;
0349 using Type = typename ColumnType::type;
0350 Type* pElement = static_cast<Type*>(oValues[I]) + iIndex;
0351 *pElement = iFiller.value(iItem, static_cast<ColumnType*>(nullptr));
0352 fillElementUsingFiller<I + 1>(iFiller, iItem, iIndex, oValues);
0353 }
0354 }
0355 };
0356
0357 template <size_t... I>
0358 static void copyFromToWithResizeAll(size_t iNElements,
0359 std::array<void*, sizeof...(Args)> const& iFrom,
0360 std::array<void*, sizeof...(Args)>& oTo,
0361 std::index_sequence<I...>) {
0362 (copyFromToWithResize<I>(iNElements, iFrom, oTo), ...);
0363 }
0364
0365 template <int I>
0366 static void copyFromToWithResize(size_t iNElements,
0367 std::array<void*, sizeof...(Args)> const& iFrom,
0368 std::array<void*, sizeof...(Args)>& oTo) {
0369 using Layout = std::tuple<Args...>;
0370 using Type = typename std::tuple_element<I, Layout>::type::type;
0371 Type* oldPtr = static_cast<Type*>(oTo[I]);
0372 Type* ptr = new Type[iNElements];
0373 oTo[I] = ptr;
0374 std::copy(static_cast<Type const*>(iFrom[I]), static_cast<Type const*>(iFrom[I]) + iNElements, ptr);
0375 delete[] oldPtr;
0376 }
0377
0378 template <int I>
0379 static void resizeFromTo(size_t iOldSize, size_t iNewSize, std::array<void*, sizeof...(Args)>& ioArray) {
0380 if constexpr (I < sizeof...(Args)) {
0381 using Layout = std::tuple<Args...>;
0382 using Type = typename std::tuple_element<I, Layout>::type::type;
0383 Type* oldPtr = static_cast<Type*>(ioArray[I]);
0384 auto ptr = new Type[iNewSize];
0385 auto nToCopy = std::min(iOldSize, iNewSize);
0386 std::copy(static_cast<Type const*>(ioArray[I]), static_cast<Type const*>(ioArray[I]) + nToCopy, ptr);
0387 resizeFromTo<I + 1>(iOldSize, iNewSize, ioArray);
0388
0389 delete[] oldPtr;
0390 ioArray[I] = ptr;
0391 }
0392 }
0393
0394 template <int I>
0395 static void resetStartingAt(size_t iStartIndex, size_t iEndIndex, std::array<void*, sizeof...(Args)>& ioArray) {
0396 if constexpr (I < sizeof...(Args)) {
0397 using Layout = std::tuple<Args...>;
0398 using Type = typename std::tuple_element<I, Layout>::type::type;
0399 auto ptr = static_cast<Type*>(ioArray[I]);
0400 auto temp = Type{};
0401 std::fill(ptr + iStartIndex, ptr + iEndIndex, temp);
0402 resetStartingAt<I + 1>(iStartIndex, iEndIndex, ioArray);
0403 }
0404 }
0405 };
0406
0407
0408 template <typename T1, typename T2>
0409 struct AddColumns;
0410 template <typename... T1, typename... T2>
0411 struct AddColumns<Table<T1...>, std::tuple<T2...>> {
0412 using type = Table<T1..., T2...>;
0413 };
0414
0415 template <typename T1, typename T2>
0416 using AddColumns_t = typename AddColumns<T1, T2>::type;
0417
0418 namespace impl {
0419 template <typename LHS, typename E, typename RHS>
0420 struct RemoveColumnCheck;
0421 template <typename LHS, typename E, typename T, typename... U>
0422 struct RemoveColumnCheck<LHS, E, std::tuple<T, U...>> {
0423 using type = typename std::conditional<
0424 std::is_same<E, T>::value,
0425 typename AddColumns<LHS, std::tuple<U...>>::type,
0426 typename RemoveColumnCheck<typename AddColumns<LHS, std::tuple<T>>::type, E, std::tuple<U...>>::type>::type;
0427 };
0428
0429 template <typename LHS, typename E>
0430 struct RemoveColumnCheck<LHS, E, std::tuple<>> {
0431 using type = LHS;
0432 };
0433 }
0434
0435 template <typename TABLE, typename E>
0436 struct RemoveColumn {
0437 using type = typename impl::RemoveColumnCheck<Table<>, E, typename TABLE::Layout>::type;
0438 };
0439
0440 template <typename TABLE, typename E>
0441 using RemoveColumn_t = typename RemoveColumn<TABLE, E>::type;
0442
0443
0444 template <typename T>
0445 struct MakeTableExaminer;
0446
0447 template <typename... Args>
0448 struct MakeTableExaminer<Table<Args...>> {
0449 static std::unique_ptr<TableExaminerBase> make(const Table<Args...>* iTable) {
0450 return std::make_unique<TableExaminer<Table<Args...>>>(iTable);
0451 }
0452 };
0453 }
0454 }
0455 #endif