147    return {float(
m(0, 0)), float(
m(1, 0)), float(
m(1, 1)), float(
m(2, 0)), float(
m(2, 1)), float(
m(2, 2))};
 
 
  166    mUseMatBudget = 
true;
 
 
  173  float getMaxR()
 const { 
return std::sqrt(mMaxR2); }
 
  179  double getHz(
double b)
 const { 
return std::copysign(1, 
b); }
 
  185  template <
class... Tr>
 
  233    const auto& trc = mCandTr[mOrder[cand]][
i];
 
  235    mat(0, 0) = trc.getSigma2X();
 
  236    mat(1, 1) = trc.getSigma2Y();
 
  237    mat(1, 0) = trc.getSigmaXY();
 
  238    mat(2, 2) = trc.getSigma2Y() * ZerrFactor;
 
 
  243  template <
class T, 
class... Tr>
 
  244  void assign(
int i, 
const T& t, 
const Tr&... args)
 
  246    static_assert(std::is_convertible<T, Track>(), 
"Wrong track type");
 
 
  254    mAllowAltPreference = 
true;
 
 
  266  std::array<std::array<Vec3D, N>, N> mDResidDz;
 
  268  std::array<std::array<Vec3D, N>, N> mD2ResidDz2;
 
  272  std::array<const Track*, N> mOrigTrPtr;
 
  273  std::array<TrackAuxPar, N> mTrAux; 
 
  274  CrossInfo mCrossings;              
 
  276  std::array<ArrTrackCovI, MAXHYP> mTrcEInv; 
 
  277  std::array<ArrTrack, MAXHYP> mCandTr;      
 
  278  std::array<ArrTrCoef, MAXHYP> mTrCFVT;     
 
  279  std::array<ArrTrDer, MAXHYP> mTrDer;       
 
  280  std::array<ArrTrPos, MAXHYP> mTrPos;       
 
  281  std::array<ArrTrPos, MAXHYP> mTrRes;       
 
  282  std::array<Vec3D, MAXHYP> mPCA;            
 
  283  std::array<float, MAXHYP> mChi2 = {0};     
 
  284  std::array<int, MAXHYP> mNIters;           
 
  285  std::array<bool, MAXHYP> mTrPropDone;      
 
  287  std::array<int, MAXHYP> mOrder{0};
 
  290  int mCrossIDAlt = -1;
 
  291  bool mAllowAltPreference = 
true;  
 
  292  bool mUseAbsDCA = 
false;          
 
  293  bool mPropagateToPCA = 
true;      
 
  294  bool mUseMatBudget = 
false;       
 
  295  bool mTGeoFallBackAllowed = 
true; 
 
  298  float mMaxR2 = 200. * 200.;       
 
  299  float mMaxDXIni = 4.;             
 
  300  float mMinParamChange = 1e-5;     
 
  301  float mMinRelChi2Change = 0.98;   
 
  302  float mMaxChi2 = 100;             
 
  303  float mMaxDist2ToMergeSeeds = 1.; 
 
  310template <
int N, 
typename... Args>
 
  311template <
class... Tr>
 
  315  static_assert(
sizeof...(args) == N, 
"incorrect number of input tracks");
 
  319  for (
int i = 0; 
i < N; 
i++) {
 
  320    mTrAux[
i].set(*mOrigTrPtr[
i], mBz);
 
  323  if (!mCrossings.set(mTrAux[0], *mOrigTrPtr[0], mTrAux[1], *mOrigTrPtr[1])) { 
 
  327  if (mCrossings.nDCA == MAXHYP) { 
 
  328    auto dst2 = (mCrossings.xDCA[0] - mCrossings.xDCA[1]) * (mCrossings.xDCA[0] - mCrossings.xDCA[1]) +
 
  329                (mCrossings.yDCA[0] - mCrossings.yDCA[1]) * (mCrossings.yDCA[0] - mCrossings.yDCA[1]);
 
  331    if (dst2 < mMaxDist2ToMergeSeeds) {
 
  333      mCrossings.xDCA[0] = 0.5 * (mCrossings.xDCA[0] + mCrossings.xDCA[1]);
 
  334      mCrossings.yDCA[0] = 0.5 * (mCrossings.yDCA[0] + mCrossings.yDCA[1]);
 
  339  for (
int ic = 0; ic < mCrossings.nDCA; ic++) {
 
  341    if (mCrossings.xDCA[ic] * mCrossings.xDCA[ic] + mCrossings.yDCA[ic] * mCrossings.yDCA[ic] > mMaxR2) {
 
  346    mCrossIDAlt = (mCrossings.nDCA == 2 && mAllowAltPreference) ? 1 - ic : -1; 
 
  347    mNIters[mCurHyp] = 0;
 
  348    mTrPropDone[mCurHyp] = 
false;
 
  349    mChi2[mCurHyp] = -1.;
 
  351    findZatXY_mid(mCurHyp);
 
  353    if (mUseAbsDCA ? minimizeChi2NoErr() : minimizeChi2()) {
 
  354      mOrder[mCurHyp] = mCurHyp;
 
  355      if (mPropagateToPCA && !FwdpropagateTracksToVertex(mCurHyp)) {
 
  362  for (
int i = mCurHyp; 
i--;) { 
 
  363    for (
int j = 
i; 
j--;) {
 
  364      if (mChi2[mOrder[
i]] < mChi2[mOrder[
j]]) {
 
  365        std::swap(mOrder[
i], mOrder[
j]);
 
  374template <
int N, 
typename... Args>
 
  378  if (!FwdcalcInverseWeight()) {
 
  381  for (
int i = N; 
i--;) { 
 
  382    const auto& tcov = mTrcEInv[mCurHyp][
i];
 
  385    miei[0][0] = tcov.sxx;
 
  386    miei[0][1] = tcov.sxy;
 
  387    miei[1][0] = tcov.sxy;
 
  388    miei[1][1] = tcov.syy;
 
  389    miei[2][2] = tcov.szz;
 
  391    mTrCFVT[mCurHyp][
i] = mWeightInv * miei;
 
  397template <
int N, 
typename... Args>
 
  401  auto* arrmat = mWeightInv.Array();
 
  402  memset(arrmat, 0, 
sizeof(mWeightInv));
 
  409  for (
int i = N; 
i--;) {
 
  410    const auto& tcov = mTrcEInv[mCurHyp][
i];
 
  411    arrmat[XX] += tcov.sxx;
 
  412    arrmat[XY] += tcov.sxy;
 
  414    arrmat[YY] += tcov.syy;
 
  416    arrmat[ZZ] += tcov.szz;
 
  420  return mWeightInv.Invert();
 
  424template <
int N, 
typename... Args>
 
  429  for (
int i = N; 
i--;) { 
 
  431    for (
int j = N; 
j--;) {                   
 
  432      const auto& matT = mTrCFVT[mCurHyp][
j]; 
 
  433      const auto& trDz = mTrDer[mCurHyp][
j];  
 
  434      auto& dr1 = mDResidDz[
i][
j];
 
  435      auto& dr2 = mD2ResidDz2[
i][
j];
 
  437      matMT[0][0] = matT[0][0];
 
  438      matMT[0][1] = matT[0][1];
 
  439      matMT[0][2] = matT[0][2];
 
  440      matMT[1][0] = matT[1][0];
 
  441      matMT[1][1] = matT[1][1];
 
  442      matMT[1][2] = matT[1][2];
 
  443      matMT[2][0] = matT[2][0];
 
  444      matMT[2][1] = matT[2][1];
 
  445      matMT[2][2] = matT[2][2];
 
  448      dr1[0] = -(matMT[0][0] * trDz.dxdz + matMT[0][1] * trDz.dydz + matMT[0][2]);
 
  449      dr1[1] = -(matMT[1][0] * trDz.dxdz + matMT[1][1] * trDz.dydz + matMT[1][2]);
 
  450      dr1[2] = -(matMT[2][0] * trDz.dxdz + matMT[2][1] * trDz.dydz + matMT[2][2]);
 
  453      dr2[0] = -(matMT[0][1] * trDz.d2ydz2 + matMT[0][0] * trDz.d2xdz2);
 
  454      dr2[1] = -(matMT[1][1] * trDz.d2ydz2 + matMT[1][0] * trDz.d2xdz2);
 
  455      dr2[2] = -(matMT[2][1] * trDz.d2ydz2 + matMT[2][0] * trDz.d2xdz2);
 
  462        dr2[0] += trDz.d2xdz2;
 
  463        dr2[1] += trDz.d2ydz2;
 
  470template <
int N, 
typename... Args>
 
  474  constexpr double NInv1 = 1. - NInv;       
 
  475  for (
int i = N; 
i--;) {                   
 
  476    const auto& trDzi = mTrDer[mCurHyp][
i]; 
 
  477    auto& dr1ii = mDResidDz[
i][
i];
 
  478    auto& dr2ii = mD2ResidDz2[
i][
i];
 
  480    dr1ii[0] = NInv1 * trDzi.dxdz;
 
  481    dr1ii[1] = NInv1 * trDzi.dydz;
 
  484    dr2ii[0] = NInv1 * trDzi.d2xdz2;
 
  485    dr2ii[1] = NInv1 * trDzi.d2ydz2;
 
  488    for (
int j = 
i; 
j--;) { 
 
  489      auto& dr1ij = mDResidDz[
i][
j];
 
  490      auto& dr1ji = mDResidDz[
j][
i];
 
  491      const auto& trDzj = mTrDer[mCurHyp][
j]; 
 
  494      dr1ij[0] = -trDzj.dxdz * NInv;
 
  495      dr1ij[1] = -trDzj.dydz * NInv;
 
  496      dr1ij[2] = -1 * NInv;
 
  499      dr1ji[0] = -trDzi.dxdz * NInv;
 
  500      dr1ji[1] = -trDzi.dydz * NInv;
 
  501      dr1ji[2] = -1 * NInv;
 
  503      auto& dr2ij = mD2ResidDz2[
i][
j];
 
  504      auto& dr2ji = mD2ResidDz2[
j][
i];
 
  507      dr2ij[0] = -trDzj.d2xdz2 * NInv;
 
  508      dr2ij[1] = -trDzj.d2ydz2 * NInv;
 
  512      dr2ji[0] = -trDzi.d2xdz2 * NInv;
 
  513      dr2ji[1] = -trDzi.d2ydz2 * NInv;
 
  521template <
int N, 
typename... Args>
 
  525  std::array<std::array<Vec3D, N>, N> covIDrDz; 
 
  528  for (
int i = N; 
i--;) {
 
  529    auto& dchi1 = mDChi2Dz[
i]; 
 
  531    for (
int j = N; 
j--;) {
 
  532      const auto& 
res = mTrRes[mCurHyp][
j];    
 
  533      const auto& covI = mTrcEInv[mCurHyp][
j]; 
 
  534      const auto& dr1 = mDResidDz[
j][
i];       
 
  535      auto& cidr = covIDrDz[
i][
j];             
 
  536      cidr[0] = covI.sxx * dr1[0] + covI.sxy * dr1[1];
 
  537      cidr[1] = covI.sxy * dr1[0] + covI.syy * dr1[1];
 
  538      cidr[2] = covI.szz * dr1[2];
 
  540      dchi1 += ROOT::Math::Dot(
res, cidr);
 
  545  for (
int i = N; 
i--;) {
 
  546    for (
int j = 
i + 1; 
j--;) {       
 
  547      auto& dchi2 = mD2Chi2Dz2[
i][
j]; 
 
  549      for (
int k = N; k--;) {
 
  550        const auto& dr1j = mDResidDz[k][
j];  
 
  551        const auto& cidrkj = covIDrDz[
i][k]; 
 
  552        dchi2 += ROOT::Math::Dot(dr1j, cidrkj);
 
  554          const auto& 
res = mTrRes[mCurHyp][k];    
 
  555          const auto& covI = mTrcEInv[mCurHyp][k]; 
 
  556          const auto& dr2ij = mD2ResidDz2[k][
j];   
 
  557          dchi2 += 
res[0] * (covI.sxx * dr2ij[0] + covI.sxy * dr2ij[1]) + 
res[1] * (covI.sxy * dr2ij[0] + covI.syy * dr2ij[1]) + 
res[2] * covI.szz * dr2ij[2];
 
  565template <
int N, 
typename... Args>
 
  569  for (
int i = N; 
i--;) {
 
  570    auto& dchi1 = mDChi2Dz[
i]; 
 
  572    for (
int j = N; 
j--;) {
 
  573      const auto& 
res = mTrRes[mCurHyp][
j]; 
 
  574      const auto& dr1 = mDResidDz[
j][
i];    
 
  575      dchi1 += ROOT::Math::Dot(
res, dr1);
 
  578        auto& dchi2 = mD2Chi2Dz2[
i][
j]; 
 
  579        dchi2 = ROOT::Math::Dot(mTrRes[mCurHyp][
i], mD2ResidDz2[
i][
j]);
 
  580        for (
int k = N; k--;) {
 
  581          dchi2 += ROOT::Math::Dot(mDResidDz[k][
i], mDResidDz[k][
j]);
 
  589template <
int N, 
typename... Args>
 
  594  mPCA[mCurHyp] = mTrCFVT[mCurHyp][N - 1] * mTrPos[mCurHyp][N - 1];
 
  595  for (
int i = N - 1; 
i--;) {
 
  596    mPCA[mCurHyp] += mTrCFVT[mCurHyp][
i] * mTrPos[mCurHyp][
i];
 
  601template <
int N, 
typename... Args>
 
  605  auto& pca = mPCA[mCurHyp];
 
  607  pca[0] = mTrPos[mCurHyp][N - 1][0];
 
  608  pca[1] = mTrPos[mCurHyp][N - 1][1];
 
  609  pca[2] = mTrPos[mCurHyp][N - 1][2];
 
  611  for (
int i = N - 1; 
i--;) {
 
  612    pca[0] += mTrPos[mCurHyp][
i][0];
 
  613    pca[1] += mTrPos[mCurHyp][
i][1];
 
  614    pca[2] += mTrPos[mCurHyp][
i][2];
 
  622template <
int N, 
typename... Args>
 
  627  for (
int i = N; 
i--;) {
 
  628    covm += ROOT::Math::Similarity(mUseAbsDCA ? getTrackRotMatrix(
i) : mTrCFVT[mOrder[cand]][
i], getTrackCovMatrix(
i, cand));
 
  634template <
int N, 
typename... Args>
 
  639  for (
int i = N; 
i--;) {
 
  640    mTrRes[mCurHyp][
i] = mTrPos[mCurHyp][
i];
 
  641    vtxLoc = mPCA[mCurHyp];
 
  642    mTrRes[mCurHyp][
i] -= vtxLoc;
 
  647template <
int N, 
typename... Args>
 
  651  for (
int i = N; 
i--;) {
 
  652    mTrDer[mCurHyp][
i].set(mCandTr[mCurHyp][
i], mBz);
 
  657template <
int N, 
typename... Args>
 
  662  for (
int i = N; 
i--;) {
 
  663    const auto& 
res = mTrRes[mCurHyp][
i];
 
  664    const auto& covI = mTrcEInv[mCurHyp][
i];
 
  665    chi2 += 
res[0] * 
res[0] * covI.sxx + 
res[1] * 
res[1] * covI.syy + 
res[2] * 
res[2] * covI.szz + 2. * 
res[0] * 
res[1] * covI.sxy;
 
  671template <
int N, 
typename... Args>
 
  676  for (
int i = N; 
i--;) {
 
  677    const auto& 
res = mTrRes[mCurHyp][
i];
 
  684template <
int N, 
typename... Args>
 
  688  for (
int i = N; 
i--;) {
 
  689    const auto& trDer = mTrDer[mCurHyp][
i];
 
  690    auto dz2h = 0.5 * corrZ[
i] * corrZ[
i];
 
  691    mTrPos[mCurHyp][
i][0] -= trDer.dxdz * corrZ[
i] - dz2h * trDer.d2xdz2;
 
  692    mTrPos[mCurHyp][
i][1] -= trDer.dydz * corrZ[
i] - dz2h * trDer.d2ydz2;
 
  693    mTrPos[mCurHyp][
i][2] -= corrZ[
i];
 
  700template <
int N, 
typename... Args>
 
  704  int ord = mOrder[icand];
 
  705  if (mTrPropDone[ord]) {
 
  708  const Vec3D& pca = mPCA[ord];
 
  709  std::array<float, 6> covMatrixPCA = calcPCACovMatrixFlat(ord);
 
  710  std::array<float, 2> cov = {covMatrixPCA[0], covMatrixPCA[2]};
 
  711  for (
int i = N; 
i--;) {
 
  712    mCandTr[ord][
i] = *mOrigTrPtr[
i]; 
 
  713    auto& trc = mCandTr[ord][
i];
 
  714    const std::array<float, 3> 
p = {(float)pca[0], (
float)pca[1], (float)pca[2]};
 
  715    if (!propagateToVtx(trc, p, cov)) {
 
  720  mTrPropDone[ord] = 
true;
 
  725template <
int N, 
typename... Args>
 
  730  double startPoint = 20.; 
 
  732  double z[2] = {startPoint, startPoint};
 
  733  double newX[2], newY[2];
 
  735  double X = mPCA[mCurHyp][0]; 
 
  736  double Y = mPCA[mCurHyp][1]; 
 
  738  mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
 
  739  mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
 
  741  double dstXY[2][3] = {{999., 999., 999.}, {999., 999., 999.}};
 
  748  for (
int i = 0; 
i < 2; 
i++) {
 
  752      mCandTr[mCurHyp][
i].propagateParamToZquadratic(
z[
i], mBz);
 
  753      newX[
i] = mCandTr[mCurHyp][
i].getX();
 
  754      newY[
i] = mCandTr[mCurHyp][
i].getY();
 
  756      newDstXY = std::sqrt((newX[
i] - X) * (newX[
i] - X) +
 
  757                           (newY[
i] - Y) * (newY[
i] - Y));
 
  760      dstXY[
i][0] = dstXY[
i][1];
 
  761      dstXY[
i][1] = dstXY[
i][2];
 
  762      dstXY[
i][2] = newDstXY;
 
  764      if (dstXY[
i][2] > dstXY[
i][1] && dstXY[
i][1] < dstXY[
i][0]) {
 
  773  float rez = 0.5 * (finalZ[0] + finalZ[1]);
 
  778template <
int N, 
typename... Args>
 
  783  double startPoint = -40.;
 
  784  double endPoint = 50.;
 
  785  double midPoint = 0.5 * (startPoint + endPoint);
 
  787  double z[2][2] = {{startPoint, endPoint}, {startPoint, endPoint}}; 
 
  789  double DeltaZ = std::abs(endPoint - startPoint);
 
  794  double epsilon = 0.0001;
 
  796  double X = mPCA[mCurHyp][0]; 
 
  797  double Y = mPCA[mCurHyp][1]; 
 
  799  mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
 
  800  mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
 
  806  while (DeltaZ > epsilon) {
 
  808    midPoint = 0.5 * (startPoint + endPoint);
 
  810    for (
int i = 0; 
i < 2; 
i++) {
 
  811      mCandTr[mCurHyp][
i].propagateParamToZquadratic(startPoint, mBz);
 
  812      newX[
i][0] = mCandTr[mCurHyp][
i].getX();
 
  813      newY[
i][0] = mCandTr[mCurHyp][
i].getY();
 
  815      mCandTr[mCurHyp][
i].propagateParamToZquadratic(endPoint, mBz);
 
  816      newX[
i][1] = mCandTr[mCurHyp][
i].getX();
 
  817      newY[
i][1] = mCandTr[mCurHyp][
i].getY();
 
  820    dstXY[0] = (newX[0][0] - newX[1][0]) * (newX[0][0] - newX[1][0]) +
 
  821               (newY[0][0] - newY[1][0]) * (newY[0][0] - newY[1][0]);
 
  823    dstXY[1] = (newX[0][1] - newX[1][1]) * (newX[0][1] - newX[1][1]) +
 
  824               (newY[0][1] - newY[1][1]) * (newY[0][1] - newY[1][1]);
 
  826    DeltaZ = std::abs(endPoint - startPoint);
 
  828    if (DeltaZ < epsilon) {
 
  829      finalZ = 0.5 * (startPoint + endPoint);
 
  834    if (dstXY[1] > dstXY[0]) {
 
  837      startPoint = midPoint;
 
  841  mPCA[mCurHyp][2] = finalZ;
 
  845template <
int N, 
typename... Args>
 
  850  double startPoint = 1.;
 
  851  double endPoint = 50.; 
 
  853  double X = mPCA[mCurHyp][0]; 
 
  854  double Y = mPCA[mCurHyp][1]; 
 
  856  mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
 
  857  mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
 
  872  for (
int i = 0; 
i < 2; 
i++) {
 
  874    mCandTr[mCurHyp][
i].propagateToZquadratic(startPoint, mBz);
 
  876    z[
i][0] = startPoint;
 
  877    y[
i][0] = mCandTr[mCurHyp][
i].getY();
 
  878    x[
i][0] = mCandTr[mCurHyp][
i].getX();
 
  880    mCandTr[mCurHyp][
i].propagateToZquadratic(endPoint, mBz);
 
  883    y[
i][1] = mCandTr[mCurHyp][
i].getY();
 
  884    x[
i][1] = mCandTr[mCurHyp][
i].getX();
 
  886    bYZ[
i] = (
y[
i][1] - 
y[
i][0] * 
z[
i][1] / 
z[
i][0]) / (1 - 
z[
i][1] / 
z[
i][0]);
 
  887    aYZ[
i] = (
y[
i][0] - bYZ[
i]) / 
z[
i][0];
 
  889    bXZ[
i] = (
x[
i][1] - 
x[
i][0] * 
z[
i][1] / 
z[
i][0]) / (1 - 
z[
i][1] / 
z[
i][0]);
 
  890    aXZ[
i] = (
x[
i][0] - bXZ[
i]) / 
z[
i][0];
 
  894  finalZ = 0.5 * ((bYZ[0] - bYZ[1]) / (aYZ[1] - aYZ[0]) + (bXZ[0] - bXZ[1]) / (aXZ[1] - aXZ[0]));
 
  896  mPCA[mCurHyp][2] = finalZ;
 
  900template <
int N, 
typename... Args>
 
  903  double startPoint = 0.;
 
  904  double endPoint = 40.; 
 
  906  double X = mPCA[mCurHyp][0]; 
 
  907  double Y = mPCA[mCurHyp][1]; 
 
  909  mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
 
  910  mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
 
  922  double Ax[2], Bx[2], Cx[2];
 
  923  double Ay[2], By[2], Cy[2];
 
  925  double deltaX[2], deltaY[2];
 
  927  bool posX[2], nulX[2], negX[2];
 
  928  double z1X[2], z2X[2], z12X[2];
 
  930  bool posY[2], nulY[2], negY[2];
 
  931  double z1Y[2], z2Y[2], z12Y[2];
 
  939  for (
int i = 0; 
i < 2; 
i++) {
 
  940    mCandTr[mCurHyp][
i].propagateToZquadratic(startPoint, mBz);
 
  941    x[
i] = mCandTr[mCurHyp][
i].getX();
 
  942    y[
i] = mCandTr[mCurHyp][
i].getY();
 
  943    sinPhi0[
i] = mCandTr[mCurHyp][
i].getSnp();
 
  944    cosPhi0[
i] = std::sqrt((1. - sinPhi0[
i]) * (1. + sinPhi0[
i]));
 
  945    tanL0[
i] = mCandTr[mCurHyp][
i].getTanl();
 
  946    qpt0[
i] = mCandTr[mCurHyp][
i].getInvQPt();
 
  950    Ax[
i] = qpt0[
i] * Hz[
i] * k[
i] * sinPhi0[
i] / (2 * tanL0[
i] * tanL0[
i]);
 
  951    Bx[
i] = cosPhi0[
i] / tanL0[
i];
 
  954    Ay[
i] = -qpt0[
i] * Hz[
i] * k[
i] * cosPhi0[
i] / (2 * tanL0[
i] * tanL0[
i]);
 
  955    By[
i] = sinPhi0[
i] / tanL0[
i];
 
  958    deltaX[
i] = Bx[
i] * Bx[
i] - 4 * Ax[
i] * Cx[
i];
 
  959    deltaY[
i] = By[
i] * By[
i] - 4 * Ay[
i] * Cy[
i];
 
  963      z1X[
i] = (-Bx[
i] - std::sqrt(deltaX[
i])) / (2 * Ax[
i]);
 
  964      z2X[
i] = (-Bx[
i] + std::sqrt(deltaX[
i])) / (2 * Ax[
i]);
 
  965    } 
else if (deltaX[
i] == 0) {
 
  967      z12X[
i] = -Bx[
i] / (2 * Ax[
i]);
 
  975      z1Y[
i] = (-By[
i] - std::sqrt(deltaY[
i])) / (2 * Ay[
i]);
 
  976      z2Y[
i] = (-By[
i] + std::sqrt(deltaY[
i])) / (2 * Ay[
i]);
 
  977    } 
else if (deltaX[
i] == 0) {
 
  979      z12Y[
i] = -By[
i] / (2 * Ay[
i]);
 
  987      if (z1X[
i] < endPoint && z1X[
i] > startPoint) {
 
  995      if (z1Y[
i] < endPoint && z1Y[
i] > startPoint) {
 
 1002    finalZ[
i] = 0.5 * (z12X[
i] + z12Y[
i]);
 
 1005  mPCA[mCurHyp][2] = 0.5 * (finalZ[0] + finalZ[1]);
 
 1009template <
int N, 
typename... Args>
 
 1013  double startPoint = 0.;
 
 1015  double X = mPCA[mCurHyp][0]; 
 
 1016  double Y = mPCA[mCurHyp][1]; 
 
 1018  mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
 
 1019  mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
 
 1027  double Ax[2], Bx[2];
 
 1028  double Ay[2], By[2];
 
 1039  for (
int i = 0; 
i < 2; 
i++) {
 
 1040    mCandTr[mCurHyp][
i].propagateToZlinear(startPoint);
 
 1041    x[
i] = mCandTr[mCurHyp][
i].getX();
 
 1042    y[
i] = mCandTr[mCurHyp][
i].getY();
 
 1043    sinPhi0[
i] = mCandTr[mCurHyp][
i].getSnp();
 
 1044    cosPhi0[
i] = std::sqrt((1. - sinPhi0[
i]) * (1. + sinPhi0[
i]));
 
 1045    tanL0[
i] = mCandTr[mCurHyp][
i].getTanl();
 
 1047    Ax[
i] = cosPhi0[
i] / tanL0[
i];
 
 1050    Ay[
i] = sinPhi0[
i] / tanL0[
i];
 
 1053    z12X[
i] = -Bx[
i] / Ax[
i];
 
 1054    z12Y[
i] = -By[
i] / Ay[
i];
 
 1056    finalZ[
i] = 0.5 * (z12X[
i] + z12Y[
i]);
 
 1059  mPCA[mCurHyp][2] = 0.5 * (finalZ[0] + finalZ[1]);
 
 1063template <
int N, 
typename... Args>
 
 1067  int ord = mOrder[icand];
 
 1069  if (!mTrPropDone[ord]) {
 
 1070    auto z = mPCA[ord][2];
 
 1071    trc.propagateParamToZquadratic(
z, mBz);
 
 1078template <
int N, 
typename... Args>
 
 1082  for (
int i = N; 
i--;) {
 
 1083    auto vai = std::abs(
v[
i]);
 
 1092template <
int N, 
typename... Args>
 
 1100  for (
int i = N; 
i--;) {
 
 1101    mCandTr[mCurHyp][
i] = *mOrigTrPtr[
i];
 
 1102    auto z = mPCA[mCurHyp][2];
 
 1104    mCandTr[mCurHyp][
i].propagateToZquadratic(
z, mBz);
 
 1106    x[
i] = mCandTr[mCurHyp][
i].getX();
 
 1107    y[
i] = mCandTr[mCurHyp][
i].getY();
 
 1109    setTrackPos(mTrPos[mCurHyp][
i], mCandTr[mCurHyp][
i]);      
 
 1110    mTrcEInv[mCurHyp][
i].set(mCandTr[mCurHyp][
i], ZerrFactor); 
 
 1116  mPCA[mCurHyp][0] = sumX / N;
 
 1117  mPCA[mCurHyp][1] = sumY / N;
 
 1119  if (mMaxDXIni > 0 && !roughDXCut()) { 
 
 1123  if (!FwdcalcPCACoefs()) { 
 
 1127  FwdcalcTrackResiduals(); 
 
 1128  float chi2Upd, chi2 = FwdcalcChi2();
 
 1130    calcTrackDerivatives();    
 
 1131    FwdcalcResidDerivatives(); 
 
 1132    FwdcalcChi2Derivatives();  
 
 1135    if (!mD2Chi2Dz2.Invert()) {
 
 1139    VecND dz = mD2Chi2Dz2 * mDChi2Dz;
 
 1141    if (!FwdcorrectTracks(dz)) { 
 
 1146    if (mCrossIDAlt >= 0 && closerToAlternative()) {
 
 1147      mAllowAltPreference = 
false;
 
 1151    FwdcalcTrackResiduals(); 
 
 1152    chi2Upd = FwdcalcChi2(); 
 
 1154    if (getAbsMax(dz) < mMinParamChange || chi2Upd > chi2 * mMinRelChi2Change) {
 
 1160  } 
while (++mNIters[mCurHyp] < mMaxIter);
 
 1162  mChi2[mCurHyp] = chi2 * NInv;
 
 1163  return mChi2[mCurHyp] < mMaxChi2;
 
 1167template <
int N, 
typename... Args>
 
 1175  for (
int i = N; 
i--;) {
 
 1177    mCandTr[mCurHyp][
i] = *mOrigTrPtr[
i];
 
 1179    auto z = mPCA[mCurHyp][2];
 
 1180    mCandTr[mCurHyp][
i].propagateParamToZquadratic(
z, mBz);
 
 1182    x[
i] = mCandTr[mCurHyp][
i].getX();
 
 1183    y[
i] = mCandTr[mCurHyp][
i].getY();
 
 1185    mPCA[mCurHyp][2] = 
z;
 
 1187    setTrackPos(mTrPos[mCurHyp][
i], mCandTr[mCurHyp][
i]); 
 
 1193  mPCA[mCurHyp][0] = sumX / N;
 
 1194  mPCA[mCurHyp][1] = sumY / N;
 
 1196  if (mMaxDXIni > 0 && !roughDXCut()) { 
 
 1201  FwdcalcTrackResiduals(); 
 
 1202  float chi2Upd, chi2 = FwdcalcChi2NoErr();
 
 1204    calcTrackDerivatives();         
 
 1205    FwdcalcResidDerivativesNoErr(); 
 
 1206    FwdcalcChi2DerivativesNoErr();  
 
 1209    if (!mD2Chi2Dz2.Invert()) {
 
 1212    VecND dz = mD2Chi2Dz2 * mDChi2Dz;
 
 1214    if (!FwdcorrectTracks(dz)) {
 
 1218    if (mCrossIDAlt >= 0 && closerToAlternative()) {
 
 1219      mAllowAltPreference = 
false;
 
 1222    FwdcalcTrackResiduals();      
 
 1223    chi2Upd = FwdcalcChi2NoErr(); 
 
 1224    if (getAbsMax(dz) < mMinParamChange || chi2Upd > chi2 * mMinRelChi2Change) {
 
 1229  } 
while (++mNIters[mCurHyp] < mMaxIter);
 
 1231  mChi2[mCurHyp] = chi2 * NInv;
 
 1232  return mChi2[mCurHyp] < mMaxChi2;
 
 1236template <
int N, 
typename... Args>
 
 1242  for (
int i = N; accept && 
i--;) {
 
 1243    for (
int j = 
i; 
j--;) {
 
 1244      if (std::abs(mCandTr[mCurHyp][
i].
getX() - mCandTr[mCurHyp][
j].
getX()) > mMaxDXIni) {
 
 1254template <
int N, 
typename... Args>
 
 1258  auto dxCur = mPCA[mCurHyp][0] - mCrossings.xDCA[mCrossIDCur], dyCur = mPCA[mCurHyp][1] - mCrossings.yDCA[mCrossIDCur];
 
 1259  auto dxAlt = mPCA[mCurHyp][0] - mCrossings.xDCA[mCrossIDAlt], dyAlt = mPCA[mCurHyp][1] - mCrossings.yDCA[mCrossIDAlt];
 
 1260  return dxCur * dxCur + dyCur * dyCur > dxAlt * dxAlt + dyAlt * dyAlt;
 
 1264template <
int N, 
typename... Args>
 
 1267  LOG(info) << N << 
"-prong vertex fitter in " << (mUseAbsDCA ? 
"abs." : 
"weighted") << 
" distance minimization mode";
 
 1268  LOG(info) << 
"Bz: " << mBz << 
" MaxIter: " << mMaxIter << 
" MaxChi2: " << mMaxChi2;
 
 1269  LOG(info) << 
"Stopping condition: Max.param change < " << mMinParamChange << 
" Rel.Chi2 change > " << mMinRelChi2Change;
 
 1270  LOG(info) << 
"Discard candidates for : Rvtx > " << getMaxR() << 
" DZ between tracks > " << mMaxDXIni;
 
 1273template <
int N, 
typename... Args>
 
 1278  if (mUseMatBudget) {
 
 1279    auto mb = mMatLUT->getMatBudget(t.
getX(), t.
getY(), t.
getZ(), p[0], p[1], p[2]);
 
 1280    x2x0 = (float)mb.meanX2X0;
 
 1282  } 
else if (mTGeoFallBackAllowed) {
 
 1284    x2x0 = (float)geoMan.meanX2X0;
 
 1292using FwdDCAFitter2 = FwdDCAFitterN<2, o2::track::TrackParCovFwd>;
 
 1293using FwdDCAFitter3 = FwdDCAFitterN<3, o2::track::TrackParCovFwd>;