Logo ROOT   6.14/05
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 /**
12  \defgroup vecops VecOps
13 */
14 
15 #ifndef ROOT_TVEC
16 #define ROOT_TVEC
17 
18 #ifdef _WIN32
19  #define _VECOPS_USE_EXTERN_TEMPLATES false
20 #else
21  #define _VECOPS_USE_EXTERN_TEMPLATES true
22 #endif
23 
24 #include <ROOT/RAdoptAllocator.hxx>
25 #include <ROOT/TypeTraits.hxx>
26 
27 #include <algorithm>
28 #include <cmath>
29 #include <numeric> // for inner_product
30 #include <sstream>
31 #include <stdexcept>
32 #include <vector>
33 #include <utility>
34 
35 #ifdef R__HAS_VDT
36 #include <vdt/vdtMath.h>
37 #endif
38 
39 namespace ROOT {
40 
41 namespace VecOps {
42 // clang-format off
43 /**
44 \class ROOT::VecOps::RVec
45 \ingroup vecops
46 \brief A "std::vector"-like collection of values implementing handy operation to analyse them
47 \tparam T The type of the contained objects
48 
49 A RVec is a container designed to make analysis of values' collections fast and easy.
50 Its storage is contiguous in memory and its interface is designed such to resemble to the one
51 of the stl vector. In addition the interface features methods and external functions to ease
52 the manipulation and analysis of the data in the RVec.
53 
54 \htmlonly
55 <a href="https://doi.org/10.5281/zenodo.1253756"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.1253756.svg" alt="DOI"></a>
56 \endhtmlonly
57 
58 ## Table of Contents
59 - [Example](#example)
60 - [Owning and adopting memory](#owningandadoptingmemory)
61 - [Usage in combination with TDataFrame](#usagetdataframe)
62 
63 ## <a name="example"></a>Example
64 Suppose to have an event featuring a collection of muons with a certain pseudorapidity,
65 momentum and charge, e.g.:
66 ~~~{.cpp}
67 std::vector<short> mu_charge {1, 1, -1, -1, -1, 1, 1, -1};
68 std::vector<float> mu_pt {56, 45, 32, 24, 12, 8, 7, 6.2};
69 std::vector<float> mu_eta {3.1, -.2, -1.1, 1, 4.1, 1.6, 2.4, -.5};
70 ~~~
71 Suppose you want to extract the transverse momenta of the muons satisfying certain
72 criteria, for example consider only negatively charged muons with a pseudorapidity
73 smaller or equal to 2 and with a transverse momentum greater than 10 GeV.
74 Such a selection would require, among the other things, the management of an explicit
75 loop, for example:
76 ~~~{.cpp}
77 std::vector<float> goodMuons_pt;
78 const auto size = mu_charge.size();
79 for (size_t i=0; i < size; ++i) {
80  if (mu_pt[i] > 10 && abs(mu_eta[i]) <= 2. && mu_charge[i] == -1) {
81  goodMuons_pt.emplace_back(mu_pt[i]);
82  }
83 }
84 ~~~
85 These operations become straightforward with RVec - we just need to *write what
86 we mean*:
87 ~~~{.cpp}
88 RVec<short> mu_charge {1, 1, -1, -1, -1, 1, 1, -1};
89 RVec<float> mu_pt {56, 45, 32, 24, 12, 8, 7, 6.2};
90 RVec<float> mu_eta {3.1, -.2, -1.1, 1, 4.1, 1.6, 2.4, -.5};
91 
92 auto goodMuons_pt = mu_pt[ (mu_pt > 10.f && abs(mu_eta) <= 2.f && mu_charge == -1)
93 ~~~
94 Now the clean collection of transverse momenta can be used within the rest of the data analysis, for
95 example to fill a histogram.
96 
97 ## <a name="owningandadoptingmemory"></a>Owning and adopting memory
98 RVec has contiguous memory associated to it. It can own it or simply adopt it. In the latter case,
99 it can be constructed with the address of the memory associated to it and its lenght. For example:
100 ~~~{.cpp}
101 std::vector<int> myStlVec {1,2,3};
102 RVec<int> myRVec(myStlVec.data(), myStlVec.size());
103 ~~~
104 In this case, the memory associated to myStlVec and myRVec is the same, myRVec simply "adopted it".
105 If any method which implies a re-allocation is called, e.g. *emplace_back* or *resize*, the adopted
106 memory is released and new one is allocated. The previous content is copied in the new memory and
107 preserved.
108 
109 ## <a name="usagetdataframe"></a>Usage in combination with TDataFrame
110 TDataFrame leverages internally RVecs. Suppose to have a dataset stored in a
111 TTree which holds these columns (here we choose C arrays to represent the
112 collections, they could be as well std::vector instances):
113 ~~~{.bash}
114  nPart "nPart/I" An integer representing the number of particles
115  px "px[nPart]/D" The C array of the particles' x component of the momentum
116  py "py[nPart]/D" The C array of the particles' y component of the momentum
117  E "E[nPart]/D" The C array of the particles' Energy
118 ~~~
119 Suppose you'd like to plot in a histogram the transverse momenta of all particles
120 for which the energy is greater than 200 MeV.
121 The code required would just be:
122 ~~~{.cpp}
123 TDataFrame d("mytree", "myfile.root");
124 using doubles = RVec<double>;
125 auto cutPt = [](doubles &pxs, doubles &pys, doubles &Es) {
126  auto all_pts = sqrt(pxs * pxs + pys * pys);
127  auto good_pts = all_pts[Es > 200.];
128  return good_pts;
129  };
130 
131 auto hpt = d.Define("pt", cutPt, {"px", "py", "E"})
132  .Histo1D("pt");
133 hpt->Draw();
134 ~~~
135 And if you'd like to express your selection as a string:
136 ~~~{.cpp}
137 TDataFrame d("mytree", "myfile.root");
138 auto hpt = d.Define("pt", "sqrt(pxs * pxs + pys * pys)[E>200]")
139  .Histo1D("pt");
140 hpt->Draw();
141 ~~~
142 
143 **/
144 // clang-format on
145 template <typename T>
146 class RVec {
147 public:
148  using Impl_t = typename std::vector<T, ::ROOT::Detail::VecOps::RAdoptAllocator<T>>;
149  using value_type = typename Impl_t::value_type;
150  using size_type = typename Impl_t::size_type;
151  using difference_type = typename Impl_t::difference_type;
152  using reference = typename Impl_t::reference;
153  using const_reference = typename Impl_t::const_reference;
154  using pointer = typename Impl_t::pointer;
155  using const_pointer = typename Impl_t::const_pointer;
156  using iterator = typename Impl_t::iterator;
157  using const_iterator = typename Impl_t::const_iterator;
158  using reverse_iterator = typename Impl_t::reverse_iterator;
159  using const_reverse_iterator = typename Impl_t::const_reverse_iterator;
160 
161 private:
163 
164 public:
165  // constructors
166  RVec() {}
167 
168  explicit RVec(size_type count) : fData(count) {}
169 
170  RVec(size_type count, const T &value) : fData(count, value) {}
171 
172  RVec(const RVec<T> &v) : fData(v.fData) {}
173 
174  RVec(RVec<T> &&v) : fData(std::move(v.fData)) {}
175 
176  RVec(const std::vector<T> &v) : fData(v.cbegin(), v.cend()) {}
177 
178  RVec(pointer p, size_type n) : fData(n, T(), ROOT::Detail::VecOps::RAdoptAllocator<T>(p)) {}
179 
180  template <class InputIt>
181  RVec(InputIt first, InputIt last) : fData(first, last) {}
182 
183  RVec(std::initializer_list<T> init) : fData(init) {}
184 
185  // assignment
187  {
188  fData = v.fData;
189  return *this;
190  }
191 
193  {
194  std::swap(fData, v.fData);
195  return *this;
196  }
197 
198  RVec<T> &operator=(std::initializer_list<T> ilist)
199  {
200  fData = ilist;
201  return *this;
202  }
203 
204  // conversion
205  template <typename U, typename = std::enable_if<std::is_convertible<T, U>::value>>
206  operator RVec<U>() const
207  {
208  RVec<U> ret(size());
209  std::copy(begin(), end(), ret.begin());
210  return ret;
211  }
212 
213  // accessors
214  reference at(size_type pos) { return fData.at(pos); }
215  const_reference at(size_type pos) const { return fData.at(pos); }
216  reference operator[](size_type pos) { return fData[pos]; }
217  const_reference operator[](size_type pos) const { return fData[pos]; }
218 
219  template <typename V, typename = std::enable_if<std::is_convertible<V, bool>::value>>
220  RVec operator[](const RVec<V> &conds) const
221  {
222  const size_type n = conds.size();
223 
224  if (n != size())
225  throw std::runtime_error("Cannot index RVec with condition vector of different size");
226 
227  RVec<T> ret;
228  ret.reserve(n);
229  for (size_type i = 0; i < n; ++i)
230  if (conds[i])
231  ret.emplace_back(fData[i]);
232  return ret;
233  }
234 
235  reference front() { return fData.front(); }
236  const_reference front() const { return fData.front(); }
237  reference back() { return fData.back(); }
238  const_reference back() const { return fData.back(); }
239  T *data() noexcept { return fData.data(); }
240  const T *data() const noexcept { return fData.data(); }
241  // iterators
242  iterator begin() noexcept { return fData.begin(); }
243  const_iterator begin() const noexcept { return fData.begin(); }
244  const_iterator cbegin() const noexcept { return fData.cbegin(); }
245  iterator end() noexcept { return fData.end(); }
246  const_iterator end() const noexcept { return fData.end(); }
247  const_iterator cend() const noexcept { return fData.cend(); }
248  reverse_iterator rbegin() noexcept { return fData.rbegin(); }
249  const_reverse_iterator rbegin() const noexcept { return fData.rbegin(); }
250  const_reverse_iterator crbegin() const noexcept { return fData.crbegin(); }
251  reverse_iterator rend() noexcept { return fData.rend(); }
252  const_reverse_iterator rend() const noexcept { return fData.rend(); }
253  const_reverse_iterator crend() const noexcept { return fData.crend(); }
254  // capacity
255  bool empty() const noexcept { return fData.empty(); }
256  size_type size() const noexcept { return fData.size(); }
257  size_type max_size() const noexcept { return fData.size(); }
258  void reserve(size_type new_cap) { fData.reserve(new_cap); }
259  size_type capacity() const noexcept { return fData.capacity(); }
260  void shrink_to_fit() { fData.shrink_to_fit(); };
261  // modifiers
262  void clear() noexcept { fData.clear(); }
263  iterator erase(iterator pos) { return fData.erase(pos); }
264  iterator erase(iterator first, iterator last) { return fData.erase(first, last); }
265  void push_back(T &&value) { fData.push_back(std::forward<T>(value)); }
266  template <class... Args>
267  reference emplace_back(Args &&... args)
268  {
269  fData.emplace_back(std::forward<Args>(args)...);
270  return fData.back();
271  }
272  /// This method is intended only for arithmetic types unlike the std::vector
273  /// corresponding one which is generic.
274  template<typename U = T, typename std::enable_if<std::is_arithmetic<U>::value, int>* = nullptr>
276  {
277  return fData.emplace(pos, value);
278  }
279  void pop_back() { fData.pop_back(); }
280  void resize(size_type count) { fData.resize(count); }
281  void resize(size_type count, const value_type &value) { fData.resize(count, value); }
282  void swap(RVec<T> &other) { std::swap(fData, other.fData); }
283 };
284 
285 ///@name RVec Unary Arithmetic Operators
286 ///@{
287 
288 #define TVEC_UNARY_OPERATOR(OP) \
289 template <typename T> \
290 RVec<T> operator OP(const RVec<T> &v) \
291 { \
292  RVec<T> ret(v); \
293  for (auto &x : ret) \
294  x = OP x; \
295 return ret; \
296 } \
297 
302 #undef TVEC_UNARY_OPERATOR
303 
304 ///@}
305 ///@name RVec Binary Arithmetic Operators
306 ///@{
307 
308 #define ERROR_MESSAGE(OP) \
309  "Cannot call operator " #OP " on vectors of different sizes."
310 
311 #define TVEC_BINARY_OPERATOR(OP) \
312 template <typename T0, typename T1> \
313 auto operator OP(const RVec<T0> &v, const T1 &y) \
314  -> RVec<decltype(v[0] OP y)> \
315 { \
316  RVec<decltype(v[0] OP y)> ret(v.size()); \
317  auto op = [&y](const T0 &x) { return x OP y; }; \
318  std::transform(v.begin(), v.end(), ret.begin(), op); \
319  return ret; \
320 } \
321  \
322 template <typename T0, typename T1> \
323 auto operator OP(const T0 &x, const RVec<T1> &v) \
324  -> RVec<decltype(x OP v[0])> \
325 { \
326  RVec<decltype(x OP v[0])> ret(v.size()); \
327  auto op = [&x](const T1 &y) { return x OP y; }; \
328  std::transform(v.begin(), v.end(), ret.begin(), op); \
329  return ret; \
330 } \
331  \
332 template <typename T0, typename T1> \
333 auto operator OP(const RVec<T0> &v0, const RVec<T1> &v1) \
334  -> RVec<decltype(v0[0] OP v1[0])> \
335 { \
336  if (v0.size() != v1.size()) \
337  throw std::runtime_error(ERROR_MESSAGE(OP)); \
338  \
339  RVec<decltype(v0[0] OP v1[0])> ret(v0.size()); \
340  auto op = [](const T0 &x, const T1 &y) { return x OP y; }; \
341  std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), op); \
342  return ret; \
343 } \
344 
353 #undef TVEC_BINARY_OPERATOR
354 
355 ///@}
356 ///@name RVec Assignment Arithmetic Operators
357 ///@{
358 
359 #define TVEC_ASSIGNMENT_OPERATOR(OP) \
360 template <typename T0, typename T1> \
361 RVec<T0>& operator OP(RVec<T0> &v, const T1 &y) \
362 { \
363  auto op = [&y](T0 &x) { return x OP y; }; \
364  std::transform(v.begin(), v.end(), v.begin(), op); \
365  return v; \
366 } \
367  \
368 template <typename T0, typename T1> \
369 RVec<T0>& operator OP(RVec<T0> &v0, const RVec<T1> &v1) \
370 { \
371  if (v0.size() != v1.size()) \
372  throw std::runtime_error(ERROR_MESSAGE(OP)); \
373  \
374  auto op = [](T0 &x, const T1 &y) { return x OP y; }; \
375  std::transform(v0.begin(), v0.end(), v1.begin(), v0.begin(), op); \
376  return v0; \
377 } \
378 
389 #undef TVEC_ASSIGNMENT_OPERATOR
390 
391 ///@}
392 ///@name RVec Comparison and Logical Operators
393 ///@{
394 
395 #define TVEC_LOGICAL_OPERATOR(OP) \
396 template <typename T0, typename T1> \
397 auto operator OP(const RVec<T0> &v, const T1 &y) \
398  -> RVec<int> /* avoid std::vector<bool> */ \
399 { \
400  RVec<int> ret(v.size()); \
401  auto op = [y](const T0 &x) -> int { return x OP y; }; \
402  std::transform(v.begin(), v.end(), ret.begin(), op); \
403  return ret; \
404 } \
405  \
406 template <typename T0, typename T1> \
407 auto operator OP(const T0 &x, const RVec<T1> &v) \
408  -> RVec<int> /* avoid std::vector<bool> */ \
409 { \
410  RVec<int> ret(v.size()); \
411  auto op = [x](const T1 &y) -> int { return x OP y; }; \
412  std::transform(v.begin(), v.end(), ret.begin(), op); \
413  return ret; \
414 } \
415  \
416 template <typename T0, typename T1> \
417 auto operator OP(const RVec<T0> &v0, const RVec<T1> &v1) \
418  -> RVec<int> /* avoid std::vector<bool> */ \
419 { \
420  if (v0.size() != v1.size()) \
421  throw std::runtime_error(ERROR_MESSAGE(OP)); \
422  \
423  RVec<int> ret(v0.size()); \
424  auto op = [](const T0 &x, const T1 &y) -> int { return x OP y; }; \
425  std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), op); \
426  return ret; \
427 } \
428 
437 #undef TVEC_LOGICAL_OPERATOR
438 
439 ///@}
440 ///@name RVec Standard Mathematical Functions
441 ///@{
442 
443 template <typename T> struct PromoteTypeImpl;
444 
445 template <> struct PromoteTypeImpl<float> { using Type = float; };
446 template <> struct PromoteTypeImpl<double> { using Type = double; };
447 template <> struct PromoteTypeImpl<long double> { using Type = long double; };
448 
449 template <typename T> struct PromoteTypeImpl { using Type = double; };
450 
451 template <typename T>
453 
454 template <typename U, typename V>
456 
457 #define TVEC_UNARY_FUNCTION(NAME, FUNC) \
458  template <typename T> \
459  RVec<PromoteType<T>> NAME(const RVec<T> &v) \
460  { \
461  RVec<PromoteType<T>> ret(v.size()); \
462  auto f = [](const T &x) { return FUNC(x); }; \
463  std::transform(v.begin(), v.end(), ret.begin(), f); \
464  return ret; \
465  }
466 
467 #define TVEC_BINARY_FUNCTION(NAME, FUNC) \
468  template <typename T0, typename T1> \
469  RVec<PromoteTypes<T0, T1>> NAME(const T0 &x, const RVec<T1> &v) \
470  { \
471  RVec<PromoteTypes<T0, T1>> ret(v.size()); \
472  auto f = [&x](const T1 &y) { return FUNC(x, y); }; \
473  std::transform(v.begin(), v.end(), ret.begin(), f); \
474  return ret; \
475  } \
476  \
477  template <typename T0, typename T1> \
478  RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v, const T1 &y) \
479  { \
480  RVec<PromoteTypes<T0, T1>> ret(v.size()); \
481  auto f = [&y](const T1 &x) { return FUNC(x, y); }; \
482  std::transform(v.begin(), v.end(), ret.begin(), f); \
483  return ret; \
484  } \
485  \
486  template <typename T0, typename T1> \
487  RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v0, const RVec<T1> &v1) \
488  { \
489  if (v0.size() != v1.size()) \
490  throw std::runtime_error(ERROR_MESSAGE(NAME)); \
491  \
492  RVec<PromoteTypes<T0, T1>> ret(v0.size()); \
493  auto f = [](const T0 &x, const T1 &y) { return FUNC(x, y); }; \
494  std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), f); \
495  return ret; \
496  } \
497 
498 #define TVEC_STD_UNARY_FUNCTION(F) TVEC_UNARY_FUNCTION(F, std::F)
499 #define TVEC_STD_BINARY_FUNCTION(F) TVEC_BINARY_FUNCTION(F, std::F)
500 
504 TVEC_STD_BINARY_FUNCTION(remainder)
505 
509 
514 
519 
527 
534 
541 
546 #undef TVEC_STD_UNARY_FUNCTION
547 
548 ///@}
549 ///@name RVec Fast Mathematical Functions with Vdt
550 ///@{
551 
552 #ifdef R__HAS_VDT
553 #define TVEC_VDT_UNARY_FUNCTION(F) TVEC_UNARY_FUNCTION(F, vdt::F)
554 
555 TVEC_VDT_UNARY_FUNCTION(fast_expf)
556 TVEC_VDT_UNARY_FUNCTION(fast_logf)
557 TVEC_VDT_UNARY_FUNCTION(fast_sinf)
558 TVEC_VDT_UNARY_FUNCTION(fast_cosf)
559 TVEC_VDT_UNARY_FUNCTION(fast_tanf)
560 TVEC_VDT_UNARY_FUNCTION(fast_asinf)
561 TVEC_VDT_UNARY_FUNCTION(fast_acosf)
562 TVEC_VDT_UNARY_FUNCTION(fast_atanf)
563 
564 TVEC_VDT_UNARY_FUNCTION(fast_exp)
565 TVEC_VDT_UNARY_FUNCTION(fast_log)
566 TVEC_VDT_UNARY_FUNCTION(fast_sin)
567 TVEC_VDT_UNARY_FUNCTION(fast_cos)
568 TVEC_VDT_UNARY_FUNCTION(fast_tan)
569 TVEC_VDT_UNARY_FUNCTION(fast_asin)
570 TVEC_VDT_UNARY_FUNCTION(fast_acos)
571 TVEC_VDT_UNARY_FUNCTION(fast_atan)
572 #undef TVEC_VDT_UNARY_FUNCTION
573 
574 #endif // R__HAS_VDT
575 
576 #undef TVEC_UNARY_FUNCTION
577 
578 ///@}
579 
580 /// Inner product
581 template <typename T, typename V>
582 auto Dot(const RVec<T> &v0, const RVec<V> &v1) -> decltype(v0[0] * v1[0])
583 {
584  if (v0.size() != v1.size())
585  throw std::runtime_error("Cannot compute inner product of vectors of different sizes");
586  return std::inner_product(v0.begin(), v0.end(), v1.begin(), decltype(v0[0] * v1[0])(0));
587 }
588 
589 /// Sum elements
590 template <typename T>
591 T Sum(const RVec<T> &v)
592 {
593  return std::accumulate(v.begin(), v.end(), T(0));
594 }
595 
596 /// Get Mean
597 template <typename T>
598 double Mean(const RVec<T> &v)
599 {
600  if (v.empty()) return 0.;
601  return double(Sum(v)) / v.size();
602 }
603 
604 /// Get variance
605 template <typename T>
606 double Var(const RVec<T> &v)
607 {
608  const std::size_t size = v.size();
609  if (size < std::size_t(2)) return 0.;
610  T sum_squares(0), squared_sum(0);
611  auto pred = [&sum_squares, &squared_sum](const T& x) {sum_squares+=x*x; squared_sum+=x;};
612  std::for_each(v.begin(), v.end(), pred);
613  squared_sum *= squared_sum;
614  const auto dsize = (double) size;
615  return 1. / (dsize - 1.) * (sum_squares - squared_sum / dsize );
616 }
617 
618 /// Get standard deviation
619 template <typename T>
620 double StdDev(const RVec<T> &v)
621 {
622  return std::sqrt(Var(v));
623 }
624 
625 /// Create new collection applying a callable to the elements of the input collection
626 template <typename T, typename F>
628 {
629  RVec<decltype(f(v[0]))> ret(v.size());
630  std::transform(v.begin(), v.end(), ret.begin(), f);
631  return ret;
632 }
633 
634 /// Create a new collection with the elements passing the filter expressed by the predicate
635 template <typename T, typename F>
636 RVec<T> Filter(const RVec<T> &v, F &&f)
637 {
638  const auto thisSize = v.size();
639  RVec<T> w;
640  w.reserve(thisSize);
641  for (auto &&val : v) {
642  if (f(val))
643  w.emplace_back(val);
644  }
645  return w;
646 }
647 
648 template <typename T>
649 void swap(RVec<T> &lhs, RVec<T> &rhs)
650 {
651  lhs.swap(rhs);
652 }
653 
654 ////////////////////////////////////////////////////////////////////////////////
655 /// Print a RVec at the prompt:
656 template <class T>
657 std::ostream &operator<<(std::ostream &os, const RVec<T> &v)
658 {
659  // In order to print properly, convert to 64 bit int if this is a char
660  constexpr bool mustConvert = std::is_same<char, T>::value || std::is_same<signed char, T>::value ||
661  std::is_same<unsigned char, T>::value || std::is_same<wchar_t, T>::value ||
662  std::is_same<char16_t, T>::value || std::is_same<char32_t, T>::value;
664  os << "{ ";
665  auto size = v.size();
666  if (size) {
667  for (std::size_t i = 0; i < size - 1; ++i) {
668  os << (Print_t)v[i] << ", ";
669  }
670  os << (Print_t)v[size - 1];
671  }
672  os << " }";
673  return os;
674 }
675 
676 #if (_VECOPS_USE_EXTERN_TEMPLATES)
677 
678 #define TVEC_EXTERN_UNARY_OPERATOR(T, OP) \
679  extern template RVec<T> operator OP<T>(const RVec<T> &);
680 
681 #define TVEC_EXTERN_BINARY_OPERATOR(T, OP) \
682  extern template auto operator OP<T, T>(const T &x, const RVec<T> &v) \
683  -> RVec<decltype(x OP v[0])>; \
684  extern template auto operator OP<T, T>(const RVec<T> &v, const T &y) \
685  -> RVec<decltype(v[0] OP y)>; \
686  extern template auto operator OP<T, T>(const RVec<T> &v0, const RVec<T> &v1)\
687  -> RVec<decltype(v0[0] OP v1[0])>;
688 
689 #define TVEC_EXTERN_ASSIGN_OPERATOR(T, OP) \
690  extern template RVec<T> &operator OP<T, T>(RVec<T> &, const T &); \
691  extern template RVec<T> &operator OP<T, T>(RVec<T> &, const RVec<T> &);
692 
693 #define TVEC_EXTERN_LOGICAL_OPERATOR(T, OP) \
694  extern template RVec<int> operator OP<T, T>(const RVec<T> &, const T &); \
695  extern template RVec<int> operator OP<T, T>(const T &, const RVec<T> &); \
696  extern template RVec<int> operator OP<T, T>(const RVec<T> &, const RVec<T> &);
697 
698 #define TVEC_EXTERN_FLOAT_TEMPLATE(T) \
699  extern template class RVec<T>; \
700  TVEC_EXTERN_UNARY_OPERATOR(T, +) \
701  TVEC_EXTERN_UNARY_OPERATOR(T, -) \
702  TVEC_EXTERN_UNARY_OPERATOR(T, !) \
703  TVEC_EXTERN_BINARY_OPERATOR(T, +) \
704  TVEC_EXTERN_BINARY_OPERATOR(T, -) \
705  TVEC_EXTERN_BINARY_OPERATOR(T, *) \
706  TVEC_EXTERN_BINARY_OPERATOR(T, /) \
707  TVEC_EXTERN_ASSIGN_OPERATOR(T, +=) \
708  TVEC_EXTERN_ASSIGN_OPERATOR(T, -=) \
709  TVEC_EXTERN_ASSIGN_OPERATOR(T, *=) \
710  TVEC_EXTERN_ASSIGN_OPERATOR(T, /=) \
711  TVEC_EXTERN_LOGICAL_OPERATOR(T, <) \
712  TVEC_EXTERN_LOGICAL_OPERATOR(T, >) \
713  TVEC_EXTERN_LOGICAL_OPERATOR(T, ==) \
714  TVEC_EXTERN_LOGICAL_OPERATOR(T, !=) \
715  TVEC_EXTERN_LOGICAL_OPERATOR(T, <=) \
716  TVEC_EXTERN_LOGICAL_OPERATOR(T, >=) \
717  TVEC_EXTERN_LOGICAL_OPERATOR(T, &&) \
718  TVEC_EXTERN_LOGICAL_OPERATOR(T, ||)
719 
720 #define TVEC_EXTERN_INTEGER_TEMPLATE(T) \
721  extern template class RVec<T>; \
722  TVEC_EXTERN_UNARY_OPERATOR(T, +) \
723  TVEC_EXTERN_UNARY_OPERATOR(T, -) \
724  TVEC_EXTERN_UNARY_OPERATOR(T, ~) \
725  TVEC_EXTERN_UNARY_OPERATOR(T, !) \
726  TVEC_EXTERN_BINARY_OPERATOR(T, +) \
727  TVEC_EXTERN_BINARY_OPERATOR(T, -) \
728  TVEC_EXTERN_BINARY_OPERATOR(T, *) \
729  TVEC_EXTERN_BINARY_OPERATOR(T, /) \
730  TVEC_EXTERN_BINARY_OPERATOR(T, %) \
731  TVEC_EXTERN_BINARY_OPERATOR(T, &) \
732  TVEC_EXTERN_BINARY_OPERATOR(T, |) \
733  TVEC_EXTERN_BINARY_OPERATOR(T, ^) \
734  TVEC_EXTERN_ASSIGN_OPERATOR(T, +=) \
735  TVEC_EXTERN_ASSIGN_OPERATOR(T, -=) \
736  TVEC_EXTERN_ASSIGN_OPERATOR(T, *=) \
737  TVEC_EXTERN_ASSIGN_OPERATOR(T, /=) \
738  TVEC_EXTERN_ASSIGN_OPERATOR(T, %=) \
739  TVEC_EXTERN_ASSIGN_OPERATOR(T, &=) \
740  TVEC_EXTERN_ASSIGN_OPERATOR(T, |=) \
741  TVEC_EXTERN_ASSIGN_OPERATOR(T, ^=) \
742  TVEC_EXTERN_ASSIGN_OPERATOR(T, >>=) \
743  TVEC_EXTERN_ASSIGN_OPERATOR(T, <<=) \
744  TVEC_EXTERN_LOGICAL_OPERATOR(T, <) \
745  TVEC_EXTERN_LOGICAL_OPERATOR(T, >) \
746  TVEC_EXTERN_LOGICAL_OPERATOR(T, ==) \
747  TVEC_EXTERN_LOGICAL_OPERATOR(T, !=) \
748  TVEC_EXTERN_LOGICAL_OPERATOR(T, <=) \
749  TVEC_EXTERN_LOGICAL_OPERATOR(T, >=) \
750  TVEC_EXTERN_LOGICAL_OPERATOR(T, &&) \
751  TVEC_EXTERN_LOGICAL_OPERATOR(T, ||)
752 
753 TVEC_EXTERN_INTEGER_TEMPLATE(char)
754 TVEC_EXTERN_INTEGER_TEMPLATE(short)
755 TVEC_EXTERN_INTEGER_TEMPLATE(int)
756 TVEC_EXTERN_INTEGER_TEMPLATE(long)
757 //TVEC_EXTERN_INTEGER_TEMPLATE(long long)
758 
759 TVEC_EXTERN_INTEGER_TEMPLATE(unsigned char)
760 TVEC_EXTERN_INTEGER_TEMPLATE(unsigned short)
761 TVEC_EXTERN_INTEGER_TEMPLATE(unsigned int)
762 TVEC_EXTERN_INTEGER_TEMPLATE(unsigned long)
763 //TVEC_EXTERN_INTEGER_TEMPLATE(unsigned long long)
764 
765 TVEC_EXTERN_FLOAT_TEMPLATE(float)
766 TVEC_EXTERN_FLOAT_TEMPLATE(double)
767 
768 #undef TVEC_EXTERN_UNARY_OPERATOR
769 #undef TVEC_EXTERN_BINARY_OPERATOR
770 #undef TVEC_EXTERN_ASSIGN_OPERATOR
771 #undef TVEC_EXTERN_LOGICAL_OPERATOR
772 #undef TVEC_EXTERN_INTEGER_TEMPLATE
773 #undef TVEC_EXTERN_FLOAT_TEMPLATE
774 
775 #define TVEC_EXTERN_UNARY_FUNCTION(T, NAME, FUNC) \
776  extern template RVec<PromoteType<T>> NAME(const RVec<T> &);
777 
778 #define TVEC_EXTERN_STD_UNARY_FUNCTION(T, F) TVEC_EXTERN_UNARY_FUNCTION(T, F, std::F)
779 
780 #define TVEC_EXTERN_BINARY_FUNCTION(T0, T1, NAME, FUNC) \
781  extern template RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &, const T1 &); \
782  extern template RVec<PromoteTypes<T0, T1>> NAME(const T0 &, const RVec<T1> &); \
783  extern template RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &, const RVec<T1> &);
784 
785 #define TVEC_EXTERN_STD_BINARY_FUNCTION(T, F) TVEC_EXTERN_BINARY_FUNCTION(T, T, F, std::F)
786 
787 #define TVEC_EXTERN_STD_FUNCTIONS(T) \
788  TVEC_EXTERN_STD_UNARY_FUNCTION(T, abs) \
789  TVEC_EXTERN_STD_BINARY_FUNCTION(T, fdim) \
790  TVEC_EXTERN_STD_BINARY_FUNCTION(T, fmod) \
791  TVEC_EXTERN_STD_BINARY_FUNCTION(T, remainder) \
792  TVEC_EXTERN_STD_UNARY_FUNCTION(T, exp) \
793  TVEC_EXTERN_STD_UNARY_FUNCTION(T, exp2) \
794  TVEC_EXTERN_STD_UNARY_FUNCTION(T, expm1) \
795  TVEC_EXTERN_STD_UNARY_FUNCTION(T, log) \
796  TVEC_EXTERN_STD_UNARY_FUNCTION(T, log10) \
797  TVEC_EXTERN_STD_UNARY_FUNCTION(T, log2) \
798  TVEC_EXTERN_STD_UNARY_FUNCTION(T, log1p) \
799  TVEC_EXTERN_STD_BINARY_FUNCTION(T, pow) \
800  TVEC_EXTERN_STD_UNARY_FUNCTION(T, sqrt) \
801  TVEC_EXTERN_STD_UNARY_FUNCTION(T, cbrt) \
802  TVEC_EXTERN_STD_BINARY_FUNCTION(T, hypot) \
803  TVEC_EXTERN_STD_UNARY_FUNCTION(T, sin) \
804  TVEC_EXTERN_STD_UNARY_FUNCTION(T, cos) \
805  TVEC_EXTERN_STD_UNARY_FUNCTION(T, tan) \
806  TVEC_EXTERN_STD_UNARY_FUNCTION(T, asin) \
807  TVEC_EXTERN_STD_UNARY_FUNCTION(T, acos) \
808  TVEC_EXTERN_STD_UNARY_FUNCTION(T, atan) \
809  TVEC_EXTERN_STD_BINARY_FUNCTION(T, atan2) \
810  TVEC_EXTERN_STD_UNARY_FUNCTION(T, sinh) \
811  TVEC_EXTERN_STD_UNARY_FUNCTION(T, cosh) \
812  TVEC_EXTERN_STD_UNARY_FUNCTION(T, tanh) \
813  TVEC_EXTERN_STD_UNARY_FUNCTION(T, asinh) \
814  TVEC_EXTERN_STD_UNARY_FUNCTION(T, acosh) \
815  TVEC_EXTERN_STD_UNARY_FUNCTION(T, atanh) \
816  TVEC_EXTERN_STD_UNARY_FUNCTION(T, floor) \
817  TVEC_EXTERN_STD_UNARY_FUNCTION(T, ceil) \
818  TVEC_EXTERN_STD_UNARY_FUNCTION(T, trunc) \
819  TVEC_EXTERN_STD_UNARY_FUNCTION(T, round) \
820  TVEC_EXTERN_STD_UNARY_FUNCTION(T, erf) \
821  TVEC_EXTERN_STD_UNARY_FUNCTION(T, erfc) \
822  TVEC_EXTERN_STD_UNARY_FUNCTION(T, lgamma) \
823  TVEC_EXTERN_STD_UNARY_FUNCTION(T, tgamma) \
824 
825 TVEC_EXTERN_STD_FUNCTIONS(float)
826 TVEC_EXTERN_STD_FUNCTIONS(double)
827 #undef TVEC_EXTERN_STD_UNARY_FUNCTION
828 #undef TVEC_EXTERN_STD_BINARY_FUNCTION
829 #undef TVEC_EXTERN_STD_UNARY_FUNCTIONS
830 
831 #ifdef R__HAS_VDT
832 
833 #define TVEC_EXTERN_VDT_UNARY_FUNCTION(T, F) TVEC_EXTERN_UNARY_FUNCTION(T, F, vdt::F)
834 
835 TVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_expf)
836 TVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_logf)
837 TVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_sinf)
838 TVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_cosf)
839 TVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_tanf)
840 TVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_asinf)
841 TVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_acosf)
842 TVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_atanf)
843 
844 TVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_exp)
845 TVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_log)
846 TVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_sin)
847 TVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_cos)
848 TVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_tan)
849 TVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_asin)
850 TVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_acos)
851 TVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_atan)
852 
853 #endif // R__HAS_VDT
854 
855 #endif // _VECOPS_USE_EXTERN_TEMPLATES
856 
857 } // End of VecOps NS
858 
859 } // End of ROOT NS
860 
861 #endif
#define TVEC_STD_BINARY_FUNCTION(F)
Definition: RVec.hxx:499
double erf(double x)
Error function encountered in integrating the normal distribution.
double tanh(double)
void resize(size_type count)
Definition: RVec.hxx:280
typename Impl_t::difference_type difference_type
Definition: RVec.hxx:151
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
auto Map(const RVec< T > &v, F &&f) -> RVec< decltype(f(v[0]))>
Create new collection applying a callable to the elements of the input collection.
Definition: RVec.hxx:627
RVec(RVec< T > &&v)
Definition: RVec.hxx:174
const_reference back() const
Definition: RVec.hxx:238
typename Impl_t::const_reverse_iterator const_reverse_iterator
Definition: RVec.hxx:159
void push_back(T &&value)
Definition: RVec.hxx:265
RVec(size_type count)
Definition: RVec.hxx:168
RVec< T > & operator=(std::initializer_list< T > ilist)
Definition: RVec.hxx:198
const T * data() const noexcept
Definition: RVec.hxx:240
double T(double x)
Definition: ChebyshevPol.h:34
#define TVEC_ASSIGNMENT_OPERATOR(OP)
Definition: RVec.hxx:359
const_iterator cend() const noexcept
Definition: RVec.hxx:247
const_reverse_iterator crend() const noexcept
Definition: RVec.hxx:253
T * data() noexcept
Definition: RVec.hxx:239
typename Impl_t::const_reference const_reference
Definition: RVec.hxx:153
double inner_product(const LAVector &, const LAVector &)
#define f(i)
Definition: RSha256.hxx:104
iterator begin() noexcept
Definition: RVec.hxx:242
RVec(const RVec< T > &v)
Definition: RVec.hxx:172
STL namespace.
#define TVEC_LOGICAL_OPERATOR(OP)
Definition: RVec.hxx:395
void swap(RVec< T > &lhs, RVec< T > &rhs)
Definition: RVec.hxx:649
double Var(const RVec< T > &v)
Get variance.
Definition: RVec.hxx:606
double tgamma(double x)
The gamma function is defined to be the extension of the factorial to real numbers.
const_iterator cbegin() const noexcept
Definition: RVec.hxx:244
double cos(double)
double erfc(double x)
Complementary error function.
bool empty() const noexcept
Definition: RVec.hxx:255
RVec< T > & operator=(RVec< T > &&v)
Definition: RVec.hxx:192
typename std::vector< ColumnValue_t, ::ROOT::Detail::VecOps::RAdoptAllocator< ColumnValue_t > > Impl_t
Definition: RVec.hxx:148
double sqrt(double)
Double_t x[n]
Definition: legend1.C:17
size_type size() const noexcept
Definition: RVec.hxx:256
double acos(double)
RVec operator[](const RVec< V > &conds) const
Definition: RVec.hxx:220
double sinh(double)
double log10(double)
size_type max_size() const noexcept
Definition: RVec.hxx:257
typename Impl_t::size_type size_type
Definition: RVec.hxx:150
double pow(double, double)
typename Impl_t::reverse_iterator reverse_iterator
Definition: RVec.hxx:158
void reserve(size_type new_cap)
Definition: RVec.hxx:258
iterator erase(iterator first, iterator last)
Definition: RVec.hxx:264
RVec< T > & operator=(const RVec< T > &v)
Definition: RVec.hxx:186
void shrink_to_fit()
Definition: RVec.hxx:260
double sin(double)
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:636
A "std::vector"-like collection of values implementing handy operation to analyse them...
Definition: RVec.hxx:146
typename Impl_t::const_pointer const_pointer
Definition: RVec.hxx:155
#define TVEC_BINARY_OPERATOR(OP)
Definition: RVec.hxx:311
double Mean(const RVec< T > &v)
Get Mean.
Definition: RVec.hxx:598
size_type capacity() const noexcept
Definition: RVec.hxx:259
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:275
const_reference front() const
Definition: RVec.hxx:236
#define F(x, y, z)
const_reverse_iterator rbegin() const noexcept
Definition: RVec.hxx:249
const_reverse_iterator crbegin() const noexcept
Definition: RVec.hxx:250
void resize(size_type count, const value_type &value)
Definition: RVec.hxx:281
void pop_back()
Definition: RVec.hxx:279
RVec(std::initializer_list< T > init)
Definition: RVec.hxx:183
iterator end() noexcept
Definition: RVec.hxx:245
#define TVEC_UNARY_OPERATOR(OP)
Definition: RVec.hxx:288
SVector< double, 2 > v
Definition: Dict.h:5
double cosh(double)
double expm1(double x)
exp(x) -1 with error cancellation when x is small
Definition: Math.h:112
const_iterator end() const noexcept
Definition: RVec.hxx:246
#define TVEC_STD_UNARY_FUNCTION(F)
Definition: RVec.hxx:498
double floor(double)
reference operator[](size_type pos)
Definition: RVec.hxx:216
RVec(size_type count, const T &value)
Definition: RVec.hxx:170
double asin(double)
reference emplace_back(Args &&... args)
Definition: RVec.hxx:267
double log1p(double x)
declarations for functions which are not implemented by some compilers
Definition: Math.h:100
reference front()
Definition: RVec.hxx:235
typename Impl_t::pointer pointer
Definition: RVec.hxx:154
decltype(PromoteType< U >()+PromoteType< V >()) PromoteTypes
Definition: RVec.hxx:455
double StdDev(const RVec< T > &v)
Get standard deviation.
Definition: RVec.hxx:620
static Int_t init()
double atan2(double, double)
int type
Definition: TGX11.cxx:120
double atan(double)
auto Dot(const RVec< T > &v0, const RVec< V > &v1) -> decltype(v0[0] *v1[0])
Inner product.
Definition: RVec.hxx:582
typename Impl_t::reference reference
Definition: RVec.hxx:152
reverse_iterator rbegin() noexcept
Definition: RVec.hxx:248
const_iterator begin() const noexcept
Definition: RVec.hxx:243
void clear() noexcept
Definition: RVec.hxx:262
T Sum(const RVec< T > &v)
Sum elements.
Definition: RVec.hxx:591
const_reference operator[](size_type pos) const
Definition: RVec.hxx:217
reverse_iterator rend() noexcept
Definition: RVec.hxx:251
typename PromoteTypeImpl< T >::Type PromoteType
Definition: RVec.hxx:452
RVec(InputIt first, InputIt last)
Definition: RVec.hxx:181
double ceil(double)
double tan(double)
iterator erase(iterator pos)
Definition: RVec.hxx:263
RVec(const std::vector< T > &v)
Definition: RVec.hxx:176
const_reference at(size_type pos) const
Definition: RVec.hxx:215
void swap(RVec< T > &other)
Definition: RVec.hxx:282
Definition: first.py:1
typename Impl_t::value_type value_type
Definition: RVec.hxx:149
double lgamma(double x)
Calculates the logarithm of the gamma function.
const_reverse_iterator rend() const noexcept
Definition: RVec.hxx:252
double exp(double)
typename Impl_t::iterator iterator
Definition: RVec.hxx:156
const Int_t n
Definition: legend1.C:16
double log(double)
RVec(pointer p, size_type n)
Definition: RVec.hxx:178
reference back()
Definition: RVec.hxx:237
reference at(size_type pos)
Definition: RVec.hxx:214
typename Impl_t::const_iterator const_iterator
Definition: RVec.hxx:157