Skip to content

Commit e02a56e

Browse files
TrackParametrization: use double math functions for TrackParD (#15990)
Follow-up to #15986. TrackParametrization, TrackParametrizationWithError and TrackUtils call the float-only gpu::CAMath functions (Sqrt, ASin, ATan2, ...), so TrackParD / PropagatorD is effectively float. Compared with a std:: double reference, propagateParamTo(x, b[3]) from x = 85 to 250 cm in 100 steps is off by 0.4 to 74 µm, depending on pt and the field (toy fields with a transverse component, no material), and finite-difference derivatives through it are noisy. This affects the barrel alignment (Detectors/Align) and the ITS3 alignment; no reconstruction workflow uses the double types. Call math_utils::detail::{sqrt, asin, ...}<value_t> instead, as Propagator.cxx already does: for double these dispatch to the double functions, for float to the same functions as before. Add GPUCommonMath::Expd and math_utils::detail::exp for the remaining Exp calls. This restores the math_utils::detail calls of cd9835a (switched back to CAMath in bf65d3c) and extends them to TrackParametrizationWithError and TrackUtils. Float results are bit-identical; TrackParD now agrees exactly with the double reference. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 1ddf4d9 commit e02a56e

7 files changed

Lines changed: 121 additions & 108 deletions

File tree

‎Common/MathUtils/include/MathUtils/detail/basicMath.h‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ GPUdi() T log(T x)
9191
return o2::gpu::GPUCommonMath::Log(x);
9292
};
9393

94+
template <class T>
95+
GPUdi() T exp(T x)
96+
{
97+
return o2::gpu::GPUCommonMath::Exp(x);
98+
};
99+
94100
#if !defined(GPUCA_GPUCODE_DEVICE) || defined(__CUDACC__) || defined(__HIPCC__) // Double specialisations, not for OpenCL and Metal
95101
template <>
96102
GPUhdi() double copysign(double x, double y)
@@ -107,6 +113,11 @@ GPUdi() double log(double x)
107113
{
108114
return o2::gpu::GPUCommonMath::Logd(x);
109115
};
116+
template <>
117+
GPUdi() double exp(double x)
118+
{
119+
return o2::gpu::GPUCommonMath::Expd(x);
120+
};
110121
#endif
111122

112123
#ifndef GPUCA_GPUCODE_DEVICE // Double overloads using std namespace not visible on GPU

‎DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ GPUdi() auto TrackParametrization<value_T>::getR2() const -> value_t
402402
template <typename value_T>
403403
GPUdi() auto TrackParametrization<value_T>::getR() const -> value_t
404404
{
405-
return gpu::CAMath::Sqrt(getR2());
405+
return math_utils::detail::sqrt<value_t>(getR2());
406406
}
407407

408408
//____________________________________________________________
@@ -441,7 +441,7 @@ GPUdi() auto TrackParametrization<value_T>::getCsp2() const -> value_t
441441
template <typename value_T>
442442
GPUdi() auto TrackParametrization<value_T>::getCsp() const -> value_t
443443
{
444-
return gpu::CAMath::Sqrt(getCsp2());
444+
return math_utils::detail::sqrt<value_t>(getCsp2());
445445
}
446446

447447
//____________________________________________________________
@@ -518,7 +518,7 @@ GPUdi() void TrackParametrization<value_T>::getCircleParamsLoc(value_t bz, o2::m
518518
constexpr value_t MinSagitta = 0.01f, TPCMidR = 160.f, MinCurv = 8 * MinSagitta / (TPCMidR * TPCMidR);
519519
if (gpu::CAMath::Abs(c.rC) > MinCurv) {
520520
c.rC = 1.f / getCurvature(bz);
521-
value_t sn = getSnp(), cs = gpu::CAMath::Sqrt((1.f - sn) * (1.f + sn));
521+
value_t sn = getSnp(), cs = math_utils::detail::sqrt<value_t>((1.f - sn) * (1.f + sn));
522522
c.xC = getX() - sn * c.rC; // center in tracking
523523
c.yC = getY() + cs * c.rC; // frame. Note: r is signed!!!
524524
c.rC = gpu::CAMath::Abs(c.rC);
@@ -546,7 +546,7 @@ GPUdi() void TrackParametrization<value_T>::getLineParams(o2::math_utils::Interv
546546
// get line parameterization as { x = x0 + xSlp*t, y = y0 + ySlp*t }
547547
o2::math_utils::detail::sincos(getAlpha(), sna, csa);
548548
o2::math_utils::detail::rotateZ<value_t>(getX(), getY(), ln.getX0(), ln.getY0(), sna, csa); // reference point in global frame
549-
value_t snp = getSnp(), csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp));
549+
value_t snp = getSnp(), csp = math_utils::detail::sqrt<value_t>((1.f - snp) * (1.f + snp));
550550
ln.setDX(csp * csa - snp * sna);
551551
ln.setDY(snp * csa + csp * sna);
552552
}
@@ -577,7 +577,7 @@ template <typename value_T>
577577
GPUdi() auto TrackParametrization<value_T>::getPhi() const -> value_t
578578
{
579579
// track pt direction phi (in 0:2pi range)
580-
value_t phi = gpu::CAMath::ASin(getSnp()) + getAlpha();
580+
value_t phi = math_utils::detail::asin<value_t>(getSnp()) + getAlpha();
581581
math_utils::detail::bringTo02Pi<value_t>(phi);
582582
return phi;
583583
}
@@ -587,7 +587,7 @@ template <typename value_T>
587587
GPUdi() auto TrackParametrization<value_T>::getPhiPos() const -> value_t
588588
{
589589
// angle of track position (in -pi:pi range)
590-
value_t phi = gpu::CAMath::ATan2(getY(), getX()) + getAlpha();
590+
value_t phi = math_utils::detail::atan2<value_t>(getY(), getX()) + getAlpha();
591591
math_utils::detail::bringTo02Pi<value_t>(phi);
592592
return phi;
593593
}
@@ -638,7 +638,7 @@ template <typename value_T>
638638
GPUdi() auto TrackParametrization<value_T>::getPInv() const -> value_t
639639
{
640640
// return the inverted track momentum
641-
return getPtInv() / gpu::CAMath::Sqrt(1.f + getTgl() * getTgl()); // getPtInv() is protected against being 0, full charge accounted
641+
return getPtInv() / math_utils::detail::sqrt<value_t>(1.f + getTgl() * getTgl()); // getPtInv() is protected against being 0, full charge accounted
642642
}
643643

644644
//____________________________________________________________
@@ -662,7 +662,7 @@ template <typename value_T>
662662
GPUdi() auto TrackParametrization<value_T>::getE() const -> value_t
663663
{
664664
// return the track energy
665-
return gpu::CAMath::Sqrt(getE2());
665+
return math_utils::detail::sqrt<value_t>(getE2());
666666
}
667667

668668
//____________________________________________________________
@@ -677,14 +677,14 @@ GPUdi() auto TrackParametrization<value_T>::getPt() const -> value_t
677677
template <typename value_T>
678678
GPUdi() auto TrackParametrization<value_T>::getTheta() const -> value_t
679679
{
680-
return constants::math::PIHalf - gpu::CAMath::ATan(mP[3]);
680+
return constants::math::PIHalf - math_utils::detail::atan<value_t>(mP[3]);
681681
}
682682

683683
//____________________________________________________________
684684
template <typename value_T>
685685
GPUdi() auto TrackParametrization<value_T>::getEta() const -> value_t
686686
{
687-
return -gpu::CAMath::Log(gpu::CAMath::Tan(0.5f * getTheta()));
687+
return -math_utils::detail::log<value_t>(math_utils::detail::tan<value_t>(0.5f * getTheta()));
688688
}
689689

690690
//_______________________________________________________

‎DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrizationWithError.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ GPUdi() void TrackParametrizationWithError<value_T>::updateCovCorr(const value_t
449449
oldDiag[i] = mC[diagI];
450450
mC[diagI] += delta2[i];
451451
for (int j = 0; j < i; j++) {
452-
mC[CovarMap[i][j]] *= gpu::CAMath::Sqrt(mC[diagI] * mC[DiagMap[j]] / (oldDiag[i] * oldDiag[j]));
452+
mC[CovarMap[i][j]] *= math_utils::detail::sqrt<value_t>(mC[diagI] * mC[DiagMap[j]] / (oldDiag[i] * oldDiag[j]));
453453
}
454454
}
455455
#pragma GCC diagnostic pop

‎DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackUtils.h‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ GPUd() void g3helx3(value_T qfield, value_T step, std::array<value_T, 7>& vect)
7676

7777
value_T tsint, sintt, sint, cos1t;
7878
if (gpu::CAMath::Abs(tet) > value_T(0.03)) {
79-
sint = gpu::CAMath::Sin(tet);
79+
sint = math_utils::detail::sin<value_T>(tet);
8080
sintt = sint / tet;
8181
tsint = (tet - sint) / tet;
82-
value_T t = gpu::CAMath::Sin(value_T(0.5) * tet);
82+
value_T t = math_utils::detail::sin<value_T>(value_T(0.5) * tet);
8383
cos1t = value_T(2) * t * t / tet;
8484
} else {
8585
tsint = tet * tet / value_T(6);
@@ -133,15 +133,15 @@ GPUd() value_T BetheBlochSolid(value_T bg, value_T rho, value_T kp1, value_T kp2
133133

134134
//*** Density effect
135135
value_T d2 = value_T(0);
136-
const value_T x = gpu::CAMath::Log(bg);
137-
const value_T lhwI = gpu::CAMath::Log(value_T(28.816e-9) * gpu::CAMath::Sqrt(rho * meanZA) / meanI);
136+
const value_T x = math_utils::detail::log<value_T>(bg);
137+
const value_T lhwI = math_utils::detail::log<value_T>(value_T(28.816e-9) * math_utils::detail::sqrt<value_T>(rho * meanZA) / meanI);
138138
if (x > kp2) {
139139
d2 = lhwI + x - value_T(0.5);
140140
} else if (x > kp1) {
141141
double r = (kp2 - x) / (kp2 - kp1);
142142
d2 = lhwI + x - value_T(0.5) + (value_T(0.5) - lhwI - kp1) * r * r * r;
143143
}
144-
auto dedx = mK * meanZA / beta2 * (value_T(0.5) * gpu::CAMath::Log(value_T(2) * me * bg2 * maxT / (meanI * meanI)) - beta2 - d2);
144+
auto dedx = mK * meanZA / beta2 * (value_T(0.5) * math_utils::detail::log<value_T>(value_T(2) * me * bg2 * maxT / (meanI * meanI)) - beta2 - d2);
145145
return dedx > value_T(0) ? dedx : value_T(0);
146146
}
147147

@@ -177,7 +177,7 @@ GPUd() value_T BetheBlochSolidOpt(value_T bg)
177177

178178
//*** Density effect
179179
value_T d2 = value_T(0);
180-
const value_T x = gpu::CAMath::Log(bg);
180+
const value_T x = math_utils::detail::log<value_T>(bg);
181181
if (x > kp2) {
182182
d2 = lhwI - value_T(0.5) + x;
183183
} else if (x > kp1) {

0 commit comments

Comments
 (0)