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
0013
0014
0015
0016 template <typename T, typename U = T>
0017 struct pair {
0018 T first{};
0019 U second{};
0020
0021
0022 constexpr pair() noexcept = default;
0023
0024
0025 constexpr pair(const T& x, const U& y) noexcept : first(x), second(y) {}
0026
0027
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
0032 constexpr pair(const pair& other) noexcept = default;
0033
0034
0035 constexpr pair(pair&& other) noexcept = default;
0036
0037
0038 constexpr pair& operator=(const pair& other) noexcept = default;
0039
0040
0041 constexpr pair& operator=(pair&& other) noexcept = default;
0042
0043
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 }
0157 #endif