Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RMergeableValue.hxx
Go to the documentation of this file.
1/**
2 \file ROOT/RDF/RMergeableValue.hxx
3 \ingroup dataframe
4 \author Vincenzo Eduardo Padulano
5 \author Enrico Guiraud
6 \date 2020-06
7*/
8
9/*************************************************************************
10 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
11 * All rights reserved. *
12 * *
13 * For the licensing terms see $ROOTSYS/LICENSE. *
14 * For the list of contributors see $ROOTSYS/README/CREDITS. *
15 *************************************************************************/
16
17#ifndef ROOT_RDF_RMERGEABLEVALUE
18#define ROOT_RDF_RMERGEABLEVALUE
19
20#include <memory>
21#include <stdexcept>
22#include <algorithm> // std::min, std::max
23
24#include "RtypesCore.h"
25#include "TList.h" // RMergeableFill::Merge
26
27namespace ROOT {
28namespace Detail {
29namespace RDF {
30
31// Fwd declarations for RMergeableValue
32template <typename T>
33class RMergeableValue;
34
35template <typename T, typename... Ts>
36std::unique_ptr<RMergeableValue<T>> MergeValues(std::unique_ptr<RMergeableValue<T>> OutputMergeable,
37 std::unique_ptr<RMergeableValue<Ts>>... InputMergeables);
38
39template <typename T, typename... Ts>
40void MergeValues(RMergeableValue<T> &OutputMergeable, const RMergeableValue<Ts> &... InputMergeables);
41
42/**
43\class ROOT::Detail::RDF::RMergeableValueBase
44\brief Base class of RMergeableValue.
45\ingroup dataframe
46Base class of the mergeable RDataFrame results family of classes. Provides a
47non-templated custom type to allow passing a `std::unique_ptr` to the mergeable
48object along the call chain. This class is never used in the public API and has
49no meaning for the final user.
50*/
52public:
53 virtual ~RMergeableValueBase() = default;
54 /**
55 Default constructor. Needed to allow serialization of ROOT objects. See
56 [TBufferFile::WriteObjectClass]
57 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
58 */
60};
61
62/**
63\class ROOT::Detail::RDF::RMergeableValue
64\ingroup dataframe
65\brief A result of an RDataFrame execution, that knows how to merge with other
66results of the same type.
67\tparam T Type of the action result.
68
69Results of the execution of an RDataFrame computation graph do not natively
70know how to merge with other results of the same type. In a distributed
71environment it is often needed to have a merging mechanism for partial results
72coming from the execution of an analysis on different chunks of the same dataset
73that has happened on different executors. In order to achieve this,
74RMergeableValue stores the result of the RDataFrame action and has a `Merge`
75method to allow the aggregation of information coming from another similar
76result into the current.
77
78A mergeable value can be retrieved from an RResultPtr through the
79[GetMergeableValue]
80(namespaceROOT_1_1Detail_1_1RDF.html#a8b3a9c7b416826acc952d78a56d14ecb) free
81function and a sequence of mergeables can be merged together with the helper
82function [MergeValues]
83(namespaceROOT_1_1Detail_1_1RDF.html#af16fefbe2d120983123ddf8a1e137277).
84All the classes and functions involved are inside the `ROOT::Detail::RDF`
85namespace.
86
87In a nutshell:
88~~~{.cpp}
89using namespace ROOT::Detail::RDF;
90ROOT::RDataFrame d("myTree", "file_*.root");
91auto h1 = d.Histo1D("Branch_A");
92auto h2 = d.Histo1D("Branch_A");
93
94// Retrieve mergeables from the `RResultPtr`s
95auto mergeableh1 = GetMergeableValue(h1);
96auto mergeableh2 = GetMergeableValue(h2);
97
98// Merge the values and get another mergeable back
99auto mergedptr = MergeValues(std::move(mergeableh1), std::move(mergeableh2));
100
101// Retrieve the merged TH1D object
102const auto &mergedhisto = mergedptr->GetValue();
103~~~
104
105Though this snippet can run on a single thread of a single machine, it is
106straightforward to generalize it to a distributed case, e.g. where `mergeableh1`
107and `mergeableh2` are created on separate machines and sent to a `reduce`
108process where the `MergeValues` function is called. The final user would then
109just be given the final merged result coming from `mergedptr->GetValue`.
110
111RMergeableValue is the base class for all the different specializations that may
112be needed according to the peculiarities of the result types. The following
113subclasses, their names hinting at the action operation of the result, are
114currently available:
115
116- RMergeableCount
117- RMergeableFill, responsible for the following actions:
118 - Graph
119 - Histo{1,2,3}D
120 - Profile{1,2}D
121 - Stats
122- RMergeableMax
123- RMergeableMean
124- RMergeableMin
125- RMergeableStdDev
126- RMergeableSum
127*/
128template <typename T>
130 // Friend function declarations
131 template <typename T1, typename... Ts>
132 friend std::unique_ptr<RMergeableValue<T1>> MergeValues(std::unique_ptr<RMergeableValue<T1>> OutputMergeable,
133 std::unique_ptr<RMergeableValue<Ts>>... InputMergeables);
134 template <typename T1, typename... Ts>
135 friend void MergeValues(RMergeableValue<T1> &OutputMergeable, const RMergeableValue<Ts> &... InputMergeables);
136
137 /////////////////////////////////////////////////////////////////////////////
138 /// \brief Aggregate the information contained in another RMergeableValue
139 /// into this.
140 ///
141 /// Virtual function reimplemented in all the subclasses.
142 ///
143 /// \note All the `Merge` methods in the RMergeableValue family are private.
144 /// To merge multiple RMergeableValue objects please use [MergeValues]
145 /// (namespaceROOT_1_1Detail_1_1RDF.html#af16fefbe2d120983123ddf8a1e137277).
146 virtual void Merge(const RMergeableValue<T> &) = 0;
147
148protected:
150
151public:
152 /**
153 Constructor taking the action result by const reference. This involves a
154 copy of the result into the data member, but gives full ownership of data
155 to the mergeable.
156 */
157 RMergeableValue(const T &value) : fValue{value} {}
158 /**
159 Default constructor. Needed to allow serialization of ROOT objects. See
160 [TBufferFile::WriteObjectClass]
161 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
162 */
163 RMergeableValue() = default;
164 /////////////////////////////////////////////////////////////////////////////
165 /// \brief Retrieve the result wrapped by this mergeable.
166 const T &GetValue() const { return fValue; }
167};
168
169/**
170\class ROOT::Detail::RDF::RMergeableCount
171\ingroup dataframe
172\brief Specialization of RMergeableValue for the
173[Count](classROOT_1_1RDF_1_1RInterface.html#a9678150c9c18cddd7b599690ba854734)
174action.
175*/
176class RMergeableCount final : public RMergeableValue<ULong64_t> {
177 /////////////////////////////////////////////////////////////////////////////
178 /// \brief Aggregate the information contained in another RMergeableValue
179 /// into this.
180 /// \param[in] other Another RMergeableValue object.
181 /// \throws std::invalid_argument If the cast of the other object to the same
182 /// type as this one fails.
183 ///
184 /// The other RMergeableValue object is cast to the same type as this object.
185 /// This is needed to make sure that only results of the same type of action
186 /// are merged together. Then the two results are added together to update
187 /// the value held by the current object.
188 ///
189 /// \note All the `Merge` methods in the RMergeableValue family are private.
190 /// To merge multiple RMergeableValue objects please use [MergeValues]
191 /// (namespaceROOT_1_1Detail_1_1RDF.html#af16fefbe2d120983123ddf8a1e137277).
192 void Merge(const RMergeableValue<ULong64_t> &other) final
193 {
194 try {
195 const auto &othercast = dynamic_cast<const RMergeableCount &>(other);
196 this->fValue += othercast.fValue;
197 } catch (const std::bad_cast &) {
198 throw std::invalid_argument("Results from different actions cannot be merged together.");
199 }
200 }
201
202public:
203 /////////////////////////////////////////////////////////////////////////////
204 /// \brief Constructor that initializes data members.
205 /// \param[in] value The action result.
207 /**
208 Default constructor. Needed to allow serialization of ROOT objects. See
209 [TBufferFile::WriteObjectClass]
210 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
211 */
212 RMergeableCount() = default;
215};
216
217/**
218\class ROOT::Detail::RDF::RMergeableFill
219\ingroup dataframe
220\brief Specialization of RMergeableValue for histograms and statistics.
221
222This subclass is responsible for merging results coming from the following
223actions:
224- [Graph](classROOT_1_1RDF_1_1RInterface.html#a804b466ebdbddef5c7e3400cc6b89301)
225- [Histo{1D,2D,3D}]
226 (classROOT_1_1RDF_1_1RInterface.html#a247ca3aeb7ce5b95015b7fae72983055)
227- [Profile{1D,2D}]
228 (classROOT_1_1RDF_1_1RInterface.html#a8ef7dc16b0e9f7bc9cfbe2d9e5de0cef)
229- [Stats](classROOT_1_1RDF_1_1RInterface.html#abc68922c464e472f5f856e8981955af6)
230
231*/
232template <typename T>
233class RMergeableFill final : public RMergeableValue<T> {
234 /////////////////////////////////////////////////////////////////////////////
235 /// \brief Aggregate the information contained in another RMergeableValue
236 /// into this.
237 /// \param[in] other Another RMergeableValue object.
238 /// \throws std::invalid_argument If the cast of the other object to the same
239 /// type as this one fails.
240 ///
241 /// The other RMergeableValue object is cast to the same type as this object.
242 /// This is needed to make sure that only results of the same type of action
243 /// are merged together. The function then calls the right `Merge` method
244 /// according to the class of the fValue data member.
245 ///
246 /// \note All the `Merge` methods in the RMergeableValue family are private.
247 /// To merge multiple RMergeableValue objects please use [MergeValues]
248 /// (namespaceROOT_1_1Detail_1_1RDF.html#af16fefbe2d120983123ddf8a1e137277).
249 void Merge(const RMergeableValue<T> &other) final
250 {
251 try {
252 const auto &othercast = dynamic_cast<const RMergeableFill<T> &>(other);
253 TList l; // The `Merge` method accepts a TList
254 l.Add(const_cast<T *>(&(othercast.fValue))); // Ugly but needed because of the signature of TList::Add
255 this->fValue.Merge(&l); // if `T == TH1D` Eventually calls TH1::ExtendAxis that creates new instances of TH1D
256 } catch (const std::bad_cast &) {
257 throw std::invalid_argument("Results from different actions cannot be merged together.");
258 }
259 }
260
261public:
262 /////////////////////////////////////////////////////////////////////////////
263 /// \brief Constructor that initializes data members.
264 /// \param[in] value The action result.
265 RMergeableFill(const T &value) : RMergeableValue<T>(value) {}
266 /**
267 Default constructor. Needed to allow serialization of ROOT objects. See
268 [TBufferFile::WriteObjectClass]
269 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
270 */
271 RMergeableFill() = default;
274};
275
276template <typename T>
277class RMergeableMax final : public RMergeableValue<T> {
278
279 void Merge(const RMergeableValue<T> &other) final
280 {
281 try {
282 const auto &othercast = dynamic_cast<const RMergeableMax<T> &>(other);
283 this->fValue = std::max(this->fValue, othercast.fValue);
284 } catch (const std::bad_cast &) {
285 throw std::invalid_argument("Results from different actions cannot be merged together.");
286 }
287 }
288
289public:
290 /////////////////////////////////////////////////////////////////////////////
291 /// \brief Constructor that initializes data members.
292 /// \param[in] value The action result.
293 RMergeableMax(const T &value) : RMergeableValue<T>(value) {}
294 /**
295 Default constructor. Needed to allow serialization of ROOT objects. See
296 [TBufferFile::WriteObjectClass]
297 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
298 */
299 RMergeableMax() = default;
301 RMergeableMax(const RMergeableMax &) = delete;
302};
303
304/**
305\class ROOT::Detail::RDF::RMergeableMean
306\ingroup dataframe
307\brief Specialization of RMergeableValue for the
308[Mean](classROOT_1_1RDF_1_1RInterface.html#ade6b020284f2f4fe9d3b09246b5f376a)
309action.
310
311This subclass is responsible for merging results coming from Mean actions. Other
312than the result itself, the number of entries that were used to compute that
313mean is also stored in the object.
314*/
315class RMergeableMean final : public RMergeableValue<Double_t> {
316 ULong64_t fCounts; ///< The number of entries used to compute the mean.
317
318 /////////////////////////////////////////////////////////////////////////////
319 /// \brief Aggregate the information contained in another RMergeableValue
320 /// into this.
321 /// \param[in] other Another RMergeableValue object.
322 /// \throws std::invalid_argument If the cast of the other object to the same
323 /// type as this one fails.
324 ///
325 /// The other RMergeableValue object is cast to the same type as this object.
326 /// This is needed to make sure that only results of the same type of action
327 /// are merged together. The function then computes the weighted mean of the
328 /// two means held by the mergeables.
329 ///
330 /// \note All the `Merge` methods in the RMergeableValue family are private.
331 /// To merge multiple RMergeableValue objects please use [MergeValues]
332 /// (namespaceROOT_1_1Detail_1_1RDF.html#af16fefbe2d120983123ddf8a1e137277).
333 void Merge(const RMergeableValue<Double_t> &other) final
334 {
335 try {
336 const auto &othercast = dynamic_cast<const RMergeableMean &>(other);
337 const auto &othervalue = othercast.fValue;
338 const auto &othercounts = othercast.fCounts;
339
340 // Compute numerator and denumerator of the weighted mean
341 const auto num = this->fValue * fCounts + othervalue * othercounts;
342 const auto denum = static_cast<Double_t>(fCounts + othercounts);
343
344 // Update data members
345 this->fValue = num / denum;
346 fCounts += othercounts;
347 } catch (const std::bad_cast &) {
348 throw std::invalid_argument("Results from different actions cannot be merged together.");
349 }
350 }
351
352public:
353 /////////////////////////////////////////////////////////////////////////////
354 /// \brief Constructor that initializes data members.
355 /// \param[in] value The action result.
356 /// \param[in] counts The number of entries used to compute that result.
358 /**
359 Default constructor. Needed to allow serialization of ROOT objects. See
360 [TBufferFile::WriteObjectClass]
361 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
362 */
363 RMergeableMean() = default;
366};
367
368template <typename T>
369class RMergeableMin final : public RMergeableValue<T> {
370
371 void Merge(const RMergeableValue<T> &other) final
372 {
373 try {
374 const auto &othercast = dynamic_cast<const RMergeableMin<T> &>(other);
375 this->fValue = std::min(this->fValue, othercast.fValue);
376 } catch (const std::bad_cast &) {
377 throw std::invalid_argument("Results from different actions cannot be merged together.");
378 }
379 }
380
381public:
382 /////////////////////////////////////////////////////////////////////////////
383 /// \brief Constructor that initializes data members.
384 /// \param[in] value The action result.
385 RMergeableMin(const T &value) : RMergeableValue<T>(value) {}
386 /**
387 Default constructor. Needed to allow serialization of ROOT objects. See
388 [TBufferFile::WriteObjectClass]
389 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
390 */
391 RMergeableMin() = default;
393 RMergeableMin(const RMergeableMin &) = delete;
394};
395
396/**
397\class ROOT::Detail::RDF::RMergeableStdDev
398\ingroup dataframe
399\brief Specialization of RMergeableValue for the
400[StdDev](classROOT_1_1RDF_1_1RInterface.html#a482c4e4f81fe1e421c016f89cd281572)
401action.
402
403This class also stores information about the number of entries and the average
404used to compute the standard deviation.
405*/
406class RMergeableStdDev final : public RMergeableValue<Double_t> {
407 ULong64_t fCounts; ///< Number of entries of the set.
408 Double_t fMean; ///< Average of the set.
409
410 /////////////////////////////////////////////////////////////////////////////
411 /// \brief Aggregate the information contained in another RMergeableValue
412 /// into this.
413 /// \param[in] other Another RMergeableValue object.
414 /// \throws std::invalid_argument If the cast of the other object to the same
415 /// type as this one fails.
416 ///
417 /// The other RMergeableValue object is cast to the same type as this object.
418 /// This is needed to make sure that only results of the same type of action
419 /// are merged together. The function then computes the aggregated standard
420 /// deviation of the two samples using an algorithm by
421 /// [Chan et al. (1979)]
422 /// (http://i.stanford.edu/pub/cstr/reports/cs/tr/79/773/CS-TR-79-773.pdf)
423 ///
424 /// \note All the `Merge` methods in the RMergeableValue family are private.
425 /// To merge multiple RMergeableValue objects please use [MergeValues]
426 /// (namespaceROOT_1_1Detail_1_1RDF.html#af16fefbe2d120983123ddf8a1e137277).
427 void Merge(const RMergeableValue<Double_t> &other) final
428 {
429 try {
430 const auto &othercast = dynamic_cast<const RMergeableStdDev &>(other);
431 const auto &othercounts = othercast.fCounts;
432 const auto &othermean = othercast.fMean;
433
434 // Compute the aggregated variance using an algorithm by Chan et al.
435 // See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Parallel_algorithm
436 const auto thisvariance = std::pow(this->fValue, 2);
437 const auto othervariance = std::pow(othercast.fValue, 2);
438
439 const auto delta = othermean - fMean;
440
441 const auto m_a = thisvariance * (fCounts - 1);
442 const auto m_b = othervariance * (othercounts - 1);
443
444 const auto sumcounts = static_cast<Double_t>(fCounts + othercounts);
445
446 const auto M2 = m_a + m_b + std::pow(delta, 2) * fCounts * othercounts / sumcounts;
447
448 const auto meannum = fMean * fCounts + othermean * othercounts;
449
450 // Update the data members
451 this->fValue = std::sqrt(M2 / (sumcounts - 1));
452 fMean = meannum / sumcounts;
453 fCounts += othercounts;
454 } catch (const std::bad_cast &) {
455 throw std::invalid_argument("Results from different actions cannot be merged together.");
456 }
457 }
458
459public:
460 /////////////////////////////////////////////////////////////////////////////
461 /// \brief Constructor that initializes data members.
462 /// \param[in] value The action result.
463 /// \param[in] counts The number of entries of the set.
464 /// \param[in] mean The average of the set.
466 : RMergeableValue<Double_t>(value), fCounts{counts}, fMean{mean}
467 {
468 }
469 /**
470 Default constructor. Needed to allow serialization of ROOT objects. See
471 [TBufferFile::WriteObjectClass]
472 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
473 */
474 RMergeableStdDev() = default;
477};
478
479template <typename T>
480class RMergeableSum final : public RMergeableValue<T> {
481
482 void Merge(const RMergeableValue<T> &other) final
483 {
484 try {
485 const auto &othercast = dynamic_cast<const RMergeableSum<T> &>(other);
486 this->fValue += othercast.fValue;
487 } catch (const std::bad_cast &) {
488 throw std::invalid_argument("Results from different actions cannot be merged together.");
489 }
490 }
491
492public:
493 /////////////////////////////////////////////////////////////////////////////
494 /// \brief Constructor that initializes data members.
495 /// \param[in] value The action result.
496 RMergeableSum(const T &value) : RMergeableValue<T>(value) {}
497 /**
498 Default constructor. Needed to allow serialization of ROOT objects. See
499 [TBufferFile::WriteObjectClass]
500 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
501 */
502 RMergeableSum() = default;
504 RMergeableSum(const RMergeableSum &) = delete;
505};
506
507/// \cond HIDDEN_SYMBOLS
508// What follows mimics C++17 std::conjunction without using recursive template instantiations.
509// Used in `MergeValues` to check that all the mergeables hold values of the same type.
510template <bool...>
511struct bool_pack {
512};
513template <class... Ts>
514using conjunction = std::is_same<bool_pack<true, Ts::value...>, bool_pack<Ts::value..., true>>;
515/// \endcond
516
517////////////////////////////////////////////////////////////////////////////////
518/// \brief Merge multiple RMergeableValue objects into one.
519/// \param[in] OutputMergeable The mergeable object where all the information
520/// will be aggregated.
521/// \param[in] InputMergeables Other mergeables containing the partial results.
522/// \returns An RMergeableValue holding the aggregated value wrapped in an
523/// `std::unique_ptr`.
524///
525/// This is the recommended way of merging multiple RMergeableValue objects.
526/// This overload takes ownership of the mergeables and gives back to the user
527/// a mergeable with the aggregated information. All the mergeables with the
528/// partial results get destroyed in the process.
529///
530/// Example usage:
531/// ~~~{.cpp}
532/// using namespace ROOT::Detail::RDF;
533/// // mh1, mh2, mh3 are std::unique_ptr<RMergeableValue<TH1D>>
534/// auto mergedptr = MergeValues(std::move(mh1), std::move(mh2), std::move(mh3));
535/// const auto &mergedhisto = mergedptr->GetValue(); // Final merged histogram
536/// // Do stuff with it
537/// mergedhisto.Draw();
538/// ~~~
539template <typename T, typename... Ts>
540std::unique_ptr<RMergeableValue<T>> MergeValues(std::unique_ptr<RMergeableValue<T>> OutputMergeable,
541 std::unique_ptr<RMergeableValue<Ts>>... InputMergeables)
542{
543 // Check all mergeables have the same template type
544 static_assert(conjunction<std::is_same<Ts, T>...>::value, "Values must all be of the same type.");
545
546 // Using dummy array initialization inspired by https://stackoverflow.com/a/25683817
547 using expander = int[];
548 // Cast to void to suppress unused-value warning in Clang
549 (void)expander{0, (OutputMergeable->Merge(*InputMergeables), 0)...};
550
551 return OutputMergeable;
552}
553
554////////////////////////////////////////////////////////////////////////////////
555/// \brief Merge multiple RMergeableValue objects into one.
556/// \param[in,out] OutputMergeable The mergeable object where all the
557/// information will be aggregated.
558/// \param[in] InputMergeables Other mergeables containing the partial results.
559///
560/// This overload modifies the mergeable objects in-place. The ownership is left
561/// to the caller. The first argument to the function will get all the
562/// values contained in the other arguments merged into itself. This is a
563/// convenience overload introduced for the ROOT Python API.
564///
565/// Example usage:
566/// ~~~{.cpp}
567/// // mh1, mh2, mh3 are std::unique_ptr<RMergeableValue<TH1D>>
568/// ROOT::Detail::RDF::MergeValues(*mh1, *mh2, *mh3);
569/// const auto &mergedhisto = mh1->GetValue(); // Final merged histogram
570/// // Do stuff with it
571/// mergedhisto.Draw();
572/// ~~~
573template <typename T, typename... Ts>
574void MergeValues(RMergeableValue<T> &OutputMergeable, const RMergeableValue<Ts> &... InputMergeables)
575{
576 // Check all mergeables are of the same type
577 static_assert(conjunction<std::is_same<Ts, T>...>::value, "Values must all be of the same type.");
578
579 // Using dummy array initialization inspired by https://stackoverflow.com/a/25683817
580 using expander = int[];
581 // Cast to void to suppress unused-value warning in Clang
582 (void)expander{0, (OutputMergeable.Merge(InputMergeables), 0)...};
583}
584} // namespace RDF
585} // namespace Detail
586} // namespace ROOT
587
588#endif // ROOT_RDF_RMERGEABLEVALUE
double Double_t
Definition RtypesCore.h:59
unsigned long long ULong64_t
Definition RtypesCore.h:74
typedef void((*Func_t)())
Specialization of RMergeableValue for the Count action.
RMergeableCount(const RMergeableCount &)=delete
void Merge(const RMergeableValue< ULong64_t > &other) final
Aggregate the information contained in another RMergeableValue into this.
RMergeableCount()=default
Default constructor.
RMergeableCount(ULong64_t value)
Constructor that initializes data members.
RMergeableCount(RMergeableCount &&)=default
Specialization of RMergeableValue for histograms and statistics.
RMergeableFill(RMergeableFill &&)=default
RMergeableFill()=default
Default constructor.
RMergeableFill(const T &value)
Constructor that initializes data members.
void Merge(const RMergeableValue< T > &other) final
Aggregate the information contained in another RMergeableValue into this.
RMergeableFill(const RMergeableFill &)=delete
RMergeableMax(RMergeableMax &&)=default
RMergeableMax(const T &value)
Constructor that initializes data members.
void Merge(const RMergeableValue< T > &other) final
Aggregate the information contained in another RMergeableValue into this.
RMergeableMax()=default
Default constructor.
RMergeableMax(const RMergeableMax &)=delete
Specialization of RMergeableValue for the Mean action.
RMergeableMean(Double_t value, ULong64_t counts)
Constructor that initializes data members.
RMergeableMean(const RMergeableMean &)=delete
ULong64_t fCounts
The number of entries used to compute the mean.
RMergeableMean(RMergeableMean &&)=default
RMergeableMean()=default
Default constructor.
void Merge(const RMergeableValue< Double_t > &other) final
Aggregate the information contained in another RMergeableValue into this.
RMergeableMin()=default
Default constructor.
RMergeableMin(const RMergeableMin &)=delete
RMergeableMin(const T &value)
Constructor that initializes data members.
void Merge(const RMergeableValue< T > &other) final
Aggregate the information contained in another RMergeableValue into this.
RMergeableMin(RMergeableMin &&)=default
Specialization of RMergeableValue for the StdDev action.
RMergeableStdDev(Double_t value, ULong64_t counts, Double_t mean)
Constructor that initializes data members.
void Merge(const RMergeableValue< Double_t > &other) final
Aggregate the information contained in another RMergeableValue into this.
RMergeableStdDev(const RMergeableStdDev &)=delete
ULong64_t fCounts
Number of entries of the set.
Double_t fMean
Average of the set.
RMergeableStdDev()=default
Default constructor.
RMergeableStdDev(RMergeableStdDev &&)=default
RMergeableSum()=default
Default constructor.
RMergeableSum(const T &value)
Constructor that initializes data members.
RMergeableSum(const RMergeableSum &)=delete
RMergeableSum(RMergeableSum &&)=default
void Merge(const RMergeableValue< T > &other) final
Aggregate the information contained in another RMergeableValue into this.
Base class of RMergeableValue.
RMergeableValueBase()=default
Default constructor.
A result of an RDataFrame execution, that knows how to merge with other results of the same type.
RMergeableValue()=default
Default constructor.
const T & GetValue() const
Retrieve the result wrapped by this mergeable.
friend void MergeValues(RMergeableValue< T1 > &OutputMergeable, const RMergeableValue< Ts > &... InputMergeables)
friend std::unique_ptr< RMergeableValue< T1 > > MergeValues(std::unique_ptr< RMergeableValue< T1 > > OutputMergeable, std::unique_ptr< RMergeableValue< Ts > >... InputMergeables)
RMergeableValue(const T &value)
Constructor taking the action result by const reference.
virtual void Merge(const RMergeableValue< T > &)=0
Aggregate the information contained in another RMergeableValue into this.
A doubly linked list.
Definition TList.h:44
virtual void Add(TObject *obj)
Definition TList.h:87
#define T1
Definition md5.inl:145
std::unique_ptr< RMergeableValue< T > > MergeValues(std::unique_ptr< RMergeableValue< T > > OutputMergeable, std::unique_ptr< RMergeableValue< Ts > >... InputMergeables)
Merge multiple RMergeableValue objects into one.
double T(double x)
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
auto * l
Definition textangle.C:4