File indexing completed on 2026-09-10 09:29:04
0001
0002
0003
0004 #ifndef VECGEOM_BACKEND_SCALARBACKEND_H_
0005 #define VECGEOM_BACKEND_SCALARBACKEND_H_
0006
0007 #include "VecGeom/base/Global.h"
0008 #include "VecGeom/base/Assert.h"
0009
0010 #include <algorithm>
0011 #include <cstring>
0012 #include <memory>
0013 #include <type_traits>
0014 #include <utility>
0015
0016 namespace vecgeom {
0017 inline namespace VECGEOM_IMPL_NAMESPACE {
0018
0019 struct kScalar {
0020 typedef int int_v;
0021 typedef Precision precision_v;
0022 typedef bool bool_v;
0023 typedef Inside_t inside_v;
0024
0025 typedef int Int_t;
0026 typedef Precision Double_t;
0027 typedef bool Bool_t;
0028 typedef int Index_t;
0029
0030 constexpr static precision_v kOne = 1.0;
0031 constexpr static precision_v kZero = 0.0;
0032 const static bool_v kTrue = true;
0033 const static bool_v kFalse = false;
0034
0035 template <class Backend>
0036 VECCORE_ATT_HOST_DEVICE static VECGEOM_CONSTEXPR_RETURN bool IsEqual()
0037 {
0038 return false;
0039 }
0040
0041 VECCORE_ATT_HOST_DEVICE
0042 VECGEOM_FORCE_INLINE
0043 static Precision Convert(Precision const &input) { return input; }
0044 };
0045
0046 template <>
0047 VECCORE_ATT_HOST_DEVICE inline VECGEOM_CONSTEXPR_RETURN bool kScalar::IsEqual<kScalar>()
0048 {
0049 return true;
0050 }
0051
0052 typedef kScalar::int_v ScalarInt;
0053 typedef kScalar::precision_v ScalarDouble;
0054 typedef kScalar::bool_v ScalarBool;
0055
0056 #ifdef VECGEOM_SCALAR
0057 constexpr size_t kVectorSize = 1;
0058 #define VECGEOM_BACKEND_TYPE vecgeom::kScalar
0059 #define VECGEOM_BACKEND_PRECISION_FROM_PTR(P) (*(P))
0060 #define VECGEOM_BACKEND_PRECISION_TYPE vecgeom::Precision
0061 #define VECGEOM_BACKEND_PRECISION_TYPE_SIZE 1
0062
0063 #define VECGEOM_BACKEND_BOOL vecgeom::ScalarBool
0064 #define VECGEOM_BACKEND_INSIDE vecgeom::kScalar::inside_v
0065 #endif
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 template <typename Type>
0076 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void copy(Type const *begin, Type const *const end, Type *const target)
0077 {
0078 #ifndef VECCORE_CUDA_DEVICE_COMPILATION
0079 std::copy(begin, end, target);
0080 #else
0081 std::memcpy(target, begin, sizeof(Type) * (end - begin));
0082 #endif
0083 }
0084
0085 namespace sfinae_impl {
0086
0087
0088
0089 template <typename, typename, typename = void>
0090 struct has_aligned_sizeof_data : std::false_type {};
0091
0092
0093 template <typename T, typename Ret, typename... Args>
0094 struct has_aligned_sizeof_data<T, Ret(Args...), std::void_t<decltype(T::aligned_sizeof_data(std::declval<Args>()...))>>
0095 : std::is_same<decltype(T::aligned_sizeof_data(std::declval<Args>()...)), Ret> {};
0096
0097
0098 template <typename T, typename Signature>
0099 constexpr bool has_aligned_sizeof_data_v = has_aligned_sizeof_data<T, Signature>::value;
0100
0101
0102 template <typename T, typename Ret, typename... Args>
0103 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE std::enable_if_t<has_aligned_sizeof_data_v<T, Ret(Args...)>, Ret>
0104 call_aligned_sizeof_data_if_exists(Args &&...args)
0105 {
0106 return T::aligned_sizeof_data(std::forward<Args>(args)...);
0107 }
0108
0109
0110 template <typename T, typename Ret, typename... Args>
0111 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE std::enable_if_t<!has_aligned_sizeof_data_v<T, Ret(Args...)>, Ret>
0112 call_aligned_sizeof_data_if_exists(Args &&...)
0113 {
0114 return Ret{};
0115 }
0116 }
0117
0118
0119
0120
0121
0122
0123
0124
0125 struct AlignedAllocator {
0126 using size_t = std::size_t;
0127 void *address;
0128 size_t sz;
0129
0130 AlignedAllocator() = delete;
0131 AlignedAllocator(const AlignedAllocator &) = delete;
0132
0133 VECCORE_ATT_HOST_DEVICE
0134 AlignedAllocator(void *buffer, size_t size) : address{buffer}, sz{size} {}
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153 VECGEOM_FORCE_INLINE
0154 VECCORE_ATT_HOST_DEVICE
0155 void *align(size_t align, size_t size, void *&ptr, size_t &space) noexcept
0156 {
0157 if (space < size) return nullptr;
0158 const auto intptr = reinterpret_cast<uintptr_t>(ptr);
0159 const auto aligned = (intptr - 1u + align) & -align;
0160 const auto diff = aligned - intptr;
0161 if (diff > (space - size))
0162 return nullptr;
0163 else {
0164 space -= diff;
0165 return ptr = reinterpret_cast<void *>(aligned);
0166 }
0167 }
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177 template <typename T, typename... Args>
0178 VECCORE_ATT_HOST_DEVICE static size_t aligned_sizeof(size_t num_elements, size_t alignment, const Args... args)
0179 {
0180 size_t aligned_size = num_elements * sizeof(T) + vecCore::math::Max(alignment, alignof(T));
0181 aligned_size += num_elements * sfinae_impl::call_aligned_sizeof_data_if_exists<T, size_t>(args...);
0182 return aligned_size;
0183 }
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193 template <typename T, typename... Args>
0194 VECCORE_ATT_HOST_DEVICE T *aligned_alloc(size_t num_elements, size_t alignment, Args &&...args)
0195 {
0196 if (alignment < alignof(T)) alignment = alignof(T);
0197 if (alignment % alignof(T) == 0 && align(alignment, num_elements * sizeof(T), address, sz)) {
0198 T *result = nullptr;
0199 auto address_old = reinterpret_cast<T *>(address);
0200
0201 address = (char *)address + num_elements * sizeof(T);
0202 if (sz < num_elements * sizeof(T)) return nullptr;
0203 sz -= num_elements * sizeof(T);
0204 for (size_t i = 0; i < num_elements; ++i) {
0205
0206 T *new_obj = new (address_old + i) T(std::forward<Args>(args)...);
0207 if (i == 0) result = new_obj;
0208 }
0209 VECGEOM_ASSERT(((unsigned long)result % alignment == 0));
0210 return result;
0211 }
0212 VECGEOM_VALIDATE(0, << "No space left to allocate in buffer");
0213 return nullptr;
0214 }
0215 };
0216
0217 template <typename Type>
0218 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Type *AlignedAllocate(size_t size)
0219 {
0220 #ifndef VECCORE_CUDA
0221 return static_cast<Type *>(vecCore::AlignedAlloc(kAlignmentBoundary, sizeof(Type) * size));
0222 #else
0223 Type *ptr = new Type[size];
0224 VECGEOM_VALIDATE(
0225 ptr != nullptr, << "Error: Memory allocation failed! If on GPU, consider increasing the heap size on GPU with "
0226 "CudaDeviceSetHeapLimit(new_size)");
0227 return ptr;
0228 #endif
0229 }
0230
0231 template <typename Type>
0232 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void AlignedFree(Type *allocated)
0233 {
0234 #ifndef VECCORE_CUDA
0235 vecCore::AlignedFree(allocated);
0236 #else
0237 delete[] allocated;
0238 #endif
0239 }
0240
0241 template <typename InputIterator1, typename InputIterator2>
0242 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE bool equal(InputIterator1 first, InputIterator1 last,
0243 InputIterator2 target)
0244 {
0245 #ifndef VECCORE_CUDA_DEVICE_COMPILATION
0246 return std::equal(first, last, target);
0247 #else
0248 while (first != last) {
0249 if (*first++ != *target++) return false;
0250 }
0251 return true;
0252 #endif
0253 }
0254 }
0255 }
0256
0257 #endif