Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/Acts/Seeding/CandidatesForMiddleSp.ipp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2022 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 namespace Acts {
0010 
0011 template <typename external_space_point_t>
0012 inline void CandidatesForMiddleSp<external_space_point_t>::setMaxElements(
0013     std::size_t n_low, std::size_t n_high) {
0014   m_max_size_high = n_high;
0015   m_max_size_low = n_low;
0016 
0017   // protection against default numbers
0018   // it may cause std::bad_alloc if we don't protect
0019   if (n_high == std::numeric_limits<std::size_t>::max() ||
0020       n_low == std::numeric_limits<std::size_t>::max()) {
0021     return;
0022   }
0023 
0024   // Reserve enough memory for all collections
0025   m_storage.reserve(n_low + n_high);
0026   m_indices_high.reserve(n_high);
0027   m_indices_low.reserve(n_low);
0028 }
0029 
0030 template <typename external_space_point_t>
0031 inline void CandidatesForMiddleSp<external_space_point_t>::pop(
0032     std::vector<std::size_t>& indices, std::size_t& current_size) {
0033   // Remove the candidate with the lowest weight in the collection
0034   // By construction, this element is always the first element in the
0035   // collection.
0036   // The removal works this way: the first element of the collection
0037   // is overwritten with the last element of the collection.
0038   // The number of stored elements (current_size) is lowered by 1
0039   // The new first element is moved down in the tree to its correct position
0040   std::swap(indices[0], indices[current_size - 1]);
0041   bubbledw(indices, 0, --current_size);
0042 }
0043 
0044 template <typename external_space_point_t>
0045 inline bool CandidatesForMiddleSp<external_space_point_t>::exists(
0046     const std::size_t n, const std::size_t max_size) const {
0047   // If the element exists, its index is lower than the current number
0048   // of stored elements
0049   return n < max_size;
0050 }
0051 
0052 template <typename external_space_point_t>
0053 inline float CandidatesForMiddleSp<external_space_point_t>::weight(
0054     const std::vector<std::size_t>& indices, std::size_t n) const {
0055   // Get the weight of the n-th element
0056   return m_storage[indices[n]].weight;
0057 }
0058 
0059 template <typename external_space_point_t>
0060 inline void CandidatesForMiddleSp<external_space_point_t>::clear() {
0061   // do not clear max size, this is set only once
0062   // reset to 0 the number of stored elements
0063   m_n_high = 0;
0064   m_n_low = 0;
0065   // Reset all values to default
0066   m_storage.clear();
0067   m_indices_high.clear();
0068   m_indices_low.clear();
0069 }
0070 
0071 template <typename external_space_point_t>
0072 bool CandidatesForMiddleSp<external_space_point_t>::push(
0073     external_space_point_t& SpB, external_space_point_t& SpM,
0074     external_space_point_t& SpT, float weight, float zOrigin, bool isQuality) {
0075   // Decide in which collection this candidate may be added to according to the
0076   // isQuality boolean
0077   if (isQuality) {
0078     return push(m_indices_high, m_n_high, m_max_size_high, SpB, SpM, SpT,
0079                 weight, zOrigin, isQuality);
0080   }
0081   return push(m_indices_low, m_n_low, m_max_size_low, SpB, SpM, SpT, weight,
0082               zOrigin, isQuality);
0083 }
0084 
0085 template <typename external_space_point_t>
0086 bool CandidatesForMiddleSp<external_space_point_t>::push(
0087     std::vector<std::size_t>& indices, std::size_t& n, const std::size_t n_max,
0088     external_space_point_t& SpB, external_space_point_t& SpM,
0089     external_space_point_t& SpT, float weight, float zOrigin, bool isQuality) {
0090   // If we do not want to store candidates, returns
0091   if (n_max == 0) {
0092     return false;
0093   }
0094 
0095   // if there is still space, add anything
0096   if (n < n_max) {
0097     addToCollection(indices, n, n_max,
0098                     value_type(SpB, SpM, SpT, weight, zOrigin, isQuality));
0099     return true;
0100   }
0101 
0102   // if no space, replace one if quality is enough
0103   // compare to element with lowest weight
0104   const auto& lowest_weight = this->weight(indices, 0);
0105   if (weight <= lowest_weight) {
0106     return false;
0107   }
0108 
0109   // remove element with lower weight and add this one
0110   pop(indices, n);
0111   addToCollection(indices, n, n_max,
0112                   value_type(SpB, SpM, SpT, weight, zOrigin, isQuality));
0113   return true;
0114 }
0115 
0116 template <typename external_space_point_t>
0117 void CandidatesForMiddleSp<external_space_point_t>::addToCollection(
0118     std::vector<std::size_t>& indices, std::size_t& n, const std::size_t n_max,
0119     value_type&& element) {
0120   // adds elements to the end of the collection
0121   if (indices.size() == n_max) {
0122     m_storage[indices[n]] = std::move(element);
0123   } else {
0124     m_storage.push_back(std::move(element));
0125     indices.push_back(m_storage.size() - 1);
0126   }
0127   // Move the added element up in the tree to its correct position
0128   bubbleup(indices, n++);
0129 }
0130 
0131 template <typename external_space_point_t>
0132 void CandidatesForMiddleSp<external_space_point_t>::bubbledw(
0133     std::vector<std::size_t>& indices, std::size_t n, std::size_t actual_size) {
0134   while (n < actual_size) {
0135     // The collection of indexes are sorted as min heap trees
0136     // left child : 2 * n + 1
0137     // right child: 2 * n + 2
0138     float current = weight(indices, n);
0139     std::size_t left_child = 2 * n + 1;
0140     std::size_t right_child = 2 * n + 2;
0141 
0142     // We have to move the current node down the tree to its correct position.
0143     // This is done by comparing its weight with the weights of its two
0144     // children. Few things can happen:
0145     //   - there are no children
0146     //   - the current weight is lower than the weight of the children
0147     //   - at least one of the children has a lower weight
0148     // In the first two cases we stop, since we are already in the correct
0149     // position
0150 
0151     // if there is no left child, that also means no right child is present.
0152     // We do nothing
0153     if (!exists(left_child, actual_size)) {
0154       break;
0155     }
0156 
0157     // At least one of the child is present. Left child for sure, right child we
0158     // have to check. We take the lowest weight of the children. By default this
0159     // is the weight of the left child, and we then check for the right child
0160 
0161     float weight_left_child = weight(indices, left_child);
0162 
0163     std::size_t selected_child = left_child;
0164     float selected_weight = weight_left_child;
0165 
0166     // Check which child has the lower weight
0167     if (exists(right_child, actual_size)) {
0168       float weight_right_child = weight(indices, right_child);
0169       if (weight_right_child <= weight_left_child) {
0170         selected_child = right_child;
0171         selected_weight = weight_right_child;
0172       }
0173     }
0174 
0175     // At this point we have the minimum weight of the children
0176     // We can compare this to the current weight
0177     // If weight of the children is higher we stop
0178     if (selected_weight >= current) {
0179       break;
0180     }
0181 
0182     // swap and repeat the process
0183     std::swap(indices[n], indices[selected_child]);
0184     n = selected_child;
0185   }  // while loop
0186 }
0187 
0188 template <typename external_space_point_t>
0189 void CandidatesForMiddleSp<external_space_point_t>::bubbleup(
0190     std::vector<std::size_t>& indices, std::size_t n) {
0191   while (n != 0) {
0192     // The collection of indexes are sorted as min heap trees
0193     // parent: (n - 1) / 2;
0194     // this works because it is an integer operation
0195     std::size_t parent_idx = (n - 1) / 2;
0196 
0197     float weight_current = weight(indices, n);
0198     float weight_parent = weight(indices, parent_idx);
0199 
0200     // If weight of the parent is lower than this one, we stop
0201     if (weight_parent <= weight_current) {
0202       break;
0203     }
0204 
0205     // swap and repeat the process
0206     std::swap(indices[n], indices[parent_idx]);
0207     n = parent_idx;
0208   }
0209 }
0210 
0211 template <typename external_space_point_t>
0212 std::vector<typename CandidatesForMiddleSp<external_space_point_t>::value_type>
0213 CandidatesForMiddleSp<external_space_point_t>::storage() {
0214   // this will retrieve the entire storage
0215   // the resulting vector is already sorted from high to low quality
0216   std::vector<value_type> output(m_n_high + m_n_low);
0217   std::size_t out_idx = output.size() - 1;
0218 
0219   // rely on the fact that m_indices_* are both min heap trees
0220   // Sorting comes naturally by popping elements one by one and
0221   // placing this element at the end of the output vector
0222   while (m_n_high != 0 || m_n_low != 0) {
0223     // no entries in collection high, we attach the entire low collection
0224     if (m_n_high == 0) {
0225       std::size_t idx = m_n_low;
0226       for (std::size_t i(0); i < idx; i++) {
0227         output[out_idx--] = std::move(m_storage[m_indices_low[0]]);
0228         pop(m_indices_low, m_n_low);
0229       }
0230       break;
0231     }
0232 
0233     // no entries in collection low, we attach the entire high collection
0234     if (m_n_low == 0) {
0235       std::size_t idx = m_n_high;
0236       for (std::size_t i(0); i < idx; i++) {
0237         output[out_idx--] = std::move(m_storage[m_indices_high[0]]);
0238         pop(m_indices_high, m_n_high);
0239       }
0240       break;
0241     }
0242 
0243     // Both have entries, get the minimum
0244     if (descendingByQuality(m_storage[m_indices_low[0]],
0245                             m_storage[m_indices_high[0]])) {
0246       output[out_idx--] = std::move(m_storage[m_indices_high[0]]);
0247       pop(m_indices_high, m_n_high);
0248     } else {
0249       output[out_idx--] = std::move(m_storage[m_indices_low[0]]);
0250       pop(m_indices_low, m_n_low);
0251     }
0252 
0253   }  // while loop
0254 
0255   clear();
0256   return output;
0257 }
0258 
0259 template <typename external_space_point_t>
0260 bool CandidatesForMiddleSp<external_space_point_t>::descendingByQuality(
0261     const value_type& i1, const value_type& i2) {
0262   if (i1.weight != i2.weight) {
0263     return i1.weight > i2.weight;
0264   }
0265 
0266   // This is for the case when the weights from different seeds
0267   // are same. This makes cpu & cuda results same
0268 
0269   const auto& bottom_l1 = i1.bottom;
0270   const auto& middle_l1 = i1.middle;
0271   const auto& top_l1 = i1.top;
0272 
0273   const auto& bottom_l2 = i2.bottom;
0274   const auto& middle_l2 = i2.middle;
0275   const auto& top_l2 = i2.top;
0276 
0277   float seed1_sum = 0.;
0278   float seed2_sum = 0.;
0279 
0280   seed1_sum +=
0281       bottom_l1->y() * bottom_l1->y() + bottom_l1->z() * bottom_l1->z();
0282   seed1_sum +=
0283       middle_l1->y() * middle_l1->y() + middle_l1->z() * middle_l1->z();
0284   seed1_sum += top_l1->y() * top_l1->y() + top_l1->z() * top_l1->z();
0285 
0286   seed2_sum +=
0287       bottom_l2->y() * bottom_l2->y() + bottom_l2->z() * bottom_l2->z();
0288   seed2_sum +=
0289       middle_l2->y() * middle_l2->y() + middle_l2->z() * middle_l2->z();
0290   seed2_sum += top_l2->y() * top_l2->y() + top_l2->z() * top_l2->z();
0291 
0292   return seed1_sum > seed2_sum;
0293 }
0294 
0295 template <typename external_space_point_t>
0296 bool CandidatesForMiddleSp<external_space_point_t>::ascendingByQuality(
0297     const value_type& i1, const value_type& i2) {
0298   return !descendingByQuality(i1, i2);
0299 }
0300 
0301 }  // namespace Acts