From 45b57cef804c2371bc6f659a44dbb4c2b8fbe90b Mon Sep 17 00:00:00 2001 From: "s.zharko@gsi.de" <s.zharko@gsi.de> Date: Thu, 24 Mar 2022 12:30:35 +0100 Subject: [PATCH] L1Algo interface: updates --- reco/L1/L1Algo/L1Array.h | 179 +++++++++++++++++++++++++++++++ reco/L1/L1Algo/L1Assert.h | 6 +- reco/L1/L1Algo/L1InitManager.cxx | 37 +++---- 3 files changed, 201 insertions(+), 21 deletions(-) create mode 100644 reco/L1/L1Algo/L1Array.h diff --git a/reco/L1/L1Algo/L1Array.h b/reco/L1/L1Algo/L1Array.h new file mode 100644 index 0000000000..d2754a9773 --- /dev/null +++ b/reco/L1/L1Algo/L1Array.h @@ -0,0 +1,179 @@ +/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergey Gorbunov, Sergei Zharko [committer] */ + +#ifndef L1Array_h +#define L1Array_h 1 + +#include <FairLogger.h> + +#include <array> +#include <string> +#include <utility> + +#include "L1Assert.h" + +/// Idea: std::array based class, where the size() and copacity() return different numbers. +/// Size returns the effective size of array (i.e. the number of elements, which were really) + +// TODO: What is better to be used here - std::size or int. Needs to be tested (S.Zharko) + + +template<class Tvalue, std::size_t MaxCapacity> +class L1Array : private std::array<Tvalue, MaxCapacity> { +public: + // Type definitions + using Tbase = std::array<Tvalue, MaxCapacity>; + using Tsize = typename Tbase::size_type; + using Tpointer = typename Tbase::pointer; + using Tcpointer = typename Tbase::const_pointer; + using Treference = typename Tbase::reference; + using Tcreference = typename Tbase::const_reference; + using Titerator = typename Tbase::iterator; + using Tciterator = typename Tbase::const_iterator; + using Tdifference = typename Tbase::difference_type; + using Triterator = typename Tbase::reverse_iterator; + using Tcriterator = typename Tbase::const_reverse_iterator; + using TarrayTraits = typename _GLIBCXX_STD_C::__array_traits<Tvalue, MaxCapacity>; + + template<typename... Tinput> + L1Array(Tinput... value) : Tbase(value...) + { + } + + template<typename... Tinput> + L1Array(int size, const char* name, Tinput... value) : Tbase(value...) + , fSize(static_cast<Tsize>(size)) + , fName(name) + { + } + + // TODO: Probably, there is a way to do this better... (S.Zharko) + L1Array(const char* name, std::initializer_list<Tvalue> init) : Tbase(), fName(name) + { +#ifndef FAST_CODE + if _GLIBCXX17_CONSTEXPR (L1Assert::kAssertionLevel >= 2 && Tbase::max_size() < init.size()) { + LOG(fatal) << '\n' + << " ***** Level 2 assertion failed: " << '\n' + << " ***** message: in L1Array with the name " << fName << ": the size of the initializer list (" + << init.size() << ") is larger then the maximum size of the array (" << Tbase::max_size() << ')'; + } +#endif // FAST_CODE + fSize = init.size(); + for (auto idx = 0; idx < fSize; ++idx) { + operator[](idx) = *(init.begin() + idx); + } + } + + L1Array(std::initializer_list<Tvalue> init) : L1Array("no name", init) {} + + /// Swap function + //friend void swap(L1Array<T, N>& lhs, L1Array<T, N>& rhs) + //{ + // std::swap(static_cast<Tbase&>(lhs), static_cast<Tbase&>(rhs)); + // std::swap(lhs.fName, rhs.fName); + // std::swap(lhs.fSize, rhs.fSize); + //} + + /// Gets name of the array + std::string GetName() const + { + std::string str = " L1Array<"; + str += fName + "> "; + return str; + } + + + /// Sets name of array from stringstream + void SetName(const std::basic_ostream<char>& name) { fName = dynamic_cast<const std::stringstream&>(name).str(); } + + /// Sets name of array from std::string parameters + void SetName(const std::string& name) { fName = name; } + + // + // BASE METHODS + // + // Element access + + Treference operator[](Tsize pos) noexcept + { +#ifndef FAST_CODE + if _GLIBCXX17_CONSTEXPR (L1Assert::kAssertionLevel >= 3 && pos >= fSize) { + LOG(fatal) << '\n' + << " ***** Level 3 assertion failed: " << '\n' + << " ***** message: in L1Array with the name " << fName << ": index out of range (pos = " << pos + << " >= size = " << fSize << ")"; + } + // TODO: do we need a simple assertion here to prevent the index out of range? (S.Zharko) +#endif // FAST_CODE + return Tbase::operator[](pos); + } + + Tcreference operator[](Tsize pos) const noexcept + { +#ifndef FAST_CODE + if _GLIBCXX17_CONSTEXPR (L1Assert::kAssertionLevel >= 3 && pos >= fSize) { + LOG(fatal) << '\n' + << " ***** Level 3 assertion failed: " << '\n' + << " ***** message: in L1Array with the name " << fName << ": index out of range (pos = " << pos + << " >= size = " << fSize << ")"; + } + // TODO: do we need a simple assertion here to prevent the index out of range? (S.Zharko) +#endif // FAST_CODE + return Tbase::operator[](pos); + } + + using Tbase::front; + + _GLIBCXX17_CONSTEXPR Treference back() noexcept { return fSize ? *(end() - 1) : *end(); } + + constexpr Tcreference back() const noexcept { return fSize ? *(end() - 1) : *end(); } + + using Tbase::data; + // Iterators + using Tbase::begin; + //using Tbase::end; + + // NOTE: _GLIBCXX17_CONSTEXPR is used in a base class and places constexpr for c++17+ and nothing instead + _GLIBCXX17_CONSTEXPR Titerator end() noexcept { return Titerator(data() + fSize); } + + _GLIBCXX17_CONSTEXPR Tciterator end() const noexcept { return Tciterator(data() + fSize); } + + _GLIBCXX17_CONSTEXPR Triterator rbegin() noexcept { return Triterator(end()); } + + _GLIBCXX17_CONSTEXPR Tcriterator rbegin() const noexcept { return Tcriterator(end()); } + + using Tbase::cbegin; + using Tbase::rend; + + _GLIBCXX17_CONSTEXPR Tciterator cend() const noexcept { return Tciterator(data() + fSize); } + + _GLIBCXX17_CONSTEXPR Tcriterator crbegin() const noexcept { return Tcriterator(end()); } + + using Tbase::crend; + + // Capasity + constexpr Tsize size() const noexcept { return fSize; } + + using Tbase::max_size; + constexpr bool empty(); + + // Operations + void fill(const Tvalue& val) { std::fill_n(begin(), size(), val); } + + void swap(L1Array& other) noexcept(TarrayTraits::_Is_nothrow_swappable::value) + { + std::swap(fName, other.fName); + std::swap(fSize, other.fSize); + std::swap_ranges(begin(), end(), other.begin()); + } + +private: + using Tbase::at; + + Tsize fSize {0}; + std::string fName {"no name"}; +}; + + +#endif // L1Array_h diff --git a/reco/L1/L1Algo/L1Assert.h b/reco/L1/L1Algo/L1Assert.h index af23e3adab..e5bdf5032b 100644 --- a/reco/L1/L1Algo/L1Assert.h +++ b/reco/L1/L1Algo/L1Assert.h @@ -22,7 +22,7 @@ #include "FairLogger.h" -#if defined(NDEBUG) || defined(L1_NO_ASSERT) // TODO: Do we need to add FAST_CODE here? (S.Zharko) +#if defined(NDEBUG) || defined(L1_NO_ASSERT) // TODO: Do we need to add FAST_CODE here? (S.Zharko) #define L1ASSERT(LEVEL, COND) #define L1MASSERT(LEVEL, COND, MSG) #else @@ -42,11 +42,11 @@ namespace L1Assert { if (!condition) { LOG(fatal) << '\n' - << " ***** Level " << level << " assertion failed: " << '\n' + << " ***** Level " << level << " assertion failed: " << '\n' << " ***** message/condition : " << msg << '\n' << " ***** file: " << fileName << '\n' << " ***** line: " << lineNo; - std::abort(); // keep it here, because sometimes LOG(fatal) does not work (for example, in your tester) + std::abort(); // keep it here, because sometimes LOG(fatal) does not work (for example, in your tester) } return 1; } diff --git a/reco/L1/L1Algo/L1InitManager.cxx b/reco/L1/L1Algo/L1InitManager.cxx index 99524ed879..e3adcb2d1e 100644 --- a/reco/L1/L1Algo/L1InitManager.cxx +++ b/reco/L1/L1Algo/L1InitManager.cxx @@ -9,10 +9,11 @@ ***********************************************************************************************************/ #include "L1InitManager.h" -#include "L1Assert.h" #include <algorithm> #include <sstream> + +#include "L1Assert.h" //----------------------------------------------------------------------------------------------------------------------- // L1InitManager::L1InitManager(L1Parameters* pParameters) : fpParameters(pParameters) {} @@ -23,16 +24,16 @@ void L1InitManager::AddStation(const L1BaseStationInfo& inStation) { // Check if other fields were defined already // Active detector IDs - - L1MASSERT(0, fInitController.GetFlag(InitKey::keActiveDetectorIDs), + + L1MASSERT(0, fInitController.GetFlag(InitKey::keActiveDetectorIDs), "Attempt to add a station info before the active detetors set had been initialized"); // Number of stations check - L1MASSERT(0, fInitController.GetFlag(InitKey::keStationsNumberCrosscheck), + L1MASSERT(0, fInitController.GetFlag(InitKey::keStationsNumberCrosscheck), "Attempt to add a station info before the numbers of stations for each detector had been initialized"); // Field function - L1MASSERT(0, fInitController.GetFlag(InitKey::keFieldFunction), + L1MASSERT(0, fInitController.GetFlag(InitKey::keFieldFunction), "Attempt to add a station info before the magnetic field function had been intialized"); // Check activeness of this station type @@ -49,9 +50,9 @@ void L1InitManager::AddStation(const L1BaseStationInfo& inStation) << inStation.GetInitController().ToString(); std::stringstream aStream; aStream << "Attempt to add an incompletely initialized station info object (detectorID = " - << static_cast<int>(inStationCopy.GetDetectorID()) - << ", stationID = " << inStationCopy.GetStationID() << ")"; - L1MASSERT(0, inStationCopy.GetInitController().IsFinalized(), aStream.str().c_str()); + << static_cast<int>(inStationCopy.GetDetectorID()) << ", stationID = " << inStationCopy.GetStationID() + << ")"; + L1MASSERT(0, inStationCopy.GetInitController().IsFinalized(), aStream.str().c_str()); } // insert the station in a set auto insertionResult = fStationsInfo.insert(std::move(inStationCopy)); @@ -59,8 +60,8 @@ void L1InitManager::AddStation(const L1BaseStationInfo& inStation) { std::stringstream aStream; aStream << "Attempt to add a dublicating station info object (detectorID = " - << static_cast<int>(inStationCopy.GetDetectorID()) - << ", stationID = " << inStationCopy.GetStationID() << ")"; + << static_cast<int>(inStationCopy.GetDetectorID()) << ", stationID = " << inStationCopy.GetStationID() + << ")"; L1MASSERT(0, insertionResult.second, aStream.str().c_str()); } } @@ -98,12 +99,13 @@ void L1InitManager::InitTargetField(double zStep) } // Check for field function - L1MASSERT(0, fInitController.GetFlag(InitKey::keFieldFunction), + L1MASSERT(0, fInitController.GetFlag(InitKey::keFieldFunction), "Attempt to initialze the field value and field region near target before initializing field function"); // Check for target defined - L1MASSERT(0, fInitController.GetFlag(InitKey::keTargetPos), - "Attempt to initialize the field value and field region near target before the target position initialization"); + L1MASSERT( + 0, fInitController.GetFlag(InitKey::keTargetPos), + "Attempt to initialize the field value and field region near target before the target position initialization"); constexpr int nDimensions {3}; constexpr int nPointsNodal {3}; @@ -150,7 +152,7 @@ void L1InitManager::PrintStations(int verbosityLevel) const void L1InitManager::PushBackCAIteration(const L1CAIteration& iteration) { // TODO: probably some checks must be inserted here (S.Zharko) - L1MASSERT(0, fInitController.GetFlag(InitKey::keCAIterationsNumberCrosscheck), + L1MASSERT(0, fInitController.GetFlag(InitKey::keCAIterationsNumberCrosscheck), "Attempt to push back a CA track finder iteration before the number of iterations was defined"); L1Vector<L1CAIteration>& iterationsContainer = fpParameters->CAIterationsContainer(); @@ -308,16 +310,15 @@ void L1InitManager::CheckStationsInfoInit() } } // loop over active detectors: end L1MASSERT(0, ifInitPassed, "Station info initialization failed"); - + // // 2) Check for maximum allowed number of stations // int nStationsTotal = GetStationsNumber(); if (nStationsTotal > L1Parameters::kMaxNstations) { std::stringstream aStream; - aStream << "Actual total number of registered stations (" << nStationsTotal - << ") is larger then designed one (" << L1Parameters::kMaxNstations - << "). Please, select another set of active tracking detectors"; + aStream << "Actual total number of registered stations (" << nStationsTotal << ") is larger then designed one (" + << L1Parameters::kMaxNstations << "). Please, select another set of active tracking detectors"; // TODO: We have to provide an instruction of how to increase the kMaxNstations // number keeping the code consistent (S.Zharko) ifInitPassed = false; -- GitLab