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