Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-10-16 05:03:39

0001 // Author: Felice Pantaleo (CERN), 2023, felice.pantaleo@cern.ch
0002 #ifndef MultiVectorManager_h
0003 #define MultiVectorManager_h
0004 
0005 #include <vector>
0006 #include <cassert>
0007 #include <algorithm>
0008 #include <span>
0009 
0010 template <typename T>
0011 class MultiVectorManager {
0012 public:
0013   void addVector(std::span<const T> vec) {
0014     vectors.emplace_back(vec);
0015     offsets.push_back(totalSize);
0016     totalSize += vec.size();
0017   }
0018 
0019   T& operator[](size_t globalIndex) {
0020     return const_cast<T&>(static_cast<const MultiVectorManager*>(this)->operator[](globalIndex));
0021   }
0022 
0023   const T& operator[](size_t globalIndex) const {
0024     assert(globalIndex < totalSize && "Global index out of range");
0025 
0026     auto it = std::upper_bound(offsets.begin(), offsets.end(), globalIndex);
0027     size_t vectorIndex = std::distance(offsets.begin(), it) - 1;
0028     size_t localIndex = globalIndex - offsets[vectorIndex];
0029 
0030     return vectors[vectorIndex][localIndex];
0031   }
0032 
0033   size_t getGlobalIndex(size_t vectorIndex, size_t localIndex) const {
0034     assert(vectorIndex < vectors.size() && "Vector index out of range");
0035 
0036     const auto& vec = vectors[vectorIndex];
0037     assert(localIndex < vec.size() && "Local index out of range");
0038 
0039     return offsets[vectorIndex] + localIndex;
0040   }
0041 
0042   std::pair<size_t, size_t> getVectorAndLocalIndex(size_t globalIndex) const {
0043     assert(globalIndex < totalSize && "Global index out of range");
0044 
0045     auto it = std::upper_bound(offsets.begin(), offsets.end(), globalIndex);
0046     size_t vectorIndex = std::distance(offsets.begin(), it) - 1;
0047     size_t localIndex = globalIndex - offsets[vectorIndex];
0048 
0049     return {vectorIndex, localIndex};
0050   }
0051 
0052   size_t size() const { return totalSize; }
0053 
0054   class Iterator {
0055   public:
0056     using iterator_category = std::forward_iterator_tag;
0057     using difference_type = std::ptrdiff_t;
0058     using value_type = T;
0059     using pointer = T*;
0060     using reference = T&;
0061 
0062     Iterator(const MultiVectorManager& manager, size_t index) : manager(manager), currentIndex(index) {}
0063 
0064     bool operator!=(const Iterator& other) const { return currentIndex != other.currentIndex; }
0065 
0066     T& operator*() const { return const_cast<T&>(manager[currentIndex]); }
0067 
0068     void operator++() { ++currentIndex; }
0069 
0070   private:
0071     const MultiVectorManager& manager;
0072     size_t currentIndex;
0073   };
0074 
0075   Iterator begin() const { return Iterator(*this, 0); }
0076 
0077   Iterator end() const { return Iterator(*this, totalSize); }
0078 
0079 private:
0080   std::vector<std::span<const T>> vectors;
0081   std::vector<size_t> offsets;
0082   size_t totalSize = 0;
0083 };
0084 
0085 #endif