73 const float invalid = std::numeric_limits<float>::quiet_NaN();
77 const float x0 = points.front().x,
y0 = points.front().y;
80 float lengthSquared = std::fma(dx.hi, dx.hi, dy.hi * dy.hi);
81 lengthSquared += 2.f * std::fma(dx.hi, dx.lo, dy.hi * dy.lo);
82 const float length = std::sqrt(lengthSquared);
87 const float invLengthSquared = 1.f / lengthSquared;
89 float x,
y, r2, xx, xy, yy;
91 std::array<CachedPoint, MaxLayoutSurfaces> cache;
92 for (std::size_t
i = 0;
i < points.size(); ++
i) {
93 const auto& in = points[
i];
98 float dot = std::fma(dx.hi, px.hi, dy.hi * py.hi);
100 float correction = std::fma(dx.hi, py.lo, dx.lo * py.hi);
101 correction = std::fma(-dy.hi, px.lo, correction);
102 correction = std::fma(-dy.lo, px.hi, correction);
105 dot += std::fma(dx.hi, px.lo, std::fma(dx.lo, px.hi, std::fma(dy.hi, py.lo, dy.lo * py.hi)));
107 const float x = dot * invLengthSquared - .5f;
108 const float y = cross * invLengthSquared;
109 const float xx = in.xx, xy = in.xy, yy = in.yy;
110 cache[
i] = {
x,
y, std::fma(
x,
x,
y *
y),
111 std::fma(cs * cs, xx, std::fma(2.f * cs * sn, xy, sn * sn * yy)) * invLengthSquared,
112 std::fma(-cs * sn, xx, std::fma(std::fma(cs, cs, -sn * sn), xy, cs * sn * yy)) * invLengthSquared,
113 std::fma(sn * sn, xx, std::fma(-2.f * cs * sn, xy, cs * cs * yy)) * invLengthSquared};
115 std::array<float, 3> fit{};
116 for (
int iteration = 0; iteration < 4; ++iteration) {
117 float matrix[3][4]{};
118 for (
const auto& point : gsl::span<const CachedPoint>{cache.data(), points.size()}) {
119 const float nx = std::fma(-2.f * fit[2], point.x, -fit[1]);
120 const float ny = std::fma(-2.f * fit[2], point.y, 1.f);
121 const float variance = std::fma(nx * nx, point.xx, std::fma(2.f * nx * ny, point.xy, ny * ny * point.yy));
122 if (!(variance > 0.f) || !std::isfinite(variance)) {
126 const float weight = 1.f / variance, basis[4] = {1.f, point.x, point.r2, point.y};
127 for (
int i = 0;
i < 3; ++
i) {
128 const float weighted =
weight * basis[
i];
129 for (
int j =
i;
j < 4; ++
j) {
130 matrix[
i][
j] = std::fma(weighted, basis[
j], matrix[
i][
j]);
135 matrix[1][0] = matrix[0][1];
136 matrix[2][0] = matrix[0][2];
137 matrix[2][1] = matrix[1][2];
139 for (
int i = 0;
i < 3; ++
i) {
141 for (
int j =
i + 1;
j < 3; ++
j) {
142 if (std::abs(matrix[
j][
i]) > std::abs(matrix[pivot][
i])) {
146 for (
int k =
i; k < 4; ++k) {
147 std::swap(matrix[
i][k], matrix[pivot][k]);
149 const float diagonal = matrix[
i][
i];
150 if (std::abs(diagonal) < 1.e-15f) {
153 for (
int k =
i; k < 4; ++k) {
154 matrix[
i][k] /= diagonal;
156 for (
int j = 0;
j < 3; ++
j) {
160 const float factor = matrix[
j][
i];
161 for (
int k =
i; k < 4; ++k) {
162 matrix[
j][k] = std::fma(-factor, matrix[
i][k], matrix[
j][k]);
166 for (
int i = 0;
i < 3; ++
i) {
167 fit[
i] = matrix[
i][3];
170 const float discriminant = std::fma(-4.f * fit[0], fit[2], std::fma(fit[1], fit[1], 1.f));
171 return discriminant > 0.f ? 2.f * fit[2] / (
length * std::sqrt(discriminant) * bz * o2::constants::math::B2C) : invalid;
216 float&
chi2, uint32_t& acceptedHitCount,
217 gsl::span<const RefitMeasurementSlot> orderedSlots,
SurfaceCatalogView surfaceCatalog,
219 bool shiftReferenceToMeasurement,
float maxChi2)
noexcept
227 float scratchChi2 =
chi2;
228 uint32_t scratchAcceptedHitCount = 0;
229 constexpr uint32_t kChi2GateMinAcceptedHits = 3;
230 for (
const auto& slot : orderedSlots) {
234 if (!slot.surface.isValid() || !(surfaceCatalog.nSurfaces == 0 || surfaceCatalog.surfaces !=
nullptr) ||
235 !(slot.surface.value() < surfaceCatalog.nSurfaces)) {
239 if (!Propagator::propagateToMeasurement(scratchState, scratchLinRef, descriptor, slot.measurement, bz, direction,
240 scratchAcceptedHitCount >= kChi2GateMinAcceptedHits, maxChi2, scratchChi2,
241 shiftReferenceToMeasurement)) {
244 ++scratchAcceptedHitCount;
246 state = scratchState;
247 linRef = scratchLinRef;
249 acceptedHitCount = scratchAcceptedHitCount;
297 gsl::span<
const gsl::span<const GlobalMeasurement>> layerGlobals,
300 bool shiftReferenceToMeasurement,
301 float maxChi2ClusterAttachment,
304 gsl::span<const float> minPt,
307 float& outChi2)
noexcept
314 std::array<detail::RefitMeasurementSlot, MaxLayoutSurfaces> slotsBuffer{};
315 const gsl::span<detail::RefitMeasurementSlot> activeSlots{slotsBuffer.data(), layerGlobals.size()};
317 float maxQoverPt,
float maxChi2NDFValue)
noexcept ->
bool {
321 return chi2 < maxChi2NDFValue * static_cast<float>(
static_cast<int>(acceptedHitCount) * 2 - 5);
326 if (!std::isfinite(bz)) {
331 std::array<detail::CircleFitPoint, MaxLayoutSurfaces> points{};
332 std::size_t nPoints = 0;
333 for (
int layer = 0; layer < static_cast<int>(layerGlobals.size()); ++
layer) {
334 const int cluster = seed.getCluster(
layer);
338 if (cluster < 0 ||
static_cast<std::size_t
>(cluster) >= layerGlobals[
layer].size()) {
341 const auto& global = layerGlobals[
layer][cluster];
342 points[nPoints++] = {global.x, global.y, global.covariance.xx, global.covariance.xy, global.covariance.yy};
345 if (!std::isfinite(qOverPt)) {
351 resetCovarianceForRefit(stateA);
353 uint32_t acceptedA = 0;
354 const int activeSurfaceCount =
static_cast<int>(layerGlobals.size());
355 bool validSlots =
false;
362 maxChi2ClusterAttachment)) {
365 if (!legAcceptable(stateA, chi2A, acceptedA, o2::constants::math::VeryBig, maxChi2NDF)) {
372 inflateDiagonalCovarianceForRefit(stateB);
374 uint32_t acceptedB = 0;
381 maxChi2ClusterAttachment)) {
384 if (!legAcceptable(stateB, chi2B, acceptedB, 50.f, maxChi2NDF)) {
389 const int nClAttached = seed.getHitLayerMask().count();
390 const int minPtSlot = activeSurfaceCount - nClAttached;
391 if (minPtSlot >= 0 && minPtSlot <
static_cast<int>(minPt.size())) {
392 const float minPtThreshold = minPt[minPtSlot];
393 if (minPtThreshold > 0.f && ptFromQOverPt(stateB.
parameters[4], stateB.
absCharge) < minPtThreshold) {
400 if (repeatRefitOut) {
403 inflateDiagonalCovarianceForRefit(stateC);
405 uint32_t acceptedC = 0;
412 maxChi2ClusterAttachment)) {
415 if (!legAcceptable(stateC, chi2C, acceptedC, o2::constants::math::VeryBig, maxChi2NDF)) {
422 outParamOut = stateOut;
bool driveRefitLeg(SurfaceTrackState &state, SurfaceTrackParameters &linRef, float &chi2, uint32_t &acceptedHitCount, gsl::span< const RefitMeasurementSlot > orderedSlots, SurfaceCatalogView surfaceCatalog, float bz, material::MaterialTraversalDirection direction, bool shiftReferenceToMeasurement, float maxChi2) noexcept
bool fitTrackSeedLegs(const TrackSeed &seed, const TimeFrame &frame, gsl::span< const gsl::span< const GlobalMeasurement > > layerGlobals, SurfaceCatalogView surfaceCatalog, float bz, bool shiftReferenceToMeasurement, float maxChi2ClusterAttachment, float maxChi2NDF, bool repeatRefitOut, gsl::span< const float > minPt, SurfaceTrackState &outParamIn, SurfaceTrackState &outParamOut, float &outChi2) noexcept