File indexing completed on 2026-09-17 09:33:06
0001
0002
0003
0004 #ifndef VECGEOM_VOLUMES_KERNEL_GENERICKERNELS_H_
0005 #define VECGEOM_VOLUMES_KERNEL_GENERICKERNELS_H_
0006
0007 #include "VecGeom/base/Global.h"
0008 #include "VecGeom/base/Transformation3D.h"
0009 #include "VecGeom/base/Vector3D.h"
0010
0011 namespace vecgeom {
0012 inline namespace VECGEOM_IMPL_NAMESPACE {
0013
0014 template <class Backend>
0015 struct GenericKernels {
0016
0017 typedef typename Backend::precision_v Float_t;
0018 typedef typename Backend::int_v Int_t;
0019 typedef typename Backend::bool_v Bool_t;
0020
0021 };
0022
0023
0024 template <typename T>
0025 VECCORE_ATT_HOST_DEVICE VECGEOM_FORCE_INLINE T fma_hd(T a, T b, T c)
0026 {
0027 #ifdef VECCORE_CUDA_DEVICE_COMPILATION
0028 return __fma_rn(a, b, c);
0029 #else
0030 return std::fma(a, b, c);
0031 #endif
0032 }
0033
0034 template <typename T>
0035 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static T Dot_fma(Vector3D<T> const &a, Vector3D<T> const &b)
0036 {
0037 return fma_hd(a[0], b[0], fma_hd(a[1], b[1], a[2] * b[2]));
0038 }
0039
0040 template <typename T>
0041 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Vector3D<T> Cross_fma(Vector3D<T> const &left,
0042 Vector3D<T> const &right)
0043 {
0044 return Vector3D<T>(fma_hd(left[1], right[2], -left[2] * right[1]), fma_hd(left[2], right[0], -left[0] * right[2]),
0045 fma_hd(left[0], right[1], -left[1] * right[0]));
0046 }
0047
0048
0049 template <typename Real_t>
0050 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE constexpr int kSign(Real_t x)
0051 {
0052 return (Real_t(0) < x) - (x < Real_t(0));
0053 }
0054
0055
0056 template <typename Real_t>
0057 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE constexpr Real_t kRelTolerance(Real_t x,
0058 Real_t tolerance = kToleranceStrict<Real_t>)
0059 {
0060 return (vecCore::math::Abs(x) + Real_t(1.)) * tolerance;
0061 }
0062
0063 template <typename Real_t>
0064 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE constexpr Real_t kRelTolerance(Vector3D<Real_t> const &p,
0065 Real_t tolerance = kToleranceStrict<Real_t>)
0066 {
0067 auto max_abs_coord = vecCore::math::Max(vecCore::math::Abs(p[0]), vecCore::math::Abs(p[1]), vecCore::math::Abs(p[2]));
0068 return kRelTolerance<Real_t>(max_abs_coord, tolerance);
0069 }
0070
0071 template <typename T>
0072 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE constexpr T MakePlusTolerantRel(T const x,
0073 T tolerance = kToleranceStrict<T>)
0074 {
0075 return (x + kRelTolerance<T>(x, tolerance));
0076 }
0077
0078 template <typename T>
0079 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE constexpr T MakeMinusTolerantRel(T const x,
0080 T tolerance = kToleranceStrict<T>)
0081 {
0082 return (x - kRelTolerance<T>(x, tolerance));
0083 }
0084
0085 template <bool tolerant, typename T>
0086 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE T MakePlusTolerant(T const &x, vecCore::Scalar<T> tol = kToleranceDist<T>)
0087 {
0088 return (tolerant) ? x + tol : x;
0089 }
0090
0091 template <bool tolerant, typename T>
0092 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE T MakeMinusTolerant(T const &x, vecCore::Scalar<T> tol = kToleranceDist<T>)
0093 {
0094 return (tolerant) ? x - T(tol) : x;
0095 }
0096
0097
0098
0099
0100
0101
0102
0103 template <bool tolerant, typename T>
0104 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE T MakePlusTolerantCrossProduct(T const &x, T const &length,
0105 vecCore::Scalar<T> tol = kToleranceDist<T>)
0106 {
0107 return (tolerant) ? x + length * T(tol) : x;
0108 }
0109
0110 template <bool tolerant, typename T>
0111 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE T MakeMinusTolerantCrossProduct(T const &x, T const &length,
0112 vecCore::Scalar<T> tol = kToleranceDist<T>)
0113 {
0114 return (tolerant) ? x - length * T(tol) : x;
0115 }
0116
0117
0118 template <bool tolerant, typename T>
0119 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE T MakePlusTolerantSquare(T const &x,
0120 vecCore::Scalar<T> tol = kToleranceDist<T>)
0121 {
0122
0123
0124 return (tolerant) ? x * (x + T(2.0 * tol)) : x * x;
0125 }
0126
0127
0128 template <bool tolerant, typename T>
0129 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE T MakeMinusTolerantSquare(T const &x,
0130 vecCore::Scalar<T> tol = kToleranceDist<T>)
0131 {
0132
0133
0134
0135 return (tolerant) ? Abs(x * (x - T(2.0 * tol))) : x * x;
0136 }
0137
0138 template <typename Real_t>
0139 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Vector3D<Real_t> NonZeroVector(Vector3D<Real_t> const &vect)
0140 {
0141 return Vector3D<Real_t>(NonZero(vect[0]), NonZero(vect[1]), NonZero(vect[2]));
0142 }
0143
0144 template <typename Real_t>
0145 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Real_t InvdirNearParallel(Real_t dist)
0146 {
0147 return kInvTolerance * dist;
0148 }
0149
0150 template <bool treatSurfaceT, class Backend>
0151 struct TreatSurfaceTraits;
0152 template <class Backend>
0153 struct TreatSurfaceTraits<true, Backend> {
0154 typedef typename Backend::inside_v Surface_t;
0155 static const Inside_t kInside = 0;
0156 static const Inside_t kOutside = 2;
0157 };
0158 template <class Backend>
0159 struct TreatSurfaceTraits<false, Backend> {
0160 typedef typename Backend::bool_v Surface_t;
0161 static const bool kInside = true;
0162 static const bool kOutside = false;
0163 };
0164
0165
0166
0167 template <bool flipT>
0168 struct Flip;
0169
0170 template <>
0171 struct Flip<true> {
0172 template <class T>
0173 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static T FlipSign(T const &value)
0174 {
0175 return -value;
0176 }
0177 template <class T>
0178 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static T FlipLogical(T const &value)
0179 {
0180 return !value;
0181 }
0182 };
0183
0184 template <>
0185 struct Flip<false> {
0186 template <class T>
0187 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static T FlipSign(T const &value)
0188 {
0189 return value;
0190 }
0191 template <class T>
0192 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static T FlipLogical(T const &value)
0193 {
0194 return value;
0195 }
0196 };
0197
0198 template <class Backend>
0199 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE typename Backend::precision_v NormalizeAngle(
0200 typename Backend::precision_v a)
0201 {
0202 return a + kTwoPi * ((a < 0) - typename Backend::int_v(a / kTwoPi));
0203 }
0204
0205
0206
0207
0208
0209 template <class Backend>
0210 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE typename Backend::precision_v DistanceToLineSegmentSquared(
0211 Vector3D<Precision> corner0, Vector3D<Precision> corner1, Vector3D<typename Backend::precision_v> const &point)
0212 {
0213
0214 typedef typename Backend::precision_v Float_t;
0215 typedef typename Backend::bool_v Bool_t;
0216
0217 Float_t result(kInfLength);
0218
0219
0220 Vector3D<Precision> line = corner1 - corner0;
0221 Vector3D<Float_t> projection = point - corner0;
0222 Float_t dot0 = projection.Dot(line);
0223 Bool_t condition = dot0 <= 0;
0224 vecCore__MaskedAssignFunc(result, condition, (point - corner0).Mag2());
0225 if (vecCore::MaskFull(condition)) return result;
0226 Precision dot1 = line.Mag2();
0227 condition = dot1 <= dot0;
0228 vecCore__MaskedAssignFunc(result, condition, (point - corner1).Mag2());
0229 condition = result < kInfLength;
0230 if (vecCore::MaskFull(condition)) return result;
0231
0232
0233 vecCore__MaskedAssignFunc(result, !condition, ((corner0 + (dot0 / dot1) * line) - point).Mag2());
0234
0235 return result;
0236 }
0237
0238
0239
0240
0241
0242 template <typename Real_v>
0243 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Real_v DistanceToLineSegmentSquared1(Vector3D<Precision> corner0,
0244 Vector3D<Precision> corner1,
0245 Vector3D<Real_v> const &point)
0246 {
0247
0248 using Bool_v = vecCore::Mask_v<Real_v>;
0249
0250 Real_v result = InfinityLength<Real_v>();
0251
0252
0253 Vector3D<Precision> line = corner1 - corner0;
0254 Vector3D<Real_v> projection = point - corner0;
0255 Real_v dot0 = projection.Dot(line);
0256 Bool_v condition = dot0 <= 0;
0257 vecCore__MaskedAssignFunc(result, condition, (point - corner0).Mag2());
0258 if (vecCore::MaskFull(condition)) return result;
0259 Precision dot1 = line.Mag2();
0260 condition = dot1 <= dot0;
0261 vecCore__MaskedAssignFunc(result, condition, (point - corner1).Mag2());
0262 condition = result < kInfLength;
0263 if (vecCore::MaskFull(condition)) return result;
0264
0265
0266 vecCore__MaskedAssignFunc(result, !condition, Real_v(((corner0 + (dot0 / dot1) * line) - point).Mag2()));
0267
0268 return result;
0269 }
0270
0271
0272
0273
0274
0275 template <typename Real_v>
0276 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Real_v DistanceToLineSegmentSquared2(Vector3D<Real_v> const &corner0,
0277 Vector3D<Real_v> const &corner1,
0278 Vector3D<Real_v> const &point,
0279 vecCore::Mask_v<Real_v> const &mask)
0280 {
0281
0282 using Bool_v = vecCore::Mask_v<Real_v>;
0283
0284 Real_v result = InfinityLength<Real_v>();
0285
0286
0287 Vector3D<Real_v> line = corner1 - corner0;
0288 Vector3D<Real_v> projection = point - corner0;
0289 Real_v dot0 = projection.Dot(line);
0290 Bool_v condition = dot0 <= 0 && mask;
0291 vecCore__MaskedAssignFunc(result, condition, (point - corner0).Mag2());
0292 if (vecCore::MaskFull(condition && mask)) return result;
0293 Real_v dot1 = line.Mag2();
0294 condition = dot1 <= dot0 && mask;
0295 vecCore__MaskedAssignFunc(result, condition, (point - corner1).Mag2());
0296 condition = result < kInfLength;
0297 if (vecCore::MaskFull(condition && mask)) return result;
0298
0299
0300 vecCore__MaskedAssignFunc(result, !condition && mask, Real_v(((corner0 + (dot0 / dot1) * line) - point).Mag2()));
0301
0302 return result;
0303 }
0304
0305
0306
0307
0308
0309
0310 template <typename Real_t>
0311 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE int QuadraticSolver(Real_t a, Real_t b, Real_t c, Real_t roots[2])
0312 {
0313 Real_t inva = 1. / NonZero(a);
0314 Real_t phalf = 0.5 * b * inva;
0315 Real_t q = c * inva;
0316 Real_t delta = phalf * phalf - q;
0317 if (delta < Real_t(0)) return 0;
0318 Real_t r1 = -phalf - Sign(phalf) * Sqrt(delta);
0319 Real_t r2 = q / vecgeom::NonZero(r1);
0320 int numroots = int(r1 > -vecgeom::kToleranceStrict<Real_t>) + int(r2 > -vecgeom::kToleranceStrict<Real_t>);
0321 roots[0] = Min(r1, r2);
0322 roots[1] = Max(r1, r2);
0323 if (numroots == 1) roots[0] = roots[1];
0324 return numroots;
0325 }
0326
0327
0328
0329
0330
0331
0332
0333 template <typename Real_t>
0334 VECCORE_ATT_HOST_DEVICE bool TriangleUnitNormalRobust(const Vector3D<Real_t> &a, const Vector3D<Real_t> &b,
0335 const Vector3D<Real_t> &c, Vector3D<Real_t> &n_unit, Real_t &dist)
0336 {
0337 using V3d = Vector3D<double>;
0338 V3d ab = V3d(b) - V3d(a);
0339 V3d ac = V3d(c) - V3d(a);
0340 V3d bc = V3d(c) - V3d(b);
0341
0342
0343 V3d n0 = Cross_fma(ab, ac);
0344 V3d n1 = Cross_fma(bc, -ab);
0345 V3d n2 = Cross_fma(-ac, -bc);
0346
0347 auto s0 = Dot_fma(n0, n0);
0348 auto s1 = Dot_fma(n1, n1);
0349 auto s2 = Dot_fma(n2, n2);
0350
0351
0352 V3d n = n0;
0353 double s2_best = s0;
0354 if (s1 > s2_best) {
0355 n = n1;
0356 s2_best = s1;
0357 }
0358 if (s2 > s2_best) {
0359 n = n2;
0360 s2_best = s2;
0361 }
0362
0363
0364 if (s2_best == 0.) {
0365 n_unit.Set(0.);
0366 dist = 0.;
0367 return false;
0368 }
0369
0370
0371 double s = n.Abs().Max();
0372 double rx = n.x() / s, ry = n.y() / s, rz = n.z() / s;
0373 double len = s * vecCore::math::Sqrt(rx * rx + ry * ry + rz * rz);
0374
0375 double inv = 1. / len;
0376 n *= inv;
0377 n_unit.Set(Real_t(n.x()), Real_t(n.y()), Real_t(n.z()));
0378 dist = -Dot_fma(n, V3d(a));
0379 return true;
0380 }
0381
0382 }
0383
0384 }
0385
0386 #endif