File indexing completed on 2026-09-09 09:27:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef VECGEOM_VOLUMES_KERNEL_BOXIMPLEMENTATION_H_
0011 #define VECGEOM_VOLUMES_KERNEL_BOXIMPLEMENTATION_H_
0012
0013 #include "VecGeom/base/Vector3D.h"
0014 #include "VecGeom/volumes/BoxStruct.h"
0015 #include "VecGeom/volumes/kernel/GenericKernels.h"
0016 #include <VecCore/VecCore>
0017
0018 #include <cstdio>
0019
0020 namespace vecgeom {
0021
0022 VECGEOM_DEVICE_FORWARD_DECLARE(struct BoxImplementation;);
0023 VECGEOM_DEVICE_DECLARE_CONV(struct, BoxImplementation);
0024
0025 inline namespace VECGEOM_IMPL_NAMESPACE {
0026
0027 class PlacedBox;
0028 template <typename T>
0029 struct BoxStruct;
0030 class UnplacedBox;
0031
0032 struct BoxImplementation {
0033
0034 using PlacedShape_t = PlacedBox;
0035 using UnplacedStruct_t = BoxStruct<Precision>;
0036 using UnplacedVolume_t = UnplacedBox;
0037
0038 template <typename Real_v>
0039 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Vector3D<Real_v> HalfSize(const UnplacedStruct_t &box)
0040 {
0041 return Vector3D<Real_v>(box.fDimensions[0], box.fDimensions[1], box.fDimensions[2]);
0042 }
0043
0044 template <typename Real_v, typename Bool_v>
0045 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Contains(UnplacedStruct_t const &box,
0046 Vector3D<Real_v> const &point, Bool_v &inside)
0047 {
0048
0049 inside = (point.Abs() - HalfSize<Real_v>(box)).Max() < Real_v(kTolerance);
0050 }
0051
0052 template <typename Real_v, typename Inside_v>
0053 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Inside(UnplacedStruct_t const &box,
0054 Vector3D<Real_v> const &point, Inside_v &inside)
0055 {
0056 Real_v dist = (point.Abs() - HalfSize<Real_v>(box)).Max();
0057
0058 inside = vecCore::Blend(dist < Real_v(0.0), Inside_v(kInside), Inside_v(kOutside));
0059 vecCore__MaskedAssignFunc(inside, Abs(dist) < Real_v(kHalfTolerance), Inside_v(kSurface));
0060 }
0061
0062 template <typename Real_v, bool ForInside>
0063 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void GenericKernelForContainsAndInside(
0064 Vector3D<Real_v> const &halfsize, Vector3D<Real_v> const &point, vecCore::Mask<Real_v> &completelyinside,
0065 vecCore::Mask<Real_v> &completelyoutside)
0066 {
0067 Real_v dist = (point.Abs() - halfsize).Max();
0068
0069 if (ForInside) completelyinside = dist < Real_v(-kHalfTolerance);
0070
0071 completelyoutside = dist > Real_v(kHalfTolerance);
0072 }
0073
0074 template <typename Real_v>
0075 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DistanceToIn(UnplacedStruct_t const &box,
0076 Vector3D<Real_v> const &point,
0077 Vector3D<Real_v> const &direction,
0078 Real_v const & , Real_v &distance)
0079 {
0080 const Vector3D<Real_v> invDir(Real_v(1.0) / NonZero(direction[0]), Real_v(1.0) / NonZero(direction[1]),
0081 Real_v(1.0) / NonZero(direction[2]));
0082
0083 const Vector3D<Real_v> signDir(Sign(direction[0]), Sign(direction[1]), Sign(direction[2]));
0084
0085 const Vector3D<Real_v> tempIn = -signDir * box.fDimensions - point;
0086 const Vector3D<Real_v> tempOut = signDir * box.fDimensions - point;
0087
0088
0089 const Real_v absOrthogOut = Abs((signDir * tempOut).Min());
0090
0091 const Real_v distOut = (tempOut * invDir).Min();
0092
0093
0094 distance = (tempIn * invDir).Max();
0095
0096 vecCore__MaskedAssignFunc(
0097 distance, distance >= distOut || distOut <= Real_v(kHalfTolerance) || absOrthogOut <= Real_v(kHalfTolerance),
0098 InfinityLength<Real_v>());
0099 }
0100
0101 template <typename Real_v>
0102 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DistanceToOut(UnplacedStruct_t const &box,
0103 Vector3D<Real_v> const &point,
0104 Vector3D<Real_v> const &direction,
0105 Real_v const & , Real_v &distance)
0106 {
0107 distance = Real_v(-1.0);
0108
0109
0110 if ((point.Abs() - HalfSize<Real_v>(box)).Max() > Real_v(kTolerance)) return;
0111
0112
0113 const Vector3D<Real_v> invDir(Real_v(1.0) / NonZero(direction[0]), Real_v(1.0) / NonZero(direction[1]),
0114 Real_v(1.0) / NonZero(direction[2]));
0115
0116 const Vector3D<Real_v> signDir(Sign(direction[0]), Sign(direction[1]), Sign(direction[2]));
0117
0118
0119 const Vector3D<Real_v> tempOut = signDir * box.fDimensions - point;
0120
0121
0122 auto skip = direction.Abs() * box.fDimensions < Vector3D<Real_v>(kTolerance);
0123
0124
0125
0126 distance = (tempOut * invDir).MinSkip(skip);
0127 }
0128
0129 template <typename Real_v>
0130 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToIn(UnplacedStruct_t const &box,
0131 Vector3D<Real_v> const &point, Real_v &safety)
0132 {
0133 safety = (point.Abs() - HalfSize<Real_v>(box)).Max();
0134 }
0135
0136 template <typename Real_v>
0137 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToOut(UnplacedStruct_t const &box,
0138 Vector3D<Real_v> const &point, Real_v &safety)
0139 {
0140 safety = (HalfSize<Real_v>(box) - point.Abs()).Min();
0141 }
0142
0143 template <typename Real_v>
0144 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Vector3D<Real_v> NormalKernel(
0145 UnplacedStruct_t const &box, Vector3D<Real_v> const &point, typename vecCore::Mask_v<Real_v> &valid)
0146 {
0147
0148
0149
0150
0151
0152
0153 const Vector3D<Real_v> safety((point.Abs() - HalfSize<Real_v>(box)).Abs());
0154 const Real_v safmin = safety.Min();
0155 valid = safmin < kHalfTolerance;
0156
0157 Vector3D<Real_v> normal(0.);
0158 vecCore__MaskedAssignFunc(normal[0], safety[0] - safmin < kHalfTolerance, Sign(point[0]));
0159 vecCore__MaskedAssignFunc(normal[1], safety[1] - safmin < kHalfTolerance, Sign(point[1]));
0160 vecCore__MaskedAssignFunc(normal[2], safety[2] - safmin < kHalfTolerance, Sign(point[2]));
0161 if (normal.Mag2() > 1.0) normal.Normalize();
0162
0163 return normal;
0164 }
0165
0166
0167
0168
0169 VECCORE_ATT_HOST_DEVICE
0170 VECGEOM_FORCE_INLINE
0171 static bool Intersect(Vector3D<Precision> const *corners, Vector3D<Precision> const &point,
0172 Vector3D<Precision> const &ray, Precision , Precision )
0173 {
0174
0175 Precision tmin, tmax, tymin, tymax, tzmin, tzmax;
0176
0177
0178 Precision inverserayx = 1. / ray[0];
0179 Precision inverserayy = 1. / ray[1];
0180
0181
0182 int sign[3];
0183 sign[0] = inverserayx < 0;
0184 sign[1] = inverserayy < 0;
0185
0186 tmin = (corners[sign[0]].x() - point.x()) * inverserayx;
0187 tmax = (corners[1 - sign[0]].x() - point.x()) * inverserayx;
0188 tymin = (corners[sign[1]].y() - point.y()) * inverserayy;
0189 tymax = (corners[1 - sign[1]].y() - point.y()) * inverserayy;
0190
0191 if ((tmin > tymax) || (tymin > tmax)) return false;
0192
0193 Precision inverserayz = 1. / ray.z();
0194 sign[2] = inverserayz < 0;
0195
0196 if (tymin > tmin) tmin = tymin;
0197 if (tymax < tmax) tmax = tymax;
0198
0199 tzmin = (corners[sign[2]].z() - point.z()) * inverserayz;
0200 tzmax = (corners[1 - sign[2]].z() - point.z()) * inverserayz;
0201
0202 if ((tmin > tzmax) || (tzmin > tmax)) return false;
0203
0204
0205
0206
0207 return true;
0208 }
0209
0210
0211
0212 template <int signx, int signy, int signz>
0213 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE
0214
0215 static Precision
0216 IntersectCached(Vector3D<Precision> const *corners, Vector3D<Precision> const &point,
0217 Vector3D<Precision> const &inverseray, Precision t0, Precision t1)
0218 {
0219
0220
0221
0222
0223 Precision tmin, tmax, tymin, tymax, tzmin, tzmax;
0224
0225
0226
0227
0228 tmin = (corners[signx].x() - point.x()) * inverseray.x();
0229 tmax = (corners[1 - signx].x() - point.x()) * inverseray.x();
0230 tymin = (corners[signy].y() - point.y()) * inverseray.y();
0231 tymax = (corners[1 - signy].y() - point.y()) * inverseray.y();
0232 if ((tmin > tymax) || (tymin > tmax)) return InfinityLength<Precision>();
0233
0234 if (tymin > tmin) tmin = tymin;
0235 if (tymax < tmax) tmax = tymax;
0236
0237 tzmin = (corners[signz].z() - point.z()) * inverseray.z();
0238 tzmax = (corners[1 - signz].z() - point.z()) * inverseray.z();
0239
0240 if ((tmin > tzmax) || (tzmin > tmax)) return InfinityLength<Precision>();
0241 if ((tzmin > tmin)) tmin = tzmin;
0242 if (tzmax < tmax) tmax = tzmax;
0243
0244 if (!((tmin < t1) && (tmax > t0))) return InfinityLength<Precision>();
0245 return tmin;
0246 }
0247
0248
0249
0250 template <typename Real_v, int signx, int signy, int signz>
0251 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Real_v IntersectCachedKernel(
0252 Vector3D<Real_v> const *corners, Vector3D<Precision> const &point, Vector3D<Precision> const &inverseray,
0253 Precision t0, Precision t1)
0254 {
0255
0256 using Bool_v = vecCore::Mask_v<Real_v>;
0257
0258 Real_v tmin = (corners[signx].x() - point.x()) * inverseray.x();
0259 Real_v tmax = (corners[1 - signx].x() - point.x()) * inverseray.x();
0260 Real_v tymin = (corners[signy].y() - point.y()) * inverseray.y();
0261 Real_v tymax = (corners[1 - signy].y() - point.y()) * inverseray.y();
0262
0263
0264 Bool_v done = (tmin > tymax) || (tymin > tmax);
0265 if (vecCore::MaskFull(done)) return InfinityLength<Real_v>();
0266
0267
0268
0269
0270 tmin = Max(tmin, tymin);
0271 tmax = Min(tmax, tymax);
0272
0273 Real_v tzmin = (corners[signz].z() - point.z()) * inverseray.z();
0274 Real_v tzmax = (corners[1 - signz].z() - point.z()) * inverseray.z();
0275
0276 done |= (tmin > tzmax) || (tzmin > tmax);
0277
0278
0279 if (vecCore::MaskFull(done)) return InfinityLength<Real_v>();
0280
0281
0282 tmin = Max(tmin, tzmin);
0283 tmax = Min(tmax, tzmax);
0284
0285 done |= !((tmin < t1) && (tmax > t0));
0286
0287
0288 vecCore__MaskedAssignFunc(tmin, done, InfinityLength<Real_v>());
0289 return tmin;
0290 }
0291
0292
0293
0294 template <typename Real_v, typename basep>
0295 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Real_v IntersectCachedKernel2(Vector3D<Real_v> const *corners,
0296 Vector3D<basep> const &point,
0297 Vector3D<basep> const &inverseray,
0298 int signx, int signy, int signz,
0299 basep t0, basep t1)
0300 {
0301
0302 using Bool_v = vecCore::Mask_v<Real_v>;
0303
0304 Real_v tmin = (corners[signx].x() - Real_v(point.x())) * inverseray.x();
0305 Real_v tymax = (corners[1 - signy].y() - Real_v(point.y())) * inverseray.y();
0306 Bool_v done = tmin > tymax;
0307 if (vecCore::MaskFull(done)) return InfinityLength<Real_v>();
0308
0309 Real_v tmax = (corners[1 - signx].x() - Real_v(point.x())) * inverseray.x();
0310 Real_v tymin = (corners[signy].y() - Real_v(point.y())) * inverseray.y();
0311
0312
0313 done |= (tymin > tmax);
0314 if (vecCore::MaskFull(done)) return InfinityLength<Real_v>();
0315
0316
0317
0318
0319
0320 tmin = Max(tmin, tymin);
0321 tmax = Min(tmax, tymax);
0322
0323 Real_v tzmin = (corners[signz].z() - point.z()) * inverseray.z();
0324 Real_v tzmax = (corners[1 - signz].z() - point.z()) * inverseray.z();
0325
0326 done |= (Real_v(tmin) > Real_v(tzmax)) || (Real_v(tzmin) > Real_v(tmax));
0327
0328
0329 if (vecCore::MaskFull(done)) return InfinityLength<Real_v>();
0330
0331
0332 tmin = Max(tmin, tzmin);
0333 tmax = Min(tmax, tzmax);
0334
0335 done |= !((tmin <= Real_v(t1 + kTolerance)) && (tmax > Real_v(t0 - kTolerance)));
0336
0337
0338 vecCore__MaskedAssignFunc(tmin, done, InfinityLength<Real_v>());
0339 return tmin;
0340 }
0341
0342
0343
0344
0345
0346
0347
0348 template <typename Real_v>
0349 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Precision IntersectMultiple(Vector3D<Real_v> const lowercorners,
0350 Vector3D<Real_v> const uppercorners,
0351 Vector3D<Precision> const &point,
0352 Vector3D<Precision> const &inverseray,
0353 Precision t0, Precision t1)
0354 {
0355
0356
0357 typedef Real_v Float_t;
0358
0359 Float_t tmin, tmax, tymin, tymax, tzmin, tzmax;
0360
0361
0362
0363
0364
0365
0366 Float_t sign[3];
0367 sign[0] = inverseray.x() < 0;
0368 sign[1] = inverseray.y() < 0;
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 Precision x0 = (lowercorners.x() - point.x()) * inverseray.x();
0379 Precision x1 = (uppercorners.x() - point.x()) * inverseray.x();
0380 Precision y0 = (lowercorners.y() - point.y()) * inverseray.y();
0381 Precision y1 = (uppercorners.y() - point.y()) * inverseray.y();
0382
0383
0384
0385
0386
0387
0388
0389
0390 tmin = (1 - sign[0]) * x0 + sign[0] * x1;
0391 tmax = sign[0] * x0 + (1 - sign[0]) * x1;
0392 tymin = (1 - sign[1]) * y0 + sign[1] * y1;
0393 tymax = sign[1] * y0 + (1 - sign[1]) * y1;
0394
0395
0396
0397
0398
0399 if ((tmin > tymax) || (tymin > tmax)) return InfinityLength<Precision>();
0400
0401
0402 sign[2] = inverseray.z() < 0;
0403
0404 if (tymin > tmin) tmin = tymin;
0405 if (tymax < tmax) tmax = tymax;
0406
0407
0408
0409
0410
0411 if ((tmin > tzmax) || (tzmin > tmax)) return InfinityLength<Precision>();
0412 if ((tzmin > tmin)) tmin = tzmin;
0413 if (tzmax < tmax) tmax = tzmax;
0414
0415 if (!((tmin < t1) && (tmax > t0))) return InfinityLength<Precision>();
0416
0417
0418 return tmin;
0419 }
0420 };
0421
0422 struct ABBoxImplementation {
0423
0424
0425
0426
0427
0428 template <typename Real_v, typename Bool_v = typename vecCore::Mask_v<Real_v>>
0429 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void ABBoxContainsKernel(Vector3D<Real_v> const &lowercorner,
0430 Vector3D<Real_v> const &uppercorner,
0431 Vector3D<Precision> const &point,
0432 Bool_v &inside)
0433 {
0434
0435 inside = lowercorner.x() < Real_v(point.x());
0436 inside &= uppercorner.x() > Real_v(point.x());
0437 if (vecCore::MaskEmpty(inside)) return;
0438
0439 inside &= lowercorner.y() < Real_v(point.y());
0440 inside &= uppercorner.y() > Real_v(point.y());
0441 if (vecCore::MaskEmpty(inside)) return;
0442
0443 inside &= lowercorner.z() < Real_v(point.z());
0444 inside &= uppercorner.z() > Real_v(point.z());
0445 }
0446
0447
0448
0449 template <typename T1, typename T2, typename Bool_v>
0450 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void ABBoxContainsKernelGeneric(Vector3D<T1> const &lowercorner,
0451 Vector3D<T1> const &uppercorner,
0452 Vector3D<T2> const &point,
0453 Bool_v &inside)
0454 {
0455 inside = lowercorner.x() < T1(point.x());
0456 inside &= uppercorner.x() > T1(point.x());
0457 if (vecCore::MaskEmpty(inside)) return;
0458
0459 inside &= lowercorner.y() < T1(point.y());
0460 inside &= uppercorner.y() > T1(point.y());
0461 if (vecCore::MaskEmpty(inside)) return;
0462
0463 inside &= lowercorner.z() < T1(point.z());
0464 inside &= uppercorner.z() > T1(point.z());
0465 }
0466
0467
0468
0469
0470
0471 template <typename Real_v, typename Real_s = typename vecCore::TypeTraits<Real_v>::ScalarType>
0472 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Real_v ABBoxSafetySqr(Vector3D<Real_v> const &lowercorner,
0473 Vector3D<Real_v> const &uppercorner,
0474 Vector3D<Real_s> const &point)
0475 {
0476
0477 using Vector3D_v = Vector3D<Real_v>;
0478 using Bool_v = vecCore::Mask_v<Real_v>;
0479
0480 const Vector3D_v kHalf(Real_v(static_cast<Real_s>(0.5)));
0481 const Vector3D_v origin((uppercorner + lowercorner) * kHalf);
0482 const Vector3D_v delta((uppercorner - lowercorner) * kHalf);
0483
0484 const Vector3D_v promotedpoint(Real_v(point.x()), Real_v(point.y()), Real_v(point.z()));
0485
0486
0487 const Vector3D_v safety = ((promotedpoint - origin).Abs()) - delta;
0488 const Bool_v outsidex = safety.x() > Real_s(0.);
0489 const Bool_v outsidey = safety.y() > Real_s(0.);
0490 const Bool_v outsidez = safety.z() > Real_s(0.);
0491
0492 Real_v runningsafetysqr(0.);
0493 Real_v runningmax(-InfinityLength<Real_v>());
0494
0495
0496
0497 {
0498
0499 Real_v tmp(0.);
0500 vecCore__MaskedAssignFunc(tmp, outsidex, safety.x() * safety.x());
0501 runningsafetysqr += tmp;
0502 runningmax = Max(runningmax, safety.x());
0503 }
0504
0505
0506 {
0507 Real_v tmp(0.);
0508 vecCore__MaskedAssignFunc(tmp, outsidey, safety.y() * safety.y());
0509 runningsafetysqr += tmp;
0510 runningmax = Max(runningmax, safety.y());
0511 }
0512
0513
0514 {
0515 Real_v tmp(0.);
0516 vecCore__MaskedAssignFunc(tmp, outsidez, safety.z() * safety.z());
0517 runningsafetysqr += tmp;
0518 runningmax = Max(runningmax, safety.z());
0519 }
0520
0521 Bool_v inside = !(outsidex || outsidey || outsidez);
0522 if (!vecCore::MaskEmpty(inside)) vecCore__MaskedAssignFunc(runningsafetysqr, inside, -runningmax * runningmax);
0523 return runningsafetysqr;
0524 }
0525
0526
0527
0528
0529
0530 template <typename Real_v, typename Real_s = typename vecCore::TypeTraits<Real_v>::ScalarType>
0531 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Real_v ABBoxSafetyRangeSqr(Vector3D<Real_v> const &lowercorner,
0532 Vector3D<Real_v> const &uppercorner,
0533 Vector3D<Real_s> const &point,
0534 Real_v &safetymaxsqr)
0535 {
0536
0537 using Vector3D_v = Vector3D<Real_v>;
0538 using Bool_v = vecCore::Mask_v<Real_v>;
0539
0540 const Vector3D_v kHalf(Real_v(static_cast<Real_s>(0.5)));
0541 const Vector3D_v origin((uppercorner + lowercorner) * kHalf);
0542 const Vector3D_v delta((uppercorner - lowercorner) * kHalf);
0543
0544 const Vector3D_v promotedpoint(Real_v(point.x()), Real_v(point.y()), Real_v(point.z()));
0545
0546
0547 const Vector3D_v safety = ((promotedpoint - origin).Abs()) - delta;
0548 const Vector3D_v safetyp = ((promotedpoint - origin).Abs()) + delta;
0549 const Bool_v outsidex = safety.x() > Real_s(0.);
0550 const Bool_v outsidey = safety.y() > Real_s(0.);
0551 const Bool_v outsidez = safety.z() > Real_s(0.);
0552
0553 Real_v runningsafetysqr(0.);
0554 safetymaxsqr = safetyp.Mag2();
0555 Real_v runningmax(-InfinityLength<Real_v>());
0556
0557
0558
0559 {
0560
0561 Real_v tmp(0.);
0562 vecCore__MaskedAssignFunc(tmp, outsidex, safety.x() * safety.x());
0563 runningsafetysqr += tmp;
0564 runningmax = Max(runningmax, safety.x());
0565
0566
0567 }
0568
0569
0570 {
0571 Real_v tmp(0.);
0572 vecCore__MaskedAssignFunc(tmp, outsidey, safety.y() * safety.y());
0573 runningsafetysqr += tmp;
0574 runningmax = Max(runningmax, safety.y());
0575
0576
0577 }
0578
0579
0580 {
0581 Real_v tmp(0.);
0582 vecCore__MaskedAssignFunc(tmp, outsidez, safety.z() * safety.z());
0583 runningsafetysqr += tmp;
0584 runningmax = Max(runningmax, safety.z());
0585
0586
0587 }
0588
0589 Bool_v inside = !(outsidex || outsidey || outsidez);
0590 if (!vecCore::MaskEmpty(inside)) vecCore__MaskedAssignFunc(runningsafetysqr, inside, -runningmax * runningmax);
0591 return runningsafetysqr;
0592 }
0593
0594 };
0595 }
0596 }
0597
0598 #endif