Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:29

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2016-2018 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 
0013 #include <algorithm>
0014 #include <iostream>
0015 #include <limits>
0016 #include <memory>
0017 #include <optional>
0018 #include <string>
0019 #include <vector>
0020 
0021 #define ACTS_CHECK_BIT(value, mask) ((value & mask) == mask)
0022 
0023 namespace Acts {
0024 
0025 /// Helper function to unpack a vector of @c shared_ptr into a vector of raw
0026 /// pointers
0027 /// @tparam T the stored type
0028 /// @param items The vector of @c shared_ptr
0029 /// @return The unpacked vector
0030 template <typename T>
0031 std::vector<T*> unpack_shared_vector(
0032     const std::vector<std::shared_ptr<T>>& items) {
0033   std::vector<T*> rawPtrs;
0034   rawPtrs.reserve(items.size());
0035   for (const std::shared_ptr<T>& item : items) {
0036     rawPtrs.push_back(item.get());
0037   }
0038   return rawPtrs;
0039 }
0040 
0041 /// Helper function to unpack a vector of @c shared_ptr into a vector of raw
0042 /// pointers (const version)
0043 /// @tparam T the stored type
0044 /// @param items The vector of @c shared_ptr
0045 /// @return The unpacked vector
0046 template <typename T>
0047 std::vector<const T*> unpack_shared_vector(
0048     const std::vector<std::shared_ptr<const T>>& items) {
0049   std::vector<const T*> rawPtrs;
0050   rawPtrs.reserve(items.size());
0051   for (const std::shared_ptr<const T>& item : items) {
0052     rawPtrs.push_back(item.get());
0053   }
0054   return rawPtrs;
0055 }
0056 
0057 /// Helper function to unpack a vector of @c shared_ptr into a vector of raw
0058 /// pointers
0059 /// @tparam T the stored type
0060 /// @param items The vector of @c shared_ptr
0061 /// @return The unpacked vector
0062 template <typename T>
0063 std::vector<const T*> unpack_shared_const_vector(
0064     const std::vector<std::shared_ptr<T>>& items) {
0065   std::vector<const T*> rawPtrs;
0066   rawPtrs.reserve(items.size());
0067   for (const std::shared_ptr<T>& item : items) {
0068     rawPtrs.push_back(item.get());
0069   }
0070   return rawPtrs;
0071 }
0072 
0073 /// This can be abandoned with C++20 to use the std::to_array method
0074 ///
0075 /// @note only the first kDIM elements will obviously be filled, if the
0076 /// vector tends to be longer, it is truncated
0077 ///
0078 /// @param vecvals the vector of bound values to be converted
0079 /// @return an array with the filled values
0080 template <std::size_t kDIM, typename value_type>
0081 std::array<value_type, kDIM> to_array(const std::vector<value_type>& vecvals) {
0082   std::array<value_type, kDIM> rarray = {};
0083   for (const auto [iv, v] : enumerate(vecvals)) {
0084     if (iv < kDIM) {
0085       rarray[iv] = v;
0086     }
0087   }
0088   return rarray;
0089 }
0090 
0091 /// @brief Dispatch a call based on a runtime value on a function taking the
0092 /// value at compile time.
0093 ///
0094 /// This function allows to write a templated functor, which accepts a @c std::size_t
0095 /// like parameter at compile time. It is then possible to make a call to the
0096 /// corresponding instance of the functor based on a runtime value. To achieve
0097 /// this, the function essentially created a if cascade between @c N and @c
0098 /// NMAX, attempting to find the right instance. Because the cascade is visible
0099 /// to the compiler entirely, it should be able to optimize.
0100 ///
0101 /// @tparam Callable Type which takes a std::size_t as a compile time param
0102 /// @tparam N Value from which to start the dispatch chain, i.e. 0 in most cases
0103 /// @tparam NMAX Maximum value up to which to attempt a dispatch
0104 /// @param v The runtime value to dispatch on
0105 /// @param args Additional arguments passed to @c Callable::invoke().
0106 /// @note @c Callable is expected to have a static member function @c invoke
0107 /// that is callable with @c Args
0108 template <template <std::size_t> class Callable, std::size_t N,
0109           std::size_t NMAX, typename... Args>
0110 auto template_switch(std::size_t v, Args&&... args) {
0111   if (v == N) {
0112     return Callable<N>::invoke(std::forward<Args>(args)...);
0113   }
0114   if (v == 0) {
0115     std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0116               << ") is not valid (v == 0 and N != 0)" << std::endl;
0117     std::abort();
0118   }
0119   if constexpr (N < NMAX) {
0120     return template_switch<Callable, N + 1, NMAX>(v,
0121                                                   std::forward<Args>(args)...);
0122   }
0123   std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0124             << ") is not valid (v > NMAX)" << std::endl;
0125   std::abort();
0126 }
0127 
0128 /// Alternative version of @c template_switch which accepts a generic
0129 /// lambda and communicates the dimension via an integral constant type
0130 /// @tparam N Value from which to start the dispatch chain, i.e. 0 in most cases
0131 /// @tparam NMAX Maximum value up to which to attempt a dispatch
0132 /// @param v The runtime value to dispatch on
0133 /// @param func The lambda to invoke
0134 /// @param args Additional arguments passed to @p func
0135 template <std::size_t N, std::size_t NMAX, typename Lambda, typename... Args>
0136 auto template_switch_lambda(std::size_t v, Lambda&& func, Args&&... args) {
0137   if (v == N) {
0138     return func(std::integral_constant<std::size_t, N>{},
0139                 std::forward<Args>(args)...);
0140   }
0141   if (v == 0) {
0142     std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0143               << ") is not valid (v == 0 and N != 0)" << std::endl;
0144     std::abort();
0145   }
0146   if constexpr (N < NMAX) {
0147     return template_switch_lambda<N + 1, NMAX>(v, func,
0148                                                std::forward<Args>(args)...);
0149   }
0150   std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0151             << ") is not valid (v > NMAX)" << std::endl;
0152   std::abort();
0153 }
0154 
0155 /// Clamp a numeric value to another type, respecting range of the target type
0156 /// @tparam T the target type
0157 /// @tparam U the source type
0158 /// @param value the value to clamp
0159 /// @return the clamped value
0160 template <typename T, typename U>
0161 T clampValue(U value) {
0162   return std::clamp(value, static_cast<U>(std::numeric_limits<T>::lowest()),
0163                     static_cast<U>(std::numeric_limits<T>::max()));
0164 }
0165 
0166 /// Return min/max from a (optionally) sorted series, obsolete with C++20
0167 /// (ranges)
0168 ///
0169 /// @tparam T a numeric series
0170 ///
0171 /// @param tseries is the number series
0172 ///
0173 /// @return [ min, max ] in an array of length 2
0174 template <typename T>
0175 std::array<typename T::value_type, 2u> min_max(const T& tseries) {
0176   return {*std::min_element(tseries.begin(), tseries.end()),
0177           *std::max_element(tseries.begin(), tseries.end())};
0178 }
0179 
0180 /// Return range and medium of a sorted numeric series
0181 ///
0182 /// @tparam T a numeric series
0183 ///
0184 /// @param tseries is the number series
0185 ///
0186 /// @return [ range, medium ] in an tuple
0187 template <typename T>
0188 std::tuple<typename T::value_type, ActsScalar> range_medium(const T& tseries) {
0189   auto [min, max] = min_max(tseries);
0190   typename T::value_type range = (max - min);
0191   ActsScalar medium = static_cast<ActsScalar>((max + min) * 0.5);
0192   return std::tie(range, medium);
0193 }
0194 
0195 }  // namespace Acts