Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-01 09:06:28

0001 #ifndef H_SIPM_SIPMTYPES
0002 #define H_SIPM_SIPMTYPES
0003 
0004 #include <cstdint>
0005 #include <cstdlib>
0006 #include <cstddef> // for std::size_t
0007 #include <cstring> // for std::memcpy, std::memmove
0008 #include <utility> // for std::move, std::forward
0009 #include <iostream>
0010 
0011 namespace sipm {
0012 /** @brief Custom implementation of @ref std::pair
0013  * This is a simple custom implementation of std::pair
0014  * but with no run-time checks to improve performance
0015  */
0016 template <typename T, typename U = T>
0017 struct pair {
0018   T first{};
0019   U second{};
0020 
0021   // Default constructor
0022   constexpr pair() noexcept = default;
0023 
0024   // Parameterized constructor
0025   constexpr pair(const T& x, const U& y) noexcept : first(x), second(y) {}
0026 
0027   // Forwarding constructor for perfect forwarding
0028   template <typename X, typename Y>
0029   constexpr pair(X&& x, Y&& y) noexcept : first(std::forward<X>(x)), second(std::forward<Y>(y)) {}
0030 
0031   // Copy constructor
0032   constexpr pair(const pair& other) noexcept = default;
0033 
0034   // Move constructor
0035   constexpr pair(pair&& other) noexcept = default;
0036 
0037   // Copy assignment
0038   constexpr pair& operator=(const pair& other) noexcept = default;
0039 
0040   // Move assignment
0041   constexpr pair& operator=(pair&& other) noexcept = default;
0042 
0043   // Swap function
0044   void swap(pair& other) noexcept {
0045     std::swap(first, other.first);
0046     std::swap(second, other.second);
0047   }
0048 };
0049 
0050 template <size_t N = 64>
0051 inline void* sipmAlloc(const size_t bytes) {
0052   static_assert((N & (N - 1)) == 0, "Alignment must be a power of 2");
0053   const size_t alignedBytes = (bytes + N - 1) & ~(N - 1);
0054 #ifdef __AVX512F__
0055   return aligned_alloc(N, alignedBytes);
0056 #else
0057   return malloc(alignedBytes);
0058 #endif
0059 }
0060 
0061 inline void sipmFree(void* ptr) { free(ptr); }
0062 
0063 template <typename T, std::size_t N = 3>
0064 class SiPMSmallVector {
0065 private:
0066   alignas(64) T m_LocalStorage[N];
0067     T* m_HeapStorage = nullptr;
0068     size_t m_Size = 0;
0069     size_t m_Capacity = N;
0070 
0071     inline bool isLocal() const noexcept {
0072         return m_Capacity == N;
0073     }
0074 
0075     void moveToHeap() {
0076       m_HeapStorage = (T*)malloc(2*N*sizeof(T));
0077         memcpy(m_HeapStorage, m_LocalStorage, m_Size * sizeof(T));
0078         m_Capacity = 2 * N;
0079     }
0080 
0081     void growHeap() {
0082       m_Capacity *= 2;
0083       m_HeapStorage = (T*)realloc(m_HeapStorage, m_Capacity  * sizeof(T));
0084     }
0085 
0086     T* data() noexcept { return isLocal() ? m_LocalStorage : m_HeapStorage; }
0087 
0088     const T* data() const noexcept { return isLocal() ? m_LocalStorage : m_HeapStorage; }
0089 
0090   public:
0091     SiPMSmallVector() = default;
0092 
0093     ~SiPMSmallVector() {
0094       if (m_HeapStorage != nullptr) {
0095         free(m_HeapStorage);
0096       }
0097     }
0098 
0099     void push_back(const T& value) {
0100       if (m_Size == m_Capacity ) {
0101         if (isLocal()) {
0102           moveToHeap();
0103         } else {
0104           growHeap();
0105         }
0106       }
0107       data()[m_Size++] = value;
0108     }
0109 
0110     void push_back(T&& value) {
0111         if (m_Size == m_Capacity ) {
0112             if (isLocal()) {
0113                 moveToHeap();
0114             } else {
0115                 growHeap();
0116             }
0117         }
0118         data()[m_Size++] = std::move(value);
0119     }
0120 
0121     void pop_back() {
0122         --m_Size;
0123     }
0124 
0125     T& operator[](std::size_t index) noexcept {
0126         return data()[index];
0127     }
0128 
0129     const T& operator[](std::size_t index) const noexcept {
0130         return data()[index];
0131     }
0132 
0133     size_t size() const noexcept {
0134         return m_Size;
0135     }
0136 
0137     void clear() {
0138         m_Size = 0;
0139         if (!isLocal()) {
0140             free(m_HeapStorage);
0141             m_HeapStorage = nullptr;
0142             m_Capacity  = N;
0143         }
0144     }
0145 
0146     T* begin() noexcept { return data(); }
0147     T* end() noexcept { return data() + m_Size; }
0148 
0149     const T* begin() const noexcept { return data(); }
0150     const T* end() const noexcept { return data() + m_Size; }
0151 
0152     const T* cbegin() const noexcept { return data(); }
0153     const T* cend() const noexcept { return data() + m_Size; }
0154 };
0155 
0156 } // namespace sipm
0157 #endif // H_SIPM_SIPMTYPES