File indexing completed on 2025-01-18 10:14:04
0001
0002
0003 #ifndef VECGEOM_VOLUMES_KERNEL_TORUSIMPLEMENTATION2_H_
0004 #define VECGEOM_VOLUMES_KERNEL_TORUSIMPLEMENTATION2_H_
0005
0006 #include "VecGeom/base/Global.h"
0007 #include "VecGeom/base/Transformation3D.h"
0008 #include "VecGeom/volumes/kernel/GenericKernels.h"
0009 #include "VecGeom/volumes/kernel/TubeImplementation.h"
0010 #include "VecGeom/volumes/TorusStruct2.h"
0011
0012 #include <cstdio>
0013 #include <VecCore/VecCore>
0014
0015 namespace vecgeom {
0016
0017 VECGEOM_DEVICE_FORWARD_DECLARE(struct TorusImplementation2;);
0018 VECGEOM_DEVICE_DECLARE_CONV(struct, TorusImplementation2);
0019
0020 inline namespace VECGEOM_IMPL_NAMESPACE {
0021
0022
0023 template <typename T>
0024 VECCORE_ATT_HOST_DEVICE
0025 unsigned int SolveCubic(T a, T b, T c, T *x)
0026 {
0027
0028
0029
0030
0031 const T ott = 1. / 3.;
0032 const T sq3 = Sqrt(3.);
0033 const T inv6sq3 = 1. / (6. * sq3);
0034 unsigned int ireal = 1;
0035 T p = b - a * a * ott;
0036 T q = c - a * b * ott + 2. * a * a * a * ott * ott * ott;
0037 T delta = 4 * p * p * p + 27. * q * q;
0038 T t, u;
0039
0040 if (delta >= 0) {
0041 delta = Sqrt(delta);
0042 t = (-3 * q * sq3 + delta) * inv6sq3;
0043 u = (3 * q * sq3 + delta) * inv6sq3;
0044 x[0] = CopySign(T(1.), t) * Cbrt(Abs(t)) - CopySign(T(1.), u) * Cbrt(Abs(u)) - a * ott;
0045 } else {
0046 delta = Sqrt(-delta);
0047 t = -0.5 * q;
0048 u = delta * inv6sq3;
0049 x[0] = 2. * Pow(t * t + u * u, T(0.5) * ott) * cos(ott * ATan2(u, t));
0050 x[0] -= a * ott;
0051 }
0052
0053 t = x[0] * x[0] + a * x[0] + b;
0054 u = a + x[0];
0055 delta = u * u - T(4.) * t;
0056 if (delta >= 0) {
0057 ireal = 3;
0058 delta = Sqrt(delta);
0059 x[1] = T(0.5) * (-u - delta);
0060 x[2] = T(0.5) * (-u + delta);
0061 }
0062
0063 return ireal;
0064 }
0065
0066 template <typename T, unsigned int i, unsigned int j>
0067 VECGEOM_FORCE_INLINE
0068 VECCORE_ATT_HOST_DEVICE
0069 void CmpAndSwap(T *array)
0070 {
0071 if (vecCore::MaskFull(array[i] > array[j])) {
0072 T c = array[j];
0073 array[j] = array[i];
0074 array[i] = c;
0075 }
0076 }
0077
0078
0079
0080
0081 template <typename T>
0082 VECGEOM_FORCE_INLINE
0083 VECCORE_ATT_HOST_DEVICE
0084 void Sort4(T *array)
0085 {
0086 CmpAndSwap<T, 0, 2>(array);
0087 CmpAndSwap<T, 1, 3>(array);
0088 CmpAndSwap<T, 0, 1>(array);
0089 CmpAndSwap<T, 2, 3>(array);
0090 CmpAndSwap<T, 1, 2>(array);
0091 }
0092
0093
0094
0095
0096 template <typename T>
0097 VECCORE_ATT_HOST_DEVICE
0098 int SolveQuartic(T a, T b, T c, T d, T *x)
0099 {
0100
0101
0102
0103
0104 T e = b - 3. * a * a / 8.;
0105 T f = c + a * a * a / 8. - 0.5 * a * b;
0106 T g = d - 3. * a * a * a * a / 256. + a * a * b / 16. - a * c / 4.;
0107 T xx[4] = {vecgeom::kInfLength, vecgeom::kInfLength, vecgeom::kInfLength, vecgeom::kInfLength};
0108 T delta;
0109 T h = 0.;
0110 unsigned int ireal = 0;
0111
0112
0113 if (Abs(f) < 1E-6) {
0114 delta = e * e - 4. * g;
0115 if (delta < 0.) return 0;
0116 delta = Sqrt(delta);
0117 h = 0.5 * (-e - delta);
0118 if (h >= 0) {
0119 h = Sqrt(h);
0120 x[ireal++] = -h - 0.25 * a;
0121 x[ireal++] = h - 0.25 * a;
0122 }
0123 h = 0.5 * (-e + delta);
0124 if (h >= 0) {
0125 h = Sqrt(h);
0126 x[ireal++] = -h - 0.25 * a;
0127 x[ireal++] = h - 0.25 * a;
0128 }
0129 Sort4(x);
0130 return ireal;
0131 }
0132
0133 if (Abs(g) < 1E-6) {
0134 x[ireal++] = -0.25 * a;
0135
0136
0137 unsigned int ncubicroots = SolveCubic<T>(0, e, f, xx);
0138
0139 for (unsigned int i = 0; i < ncubicroots; i++)
0140 x[ireal++] = xx[i] - 0.25 * a;
0141 Sort4(x);
0142 return ireal;
0143 }
0144
0145 ireal = SolveCubic<T>(2. * e, e * e - 4. * g, -f * f, xx);
0146 if (ireal == 1) {
0147 if (xx[0] <= 0) return 0;
0148 h = Sqrt(xx[0]);
0149 } else {
0150
0151 for (unsigned int i = 0; i < 3; i++) {
0152 h = xx[i];
0153 if (h >= 0) break;
0154 }
0155 if (h <= 0) return 0;
0156 h = Sqrt(h);
0157 }
0158 T j = 0.5 * (e + h * h - f / h);
0159 ireal = 0;
0160 delta = h * h - 4. * j;
0161 if (delta >= 0) {
0162 delta = Sqrt(delta);
0163 x[ireal++] = 0.5 * (-h - delta) - 0.25 * a;
0164 x[ireal++] = 0.5 * (-h + delta) - 0.25 * a;
0165 }
0166 delta = h * h - 4. * g / j;
0167 if (delta >= 0) {
0168 delta = Sqrt(delta);
0169 x[ireal++] = 0.5 * (h - delta) - 0.25 * a;
0170 x[ireal++] = 0.5 * (h + delta) - 0.25 * a;
0171 }
0172 Sort4(x);
0173 return ireal;
0174 }
0175
0176 class PlacedTorus2;
0177 template <typename T>
0178 struct TorusStruct2;
0179 class UnplacedTorus2;
0180
0181 class SIMDUnplacedTorus2;
0182
0183 struct TorusImplementation2 {
0184 using PlacedShape_t = PlacedTorus2;
0185 using UnplacedStruct_t = TorusStruct2<Precision>;
0186 using UnplacedVolume_t = UnplacedTorus2;
0187
0188 template <class Real_v>
0189 VECCORE_ATT_HOST_DEVICE
0190 static Real_v DistSqrToTorusR(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point,
0191 Vector3D<Real_v> const &dir, Real_v dist)
0192 {
0193 Vector3D<Real_v> p = point + dir * dist;
0194 Real_v rxy = p.Perp();
0195 return (rxy - torus.rtor()) * (rxy - torus.rtor()) + p.z() * p.z();
0196 }
0197
0198 template <typename Real_v>
0199 VECGEOM_FORCE_INLINE
0200 VECCORE_ATT_HOST_DEVICE
0201 static void DistanceToOut(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point, Vector3D<Real_v> const &dir,
0202 Real_v const & , Real_v &distance)
0203 {
0204 using Inside_v = vecCore::Index_v<Real_v>;
0205 using Bool_v = vecCore::Mask_v<Real_v>;
0206
0207 bool hasphi = (torus.dphi() < kTwoPi);
0208 bool hasrmin = (torus.rmin() > 0);
0209
0210
0211 Bool_v done = Bool_v(false);
0212 distance = kInfLength;
0213
0214
0215 Real_v distz = Abs(point.z()) - torus.rmax();
0216 done |= distz > kHalfTolerance;
0217
0218
0219 Real_v rsq = point.x() * point.x() + point.y() * point.y();
0220
0221 Precision outerExclRadius = torus.rtor() + torus.rmax() + kHalfTolerance;
0222 done |= rsq > outerExclRadius * outerExclRadius;
0223 Precision innerExclRadius = torus.rtor() - torus.rmax() - kHalfTolerance;
0224 done |= rsq < innerExclRadius * innerExclRadius;
0225 vecCore__MaskedAssignFunc(distance, done, Real_v(-1.));
0226 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(done))
0227 return;
0228
0229
0230
0231
0232
0233
0234 Inside_v locus;
0235 TorusImplementation2::InsideKernel<Real_v, Inside_v>(torus, point, locus);
0236 vecCore__MaskedAssignFunc(distance, locus == EInside::kOutside, Real_v(-1.));
0237 done |= locus == EInside::kOutside;
0238 if (vecCore::EarlyReturnAllowed() && vecCore::MaskFull(done))
0239 return;
0240
0241 Real_v dout = ToBoundary<Real_v, false>(torus, point, dir, torus.rmax(), true);
0242
0243 Real_v din(kInfLength);
0244 if (hasrmin) {
0245 din = ToBoundary<Real_v, true>(torus, point, dir, torus.rmin(), true);
0246
0247 }
0248 distance = Min(dout, din);
0249
0250
0251
0252 if (hasphi) {
0253 Real_v distPhi1;
0254 Real_v distPhi2;
0255
0256 torus.GetWedge().DistanceToOut<Real_v>(point, dir, distPhi1, distPhi2);
0257 Bool_v smallerphi = distPhi1 < distance;
0258 if (!vecCore::MaskEmpty(smallerphi)) {
0259 Vector3D<Real_v> intersectionPoint = point + dir * distPhi1;
0260 Bool_v insideDisk;
0261
0262 UnplacedContainsDisk<Real_v, Bool_v>(torus, intersectionPoint, insideDisk);
0263
0264 if (!vecCore::MaskEmpty(insideDisk))
0265 {
0266 Real_v diri = intersectionPoint.x() * torus.GetWedge().GetAlong1().x() +
0267 intersectionPoint.y() * torus.GetWedge().GetAlong1().y();
0268 Bool_v rightside = (diri >= 0);
0269
0270 vecCore__MaskedAssignFunc(distance, rightside && smallerphi && insideDisk, distPhi1);
0271 }
0272 }
0273 smallerphi = distPhi2 < distance;
0274 if (!vecCore::MaskEmpty(smallerphi)) {
0275
0276 Vector3D<Real_v> intersectionPoint = point + dir * distPhi2;
0277 Bool_v insideDisk;
0278
0279 UnplacedContainsDisk<Real_v, Bool_v>(torus, intersectionPoint, insideDisk);
0280 if (!vecCore::MaskEmpty(insideDisk))
0281 {
0282 Real_v diri2 = intersectionPoint.x() * torus.GetWedge().GetAlong2().x() +
0283 intersectionPoint.y() * torus.GetWedge().GetAlong2().y();
0284 Bool_v rightside = (diri2 >= Real_v(0));
0285 vecCore__MaskedAssignFunc(distance, rightside && (distPhi2 < distance) && smallerphi && insideDisk, distPhi2);
0286 }
0287 }
0288 }
0289
0290 vecCore__MaskedAssignFunc(distance, done || distance >= kInfLength, Real_v(-1.));
0291 }
0292
0293 template <typename Real_v, typename Bool_v, bool notForDisk>
0294 VECGEOM_FORCE_INLINE
0295 VECCORE_ATT_HOST_DEVICE
0296 static void ContainsKernel(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point, Bool_v &inside)
0297 {
0298 Bool_v unused;
0299 Bool_v outside;
0300 TorusImplementation2::GenericKernelForContainsAndInside<Real_v, false, notForDisk>(torus, point, unused, outside);
0301 inside = !outside;
0302 }
0303
0304 template <typename Real_v, typename Bool_v>
0305 VECGEOM_FORCE_INLINE
0306 VECCORE_ATT_HOST_DEVICE
0307 static void UnplacedContainsDisk(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point, Bool_v &inside)
0308 {
0309 ContainsKernel<Real_v, Bool_v, false>(torus, point, inside);
0310 }
0311
0312 template <typename Real_v, typename Inside_t>
0313 VECGEOM_FORCE_INLINE
0314 VECCORE_ATT_HOST_DEVICE
0315 static void InsideKernel(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point, Inside_t &inside)
0316 {
0317
0318 using Bool_v = vecCore::Mask_v<Real_v>;
0319
0320 Bool_v completelyinside, completelyoutside;
0321 TorusImplementation2::GenericKernelForContainsAndInside<Real_v, true, true>(torus, point, completelyinside,
0322 completelyoutside);
0323 inside = Inside_t(EInside::kSurface);
0324 vecCore::MaskedAssign(inside, completelyoutside, Inside_t(EInside::kOutside));
0325 vecCore::MaskedAssign(inside, completelyinside, Inside_t(EInside::kInside));
0326 }
0327
0328 template <typename Real_v, bool ForInside, bool notForDisk>
0329 VECGEOM_FORCE_INLINE
0330 VECCORE_ATT_HOST_DEVICE
0331 static void GenericKernelForContainsAndInside(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point,
0332 typename vecCore::Mask_v<Real_v> &completelyinside,
0333 typename vecCore::Mask_v<Real_v> &completelyoutside)
0334
0335 {
0336
0337
0338
0339
0340
0341 using Bool_v = vecCore::Mask_v<Real_v>;
0342 VECGEOM_CONST Precision tol = 100. * vecgeom::kTolerance;
0343
0344 Real_v rxy = Sqrt(point[0] * point[0] + point[1] * point[1]);
0345 Real_v radsq = (rxy - torus.rtor()) * (rxy - torus.rtor()) + point[2] * point[2];
0346
0347 if (ForInside) {
0348 completelyoutside = radsq > (tol * torus.rmax() + torus.rmax2());
0349 completelyinside = radsq < (-tol * torus.rmax() + torus.rmax2());
0350 } else {
0351 completelyoutside = radsq > torus.rmax2();
0352 }
0353
0354 if (vecCore::EarlyReturnAllowed()) {
0355 if (vecCore::MaskFull(completelyoutside)) {
0356 return;
0357 }
0358 }
0359
0360 if (ForInside) {
0361 completelyoutside |= radsq < (-tol * torus.rmin() + torus.rmin2());
0362 completelyinside &= radsq > (tol * torus.rmin() + torus.rmin2());
0363 } else {
0364 completelyoutside |= radsq < torus.rmin2();
0365 }
0366
0367
0368 if (vecCore::EarlyReturnAllowed()) {
0369 if (vecCore::MaskFull(completelyoutside)) {
0370 return;
0371 }
0372 }
0373
0374
0375 if ((torus.dphi() < kTwoPi) && (notForDisk)) {
0376 Bool_v completelyoutsidephi;
0377 Bool_v completelyinsidephi;
0378 torus.GetWedge().GenericKernelForContainsAndInside<Real_v, ForInside>(point, completelyinsidephi,
0379 completelyoutsidephi);
0380
0381 completelyoutside |= completelyoutsidephi;
0382 if (ForInside) completelyinside &= completelyinsidephi;
0383 }
0384 }
0385
0386 template <typename Real_v, bool ForRmin>
0387 VECGEOM_FORCE_INLINE
0388 VECCORE_ATT_HOST_DEVICE
0389 static Real_v ToBoundary(UnplacedStruct_t const &torus, Vector3D<Real_v> const &pt, Vector3D<Real_v> const &dir,
0390 Real_v radius, bool out)
0391 {
0392
0393
0394
0395
0396
0397
0398 Real_v s = vecgeom::kInfLength;
0399 VECGEOM_CONST Real_v tol = 100. * vecgeom::kTolerance;
0400 Real_v r0sq = pt[0] * pt[0] + pt[1] * pt[1] + pt[2] * pt[2];
0401 Real_v rdotn = pt[0] * dir[0] + pt[1] * dir[1] + pt[2] * dir[2];
0402 Real_v rsumsq = torus.rtor2() + radius * radius;
0403 Real_v a = 4. * rdotn;
0404 Real_v b = 2. * (r0sq + 2. * rdotn * rdotn - rsumsq + 2. * torus.rtor2() * dir[2] * dir[2]);
0405 Real_v c = 4. * (r0sq * rdotn - rsumsq * rdotn + 2. * torus.rtor2() * pt[2] * dir[2]);
0406 Real_v d = r0sq * r0sq - 2. * r0sq * rsumsq + 4. * torus.rtor2() * pt[2] * pt[2] +
0407 (torus.rtor2() - radius * radius) * (torus.rtor2() - radius * radius);
0408
0409 Real_v x[4] = {vecgeom::kInfLength, vecgeom::kInfLength, vecgeom::kInfLength, vecgeom::kInfLength};
0410 int nsol = 0;
0411
0412
0413 if (vecCore::MaskFull(Abs(dir[2]) < 1E-3 && Abs(pt[2]) < 0.1 * radius)) {
0414 Real_v r0 = torus.rtor() - Sqrt((radius - pt[2]) * (radius + pt[2]));
0415 Real_v invdirxy2 = 1. / (1 - dir.z() * dir.z());
0416 Real_v b0 = (pt[0] * dir[0] + pt[1] * dir[1]) * invdirxy2;
0417 Real_v c0 = (pt[0] * pt[0] + (pt[1] - r0) * (pt[1] + r0)) * invdirxy2;
0418 Real_v delta = b0 * b0 - c0;
0419 if (vecCore::MaskFull(delta > 0)) {
0420 x[nsol] = -b0 - Sqrt(delta);
0421 if (vecCore::MaskFull(x[nsol] > -tol)) nsol++;
0422 x[nsol] = -b0 + Sqrt(delta);
0423 if (vecCore::MaskFull(x[nsol] > -tol)) nsol++;
0424 }
0425 r0 = torus.rtor() + Sqrt((radius - pt[2]) * (radius + pt[2]));
0426 c0 = (pt[0] * pt[0] + (pt[1] - r0) * (pt[1] + r0)) * invdirxy2;
0427 delta = b0 * b0 - c0;
0428 if (vecCore::MaskFull(delta > 0)) {
0429 x[nsol] = -b0 - Sqrt(delta);
0430 if (vecCore::MaskFull(x[nsol] > -tol)) nsol++;
0431 x[nsol] = -b0 + Sqrt(delta);
0432 if (vecCore::MaskFull(x[nsol] > -tol)) nsol++;
0433 }
0434 if (nsol) {
0435 Sort4(x);
0436 }
0437 } else {
0438 nsol = SolveQuartic(a, b, c, d, x);
0439 }
0440 if (!nsol) {
0441 return vecgeom::kInfLength;
0442 }
0443
0444
0445 Real_v ndotd;
0446 bool inner = vecCore::MaskFull(Abs(radius - torus.rmin()) < vecgeom::kTolerance);
0447 for (int i = 0; i < nsol; i++) {
0448 if (vecCore::MaskFull(x[i] < -10)) continue;
0449
0450 Vector3D<Real_v> r0 = pt + x[i] * dir;
0451 Vector3D<Real_v> norm = r0;
0452 r0.z() = 0.;
0453 r0.Normalize();
0454 r0 *= torus.rtor();
0455 norm -= r0;
0456
0457
0458
0459
0460 ndotd = norm.Dot(dir);
0461 if (inner ^ out) {
0462 if (vecCore::MaskFull(ndotd < 0)) continue;
0463 } else {
0464 if (vecCore::MaskFull(ndotd > 0)) continue;
0465 }
0466
0467
0468 if (torus.dphi() < vecgeom::kTwoPi) {
0469 if (!vecCore::MaskFull(torus.GetWedge().ContainsWithBoundary<Real_v>(r0))) continue;
0470 }
0471
0472 s = x[i];
0473
0474 Real_v eps = vecgeom::kInfLength;
0475 Real_v delta = s * s * s * s + a * s * s * s + b * s * s + c * s + d;
0476 Real_v eps0 = -delta / (4. * s * s * s + 3. * a * s * s + 2. * b * s + c);
0477 int ntry = 0;
0478 while (vecCore::MaskFull(Abs(eps) > vecgeom::kTolerance)) {
0479 if (vecCore::MaskFull(Abs(eps0) > 100)) break;
0480 s += eps0;
0481 if (vecCore::MaskFull(Abs(s + eps0) < vecgeom::kTolerance)) break;
0482 delta = s * s * s * s + a * s * s * s + b * s * s + c * s + d;
0483 eps = -delta / (4. * s * s * s + 3. * a * s * s + 2. * b * s + c);
0484 if (vecCore::MaskFull(Abs(eps) >= Abs(eps0))) break;
0485 ntry++;
0486
0487 if (ntry > 100) break;
0488 eps0 = eps;
0489 }
0490
0491 if (vecCore::MaskFull(s < -tol)) continue;
0492 return Max(Real_v(0.), s);
0493 }
0494 return vecgeom::kInfLength;
0495 }
0496
0497 template <typename Real_v>
0498 VECGEOM_FORCE_INLINE
0499 VECCORE_ATT_HOST_DEVICE
0500 static void SafetyToOut(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point, Real_v &safety)
0501 {
0502 Real_v rxy = Sqrt(point[0] * point[0] + point[1] * point[1]);
0503 Real_v rad = Sqrt((rxy - torus.rtor()) * (rxy - torus.rtor()) + point[2] * point[2]);
0504 safety = torus.rmax() - rad;
0505 if (torus.rmin()) {
0506 safety = Min(rad - torus.rmin(), torus.rmax() - rad);
0507 }
0508
0509
0510 bool hasphi = (torus.dphi() < kTwoPi);
0511 if (hasphi) {
0512 Real_v safetyPhi = torus.GetWedge().SafetyToOut<Real_v>(point);
0513 safety = Min(safetyPhi, safety);
0514 }
0515 }
0516
0517 template <typename Real_v>
0518 VECGEOM_FORCE_INLINE
0519 VECCORE_ATT_HOST_DEVICE
0520 static void Contains(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point,
0521 typename vecCore::Mask_v<Real_v> &contains)
0522 {
0523 using Bool_v = vecCore::Mask_v<Real_v>;
0524 Bool_v unused, outside;
0525 TorusImplementation2::GenericKernelForContainsAndInside<Real_v, true, false>(torus, point, unused, outside);
0526 contains = !outside;
0527 }
0528
0529 template <typename Real_v, typename Inside_t>
0530 VECGEOM_FORCE_INLINE
0531 VECCORE_ATT_HOST_DEVICE
0532 static void Inside(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point, Inside_t &inside)
0533 {
0534 TorusImplementation2::InsideKernel<Real_v, Inside_t>(torus, point, inside);
0535 }
0536
0537 template <typename Real_v>
0538 VECGEOM_FORCE_INLINE
0539 VECCORE_ATT_HOST_DEVICE
0540 static void DistanceToIn(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point,
0541 Vector3D<Real_v> const &direction, Real_v const &stepMax, Real_v &distance)
0542 {
0543
0544
0545
0546
0547
0548
0549 Vector3D<Real_v> localPoint = point;
0550 Vector3D<Real_v> localDirection = direction;
0551
0552 using Bool_v = vecCore::Mask_v<Real_v>;
0553 using Inside_v = vecCore::Index_v<Real_v>;
0554
0555
0556 distance = kInfLength;
0557
0558
0559 Bool_v inBounds;
0560 Bool_v done = Bool_v(false);
0561 Inside_v inside = Inside_v(EInside::kOutside);
0562 Real_v tubeDistance = kInfLength;
0563
0564 #ifndef VECGEOM_NO_SPECIALIZATION
0565
0566
0567 TubeImplementation<TubeTypes::HollowTube>::Contains(torus.GetBoundingTube().GetStruct(), localPoint, inBounds);
0568
0569
0570 TubeImplementation<TubeTypes::HollowTube>::DistanceToIn(torus.GetBoundingTube().GetStruct(), localPoint,
0571 localDirection, stepMax, tubeDistance);
0572 #else
0573
0574
0575 TubeImplementation<TubeTypes::UniversalTube>::Contains(torus.GetBoundingTube().GetStruct(), localPoint, inBounds);
0576
0577
0578
0579 if (!inBounds) {
0580 TubeImplementation<TubeTypes::UniversalTube>::DistanceToIn(torus.GetBoundingTube().GetStruct(), localPoint,
0581 localDirection, stepMax, tubeDistance);
0582 } else {
0583 tubeDistance = 0.;
0584 }
0585
0586 #endif
0587 if (inBounds) {
0588
0589 TorusImplementation2::InsideKernel<Real_v, Inside_v>(torus, point, inside);
0590 if (vecCore::MaskFull(inside == Inside_v(EInside::kInside))) {
0591 done = Bool_v(true);
0592 distance = Real_v(-1.);
0593 }
0594 } else {
0595 done = Bool_v(vecCore::MaskFull(tubeDistance == kInfLength));
0596 }
0597
0598 if (vecCore::EarlyReturnAllowed()) {
0599 if (vecCore::MaskFull(done)) {
0600 return;
0601 }
0602 }
0603
0604
0605
0606 localPoint += tubeDistance * localDirection;
0607 Bool_v hasphi = Bool_v(torus.dphi() < vecgeom::kTwoPi);
0608 if (vecCore::MaskFull(hasphi)) {
0609 Real_v d1, d2;
0610
0611 auto wedge = torus.GetWedge();
0612
0613
0614 wedge.DistanceToIn<Real_v>(localPoint, localDirection, d1, d2);
0615
0616
0617 if (vecCore::MaskFull(d1 != kInfLength)) {
0618 Real_v daxis = DistSqrToTorusR(torus, localPoint, localDirection, d1);
0619 if (vecCore::MaskFull(daxis >= torus.rmin2() && daxis < torus.rmax2())) {
0620 distance = d1;
0621
0622 if (vecCore::MaskFull(Abs(distance) < kTolerance)) {
0623 distance += tubeDistance;
0624 return;
0625 }
0626 }
0627 }
0628
0629 if (vecCore::MaskFull(d2 != kInfLength)) {
0630 Real_v daxis = DistSqrToTorusR(torus, localPoint, localDirection, d2);
0631 if (vecCore::MaskFull(daxis >= torus.rmin2() && daxis < torus.rmax2())) {
0632 distance = Min(d2, distance);
0633
0634 if (vecCore::MaskFull(Abs(distance) < kTolerance)) {
0635 distance += tubeDistance;
0636 return;
0637 }
0638 }
0639 }
0640 distance = kInfLength;
0641 }
0642
0643 Real_v dd = ToBoundary<Real_v, false>(torus, localPoint, localDirection, torus.rmax(), false);
0644
0645
0646 if (torus.rmin() > 0.) {
0647 Real_v ddrmin = ToBoundary<Real_v, true>(torus, localPoint, localDirection, torus.rmin(), false);
0648 dd = Min(dd, ddrmin);
0649 }
0650 distance = Min(distance, dd);
0651 distance += tubeDistance;
0652
0653
0654 if (vecCore::MaskFull(Abs(distance) > kInfLength)) distance = kInfLength;
0655
0656 return;
0657 }
0658
0659 template <typename Real_v>
0660 VECGEOM_FORCE_INLINE
0661 VECCORE_ATT_HOST_DEVICE
0662 static void SafetyToIn(UnplacedStruct_t const &torus, Vector3D<Real_v> const &point, Real_v &safety)
0663 {
0664
0665
0666 Vector3D<Real_v> localPoint = point;
0667
0668
0669 Real_v rxy = Sqrt(localPoint[0] * localPoint[0] + localPoint[1] * localPoint[1]);
0670 Real_v rad = Sqrt((rxy - torus.rtor()) * (rxy - torus.rtor()) + localPoint[2] * localPoint[2]);
0671 safety = rad - torus.rmax();
0672 if (torus.rmin()) {
0673 safety = Max(torus.rmin() - rad, rad - torus.rmax());
0674 }
0675
0676 bool hasphi = (torus.dphi() < kTwoPi);
0677 if (hasphi && vecCore::MaskFull(rxy != 0.)) {
0678 Real_v safetyPhi = torus.GetWedge().SafetyToIn<Real_v>(localPoint);
0679 safety = Max(safetyPhi, safety);
0680 }
0681 }
0682
0683 VECCORE_ATT_HOST_DEVICE
0684 static void PrintType() { printf("SpecializedTorus2"); }
0685
0686 template <typename Stream>
0687 static void PrintType(Stream &s, int transCodeT = translation::kGeneric, int rotCodeT = rotation::kGeneric)
0688 {
0689 s << "SpecializedTorus2<" << transCodeT << "," << rotCodeT << ">";
0690 }
0691
0692 template <typename Stream>
0693 static void PrintImplementationType(Stream &s)
0694 {
0695 s << "TorusImplemenation2";
0696 }
0697
0698 template <typename Stream>
0699 static void PrintUnplacedType(Stream &s)
0700 {
0701 s << "UnplacedTorus2";
0702 }
0703
0704 };
0705 }
0706 }
0707
0708 #endif