Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RVariation.hxx
Go to the documentation of this file.
1// Author: Enrico Guiraud, CERN 10/2021
2
3/*************************************************************************
4 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11#ifndef ROOT_RDF_RVARIATION
12#define ROOT_RDF_RVARIATION
13
14#include "Utils.hxx" // IsRVec
15#include "ColumnReaderUtils.hxx"
16#include "RColumnReaderBase.hxx"
17#include "RLoopManager.hxx"
18#include "RVariationBase.hxx"
19
20#include <ROOT/RStringView.hxx>
21#include <ROOT/TypeTraits.hxx>
22#include <Rtypes.h> // R__CLING_PTRCHECK, Long64_t
23
24#include <array>
25#include <deque>
26#include <map>
27#include <string>
28#include <type_traits> // std::is_same, std::conditional_t
29#include <utility> // std::index_sequence
30#include <vector>
31
32class TTreeReader;
33
34namespace ROOT {
35
36namespace RDF {
37class RDataSource;
38}
39
40namespace Internal {
41namespace RDF {
42
43using namespace ROOT::TypeTraits;
44
45/// @name Helper functions for the case of a single column being varied.
46///@{
47template <typename T>
48bool ResultsSizeEq(const T &results, std::size_t expected, std::size_t nColumns, std::true_type /*isSingleColumn*/)
49{
50 assert(nColumns == 1);
51 (void)nColumns;
52
53 return results.size() == expected;
54}
55
56template <typename T>
57std::size_t GetNVariations(const RVec<T> &results)
58{
59 return results.size();
60}
61
62template <typename T>
63void ResizeResults(ROOT::RVec<T> &results, std::size_t /*nCols*/, std::size_t nVariations)
64{
65 results.resize(nVariations);
66}
67
68/// Assign into fLastResults[slot] without changing the addresses of its elements (we gave those addresses away in
69/// GetValuePtr)
70/// The callee is responsible of making sure that `resStorage` has the correct size.
71template <typename T>
72void AssignResults(ROOT::RVec<T> &resStorage, ROOT::RVec<T> &&tmpResults)
73{
74 const auto nVariations = resStorage.size(); // we have already checked that tmpResults has the same size
75
76 for (auto i = 0u; i < nVariations; ++i)
77 resStorage[i] = std::move(tmpResults[i]);
78}
79
80template <typename T>
81void *GetValuePtrHelper(ROOT::RVec<T> &v, std::size_t /*colIdx*/, std::size_t varIdx)
82{
83 return static_cast<void *>(&v[varIdx]);
84}
85///@}
86
87/// @name Helper functions for the case of multiple columns being varied simultaneously.
88///@{
89template <typename T>
90bool ResultsSizeEq(const T &results, std::size_t expected, std::size_t /*nColumns*/, std::false_type /*isSingleColumn*/)
91{
92 return std::all_of(results.begin(), results.end(),
93 [expected](const auto &inner) { return inner.size() == expected; });
94}
95
96template <typename T>
97std::size_t GetNVariations(const std::vector<RVec<T>> &results)
98{
99 assert(!results.empty());
100 return results[0].size();
101}
102
103template <typename T>
104void ResizeResults(std::vector<ROOT::RVec<T>> &results, std::size_t nCols, std::size_t nVariations)
105{
106 results.resize(nCols);
107 for (auto &rvecOverVariations : results)
108 rvecOverVariations.resize(nVariations);
109}
110
111// The callee is responsible of making sure that `resStorage` has the correct outer and inner sizes.
112template <typename T>
113void AssignResults(std::vector<ROOT::RVec<T>> &resStorage, ROOT::RVec<ROOT::RVec<T>> &&tmpResults)
114{
115 const auto nCols = resStorage.size();
116 const auto nVariations = resStorage[0].size();
117 for (auto colIdx = 0u; colIdx < nCols; ++colIdx)
118 for (auto varIdx = 0u; varIdx < nVariations; ++varIdx)
119 resStorage[colIdx][varIdx] = std::move(tmpResults[colIdx][varIdx]);
120}
121
122template <typename T>
123void *GetValuePtrHelper(std::vector<ROOT::RVec<T>> &v, std::size_t colIdx, std::size_t varIdx)
124{
125 return static_cast<void *>(&v[colIdx][varIdx]);
126}
127///@}
128
129template <typename VaryExpressionRet_t, bool IsSingleColumn>
131};
132
133template <typename T>
134struct ColumnType<ROOT::RVec<T>, true> {
135 using type = T;
136};
137
138template <typename T>
139struct ColumnType<ROOT::RVec<ROOT::RVec<T>>, false> {
140 using type = T;
141};
142
143/// When varying a single column, Ret_t is RVec<T> and ColumnType_t is T.
144/// When varying multiple columns, Ret_t is RVec<RVec<T>> and ColumnType_t is T.
145template <bool IsSingleColumn, typename Ret_t>
147
148template <typename F, bool IsSingleColumn>
149class R__CLING_PTRCHECK(off) RVariation final : public RVariationBase {
151 using TypeInd_t = std::make_index_sequence<ColumnTypes_t::list_size>;
154 using Result_t = std::conditional_t<IsSingleColumn, ROOT::RVec<VariedCol_t>, std::vector<ROOT::RVec<VariedCol_t>>>;
155
157 /// Per-slot storage for varied column values (for one or multiple columns depending on IsSingleColumn).
158 std::vector<Result_t> fLastResults;
159
160 /// Column readers per slot and per input column
161 std::vector<std::array<RColumnReaderBase *, ColumnTypes_t::list_size>> fValues;
162
163 template <typename... ColTypes, std::size_t... S>
164 void UpdateHelper(unsigned int slot, Long64_t entry, TypeList<ColTypes...>, std::index_sequence<S...>)
165 {
166 // fExpression must return an RVec<T>
167 auto &&results = fExpression(fValues[slot][S]->template Get<ColTypes>(entry)...);
168 (void)entry; // avoid unused parameter warnings (gcc 12.1)
169
170 if (!ResultsSizeEq(results, fVariationNames.size(), fColNames.size(),
171 std::integral_constant<bool, IsSingleColumn>{})) {
172 std::string variationName = fVariationNames[0].substr(0, fVariationNames[0].find_first_of(':'));
173 throw std::runtime_error("The evaluation of the expression for variation \"" + variationName +
174 "\" resulted in " + std::to_string(GetNVariations(results)) + " values, but " +
175 std::to_string(fVariationNames.size()) + " were expected.");
176 }
177
178 AssignResults(fLastResults[slot * CacheLineStep<Result_t>()], std::move(results));
179 }
180
181public:
182 RVariation(const std::vector<std::string> &colNames, std::string_view variationName, F expression,
183 const std::vector<std::string> &variationTags, std::string_view type, const RColumnRegister &defines,
184 RLoopManager &lm, const ColumnNames_t &inputColNames)
185 : RVariationBase(colNames, variationName, variationTags, type, defines, lm, inputColNames),
186 fExpression(std::move(expression)), fLastResults(lm.GetNSlots() * RDFInternal::CacheLineStep<Result_t>()),
187 fValues(lm.GetNSlots())
188 {
189 fLoopManager->Register(this);
190
191 for (auto i = 0u; i < lm.GetNSlots(); ++i)
192 ResizeResults(fLastResults[i * RDFInternal::CacheLineStep<Result_t>()], colNames.size(), variationTags.size());
193 }
194
195 RVariation(const RVariation &) = delete;
196 RVariation &operator=(const RVariation &) = delete;
197 ~RVariation() { fLoopManager->Deregister(this); }
198
199 void InitSlot(TTreeReader *r, unsigned int slot) final
200 {
201 RColumnReadersInfo info{fInputColumns, fColumnRegister, fIsDefine.data(), *fLoopManager};
202 fValues[slot] = GetColumnReaders(slot, r, ColumnTypes_t{}, info);
203 fLastCheckedEntry[slot * CacheLineStep<Long64_t>()] = -1;
204 }
205
206 /// Return the (type-erased) address of the value for the given processing slot.
207 void *GetValuePtr(unsigned int slot, const std::string &column, const std::string &variation) final
208 {
209 const auto colIt = std::find(fColNames.begin(), fColNames.end(), column);
210 assert(colIt != fColNames.end());
211 const auto colIdx = std::distance(fColNames.begin(), colIt);
212
213 const auto varIt = std::find(fVariationNames.begin(), fVariationNames.end(), variation);
214 assert(varIt != fVariationNames.end());
215 const auto varIdx = std::distance(fVariationNames.begin(), varIt);
216
217 return GetValuePtrHelper(fLastResults[slot * CacheLineStep<Result_t>()], colIdx, varIdx);
218 }
219
220 /// Update the value at the address returned by GetValuePtr with the content corresponding to the given entry
221 void Update(unsigned int slot, Long64_t entry) final
222 {
223 if (entry != fLastCheckedEntry[slot * CacheLineStep<Long64_t>()]) {
224 // evaluate this filter, cache the result
225 UpdateHelper(slot, entry, ColumnTypes_t{}, TypeInd_t{});
226 fLastCheckedEntry[slot * CacheLineStep<Long64_t>()] = entry;
227 }
228 }
229
230 const std::type_info &GetTypeId() const final { return typeid(VariedCol_t); }
231
232 /// Clean-up operations to be performed at the end of a task.
233 void FinalizeSlot(unsigned int slot) final { fValues[slot].fill(nullptr); }
234};
235
236} // namespace RDF
237} // namespace Internal
238} // namespace ROOT
239
240#endif // ROOT_RDF_RVARIATION
long long Long64_t
Definition RtypesCore.h:80
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
The head node of a RDF computation graph.
void resize(size_type N)
Definition RVec.hxx:584
A binder for user-defined columns, variations and aliases.
This type includes all parts of RVariation that do not depend on the callable signature.
void Update(unsigned int slot, Long64_t entry) final
Update the value at the address returned by GetValuePtr with the content corresponding to the given e...
std::conditional_t< IsSingleColumn, ROOT::RVec< VariedCol_t >, std::vector< ROOT::RVec< VariedCol_t > > > Result_t
const std::type_info & GetTypeId() const final
void FinalizeSlot(unsigned int slot) final
Clean-up operations to be performed at the end of a task.
void * GetValuePtr(unsigned int slot, const std::string &column, const std::string &variation) final
Return the (type-erased) address of the value for the given processing slot.
std::make_index_sequence< ColumnTypes_t::list_size > TypeInd_t
ColumnType_t< IsSingleColumn, Ret_t > VariedCol_t
RVariation(const std::vector< std::string > &colNames, std::string_view variationName, F expression, const std::vector< std::string > &variationTags, std::string_view type, const RColumnRegister &defines, RLoopManager &lm, const ColumnNames_t &inputColNames)
void InitSlot(TTreeReader *r, unsigned int slot) final
RVariation & operator=(const RVariation &)=delete
typename CallableTraits< F >::ret_type Ret_t
std::vector< std::array< RColumnReaderBase *, ColumnTypes_t::list_size > > fValues
Column readers per slot and per input column.
void UpdateHelper(unsigned int slot, Long64_t entry, TypeList< ColTypes... >, std::index_sequence< S... >)
typename CallableTraits< F >::arg_types ColumnTypes_t
std::vector< Result_t > fLastResults
Per-slot storage for varied column values (for one or multiple columns depending on IsSingleColumn).
RVariation(const RVariation &)=delete
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1480
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:44
#define F(x, y, z)
typename ColumnType< Ret_t, IsSingleColumn >::type ColumnType_t
When varying a single column, Ret_t is RVec<T> and ColumnType_t is T.
std::size_t GetNVariations(const RVec< T > &results)
unsigned int GetNSlots()
Definition RDFUtils.cxx:283
void ResizeResults(ROOT::RVec< T > &results, std::size_t, std::size_t nVariations)
void * GetValuePtrHelper(ROOT::RVec< T > &v, std::size_t, std::size_t varIdx)
constexpr std::size_t CacheLineStep()
Stepping through CacheLineStep<T> values in a vector<T> brings you to a new cache line.
Definition Utils.hxx:220
void AssignResults(ROOT::RVec< T > &resStorage, ROOT::RVec< T > &&tmpResults)
Assign into fLastResults[slot] without changing the addresses of its elements (we gave those addresse...
std::array< RDFDetail::RColumnReaderBase *, sizeof...(ColTypes)> GetColumnReaders(unsigned int slot, TTreeReader *r, TypeList< ColTypes... >, const RColumnReadersInfo &colInfo, const std::string &variationName="nominal")
Create a group of column readers, one per type in the parameter pack.
bool ResultsSizeEq(const T &results, std::size_t expected, std::size_t nColumns, std::true_type)
std::vector< std::string > ColumnNames_t
ROOT type_traits extensions.
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
Extract types from the signature of a callable object. See CallableTraits.
This type aggregates some of the arguments passed to GetColumnReaders.
Lightweight storage for a collection of types.