Logo ROOT  
Reference Guide
RVec.hxx
Go to the documentation of this file.
1 // Author: Enrico Guiraud, Enric Tejedor, Danilo Piparo CERN 01/2018
2 
3 /*************************************************************************
4  * Copyright (C) 1995-2018, 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_RVEC
12 #define ROOT_RVEC
13 
14 #ifdef _WIN32
15  #ifndef M_PI
16  #ifndef _USE_MATH_DEFINES
17  #define _USE_MATH_DEFINES
18  #endif
19  #include <math.h>
20  #undef _USE_MATH_DEFINES
21  #endif
22  #define _VECOPS_USE_EXTERN_TEMPLATES false
23 #else
24  #define _VECOPS_USE_EXTERN_TEMPLATES true
25 #endif
26 
27 #include <ROOT/RAdoptAllocator.hxx>
29 #include <ROOT/RStringView.hxx>
30 #include <TError.h> // R__ASSERT
31 #include <ROOT/TypeTraits.hxx>
32 
33 #include <algorithm>
34 #include <cmath>
35 #include <numeric> // for inner_product
36 #include <sstream>
37 #include <stdexcept>
38 #include <type_traits>
39 #include <vector>
40 #include <utility>
41 #include <tuple>
42 
43 #ifdef R__HAS_VDT
44 #include <vdt/vdtMath.h>
45 #endif
46 
47 
48 namespace ROOT {
49 
50 namespace VecOps {
51 template<typename T>
52 class RVec;
53 }
54 
55 namespace Detail {
56 namespace VecOps {
57 
58 template<typename T>
60 
61 template <typename... T>
62 std::size_t GetVectorsSize(std::string_view id, const RVec<T> &... vs)
63 {
64  constexpr const auto nArgs = sizeof...(T);
65  const std::size_t sizes[] = {vs.size()...};
66  if (nArgs > 1) {
67  for (auto i = 1UL; i < nArgs; i++) {
68  if (sizes[0] == sizes[i])
69  continue;
70  std::string msg(id);
71  msg += ": input RVec instances have different lengths!";
72  throw std::runtime_error(msg);
73  }
74  }
75  return sizes[0];
76 }
77 
78 template <typename F, typename... T>
79 auto MapImpl(F &&f, const RVec<T> &... vs) -> RVec<decltype(f(vs[0]...))>
80 {
81  const auto size = GetVectorsSize("Map", vs...);
82  RVec<decltype(f(vs[0]...))> ret(size);
83 
84  for (auto i = 0UL; i < size; i++)
85  ret[i] = f(vs[i]...);
86 
87  return ret;
88 }
89 
90 template <typename Tuple_t, std::size_t... Is>
91 auto MapFromTuple(Tuple_t &&t, std::index_sequence<Is...>)
92  -> decltype(MapImpl(std::get<std::tuple_size<Tuple_t>::value - 1>(t), std::get<Is>(t)...))
93 {
94  constexpr const auto tupleSizeM1 = std::tuple_size<Tuple_t>::value - 1;
95  return MapImpl(std::get<tupleSizeM1>(t), std::get<Is>(t)...);
96 }
97 
98 }
99 }
100 
101 namespace Internal {
102 namespace VecOps {
103 
104 // We use this helper to workaround a limitation of compilers such as
105 // gcc 4.8 amd clang on osx 10.14 for which std::vector<bool>::emplace_back
106 // is not defined.
107 template <typename T, typename... Args>
108 void EmplaceBack(T &v, Args &&... args)
109 {
110  v.emplace_back(std::forward<Args>(args)...);
111 }
112 
113 template <typename... Args>
114 void EmplaceBack(std::vector<bool> &v, Args &&... args)
115 {
116  v.push_back(std::forward<Args>(args)...);
117 }
118 
119 } // End of VecOps NS
120 } // End of Internal NS
121 
122 namespace VecOps {
123 
124 // Note that we open here with @{ the Doxygen group vecops and it is
125 // closed again at the end of the C++ namespace VecOps
126 /**
127  * \defgroup vecops VecOps
128  * A "std::vector"-like collection of values implementing handy operation to analyse them
129  * @{
130 */
131 
132 // clang-format off
133 /**
134 \class ROOT::VecOps::RVec
135 \brief A "std::vector"-like collection of values implementing handy operation to analyse them
136 \tparam T The type of the contained objects
137 
138 A RVec is a container designed to make analysis of values' collections fast and easy.
139 Its storage is contiguous in memory and its interface is designed such to resemble to the one
140 of the stl vector. In addition the interface features methods and external functions to ease
141 the manipulation and analysis of the data in the RVec.
142 
143 \htmlonly
144 <a href="https://doi.org/10.5281/zenodo.1253756"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.1253756.svg" alt="DOI"></a>
145 \endhtmlonly
146 
147 ## Table of Contents
148 - [Example](\ref example)
149 - [Owning and adopting memory](\ref owningandadoptingmemory)
150 - [Sorting and manipulation of indices](\ref sorting)
151 - [Usage in combination with RDataFrame](\ref usagetdataframe)
152 - [Reference for the RVec class](\ref RVecdoxyref)
153 
154 Also see the [reference for RVec helper functions](https://root.cern/doc/master/namespaceROOT_1_1VecOps.html).
155 
156 \anchor example
157 ## Example
158 Suppose to have an event featuring a collection of muons with a certain pseudorapidity,
159 momentum and charge, e.g.:
160 ~~~{.cpp}
161 std::vector<short> mu_charge {1, 1, -1, -1, -1, 1, 1, -1};
162 std::vector<float> mu_pt {56, 45, 32, 24, 12, 8, 7, 6.2};
163 std::vector<float> mu_eta {3.1, -.2, -1.1, 1, 4.1, 1.6, 2.4, -.5};
164 ~~~
165 Suppose you want to extract the transverse momenta of the muons satisfying certain
166 criteria, for example consider only negatively charged muons with a pseudorapidity
167 smaller or equal to 2 and with a transverse momentum greater than 10 GeV.
168 Such a selection would require, among the other things, the management of an explicit
169 loop, for example:
170 ~~~{.cpp}
171 std::vector<float> goodMuons_pt;
172 const auto size = mu_charge.size();
173 for (size_t i=0; i < size; ++i) {
174  if (mu_pt[i] > 10 && abs(mu_eta[i]) <= 2. && mu_charge[i] == -1) {
175  goodMuons_pt.emplace_back(mu_pt[i]);
176  }
177 }
178 ~~~
179 These operations become straightforward with RVec - we just need to *write what
180 we mean*:
181 ~~~{.cpp}
182 auto goodMuons_pt = mu_pt[ (mu_pt > 10.f && abs(mu_eta) <= 2.f && mu_charge == -1) ]
183 ~~~
184 Now the clean collection of transverse momenta can be used within the rest of the data analysis, for
185 example to fill a histogram.
186 
187 \anchor owningandadoptingmemory
188 ## Owning and adopting memory
189 RVec has contiguous memory associated to it. It can own it or simply adopt it. In the latter case,
190 it can be constructed with the address of the memory associated to it and its length. For example:
191 ~~~{.cpp}
192 std::vector<int> myStlVec {1,2,3};
193 RVec<int> myRVec(myStlVec.data(), myStlVec.size());
194 ~~~
195 In this case, the memory associated to myStlVec and myRVec is the same, myRVec simply "adopted it".
196 If any method which implies a re-allocation is called, e.g. *emplace_back* or *resize*, the adopted
197 memory is released and new one is allocated. The previous content is copied in the new memory and
198 preserved.
199 
200 \anchor sorting
201 ## Sorting and manipulation of indices
202 
203 ### Sorting
204 RVec complies to the STL interfaces when it comes to iterations. As a result, standard algorithms
205 can be used, for example sorting:
206 ~~~{.cpp}
207 RVec<double> v{6., 4., 5.};
208 std::sort(v.begin(), v.end());
209 ~~~
210 
211 For convinience, helpers are provided too:
212 ~~~{.cpp}
213 auto sorted_v = Sort(v);
214 auto reversed_v = Reverse(v);
215 ~~~
216 
217 ### Manipulation of indices
218 
219 It is also possible to manipulated the RVecs acting on their indices. For example,
220 the following syntax
221 ~~~{.cpp}
222 RVec<double> v0 {9., 7., 8.};
223 auto v1 = Take(v0, {1, 2, 0});
224 ~~~
225 will yield a new RVec<double> the content of which is the first, second and zeroth element of
226 v0, i.e. `{7., 8., 9.}`.
227 
228 The `Argsort` helper extracts the indices which order the content of a `RVec`. For example,
229 this snippet accomplish in a more expressive way what we just achieved:
230 ~~~{.cpp}
231 auto v1_indices = Argsort(v0); // The content of v1_indices is {1, 2, 0}.
232 v1 = Take(v0, v1_indices);
233 ~~~
234 
235 The `Take` utility allows to extract portions of the `RVec`. The content to be *taken*
236 can be specified with an `RVec` of indices or an integer. If the integer is negative,
237 elements will be picked starting from the end of the container:
238 ~~~{.cpp}
239 RVec<float> vf {1.f, 2.f, 3.f, 4.f};
240 auto vf_1 = Take(vf, {1, 3}); // The content is {2.f, 4.f}
241 auto vf_2 = Take(vf, 2); // The content is {1.f, 2.f}
242 auto vf_3 = Take(vf, -3); // The content is {2.f, 3.f, 4.f}
243 ~~~
244 
245 \anchor usagetdataframe
246 ## Usage in combination with RDataFrame
247 RDataFrame leverages internally RVecs. Suppose to have a dataset stored in a
248 TTree which holds these columns (here we choose C arrays to represent the
249 collections, they could be as well std::vector instances):
250 ~~~{.bash}
251  nPart "nPart/I" An integer representing the number of particles
252  px "px[nPart]/D" The C array of the particles' x component of the momentum
253  py "py[nPart]/D" The C array of the particles' y component of the momentum
254  E "E[nPart]/D" The C array of the particles' Energy
255 ~~~
256 Suppose you'd like to plot in a histogram the transverse momenta of all particles
257 for which the energy is greater than 200 MeV.
258 The code required would just be:
259 ~~~{.cpp}
260 RDataFrame d("mytree", "myfile.root");
261 using doubles = RVec<double>;
262 auto cutPt = [](doubles &pxs, doubles &pys, doubles &Es) {
263  auto all_pts = sqrt(pxs * pxs + pys * pys);
264  auto good_pts = all_pts[Es > 200.];
265  return good_pts;
266  };
267 
268 auto hpt = d.Define("pt", cutPt, {"px", "py", "E"})
269  .Histo1D("pt");
270 hpt->Draw();
271 ~~~
272 And if you'd like to express your selection as a string:
273 ~~~{.cpp}
274 RDataFrame d("mytree", "myfile.root");
275 auto hpt = d.Define("pt", "sqrt(pxs * pxs + pys * pys)[E>200]")
276  .Histo1D("pt");
277 hpt->Draw();
278 ~~~
279 <a name="RVecdoxyref"></a>
280 **/
281 // clang-format on
282 template <typename T>
283 class RVec {
284  // Here we check if T is a bool. This is done in order to decide what type
285  // to use as a storage. If T is anything but bool, we use a vector<T, RAdoptAllocator<T>>.
286  // If T is a bool, we opt for a plain vector<bool> otherwise we'll not be able
287  // to write the data type given the shortcomings of TCollectionProxy design.
288  static constexpr const auto IsVecBool = std::is_same<bool, T>::value;
289 public:
290  using Impl_t = typename std::conditional<IsVecBool, std::vector<bool>, std::vector<T, ::ROOT::Detail::VecOps::RAdoptAllocator<T>>>::type;
291  using value_type = typename Impl_t::value_type;
292  using size_type = typename Impl_t::size_type;
293  using difference_type = typename Impl_t::difference_type;
294  using reference = typename Impl_t::reference;
295  using const_reference = typename Impl_t::const_reference;
296  using pointer = typename Impl_t::pointer;
297  using const_pointer = typename Impl_t::const_pointer;
298  // The data_t and const_data_t types are chosen to be void in case T is a bool.
299  // This way we can as elegantly as in the STL return void upon calling the data() method.
302  using iterator = typename Impl_t::iterator;
303  using const_iterator = typename Impl_t::const_iterator;
304  using reverse_iterator = typename Impl_t::reverse_iterator;
305  using const_reverse_iterator = typename Impl_t::const_reverse_iterator;
306 
307 private:
309 
310 public:
311  // constructors
312  RVec() {}
313 
314  explicit RVec(size_type count) : fData(count) {}
315 
316  RVec(size_type count, const T &value) : fData(count, value) {}
317 
318  RVec(const RVec<T> &v) : fData(v.fData) {}
319 
320  RVec(RVec<T> &&v) : fData(std::move(v.fData)) {}
321 
322  RVec(const std::vector<T> &v) : fData(v.cbegin(), v.cend()) {}
323 
324  RVec(pointer p, size_type n) : fData(n, T(), ROOT::Detail::VecOps::RAdoptAllocator<T>(p)) {}
325 
326  template <class InputIt>
327  RVec(InputIt first, InputIt last) : fData(first, last) {}
328 
329  RVec(std::initializer_list<T> init) : fData(init) {}
330 
331  // assignment
333  {
334  fData = v.fData;
335  return *this;
336  }
337 
339  {
340  std::swap(fData, v.fData);
341  return *this;
342  }
343 
344  RVec<T> &operator=(std::initializer_list<T> ilist)
345  {
346  fData = ilist;
347  return *this;
348  }
349 
350  // conversion
351  template <typename U, typename = std::enable_if<std::is_convertible<T, U>::value>>
352  operator RVec<U>() const
353  {
354  RVec<U> ret(size());
355  std::copy(begin(), end(), ret.begin());
356  return ret;
357  }
358 
359  // accessors
360  reference at(size_type pos) { return fData.at(pos); }
361  const_reference at(size_type pos) const { return fData.at(pos); }
362  /// No exception thrown. The user specifies the desired value in case the RVec is shorter than `pos`.
363  value_type at(size_type pos, value_type fallback) { return pos < fData.size() ? fData[pos] : fallback; }
364  /// No exception thrown. The user specifies the desired value in case the RVec is shorter than `pos`.
365  value_type at(size_type pos, value_type fallback) const { return pos < fData.size() ? fData[pos] : fallback; }
366  reference operator[](size_type pos) { return fData[pos]; }
367  const_reference operator[](size_type pos) const { return fData[pos]; }
368 
369  template <typename V, typename = std::enable_if<std::is_convertible<V, bool>::value>>
370  RVec operator[](const RVec<V> &conds) const
371  {
372  const size_type n = conds.size();
373 
374  if (n != size())
375  throw std::runtime_error("Cannot index RVec with condition vector of different size");
376 
377  RVec<T> ret;
378  ret.reserve(n);
379  for (size_type i = 0; i < n; ++i)
380  if (conds[i])
381  ret.emplace_back(fData[i]);
382  return ret;
383  }
384 
385  reference front() { return fData.front(); }
386  const_reference front() const { return fData.front(); }
387  reference back() { return fData.back(); }
388  const_reference back() const { return fData.back(); }
389  data_t data() noexcept { return fData.data(); }
390  const_data_t data() const noexcept { return fData.data(); }
391  // iterators
392  iterator begin() noexcept { return fData.begin(); }
393  const_iterator begin() const noexcept { return fData.begin(); }
394  const_iterator cbegin() const noexcept { return fData.cbegin(); }
395  iterator end() noexcept { return fData.end(); }
396  const_iterator end() const noexcept { return fData.end(); }
397  const_iterator cend() const noexcept { return fData.cend(); }
398  reverse_iterator rbegin() noexcept { return fData.rbegin(); }
399  const_reverse_iterator rbegin() const noexcept { return fData.rbegin(); }
400  const_reverse_iterator crbegin() const noexcept { return fData.crbegin(); }
401  reverse_iterator rend() noexcept { return fData.rend(); }
402  const_reverse_iterator rend() const noexcept { return fData.rend(); }
403  const_reverse_iterator crend() const noexcept { return fData.crend(); }
404  // capacity
405  bool empty() const noexcept { return fData.empty(); }
406  size_type size() const noexcept { return fData.size(); }
407  size_type max_size() const noexcept { return fData.size(); }
408  void reserve(size_type new_cap) { fData.reserve(new_cap); }
409  size_type capacity() const noexcept { return fData.capacity(); }
410  void shrink_to_fit() { fData.shrink_to_fit(); };
411  // modifiers
412  void clear() noexcept { fData.clear(); }
413  iterator erase(iterator pos) { return fData.erase(pos); }
414  iterator erase(iterator first, iterator last) { return fData.erase(first, last); }
415  void push_back(T &&value) { fData.push_back(std::forward<T>(value)); }
416  void push_back(const value_type& value) { fData.push_back(value); };
417  template <class... Args>
418  reference emplace_back(Args &&... args)
419  {
420  ROOT::Internal::VecOps::EmplaceBack(fData, std::forward<Args>(args)...);
421  return fData.back();
422  }
423  /// This method is intended only for arithmetic types unlike the std::vector
424  /// corresponding one which is generic.
425  template<typename U = T, typename std::enable_if<std::is_arithmetic<U>::value, int>* = nullptr>
427  {
428  return fData.emplace(pos, value);
429  }
430  void pop_back() { fData.pop_back(); }
431  void resize(size_type count) { fData.resize(count); }
432  void resize(size_type count, const value_type &value) { fData.resize(count, value); }
433  void swap(RVec<T> &other) { std::swap(fData, other.fData); }
434 };
435 
436 ///@name RVec Unary Arithmetic Operators
437 ///@{
438 
439 #define RVEC_UNARY_OPERATOR(OP) \
440 template <typename T> \
441 RVec<T> operator OP(const RVec<T> &v) \
442 { \
443  RVec<T> ret(v); \
444  for (auto &x : ret) \
445  x = OP x; \
446 return ret; \
447 } \
448 
453 #undef RVEC_UNARY_OPERATOR
454 
455 ///@}
456 ///@name RVec Binary Arithmetic Operators
457 ///@{
458 
459 #define ERROR_MESSAGE(OP) \
460  "Cannot call operator " #OP " on vectors of different sizes."
461 
462 #define RVEC_BINARY_OPERATOR(OP) \
463 template <typename T0, typename T1> \
464 auto operator OP(const RVec<T0> &v, const T1 &y) \
465  -> RVec<decltype(v[0] OP y)> \
466 { \
467  RVec<decltype(v[0] OP y)> ret(v.size()); \
468  auto op = [&y](const T0 &x) { return x OP y; }; \
469  std::transform(v.begin(), v.end(), ret.begin(), op); \
470  return ret; \
471 } \
472  \
473 template <typename T0, typename T1> \
474 auto operator OP(const T0 &x, const RVec<T1> &v) \
475  -> RVec<decltype(x OP v[0])> \
476 { \
477  RVec<decltype(x OP v[0])> ret(v.size()); \
478  auto op = [&x](const T1 &y) { return x OP y; }; \
479  std::transform(v.begin(), v.end(), ret.begin(), op); \
480  return ret; \
481 } \
482  \
483 template <typename T0, typename T1> \
484 auto operator OP(const RVec<T0> &v0, const RVec<T1> &v1) \
485  -> RVec<decltype(v0[0] OP v1[0])> \
486 { \
487  if (v0.size() != v1.size()) \
488  throw std::runtime_error(ERROR_MESSAGE(OP)); \
489  \
490  RVec<decltype(v0[0] OP v1[0])> ret(v0.size()); \
491  auto op = [](const T0 &x, const T1 &y) { return x OP y; }; \
492  std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), op); \
493  return ret; \
494 } \
495 
504 #undef RVEC_BINARY_OPERATOR
505 
506 ///@}
507 ///@name RVec Assignment Arithmetic Operators
508 ///@{
509 
510 #define RVEC_ASSIGNMENT_OPERATOR(OP) \
511 template <typename T0, typename T1> \
512 RVec<T0>& operator OP(RVec<T0> &v, const T1 &y) \
513 { \
514  auto op = [&y](T0 &x) { return x OP y; }; \
515  std::transform(v.begin(), v.end(), v.begin(), op); \
516  return v; \
517 } \
518  \
519 template <typename T0, typename T1> \
520 RVec<T0>& operator OP(RVec<T0> &v0, const RVec<T1> &v1) \
521 { \
522  if (v0.size() != v1.size()) \
523  throw std::runtime_error(ERROR_MESSAGE(OP)); \
524  \
525  auto op = [](T0 &x, const T1 &y) { return x OP y; }; \
526  std::transform(v0.begin(), v0.end(), v1.begin(), v0.begin(), op); \
527  return v0; \
528 } \
529 
540 #undef RVEC_ASSIGNMENT_OPERATOR
541 
542 ///@}
543 ///@name RVec Comparison and Logical Operators
544 ///@{
545 
546 #define RVEC_LOGICAL_OPERATOR(OP) \
547 template <typename T0, typename T1> \
548 auto operator OP(const RVec<T0> &v, const T1 &y) \
549  -> RVec<int> /* avoid std::vector<bool> */ \
550 { \
551  RVec<int> ret(v.size()); \
552  auto op = [y](const T0 &x) -> int { return x OP y; }; \
553  std::transform(v.begin(), v.end(), ret.begin(), op); \
554  return ret; \
555 } \
556  \
557 template <typename T0, typename T1> \
558 auto operator OP(const T0 &x, const RVec<T1> &v) \
559  -> RVec<int> /* avoid std::vector<bool> */ \
560 { \
561  RVec<int> ret(v.size()); \
562  auto op = [x](const T1 &y) -> int { return x OP y; }; \
563  std::transform(v.begin(), v.end(), ret.begin(), op); \
564  return ret; \
565 } \
566  \
567 template <typename T0, typename T1> \
568 auto operator OP(const RVec<T0> &v0, const RVec<T1> &v1) \
569  -> RVec<int> /* avoid std::vector<bool> */ \
570 { \
571  if (v0.size() != v1.size()) \
572  throw std::runtime_error(ERROR_MESSAGE(OP)); \
573  \
574  RVec<int> ret(v0.size()); \
575  auto op = [](const T0 &x, const T1 &y) -> int { return x OP y; }; \
576  std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), op); \
577  return ret; \
578 } \
579 
588 #undef RVEC_LOGICAL_OPERATOR
589 
590 ///@}
591 ///@name RVec Standard Mathematical Functions
592 ///@{
593 
594 /// \cond
595 template <typename T> struct PromoteTypeImpl;
596 
597 template <> struct PromoteTypeImpl<float> { using Type = float; };
598 template <> struct PromoteTypeImpl<double> { using Type = double; };
599 template <> struct PromoteTypeImpl<long double> { using Type = long double; };
600 
601 template <typename T> struct PromoteTypeImpl { using Type = double; };
602 
603 template <typename T>
604 using PromoteType = typename PromoteTypeImpl<T>::Type;
605 
606 template <typename U, typename V>
607 using PromoteTypes = decltype(PromoteType<U>() + PromoteType<V>());
608 
609 /// \endcond
610 
611 #define RVEC_UNARY_FUNCTION(NAME, FUNC) \
612  template <typename T> \
613  RVec<PromoteType<T>> NAME(const RVec<T> &v) \
614  { \
615  RVec<PromoteType<T>> ret(v.size()); \
616  auto f = [](const T &x) { return FUNC(x); }; \
617  std::transform(v.begin(), v.end(), ret.begin(), f); \
618  return ret; \
619  }
620 
621 #define RVEC_BINARY_FUNCTION(NAME, FUNC) \
622  template <typename T0, typename T1> \
623  RVec<PromoteTypes<T0, T1>> NAME(const T0 &x, const RVec<T1> &v) \
624  { \
625  RVec<PromoteTypes<T0, T1>> ret(v.size()); \
626  auto f = [&x](const T1 &y) { return FUNC(x, y); }; \
627  std::transform(v.begin(), v.end(), ret.begin(), f); \
628  return ret; \
629  } \
630  \
631  template <typename T0, typename T1> \
632  RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v, const T1 &y) \
633  { \
634  RVec<PromoteTypes<T0, T1>> ret(v.size()); \
635  auto f = [&y](const T1 &x) { return FUNC(x, y); }; \
636  std::transform(v.begin(), v.end(), ret.begin(), f); \
637  return ret; \
638  } \
639  \
640  template <typename T0, typename T1> \
641  RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v0, const RVec<T1> &v1) \
642  { \
643  if (v0.size() != v1.size()) \
644  throw std::runtime_error(ERROR_MESSAGE(NAME)); \
645  \
646  RVec<PromoteTypes<T0, T1>> ret(v0.size()); \
647  auto f = [](const T0 &x, const T1 &y) { return FUNC(x, y); }; \
648  std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), f); \
649  return ret; \
650  } \
651 
652 #define RVEC_STD_UNARY_FUNCTION(F) RVEC_UNARY_FUNCTION(F, std::F)
653 #define RVEC_STD_BINARY_FUNCTION(F) RVEC_BINARY_FUNCTION(F, std::F)
654 
658 RVEC_STD_BINARY_FUNCTION(remainder)
659 
663 
668 
673 
681 
688 
695 
700 #undef RVEC_STD_UNARY_FUNCTION
701 
702 ///@}
703 ///@name RVec Fast Mathematical Functions with Vdt
704 ///@{
705 
706 #ifdef R__HAS_VDT
707 #define RVEC_VDT_UNARY_FUNCTION(F) RVEC_UNARY_FUNCTION(F, vdt::F)
708 
709 RVEC_VDT_UNARY_FUNCTION(fast_expf)
710 RVEC_VDT_UNARY_FUNCTION(fast_logf)
711 RVEC_VDT_UNARY_FUNCTION(fast_sinf)
712 RVEC_VDT_UNARY_FUNCTION(fast_cosf)
713 RVEC_VDT_UNARY_FUNCTION(fast_tanf)
714 RVEC_VDT_UNARY_FUNCTION(fast_asinf)
715 RVEC_VDT_UNARY_FUNCTION(fast_acosf)
716 RVEC_VDT_UNARY_FUNCTION(fast_atanf)
717 
718 RVEC_VDT_UNARY_FUNCTION(fast_exp)
719 RVEC_VDT_UNARY_FUNCTION(fast_log)
720 RVEC_VDT_UNARY_FUNCTION(fast_sin)
721 RVEC_VDT_UNARY_FUNCTION(fast_cos)
722 RVEC_VDT_UNARY_FUNCTION(fast_tan)
723 RVEC_VDT_UNARY_FUNCTION(fast_asin)
724 RVEC_VDT_UNARY_FUNCTION(fast_acos)
725 RVEC_VDT_UNARY_FUNCTION(fast_atan)
726 #undef RVEC_VDT_UNARY_FUNCTION
727 
728 #endif // R__HAS_VDT
729 
730 #undef RVEC_UNARY_FUNCTION
731 
732 ///@}
733 
734 /// Inner product
735 ///
736 /// Example code, at the ROOT prompt:
737 /// ~~~{.cpp}
738 /// using namespace ROOT::VecOps;
739 /// RVec<float> v1 {1., 2., 3.};
740 /// RVec<float> v2 {4., 5., 6.};
741 /// auto v1_dot_v2 = Dot(v1, v2);
742 /// v1_dot_v2
743 /// // (float) 32.f
744 /// ~~~
745 template <typename T, typename V>
746 auto Dot(const RVec<T> &v0, const RVec<V> &v1) -> decltype(v0[0] * v1[0])
747 {
748  if (v0.size() != v1.size())
749  throw std::runtime_error("Cannot compute inner product of vectors of different sizes");
750  return std::inner_product(v0.begin(), v0.end(), v1.begin(), decltype(v0[0] * v1[0])(0));
751 }
752 
753 /// Sum elements of an RVec
754 ///
755 /// Example code, at the ROOT prompt:
756 /// ~~~{.cpp}
757 /// using namespace ROOT::VecOps;
758 /// RVec<float> v {1.f, 2.f, 3.f};
759 /// auto v_sum = Sum(v);
760 /// v_sum
761 /// // (float) 6.f
762 /// ~~~
763 template <typename T>
764 T Sum(const RVec<T> &v)
765 {
766  return std::accumulate(v.begin(), v.end(), T(0));
767 }
768 
769 /// Get the mean of the elements of an RVec
770 ///
771 /// The return type is a double precision floating point number.
772 /// Example code, at the ROOT prompt:
773 /// ~~~{.cpp}
774 /// using namespace ROOT::VecOps;
775 /// RVec<float> v {1.f, 2.f, 4.f};
776 /// auto v_mean = Mean(v);
777 /// v_mean
778 /// // (double) 2.3333333
779 /// ~~~
780 template <typename T>
781 double Mean(const RVec<T> &v)
782 {
783  if (v.empty()) return 0.;
784  return double(Sum(v)) / v.size();
785 }
786 
787 /// Get the greatest element of an RVec
788 ///
789 /// Example code, at the ROOT prompt:
790 /// ~~~~{.cpp}
791 /// using namespace ROOT::VecOps;
792 /// RVec<float> v {1.f, 2.f, 4.f};
793 /// auto v_max = Max(v)
794 /// v_max
795 /// (float) 4.f
796 /// ~~~~
797 template <typename T>
798 T Max(const RVec<T> &v)
799 {
800  return *std::max_element(v.begin(), v.end());
801 }
802 
803 /// Get the smallest element of an RVec
804 ///
805 /// Example code, at the ROOT prompt:
806 /// ~~~~{.cpp}
807 /// using namespace ROOT::VecOps;
808 /// RVec<float> v {1.f, 2.f, 4.f};
809 /// auto v_min = Min(v)
810 /// v_min
811 /// (float) 1.f
812 /// ~~~~
813 template <typename T>
814 T Min(const RVec<T> &v)
815 {
816  return *std::min_element(v.begin(), v.end());
817 }
818 
819 /// Get the index of the greatest element of an RVec
820 /// In case of multiple occurrences of the maximum values,
821 /// the index corresponding to the first occurrence is returned.
822 ///
823 /// Example code, at the ROOT prompt:
824 /// ~~~~{.cpp}
825 /// using namespace ROOT::VecOps;
826 /// RVec<float> v {1.f, 2.f, 4.f};
827 /// auto v_argmax = ArgMax(v);
828 /// v_argmax
829 /// // (int) 2
830 /// ~~~~
831 template <typename T>
832 std::size_t ArgMax(const RVec<T> &v)
833 {
834  return std::distance(v.begin(), std::max_element(v.begin(), v.end()));
835 }
836 
837 /// Get the index of the smallest element of an RVec
838 /// In case of multiple occurrences of the minimum values,
839 /// the index corresponding to the first occurrence is returned.
840 ///
841 /// Example code, at the ROOT prompt:
842 /// ~~~~{.cpp}
843 /// using namespace ROOT::VecOps;
844 /// RVec<float> v {1.f, 2.f, 4.f};
845 /// auto v_argmin = ArgMin(v);
846 /// v_argmin
847 /// // (int) 0
848 /// ~~~~
849 template <typename T>
850 std::size_t ArgMin(const RVec<T> &v)
851 {
852  return std::distance(v.begin(), std::min_element(v.begin(), v.end()));
853 }
854 
855 /// Get the variance of the elements of an RVec
856 ///
857 /// The return type is a double precision floating point number.
858 /// Example code, at the ROOT prompt:
859 /// ~~~{.cpp}
860 /// using namespace ROOT::VecOps;
861 /// RVec<float> v {1.f, 2.f, 4.f};
862 /// auto v_var = Var(v);
863 /// v_var
864 /// // (double) 2.3333333
865 /// ~~~
866 template <typename T>
867 double Var(const RVec<T> &v)
868 {
869  const std::size_t size = v.size();
870  if (size < std::size_t(2)) return 0.;
871  T sum_squares(0), squared_sum(0);
872  auto pred = [&sum_squares, &squared_sum](const T& x) {sum_squares+=x*x; squared_sum+=x;};
873  std::for_each(v.begin(), v.end(), pred);
874  squared_sum *= squared_sum;
875  const auto dsize = (double) size;
876  return 1. / (dsize - 1.) * (sum_squares - squared_sum / dsize );
877 }
878 
879 /// Get the standard deviation of the elements of an RVec
880 ///
881 /// The return type is a double precision floating point number.
882 /// Example code, at the ROOT prompt:
883 /// ~~~{.cpp}
884 /// using namespace ROOT::VecOps;
885 /// RVec<float> v {1.f, 2.f, 4.f};
886 /// auto v_sd = StdDev(v);
887 /// v_sd
888 /// // (double) 1.5275252
889 /// ~~~
890 template <typename T>
891 double StdDev(const RVec<T> &v)
892 {
893  return std::sqrt(Var(v));
894 }
895 
896 /// Create new collection applying a callable to the elements of the input collection
897 ///
898 /// Example code, at the ROOT prompt:
899 /// ~~~{.cpp}
900 /// using namespace ROOT::VecOps;
901 /// RVec<float> v {1.f, 2.f, 4.f};
902 /// auto v_square = Map(v, [](float f){return f* 2.f;});
903 /// v_square
904 /// // (ROOT::VecOps::RVec<float> &) { 2.00000f, 4.00000f, 8.00000f }
905 ///
906 /// RVec<float> x({1.f, 2.f, 3.f});
907 /// RVec<float> y({4.f, 5.f, 6.f});
908 /// RVec<float> z({7.f, 8.f, 9.f});
909 /// auto mod = [](float x, float y, float z) { return sqrt(x * x + y * y + z * z); };
910 /// auto v_mod = Map(x, y, z, mod);
911 /// v_mod
912 /// // (ROOT::VecOps::RVec<float> &) { 8.12404f, 9.64365f, 11.2250f }
913 /// ~~~
914 template <typename... Args>
915 auto Map(Args &&... args)
916  -> decltype(ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...),
917  std::make_index_sequence<sizeof...(args) - 1>()))
918 {
919  /*
920  Here the strategy in order to generalise the previous implementation of Map, i.e.
921  `RVec Map(RVec, F)`, here we need to move the last parameter of the pack in first
922  position in order to be able to invoke the Map function with automatic type deduction.
923  This is achieved in two steps:
924  1. Forward as tuple the pack to MapFromTuple
925  2. Invoke the MapImpl helper which has the signature `template<...T, F> RVec MapImpl(F &&f, RVec<T>...)`
926  NOTA BENE: the signature is very heavy but it is one of the lightest ways to manage in C++11
927  to build the return type based on the template args.
928  */
929  return ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...),
930  std::make_index_sequence<sizeof...(args) - 1>());
931 }
932 
933 /// Create a new collection with the elements passing the filter expressed by the predicate
934 ///
935 /// Example code, at the ROOT prompt:
936 /// ~~~{.cpp}
937 /// using namespace ROOT::VecOps;
938 /// RVec<int> v {1, 2, 4};
939 /// auto v_even = Filter(v, [](int i){return 0 == i%2;});
940 /// v_even
941 /// // (ROOT::VecOps::RVec<int> &) { 2, 4 }
942 /// ~~~
943 template <typename T, typename F>
944 RVec<T> Filter(const RVec<T> &v, F &&f)
945 {
946  const auto thisSize = v.size();
947  RVec<T> w;
948  w.reserve(thisSize);
949  for (auto &&val : v) {
950  if (f(val))
951  w.emplace_back(val);
952  }
953  return w;
954 }
955 
956 /// Return true if any of the elements equates to true, return false otherwise.
957 ///
958 /// Example code, at the ROOT prompt:
959 /// ~~~{.cpp}
960 /// using namespace ROOT::VecOps;
961 /// RVec<int> v {0, 1, 0};
962 /// auto anyTrue = Any(v);
963 /// anyTrue
964 /// // (bool) true
965 /// ~~~
966 template <typename T>
967 auto Any(const RVec<T> &v) -> decltype(v[0] == true)
968 {
969  for (auto &&e : v)
970  if (e == true)
971  return true;
972  return false;
973 }
974 
975 /// Return true if all of the elements equate to true, return false otherwise.
976 ///
977 /// Example code, at the ROOT prompt:
978 /// ~~~{.cpp}
979 /// using namespace ROOT::VecOps;
980 /// RVec<int> v {0, 1, 0};
981 /// auto allTrue = All(v);
982 /// allTrue
983 /// // (bool) false
984 /// ~~~
985 template <typename T>
986 auto All(const RVec<T> &v) -> decltype(v[0] == false)
987 {
988  for (auto &&e : v)
989  if (e == false)
990  return false;
991  return true;
992 }
993 
994 template <typename T>
995 void swap(RVec<T> &lhs, RVec<T> &rhs)
996 {
997  lhs.swap(rhs);
998 }
999 
1000 /// Return an RVec of indices that sort the input RVec
1001 ///
1002 /// Example code, at the ROOT prompt:
1003 /// ~~~{.cpp}
1004 /// using namespace ROOT::VecOps;
1005 /// RVec<double> v {2., 3., 1.};
1006 /// auto sortIndices = Argsort(v);
1007 /// // (ROOT::VecOps::RVec<unsigned long> &) { 2, 0, 1 }
1008 /// auto values = Take(v, sortIndices)
1009 /// // (ROOT::VecOps::RVec<double> &) { 1., 2., 3. }
1010 /// ~~~
1011 template <typename T>
1013 {
1014  using size_type = typename RVec<T>::size_type;
1015  RVec<size_type> i(v.size());
1016  std::iota(i.begin(), i.end(), 0);
1017  std::sort(i.begin(), i.end(), [&v](size_type i1, size_type i2) { return v[i1] < v[i2]; });
1018  return i;
1019 }
1020 
1021 /// Return an RVec of indices that sort the input RVec based on a comparison function.
1022 ///
1023 /// Example code, at the ROOT prompt:
1024 /// ~~~{.cpp}
1025 /// using namespace ROOT::VecOps;
1026 /// RVec<double> v {2., 3., 1.};
1027 /// auto sortIndices = Argsort(v, [](double x, double y) {return x > y;})
1028 /// // (ROOT::VecOps::RVec<unsigned long> &) { 1, 0, 2 }
1029 /// auto values = Take(v, sortIndices)
1030 /// // (ROOT::VecOps::RVec<double> &) { 3., 2., 1. }
1031 /// ~~~
1032 template <typename T, typename Compare>
1034 {
1035  using size_type = typename RVec<T>::size_type;
1036  RVec<size_type> i(v.size());
1037  std::iota(i.begin(), i.end(), 0);
1038  std::sort(i.begin(), i.end(),
1039  [&v, &c](size_type i1, size_type i2) { return c(v[i1], v[i2]); });
1040  return i;
1041 }
1042 
1043 /// Return elements of a vector at given indices
1044 ///
1045 /// Example code, at the ROOT prompt:
1046 /// ~~~{.cpp}
1047 /// using namespace ROOT::VecOps;
1048 /// RVec<double> v {2., 3., 1.};
1049 /// auto vTaken = Take(v, {0,2});
1050 /// vTaken
1051 /// // (ROOT::VecOps::RVec<double>) { 2.0000000, 1.0000000 }
1052 /// ~~~
1053 template <typename T>
1054 RVec<T> Take(const RVec<T> &v, const RVec<typename RVec<T>::size_type> &i)
1055 {
1056  using size_type = typename RVec<T>::size_type;
1057  const size_type isize = i.size();
1058  RVec<T> r(isize);
1059  for (size_type k = 0; k < isize; k++)
1060  r[k] = v[i[k]];
1061  return r;
1062 }
1063 
1064 /// Return first or last `n` elements of an RVec
1065 ///
1066 /// if `n > 0` and last elements if `n < 0`.
1067 ///
1068 /// Example code, at the ROOT prompt:
1069 /// ~~~{.cpp}
1070 /// using namespace ROOT::VecOps;
1071 /// RVec<double> v {2., 3., 1.};
1072 /// auto firstTwo = Take(v, 2);
1073 /// firstTwo
1074 /// // (ROOT::VecOps::RVec<double>) { 2.0000000, 3.0000000 }
1075 /// auto lastOne = Take(v, -1);
1076 /// lastOne
1077 /// // (ROOT::VecOps::RVec<double>) { 1.0000000 }
1078 /// ~~~
1079 template <typename T>
1080 RVec<T> Take(const RVec<T> &v, const int n)
1081 {
1082  using size_type = typename RVec<T>::size_type;
1083  const size_type size = v.size();
1084  const size_type absn = std::abs(n);
1085  if (absn > size) {
1086  std::stringstream ss;
1087  ss << "Try to take " << absn << " elements but vector has only size " << size << ".";
1088  throw std::runtime_error(ss.str());
1089  }
1090  RVec<T> r(absn);
1091  if (n < 0) {
1092  for (size_type k = 0; k < absn; k++)
1093  r[k] = v[size - absn + k];
1094  } else {
1095  for (size_type k = 0; k < absn; k++)
1096  r[k] = v[k];
1097  }
1098  return r;
1099 }
1100 
1101 /// Return copy of reversed vector
1102 ///
1103 /// Example code, at the ROOT prompt:
1104 /// ~~~{.cpp}
1105 /// using namespace ROOT::VecOps;
1106 /// RVec<double> v {2., 3., 1.};
1107 /// auto v_reverse = Reverse(v);
1108 /// v_reverse
1109 /// // (ROOT::VecOps::RVec<double>) { 1.0000000, 3.0000000, 2.0000000 }
1110 /// ~~~
1111 template <typename T>
1113 {
1114  RVec<T> r(v);
1115  std::reverse(r.begin(), r.end());
1116  return r;
1117 }
1118 
1119 /// Return copy of RVec with elements sorted in ascending order
1120 ///
1121 /// This helper is different from ArgSort since it does not return an RVec of indices,
1122 /// but an RVec of values.
1123 ///
1124 /// Example code, at the ROOT prompt:
1125 /// ~~~{.cpp}
1126 /// using namespace ROOT::VecOps;
1127 /// RVec<double> v {2., 3., 1.};
1128 /// auto v_sorted = Sort(v);
1129 /// v_sorted
1130 /// // (ROOT::VecOps::RVec<double>) { 1.0000000, 2.0000000, 3.0000000 }
1131 /// ~~~
1132 template <typename T>
1134 {
1135  RVec<T> r(v);
1136  std::sort(r.begin(), r.end());
1137  return r;
1138 }
1139 
1140 /// Return copy of RVec with elements sorted based on a comparison operator
1141 ///
1142 /// The comparison operator has to fullfill the same requirements of the
1143 /// predicate of by std::sort.
1144 ///
1145 ///
1146 /// This helper is different from ArgSort since it does not return an RVec of indices,
1147 /// but an RVec of values.
1148 ///
1149 /// Example code, at the ROOT prompt:
1150 /// ~~~{.cpp}
1151 /// using namespace ROOT::VecOps;
1152 /// RVec<double> v {2., 3., 1.};
1153 /// auto v_sorted = Sort(v, [](double x, double y) {return 1/x < 1/y;});
1154 /// v_sorted
1155 /// // (ROOT::VecOps::RVec<double>) { 3.0000000, 2.0000000, 1.0000000 }
1156 /// ~~~
1157 template <typename T, typename Compare>
1159 {
1160  RVec<T> r(v);
1161  std::sort(r.begin(), r.end(), std::forward<Compare>(c));
1162  return r;
1163 }
1164 
1165 /// Return the indices that represent all combinations of the elements of two
1166 /// RVecs.
1167 ///
1168 /// The type of the return value is an RVec of two RVecs containing indices.
1169 ///
1170 /// Example code, at the ROOT prompt:
1171 /// ~~~{.cpp}
1172 /// using namespace ROOT::VecOps;
1173 /// auto comb_idx = Combinations(3, 2);
1174 /// comb_idx
1175 /// // (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 0, 1, 1, 2, 2 }, { 0, 1, 0, 1, 0, 1 } }
1176 /// ~~~
1177 inline RVec<RVec<std::size_t>> Combinations(const std::size_t size1, const std::size_t size2)
1178 {
1179  using size_type = std::size_t;
1180  RVec<RVec<size_type>> r(2);
1181  r[0].resize(size1*size2);
1182  r[1].resize(size1*size2);
1183  size_type c = 0;
1184  for(size_type i=0; i<size1; i++) {
1185  for(size_type j=0; j<size2; j++) {
1186  r[0][c] = i;
1187  r[1][c] = j;
1188  c++;
1189  }
1190  }
1191  return r;
1192 }
1193 
1194 /// Return the indices that represent all combinations of the elements of two
1195 /// RVecs.
1196 ///
1197 /// The type of the return value is an RVec of two RVecs containing indices.
1198 ///
1199 /// Example code, at the ROOT prompt:
1200 /// ~~~{.cpp}
1201 /// using namespace ROOT::VecOps;
1202 /// RVec<double> v1 {1., 2., 3.};
1203 /// RVec<double> v2 {-4., -5.};
1204 /// auto comb_idx = Combinations(v1, v2);
1205 /// comb_idx
1206 /// // (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 0, 1, 1, 2, 2 }, { 0, 1,
1207 /// 0, 1, 0, 1 } }
1208 /// ~~~
1209 template <typename T1, typename T2>
1211 {
1212  return Combinations(v1.size(), v2.size());
1213 }
1214 
1215 /// Return the indices that represent all unique combinations of the
1216 /// elements of a given RVec.
1217 ///
1218 /// ~~~{.cpp}
1219 /// using namespace ROOT::VecOps;
1220 /// RVec<double> v {1., 2., 3., 4.};
1221 /// auto v_1 = Combinations(v, 1);
1222 /// v_1
1223 /// (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 1, 2, 3 } }
1224 /// auto v_2 = Combinations(v, 2);
1225 /// auto v_2
1226 /// (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 0, 0, 1, 1, 2 }, { 1, 2, 3, 2, 3, 3 } }
1227 /// auto v_3 = Combinations(v, 3);
1228 /// v_3
1229 /// (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 0, 0, 1 }, { 1, 1, 2, 2 }, { 2, 3, 3, 3 } }
1230 /// auto v_4 = Combinations(v, 4);
1231 /// v_4
1232 /// (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0 }, { 1 }, { 2 }, { 3 } }
1233 /// ~~~
1234 template <typename T>
1236 {
1237  using size_type = typename RVec<T>::size_type;
1238  const size_type s = v.size();
1239  if (n > s) {
1240  std::stringstream ss;
1241  ss << "Cannot make unique combinations of size " << n << " from vector of size " << s << ".";
1242  throw std::runtime_error(ss.str());
1243  }
1245  for(size_type k=0; k<s; k++)
1246  indices[k] = k;
1248  for(size_type k=0; k<n; k++)
1249  c[k].emplace_back(indices[k]);
1250  while (true) {
1251  bool run_through = true;
1252  long i = n - 1;
1253  for (; i>=0; i--) {
1254  if (indices[i] != i + s - n){
1255  run_through = false;
1256  break;
1257  }
1258  }
1259  if (run_through) {
1260  return c;
1261  }
1262  indices[i]++;
1263  for (long j=i+1; j<(long)n; j++)
1264  indices[j] = indices[j-1] + 1;
1265  for(size_type k=0; k<n; k++)
1266  c[k].emplace_back(indices[k]);
1267  }
1268 }
1269 
1270 /// Return the indices of the elements which are not zero
1271 ///
1272 /// Example code, at the ROOT prompt:
1273 /// ~~~{.cpp}
1274 /// using namespace ROOT::VecOps;
1275 /// RVec<double> v {2., 0., 3., 0., 1.};
1276 /// auto nonzero_idx = Nonzero(v);
1277 /// nonzero_idx
1278 /// // (ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type>) { 0, 2, 4 }
1279 /// ~~~
1280 template <typename T>
1282 {
1283  using size_type = typename RVec<T>::size_type;
1285  const auto size = v.size();
1286  r.reserve(size);
1287  for(size_type i=0; i<size; i++) {
1288  if(v[i] != 0) {
1289  r.emplace_back(i);
1290  }
1291  }
1292  return r;
1293 }
1294 
1295 /// Return the intersection of elements of two RVecs.
1296 ///
1297 /// Each element of v1 is looked up in v2 and added to the returned vector if
1298 /// found. Following, the order of v1 is preserved. If v2 is already sorted, the
1299 /// optional argument v2_is_sorted can be used to toggle of the internal sorting
1300 /// step, therewith optimising runtime.
1301 ///
1302 /// Example code, at the ROOT prompt:
1303 /// ~~~{.cpp}
1304 /// using namespace ROOT::VecOps;
1305 /// RVec<double> v1 {1., 2., 3.};
1306 /// RVec<double> v2 {-4., -5., 2., 1.};
1307 /// auto v1_intersect_v2 = Intersect(v1, v2);
1308 /// v1_intersect_v2
1309 /// // (ROOT::VecOps::RVec<double>) { 1.0000000, 2.0000000 }
1310 /// ~~~
1311 template <typename T>
1312 RVec<T> Intersect(const RVec<T>& v1, const RVec<T>& v2, bool v2_is_sorted = false)
1313 {
1314  RVec<T> v2_sorted;
1315  if (!v2_is_sorted) v2_sorted = Sort(v2);
1316  const auto v2_begin = v2_is_sorted ? v2.begin() : v2_sorted.begin();
1317  const auto v2_end = v2_is_sorted ? v2.end() : v2_sorted.end();
1318  RVec<T> r;
1319  const auto size = v1.size();
1320  r.reserve(size);
1321  using size_type = typename RVec<T>::size_type;
1322  for(size_type i=0; i<size; i++) {
1323  if (std::binary_search(v2_begin, v2_end, v1[i])) {
1324  r.emplace_back(v1[i]);
1325  }
1326  }
1327  return r;
1328 }
1329 
1330 /// Return the elements of v1 if the condition c is true and v2 if the
1331 /// condition c is false.
1332 ///
1333 /// Example code, at the ROOT prompt:
1334 /// ~~~{.cpp}
1335 /// using namespace ROOT::VecOps;
1336 /// RVec<double> v1 {1., 2., 3.};
1337 /// RVec<double> v2 {-1., -2., -3.};
1338 /// auto c = v1 > 1;
1339 /// c
1340 /// // (ROOT::VecOps::RVec<int> &) { 0, 1, 1 }
1341 /// auto if_c_v1_else_v2 = Where(c, v1, v2);
1342 /// if_c_v1_else_v2
1343 /// // (ROOT::VecOps::RVec<double> &) { -1.0000000, 2.0000000, 3.0000000 }
1344 /// ~~~
1345 template <typename T>
1346 RVec<T> Where(const RVec<int>& c, const RVec<T>& v1, const RVec<T>& v2)
1347 {
1348  using size_type = typename RVec<T>::size_type;
1349  const size_type size = c.size();
1350  RVec<T> r;
1351  r.reserve(size);
1352  for (size_type i=0; i<size; i++) {
1353  r.emplace_back(c[i] != 0 ? v1[i] : v2[i]);
1354  }
1355  return r;
1356 }
1357 
1358 /// Return the elements of v1 if the condition c is true and sets the value v2
1359 /// if the condition c is false.
1360 ///
1361 /// Example code, at the ROOT prompt:
1362 /// ~~~{.cpp}
1363 /// using namespace ROOT::VecOps;
1364 /// RVec<double> v1 {1., 2., 3.};
1365 /// double v2 = 4.;
1366 /// auto c = v1 > 1;
1367 /// c
1368 /// // (ROOT::VecOps::RVec<int> &) { 0, 1, 1 }
1369 /// auto if_c_v1_else_v2 = Where(c, v1, v2);
1370 /// if_c_v1_else_v2
1371 /// // (ROOT::VecOps::RVec<double>) { 4.0000000, 2.0000000, 3.0000000 }
1372 /// ~~~
1373 template <typename T>
1374 RVec<T> Where(const RVec<int>& c, const RVec<T>& v1, T v2)
1375 {
1376  using size_type = typename RVec<T>::size_type;
1377  const size_type size = c.size();
1378  RVec<T> r;
1379  r.reserve(size);
1380  for (size_type i=0; i<size; i++) {
1381  r.emplace_back(c[i] != 0 ? v1[i] : v2);
1382  }
1383  return r;
1384 }
1385 
1386 /// Return the elements of v2 if the condition c is false and sets the value v1
1387 /// if the condition c is true.
1388 ///
1389 /// Example code, at the ROOT prompt:
1390 /// ~~~{.cpp}
1391 /// using namespace ROOT::VecOps;
1392 /// double v1 = 4.;
1393 /// RVec<double> v2 {1., 2., 3.};
1394 /// auto c = v2 > 1;
1395 /// c
1396 /// // (ROOT::VecOps::RVec<int> &) { 0, 1, 1 }
1397 /// auto if_c_v1_else_v2 = Where(c, v1, v2);
1398 /// if_c_v1_else_v2
1399 /// // (ROOT::VecOps::RVec<double>) { 1.0000000, 4.0000000, 4.0000000 }
1400 /// ~~~
1401 template <typename T>
1402 RVec<T> Where(const RVec<int>& c, T v1, const RVec<T>& v2)
1403 {
1404  using size_type = typename RVec<T>::size_type;
1405  const size_type size = c.size();
1406  RVec<T> r;
1407  r.reserve(size);
1408  for (size_type i=0; i<size; i++) {
1409  r.emplace_back(c[i] != 0 ? v1 : v2[i]);
1410  }
1411  return r;
1412 }
1413 
1414 /// Return a vector with the value v2 if the condition c is false and sets the
1415 /// value v1 if the condition c is true.
1416 ///
1417 /// Example code, at the ROOT prompt:
1418 /// ~~~{.cpp}
1419 /// using namespace ROOT::VecOps;
1420 /// double v1 = 4.;
1421 /// double v2 = 2.;
1422 /// RVec<int> c {0, 1, 1};
1423 /// auto if_c_v1_else_v2 = Where(c, v1, v2);
1424 /// if_c_v1_else_v2
1425 /// // (ROOT::VecOps::RVec<double>) { 2.0000000, 4.0000000, 4.0000000 }
1426 /// ~~~
1427 template <typename T>
1429 {
1430  using size_type = typename RVec<T>::size_type;
1431  const size_type size = c.size();
1432  RVec<T> r;
1433  r.reserve(size);
1434  for (size_type i=0; i<size; i++) {
1435  r.emplace_back(c[i] != 0 ? v1 : v2);
1436  }
1437  return r;
1438 }
1439 
1440 /// Return the concatenation of two RVecs.
1441 ///
1442 /// Example code, at the ROOT prompt:
1443 /// ~~~{.cpp}
1444 /// using namespace ROOT::VecOps;
1445 /// RVec<float> rvf {0.f, 1.f, 2.f};
1446 /// RVec<int> rvi {7, 8, 9};
1447 /// Concatenate(rvf, rvi);
1448 /// // (ROOT::VecOps::RVec<float>) { 2.0000000, 4.0000000, 4.0000000 }
1449 /// ~~~
1452 {
1453  RVec<Common_t> res;
1454  res.reserve(v0.size() + v1.size());
1455  std::copy(v0.begin(), v0.end(), std::back_inserter(res));
1456  std::copy(v1.begin(), v1.end(), std::back_inserter(res));
1457  return res;
1458 }
1459 
1460 /// Return the angle difference \f$\Delta \phi\f$ of two scalars.
1461 ///
1462 /// The function computes the closest angle from v1 to v2 with sign and is
1463 /// therefore in the range \f$[-\pi, \pi]\f$.
1464 /// The computation is done per default in radians \f$c = \pi\f$ but can be switched
1465 /// to degrees \f$c = 180\f$.
1466 template <typename T>
1467 T DeltaPhi(T v1, T v2, const T c = M_PI)
1468 {
1469  static_assert(std::is_floating_point<T>::value,
1470  "DeltaPhi must be called with floating point values.");
1471  auto r = std::fmod(v2 - v1, 2.0 * c);
1472  if (r < -c) {
1473  r += 2.0 * c;
1474  }
1475  else if (r > c) {
1476  r -= 2.0 * c;
1477  }
1478  return r;
1479 }
1480 
1481 /// Return the angle difference \f$\Delta \phi\f$ in radians of two vectors.
1482 ///
1483 /// The function computes the closest angle from v1 to v2 with sign and is
1484 /// therefore in the range \f$[-\pi, \pi]\f$.
1485 /// The computation is done per default in radians \f$c = \pi\f$ but can be switched
1486 /// to degrees \f$c = 180\f$.
1487 template <typename T>
1488 RVec<T> DeltaPhi(const RVec<T>& v1, const RVec<T>& v2, const T c = M_PI)
1489 {
1490  using size_type = typename RVec<T>::size_type;
1491  const size_type size = v1.size();
1492  auto r = RVec<T>(size);
1493  for (size_type i = 0; i < size; i++) {
1494  r[i] = DeltaPhi(v1[i], v2[i], c);
1495  }
1496  return r;
1497 }
1498 
1499 /// Return the angle difference \f$\Delta \phi\f$ in radians of a vector and a scalar.
1500 ///
1501 /// The function computes the closest angle from v1 to v2 with sign and is
1502 /// therefore in the range \f$[-\pi, \pi]\f$.
1503 /// The computation is done per default in radians \f$c = \pi\f$ but can be switched
1504 /// to degrees \f$c = 180\f$.
1505 template <typename T>
1506 RVec<T> DeltaPhi(const RVec<T>& v1, T v2, const T c = M_PI)
1507 {
1508  using size_type = typename RVec<T>::size_type;
1509  const size_type size = v1.size();
1510  auto r = RVec<T>(size);
1511  for (size_type i = 0; i < size; i++) {
1512  r[i] = DeltaPhi(v1[i], v2, c);
1513  }
1514  return r;
1515 }
1516 
1517 /// Return the angle difference \f$\Delta \phi\f$ in radians of a scalar and a vector.
1518 ///
1519 /// The function computes the closest angle from v1 to v2 with sign and is
1520 /// therefore in the range \f$[-\pi, \pi]\f$.
1521 /// The computation is done per default in radians \f$c = \pi\f$ but can be switched
1522 /// to degrees \f$c = 180\f$.
1523 template <typename T>
1524 RVec<T> DeltaPhi(T v1, const RVec<T>& v2, const T c = M_PI)
1525 {
1526  using size_type = typename RVec<T>::size_type;
1527  const size_type size = v2.size();
1528  auto r = RVec<T>(size);
1529  for (size_type i = 0; i < size; i++) {
1530  r[i] = DeltaPhi(v1, v2[i], c);
1531  }
1532  return r;
1533 }
1534 
1535 /// Return the square of the distance on the \f$\eta\f$-\f$\phi\f$ plane (\f$\Delta R\f$) from
1536 /// the collections eta1, eta2, phi1 and phi2.
1537 ///
1538 /// The function computes \f$\Delta R^2 = (\eta_1 - \eta_2)^2 + (\phi_1 - \phi_2)^2\f$
1539 /// of the given collections eta1, eta2, phi1 and phi2. The angle \f$\phi\f$ can
1540 /// be set to radian or degrees using the optional argument c, see the documentation
1541 /// of the DeltaPhi helper.
1542 template <typename T>
1543 RVec<T> DeltaR2(const RVec<T>& eta1, const RVec<T>& eta2, const RVec<T>& phi1, const RVec<T>& phi2, const T c = M_PI)
1544 {
1545  const auto dphi = DeltaPhi(phi1, phi2, c);
1546  return (eta1 - eta2) * (eta1 - eta2) + dphi * dphi;
1547 }
1548 
1549 /// Return the distance on the \f$\eta\f$-\f$\phi\f$ plane (\f$\Delta R\f$) from
1550 /// the collections eta1, eta2, phi1 and phi2.
1551 ///
1552 /// The function computes \f$\Delta R = \sqrt{(\eta_1 - \eta_2)^2 + (\phi_1 - \phi_2)^2}\f$
1553 /// of the given collections eta1, eta2, phi1 and phi2. The angle \f$\phi\f$ can
1554 /// be set to radian or degrees using the optional argument c, see the documentation
1555 /// of the DeltaPhi helper.
1556 template <typename T>
1557 RVec<T> DeltaR(const RVec<T>& eta1, const RVec<T>& eta2, const RVec<T>& phi1, const RVec<T>& phi2, const T c = M_PI)
1558 {
1559  return sqrt(DeltaR2(eta1, eta2, phi1, phi2, c));
1560 }
1561 
1562 /// Return the distance on the \f$\eta\f$-\f$\phi\f$ plane (\f$\Delta R\f$) from
1563 /// the scalars eta1, eta2, phi1 and phi2.
1564 ///
1565 /// The function computes \f$\Delta R = \sqrt{(\eta_1 - \eta_2)^2 + (\phi_1 - \phi_2)^2}\f$
1566 /// of the given scalars eta1, eta2, phi1 and phi2. The angle \f$\phi\f$ can
1567 /// be set to radian or degrees using the optional argument c, see the documentation
1568 /// of the DeltaPhi helper.
1569 template <typename T>
1570 T DeltaR(T eta1, T eta2, T phi1, T phi2, const T c = M_PI)
1571 {
1572  const auto dphi = DeltaPhi(phi1, phi2, c);
1573  return std::sqrt((eta1 - eta2) * (eta1 - eta2) + dphi * dphi);
1574 }
1575 
1576 /// Return the invariant mass of two particles given the collections of the quantities
1577 /// transverse momentum (pt), rapidity (eta), azimuth (phi) and mass.
1578 ///
1579 /// The function computes the invariant mass of two particles with the four-vectors
1580 /// (pt1, eta2, phi1, mass1) and (pt2, eta2, phi2, mass2).
1581 template <typename T>
1583  const RVec<T>& pt1, const RVec<T>& eta1, const RVec<T>& phi1, const RVec<T>& mass1,
1584  const RVec<T>& pt2, const RVec<T>& eta2, const RVec<T>& phi2, const RVec<T>& mass2)
1585 {
1586  std::size_t size = pt1.size();
1587 
1588  R__ASSERT(eta1.size() == size && phi1.size() == size && mass1.size() == size);
1589  R__ASSERT(pt2.size() == size && phi2.size() == size && mass2.size() == size);
1590 
1591  RVec<T> inv_masses(size);
1592 
1593  for (std::size_t i = 0u; i < size; ++i) {
1594  // Conversion from (pt, eta, phi, mass) to (x, y, z, e) coordinate system
1595  const auto x1 = pt1[i] * std::cos(phi1[i]);
1596  const auto y1 = pt1[i] * std::sin(phi1[i]);
1597  const auto z1 = pt1[i] * std::sinh(eta1[i]);
1598  const auto e1 = std::sqrt(x1 * x1 + y1 * y1 + z1 * z1 + mass1[i] * mass1[i]);
1599 
1600  const auto x2 = pt2[i] * std::cos(phi2[i]);
1601  const auto y2 = pt2[i] * std::sin(phi2[i]);
1602  const auto z2 = pt2[i] * std::sinh(eta2[i]);
1603  const auto e2 = std::sqrt(x2 * x2 + y2 * y2 + z2 * z2 + mass2[i] * mass2[i]);
1604 
1605  // Addition of particle four-vector elements
1606  const auto e = e1 + e2;
1607  const auto x = x1 + x2;
1608  const auto y = y1 + y2;
1609  const auto z = z1 + z2;
1610 
1611  inv_masses[i] = std::sqrt(e * e - x * x - y * y - z * z);
1612  }
1613 
1614  // Return invariant mass with (+, -, -, -) metric
1615  return inv_masses;
1616 }
1617 
1618 /// Return the invariant mass of multiple particles given the collections of the
1619 /// quantities transverse momentum (pt), rapidity (eta), azimuth (phi) and mass.
1620 ///
1621 /// The function computes the invariant mass of multiple particles with the
1622 /// four-vectors (pt, eta, phi, mass).
1623 template <typename T>
1624 T InvariantMass(const RVec<T>& pt, const RVec<T>& eta, const RVec<T>& phi, const RVec<T>& mass)
1625 {
1626  const std::size_t size = pt.size();
1627 
1628  R__ASSERT(eta.size() == size && phi.size() == size && mass.size() == size);
1629 
1630  T x_sum = 0.;
1631  T y_sum = 0.;
1632  T z_sum = 0.;
1633  T e_sum = 0.;
1634 
1635  for (std::size_t i = 0u; i < size; ++ i) {
1636  // Convert to (e, x, y, z) coordinate system and update sums
1637  const auto x = pt[i] * std::cos(phi[i]);
1638  x_sum += x;
1639  const auto y = pt[i] * std::sin(phi[i]);
1640  y_sum += y;
1641  const auto z = pt[i] * std::sinh(eta[i]);
1642  z_sum += z;
1643  const auto e = std::sqrt(x * x + y * y + z * z + mass[i] * mass[i]);
1644  e_sum += e;
1645  }
1646 
1647  // Return invariant mass with (+, -, -, -) metric
1648  return std::sqrt(e_sum * e_sum - x_sum * x_sum - y_sum * y_sum - z_sum * z_sum);
1649 }
1650 
1651 ////////////////////////////////////////////////////////////////////////////
1652 /// \brief Build an RVec of objects starting from RVecs of input to their constructors.
1653 /// \tparam T Type of the objects contained in the created RVec.
1654 /// \tparam Args_t Pack of types templating the input RVecs.
1655 /// \param[in] args The RVecs containing the values used to initialise the output objects.
1656 /// \return The RVec of objects initialised with the input parameters.
1657 ///
1658 /// Example code, at the ROOT prompt:
1659 /// ~~~{.cpp}
1660 /// using namespace ROOT::VecOps;
1661 /// RVec<float> pts = {15.5, 34.32, 12.95};
1662 /// RVec<float> etas = {0.3, 2.2, 1.32};
1663 /// RVec<float> phis = {0.1, 3.02, 2.2};
1664 /// RVec<float> masses = {105.65, 105.65, 105.65};
1665 /// auto fourVecs = Construct<ROOT::Math::PtEtaPhiMVector>(pts, etas, phis, masses);
1666 /// cout << fourVecs << endl;
1667 /// // { (15.5,0.3,0.1,105.65), (34.32,2.2,3.02,105.65), (12.95,1.32,2.2,105.65) }
1668 /// ~~~
1669 template <typename T, typename... Args_t>
1671 {
1672  const auto size = ::ROOT::Detail::VecOps::GetVectorsSize("Construct", args...);
1673  RVec<T> ret;
1674  ret.reserve(size);
1675  for (auto i = 0UL; i < size; ++i) {
1676  ret.emplace_back(args[i]...);
1677  }
1678  return ret;
1679 }
1680 
1681 ////////////////////////////////////////////////////////////////////////////////
1682 /// Print a RVec at the prompt:
1683 template <class T>
1684 std::ostream &operator<<(std::ostream &os, const RVec<T> &v)
1685 {
1686  // In order to print properly, convert to 64 bit int if this is a char
1687  constexpr bool mustConvert = std::is_same<char, T>::value || std::is_same<signed char, T>::value ||
1688  std::is_same<unsigned char, T>::value || std::is_same<wchar_t, T>::value ||
1689  std::is_same<char16_t, T>::value || std::is_same<char32_t, T>::value;
1691  os << "{ ";
1692  auto size = v.size();
1693  if (size) {
1694  for (std::size_t i = 0; i < size - 1; ++i) {
1695  os << (Print_t)v[i] << ", ";
1696  }
1697  os << (Print_t)v[size - 1];
1698  }
1699  os << " }";
1700  return os;
1701 }
1702 
1703 #if (_VECOPS_USE_EXTERN_TEMPLATES)
1704 
1705 #define RVEC_EXTERN_UNARY_OPERATOR(T, OP) \
1706  extern template RVec<T> operator OP<T>(const RVec<T> &);
1707 
1708 #define RVEC_EXTERN_BINARY_OPERATOR(T, OP) \
1709  extern template auto operator OP<T, T>(const T &x, const RVec<T> &v) \
1710  -> RVec<decltype(x OP v[0])>; \
1711  extern template auto operator OP<T, T>(const RVec<T> &v, const T &y) \
1712  -> RVec<decltype(v[0] OP y)>; \
1713  extern template auto operator OP<T, T>(const RVec<T> &v0, const RVec<T> &v1)\
1714  -> RVec<decltype(v0[0] OP v1[0])>;
1715 
1716 #define RVEC_EXTERN_ASSIGN_OPERATOR(T, OP) \
1717  extern template RVec<T> &operator OP<T, T>(RVec<T> &, const T &); \
1718  extern template RVec<T> &operator OP<T, T>(RVec<T> &, const RVec<T> &);
1719 
1720 #define RVEC_EXTERN_LOGICAL_OPERATOR(T, OP) \
1721  extern template RVec<int> operator OP<T, T>(const RVec<T> &, const T &); \
1722  extern template RVec<int> operator OP<T, T>(const T &, const RVec<T> &); \
1723  extern template RVec<int> operator OP<T, T>(const RVec<T> &, const RVec<T> &);
1724 
1725 #define RVEC_EXTERN_FLOAT_TEMPLATE(T) \
1726  extern template class RVec<T>; \
1727  RVEC_EXTERN_UNARY_OPERATOR(T, +) \
1728  RVEC_EXTERN_UNARY_OPERATOR(T, -) \
1729  RVEC_EXTERN_UNARY_OPERATOR(T, !) \
1730  RVEC_EXTERN_BINARY_OPERATOR(T, +) \
1731  RVEC_EXTERN_BINARY_OPERATOR(T, -) \
1732  RVEC_EXTERN_BINARY_OPERATOR(T, *) \
1733  RVEC_EXTERN_BINARY_OPERATOR(T, /) \
1734  RVEC_EXTERN_ASSIGN_OPERATOR(T, +=) \
1735  RVEC_EXTERN_ASSIGN_OPERATOR(T, -=) \
1736  RVEC_EXTERN_ASSIGN_OPERATOR(T, *=) \
1737  RVEC_EXTERN_ASSIGN_OPERATOR(T, /=) \
1738  RVEC_EXTERN_LOGICAL_OPERATOR(T, <) \
1739  RVEC_EXTERN_LOGICAL_OPERATOR(T, >) \
1740  RVEC_EXTERN_LOGICAL_OPERATOR(T, ==) \
1741  RVEC_EXTERN_LOGICAL_OPERATOR(T, !=) \
1742  RVEC_EXTERN_LOGICAL_OPERATOR(T, <=) \
1743  RVEC_EXTERN_LOGICAL_OPERATOR(T, >=) \
1744  RVEC_EXTERN_LOGICAL_OPERATOR(T, &&) \
1745  RVEC_EXTERN_LOGICAL_OPERATOR(T, ||)
1746 
1747 #define RVEC_EXTERN_INTEGER_TEMPLATE(T) \
1748  extern template class RVec<T>; \
1749  RVEC_EXTERN_UNARY_OPERATOR(T, +) \
1750  RVEC_EXTERN_UNARY_OPERATOR(T, -) \
1751  RVEC_EXTERN_UNARY_OPERATOR(T, ~) \
1752  RVEC_EXTERN_UNARY_OPERATOR(T, !) \
1753  RVEC_EXTERN_BINARY_OPERATOR(T, +) \
1754  RVEC_EXTERN_BINARY_OPERATOR(T, -) \
1755  RVEC_EXTERN_BINARY_OPERATOR(T, *) \
1756  RVEC_EXTERN_BINARY_OPERATOR(T, /) \
1757  RVEC_EXTERN_BINARY_OPERATOR(T, %) \
1758  RVEC_EXTERN_BINARY_OPERATOR(T, &) \
1759  RVEC_EXTERN_BINARY_OPERATOR(T, |) \
1760  RVEC_EXTERN_BINARY_OPERATOR(T, ^) \
1761  RVEC_EXTERN_ASSIGN_OPERATOR(T, +=) \
1762  RVEC_EXTERN_ASSIGN_OPERATOR(T, -=) \
1763  RVEC_EXTERN_ASSIGN_OPERATOR(T, *=) \
1764  RVEC_EXTERN_ASSIGN_OPERATOR(T, /=) \
1765  RVEC_EXTERN_ASSIGN_OPERATOR(T, %=) \
1766  RVEC_EXTERN_ASSIGN_OPERATOR(T, &=) \
1767  RVEC_EXTERN_ASSIGN_OPERATOR(T, |=) \
1768  RVEC_EXTERN_ASSIGN_OPERATOR(T, ^=) \
1769  RVEC_EXTERN_ASSIGN_OPERATOR(T, >>=) \
1770  RVEC_EXTERN_ASSIGN_OPERATOR(T, <<=) \
1771  RVEC_EXTERN_LOGICAL_OPERATOR(T, <) \
1772  RVEC_EXTERN_LOGICAL_OPERATOR(T, >) \
1773  RVEC_EXTERN_LOGICAL_OPERATOR(T, ==) \
1774  RVEC_EXTERN_LOGICAL_OPERATOR(T, !=) \
1775  RVEC_EXTERN_LOGICAL_OPERATOR(T, <=) \
1776  RVEC_EXTERN_LOGICAL_OPERATOR(T, >=) \
1777  RVEC_EXTERN_LOGICAL_OPERATOR(T, &&) \
1778  RVEC_EXTERN_LOGICAL_OPERATOR(T, ||)
1779 
1780 RVEC_EXTERN_INTEGER_TEMPLATE(char)
1781 RVEC_EXTERN_INTEGER_TEMPLATE(short)
1782 RVEC_EXTERN_INTEGER_TEMPLATE(int)
1783 RVEC_EXTERN_INTEGER_TEMPLATE(long)
1784 //RVEC_EXTERN_INTEGER_TEMPLATE(long long)
1785 
1786 RVEC_EXTERN_INTEGER_TEMPLATE(unsigned char)
1787 RVEC_EXTERN_INTEGER_TEMPLATE(unsigned short)
1788 RVEC_EXTERN_INTEGER_TEMPLATE(unsigned int)
1789 RVEC_EXTERN_INTEGER_TEMPLATE(unsigned long)
1790 //RVEC_EXTERN_INTEGER_TEMPLATE(unsigned long long)
1791 
1792 RVEC_EXTERN_FLOAT_TEMPLATE(float)
1793 RVEC_EXTERN_FLOAT_TEMPLATE(double)
1794 
1795 #undef RVEC_EXTERN_UNARY_OPERATOR
1796 #undef RVEC_EXTERN_BINARY_OPERATOR
1797 #undef RVEC_EXTERN_ASSIGN_OPERATOR
1798 #undef RVEC_EXTERN_LOGICAL_OPERATOR
1799 #undef RVEC_EXTERN_INTEGER_TEMPLATE
1800 #undef RVEC_EXTERN_FLOAT_TEMPLATE
1801 
1802 #define RVEC_EXTERN_UNARY_FUNCTION(T, NAME, FUNC) \
1803  extern template RVec<PromoteType<T>> NAME(const RVec<T> &);
1804 
1805 #define RVEC_EXTERN_STD_UNARY_FUNCTION(T, F) RVEC_EXTERN_UNARY_FUNCTION(T, F, std::F)
1806 
1807 #define RVEC_EXTERN_BINARY_FUNCTION(T0, T1, NAME, FUNC) \
1808  extern template RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &, const T1 &); \
1809  extern template RVec<PromoteTypes<T0, T1>> NAME(const T0 &, const RVec<T1> &); \
1810  extern template RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &, const RVec<T1> &);
1811 
1812 #define RVEC_EXTERN_STD_BINARY_FUNCTION(T, F) RVEC_EXTERN_BINARY_FUNCTION(T, T, F, std::F)
1813 
1814 #define RVEC_EXTERN_STD_FUNCTIONS(T) \
1815  RVEC_EXTERN_STD_UNARY_FUNCTION(T, abs) \
1816  RVEC_EXTERN_STD_BINARY_FUNCTION(T, fdim) \
1817  RVEC_EXTERN_STD_BINARY_FUNCTION(T, fmod) \
1818  RVEC_EXTERN_STD_BINARY_FUNCTION(T, remainder) \
1819  RVEC_EXTERN_STD_UNARY_FUNCTION(T, exp) \
1820  RVEC_EXTERN_STD_UNARY_FUNCTION(T, exp2) \
1821  RVEC_EXTERN_STD_UNARY_FUNCTION(T, expm1) \
1822  RVEC_EXTERN_STD_UNARY_FUNCTION(T, log) \
1823  RVEC_EXTERN_STD_UNARY_FUNCTION(T, log10) \
1824  RVEC_EXTERN_STD_UNARY_FUNCTION(T, log2) \
1825  RVEC_EXTERN_STD_UNARY_FUNCTION(T, log1p) \
1826  RVEC_EXTERN_STD_BINARY_FUNCTION(T, pow) \
1827  RVEC_EXTERN_STD_UNARY_FUNCTION(T, sqrt) \
1828  RVEC_EXTERN_STD_UNARY_FUNCTION(T, cbrt) \
1829  RVEC_EXTERN_STD_BINARY_FUNCTION(T, hypot) \
1830  RVEC_EXTERN_STD_UNARY_FUNCTION(T, sin) \
1831  RVEC_EXTERN_STD_UNARY_FUNCTION(T, cos) \
1832  RVEC_EXTERN_STD_UNARY_FUNCTION(T, tan) \
1833  RVEC_EXTERN_STD_UNARY_FUNCTION(T, asin) \
1834  RVEC_EXTERN_STD_UNARY_FUNCTION(T, acos) \
1835  RVEC_EXTERN_STD_UNARY_FUNCTION(T, atan) \
1836  RVEC_EXTERN_STD_BINARY_FUNCTION(T, atan2) \
1837  RVEC_EXTERN_STD_UNARY_FUNCTION(T, sinh) \
1838  RVEC_EXTERN_STD_UNARY_FUNCTION(T, cosh) \
1839  RVEC_EXTERN_STD_UNARY_FUNCTION(T, tanh) \
1840  RVEC_EXTERN_STD_UNARY_FUNCTION(T, asinh) \
1841  RVEC_EXTERN_STD_UNARY_FUNCTION(T, acosh) \
1842  RVEC_EXTERN_STD_UNARY_FUNCTION(T, atanh) \
1843  RVEC_EXTERN_STD_UNARY_FUNCTION(T, floor) \
1844  RVEC_EXTERN_STD_UNARY_FUNCTION(T, ceil) \
1845  RVEC_EXTERN_STD_UNARY_FUNCTION(T, trunc) \
1846  RVEC_EXTERN_STD_UNARY_FUNCTION(T, round) \
1847  RVEC_EXTERN_STD_UNARY_FUNCTION(T, erf) \
1848  RVEC_EXTERN_STD_UNARY_FUNCTION(T, erfc) \
1849  RVEC_EXTERN_STD_UNARY_FUNCTION(T, lgamma) \
1850  RVEC_EXTERN_STD_UNARY_FUNCTION(T, tgamma) \
1851 
1852 RVEC_EXTERN_STD_FUNCTIONS(float)
1853 RVEC_EXTERN_STD_FUNCTIONS(double)
1854 #undef RVEC_EXTERN_STD_UNARY_FUNCTION
1855 #undef RVEC_EXTERN_STD_BINARY_FUNCTION
1856 #undef RVEC_EXTERN_STD_UNARY_FUNCTIONS
1857 
1858 #ifdef R__HAS_VDT
1859 
1860 #define RVEC_EXTERN_VDT_UNARY_FUNCTION(T, F) RVEC_EXTERN_UNARY_FUNCTION(T, F, vdt::F)
1861 
1862 RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_expf)
1863 RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_logf)
1864 RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_sinf)
1865 RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_cosf)
1866 RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_tanf)
1867 RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_asinf)
1868 RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_acosf)
1869 RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_atanf)
1870 
1871 RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_exp)
1872 RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_log)
1873 RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_sin)
1874 RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_cos)
1875 RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_tan)
1876 RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_asin)
1877 RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_acos)
1878 RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_atan)
1879 
1880 #endif // R__HAS_VDT
1881 
1882 #endif // _VECOPS_USE_EXTERN_TEMPLATES
1883 
1884 /** @} */ // end of Doxygen group vecops
1885 
1886 } // End of VecOps NS
1887 
1888 // Allow to use RVec as ROOT::RVec
1889 using ROOT::VecOps::RVec;
1890 
1891 } // End of ROOT NS
1892 
1893 #endif // ROOT_RVEC
c
#define c(i)
Definition: RSha256.hxx:101
ROOT::Detail::VecOps::GetVectorsSize
std::size_t GetVectorsSize(std::string_view id, const RVec< T > &... vs)
Definition: RVec.hxx:62
ROOT::VecOps::Map
auto Map(Args &&... args) -> decltype(ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...), std::make_index_sequence< sizeof...(args) - 1 >()))
Create new collection applying a callable to the elements of the input collection.
Definition: RVec.hxx:915
ROOT::VecOps::Argsort
RVec< typename RVec< T >::size_type > Argsort(const RVec< T > &v)
Return an RVec of indices that sort the input RVec.
Definition: RVec.hxx:1012
n
const Int_t n
Definition: legend1.C:16
ROOT::VecOps::Concatenate
RVec< Common_t > Concatenate(const RVec< T0 > &v0, const RVec< T1 > &v1)
Return the concatenation of two RVecs.
Definition: RVec.hxx:1451
ROOT::VecOps::RVec::emplace
iterator emplace(const_iterator pos, U value)
This method is intended only for arithmetic types unlike the std::vector corresponding one which is g...
Definition: RVec.hxx:426
first
Definition: first.py:1
ROOT::VecOps::RVec::capacity
size_type capacity() const noexcept
Definition: RVec.hxx:409
v0
@ v0
Definition: rootcling_impl.cxx:3665
e
#define e(i)
Definition: RSha256.hxx:103
ROOT::VecOps::RVec::crbegin
const_reverse_iterator crbegin() const noexcept
Definition: RVec.hxx:400
ROOT::VecOps::RVec::pop_back
void pop_back()
Definition: RVec.hxx:430
ROOT::VecOps::RVec::operator[]
reference operator[](size_type pos)
Definition: RVec.hxx:366
ROOT::Internal::VecOps::EmplaceBack
void EmplaceBack(T &v, Args &&... args)
Definition: RVec.hxx:108
ROOT::VecOps::RVec::data
data_t data() noexcept
Definition: RVec.hxx:389
ROOT::Math::erf
double erf(double x)
Error function encountered in integrating the normal distribution.
Definition: SpecFuncMathCore.cxx:59
f
#define f(i)
Definition: RSha256.hxx:104
ROOT::VecOps::InvariantMasses
RVec< T > InvariantMasses(const RVec< T > &pt1, const RVec< T > &eta1, const RVec< T > &phi1, const RVec< T > &mass1, const RVec< T > &pt2, const RVec< T > &eta2, const RVec< T > &phi2, const RVec< T > &mass2)
Return the invariant mass of two particles given the collections of the quantities transverse momentu...
Definition: RVec.hxx:1582
RVEC_LOGICAL_OPERATOR
#define RVEC_LOGICAL_OPERATOR(OP)
Definition: RVec.hxx:546
ROOT::VecOps::Mean
double Mean(const RVec< T > &v)
Get the mean of the elements of an RVec.
Definition: RVec.hxx:781
ROOT::VecOps::RVec::emplace_back
reference emplace_back(Args &&... args)
Definition: RVec.hxx:418
ROOT::VecOps::RVec::front
reference front()
Definition: RVec.hxx:385
Compare
Int_t Compare(const void *item1, const void *item2)
Definition: TGListTree.cxx:2138
RVEC_BINARY_OPERATOR
#define RVEC_BINARY_OPERATOR(OP)
Definition: RVec.hxx:462
ROOT::VecOps::RVec< bool >::pointer
typename Impl_t::pointer pointer
Definition: RVec.hxx:296
tan
double tan(double)
floor
double floor(double)
ROOT::Detail::indices
Definition: span.hxx:60
ROOT::VecOps::RVec::push_back
void push_back(const value_type &value)
Definition: RVec.hxx:416
F
#define F(x, y, z)
ROOT::VecOps::RVec::end
const_iterator end() const noexcept
Definition: RVec.hxx:396
ROOT::VecOps::RVec::RVec
RVec(size_type count, const T &value)
Definition: RVec.hxx:316
r
ROOT::R::TRInterface & r
Definition: Object.C:4
RVEC_UNARY_OPERATOR
#define RVEC_UNARY_OPERATOR(OP)
Definition: RVec.hxx:439
string_view
basic_string_view< char > string_view
Definition: libcpp_string_view.h:786
exp
double exp(double)
ROOT::VecOps::StdDev
double StdDev(const RVec< T > &v)
Get the standard deviation of the elements of an RVec.
Definition: RVec.hxx:891
ROOT::VecOps::RVec::rbegin
reverse_iterator rbegin() noexcept
Definition: RVec.hxx:398
log
double log(double)
TGeant4Unit::s
static constexpr double s
Definition: TGeant4SystemOfUnits.h:162
tanh
double tanh(double)
ROOT::VecOps::RVec::operator[]
const_reference operator[](size_type pos) const
Definition: RVec.hxx:367
ROOT::VecOps::Max
T Max(const RVec< T > &v)
Get the greatest element of an RVec.
Definition: RVec.hxx:798
ROOT::VecOps::RVec::rend
reverse_iterator rend() noexcept
Definition: RVec.hxx:401
sin
double sin(double)
x
Double_t x[n]
Definition: legend1.C:17
cos
double cos(double)
long
long
Definition: Converters.cxx:876
ROOT::Detail::VecOps::MapFromTuple
auto MapFromTuple(Tuple_t &&t, std::index_sequence< Is... >) -> decltype(MapImpl(std::get< std::tuple_size< Tuple_t >::value - 1 >(t), std::get< Is >(t)...))
Definition: RVec.hxx:91
ROOT::VecOps::RVec< bool >::reference
typename Impl_t::reference reference
Definition: RVec.hxx:294
ROOT::VecOps::Nonzero
RVec< typename RVec< T >::size_type > Nonzero(const RVec< T > &v)
Return the indices of the elements which are not zero.
Definition: RVec.hxx:1281
ceil
double ceil(double)
ROOT::Math::tgamma
double tgamma(double x)
The gamma function is defined to be the extension of the factorial to real numbers.
Definition: SpecFuncMathCore.cxx:89
ROOT::VecOps::RVec::begin
const_iterator begin() const noexcept
Definition: RVec.hxx:393
ROOT::VecOps::All
auto All(const RVec< T > &v) -> decltype(v[0]==false)
Return true if all of the elements equate to true, return false otherwise.
Definition: RVec.hxx:986
ROOT::VecOps::RVec::clear
void clear() noexcept
Definition: RVec.hxx:412
ROOT::Math::IntegrationOneDim::Type
Type
enumeration specifying the integration types.
Definition: AllIntegrationTypes.h:32
ROOT::Math::erfc
double erfc(double x)
Complementary error function.
Definition: SpecFuncMathCore.cxx:44
v
@ v
Definition: rootcling_impl.cxx:3664
ROOT::VecOps::RVec::swap
void swap(RVec< T > &other)
Definition: RVec.hxx:433
ROOT::VecOps::RVec< bool >::iterator
typename Impl_t::iterator iterator
Definition: RVec.hxx:302
RVEC_STD_UNARY_FUNCTION
#define RVEC_STD_UNARY_FUNCTION(F)
Definition: RVec.hxx:652
RAdoptAllocator.hxx
x1
static const double x1[5]
Definition: RooGaussKronrodIntegrator1D.cxx:346
ROOT::VecOps::swap
void swap(RVec< T > &lhs, RVec< T > &rhs)
Definition: RVec.hxx:995
ROOT::VecOps::RVec::RVec
RVec(InputIt first, InputIt last)
Definition: RVec.hxx:327
ROOT::VecOps::Construct
RVec< T > Construct(const RVec< Args_t > &... args)
Build an RVec of objects starting from RVecs of input to their constructors.
Definition: RVec.hxx:1670
ROOT::VecOps::RVec::erase
iterator erase(iterator pos)
Definition: RVec.hxx:413
ROOT::VecOps::Where
RVec< T > Where(const RVec< int > &c, const RVec< T > &v1, const RVec< T > &v2)
Return the elements of v1 if the condition c is true and v2 if the condition c is false.
Definition: RVec.hxx:1346
ROOT::VecOps::Take
RVec< T > Take(const RVec< T > &v, const RVec< typename RVec< T >::size_type > &i)
Return elements of a vector at given indices.
Definition: RVec.hxx:1054
ROOT::VecOps::RVec::RVec
RVec(const std::vector< T > &v)
Definition: RVec.hxx:322
ROOT::VecOps::RVec::RVec
RVec(pointer p, size_type n)
Definition: RVec.hxx:324
ROOT::VecOps::RVec::back
reference back()
Definition: RVec.hxx:387
atan2
double atan2(double, double)
ROOT::VecOps::RVec< bool >::const_iterator
typename Impl_t::const_iterator const_iterator
Definition: RVec.hxx:303
ROOT::VecOps::RVec::at
const_reference at(size_type pos) const
Definition: RVec.hxx:361
RIntegerSequence.hxx
ROOT::VecOps::RVec< bool >::const_data_t
typename std::conditional< IsVecBool, void, typename Impl_t::const_pointer >::type const_data_t
Definition: RVec.hxx:301
ROOT::VecOps::RVec< bool >::value_type
typename Impl_t::value_type value_type
Definition: RVec.hxx:291
log10
double log10(double)
ROOT::VecOps::RVec::rend
const_reverse_iterator rend() const noexcept
Definition: RVec.hxx:402
ROOT::Minuit2::inner_product
double inner_product(const LAVector &, const LAVector &)
Definition: LaInnerProduct.cxx:18
ROOT::VecOps::operator<<
std::ostream & operator<<(std::ostream &os, const RVec< T > &v)
Print a RVec at the prompt:
Definition: RVec.hxx:1684
ROOT::VecOps::RVec::fData
Impl_t fData
Definition: RVec.hxx:308
ROOT::VecOps::RVec::resize
void resize(size_type count)
Definition: RVec.hxx:431
size
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::VecOps::RVec< bool >::difference_type
typename Impl_t::difference_type difference_type
Definition: RVec.hxx:293
ROOT::VecOps::ArgMin
std::size_t ArgMin(const RVec< T > &v)
Get the index of the smallest element of an RVec In case of multiple occurrences of the minimum value...
Definition: RVec.hxx:850
ROOT::VecOps::RVec::at
reference at(size_type pos)
Definition: RVec.hxx:360
RStringView.hxx
ROOT::VecOps::RVec::RVec
RVec(RVec< T > &&v)
Definition: RVec.hxx:320
RVEC_ASSIGNMENT_OPERATOR
#define RVEC_ASSIGNMENT_OPERATOR(OP)
Definition: RVec.hxx:510
ROOT::VecOps::RVec::RVec
RVec(size_type count)
Definition: RVec.hxx:314
ROOT::VecOps::RVec::data
const_data_t data() const noexcept
Definition: RVec.hxx:390
RVEC_STD_BINARY_FUNCTION
#define RVEC_STD_BINARY_FUNCTION(F)
Definition: RVec.hxx:653
ROOT::VecOps::RVec::cend
const_iterator cend() const noexcept
Definition: RVec.hxx:397
ROOT::VecOps::DeltaR
RVec< T > DeltaR(const RVec< T > &eta1, const RVec< T > &eta2, const RVec< T > &phi1, const RVec< T > &phi2, const T c=M_PI)
Return the distance on the - plane ( ) from the collections eta1, eta2, phi1 and phi2.
Definition: RVec.hxx:1557
ROOT::VecOps::DeltaPhi
T DeltaPhi(T v1, T v2, const T c=M_PI)
Return the angle difference of two scalars.
Definition: RVec.hxx:1467
ROOT::VecOps::RVec::operator=
RVec< T > & operator=(std::initializer_list< T > ilist)
Definition: RVec.hxx:344
TypeTraits.hxx
ROOT::VecOps::RVec::crend
const_reverse_iterator crend() const noexcept
Definition: RVec.hxx:403
double
double
Definition: Converters.cxx:939
ROOT::VecOps::Sum
T Sum(const RVec< T > &v)
Sum elements of an RVec.
Definition: RVec.hxx:764
y
Double_t y[n]
Definition: legend1.C:17
sqrt
double sqrt(double)
ROOT::Math::expm1
double expm1(double x)
exp(x) -1 with error cancellation when x is small
Definition: Math.h:110
ROOT::VecOps::InvariantMass
T InvariantMass(const RVec< T > &pt, const RVec< T > &eta, const RVec< T > &phi, const RVec< T > &mass)
Return the invariant mass of multiple particles given the collections of the quantities transverse mo...
Definition: RVec.hxx:1624
ROOT::VecOps::Var
double Var(const RVec< T > &v)
Get the variance of the elements of an RVec.
Definition: RVec.hxx:867
ROOT::VecOps::RVec::back
const_reference back() const
Definition: RVec.hxx:388
ROOT::VecOps::Filter
RVec< T > Filter(const RVec< T > &v, F &&f)
Create a new collection with the elements passing the filter expressed by the predicate.
Definition: RVec.hxx:944
acos
double acos(double)
ROOT::VecOps::RVec::push_back
void push_back(T &&value)
Definition: RVec.hxx:415
ROOT::VecOps::RVec< bool >::const_reverse_iterator
typename Impl_t::const_reverse_iterator const_reverse_iterator
Definition: RVec.hxx:305
ROOT::VecOps::Intersect
RVec< T > Intersect(const RVec< T > &v1, const RVec< T > &v2, bool v2_is_sorted=false)
Return the intersection of elements of two RVecs.
Definition: RVec.hxx:1312
ROOT::VecOps::RVec::IsVecBool
static constexpr const auto IsVecBool
Definition: RVec.hxx:288
ROOT::VecOps::RVec< bool >::const_reference
typename Impl_t::const_reference const_reference
Definition: RVec.hxx:295
ROOT::VecOps::Dot
auto Dot(const RVec< T > &v0, const RVec< V > &v1) -> decltype(v0[0] *v1[0])
Inner product.
Definition: RVec.hxx:746
v1
@ v1
Definition: rootcling_impl.cxx:3666
ROOT::VecOps::Reverse
RVec< T > Reverse(const RVec< T > &v)
Return copy of reversed vector.
Definition: RVec.hxx:1112
R__ASSERT
#define R__ASSERT(e)
Definition: TError.h:118
ROOT::VecOps::RVec::empty
bool empty() const noexcept
Definition: RVec.hxx:405
ROOT::Detail::VecOps::MapImpl
auto MapImpl(F &&f, const RVec< T > &... vs) -> RVec< decltype(f(vs[0]...))>
Definition: RVec.hxx:79
ROOT::VecOps::Sort
RVec< T > Sort(const RVec< T > &v)
Return copy of RVec with elements sorted in ascending order.
Definition: RVec.hxx:1133
v2
@ v2
Definition: rootcling_impl.cxx:3667
M_PI
#define M_PI
Definition: Rotated.cxx:105
ROOT::VecOps::RVec::begin
iterator begin() noexcept
Definition: RVec.hxx:392
ROOT::VecOps::RVec::RVec
RVec(const RVec< T > &v)
Definition: RVec.hxx:318
ROOT::VecOps::RVec::operator[]
RVec operator[](const RVec< V > &conds) const
Definition: RVec.hxx:370
ROOT::Math::log1p
double log1p(double x)
declarations for functions which are not implemented by some compilers
Definition: Math.h:98
ROOT::VecOps::RVec::max_size
size_type max_size() const noexcept
Definition: RVec.hxx:407
ROOT::Math::Chebyshev::T
double T(double x)
Definition: ChebyshevPol.h:34
ROOT::VecOps::Combinations
RVec< RVec< std::size_t > > Combinations(const std::size_t size1, const std::size_t size2)
Return the indices that represent all combinations of the elements of two RVecs.
Definition: RVec.hxx:1177
sinh
double sinh(double)
ROOT::VecOps::RVec< bool >::reverse_iterator
typename Impl_t::reverse_iterator reverse_iterator
Definition: RVec.hxx:304
ROOT::VecOps::RVec::cbegin
const_iterator cbegin() const noexcept
Definition: RVec.hxx:394
x2
static const double x2[5]
Definition: RooGaussKronrodIntegrator1D.cxx:364
atan
double atan(double)
cosh
double cosh(double)
ROOT::VecOps::RVec::reserve
void reserve(size_type new_cap)
Definition: RVec.hxx:408
ROOT::VecOps::RVec::operator=
RVec< T > & operator=(RVec< T > &&v)
Definition: RVec.hxx:338
ROOT::VecOps::Any
auto Any(const RVec< T > &v) -> decltype(v[0]==true)
Return true if any of the elements equates to true, return false otherwise.
Definition: RVec.hxx:967
ROOT::Math::lgamma
double lgamma(double x)
Calculates the logarithm of the gamma function.
Definition: SpecFuncMathCore.cxx:74
ROOT::VecOps::RVec::erase
iterator erase(iterator first, iterator last)
Definition: RVec.hxx:414
ROOT::VecOps::RVec::shrink_to_fit
void shrink_to_fit()
Definition: RVec.hxx:410
ROOT::VecOps::RVec::operator=
RVec< T > & operator=(const RVec< T > &v)
Definition: RVec.hxx:332
type
int type
Definition: TGX11.cxx:121
ROOT::VecOps::RVec::size
size_type size() const noexcept
Definition: RVec.hxx:406
pt
TPaveText * pt
Definition: entrylist_figure1.C:7
ROOT::VecOps::Min
T Min(const RVec< T > &v)
Get the smallest element of an RVec.
Definition: RVec.hxx:814
ROOT::VecOps::RVec< bool >::Impl_t
typename std::conditional< IsVecBool, std::vector< bool >, std::vector< bool, ::ROOT::Detail::VecOps::RAdoptAllocator< bool > >>::type Impl_t
Definition: RVec.hxx:290
RooBatchCompute::fast_log
double fast_log(double x)
Definition: RooVDTHeaders.h:56
ROOT::VecOps::RVec< bool >::const_pointer
typename Impl_t::const_pointer const_pointer
Definition: RVec.hxx:297
pow
double pow(double, double)
asin
double asin(double)
ROOT::VecOps::RVec< bool >::size_type
typename Impl_t::size_type size_type
Definition: RVec.hxx:292
ROOT::VecOps::ArgMax
std::size_t ArgMax(const RVec< T > &v)
Get the index of the greatest element of an RVec In case of multiple occurrences of the maximum value...
Definition: RVec.hxx:832
ROOT::VecOps::RVec< bool >::data_t
typename std::conditional< IsVecBool, void, typename Impl_t::pointer >::type data_t
Definition: RVec.hxx:300
ROOT
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: EExecutionPolicy.hxx:4
ROOT::VecOps::RVec
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition: RVec.hxx:283
ROOT::VecOps::RVec::front
const_reference front() const
Definition: RVec.hxx:386
RooBatchCompute::fast_exp
double fast_exp(double x)
Definition: RooVDTHeaders.h:52
ROOT::Detail::VecOps::RVec
ROOT::VecOps::RVec< T > RVec
Definition: RVec.hxx:59
ROOT::VecOps::RVec::rbegin
const_reverse_iterator rbegin() const noexcept
Definition: RVec.hxx:399
ROOT::VecOps::RVec::at
value_type at(size_type pos, value_type fallback) const
No exception thrown. The user specifies the desired value in case the RVec is shorter than pos.
Definition: RVec.hxx:365
ROOT::VecOps::RVec::at
value_type at(size_type pos, value_type fallback)
No exception thrown. The user specifies the desired value in case the RVec is shorter than pos.
Definition: RVec.hxx:363
ROOT::VecOps::DeltaR2
RVec< T > DeltaR2(const RVec< T > &eta1, const RVec< T > &eta2, const RVec< T > &phi1, const RVec< T > &phi2, const T c=M_PI)
Return the square of the distance on the - plane ( ) from the collections eta1, eta2,...
Definition: RVec.hxx:1543
ROOT::VecOps::RVec::resize
void resize(size_type count, const value_type &value)
Definition: RVec.hxx:432
ROOT::VecOps::RVec::RVec
RVec(std::initializer_list< T > init)
Definition: RVec.hxx:329
ROOT::VecOps::RVec::RVec
RVec()
Definition: RVec.hxx:312
TError.h
ROOT::VecOps::RVec::end
iterator end() noexcept
Definition: RVec.hxx:395