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- [HistoND](classROOT_1_1RDF_1_1RInterface.html#a0c9956a0f48c26f8e4294e17376c7fea)
228- [Profile{1D,2D}]
229 (classROOT_1_1RDF_1_1RInterface.html#a8ef7dc16b0e9f7bc9cfbe2d9e5de0cef)
230- [Stats](classROOT_1_1RDF_1_1RInterface.html#abc68922c464e472f5f856e8981955af6)
231
232*/
233template <typename T>
234class RMergeableFill final : public RMergeableValue<T> {
235
236 // RDataFrame's generic Fill method supports two possible signatures for Merge.
237 // Templated to create a dependent type to SFINAE on - in reality, `U` will always be `T`.
238 // This overload handles Merge(TCollection*)...
239 template <typename U, std::enable_if_t<std::is_base_of<TObject, U>::value, int> = 0>
240 auto DoMerge(const RMergeableFill<U> &other, int /*toincreaseoverloadpriority*/)
241 -> decltype(((U &)this->fValue).Merge((TCollection *)nullptr), void())
242 {
243 TList l; // The `Merge` method accepts a TList
244 l.Add(const_cast<U *>(&other.fValue)); // Ugly but needed because of the signature of TList::Add
245 this->fValue.Merge(&l); // if `T == TH1D` Eventually calls TH1::ExtendAxis that creates new instances of TH1D
246 }
247
248 // ...and this one handles Merge(const std::vector<T*> &)
249 template <typename U>
250 auto DoMerge(const RMergeableFill<U> &other, double /*todecreaseoverloadpriority*/)
251 -> decltype(this->fValue.Merge(std::vector<U *>{}), void())
252 {
253 this->fValue.Merge({const_cast<U *>(&other.fValue)});
254 }
255
256 /////////////////////////////////////////////////////////////////////////////
257 /// \brief Aggregate the information contained in another RMergeableValue
258 /// into this.
259 /// \param[in] other Another RMergeableValue object.
260 /// \throws std::invalid_argument If the cast of the other object to the same
261 /// type as this one fails.
262 ///
263 /// The other RMergeableValue object is cast to the same type as this object.
264 /// This is needed to make sure that only results of the same type of action
265 /// are merged together. The function then calls the right `Merge` method
266 /// according to the class of the fValue data member.
267 ///
268 /// \note All the `Merge` methods in the RMergeableValue family are private.
269 /// To merge multiple RMergeableValue objects please use [MergeValues]
270 /// (namespaceROOT_1_1Detail_1_1RDF.html#af16fefbe2d120983123ddf8a1e137277).
271 void Merge(const RMergeableValue<T> &other) final
272 {
273 try {
274 const auto &othercast = dynamic_cast<const RMergeableFill<T> &>(other);
275 DoMerge(othercast, /*toselecttherightoverload=*/0);
276 } catch (const std::bad_cast &) {
277 throw std::invalid_argument("Results from different actions cannot be merged together.");
278 }
279 }
280
281public:
282 /////////////////////////////////////////////////////////////////////////////
283 /// \brief Constructor that initializes data members.
284 /// \param[in] value The action result.
285 RMergeableFill(const T &value) : RMergeableValue<T>(value) {}
286 /**
287 Default constructor. Needed to allow serialization of ROOT objects. See
288 [TBufferFile::WriteObjectClass]
289 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
290 */
291 RMergeableFill() = default;
294};
295
296template <typename T>
297class RMergeableMax final : public RMergeableValue<T> {
298
299 void Merge(const RMergeableValue<T> &other) final
300 {
301 try {
302 const auto &othercast = dynamic_cast<const RMergeableMax<T> &>(other);
303 this->fValue = std::max(this->fValue, othercast.fValue);
304 } catch (const std::bad_cast &) {
305 throw std::invalid_argument("Results from different actions cannot be merged together.");
306 }
307 }
308
309public:
310 /////////////////////////////////////////////////////////////////////////////
311 /// \brief Constructor that initializes data members.
312 /// \param[in] value The action result.
313 RMergeableMax(const T &value) : RMergeableValue<T>(value) {}
314 /**
315 Default constructor. Needed to allow serialization of ROOT objects. See
316 [TBufferFile::WriteObjectClass]
317 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
318 */
319 RMergeableMax() = default;
321 RMergeableMax(const RMergeableMax &) = delete;
322};
323
324/**
325\class ROOT::Detail::RDF::RMergeableMean
326\ingroup dataframe
327\brief Specialization of RMergeableValue for the
328[Mean](classROOT_1_1RDF_1_1RInterface.html#ade6b020284f2f4fe9d3b09246b5f376a)
329action.
330
331This subclass is responsible for merging results coming from Mean actions. Other
332than the result itself, the number of entries that were used to compute that
333mean is also stored in the object.
334*/
335class RMergeableMean final : public RMergeableValue<Double_t> {
336 ULong64_t fCounts; ///< The number of entries used to compute the mean.
337
338 /////////////////////////////////////////////////////////////////////////////
339 /// \brief Aggregate the information contained in another RMergeableValue
340 /// into this.
341 /// \param[in] other Another RMergeableValue object.
342 /// \throws std::invalid_argument If the cast of the other object to the same
343 /// type as this one fails.
344 ///
345 /// The other RMergeableValue object is cast to the same type as this object.
346 /// This is needed to make sure that only results of the same type of action
347 /// are merged together. The function then computes the weighted mean of the
348 /// two means held by the mergeables.
349 ///
350 /// \note All the `Merge` methods in the RMergeableValue family are private.
351 /// To merge multiple RMergeableValue objects please use [MergeValues]
352 /// (namespaceROOT_1_1Detail_1_1RDF.html#af16fefbe2d120983123ddf8a1e137277).
353 void Merge(const RMergeableValue<Double_t> &other) final
354 {
355 try {
356 const auto &othercast = dynamic_cast<const RMergeableMean &>(other);
357 const auto &othervalue = othercast.fValue;
358 const auto &othercounts = othercast.fCounts;
359
360 // Compute numerator and denumerator of the weighted mean
361 const auto num = this->fValue * fCounts + othervalue * othercounts;
362 const auto denum = static_cast<Double_t>(fCounts + othercounts);
363
364 // Update data members
365 this->fValue = num / denum;
366 fCounts += othercounts;
367 } catch (const std::bad_cast &) {
368 throw std::invalid_argument("Results from different actions cannot be merged together.");
369 }
370 }
371
372public:
373 /////////////////////////////////////////////////////////////////////////////
374 /// \brief Constructor that initializes data members.
375 /// \param[in] value The action result.
376 /// \param[in] counts The number of entries used to compute that result.
378 /**
379 Default constructor. Needed to allow serialization of ROOT objects. See
380 [TBufferFile::WriteObjectClass]
381 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
382 */
383 RMergeableMean() = default;
386};
387
388template <typename T>
389class RMergeableMin final : public RMergeableValue<T> {
390
391 void Merge(const RMergeableValue<T> &other) final
392 {
393 try {
394 const auto &othercast = dynamic_cast<const RMergeableMin<T> &>(other);
395 this->fValue = std::min(this->fValue, othercast.fValue);
396 } catch (const std::bad_cast &) {
397 throw std::invalid_argument("Results from different actions cannot be merged together.");
398 }
399 }
400
401public:
402 /////////////////////////////////////////////////////////////////////////////
403 /// \brief Constructor that initializes data members.
404 /// \param[in] value The action result.
405 RMergeableMin(const T &value) : RMergeableValue<T>(value) {}
406 /**
407 Default constructor. Needed to allow serialization of ROOT objects. See
408 [TBufferFile::WriteObjectClass]
409 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
410 */
411 RMergeableMin() = default;
413 RMergeableMin(const RMergeableMin &) = delete;
414};
415
416/**
417\class ROOT::Detail::RDF::RMergeableStdDev
418\ingroup dataframe
419\brief Specialization of RMergeableValue for the
420[StdDev](classROOT_1_1RDF_1_1RInterface.html#a482c4e4f81fe1e421c016f89cd281572)
421action.
422
423This class also stores information about the number of entries and the average
424used to compute the standard deviation.
425*/
426class RMergeableStdDev final : public RMergeableValue<Double_t> {
427 ULong64_t fCounts; ///< Number of entries of the set.
428 Double_t fMean; ///< Average of the set.
429
430 /////////////////////////////////////////////////////////////////////////////
431 /// \brief Aggregate the information contained in another RMergeableValue
432 /// into this.
433 /// \param[in] other Another RMergeableValue object.
434 /// \throws std::invalid_argument If the cast of the other object to the same
435 /// type as this one fails.
436 ///
437 /// The other RMergeableValue object is cast to the same type as this object.
438 /// This is needed to make sure that only results of the same type of action
439 /// are merged together. The function then computes the aggregated standard
440 /// deviation of the two samples using an algorithm by
441 /// [Chan et al. (1979)]
442 /// (http://i.stanford.edu/pub/cstr/reports/cs/tr/79/773/CS-TR-79-773.pdf)
443 ///
444 /// \note All the `Merge` methods in the RMergeableValue family are private.
445 /// To merge multiple RMergeableValue objects please use [MergeValues]
446 /// (namespaceROOT_1_1Detail_1_1RDF.html#af16fefbe2d120983123ddf8a1e137277).
447 void Merge(const RMergeableValue<Double_t> &other) final
448 {
449 try {
450 const auto &othercast = dynamic_cast<const RMergeableStdDev &>(other);
451 const auto &othercounts = othercast.fCounts;
452 const auto &othermean = othercast.fMean;
453
454 // Compute the aggregated variance using an algorithm by Chan et al.
455 // See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Parallel_algorithm
456 const auto thisvariance = std::pow(this->fValue, 2);
457 const auto othervariance = std::pow(othercast.fValue, 2);
458
459 const auto delta = othermean - fMean;
460
461 const auto m_a = thisvariance * (fCounts - 1);
462 const auto m_b = othervariance * (othercounts - 1);
463
464 const auto sumcounts = static_cast<Double_t>(fCounts + othercounts);
465
466 const auto M2 = m_a + m_b + std::pow(delta, 2) * fCounts * othercounts / sumcounts;
467
468 const auto meannum = fMean * fCounts + othermean * othercounts;
469
470 // Update the data members
471 this->fValue = std::sqrt(M2 / (sumcounts - 1));
472 fMean = meannum / sumcounts;
473 fCounts += othercounts;
474 } catch (const std::bad_cast &) {
475 throw std::invalid_argument("Results from different actions cannot be merged together.");
476 }
477 }
478
479public:
480 /////////////////////////////////////////////////////////////////////////////
481 /// \brief Constructor that initializes data members.
482 /// \param[in] value The action result.
483 /// \param[in] counts The number of entries of the set.
484 /// \param[in] mean The average of the set.
486 : RMergeableValue<Double_t>(value), fCounts{counts}, fMean{mean}
487 {
488 }
489 /**
490 Default constructor. Needed to allow serialization of ROOT objects. See
491 [TBufferFile::WriteObjectClass]
492 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
493 */
494 RMergeableStdDev() = default;
497};
498
499template <typename T>
500class RMergeableSum final : public RMergeableValue<T> {
501
502 void Merge(const RMergeableValue<T> &other) final
503 {
504 try {
505 const auto &othercast = dynamic_cast<const RMergeableSum<T> &>(other);
506 this->fValue += othercast.fValue;
507 } catch (const std::bad_cast &) {
508 throw std::invalid_argument("Results from different actions cannot be merged together.");
509 }
510 }
511
512public:
513 /////////////////////////////////////////////////////////////////////////////
514 /// \brief Constructor that initializes data members.
515 /// \param[in] value The action result.
516 RMergeableSum(const T &value) : RMergeableValue<T>(value) {}
517 /**
518 Default constructor. Needed to allow serialization of ROOT objects. See
519 [TBufferFile::WriteObjectClass]
520 (classTBufferFile.html#a209078a4cb58373b627390790bf0c9c1)
521 */
522 RMergeableSum() = default;
524 RMergeableSum(const RMergeableSum &) = delete;
525};
526
527/// \cond HIDDEN_SYMBOLS
528// What follows mimics C++17 std::conjunction without using recursive template instantiations.
529// Used in `MergeValues` to check that all the mergeables hold values of the same type.
530template <bool...>
531struct bool_pack {
532};
533template <class... Ts>
534using conjunction = std::is_same<bool_pack<true, Ts::value...>, bool_pack<Ts::value..., true>>;
535/// \endcond
536
537////////////////////////////////////////////////////////////////////////////////
538/// \brief Merge multiple RMergeableValue objects into one.
539/// \param[in] OutputMergeable The mergeable object where all the information
540/// will be aggregated.
541/// \param[in] InputMergeables Other mergeables containing the partial results.
542/// \returns An RMergeableValue holding the aggregated value wrapped in an
543/// `std::unique_ptr`.
544///
545/// This is the recommended way of merging multiple RMergeableValue objects.
546/// This overload takes ownership of the mergeables and gives back to the user
547/// a mergeable with the aggregated information. All the mergeables with the
548/// partial results get destroyed in the process.
549///
550/// Example usage:
551/// ~~~{.cpp}
552/// using namespace ROOT::Detail::RDF;
553/// // mh1, mh2, mh3 are std::unique_ptr<RMergeableValue<TH1D>>
554/// auto mergedptr = MergeValues(std::move(mh1), std::move(mh2), std::move(mh3));
555/// const auto &mergedhisto = mergedptr->GetValue(); // Final merged histogram
556/// // Do stuff with it
557/// mergedhisto.Draw();
558/// ~~~
559template <typename T, typename... Ts>
560std::unique_ptr<RMergeableValue<T>> MergeValues(std::unique_ptr<RMergeableValue<T>> OutputMergeable,
561 std::unique_ptr<RMergeableValue<Ts>>... InputMergeables)
562{
563 // Check all mergeables have the same template type
564 static_assert(conjunction<std::is_same<Ts, T>...>::value, "Values must all be of the same type.");
565
566 // Using dummy array initialization inspired by https://stackoverflow.com/a/25683817
567 using expander = int[];
568 // Cast to void to suppress unused-value warning in Clang
569 (void)expander{0, (OutputMergeable->Merge(*InputMergeables), 0)...};
570
571 return OutputMergeable;
572}
573
574////////////////////////////////////////////////////////////////////////////////
575/// \brief Merge multiple RMergeableValue objects into one.
576/// \param[in,out] OutputMergeable The mergeable object where all the
577/// information will be aggregated.
578/// \param[in] InputMergeables Other mergeables containing the partial results.
579///
580/// This overload modifies the mergeable objects in-place. The ownership is left
581/// to the caller. The first argument to the function will get all the
582/// values contained in the other arguments merged into itself. This is a
583/// convenience overload introduced for the ROOT Python API.
584///
585/// Example usage:
586/// ~~~{.cpp}
587/// // mh1, mh2, mh3 are std::unique_ptr<RMergeableValue<TH1D>>
588/// ROOT::Detail::RDF::MergeValues(*mh1, *mh2, *mh3);
589/// const auto &mergedhisto = mh1->GetValue(); // Final merged histogram
590/// // Do stuff with it
591/// mergedhisto.Draw();
592/// ~~~
593template <typename T, typename... Ts>
594void MergeValues(RMergeableValue<T> &OutputMergeable, const RMergeableValue<Ts> &... InputMergeables)
595{
596 // Check all mergeables are of the same type
597 static_assert(conjunction<std::is_same<Ts, T>...>::value, "Values must all be of the same type.");
598
599 // Using dummy array initialization inspired by https://stackoverflow.com/a/25683817
600 using expander = int[];
601 // Cast to void to suppress unused-value warning in Clang
602 (void)expander{0, (OutputMergeable.Merge(InputMergeables), 0)...};
603}
604} // namespace RDF
605} // namespace Detail
606} // namespace ROOT
607
608#endif // ROOT_RDF_RMERGEABLEVALUE
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
double Double_t
Definition RtypesCore.h:59
unsigned long long ULong64_t
Definition RtypesCore.h:81
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
auto DoMerge(const RMergeableFill< U > &other, double) -> decltype(this->fValue.Merge(std::vector< U * >{}), void())
auto DoMerge(const RMergeableFill< U > &other, int) -> decltype(((U &) this->fValue).Merge((TCollection *) nullptr), void())
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.
Collection abstract base class.
Definition TCollection.h:65
A doubly linked list.
Definition TList.h:38
virtual void Add(TObject *obj)
Definition TList.h:81
#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