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