From 4fc0c84a483920cf30e2f5430ff1ef94f44f8edb Mon Sep 17 00:00:00 2001
From: "s.zharko@gsi.de" <s.zharko@gsi.de>
Date: Wed, 3 Aug 2022 20:51:33 +0200
Subject: [PATCH] L1: implemented move constructor and assignment operator for
 L1Vector

---
 reco/L1/CbmL1Performance.cxx |   6 +-
 reco/L1/CbmL1ReadEvent.cxx   |   2 -
 reco/L1/L1Algo/L1Algo.h      | 547 +++++++++++++++++++----------------
 reco/L1/L1Algo/L1Timer.h     |  59 ++--
 reco/L1/L1Algo/L1Triplet.h   |  39 +--
 reco/L1/L1Algo/L1Utils.h     |   8 +-
 reco/L1/L1Algo/L1Vector.h    |  34 ++-
 7 files changed, 389 insertions(+), 306 deletions(-)

diff --git a/reco/L1/CbmL1Performance.cxx b/reco/L1/CbmL1Performance.cxx
index 0cb1ac9106..820efc06a5 100644
--- a/reco/L1/CbmL1Performance.cxx
+++ b/reco/L1/CbmL1Performance.cxx
@@ -2212,12 +2212,12 @@ void CbmL1::InputPerformance()
 
       if (hm->GetNofLinks() == 0) continue;
       Float_t bestWeight  = 0.f;
-      Float_t totalWeight = 0.f;
+      //Float_t totalWeight = 0.f;
       int iMCPoint        = -1;
       CbmLink link;
 
       for (int iLink = 0; iLink < hm->GetNofLinks(); iLink++) {
-        totalWeight += hm->GetLink(iLink).GetWeight();
+        //totalWeight += hm->GetLink(iLink).GetWeight();
         if (hm->GetLink(iLink).GetWeight() > bestWeight) {
           bestWeight = hm->GetLink(iLink).GetWeight();
           iMCPoint   = hm->GetLink(iLink).GetIndex();
@@ -2225,8 +2225,8 @@ void CbmL1::InputPerformance()
         }
       }
 
+      // TODO: Unify the cut and the whole code block for different detectors (S.Zharko)
       // if (bestWeight / totalWeight < 0.7 || iMCPoint < 0) continue;
-
       if (iMCPoint < 0) continue;
 
       CbmTofPoint* pt = (CbmTofPoint*) fpTofPoints->Get(link.GetFile(), link.GetEntry(), link.GetIndex());
diff --git a/reco/L1/CbmL1ReadEvent.cxx b/reco/L1/CbmL1ReadEvent.cxx
index fc6a9c5b83..b9d8f9a575 100644
--- a/reco/L1/CbmL1ReadEvent.cxx
+++ b/reco/L1/CbmL1ReadEvent.cxx
@@ -1522,7 +1522,6 @@ void CbmL1::HitMatch()
         }
 
         Float_t bestWeight  = 0.f;
-        Float_t totalWeight = 0.f;
         for (Int_t iLink = 0; iLink < stsHitMatch.GetNofLinks(); iLink++) {
           const CbmLink& link = stsHitMatch.GetLink(iLink);
           Int_t iFile         = link.GetFile();
@@ -1541,7 +1540,6 @@ void CbmL1::HitMatch()
 
           assert(pnt_it != dFEI2vMCPoints.end());
 
-          totalWeight += link.GetWeight();
           if (link.GetWeight() > bestWeight) {
             bestWeight = link.GetWeight();
             iP         = pnt_it->second;
diff --git a/reco/L1/L1Algo/L1Algo.h b/reco/L1/L1Algo/L1Algo.h
index 120b17348d..4cd34ad21a 100644
--- a/reco/L1/L1Algo/L1Algo.h
+++ b/reco/L1/L1Algo/L1Algo.h
@@ -64,9 +64,14 @@ class L1AlgoDraw;
 #include "omp.h"
 #endif
 
-using std::map;
+// *******************************
+// ** Types definition (global) **
+// *******************************
+
+using L1StationsArray_t = std::array<L1Station, L1Constants::size::kMaxNstations>;
+using L1MaterialArray_t = std::array<L1Material, L1Constants::size::kMaxNstations>;
+using Tindex            = int;  // TODO: Replace with L1HitIndex_t, if suitable
 
-typedef int Tindex;
 #ifdef PULLS
 #define TRIP_PERFORMANCE
 class L1AlgoPulls;
@@ -80,68 +85,68 @@ template<Tindex NHits>
 class L1AlgoEfficiencyPerformance;
 #endif
 
-using L1StationsArray_t = std::array<L1Station, L1Constants::size::kMaxNstations>;
-using L1MaterialArray_t = std::array<L1Material, L1Constants::size::kMaxNstations>;
 
 /// Main class of L1 CA track finder algorithm
 ///
 class L1Algo {
 public:
+  // *************************
+  // ** Friend classes list **
+  // *************************
+
+  friend class CbmL1;  /// TODO: Remove this dependency
+  friend class ParalleledDup;
+  friend class ParalleledTrip;
+#ifdef DRAW
+  friend class L1AlgoDraw;
+#endif
+
+  // **********************************
+  // ** Member functions declaration **
+  // **********************************
+
+  // ** Constructors and destructor
+
+  /// Constructor
+  /// \param nThreads  Number of threads for multi-threaded mode
   L1Algo(unsigned int nThreads = 1);
 
+  /// Copy constructor
   L1Algo(const L1Algo&) = delete;
-  L1Algo operator=(const L1Algo&) = delete;
 
-  /// Sets a default particle mass for the track fit
-  /// it is used during reconstruction
-  /// for the multiple scattering and energy loss estimation
-  /// \param mass Default particle mass
-  void SetDefaultParticleMass(float mass) { fDefaultMass = mass; }
+  /// Move constructor
+  L1Algo(L1Algo&&) = delete;
 
-  /// Gets default particle mass
-  /// \return particle mass
-  float GetDefaultParticleMass() const { return fDefaultMass; }
+  /// Copy assignment operator
+  L1Algo& operator=(const L1Algo&) = delete;
 
-  /// Gets default particle mass squared
-  /// \return particle mass squared
-  float GetDefaultParticleMass2() const { return fDefaultMass * fDefaultMass; }
+  /// Move assignment operator
+  L1Algo& operator=(L1Algo&&) = delete;
 
+  /// Destructor
+  ~L1Algo() = default;
 
-  /// pack station, thread and triplet indices to an unique triplet ID
-  static unsigned int PackTripletId(unsigned int Station, unsigned int Thread, unsigned int Triplet)
-  {
-    //SG!!#ifndef FAST_CODE
-    assert(Station < L1Constants::size::kMaxNstations);
-    assert(Thread < L1Constants::size::kMaxNthreads);
-    assert(Triplet < L1Constants::size::kMaxNtriplets);
-    //#endif
-    constexpr unsigned int kMoveThread  = L1Constants::size::kTripletBits;
-    constexpr unsigned int kMoveStation = L1Constants::size::kTripletBits + L1Constants::size::kThreadBits;
-    return (Station << kMoveStation) + (Thread << kMoveThread) + Triplet;
-  }
 
-  /// unpack the triplet ID to its station index
-  static unsigned int TripletId2Station(unsigned int ID)
-  {
-    constexpr unsigned int kMoveStation = L1Constants::size::kTripletBits + L1Constants::size::kThreadBits;
-    return ID >> kMoveStation;
-  }
+  // ** Functions, which pack and unpack indexes of station, thread and triplet **
 
-  /// unpack the triplet ID to its thread index
-  static unsigned int TripletId2Thread(unsigned int ID)
-  {
-    constexpr unsigned int kMoveThread = L1Constants::size::kTripletBits;
-    constexpr unsigned int kThreadMask = (1u << L1Constants::size::kThreadBits) - 1u;
-    return (ID >> kMoveThread) & kThreadMask;
-  }
+  // TODO: move to L1Triplet class (S.Zharko)
+  /// Packs station, thread and triplet indices to an unique triplet ID
+  /// \param  iStation  Index of station in the active stations array
+  /// \param  iThread   Index of thread processing triplet
+  /// \param  iTriplet  Index of triplet
+  static unsigned int PackTripletId(unsigned int iStation, unsigned int iThread, unsigned int iTriplet);
 
-  /// unpack the triplet ID to its triplet index
-  static unsigned int TripletId2Triplet(unsigned int ID)
-  {
-    constexpr unsigned int kTripletMask = (1u << L1Constants::size::kTripletBits) - 1u;
-    return ID & kTripletMask;
-  }
+  /// Unpacks the triplet ID to its station index
+  /// \param  id  Unique triplet ID
+  static unsigned int TripletId2Station(unsigned int id);
+
+  /// Unpacks the triplet ID to its thread index
+  /// \param  id  Unique triplet ID
+  static unsigned int TripletId2Thread(unsigned int id);
 
+  /// Unpacks the triplet ID to its triplet index
+  /// \param  id  Unique triplet ID
+  static unsigned int TripletId2Triplet(unsigned int id);
 
   /// pack thread and track indices to an unique track ID
   static int PackTrackId(int Thread, int Track)
@@ -155,169 +160,16 @@ public:
   /// unpack the track ID to its track index
   static int TrackId2Track(int ID) { return TripletId2Triplet((unsigned int) ID); }
 
+  /// Sets L1Algo parameters object
+  /// \param other - reference to the L1Parameters object
+  void SetParameters(const L1Parameters& other) { fParameters = other; }
+  // TODO: remove it (S.Zharko)
 
-  L1Vector<L1Triplet> fTriplets[L1Constants::size::kMaxNstations][L1Constants::size::kMaxNthreads] {
-    {"L1Algo::fTriplets"}};  // created triplets at station + thread
-
-  // Track candidates created out of adjacent triplets before the final track selection.
-  // The candidates may share any amount of hits.
-  L1Vector<L1Branch> fTrackCandidates[L1Constants::size::kMaxNthreads] {"L1Algo::fTrackCandidates"};
-
-  Tindex fDupletPortionStopIndex[L1Constants::size::kMaxNstations] {0};  // end of the duplet portions for the station
-  L1Vector<Tindex> fDupletPortionSize {"L1Algo::fDupletPortionSize"};    // N duplets in a portion
-
-#ifdef DRAW
-  L1AlgoDraw* draw {nullptr};
-  void DrawRecoTracksTime(const L1Vector<CbmL1Track>& tracks);
-#endif
-
-  enum TrackingMode
-  {
-    kSts,
-    kGlobal,
-    kMcbm
-  };
-
-  void Init(const bool UseHitErrors, const TrackingMode mode, const bool MissingHits);
-
-  void SetData(L1Vector<L1Hit>& Hits_, int nStrips_, L1Vector<unsigned char>& SFlag_,
-               const L1HitIndex_t* HitsStartIndex_, const L1HitIndex_t* HitsStopIndex_);
-
-  void PrintHits();
-
-  /// The main procedure - find tracks.
-  void CATrackFinder();
-
-  /// Track fitting procedures
-  void KFTrackFitter_simple();  // version, which use procedured used during the reconstruction
-  void L1KFTrackFitter();       // version from SIMD-KF benchmark
-
-  void L1KFTrackFitterMuch();
-
-  float GetMaxInvMom() const { return fMaxInvMom[0]; }
-
-  /// ----- Input data -----
-  // filled in CbmL1::ReadEvent();
-
-  void SetNThreads(unsigned int n);
-
-private:
-  int fNstations {0};            ///< number of all detector stations
-  int fNstationsBeforePipe {0};  ///< number of stations before pipe (MVD stations in CBM)
-  int fNfieldStations {0};       ///< number of stations in the field region
-  //alignas(16) L1StationsArray_t fStations {};  ///< array of L1Station objects
-  //alignas(16) L1MaterialArray_t fRadThick {};  ///< material for each station
-  float fDefaultMass {L1Constants::phys::kMuonMass};  ///< mass of the propagated particle [GeV/c2]
-
-public:
-  /// Gets total number of stations used in tracking
-  int GetNstations() const { return fNstations; }
-
-  /// Gets number of stations before the pipe (MVD stations in CBM)
-  int GetNstationsBeforePipe() const { return fNstationsBeforePipe; }
-
-  /// Gets number of stations situated in field region (MVD + STS in CBM)
-  int GetNfieldStations() const { return fNfieldStations; }
-
-  /// Get mc track ID for a hit (debug tool)
-  int GetMcTrackIdForHit(int iHit);
-
-  /// Get mc track ID for a hit (debug tool)
-  int GetMcTrackIdForUnusedHit(int iHit);
-
-public:
-  int fNstrips {0};                                ///< number of strips
-  L1Vector<L1Hit>* vHits {nullptr};                ///< hits as a combination of front and back strips and z-position
-  L1Grid vGrid[L1Constants::size::kMaxNstations];  ///<
-  L1Grid vGridTime[L1Constants::size::kMaxNstations];  ///<
-
-  L1Vector<unsigned char>* fStripFlag {nullptr};  // information of hits station & using hits in tracks;
-
-  double fCATime {0.};  // time of track finding
-
-  L1Vector<L1Track> fTracks {"L1Algo::fTracks"};           ///< reconstructed tracks
-  L1Vector<L1HitIndex_t> fRecoHits {"L1Algo::fRecoHits"};  ///< packed hits of reconstructed tracks
-
-  const L1HitIndex_t* HitsStartIndex {nullptr};  ///< station-bounders in vHits array
-  const L1HitIndex_t* HitsStopIndex {nullptr};   ///< station-bounders in vHits array
-
-
-  //  L1Branch* pointer;
-  unsigned int NHitsIsecAll {0};
-
-  L1Vector<L1Hit> vNotUsedHits_A {"L1Algo::vNotUsedHits_A"};
-  L1Vector<L1Hit> vNotUsedHits_B {"L1Algo::vNotUsedHits_B"};
-  L1Vector<L1Hit> vNotUsedHits_Buf {"L1Algo::vNotUsedHits_Buf"};
-  L1Vector<L1HitPoint> vNotUsedHitsxy_A {"L1Algo::vNotUsedHitsxy_A"};
-  L1Vector<L1HitPoint> vNotUsedHitsxy_buf {"L1Algo::vNotUsedHitsxy_buf"};
-  L1Vector<L1HitPoint> vNotUsedHitsxy_B {"L1Algo::vNotUsedHitsxy_B"};
-  L1Vector<L1Track> fTracks_local[L1Constants::size::kMaxNthreads] {"L1Algo::fTracks_local"};
-  L1Vector<L1HitIndex_t> fRecoHits_local[L1Constants::size::kMaxNthreads] {"L1Algo::fRecoHits_local"};
-
-  L1Vector<L1HitIndex_t> RealIHit_v {"L1Algo::RealIHit_v"};
-  L1Vector<L1HitIndex_t> RealIHit_v_buf {"L1Algo::RealIHit_v_buf"};
-  L1Vector<L1HitIndex_t> RealIHit_v_buf2 {"L1Algo::RealIHit_v_buf2"};
-
-#ifdef _OPENMP
-  L1Vector<omp_lock_t> fStripToTrackLock {"L1Algo::fStripToTrackLock"};
-#endif
-
-  L1Vector<int> fStripToTrack {"L1Algo::fStripToTrack"};  // strip to track pointers
-
-  int fNThreads {0};
-  bool fUseHitErrors {true};
-  bool fMissingHits {0};  ///< TODO ???
-  TrackingMode fTrackingMode {kSts};
-
-  fvec EventTime[L1Constants::size::kMaxNthreads][L1Constants::size::kMaxNthreads] {{0}};
-  fvec Err[L1Constants::size::kMaxNthreads][L1Constants::size::kMaxNthreads] {{0}};
-
-  /// --- data used during finding iterations
-  int isec {0};                                       // iteration TODO: to be dispatched (S.Zharko, 21.06.2022)
-  const L1CAIteration* fpCurrentIteration = nullptr;  ///< pointer to the current CA track finder iteration
-
-  L1Vector<L1Hit>* vHitsUnused           = nullptr;
-  L1Vector<L1HitIndex_t>* RealIHitP      = nullptr;
-  L1Vector<L1HitIndex_t>* RealIHitPBuf   = nullptr;
-  L1Vector<L1HitPoint>* vHitPointsUnused = nullptr;
-  L1HitIndex_t* RealIHit                 = nullptr;  // index in vHits indexed by index in vHitsUnused
-
-  L1HitIndex_t HitsUnusedStartIndex[L1Constants::size::kMaxNstations + 1] {0};
-  L1HitIndex_t HitsUnusedStopIndex[L1Constants::size::kMaxNstations + 1] {0};
-  L1HitIndex_t HitsUnusedStartIndexEnd[L1Constants::size::kMaxNstations + 1] {0};
-  L1HitIndex_t HitsUnusedStopIndexEnd[L1Constants::size::kMaxNstations + 1] {0};
-
-
-  L1Vector<int> fHitFirstTriplet {"L1Algo::fHitFirstTriplet"};  /// link hit -> first triplet { hit, *, *}
-  L1Vector<int> fHitNtriplets {"L1Algo::fHitNtriplets"};        /// link hit ->n triplets { hit, *, *}
-
-
-  //  fvec u_front[Portion/fvecLen], u_back[Portion/fvecLen];
-  //  fvec zPos[Portion/fvecLen];
-  //  fvec fHitTime[Portion/fvecLen];
-
-  nsL1::vector<L1TrackPar>::TSimd fT_3[L1Constants::size::kMaxNthreads];
-
-  L1Vector<L1HitIndex_t> fhitsl_3[L1Constants::size::kMaxNthreads] {"L1Algo::fhitsl_3"};
-  L1Vector<L1HitIndex_t> fhitsm_3[L1Constants::size::kMaxNthreads] {"L1Algo::fhitsm_3"};
-  L1Vector<L1HitIndex_t> fhitsr_3[L1Constants::size::kMaxNthreads] {"L1Algo::fhitsr_3"};
-
-  nsL1::vector<fvec>::TSimd fu_front3[L1Constants::size::kMaxNthreads];
-  nsL1::vector<fvec>::TSimd fu_back3[L1Constants::size::kMaxNthreads];
-  nsL1::vector<fvec>::TSimd fz_pos3[L1Constants::size::kMaxNthreads];
-  nsL1::vector<fvec>::TSimd fTimeR[L1Constants::size::kMaxNthreads];
-  nsL1::vector<fvec>::TSimd fTimeER[L1Constants::size::kMaxNthreads];
-  nsL1::vector<fvec>::TSimd dx[L1Constants::size::kMaxNthreads];
-  nsL1::vector<fvec>::TSimd dy[L1Constants::size::kMaxNthreads];
-  nsL1::vector<fvec>::TSimd du[L1Constants::size::kMaxNthreads];
-  nsL1::vector<fvec>::TSimd dv[L1Constants::size::kMaxNthreads];
-
-
-  //   Tindex NHits_l[L1Constants::size::kMaxNstations];
-  //   Tindex NHits_l_P[L1Constants::size::kMaxNstations];
-  /// ----- Output data -----
+  /// Gets a pointer to the L1Algo parameters object
+  const L1Parameters* GetParameters() const { return &fParameters; }
 
-  friend class CbmL1;
+  /// Gets a pointer to the L1Algo initialization object
+  L1InitManager* GetInitManager() { return &fInitManager; }
 
   /// ----- Hit-point-strips conversion routines ------
 
@@ -333,26 +185,25 @@ public:
 
   inline int UnPackIndex(const int& i, int& a, int& b, int& c);
   /// -- Flags routines --
-  inline __attribute__((always_inline)) static unsigned char GetFStation(unsigned char flag) { return flag / 4; }
-  inline __attribute__((always_inline)) static bool GetFUsed(unsigned char flag) { return (flag & 0x02) != 0; }
+  [[gnu::always_inline]] static unsigned char GetFStation(unsigned char flag) { return flag / 4; }
+  [[gnu::always_inline]] static bool GetFUsed(unsigned char flag) { return (flag & 0x02) != 0; }
   //   bool GetFUsedD  ( unsigned char flag ){ return (flag&0x01)!=0; }
 
 
-  /// Sets L1Algo parameters object
-  /// \param other - reference to the L1Parameters object
-  void SetParameters(const L1Parameters& other) { fParameters = other; }
-  // TODO: remove it (S.Zharko)
+  /// \brief Sets a default particle mass for the track fit
+  /// It is used during reconstruction
+  /// for the multiple scattering and energy loss estimation
+  /// \param mass Default particle mass
+  void SetDefaultParticleMass(float mass) { fDefaultMass = mass; }
 
-  /// Gets a pointer to the L1Algo parameters object
-  const L1Parameters* GetParameters() const { return &fParameters; }
+  /// Gets default particle mass
+  /// \return particle mass
+  float GetDefaultParticleMass() const { return fDefaultMass; }
 
-  /// Gets a pointer to the L1Algo initialization object
-  L1InitManager* GetInitManager() { return &fInitManager; }
+  /// Gets default particle mass squared
+  /// \return particle mass squared
+  float GetDefaultParticleMass2() const { return fDefaultMass * fDefaultMass; }
 
-private:
-  L1Parameters fParameters {};           ///< Object of L1Algo parameters class
-  L1InitManager fInitManager {};         ///< Object of L1Algo initialization manager class
-  L1ClonesMerger fClonesMerger {*this};  ///< Object of L1Algo clones merger algorithm
 
   /*********************************************************************************************/ /**
    *                             ------  FUNCTIONAL PART ------
@@ -394,34 +245,36 @@ private:
   /// \return chi2
   fscal BranchExtender(L1Branch& t);
 
-  inline __attribute__((always_inline)) void PackLocation(unsigned int& location, unsigned int& triplet,
-                                                          unsigned int iStation, unsigned int& thread)
+  [[gnu::always_inline]] void PackLocation(unsigned int& location, unsigned int& triplet, unsigned int iStation,
+                                           unsigned int& thread)
   {
     location = (triplet << 11) | (thread << 3) | iStation;
   }
 
-  inline __attribute__((always_inline)) void UnPackStation(unsigned int& location, unsigned int& iStation)
+  [[gnu::always_inline]] void UnPackStation(unsigned int& location, unsigned int& iStation)
   {
     iStation = location & 0x7;
   }
 
-  inline __attribute__((always_inline)) void UnPackThread(unsigned int& location, unsigned int& thread)
+  [[gnu::always_inline]] void UnPackThread(unsigned int& location, unsigned int& thread)
   {
     thread = (location >> 3) & 0xFF;
   }
 
-  inline __attribute__((always_inline)) void UnPackTriplet(unsigned int& location, unsigned int& triplet)
+  [[gnu::always_inline]] void UnPackTriplet(unsigned int& location, unsigned int& triplet)
   {
     triplet = (location >> 11);
   }
 
-  inline __attribute__((always_inline)) void SetFStation(unsigned char& flag, unsigned int iStation)
+  [[gnu::always_inline]] void SetFStation(unsigned char& flag, unsigned int iStation)
   {
     flag = iStation * 4 + (flag % 4);
   }
-  inline __attribute__((always_inline)) void SetFUsed(unsigned char& flag) { flag |= 0x02; }
+
+  [[gnu::always_inline]] void SetFUsed(unsigned char& flag) { flag |= 0x02; }
   //   void SetFUsedD   ( unsigned char &flag ){ flag |= 0x01; }
-  inline __attribute__((always_inline)) void SetFUnUsed(unsigned char& flag) { flag &= 0xFC; }
+
+  [[gnu::always_inline]] void SetFUnUsed(unsigned char& flag) { flag &= 0xFC; }
   //   void SetFUnUsedD ( unsigned char &flag ){ flag &= 0xFE; }
 
   /// Prepare the portion of left hits data
@@ -443,10 +296,8 @@ private:
   void findDoubletsStep0(  // input
     Tindex n1, const L1Station& stal, const L1Station& stam, L1HitPoint* vHits_m, L1TrackPar* T_1,
     L1HitIndex_t* hitsl_1,
-
     // output
     Tindex& n2, L1Vector<L1HitIndex_t>& i1_2,
-
 #ifdef DOUB_PERFORMANCE
     L1Vector<L1HitIndex_t>& hitsl_2,
 #endif  // DOUB_PERFORMANCE
@@ -517,14 +368,9 @@ private:
   void TripletsStaPort(  // input
     int istal, int istam, int istar, Tindex& nstaltriplets, L1TrackPar* T_1, L1FieldRegion* fld_1,
     L1HitIndex_t* hitsl_1,
-
     Tindex& n_2, L1Vector<L1HitIndex_t>& i1_2, L1Vector<L1HitIndex_t>& hitsm_2,
-
     const L1Vector<char>& mrDuplets
-
     // output
-
-
   );
 
 
@@ -543,6 +389,181 @@ private:
   void FilterFirstL(L1TrackParFit& track, fvec& x, fvec& y, fvec& t, fvec& t_er, L1Station& st, fvec& dx, fvec& dy,
                     fvec& dxy);
 
+
+#ifdef DRAW
+  L1AlgoDraw* draw {nullptr};
+  void DrawRecoTracksTime(const L1Vector<CbmL1Track>& tracks);
+#endif
+
+  enum TrackingMode
+  {
+    kSts,
+    kGlobal,
+    kMcbm
+  };
+
+  void Init(const bool UseHitErrors, const TrackingMode mode, const bool MissingHits);
+
+  void SetData(L1Vector<L1Hit>& Hits_, int nStrips_, L1Vector<unsigned char>& SFlag_,
+               const L1HitIndex_t* HitsStartIndex_, const L1HitIndex_t* HitsStopIndex_);
+
+  void PrintHits();
+
+  /// The main procedure - find tracks.
+  void CATrackFinder();
+
+  /// Track fitting procedures
+  void KFTrackFitter_simple();  // version, which use procedured used during the reconstruction
+  void L1KFTrackFitter();       // version from SIMD-KF benchmark
+
+  void L1KFTrackFitterMuch();
+
+  float GetMaxInvMom() const { return fMaxInvMom[0]; }
+
+  void SetNThreads(unsigned int n);
+
+public:
+  /// Gets total number of stations used in tracking
+  int GetNstations() const { return fNstations; }
+
+  /// Gets number of stations before the pipe (MVD stations in CBM)
+  int GetNstationsBeforePipe() const { return fNstationsBeforePipe; }
+
+  /// Gets number of stations situated in field region (MVD + STS in CBM)
+  int GetNfieldStations() const { return fNfieldStations; }
+
+  /// Get mc track ID for a hit (debug tool)
+  int GetMcTrackIdForHit(int iHit);
+
+  /// Get mc track ID for a hit (debug tool)
+  int GetMcTrackIdForUnusedHit(int iHit);
+
+private:
+  int fNstations {0};            ///< number of all detector stations
+  int fNstationsBeforePipe {0};  ///< number of stations before pipe (MVD stations in CBM)
+  int fNfieldStations {0};       ///< number of stations in the field region
+  //alignas(16) L1StationsArray_t fStations {};  ///< array of L1Station objects
+  //alignas(16) L1MaterialArray_t fRadThick {};  ///< material for each station
+  float fDefaultMass {L1Constants::phys::kMuonMass};  ///< mass of the propagated particle [GeV/c2]
+
+
+  // ***************************
+  // ** Member variables list **
+  // ***************************
+
+  L1Vector<unsigned char> fvHitKeyFlags {
+    "L1Algo::fvHitKeyFlags"};  ///< List of key flags: has been this hit or cluster already used
+
+public:
+  int fNstrips {0};                                    ///< number of strips
+  L1Vector<L1Hit>* vHits {nullptr};                    ///< hits as a combination of front-, backstrips and z-position
+  L1Grid vGrid[L1Constants::size::kMaxNstations];      ///<
+  L1Grid vGridTime[L1Constants::size::kMaxNstations];  ///<
+
+  L1Vector<unsigned char>* fStripFlag {nullptr};  // information of hits station & using hits in tracks;
+
+  double fCATime {0.};  // time of track finding
+
+  L1Vector<L1Track> fTracks {"L1Algo::fTracks"};           ///< reconstructed tracks
+  L1Vector<L1HitIndex_t> fRecoHits {"L1Algo::fRecoHits"};  ///< packed hits of reconstructed tracks
+
+  const L1HitIndex_t* HitsStartIndex {nullptr};  // station-bounders in vHits array
+  const L1HitIndex_t* HitsStopIndex {nullptr};   // station-bounders in vHits array
+
+
+  /// Created triplets vs station and thread index
+  L1Vector<L1Triplet> fTriplets[L1Constants::size::kMaxNstations][L1Constants::size::kMaxNthreads] {
+    {"L1Algo::fTriplets"}};
+
+  /// Track candidates created out of adjacent triplets before the final track selection.
+  /// The candidates may share any amount of hits.
+  L1Vector<L1Branch> fTrackCandidates[L1Constants::size::kMaxNthreads] {"L1Algo::fTrackCandidates"};
+
+  Tindex fDupletPortionStopIndex[L1Constants::size::kMaxNstations] {0};  ///< end of the duplet portions for the station
+  L1Vector<Tindex> fDupletPortionSize {"L1Algo::fDupletPortionSize"};    ///< Number of duplets in a portion
+
+
+  //  L1Branch* pointer;
+  unsigned int NHitsIsecAll {0};
+  
+  L1Vector<L1Hit> vNotUsedHits_A {"L1Algo::vNotUsedHits_A"};
+  L1Vector<L1Hit> vNotUsedHits_B {"L1Algo::vNotUsedHits_B"};
+  L1Vector<L1Hit> vNotUsedHits_Buf {"L1Algo::vNotUsedHits_Buf"};
+  L1Vector<L1HitPoint> vNotUsedHitsxy_A {"L1Algo::vNotUsedHitsxy_A"};
+  L1Vector<L1HitPoint> vNotUsedHitsxy_buf {"L1Algo::vNotUsedHitsxy_buf"};
+  L1Vector<L1HitPoint> vNotUsedHitsxy_B {"L1Algo::vNotUsedHitsxy_B"};
+  L1Vector<L1Track> fTracks_local[L1Constants::size::kMaxNthreads] {"L1Algo::fTracks_local"};
+  L1Vector<L1HitIndex_t> fRecoHits_local[L1Constants::size::kMaxNthreads] {"L1Algo::fRecoHits_local"};
+
+  L1Vector<L1HitIndex_t> RealIHit_v {"L1Algo::RealIHit_v"};
+  L1Vector<L1HitIndex_t> RealIHit_v_buf {"L1Algo::RealIHit_v_buf"};
+  L1Vector<L1HitIndex_t> RealIHit_v_buf2 {"L1Algo::RealIHit_v_buf2"};
+
+#ifdef _OPENMP
+  L1Vector<omp_lock_t> fStripToTrackLock {"L1Algo::fStripToTrackLock"};
+#endif
+
+  L1Vector<int> fStripToTrack {"L1Algo::fStripToTrack"};    // front strip to track pointers
+  L1Vector<int> fStripToTrackB {"L1Algo::fStripToTrackB"};  // back strip to track pointers
+
+  int fNThreads {0};
+  bool fUseHitErrors {true};
+  bool fMissingHits {0};  ///< TODO ???
+  TrackingMode fTrackingMode {kSts};
+
+  fvec EventTime[L1Constants::size::kMaxNthreads][L1Constants::size::kMaxNthreads] {{0}};
+  fvec Err[L1Constants::size::kMaxNthreads][L1Constants::size::kMaxNthreads] {{0}};
+
+  /// --- data used during finding iterations
+  int isec {0};                                       // iteration TODO: to be dispatched (S.Zharko, 21.06.2022)
+  const L1CAIteration* fpCurrentIteration = nullptr;  ///< pointer to the current CA track finder iteration
+
+  L1Vector<L1Hit>* vHitsUnused           = nullptr;
+  L1Vector<L1HitIndex_t>* RealIHitP      = nullptr;
+  L1Vector<L1HitIndex_t>* RealIHitPBuf   = nullptr;
+  L1Vector<L1HitPoint>* vHitPointsUnused = nullptr;
+  L1HitIndex_t* RealIHit                 = nullptr;  // index in vHits indexed by index in vHitsUnused
+
+  L1HitIndex_t HitsUnusedStartIndex[L1Constants::size::kMaxNstations + 1] {0};
+  L1HitIndex_t HitsUnusedStopIndex[L1Constants::size::kMaxNstations + 1] {0};
+  L1HitIndex_t HitsUnusedStartIndexEnd[L1Constants::size::kMaxNstations + 1] {0};
+  L1HitIndex_t HitsUnusedStopIndexEnd[L1Constants::size::kMaxNstations + 1] {0};
+
+  L1Vector<int> fHitFirstTriplet {"L1Algo::fHitFirstTriplet"};  /// link hit -> first triplet { hit, *, *}
+  L1Vector<int> fHitNtriplets {"L1Algo::fHitNtriplets"};        /// link hit ->n triplets { hit, *, *}
+
+
+  //  fvec u_front[Portion/fvecLen], u_back[Portion/fvecLen];
+  //  fvec zPos[Portion/fvecLen];
+  //  fvec fHitTime[Portion/fvecLen];
+
+  nsL1::vector<L1TrackPar>::TSimd fT_3[L1Constants::size::kMaxNthreads];
+
+  L1Vector<L1HitIndex_t> fhitsl_3[L1Constants::size::kMaxNthreads] {"L1Algo::fhitsl_3"};
+  L1Vector<L1HitIndex_t> fhitsm_3[L1Constants::size::kMaxNthreads] {"L1Algo::fhitsm_3"};
+  L1Vector<L1HitIndex_t> fhitsr_3[L1Constants::size::kMaxNthreads] {"L1Algo::fhitsr_3"};
+
+  nsL1::vector<fvec>::TSimd fu_front3[L1Constants::size::kMaxNthreads];
+  nsL1::vector<fvec>::TSimd fu_back3[L1Constants::size::kMaxNthreads];
+  nsL1::vector<fvec>::TSimd fz_pos3[L1Constants::size::kMaxNthreads];
+  nsL1::vector<fvec>::TSimd fTimeR[L1Constants::size::kMaxNthreads];
+  nsL1::vector<fvec>::TSimd fTimeER[L1Constants::size::kMaxNthreads];
+  nsL1::vector<fvec>::TSimd dx[L1Constants::size::kMaxNthreads];
+  nsL1::vector<fvec>::TSimd dy[L1Constants::size::kMaxNthreads];
+  nsL1::vector<fvec>::TSimd du[L1Constants::size::kMaxNthreads];
+  nsL1::vector<fvec>::TSimd dv[L1Constants::size::kMaxNthreads];
+
+
+  //   Tindex NHits_l[L1Constants::size::kMaxNstations];
+  //   Tindex NHits_l_P[L1Constants::size::kMaxNstations];
+  /// ----- Output data -----
+
+
+private:
+  L1Parameters fParameters {};           ///< Object of L1Algo parameters class
+  L1InitManager fInitManager {};         ///< Object of L1Algo initialization manager class
+  L1ClonesMerger fClonesMerger {*this};  ///< Object of L1Algo clones merger algorithm
+
 #ifdef TBB
   enum
   {
@@ -550,8 +571,6 @@ private:
     nblocks  = 1   // number of stations on one thread
   };
 
-  friend class ParalleledDup;
-  friend class ParalleledTrip;
 #endif  // TBB
 #ifdef TBB2
 public:
@@ -602,7 +621,7 @@ private:
   };
 #endif  // FIND_GAPED_TRACKS
 
-  map<int, int> threadNumberToCpuMap {};
+  std::map<int, int> threadNumberToCpuMap {};
 
   float fTrackChi2Cut {10.f};
   float fTripletChi2Cut {5.f};  // cut for selecting triplets before collecting tracks.per one DoF
@@ -646,9 +665,51 @@ private:
 #ifdef DOUB_PERFORMANCE
   L1AlgoEfficiencyPerformance<2>* fL1Eff_doublets;
 #endif
-#ifdef DRAW
-  friend class L1AlgoDraw;
-#endif
 } _fvecalignment;
 
+
+// ********************************************
+// ** Inline member functions implementation **
+// ********************************************
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+[[gnu::always_inline]] inline unsigned int L1Algo::PackTripletId(unsigned int iStation, unsigned int iThread,
+                                                                 unsigned int iTriplet)
+{
+#ifndef FAST_CODE
+  assert(iStation < L1Constants::size::kMaxNstations);
+  assert(iThread < L1Constants::size::kMaxNthreads);
+  assert(iTriplet < L1Constants::size::kMaxNtriplets);
+#endif
+  constexpr unsigned int kMoveThread  = L1Constants::size::kTripletBits;
+  constexpr unsigned int kMoveStation = L1Constants::size::kTripletBits + L1Constants::size::kThreadBits;
+  return (iStation << kMoveStation) + (iThread << kMoveThread) + iTriplet;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+[[gnu::always_inline]] inline unsigned int L1Algo::TripletId2Station(unsigned int id)
+{
+  constexpr unsigned int kMoveStation = L1Constants::size::kTripletBits + L1Constants::size::kThreadBits;
+  return id >> kMoveStation;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+[[gnu::always_inline]] inline unsigned int L1Algo::TripletId2Thread(unsigned int id)
+{
+  constexpr unsigned int kMoveThread = L1Constants::size::kTripletBits;
+  constexpr unsigned int kThreadMask = (1u << L1Constants::size::kThreadBits) - 1u;
+  return (id >> kMoveThread) & kThreadMask;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+[[gnu::always_inline]] inline unsigned int L1Algo::TripletId2Triplet(unsigned int id)
+{
+  constexpr unsigned int kTripletMask = (1u << L1Constants::size::kTripletBits) - 1u;
+  return id & kTripletMask;
+}
+
 #endif
diff --git a/reco/L1/L1Algo/L1Timer.h b/reco/L1/L1Algo/L1Timer.h
index 3688207ab4..5ffdadb0ee 100644
--- a/reco/L1/L1Algo/L1Timer.h
+++ b/reco/L1/L1Algo/L1Timer.h
@@ -12,17 +12,10 @@
 
 #include "L1Def.h"
 
-using std::cout;
-using std::endl;
-using std::ios;
-using std::setw;
-using std::string;
-using std::vector;
-
 class TimerInfo {
 public:
   TimerInfo() : fName(""), fReal(0), fCpu(0) {};
-  TimerInfo(const string& name) : fName(name), fReal(0), fCpu(0) {};
+  TimerInfo(const std::string& name) : fName(name), fReal(0), fCpu(0) {};
 
   TimerInfo& operator=(TStopwatch& sw)
   {
@@ -50,25 +43,25 @@ public:
     return r;
   }
 
-  // void Print(){ cout << fReal << "/" << fCpu; };
-  void PrintReal() { cout << fReal; };
+  // void Print(){ std::cout << fReal << "/" << fCpu; };
+  void PrintReal() { std::cout << fReal; };
   float Real() { return fReal; };
-  string& Name() { return fName; };
+  std::string& Name() { return fName; };
 
 private:
-  string fName;
+  std::string fName;
   float fReal, fCpu;
 };
 
 class L1CATFIterTimerInfo {
 public:
   L1CATFIterTimerInfo() : fNameToI(), fTIs() {};
-  void Add(string name)
+  void Add(std::string name)
   {
     fNameToI[name] = fTIs.size();
     fTIs.push_back(TimerInfo(name));
   };
-  TimerInfo& operator[](string name) { return fTIs[fNameToI[name]]; };
+  TimerInfo& operator[](std::string name) { return fTIs[fNameToI[name]]; };
   TimerInfo& operator[](int i) { return fTIs[i]; };
   void operator+=(L1CATFIterTimerInfo& t)
   {
@@ -90,26 +83,26 @@ public:
   {
     if (f) {
       PrintNames();
-      cout << endl;
+      std::cout << '\n';
     }
     fTIs[0].PrintReal();
     for (unsigned int i = 1; i < fTIs.size(); ++i) {
-      cout << " | " << setw(fTIs[i].Name().size());
+      std::cout << " | " << std::setw(fTIs[i].Name().size());
       fTIs[i].PrintReal();
     }
-    if (f) cout << endl;
+    if (f) std::cout << '\n';
   };
   void PrintNames()
   {
-    cout << fTIs[0].Name();
+    std::cout << fTIs[0].Name();
     for (unsigned int i = 1; i < fTIs.size(); ++i) {
-      cout << " | " << fTIs[i].Name();
+      std::cout << " | " << fTIs[i].Name();
     }
   };
 
 private:
-  map<string, int> fNameToI;
-  vector<TimerInfo> fTIs;
+  std::map<std::string, int> fNameToI;
+  std::vector<TimerInfo> fTIs;
 };
 
 class L1CATFTimerInfo {
@@ -117,7 +110,7 @@ public:
   L1CATFTimerInfo() : fTIIs(), fTIAll() {};
   void SetNIter(int n) { fTIIs.resize(n); };
 
-  void Add(string name)
+  void Add(std::string name)
   {
     for (unsigned int i = 0; i < fTIIs.size(); ++i)
       fTIIs[i].Add(name);
@@ -152,25 +145,25 @@ public:
   L1CATFIterTimerInfo& GetAllInfo() { return fTIAll; };
   void PrintReal()
   {
-    cout.precision(1);
-    cout.setf(ios::fixed);
-    cout << " stage "
-         << " : ";
+    std::cout.precision(1);
+    std::cout.setf(std::ios::fixed);
+    std::cout << " stage "
+              << " : ";
     fTIAll.PrintNames();
-    cout << endl;
+    std::cout << '\n';
     for (unsigned int i = 0; i < fTIIs.size(); ++i) {
-      cout << " iter " << i << " : ";
+      std::cout << " iter " << i << " : ";
       fTIIs[i].PrintReal();
-      cout << endl;
+      std::cout << '\n';
     }
-    cout << " all   "
-         << " : ";
+    std::cout << " all   "
+              << " : ";
     fTIAll.PrintReal();
-    cout << endl;
+    std::cout << '\n';
   };
 
 private:
-  vector<L1CATFIterTimerInfo> fTIIs;
+  std::vector<L1CATFIterTimerInfo> fTIIs;
   L1CATFIterTimerInfo fTIAll;
 };
 
diff --git a/reco/L1/L1Algo/L1Triplet.h b/reco/L1/L1Algo/L1Triplet.h
index 988c06fda5..933758eb80 100644
--- a/reco/L1/L1Algo/L1Triplet.h
+++ b/reco/L1/L1Algo/L1Triplet.h
@@ -15,7 +15,6 @@
 /// L1Triplet class represents a short 3-hit track segment called a "triplet".
 ///
 class L1Triplet {
-
 public:
   /// default constructor
   L1Triplet() = default;
@@ -74,24 +73,26 @@ public:
   void Print();
 
 private:
-  fscal fChi2 = 0.f;  // chi^2
-  fscal fQp   = 0.f;  // q/p
-  fscal fCqp  = 0.f;  // RMS of q/p
-  fscal fTx   = 0.f;  // tx at the left hit
-  fscal fCtx  = 0.f;  // RMS of tx
-  fscal fTy   = 0.f;  // ty at the left hit
-  fscal fCty  = 0.f;  // RMS of ty
-
-  unsigned int fFirstNeighbour = 0;  // ID of the first neighbouring triplet
-  L1HitIndex_t fHitL           = 0;  // left hit index (16b) in vHits array
-  L1HitIndex_t fHitM           = 0;  // middle hit index (16b)
-  L1HitIndex_t fHitR           = 0;  // right hit index (16b)
-  int fNneighbours             = 0;  // n of neighbouring triplets
-  unsigned char fLevel         = 0;  // triplet level
-                                     // == its possible position on the longest track candidate it belongs to.
-                                     // level 0 = rightmost triplet of a track candidate
-                                     // level k = k-ths triplet along the track counting upstream, from right to left.
-  unsigned char fSta = 0;            // packed station numbers: staL (4b), staM-1-staL (2b), staR-2-staL (2b)
+  fscal fChi2 = 0.f;  ///< chi^2
+  fscal fQp   = 0.f;  ///< q/p
+  fscal fCqp  = 0.f;  ///< RMS of q/p
+  fscal fTx   = 0.f;  ///< tx at the left hit
+  fscal fCtx  = 0.f;  ///< RMS of tx
+  fscal fTy   = 0.f;  ///< ty at the left hit
+  fscal fCty  = 0.f;  ///< RMS of ty
+
+  unsigned int fFirstNeighbour = 0;  ///< ID of the first neighbouring triplet
+  L1HitIndex_t fHitL           = 0;  ///< left hit index (16b) in vHits array
+  L1HitIndex_t fHitM           = 0;  ///< middle hit index (16b)
+  L1HitIndex_t fHitR           = 0;  ///< right hit index (16b)
+  int fNneighbours             = 0;  ///< n of neighbouring triplets
+
+  /// Triplet level - its possible position on the longest track candidate it belongs to.
+  /// level 0 = rightmost triplet of a track candidate
+  /// level k = k-ths triplet along the track counting upstream, from right to left.
+  unsigned char fLevel = 0;
+
+  unsigned char fSta = 0;  ///< packed station numbers: staL (4b), staM-1-staL (2b), staR-2-staL (2b)
 };
 
 #endif
diff --git a/reco/L1/L1Algo/L1Utils.h b/reco/L1/L1Algo/L1Utils.h
index fdd3ba8f9e..a813f52a36 100644
--- a/reco/L1/L1Algo/L1Utils.h
+++ b/reco/L1/L1Algo/L1Utils.h
@@ -69,14 +69,18 @@ namespace L1Utils
   class TimeProfiler {
   public:
     /// Constructor
-    TimeProfiler(const char* scopeName) : fScopeName(scopeName), fStart(std::chrono::high_resolution_clock::now()) {}
+    TimeProfiler(const char* scopeName) : fScopeName(scopeName), fStart(std::chrono::high_resolution_clock::now())
+    {
+      LOG(info) << "---------- Time measurement in scope \033[1;32m" << fScopeName << "\033[0m: Start";
+    }
 
     /// Destructor
     ~TimeProfiler()
     {
       auto stop = std::chrono::high_resolution_clock::now();
       auto time = std::chrono::duration_cast<std::chrono::nanoseconds>(stop - fStart).count();
-      LOG(info) << "Scope \033[1;32m" << fScopeName << "\033[0m was executed in " << time << " ns";
+      LOG(info) << "---------- Time measurement in scope \033[1;32m" << fScopeName
+                << "\033[0m: Finish. Result: " << time << " ns";
     }
 
   private:
diff --git a/reco/L1/L1Algo/L1Vector.h b/reco/L1/L1Algo/L1Vector.h
index f5d39e5f1c..780a9cf125 100644
--- a/reco/L1/L1Algo/L1Vector.h
+++ b/reco/L1/L1Algo/L1Vector.h
@@ -47,13 +47,39 @@ public:
   /// Constructor to make initializations like L1Vector<int> myVector {"MyVector", {1, 2, 3}}
   L1Vector(const std::string& name, std::initializer_list<T> init) : Tbase(init), fName(name) {}
 
-  L1Vector(const L1Vector& v) : Tbase() { *this = v; }
+  /// Copy constructor
+  L1Vector(const L1Vector& v) : Tbase()
+  {
+    //LOG(info) << "\033[1;32mCALL L1Vector copy constructor\033[0m";
+    *this = v;
+  }
+
+  /// Move constructor
+  L1Vector(L1Vector&& v) noexcept : Tbase(std::move(v)), fName(std::move(v.fName))
+  {
+    //LOG(info) << "\033[1;32mCALL L1Vector move constructor\033[0m";
+  }
 
+  /// Copy assignment operator
   L1Vector& operator=(const L1Vector& v)
   {
-    fName = v.fName;
-    Tbase::reserve(v.capacity());  // make sure that the capacity is transmitted
-    Tbase::assign(v.begin(), v.end());
+    //LOG(info) << "\033[1;32mCALL L1Vector copy assignment operator\033[0m";
+    if (this != &v) {
+      fName = v.fName;
+      Tbase::reserve(v.capacity());  // make sure that the capacity is transmitted
+      Tbase::assign(v.begin(), v.end());
+    }
+    return *this;
+  }
+
+  /// Move assignment operator
+  L1Vector& operator=(L1Vector&& v) noexcept
+  {
+    //LOG(info) << "\033[1;32mCALL L1Vector move assignment operator\033[0m";
+    if (this != &v) {
+      std::swap(fName, v.fName);
+      Tbase::swap(v);
+    }
     return *this;
   }
 
-- 
GitLab