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