Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-03-13 09:29:12

0001 /// \file Vector.h
0002 /// \author Johannes de Fine Licht (johannes.definelicht@cern.ch)
0003 
0004 #ifndef VECGEOM_BASE_VECTOR_H_
0005 #define VECGEOM_BASE_VECTOR_H_
0006 
0007 #include "VecGeom/base/Config.h"
0008 #include "VecGeom/base/Cuda.h"
0009 #include "VecGeom/base/Global.h"
0010 #include <initializer_list>
0011 #ifdef VECGEOM_ENABLE_CUDA
0012 #include "VecGeom/backend/cuda/Interface.h"
0013 #endif
0014 
0015 namespace vecgeom {
0016 
0017 VECGEOM_DEVICE_FORWARD_DECLARE(template <typename Type> class Vector;);
0018 VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE(class, Vector, typename);
0019 
0020 inline namespace VECGEOM_IMPL_NAMESPACE {
0021 
0022 namespace Internal {
0023 template <typename T>
0024 struct AllocTrait {
0025 
0026   // Allocate raw buffer to hold the element.
0027   VECCORE_ATT_HOST_DEVICE
0028   static T *Allocate(size_t nElems) { return reinterpret_cast<T *>(new char[nElems * sizeof(T)]); }
0029 
0030   // Release raw buffer to hold the element.
0031   VECCORE_ATT_HOST_DEVICE
0032   static void Deallocate(T *startBuffer) { delete[]((char *)startBuffer); }
0033 
0034   VECCORE_ATT_HOST_DEVICE
0035   static void Destroy(T &obj) { obj.~T(); };
0036 
0037   VECCORE_ATT_HOST_DEVICE
0038   static void Destroy(T *arr, size_t nElem)
0039   {
0040     for (size_t i = 0; i < nElem; ++i)
0041       Destroy(arr[i]);
0042   }
0043 };
0044 
0045 template <typename T>
0046 struct AllocTrait<T *> {
0047 
0048   // Allocate raw buffer to hold the element.
0049   VECCORE_ATT_HOST_DEVICE
0050   static T **Allocate(size_t nElems) { return reinterpret_cast<T **>(new char[nElems * sizeof(T *)]); }
0051 
0052   // Release raw buffer to hold the element.
0053   VECCORE_ATT_HOST_DEVICE
0054   static void Deallocate(T **startBuffer) { delete[]((char *)startBuffer); }
0055 
0056   VECCORE_ATT_HOST_DEVICE
0057   static void Destroy(T *&) {}
0058 
0059   VECCORE_ATT_HOST_DEVICE
0060   static void Destroy(T ** /*arr*/, size_t /*nElem*/) {}
0061 };
0062 } // namespace Internal
0063 
0064 template <typename Type>
0065 class VectorBase {
0066 
0067 private:
0068   Type *fData;
0069   size_t fSize, fMemorySize;
0070   bool fAllocated;
0071 
0072 public:
0073   using value_type = Type;
0074 
0075   VECCORE_ATT_HOST_DEVICE
0076   VectorBase() : VectorBase(5) {}
0077 
0078   VECCORE_ATT_HOST_DEVICE
0079   VectorBase(size_t maxsize) : fData(nullptr), fSize(0), fMemorySize(0), fAllocated(true) { reserve(maxsize); }
0080 
0081   VECCORE_ATT_HOST_DEVICE
0082   VectorBase(Type *const vec, const int sz) : fData(vec), fSize(sz), fMemorySize(sz), fAllocated(false) {}
0083 
0084   VECCORE_ATT_HOST_DEVICE
0085   VectorBase(Type *const vec, const int sz, const int maxsize)
0086       : fData(vec), fSize(sz), fMemorySize(maxsize), fAllocated(false)
0087   {
0088   }
0089 
0090   VECCORE_ATT_HOST_DEVICE
0091   VectorBase(VectorBase const &other) : fSize(other.fSize), fMemorySize(other.fMemorySize), fAllocated(true)
0092   {
0093     fData = Internal::AllocTrait<Type>::Allocate(fMemorySize);
0094     for (size_t i = 0; i < fSize; ++i)
0095       new (&fData[i]) Type(other.fData[i]);
0096   }
0097 
0098   VECCORE_ATT_HOST_DEVICE
0099   VectorBase &operator=(VectorBase const &other)
0100   {
0101     if (&other != this) {
0102       reserve(other.fMemorySize);
0103       for (size_t i = 0; i < other.fSize; ++i)
0104         push_back(other.fData[i]);
0105     }
0106     return *this;
0107   }
0108 
0109   VECCORE_ATT_HOST_DEVICE
0110   VectorBase(std::initializer_list<Type> entries)
0111   {
0112     fSize       = entries.size();
0113     fData       = Internal::AllocTrait<Type>::Allocate(fSize);
0114     fAllocated  = true;
0115     fMemorySize = entries.size() * sizeof(Type);
0116     for (auto itm : entries)
0117       this->push_back(itm);
0118   }
0119 
0120   VECCORE_ATT_HOST_DEVICE
0121   ~VectorBase()
0122   {
0123     if (fAllocated) Internal::AllocTrait<Type>::Deallocate(fData);
0124   }
0125 
0126   VECCORE_ATT_HOST_DEVICE
0127   void clear()
0128   {
0129     Internal::AllocTrait<Type>::Destroy(fData, fSize);
0130     fSize = 0;
0131   }
0132 
0133   VECCORE_ATT_HOST_DEVICE
0134   VECGEOM_FORCE_INLINE
0135   Type &operator[](const int index) { return fData[index]; }
0136 
0137   VECCORE_ATT_HOST_DEVICE
0138   VECGEOM_FORCE_INLINE
0139   Type const &operator[](const int index) const { return fData[index]; }
0140 
0141   VECCORE_ATT_HOST_DEVICE
0142   void push_back(const Type item)
0143   {
0144     if (fSize == fMemorySize) {
0145       assert(fAllocated && "Trying to push on a 'fixed' size vector (memory "
0146                            "not allocated by Vector itself)");
0147       reserve(fMemorySize << 1);
0148     }
0149     new (&fData[fSize]) Type(item);
0150     fSize++;
0151   }
0152 
0153   typedef Type *iterator;
0154   typedef Type const *const_iterator;
0155 
0156   VECCORE_ATT_HOST_DEVICE
0157   VECGEOM_FORCE_INLINE
0158   iterator begin() const { return &fData[0]; }
0159 
0160   VECCORE_ATT_HOST_DEVICE
0161   VECGEOM_FORCE_INLINE
0162   iterator end() const { return &fData[fSize]; }
0163 
0164   VECCORE_ATT_HOST_DEVICE
0165   VECGEOM_FORCE_INLINE
0166   const_iterator cbegin() const { return &fData[0]; }
0167 
0168   VECCORE_ATT_HOST_DEVICE
0169   VECGEOM_FORCE_INLINE
0170   const_iterator cend() const { return &fData[fSize]; }
0171 
0172   VECCORE_ATT_HOST_DEVICE
0173   VECGEOM_FORCE_INLINE
0174   size_t size() const { return fSize; }
0175 
0176   VECCORE_ATT_HOST_DEVICE
0177   VECGEOM_FORCE_INLINE
0178   size_t capacity() const { return fMemorySize; }
0179 
0180   VECCORE_ATT_HOST_DEVICE
0181   VECGEOM_FORCE_INLINE
0182   void resize(size_t newsize, Type value)
0183   {
0184     if (newsize <= fSize) {
0185       for (size_t i = newsize; i < fSize; ++i) {
0186         Internal::AllocTrait<Type>::Destroy(fData[i]);
0187       }
0188       fSize = newsize;
0189     } else {
0190       if (newsize > fMemorySize) {
0191         reserve(newsize);
0192       }
0193       for (size_t i = fSize; i < newsize; ++i)
0194         push_back(value);
0195     }
0196   }
0197 
0198   VECCORE_ATT_HOST_DEVICE
0199   VECGEOM_FORCE_INLINE
0200   void reserve(size_t newsize)
0201   {
0202     if (newsize <= fMemorySize) {
0203       // Do nothing ...
0204     } else {
0205       Type *newdata = Internal::AllocTrait<Type>::Allocate(newsize);
0206       for (size_t i = 0; i < fSize; ++i)
0207         new (&newdata[i]) Type(fData[i]);
0208       Internal::AllocTrait<Type>::Destroy(fData, fSize);
0209       if (fAllocated) {
0210         Internal::AllocTrait<Type>::Deallocate(fData);
0211       }
0212       fData       = newdata;
0213       fMemorySize = newsize;
0214       fAllocated  = true;
0215     }
0216   }
0217 
0218   VECCORE_ATT_HOST_DEVICE
0219   VECGEOM_FORCE_INLINE
0220   iterator erase(const_iterator position)
0221   {
0222     iterator where = (begin() + (position - cbegin()));
0223     if (where + 1 != end()) {
0224       auto last = cend();
0225       for (auto c = where; (c + 1) != last; ++c)
0226         *c = *(c + 1);
0227     }
0228     --fSize;
0229     if (fSize) Internal::AllocTrait<Type>::Destroy(fData[fSize]);
0230     return where;
0231   }
0232 };
0233 
0234 template <typename Type>
0235 class Vector : public VectorBase<Type> {
0236 public:
0237   using VectorBase<Type>::VectorBase;
0238   using typename VectorBase<Type>::iterator;
0239   using typename VectorBase<Type>::const_iterator;
0240 
0241 #ifdef VECGEOM_CUDA_INTERFACE
0242   DevicePtr<cuda::Vector<CudaType_t<Type>>> CopyToGpu(DevicePtr<CudaType_t<Type>> const gpu_ptr_arr,
0243                                                       DevicePtr<cuda::Vector<CudaType_t<Type>>> const gpu_ptr) const
0244   {
0245     gpu_ptr.Construct(gpu_ptr_arr, VectorBase<Type>::size());
0246     return gpu_ptr;
0247   }
0248 #endif
0249 };
0250 } // namespace VECGEOM_IMPL_NAMESPACE
0251 } // namespace vecgeom
0252 
0253 #endif // VECGEOM_BASE_CONTAINER_H_