19 #define _VECOPS_USE_EXTERN_TEMPLATES false
21 #define _VECOPS_USE_EXTERN_TEMPLATES true
35 #include <type_traits>
39 #define _USE_MATH_DEFINES // enable definition of M_PI
48 #include <vdt/vdtMath.h>
62 using RVec = ROOT::VecOps::RVec<T>;
64 template <
typename... T>
65 std::size_t GetVectorsSize(std::string_view
id,
const RVec<T> &... vs)
67 constexpr
const auto nArgs =
sizeof...(T);
68 const std::size_t sizes[] = {vs.size()...};
70 for (
auto i = 1UL; i < nArgs; i++) {
71 if (sizes[0] == sizes[i])
74 msg +=
": input RVec instances have different lengths!";
75 throw std::runtime_error(msg);
81 template <
typename F,
typename... T>
82 auto MapImpl(F &&f,
const RVec<T> &... vs) -> RVec<decltype(f(vs[0]...))>
84 const auto size = GetVectorsSize(
"Map", vs...);
85 RVec<decltype(f(vs[0]...))> ret(size);
87 for (
auto i = 0UL; i < size; i++)
93 template <
typename Tuple_t, std::size_t... Is>
94 auto 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)...))
97 constexpr
const auto tupleSizeM1 = std::tuple_size<Tuple_t>::value - 1;
98 return MapImpl(std::get<tupleSizeM1>(t), std::get<Is>(t)...);
110 template <
typename T,
typename... Args>
111 void EmplaceBack(T &v, Args &&... args)
113 v.emplace_back(std::forward<Args>(args)...);
116 template <
typename... Args>
117 void EmplaceBack(std::vector<bool> &v, Args &&... args)
119 v.push_back(std::forward<Args>(args)...);
273 template <
typename T>
279 static constexpr
const auto IsVecBool = std::is_same<bool, T>::value;
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;
291 using data_t =
typename std::conditional<IsVecBool, void, typename Impl_t::pointer>::type;
292 using const_data_t =
typename std::conditional<IsVecBool, void, typename Impl_t::const_pointer>::type;
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;
305 explicit RVec(size_type count) : fData(count) {}
307 RVec(size_type count,
const T &value) : fData(count, value) {}
309 RVec(
const RVec<T> &v) : fData(v.fData) {}
311 RVec(RVec<T> &&v) : fData(std::move(v.fData)) {}
313 RVec(
const std::vector<T> &v) : fData(v.cbegin(), v.cend()) {}
315 RVec(pointer p, size_type n) : fData(n, T(), ROOT::Detail::VecOps::RAdoptAllocator<T>(p)) {}
317 template <
class InputIt>
318 RVec(InputIt first, InputIt last) : fData(first, last) {}
320 RVec(std::initializer_list<T> init) : fData(init) {}
323 RVec<T> &operator=(
const RVec<T> &v)
329 RVec<T> &operator=(RVec<T> &&v)
331 std::swap(fData, v.fData);
335 RVec<T> &operator=(std::initializer_list<T> ilist)
342 template <typename U, typename = std::enable_if<std::is_convertible<T, U>::value>>
343 operator RVec<U>()
const
346 std::copy(begin(), end(), ret.begin());
350 const Impl_t &AsVector()
const {
return fData; }
351 Impl_t &AsVector() {
return fData; }
354 reference at(size_type pos) {
return fData.at(pos); }
355 const_reference at(size_type pos)
const {
return fData.at(pos); }
357 value_type at(size_type pos, value_type fallback) {
return pos < fData.size() ? fData[pos] : fallback; }
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]; }
363 template <typename V, typename = std::enable_if<std::is_convertible<V, bool>::value>>
364 RVec operator[](
const RVec<V> &conds)
const
366 const size_type n = conds.size();
369 throw std::runtime_error(
"Cannot index RVec with condition vector of different size");
373 for (size_type i = 0; i < n; ++i)
375 ret.emplace_back(fData[i]);
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(); }
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(); }
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(); };
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)
414 ROOT::Internal::VecOps::EmplaceBack(fData, std::forward<Args>(args)...);
419 template<typename U = T, typename std::enable_if<std::is_arithmetic<U>::value,
int>* =
nullptr>
420 iterator emplace(const_iterator pos, U value)
422 return fData.emplace(pos, value);
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); }
433 #define RVEC_UNARY_OPERATOR(OP) \
434 template <typename T> \
435 RVec<T> operator OP(const RVec<T> &v) \
438 for (auto &x : ret) \
443 RVEC_UNARY_OPERATOR(+)
444 RVEC_UNARY_OPERATOR(-)
445 RVEC_UNARY_OPERATOR(~)
446 RVEC_UNARY_OPERATOR(!)
447 #undef RVEC_UNARY_OPERATOR
453 #define ERROR_MESSAGE(OP) \
454 "Cannot call operator " #OP " on vectors of different sizes."
456 #define RVEC_BINARY_OPERATOR(OP) \
457 template <typename T0, typename T1> \
458 auto operator OP(const RVec<T0> &v, const T1 &y) \
459 -> RVec<decltype(v[0] OP y)> \
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); \
467 template <typename T0, typename T1> \
468 auto operator OP(const T0 &x, const RVec<T1> &v) \
469 -> RVec<decltype(x OP v[0])> \
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); \
477 template <typename T0, typename T1> \
478 auto operator OP(const RVec<T0> &v0, const RVec<T1> &v1) \
479 -> RVec<decltype(v0[0] OP v1[0])> \
481 if (v0.size() != v1.size()) \
482 throw std::runtime_error(ERROR_MESSAGE(OP)); \
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); \
490 RVEC_BINARY_OPERATOR(+)
491 RVEC_BINARY_OPERATOR(-)
492 RVEC_BINARY_OPERATOR(*)
493 RVEC_BINARY_OPERATOR(/)
494 RVEC_BINARY_OPERATOR(%)
495 RVEC_BINARY_OPERATOR(^)
496 RVEC_BINARY_OPERATOR(|)
497 RVEC_BINARY_OPERATOR(&)
498 #undef RVEC_BINARY_OPERATOR
504 #define RVEC_ASSIGNMENT_OPERATOR(OP) \
505 template <typename T0, typename T1> \
506 RVec<T0>& operator OP(RVec<T0> &v, const T1 &y) \
508 auto op = [&y](T0 &x) { return x OP y; }; \
509 std::transform(v.begin(), v.end(), v.begin(), op); \
513 template <typename T0, typename T1> \
514 RVec<T0>& operator OP(RVec<T0> &v0, const RVec<T1> &v1) \
516 if (v0.size() != v1.size()) \
517 throw std::runtime_error(ERROR_MESSAGE(OP)); \
519 auto op = [](T0 &x, const T1 &y) { return x OP y; }; \
520 std::transform(v0.begin(), v0.end(), v1.begin(), v0.begin(), op); \
524 RVEC_ASSIGNMENT_OPERATOR(+=)
525 RVEC_ASSIGNMENT_OPERATOR(-=)
526 RVEC_ASSIGNMENT_OPERATOR(*=)
527 RVEC_ASSIGNMENT_OPERATOR(/=)
528 RVEC_ASSIGNMENT_OPERATOR(%=)
529 RVEC_ASSIGNMENT_OPERATOR(^=)
530 RVEC_ASSIGNMENT_OPERATOR(|=)
531 RVEC_ASSIGNMENT_OPERATOR(&=)
532 RVEC_ASSIGNMENT_OPERATOR(>>=)
533 RVEC_ASSIGNMENT_OPERATOR(<<=)
534 #undef RVEC_ASSIGNMENT_OPERATOR
540 #define RVEC_LOGICAL_OPERATOR(OP) \
541 template <typename T0, typename T1> \
542 auto operator OP(const RVec<T0> &v, const T1 &y) \
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); \
551 template <typename T0, typename T1> \
552 auto operator OP(const T0 &x, const RVec<T1> &v) \
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); \
561 template <typename T0, typename T1> \
562 auto operator OP(const RVec<T0> &v0, const RVec<T1> &v1) \
565 if (v0.size() != v1.size()) \
566 throw std::runtime_error(ERROR_MESSAGE(OP)); \
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); \
574 RVEC_LOGICAL_OPERATOR(<)
575 RVEC_LOGICAL_OPERATOR(>)
576 RVEC_LOGICAL_OPERATOR(==)
577 RVEC_LOGICAL_OPERATOR(!=)
578 RVEC_LOGICAL_OPERATOR(<=)
579 RVEC_LOGICAL_OPERATOR(>=)
580 RVEC_LOGICAL_OPERATOR(&&)
581 RVEC_LOGICAL_OPERATOR(||)
582 #undef RVEC_LOGICAL_OPERATOR
589 template <
typename T>
struct PromoteTypeImpl;
591 template <>
struct PromoteTypeImpl<float> {
using Type = float; };
592 template <>
struct PromoteTypeImpl<double> {
using Type = double; };
593 template <>
struct PromoteTypeImpl<long double> {
using Type =
long double; };
595 template <
typename T>
struct PromoteTypeImpl {
using Type = double; };
597 template <
typename T>
598 using PromoteType =
typename PromoteTypeImpl<T>::Type;
600 template <
typename U,
typename V>
601 using PromoteTypes = decltype(PromoteType<U>() + PromoteType<V>());
605 #define RVEC_UNARY_FUNCTION(NAME, FUNC) \
606 template <typename T> \
607 RVec<PromoteType<T>> NAME(const RVec<T> &v) \
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); \
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) \
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); \
625 template <typename T0, typename T1> \
626 RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v, const T1 &y) \
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); \
634 template <typename T0, typename T1> \
635 RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v0, const RVec<T1> &v1) \
637 if (v0.size() != v1.size()) \
638 throw std::runtime_error(ERROR_MESSAGE(NAME)); \
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); \
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)
649 RVEC_STD_UNARY_FUNCTION(abs)
650 RVEC_STD_BINARY_FUNCTION(fdim)
651 RVEC_STD_BINARY_FUNCTION(fmod)
652 RVEC_STD_BINARY_FUNCTION(remainder)
654 RVEC_STD_UNARY_FUNCTION(exp)
655 RVEC_STD_UNARY_FUNCTION(exp2)
656 RVEC_STD_UNARY_FUNCTION(expm1)
658 RVEC_STD_UNARY_FUNCTION(log)
659 RVEC_STD_UNARY_FUNCTION(log10)
660 RVEC_STD_UNARY_FUNCTION(log2)
661 RVEC_STD_UNARY_FUNCTION(log1p)
663 RVEC_STD_BINARY_FUNCTION(pow)
664 RVEC_STD_UNARY_FUNCTION(sqrt)
665 RVEC_STD_UNARY_FUNCTION(cbrt)
666 RVEC_STD_BINARY_FUNCTION(hypot)
668 RVEC_STD_UNARY_FUNCTION(sin)
669 RVEC_STD_UNARY_FUNCTION(cos)
670 RVEC_STD_UNARY_FUNCTION(tan)
671 RVEC_STD_UNARY_FUNCTION(asin)
672 RVEC_STD_UNARY_FUNCTION(acos)
673 RVEC_STD_UNARY_FUNCTION(atan)
674 RVEC_STD_BINARY_FUNCTION(atan2)
676 RVEC_STD_UNARY_FUNCTION(sinh)
677 RVEC_STD_UNARY_FUNCTION(cosh)
678 RVEC_STD_UNARY_FUNCTION(tanh)
679 RVEC_STD_UNARY_FUNCTION(asinh)
680 RVEC_STD_UNARY_FUNCTION(acosh)
681 RVEC_STD_UNARY_FUNCTION(atanh)
683 RVEC_STD_UNARY_FUNCTION(floor)
684 RVEC_STD_UNARY_FUNCTION(ceil)
685 RVEC_STD_UNARY_FUNCTION(trunc)
686 RVEC_STD_UNARY_FUNCTION(round)
687 RVEC_STD_UNARY_FUNCTION(lround)
688 RVEC_STD_UNARY_FUNCTION(llround)
690 RVEC_STD_UNARY_FUNCTION(erf)
691 RVEC_STD_UNARY_FUNCTION(erfc)
692 RVEC_STD_UNARY_FUNCTION(lgamma)
693 RVEC_STD_UNARY_FUNCTION(tgamma)
694 #undef RVEC_STD_UNARY_FUNCTION
701 #define RVEC_VDT_UNARY_FUNCTION(F) RVEC_UNARY_FUNCTION(F, vdt::F)
703 RVEC_VDT_UNARY_FUNCTION(fast_expf)
704 RVEC_VDT_UNARY_FUNCTION(fast_logf)
705 RVEC_VDT_UNARY_FUNCTION(fast_sinf)
706 RVEC_VDT_UNARY_FUNCTION(fast_cosf)
707 RVEC_VDT_UNARY_FUNCTION(fast_tanf)
708 RVEC_VDT_UNARY_FUNCTION(fast_asinf)
709 RVEC_VDT_UNARY_FUNCTION(fast_acosf)
710 RVEC_VDT_UNARY_FUNCTION(fast_atanf)
712 RVEC_VDT_UNARY_FUNCTION(fast_exp)
713 RVEC_VDT_UNARY_FUNCTION(fast_log)
714 RVEC_VDT_UNARY_FUNCTION(fast_sin)
715 RVEC_VDT_UNARY_FUNCTION(fast_cos)
716 RVEC_VDT_UNARY_FUNCTION(fast_tan)
717 RVEC_VDT_UNARY_FUNCTION(fast_asin)
718 RVEC_VDT_UNARY_FUNCTION(fast_acos)
719 RVEC_VDT_UNARY_FUNCTION(fast_atan)
720 #undef RVEC_VDT_UNARY_FUNCTION
724 #undef RVEC_UNARY_FUNCTION
739 template <
typename T,
typename V>
740 auto Dot(
const RVec<T> &v0,
const RVec<V> &v1) -> decltype(v0[0] * v1[0])
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));
757 template <
typename T>
758 T Sum(
const RVec<T> &v)
760 return std::accumulate(v.begin(), v.end(), T(0));
774 template <
typename T>
775 double Mean(
const RVec<T> &v)
777 if (v.empty())
return 0.;
778 return double(Sum(v)) / v.size();
791 template <
typename T>
792 T Max(
const RVec<T> &v)
794 return *std::max_element(v.begin(), v.end());
807 template <
typename T>
808 T Min(
const RVec<T> &v)
810 return *std::min_element(v.begin(), v.end());
825 template <
typename T>
826 std::size_t ArgMax(
const RVec<T> &v)
828 return std::distance(v.begin(), std::max_element(v.begin(), v.end()));
843 template <
typename T>
844 std::size_t ArgMin(
const RVec<T> &v)
846 return std::distance(v.begin(), std::min_element(v.begin(), v.end()));
860 template <
typename T>
861 double Var(
const RVec<T> &v)
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 );
884 template <
typename T>
885 double StdDev(
const RVec<T> &v)
887 return std::sqrt(Var(v));
908 template <
typename... Args>
909 auto Map(Args &&... args)
910 -> decltype(ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...),
911 std::make_index_sequence<
sizeof...(args) - 1>()))
923 return ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...),
924 std::make_index_sequence<
sizeof...(args) - 1>());
937 template <
typename T,
typename F>
938 RVec<T> Filter(
const RVec<T> &v, F &&f)
940 const auto thisSize = v.size();
943 for (
auto &&val : v) {
960 template <
typename T>
961 auto Any(
const RVec<T> &v) -> decltype(v[0] ==
true)
979 template <
typename T>
980 auto All(
const RVec<T> &v) -> decltype(v[0] ==
false)
988 template <
typename T>
989 void swap(RVec<T> &lhs, RVec<T> &rhs)
1004 template <
typename T>
1005 RVec<typename RVec<T>::size_type> Argsort(
const RVec<T> &v)
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]; });
1024 template <
typename T>
1025 RVec<T> Take(
const RVec<T> &v,
const RVec<
typename RVec<T>::size_type> &i)
1027 using size_type =
typename RVec<T>::size_type;
1028 const size_type isize = i.size();
1030 for (size_type k = 0; k < isize; k++)
1050 template <
typename T>
1051 RVec<T> Take(
const RVec<T> &v,
const int n)
1053 using size_type =
typename RVec<T>::size_type;
1054 const size_type size = v.size();
1055 const size_type absn = std::abs(n);
1057 std::stringstream ss;
1058 ss <<
"Try to take " << absn <<
" elements but vector has only size " << size <<
".";
1059 throw std::runtime_error(ss.str());
1063 for (size_type k = 0; k < absn; k++)
1064 r[k] = v[size - absn + k];
1066 for (size_type k = 0; k < absn; k++)
1082 template <
typename T>
1083 RVec<T> Reverse(
const RVec<T> &v)
1086 std::reverse(r.begin(), r.end());
1103 template <
typename T>
1104 RVec<T> Sort(
const RVec<T> &v)
1107 std::sort(r.begin(), r.end());
1128 template <
typename T,
typename Compare>
1129 RVec<T> Sort(
const RVec<T> &v, Compare &&c)
1132 std::sort(r.begin(), r.end(), std::forward<Compare>(c));
1148 inline RVec<RVec<std::size_t>> Combinations(
const std::size_t size1,
const std::size_t size2)
1150 using size_type = std::size_t;
1151 RVec<RVec<size_type>> r(2);
1152 r[0].resize(size1*size2);
1153 r[1].resize(size1*size2);
1155 for(size_type i=0; i<size1; i++) {
1156 for(size_type j=0; j<size2; j++) {
1180 template <
typename T1,
typename T2>
1181 RVec<RVec<typename RVec<T1>::size_type>> Combinations(
const RVec<T1> &v1,
const RVec<T2> &v2)
1183 return Combinations(v1.size(), v2.size());
1205 template <
typename T>
1206 RVec<RVec<typename RVec<T>::size_type>> Combinations(
const RVec<T>& v,
const typename RVec<T>::size_type n)
1208 using size_type =
typename RVec<T>::size_type;
1209 const size_type s = v.size();
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());
1215 RVec<size_type> indices(s);
1216 for(size_type k=0; k<s; k++)
1218 RVec<RVec<size_type>> c(n);
1219 for(size_type k=0; k<n; k++)
1220 c[k].emplace_back(indices[k]);
1222 bool run_through =
true;
1225 if (indices[i] != i + s - n){
1226 run_through =
false;
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]);
1251 template <
typename T>
1252 RVec<typename RVec<T>::size_type> Nonzero(
const RVec<T> &v)
1254 using size_type =
typename RVec<T>::size_type;
1256 const auto size = v.size();
1258 for(size_type i=0; i<size; i++) {
1282 template <
typename T>
1283 RVec<T> Intersect(
const RVec<T>& v1,
const RVec<T>& v2,
bool v2_is_sorted =
false)
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();
1290 const auto size = v1.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]);
1316 template <
typename T>
1317 RVec<T> Where(
const RVec<int>& c,
const RVec<T>& v1,
const RVec<T>& v2)
1319 using size_type =
typename RVec<T>::size_type;
1320 const size_type size = c.size();
1323 for (size_type i=0; i<size; i++) {
1324 r.emplace_back(c[i] != 0 ? v1[i] : v2[i]);
1344 template <
typename T>
1345 RVec<T> Where(
const RVec<int>& c,
const RVec<T>& v1, T v2)
1347 using size_type =
typename RVec<T>::size_type;
1348 const size_type size = c.size();
1351 for (size_type i=0; i<size; i++) {
1352 r.emplace_back(c[i] != 0 ? v1[i] : v2);
1372 template <
typename T>
1373 RVec<T> Where(
const RVec<int>& c, T v1,
const RVec<T>& v2)
1375 using size_type =
typename RVec<T>::size_type;
1376 const size_type size = c.size();
1379 for (size_type i=0; i<size; i++) {
1380 r.emplace_back(c[i] != 0 ? v1 : v2[i]);
1398 template <
typename T>
1399 RVec<T> Where(
const RVec<int>& c, T v1, T v2)
1401 using size_type =
typename RVec<T>::size_type;
1402 const size_type size = c.size();
1405 for (size_type i=0; i<size; i++) {
1406 r.emplace_back(c[i] != 0 ? v1 : v2);
1421 template <typename T0, typename T1, typename Common_t = typename std::common_type<T0, T1>::type>
1422 RVec<Common_t> Concatenate(
const RVec<T0> &v0,
const RVec<T1> &v1)
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());
1440 template <
typename T>
1441 T DeltaPhi(T v1, T v2,
const T c = M_PI)
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);
1461 template <
typename T>
1462 RVec<T> DeltaPhi(
const RVec<T>& v1,
const RVec<T>& v2,
const T c = M_PI)
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);
1479 template <
typename T>
1480 RVec<T> DeltaPhi(
const RVec<T>& v1, T v2,
const T c = M_PI)
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);
1497 template <
typename T>
1498 RVec<T> DeltaPhi(T v1,
const RVec<T>& v2,
const T c = M_PI)
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);
1516 template <
typename T>
1517 RVec<T> DeltaR2(
const RVec<T>& eta1,
const RVec<T>& eta2,
const RVec<T>& phi1,
const RVec<T>& phi2,
const T c = M_PI)
1519 const auto dphi = DeltaPhi(phi1, phi2, c);
1520 return (eta1 - eta2) * (eta1 - eta2) + dphi * dphi;
1530 template <
typename T>
1531 RVec<T> DeltaR(
const RVec<T>& eta1,
const RVec<T>& eta2,
const RVec<T>& phi1,
const RVec<T>& phi2,
const T c = M_PI)
1533 return sqrt(DeltaR2(eta1, eta2, phi1, phi2, c));
1543 template <
typename T>
1544 T DeltaR(T eta1, T eta2, T phi1, T phi2,
const T c = M_PI)
1546 const auto dphi = DeltaPhi(phi1, phi2, c);
1547 return std::sqrt((eta1 - eta2) * (eta1 - eta2) + dphi * dphi);
1555 template <
typename T>
1556 RVec<T> InvariantMasses(
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)
1560 std::size_t size = pt1.size();
1562 R__ASSERT(eta1.size() == size && phi1.size() == size && mass1.size() == size);
1563 R__ASSERT(pt2.size() == size && phi2.size() == size && mass2.size() == size);
1565 RVec<T> inv_masses(size);
1567 for (std::size_t i = 0u; i < size; ++i) {
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]);
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]);
1580 const auto e = e1 + e2;
1581 const auto x = x1 + x2;
1582 const auto y = y1 + y2;
1583 const auto z = z1 + z2;
1585 inv_masses[i] = std::sqrt(e * e - x * x - y * y - z * z);
1597 template <
typename T>
1598 T InvariantMass(
const RVec<T>& pt,
const RVec<T>& eta,
const RVec<T>& phi,
const RVec<T>& mass)
1600 const std::size_t size = pt.size();
1602 R__ASSERT(eta.size() == size && phi.size() == size && mass.size() == size);
1609 for (std::size_t i = 0u; i < size; ++ i) {
1611 const auto x = pt[i] * std::cos(phi[i]);
1613 const auto y = pt[i] * std::sin(phi[i]);
1615 const auto z = pt[i] * std::sinh(eta[i]);
1617 const auto e = std::sqrt(x * x + y * y + z * z + mass[i] * mass[i]);
1622 return std::sqrt(e_sum * e_sum - x_sum * x_sum - y_sum * y_sum - z_sum * z_sum);
1643 template <
typename T,
typename... Args_t>
1644 RVec<T> Construct(
const RVec<Args_t> &... args)
1646 const auto size = ::ROOT::Detail::VecOps::GetVectorsSize(
"Construct", args...);
1649 for (
auto i = 0UL; i < size; ++i) {
1650 ret.emplace_back(args[i]...);
1658 std::ostream &operator<<(std::ostream &os, const RVec<T> &v)
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;
1664 using Print_t =
typename std::conditional<mustConvert, long long int, T>::type;
1666 auto size = v.size();
1668 for (std::size_t i = 0; i < size - 1; ++i) {
1669 os << (Print_t)v[i] <<
", ";
1671 os << (Print_t)v[size - 1];
1677 #if (_VECOPS_USE_EXTERN_TEMPLATES)
1679 #define RVEC_EXTERN_UNARY_OPERATOR(T, OP) \
1680 extern template RVec<T> operator OP<T>(const RVec<T> &);
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])>;
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> &);
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> &);
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, ||)
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, ||)
1754 RVEC_EXTERN_INTEGER_TEMPLATE(
char)
1755 RVEC_EXTERN_INTEGER_TEMPLATE(
short)
1756 RVEC_EXTERN_INTEGER_TEMPLATE(
int)
1757 RVEC_EXTERN_INTEGER_TEMPLATE(
long)
1760 RVEC_EXTERN_INTEGER_TEMPLATE(
unsigned char)
1761 RVEC_EXTERN_INTEGER_TEMPLATE(
unsigned short)
1762 RVEC_EXTERN_INTEGER_TEMPLATE(
unsigned int)
1763 RVEC_EXTERN_INTEGER_TEMPLATE(
unsigned long)
1766 RVEC_EXTERN_FLOAT_TEMPLATE(
float)
1767 RVEC_EXTERN_FLOAT_TEMPLATE(
double)
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
1776 #define RVEC_EXTERN_UNARY_FUNCTION(T, NAME, FUNC) \
1777 extern template RVec<PromoteType<T>> NAME(const RVec<T> &);
1779 #define RVEC_EXTERN_STD_UNARY_FUNCTION(T, F) RVEC_EXTERN_UNARY_FUNCTION(T, F, std::F)
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> &);
1786 #define RVEC_EXTERN_STD_BINARY_FUNCTION(T, F) RVEC_EXTERN_BINARY_FUNCTION(T, T, F, std::F)
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) \
1826 RVEC_EXTERN_STD_FUNCTIONS(
float)
1827 RVEC_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
1834 #define RVEC_EXTERN_VDT_UNARY_FUNCTION(T, F) RVEC_EXTERN_UNARY_FUNCTION(T, F, vdt::F)
1836 RVEC_EXTERN_VDT_UNARY_FUNCTION(
float, fast_expf)
1837 RVEC_EXTERN_VDT_UNARY_FUNCTION(
float, fast_logf)
1838 RVEC_EXTERN_VDT_UNARY_FUNCTION(
float, fast_sinf)
1839 RVEC_EXTERN_VDT_UNARY_FUNCTION(
float, fast_cosf)
1840 RVEC_EXTERN_VDT_UNARY_FUNCTION(
float, fast_tanf)
1841 RVEC_EXTERN_VDT_UNARY_FUNCTION(
float, fast_asinf)
1842 RVEC_EXTERN_VDT_UNARY_FUNCTION(
float, fast_acosf)
1843 RVEC_EXTERN_VDT_UNARY_FUNCTION(
float, fast_atanf)
1845 RVEC_EXTERN_VDT_UNARY_FUNCTION(
double, fast_exp)
1846 RVEC_EXTERN_VDT_UNARY_FUNCTION(
double, fast_log)
1847 RVEC_EXTERN_VDT_UNARY_FUNCTION(
double, fast_sin)
1848 RVEC_EXTERN_VDT_UNARY_FUNCTION(
double, fast_cos)
1849 RVEC_EXTERN_VDT_UNARY_FUNCTION(
double, fast_tan)
1850 RVEC_EXTERN_VDT_UNARY_FUNCTION(
double, fast_asin)
1851 RVEC_EXTERN_VDT_UNARY_FUNCTION(
double, fast_acos)
1852 RVEC_EXTERN_VDT_UNARY_FUNCTION(
double, fast_atan)
1854 #endif // R__HAS_VDT
1856 #endif // _VECOPS_USE_EXTERN_TEMPLATES
1861 using ROOT::VecOps::RVec;