diff --git a/algo/ca/core/CMakeLists.txt b/algo/ca/core/CMakeLists.txt
index 36d86f93bcd7b9eb84a66594c4e21cb3b73cb5bd..3e2065b1c642b5fb109374ec92d08a6a0991c3cf 100644
--- a/algo/ca/core/CMakeLists.txt
+++ b/algo/ca/core/CMakeLists.txt
@@ -36,6 +36,7 @@ set(SRCS
   ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaTrackFit.cxx
   ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaTrackFitter.cxx
   ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaTripletConstructor.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/utils/CaUtils.cxx
 )
 
 SET_SOURCE_FILES_PROPERTIES(${SRCS} PROPERTIES COMPILE_FLAGS "-O3")
diff --git a/algo/ca/core/pars/CaParameters.cxx b/algo/ca/core/pars/CaParameters.cxx
index 73ab58bbc61d7f1a838ca7d59af72a2c684a10ed..516e86f3d71c5ed495a1a41a24829cb42254b84f 100644
--- a/algo/ca/core/pars/CaParameters.cxx
+++ b/algo/ca/core/pars/CaParameters.cxx
@@ -81,7 +81,7 @@ void Parameters::CheckConsistency() const
    */
   bool ifFieldStatusFlagsOk = std::is_sorted(
     fStations.cbegin(), fStations.cbegin() + fNstationsActiveTotal,
-    [&](const ca::Station& lhs, const ca::Station& rhs) { return bool(lhs.fieldStatus) > bool(rhs.fieldStatus); });
+    [&](const ca::StationV& lhs, const ca::StationV& rhs) { return bool(lhs.fieldStatus) > bool(rhs.fieldStatus); });
 
   if (!ifFieldStatusFlagsOk) {
     std::stringstream msg;
diff --git a/algo/ca/core/pars/CaParameters.h b/algo/ca/core/pars/CaParameters.h
index 93ee1b1b92b9a4234499f67d54e1972fea637198..26fb064623a87c5591820952aeda8e854404c758 100644
--- a/algo/ca/core/pars/CaParameters.h
+++ b/algo/ca/core/pars/CaParameters.h
@@ -34,7 +34,7 @@ namespace cbm::algo::ca
 
   /// Type definitions for used containers
   using IterationsContainer_t = cbm::algo::ca::Vector<cbm::algo::ca::Iteration>;
-  using StationsContainer_t   = std::array<ca::Station, constants::size::MaxNstations>;
+  using StationsContainer_t   = std::array<ca::StationV, constants::size::MaxNstations>;
   using MaterialContainer_t   = std::array<ca::MaterialMap, constants::size::MaxNstations>;
 
   /// \class cbm::algo::ca::Parameters
@@ -134,7 +134,7 @@ namespace cbm::algo::ca
 
     /// \brief Gets reference to the particular station
     /// \param iStation  Index of station in the active stations container
-    const Station& GetStation(int iStation) const { return fStations[iStation]; }
+    const StationV& GetStation(int iStation) const { return fStations[iStation]; }
 
     /// \brief Gets a search window for a selected station and track group
     /// \note  For a particular track finder iteration one can select a track group, which is defined by the minimal
diff --git a/algo/ca/core/pars/CaStation.cxx b/algo/ca/core/pars/CaStation.cxx
index 241b4b28e9f123d48c8b065ce3f0cccc1ae7e4cc..254ffc44ac42969baec5fb0fcf4a3679ecb9101f 100644
--- a/algo/ca/core/pars/CaStation.cxx
+++ b/algo/ca/core/pars/CaStation.cxx
@@ -14,7 +14,8 @@ using namespace cbm::algo::ca;
 
 //------------------------------------------------------------------------------------------------------------------------------------
 //
-void Station::CheckConsistency() const
+template<typename DataT>
+void Station<DataT>::CheckConsistency() const
 {
   /// Integer fields initialization checks
 
@@ -40,18 +41,19 @@ void Station::CheckConsistency() const
 
   /// SIMD vector checks: all the words in a SIMD vector must be equal
 
-  utils::CheckSimdVectorEquality(fZ, "CaStation::fZ");
-  utils::CheckSimdVectorEquality(Xmax, "CaStation::Xmax");
-  utils::CheckSimdVectorEquality(Ymax, "CaStation::Ymax");
+  utils::CheckSimdVectorEquality<DataT>(fZ, "CaStation::fZ");
+  utils::CheckSimdVectorEquality<DataT>(Xmax, "CaStation::Xmax");
+  utils::CheckSimdVectorEquality<DataT>(Ymax, "CaStation::Ymax");
 
 
   /// Inner and outer radia checks:
   ///  (i)  both Xmax and Ymax must be > 0
 
-  if (Xmax[0] < 0. || Ymax[0] < 0.) {
+  if (this->GetXmax<float>() < 0. || this->GetYmax<float>() < 0.) {
     std::stringstream msg;
     msg << "CaStation: " << this->ToString() << " has incorrect sizes: "
-        << "Xmax = " << Xmax[0] << " [cm], Ymax = " << Ymax[0] << " [cm] (0 < Xmax && 0 < Ymax expected)";
+        << "Xmax = " << this->GetXmax<float>() << " [cm], Ymax = " << this->GetYmax<float>()
+        << " [cm] (0 < Xmax && 0 < Ymax expected)";
     throw std::logic_error(msg.str());
   }
 
@@ -65,14 +67,15 @@ void Station::CheckConsistency() const
 
 //------------------------------------------------------------------------------------------------------------------------------------
 //
-std::string Station::ToString(int verbosityLevel, int indentLevel, bool isHeader) const
+template<typename DataT>
+std::string Station<DataT>::ToString(int verbosityLevel, int indentLevel, bool isHeader) const
 {
   std::stringstream msg{};
   constexpr char indentChar = '\t';
   constexpr char columnSize = 15;
   std::string indent(indentLevel, indentChar);
   if (verbosityLevel == 0) {
-    msg << "station type = " << type << ", z = " << fZ[0] << " cm";
+    msg << "station type = " << type << ", z = " << this->GetZ<float>() << " cm";
   }
   else {
     if (isHeader) {
@@ -90,9 +93,9 @@ std::string Station::ToString(int verbosityLevel, int indentLevel, bool isHeader
       msg << std::setw(columnSize) << std::setfill(' ') << this->GetType() << ' ';
       msg << std::setw(columnSize) << std::setfill(' ') << this->GetTimeStatus() << ' ';
       msg << std::setw(columnSize) << std::setfill(' ') << this->GetFieldStatus() << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << this->GetZScal() << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << this->GetXmaxScal() << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << this->GetYmaxScal();
+      msg << std::setw(columnSize) << std::setfill(' ') << this->GetZ<float>() << ' ';
+      msg << std::setw(columnSize) << std::setfill(' ') << this->GetXmax<float>() << ' ';
+      msg << std::setw(columnSize) << std::setfill(' ') << this->GetYmax<float>();
     }
     if (verbosityLevel > 3) {
       msg << indent << "Field approcimation coefficients:\n";
@@ -101,3 +104,9 @@ std::string Station::ToString(int verbosityLevel, int indentLevel, bool isHeader
   }
   return msg.str();
 }
+namespace cbm::algo::ca
+{
+  template class Station<fvec>;
+  template class Station<float>;
+  template class Station<double>;
+}  // namespace cbm::algo::ca
diff --git a/algo/ca/core/pars/CaStation.h b/algo/ca/core/pars/CaStation.h
index 43b9274ae401233433c7cba6096180b7d13fb546..15897be25157c47ac600b41b48bb27640326a905 100644
--- a/algo/ca/core/pars/CaStation.h
+++ b/algo/ca/core/pars/CaStation.h
@@ -15,6 +15,7 @@ namespace cbm::algo::ca
   /// Structure Station
   /// Contains a set of geometry parameters for a particular station
   ///
+  template<typename DataT>
   class Station {
    public:
     // TODO: SZh 12.05.2022: Rewrite type into L1DetectorID, change detector indexing scheme
@@ -24,12 +25,27 @@ namespace cbm::algo::ca
     int timeInfo = constants::Undef<int>;  ///< flag: if time information can be used
     int fieldStatus =
       constants::Undef<int>;             ///< flag: 1 - station is INSIDE the field, 0 - station is OUTSIDE the field
-    fvec fZ   = constants::Undef<fvec>;  ///< z position of station     [cm]
-    fvec Xmax = constants::Undef<fvec>;  ///< min radius of the station [cm]
-    fvec Ymax = constants::Undef<fvec>;  ///< max radius of the station [cm]
+    DataT fZ   = constants::Undef<DataT>;  ///< z position of station     [cm]
+    DataT Xmax = constants::Undef<DataT>;  ///< min radius of the station [cm]
+    DataT Ymax = constants::Undef<DataT>;  ///< max radius of the station [cm]
 
     FieldSlice fieldSlice{};  ///< Magnetic field near the station
 
+    Station() = default;
+
+    /// \brief Copy constructor with type conversion
+    template<typename DataI>
+    Station(const Station<DataI>& other)
+      : type(other.GetType())
+      , timeInfo(other.GetTimeStatus())
+      , fieldStatus(other.GetFieldStatus())
+      , fZ(other.template GetZ<DataT>())
+      , Xmax(other.template GetXmax<DataT>())
+      , Ymax(other.template GetYmax<DataT>())
+      , fieldSlice(other.fieldSlice)
+    {
+    }
+
     // Serialization block
     friend class boost::serialization::access;
     template<class Archive>
@@ -60,23 +76,26 @@ namespace cbm::algo::ca
     /// \brief Gets field status flag
     int GetFieldStatus() const { return fieldStatus; }
 
-    /// \brief Gets simdized z-position of the station
-    fvec GetZSimd() const { return fZ; }
-
-    /// \brief Gets scalar z-position of the station
-    fscal GetZScal() const { return fZ[0]; }
-
-    /// \brief Gets simdized limit of the station size in x-axis direction
-    fvec GetXmaxSimd() const { return Xmax; }
-
-    /// \brief Gets scalar limit of the station size in x-axis direction
-    fscal GetXmaxScal() const { return Xmax[0]; }
+    /// \brief Gets z-position of the station
+    template<typename DataO = DataT>
+    DataO GetZ() const
+    {
+      return utils::GetValSimpl<DataT, DataO>(fZ);
+    }
 
-    /// \brief Gets simdized limit of the station size in y-axis direction
-    fvec GetYmaxSimd() const { return Ymax; }
+    /// \brief Gets limit of the station size in x-axis direction
+    template<typename DataO = DataT>
+    DataO GetXmax() const
+    {
+      return utils::GetValSimpl<DataT, DataO>(Xmax);
+    }
 
-    /// \brief Gets scalar limit of the station size in y-axis direction
-    fscal GetYmaxScal() const { return Ymax[0]; }
+    /// \brief Gets limit of the station size in y-axis direction
+    template<typename DataO = DataT>
+    DataO GetYmax() const
+    {
+      return utils::GetValSimpl<DataT, DataO>(Ymax);
+    }
 
     /// \brief String representation of class contents
     /// \param verbosityLevel  Verbosity level of the output
@@ -85,4 +104,14 @@ namespace cbm::algo::ca
 
   } _fvecalignment;
 
+  class StationV : public Station<fvec> {
+    using Station<fvec>::Station;  /// inherit all the constructors
+  };
+  class StationF : public Station<float> {
+    using Station<float>::Station;  /// inherit all the constructors
+  };
+  class StationD : public Station<double> {
+    using Station<double>::Station;  /// inherit all the constructors
+  };
+
 }  // namespace cbm::algo::ca
diff --git a/algo/ca/core/pars/CaStationInitializer.cxx b/algo/ca/core/pars/CaStationInitializer.cxx
index 8b5f9e0b5bb58a39f1088a8a153b2620bef6f378..b6679f9665171b4cadf894c811efe626e700b316 100644
--- a/algo/ca/core/pars/CaStationInitializer.cxx
+++ b/algo/ca/core/pars/CaStationInitializer.cxx
@@ -19,8 +19,8 @@
 
 using cbm::algo::ca::EDetectorID;
 using cbm::algo::ca::MaterialMap;
-using cbm::algo::ca::Station;
 using cbm::algo::ca::StationInitializer;
+using cbm::algo::ca::StationV;
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
@@ -42,7 +42,7 @@ void StationInitializer::Reset()
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-const Station& StationInitializer::GetStation() const
+const StationV& StationInitializer::GetStation() const
 {
   if (!fInitController.IsFinalized()) {
     std::stringstream msg;
diff --git a/algo/ca/core/pars/CaStationInitializer.h b/algo/ca/core/pars/CaStationInitializer.h
index d532be1ea375c0948a44c7643d29308dc3a35101..e1bf423d4827bbe61978061c370545ac1f83aa1e 100644
--- a/algo/ca/core/pars/CaStationInitializer.h
+++ b/algo/ca/core/pars/CaStationInitializer.h
@@ -101,7 +101,7 @@ namespace cbm::algo::ca
     const InitController_t& GetInitController() const { return fInitController; }
 
     /// \brief Gets a reference to ca::Station info field of the L1BaseStation info
-    const Station& GetStation() const;
+    const StationV& GetStation() const;
 
     /// \brief Gets a reference to ca::MaterialMap map
     const MaterialMap& GetMaterialMap() const;
@@ -206,7 +206,7 @@ namespace cbm::algo::ca
     double fZref{0};                       ///< reference z
     double fZmin{0};                       ///< min z
     double fZmax{0};                       ///< max z
-    Station fStation{};                    ///< ca::Station structure, describes a station in L1Algo
+    StationV fStation{};                   ///< ca::Station structure, describes a station in L1Algo
     MaterialMap fThicknessMap{};           ///< Map of station thickness in units of radiation length
     InitController_t fInitController{};    ///< Class fileds initialization flags
     ManagementFlags_t fManagementFlags{};  ///< bitset flags to manage internal behaviour of the class
diff --git a/algo/ca/core/tracking/CaFramework.cxx b/algo/ca/core/tracking/CaFramework.cxx
index 360920be92d8298ad278b9c3bb0a5b30143c44c1..e5fc12f6ec797e7183d3b6bfdf670e61750e77b2 100644
--- a/algo/ca/core/tracking/CaFramework.cxx
+++ b/algo/ca/core/tracking/CaFramework.cxx
@@ -56,7 +56,7 @@ void Framework::ReceiveParameters(Parameters&& parameters)
   fNfieldStations = std::lower_bound(fParameters.GetStations().cbegin(),
                                      fParameters.GetStations().cbegin() + fParameters.GetNstationsActive(),
                                      0,  // we are looking for the first zero element
-                                     [](const ca::Station& s, int edge) { return bool(s.fieldStatus) > edge; })
+                                     [](const ca::StationV& s, int edge) { return bool(s.fieldStatus) > edge; })
                     - fParameters.GetStations().cbegin();
 
   fGhostSuppression = fParameters.GetGhostSuppression();
diff --git a/algo/ca/core/tracking/CaFramework.h b/algo/ca/core/tracking/CaFramework.h
index 44c0681332da847718e5c5df33098da01c229309..449a17cc781c9b5452df22550949b5d1fe46c274 100644
--- a/algo/ca/core/tracking/CaFramework.h
+++ b/algo/ca/core/tracking/CaFramework.h
@@ -53,7 +53,7 @@ namespace cbm::algo::ca
   // ** Types definition (global) **
   // *******************************
 
-  using CaStationsArray_t = std::array<ca::Station, constants::size::MaxNstations>;
+  using CaStationsArray_t = std::array<ca::StationV, constants::size::MaxNstations>;
   using CaMaterialArray_t = std::array<ca::MaterialMap, constants::size::MaxNstations>;
   using Tindex            = int;  // TODO: Replace with ca::HitIndex_t, if suitable
 
diff --git a/algo/ca/core/tracking/CaTrackExtender.cxx b/algo/ca/core/tracking/CaTrackExtender.cxx
index 3858466c0cc512bdacc375c9596ce332969388fb..0491bc7bea3b75ba106df53900f5af12f85f857b 100644
--- a/algo/ca/core/tracking/CaTrackExtender.cxx
+++ b/algo/ca/core/tracking/CaTrackExtender.cxx
@@ -61,9 +61,9 @@ void TrackExtender::FitBranchFast(const ca::Branch& t, TrackParamV& Tout, const
   int ista1 = hit1.Station();
   int ista2 = hit2.Station();
 
-  const ca::Station& sta0 = frAlgo.GetParameters().GetStation(ista0);
-  const ca::Station& sta1 = frAlgo.GetParameters().GetStation(ista1);
-  const ca::Station& sta2 = frAlgo.GetParameters().GetStation(ista2);
+  const ca::StationV& sta0 = frAlgo.GetParameters().GetStation(ista0);
+  const ca::StationV& sta1 = frAlgo.GetParameters().GetStation(ista1);
+  const ca::StationV& sta2 = frAlgo.GetParameters().GetStation(ista2);
 
   fvec x0 = hit0.X();
   fvec y0 = hit0.Y();
@@ -113,7 +113,7 @@ void TrackExtender::FitBranchFast(const ca::Branch& t, TrackParamV& Tout, const
   for (int i = iFirstHit + step; step * i <= step * iLastHit; i += step) {
     const ca::Hit& hit     = frAlgo.GetInputData().GetHit(hits[i]);
     int ista               = hit.Station();
-    const ca::Station& sta = frAlgo.GetParameters().GetStation(ista);
+    const ca::StationV& sta = frAlgo.GetParameters().GetStation(ista);
 
     fit.Extrapolate(hit.Z(), fld);
     fit.FilterHit(sta, hit);
@@ -168,9 +168,9 @@ void TrackExtender::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool up
   const int ista1 = hit1.Station();
   const int ista2 = hit2.Station();
 
-  const ca::Station& sta0 = frAlgo.GetParameters().GetStation(ista0);
-  const ca::Station& sta1 = frAlgo.GetParameters().GetStation(ista1);
-  const ca::Station& sta2 = frAlgo.GetParameters().GetStation(ista2);
+  const ca::StationV& sta0 = frAlgo.GetParameters().GetStation(ista0);
+  const ca::StationV& sta1 = frAlgo.GetParameters().GetStation(ista1);
+  const ca::StationV& sta2 = frAlgo.GetParameters().GetStation(ista2);
 
   fvec x0 = hit0.X();
   fvec y0 = hit0.Y();
@@ -200,7 +200,7 @@ void TrackExtender::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool up
 
   for (; (ista < frAlgo.GetParameters().GetNstationsActive()) && (ista >= 0); ista += step) {  // CHECKME why ista2?
 
-    const ca::Station& sta = frAlgo.GetParameters().GetStation(ista);
+    const ca::StationV& sta = frAlgo.GetParameters().GetStation(ista);
 
     fit.Extrapolate(sta.fZ, fld);
 
diff --git a/algo/ca/core/tracking/CaTrackFinder.cxx b/algo/ca/core/tracking/CaTrackFinder.cxx
index 6cc55dd4c37c9824fcb3bf60c6edcf8148e7feb9..4d669171aa78715feb5c0ab11fc91a2b437e1611 100644
--- a/algo/ca/core/tracking/CaTrackFinder.cxx
+++ b/algo/ca/core/tracking/CaTrackFinder.cxx
@@ -104,7 +104,7 @@ void TrackFinder::FindTracks()
 
       ca::HitIndex_t caHitId = frAlgo.fInputData.GetStreamStartIndex(iStream) + ih;
       const ca::Hit& h       = frAlgo.fInputData.GetHit(caHitId);
-      const ca::Station& st  = frAlgo.GetParameters().GetStation(h.Station());
+      const ca::StationV& st = frAlgo.GetParameters().GetStation(h.Station());
 
       fscal dx = h.X() - targX;
       fscal dy = h.Y() - targY;
diff --git a/algo/ca/core/tracking/CaTrackFinderWindow.cxx b/algo/ca/core/tracking/CaTrackFinderWindow.cxx
index b1f0c47b1f8c430d22b2e399eecb5d6ec79624af..e923255cd30de1fa3bd961921f6297edf2da675d 100644
--- a/algo/ca/core/tracking/CaTrackFinderWindow.cxx
+++ b/algo/ca/core/tracking/CaTrackFinderWindow.cxx
@@ -219,7 +219,7 @@ void TrackFinderWindow::CaTrackFinderSlice()
     fscal yStep    = sizeY / sqrt(nBins2D);
     fscal xStep    = sizeX / sqrt(nBins2D);
 
-    fscal scale = frAlgo.GetParameters().GetStation(iS).GetZScal() - frAlgo.GetParameters().GetTargetPositionZ()[0];
+    fscal scale = frAlgo.GetParameters().GetStation(iS).GetZ<float>() - frAlgo.GetParameters().GetTargetPositionZ()[0];
 
     if (yStep > 0.3 * scale) yStep = 0.3 * scale;
     if (yStep < 0.01 * scale) yStep = 0.01 * scale;
diff --git a/algo/ca/core/tracking/CaTrackFit.cxx b/algo/ca/core/tracking/CaTrackFit.cxx
index 5a0cb9d96adc9b436aea8c31054712817867d27b..7707ea27dafa780b78ef2b3b7fa48a35447ba29b 100644
--- a/algo/ca/core/tracking/CaTrackFit.cxx
+++ b/algo/ca/core/tracking/CaTrackFit.cxx
@@ -317,7 +317,7 @@ namespace cbm::algo::ca
     fTr.C66() -= K60 * F60 + K61 * F61;
   }
 
-  void TrackFit::FilterHit(const ca::Station& sta, const ca::Hit& hit)
+  void TrackFit::FilterHit(const ca::StationV& sta, const ca::Hit& hit)
   {
     ca::MeasurementXy<fvec> m;
     m.SetDx2(hit.dX2());
diff --git a/algo/ca/core/tracking/CaTrackFit.h b/algo/ca/core/tracking/CaTrackFit.h
index 6a61583b42bfb197a986a3f4355882dfa1c38aba..363073dd3f08c2830cc0835a0bc0943ee844ec66 100644
--- a/algo/ca/core/tracking/CaTrackFit.h
+++ b/algo/ca/core/tracking/CaTrackFit.h
@@ -27,7 +27,7 @@ namespace cbm::algo::ca
   }  // namespace
 
   class Hit;
-  class Station;
+  class StationV;
 
 
   /// Track fit utilities for the CA tracking based on the Kalman Filter
@@ -105,7 +105,7 @@ namespace cbm::algo::ca
     void FilterTime(MeasurementTime<fvec> mt) { FilterTime(mt.T(), mt.Dt2(), mt.NdfT()); }
 
     /// filter the track with the hit
-    void FilterHit(const ca::Station& s, const ca::Hit& h);
+    void FilterHit(const ca::StationV& s, const ca::Hit& h);
 
     /// filter the inverse speed
     void FilterVi(fvec vi);
diff --git a/algo/ca/core/tracking/CaTrackFitter.cxx b/algo/ca/core/tracking/CaTrackFitter.cxx
index b1e551c050eb6bd35b0fab1268e234b1ee3a4957..3ad17f11b2e0887e6f1721b152b053353f44f545 100644
--- a/algo/ca/core/tracking/CaTrackFitter.cxx
+++ b/algo/ca/core/tracking/CaTrackFitter.cxx
@@ -54,7 +54,7 @@ void TrackFitter::FitCaTracks()
 
   Track* t[fvec::size()]{nullptr};
 
-  const ca::Station* sta = frAlgo.GetParameters().GetStations().begin();
+  const ca::StationV* sta = frAlgo.GetParameters().GetStations().begin();
 
   // Spatial-time position of a hit vs. station and track in the portion
 
@@ -200,7 +200,7 @@ void TrackFitter::FitCaTracks()
 
       for (int ih = nHitsTrack - 1; ih >= 0; ih--) {
         const int ista        = iSta[ih];
-        const ca::Station& st = frAlgo.GetParameters().GetStation(ista);
+        const ca::StationV& st = frAlgo.GetParameters().GetStation(ista);
         By[ista][iVec]        = st.fieldSlice.cy[0][0];
       }
     }
diff --git a/algo/ca/core/tracking/CaTripletConstructor.cxx b/algo/ca/core/tracking/CaTripletConstructor.cxx
index 3136cee21469f672776d8b0329b45a97a3b381fa..3d1d0b1763e91e5eb4d87a11a2417b4b3b63b08c 100644
--- a/algo/ca/core/tracking/CaTripletConstructor.cxx
+++ b/algo/ca/core/tracking/CaTripletConstructor.cxx
@@ -401,7 +401,7 @@ void TripletConstructor::FitTriplets()
   // prepare data
   int ista[NHits] = {fIstaL, fIstaM, fIstaR};
 
-  ca::Station sta[3];
+  ca::StationV sta[3];
   for (int is = 0; is < NHits; ++is) {
     sta[is] = fAlgo->fParameters.GetStation(ista[is]);
   };
@@ -630,7 +630,7 @@ void TripletConstructor::CollectHits(const TrackParamV& Tr, const int iSta, cons
   collectedHits.clear();
   collectedHits.reserve(maxNhits);
 
-  const ca::Station& sta = fAlgo->fParameters.GetStation(iSta);
+  const ca::StationV& sta = fAlgo->fParameters.GetStation(iSta);
 
   fFit.SetTrack(Tr);
   TrackParamV& T = fFit.Tr();
diff --git a/algo/ca/core/tracking/CaTripletConstructor.h b/algo/ca/core/tracking/CaTripletConstructor.h
index 5d2c558c79e21b63731d3001b33c38b23ab83235..68234e0682a94b18daeaccf3ad378741bcc31be9 100644
--- a/algo/ca/core/tracking/CaTripletConstructor.h
+++ b/algo/ca/core/tracking/CaTripletConstructor.h
@@ -81,11 +81,11 @@ namespace cbm::algo::ca
 
    private:
     /// left station
-    const ca::Station& staL() { return *fStaL; }
+    const ca::StationV& staL() { return *fStaL; }
     /// middle station
-    const ca::Station& staM() { return *fStaM; }
+    const ca::StationV& staM() { return *fStaM; }
     /// right station
-    const ca::Station& staR() { return *fStaR; }
+    const ca::StationV& staR() { return *fStaR; }
 
    private:
     bool fIsInitialized{false};     ///< is initialized;
@@ -95,12 +95,12 @@ namespace cbm::algo::ca
     int fIstaM{-1};  ///< middle station index
     int fIstaR{-1};  ///< right station index
 
-    const ca::Station* fStaL{nullptr};  ///< left station
-    const ca::Station* fStaM{nullptr};  ///< mid station
-    const ca::Station* fStaR{nullptr};  ///< right station
+    const ca::StationV* fStaL{nullptr};  ///< left station
+    const ca::StationV* fStaM{nullptr};  ///< mid station
+    const ca::StationV* fStaR{nullptr};  ///< right station
 
-    const ca::Station* fFld0Sta[2];  // two stations for approximating the field between the target and the left hit
-    const ca::Station* fFld1Sta[3];  // three stations for approximating the field between the left and the right hit
+    const ca::StationV* fFld0Sta[2];  // two stations for approximating the field between the target and the left hit
+    const ca::StationV* fFld1Sta[3];  // three stations for approximating the field between the left and the right hit
 
     ca::HitIndex_t fIhitL;  ///< index of the left hit in fAlgo->fWindowHits
     TrackParamV fTrL;
diff --git a/algo/ca/core/utils/CaUtils.cxx b/algo/ca/core/utils/CaUtils.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5b75ffb3b4ddaf99fbd1ee505cf3099648c49694
--- /dev/null
+++ b/algo/ca/core/utils/CaUtils.cxx
@@ -0,0 +1,42 @@
+/* Copyright (C) 2022-2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov, Sergei Zharko [committer] */
+
+#include "CaUtils.h"
+
+/// Namespace contains compile-time constants definition for the CA tracking algorithm
+///
+namespace cbm::algo::ca::utils
+{
+  /// \brief Stingstream output operation for simd data
+  template<typename DataT>
+  void PrintSIMDmsg(std::stringstream& msg, DataT& v)
+  {
+    if constexpr (std::is_same_v<DataT, float> or std::is_same_v<DataT, double>) {
+      msg << v;
+    }
+    else {
+      msg << "[";
+      for (size_t i = 0; i < DataT::size() - 1; i++)
+        msg << v[i] << ",";
+      msg << v[DataT::size() - 1] << "]";
+    }
+  }
+
+  /// \brief Checks, if a SIMD vector horizontally equal
+  /// TODO: Find this method in the VC!
+  template<>
+  void CheckSimdVectorEquality(fvec v, const char* name)
+  {
+    bool ok = true;
+    for (size_t i = 1; i < fvec::size(); i++) {
+      ok = ok && (v[i] == v[0]);
+    }
+    if (!ok) {
+      std::stringstream msg;
+      msg << name << " SIMD vector is inconsistent, not all of the words are equal each other: ";
+      PrintSIMDmsg(msg, v);
+      throw std::logic_error(msg.str());
+    }
+  }
+}  // namespace cbm::algo::ca::utils
diff --git a/algo/ca/core/utils/CaUtils.h b/algo/ca/core/utils/CaUtils.h
index c77df1d573f7d708d4b6f92131a65274e482f345..1f14d08f0f2a43ad3e0477cb1846c8a60b700b90 100644
--- a/algo/ca/core/utils/CaUtils.h
+++ b/algo/ca/core/utils/CaUtils.h
@@ -89,21 +89,43 @@ namespace cbm::algo::ca::utils
     }
   }
 
+  /// \brief Stingstream output operation for simd data
+  template<typename DataT>
+  void PrintSIMDmsg(std::stringstream& msg, DataT& v);
+
+  /// \brief Checks, if a SIMD vector horizontally equal
+  template<typename DataT>
+  inline void CheckSimdVectorEquality(DataT /*v*/, const char* /*name*/)
+  {
+  }
+
   /// \brief Checks, if a SIMD vector horizontally equal
   /// TODO: Find this method in the VC!
-  [[gnu::always_inline]] inline void CheckSimdVectorEquality(fvec v, const char* name)
+  template<>
+  void CheckSimdVectorEquality(fvec v, const char* name);
+
+  /// \brief template based common fvec/float/double variable converter
+  template<typename DataT, typename DataO>
+  inline DataO GetValSimpl(const DataT& val)
   {
-    bool ok = true;
-    for (size_t i = 1; i < fvec::size(); i++) {
-      ok = ok && (v[i] == v[0]);
-    }
-    if (!ok) {
-      std::stringstream msg;
-      msg << name << " SIMD vector is inconsistent, not all of the words are equal each other: " << v;
-      throw std::logic_error(msg.str());
-    }
+    return static_cast<DataO>(val);
+  }
+
+  /// \brief template based common fvec/float/double variable converter
+  /// fvec to float implementation
+  template<>
+  inline float GetValSimpl(const fvec& val)
+  {
+    return val[0];
   }
 
+  /// \brief template based common fvec/float/double variable converter
+  /// fvec to double implementation
+  template<>
+  inline double GetValSimpl(const fvec& val)
+  {
+    return static_cast<double>(val[0]);
+  }
 
   template<typename TdataA, typename TdataB, bool TDoAllA, bool TDoAllB>
   class VecCopySpec {
diff --git a/reco/KF/CbmKfTrackFitter.cxx b/reco/KF/CbmKfTrackFitter.cxx
index 272cf0e93b5ed3ddddc8ebf039a498bcdeed99b5..e14e9b3a7d1726ed86da3d0ccb7a327e86f9fba7 100644
--- a/reco/KF/CbmKfTrackFitter.cxx
+++ b/reco/KF/CbmKfTrackFitter.cxx
@@ -190,7 +190,7 @@ bool CbmKfTrackFitter::CreateGlobalTrack(CbmKfTrackFitter::Track& kfTrack, const
       CbmKfTrackFitter::FitNode& n = t.fNodes[i];
       n                            = {};
       n.fMaterialLayer             = i;
-      n.fZ                         = caPar.GetStation(i).GetZScal();
+      n.fZ                         = caPar.GetStation(i).GetZ<float>();
       n.fRadThick                  = 0.;
       n.fIsRadThickSet             = false;
       n.fIsFitted                  = false;
diff --git a/reco/KF/ParticleFitter/CbmL1PFFitter.cxx b/reco/KF/ParticleFitter/CbmL1PFFitter.cxx
index 3c9c01e52114365b410c80a0dc03904a49f1198f..f5eba8ed2cbe727718503073ec55b8011711d697 100644
--- a/reco/KF/ParticleFitter/CbmL1PFFitter.cxx
+++ b/reco/KF/ParticleFitter/CbmL1PFFitter.cxx
@@ -180,7 +180,7 @@ void CbmL1PFFitter::Fit(std::vector<CbmStsTrack>& Tracks, const std::vector<CbmM
   CbmStsTrack* tr[fvec::size()]{nullptr};
 
   int ista;
-  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
+  const ca::StationV* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
 
   fvec x[nHits];
   fvec y[nHits];
@@ -498,7 +498,7 @@ void CbmL1PFFitter::GetChiToVertex(vector<CbmStsTrack>& Tracks, vector<PFFieldRe
 
   int nStations = fNmvdStationsActive + fNstsStationsActive;
 
-  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
+  const ca::StationV* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
   fvec* zSta             = new fvec[nStations];
   for (int iSta = 0; iSta < nStations; iSta++) {
     zSta[iSta] = sta[iSta].fZ;
@@ -652,7 +652,7 @@ void CbmL1PFFitter::CalculateFieldRegion(vector<CbmStsTrack>& Tracks, vector<PFF
   CbmStsTrack* tr[fvec::size()];
 
   int ista;
-  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
+  const ca::StationV* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
   ca::FieldValue fB[3], fB_temp _fvecalignment;
   fvec zField[3];
 
@@ -723,7 +723,7 @@ void CbmL1PFFitter::CalculateFieldRegionAtLastPoint(vector<CbmStsTrack>& Tracks,
   CbmStsTrack* tr[fvec::size()];
 
   int ista;
-  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
+  const ca::StationV* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
   ca::FieldValue fB[3], fB_temp _fvecalignment;
   fvec zField[3];
 
diff --git a/reco/L1/CbmL1Performance.cxx b/reco/L1/CbmL1Performance.cxx
index 40268631ebd530bba1e947094a94a8f98f99b6dc..51e05993e5367363e50abba3271f69db63f35b38 100644
--- a/reco/L1/CbmL1Performance.cxx
+++ b/reco/L1/CbmL1Performance.cxx
@@ -1654,7 +1654,7 @@ void CbmL1::FieldApproxCheck()
 
   for (int ist = 0; ist < fpAlgo->GetParameters().GetNstationsActive(); ist++) {
 
-    const ca::Station& st = fpAlgo->GetParameters().GetStation(ist);
+    const ca::StationV& st = fpAlgo->GetParameters().GetStation(ist);
 
     double z    = st.fZ[0];
     double Xmax = st.Xmax[0];
diff --git a/reco/L1/L1Algo/utils/L1AlgoDraw.cxx b/reco/L1/L1Algo/utils/L1AlgoDraw.cxx
index a3ed77b8745e18ed5a03ffc29e5fc44dcdd55438..cc0b4f001ec5f9c72f9bdbcbab6dda51dfa33e0c 100644
--- a/reco/L1/L1Algo/utils/L1AlgoDraw.cxx
+++ b/reco/L1/L1Algo/utils/L1AlgoDraw.cxx
@@ -564,7 +564,7 @@ void L1AlgoDraw::DrawInputHits()
 
 
   for (int ista = NStations - 1; ista >= 0; ista--) {  //  //start downstream chambers
-    ca::Station& st   = vStations[ista];
+    ca::StationV& st  = vStations[ista];
     Int_t n_poly      = 0;
     Int_t n_poly_fake = 0;
     for (int ih = HitsStartIndex[ista]; ih < HitsStopIndex[ista]; ih++) {
@@ -696,7 +696,7 @@ void L1AlgoDraw::DrawRestHits(ca::HitIndex_t* StsRestHitsStartIndex, ca::HitInde
 
 
   for (int ista = NStations - 1; ista >= 0; ista--) {  //  //start downstream chambers
-    ca::Station& st   = vStations[ista];
+    ca::StationV& st  = vStations[ista];
     Int_t n_poly      = 0;
     Int_t n_poly_fake = 0;
     for (ca::HitIndex_t iRestHit = StsRestHitsStartIndex[ista]; iRestHit < StsRestHitsStopIndex[ista]; iRestHit++) {
diff --git a/reco/L1/L1Algo/utils/L1AlgoDraw.h b/reco/L1/L1Algo/utils/L1AlgoDraw.h
index 1c288b67dda6ba83418d46bc6629dc4e27cb5507..d753fcb8eb0efe45487f4d15cfea2144fadca31c 100644
--- a/reco/L1/L1Algo/utils/L1AlgoDraw.h
+++ b/reco/L1/L1Algo/utils/L1AlgoDraw.h
@@ -74,7 +74,7 @@ class L1AlgoDraw {
   int HitsStopIndex[20]{0};
 
   int NStations{0};
-  ca::Station vStations[20]{};
+  ca::StationV vStations[20]{};
 
   int mcolor[10]{5, 7, 3, 8, 6, 2, 4, 1, 9, 14};  // color for hits on i-station
   int StaColor{17};                               // color for stantions