diff --git a/Framework/StackInterface/ParticleBase.h b/Framework/StackInterface/ParticleBase.h index 823fe24827ee01e0fb34acfad70b1a03bc35195c..417ca49c63bc6a03051416219193a41ea2d4ace1 100644 --- a/Framework/StackInterface/ParticleBase.h +++ b/Framework/StackInterface/ParticleBase.h @@ -13,7 +13,6 @@ #define _include_particleBase_h_ #include <type_traits> -#include <iostream> namespace corsika::stack { @@ -92,8 +91,8 @@ namespace corsika::stack { /** @name Access to underlying stack data, these are service function for user classes. User code can only rely on GetIndex - and GetStackData to retrieve data - @{ + and GetStackData to retrieve data + @{ */ auto& GetStackData() { return GetIterator().GetStackData(); } const auto& GetStackData() const { return GetIterator().GetStackData(); } @@ -103,7 +102,7 @@ namespace corsika::stack { /** * return the index number of the underlying iterator object */ - unsigned int GetIndex() const { std::cout << "ParticleBase" << std::endl; return GetIterator().GetIndexFromIterator(); } + unsigned int GetIndex() const { return GetIterator().GetIndexFromIterator(); } ///@} }; diff --git a/Framework/StackInterface/SecondaryView.h b/Framework/StackInterface/SecondaryView.h index 4e2f22f9746fb00df07b9f82980f64f0b3923a79..29b25a1b7140c7e8fe76b3a98b8d38f3fb1daa4a 100644 --- a/Framework/StackInterface/SecondaryView.h +++ b/Framework/StackInterface/SecondaryView.h @@ -3,65 +3,86 @@ #include <corsika/stack/Stack.h> -#include <iostream> #include <algorithm> #include <vector> namespace corsika::stack { /** + * @class SecondaryView + * * SecondaryView can only be constructed by giving a valid * Projectile particle, following calls to AddSecondary will * populate the original Stack, but will be directly accessible via - * the SecondaryView - - @class StackIteratorInterface - - The StackIteratorInterface is the main interface to iterator over - particles on a stack. At the same time StackIteratorInterface is a - Particle object by itself, thus there is no difference between - type and ref_type for convenience of the physicist. + * the SecondaryView, e.g. This allows to write code like \verbatim - for (auto& p : theStack) { p.SetEnergy(newEnergy); } + auto projectileInput = mainStack.GetNextParticle(); + const unsigned int nMain = mainStack.GetSize(); + SecondaryView<StackData, ParticleInterface> mainStackView(projectileInput); + mainStackView.AddSecondary(...data...); + mainStackView.AddSecondary(...data...); + mainStackView.AddSecondary(...data...); + mainStackView.AddSecondary(...data...); + assert(mainStackView.GetSize() == 4); + assert(mainStack.GetSize() = nMain+4); \endverbatim - The template argument Stack determines the type of Stack object - the data is stored in. A pointer to the Stack object is part of - the StackIteratorInterface. In addition to Stack the iterator only knows - the index fIndex in the Stack data. + All operations possible on a Stack object are also possible on a + SecondaryView object. This means you can add, delete, copy, swap, + iterate, etc. + */ - The template argument Particles acts as a policy to provide - readout function of Particle data from the stack. The Particle - class must know how to retrieve information from the Stack data - for a particle entry at any index fIndex. + /* INTERNAL NOTE FOR DEVELOPERS The secondary particle indices are + stored in a std::vector fIndices, the index of the primary projectle + particle is explicitly stored in fProjectileIndex. StackIterator + indices are refering to those numbers, where + StackIterator::GetIndex()==0 refers to the fProjectileIndex and + StackIterator::GetIndex()>0 to fIndices[i+1], see function GetIndexFromIterator. */ - template <typename StackData, template <typename> typename ParticleInterface> - class SecondaryView : public Stack<StackData&, ParticleInterface> { + template <typename StackDataType, template <typename> typename ParticleInterface> + class SecondaryView : public Stack<StackDataType&, ParticleInterface> { + + using ViewType = SecondaryView<StackDataType, ParticleInterface>; private: /** * Helper type for inside this class */ - using InnerStackType = Stack<StackData&, ParticleInterface>; + using InnerStackType = Stack<StackDataType&, ParticleInterface>; /** * @name We need this "special" types with non-reference StackData for * the constructor of the SecondaryView class * @{ */ - using InnerStackTypeV = Stack<StackData, ParticleInterface>; - typedef StackIteratorInterface<typename std::remove_reference<StackData>::type, + using InnerStackTypeV = Stack<StackDataType, ParticleInterface>; + typedef StackIteratorInterface<typename std::remove_reference<StackDataType>::type, ParticleInterface, InnerStackTypeV> StackIteratorV; /// @} public: - friend typename InnerStackType::StackIterator; - friend typename InnerStackType::ConstStackIterator; - + using StackIterator = + StackIteratorInterface<typename std::remove_reference<StackDataType>::type, + ParticleInterface, ViewType>; + using ConstStackIterator = + ConstStackIteratorInterface<typename std::remove_reference<StackDataType>::type, + ParticleInterface, ViewType>; + + /** + * this is the full type of the declared ParticleInterface: typedef typename + */ + using ParticleType = typename StackIterator::ParticleInterfaceType; + + friend class StackIteratorInterface< + typename std::remove_reference<StackDataType>::type, ParticleInterface, ViewType>; + + friend class ConstStackIteratorInterface< + typename std::remove_reference<StackDataType>::type, ParticleInterface, ViewType>; + private: /** * This is not accessible, since we don't want to allow creating a @@ -72,65 +93,68 @@ namespace corsika::stack { public: SecondaryView(StackIteratorV& vP) - : Stack<StackData&, ParticleInterface>(vP.GetStackData()) + : Stack<StackDataType&, ParticleInterface>(vP.GetStackData()) , fProjectileIndex(vP.GetIndex()) {} auto GetProjectile() { - return typename InnerStackType::StackIterator(static_cast<InnerStackType&>(*this), - fProjectileIndex); + // NOTE: 0 is special marker here for PROJECTILE, see GetIndexFromIterator + return StackIterator(*this, 0); } template <typename... Args> auto AddSecondary(const Args... v) { InnerStackType::GetStackData().IncrementSize(); + const unsigned int idSec = GetSize(); const unsigned int index = InnerStackType::GetStackData().GetSize() - 1; fIndices.push_back(index); - typename InnerStackType::StackIterator proj = GetProjectile(); - return typename InnerStackType::StackIterator(static_cast<InnerStackType&>(*this), - index, proj, v...); + StackIterator proj = GetProjectile(); + // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see + // GetIndexFromIterator + return StackIterator(*this, idSec + 1, proj, v...); } /** * overwrite Stack::GetSize to return actual number of secondaries */ - unsigned int GetSize() const { - for (const auto& V : fIndices) std::cout << V << " " << std::endl; - return fIndices.size(); } + unsigned int GetSize() const { return fIndices.size(); } /** * @name These are functions required by std containers and std loops - * The Stack-versions must be overwritten, since here we need the correct SecondaryView::GetSize + * The Stack-versions must be overwritten, since here we need the correct + * SecondaryView::GetSize * @{ */ - auto begin() { return typename InnerStackType::StackIterator(*this, 0); } - auto end() { return typename InnerStackType::StackIterator(*this, GetSize()); } - auto last() { return typename InnerStackType::StackIterator(*this, GetSize() - 1); } - - auto begin() const { return typename InnerStackType::ConstStackIterator(*this, 0); } - auto end() const { return typename InnerStackType::ConstStackIterator(*this, GetSize()); } - auto last() const { return typename InnerStackType::ConstStackIterator(*this, GetSize() - 1); } - - auto cbegin() const { return typename InnerStackType::ConstStackIterator(*this, 0); } - auto cend() const { return typename InnerStackType::ConstStackIterator(*this, GetSize()); } - auto clast() const { return typename InnerStackType::ConstStackIterator(*this, GetSize() - 1); } + // NOTE: the "+1" is since "0" is special marker here for PROJECTILE, see + // GetIndexFromIterator + auto begin() { return StackIterator(*this, 0 + 1); } + auto end() { return StackIterator(*this, GetSize() + 1); } + auto last() { return StackIterator(*this, GetSize() - 1 + 1); } + + auto begin() const { return ConstStackIterator(*this, 0 + 1); } + auto end() const { return ConstStackIterator(*this, GetSize() + 1); } + auto last() const { return ConstStackIterator(*this, GetSize() - 1 + 1); } + + auto cbegin() const { return ConstStackIterator(*this, 0 + 1); } + auto cend() const { return ConstStackIterator(*this, GetSize() + 1); } + auto clast() const { return ConstStackIterator(*this, GetSize() - 1 + 1); } /// @} - /** * need overwrite Stack::Delete, since we want to call SecondaryView::DeleteLast */ - void Delete(typename InnerStackType::StackIterator p) { + void Delete(StackIterator p) { if (IsEmpty()) { /* error */ throw std::runtime_error("Stack, cannot delete entry since size is zero"); } - if (p.GetIndex() < GetSize() - 1) InnerStackType::GetStackData().Copy(GetSize() - 1, p.GetIndex()); + if (p.GetIndex() < GetSize() - 1) + InnerStackType::GetStackData().Copy(GetSize() - 1, p.GetIndex()); DeleteLast(); } - + /** * need overwrite Stack::Delete, since we want to call SecondaryView::DeleteLast */ - void Delete(typename InnerStackType::ParticleType p) { Delete(p.GetIterator()); } + void Delete(ParticleType p) { Delete(p.GetIterator()); } /** * delete last particle on stack by decrementing stack size @@ -140,15 +164,21 @@ namespace corsika::stack { InnerStackType::GetStackData().DecrementSize(); } + /** + * return next particle from stack, need to overwrtie Stack::GetNextParticle to get + * right reference + */ + StackIterator GetNextParticle() { return last(); } + /** * check if there are no further particles on stack */ bool IsEmpty() { return GetSize() == 0; } - + protected: unsigned int GetIndexFromIterator(const unsigned int vI) const { - std::cout << "SecondaryView::GetIndexFromIterator " << vI << " " << fIndices[vI] << std::endl; - return fIndices[vI]; + if (vI == 0) return fProjectileIndex; + return fIndices[vI - 1]; } private: diff --git a/Framework/StackInterface/Stack.h b/Framework/StackInterface/Stack.h index e9155ff4cd93fd262c838b7bcaeb3de55da3c5fd..aba9049a086f8996d8bdf692efe9a14f437c6538 100644 --- a/Framework/StackInterface/Stack.h +++ b/Framework/StackInterface/Stack.h @@ -19,26 +19,22 @@ #include <corsika/stack/SecondaryView.h> - // SFINAE test template <typename T> -class HasGetIndexFromIterator -{ +class HasGetIndexFromIterator { private: - typedef char YesType[1]; - typedef char NoType[2]; - - template <typename C> static YesType& test( decltype(&C::GetIndexFromIterator) ) ; - template <typename C> static NoType& test(...); + typedef char YesType[1]; + typedef char NoType[2]; + template <typename C> + static YesType& test(decltype(&C::GetIndexFromIterator)); + template <typename C> + static NoType& test(...); public: - enum { value = sizeof(test<T>(0)) == sizeof(YesType) }; + enum { value = sizeof(test<T>(0)) == sizeof(YesType) }; }; - - - /** All classes around management of particles on a stack. */ @@ -117,12 +113,12 @@ namespace corsika::stack { * object. Using CRTP, this also determines the type of * ParticleInterface template class simultaneously. */ - typedef StackIteratorInterface<typename std::remove_reference<StackDataType>::type, - ParticleInterface, StackType> - StackIterator; - typedef ConstStackIteratorInterface< - typename std::remove_reference<StackDataType>::type, ParticleInterface, StackType> - ConstStackIterator; + using StackIterator = + StackIteratorInterface<typename std::remove_reference<StackDataType>::type, + ParticleInterface, StackType>; + using ConstStackIterator = + ConstStackIteratorInterface<typename std::remove_reference<StackDataType>::type, + ParticleInterface, StackType>; /** * this is the full type of the declared ParticleInterface: typedef typename @@ -136,7 +132,7 @@ namespace corsika::stack { friend class ConstStackIteratorInterface< typename std::remove_reference<StackDataType>::type, ParticleInterface, StackType>; - + public: unsigned int GetCapacity() const { return fData.GetCapacity(); } unsigned int GetSize() const { return fData.GetSize(); } @@ -232,13 +228,10 @@ namespace corsika::stack { StackIterator GetNextParticle() { return last(); } protected: - - //typename std::enable_if<HasGetIndexFromIterator<T>::value, unsigned int>::type - //typename std::enable_if<std::is_base_of<decltype(*this)>, SecondaryView<StackDataType, ParticleInterface>>::value, unsigned int>::type - unsigned int - GetIndexFromIterator(const unsigned int vI) const { - std::cout << "Stack::GetIndexFromIterator " << vI << std::endl; - return vI; } + // typename std::enable_if<HasGetIndexFromIterator<T>::value, unsigned int>::type + // typename std::enable_if<std::is_base_of<decltype(*this)>, + // SecondaryView<StackDataType, ParticleInterface>>::value, unsigned int>::type + unsigned int GetIndexFromIterator(const unsigned int vI) const { return vI; } typename std::remove_reference<StackDataType>::type& GetStackData() { return fData; } const typename std::remove_reference<StackDataType>::type& GetStackData() const { diff --git a/Framework/StackInterface/StackIteratorInterface.h b/Framework/StackInterface/StackIteratorInterface.h index 02a7a6268e664322ea554de2439958532fde8dd1..124fa158c6c0b4cb741980580c709e89bb43168b 100644 --- a/Framework/StackInterface/StackIteratorInterface.h +++ b/Framework/StackInterface/StackIteratorInterface.h @@ -14,7 +14,6 @@ #include <corsika/stack/ParticleBase.h> -#include <iostream> #include <type_traits> namespace corsika::stack { @@ -146,15 +145,17 @@ namespace corsika::stack { bool operator==(const StackIteratorInterface& rhs) { return fIndex == rhs.fIndex; } bool operator!=(const StackIteratorInterface& rhs) { return fIndex != rhs.fIndex; } - /** - * Convert iterator to value type, where value type is the user-provided particle readout class - */ + /** + * Convert iterator to value type, where value type is the user-provided particle + * readout class + */ ParticleInterfaceType& operator*() { return static_cast<ParticleInterfaceType&>(*this); } - /** - * Convert iterator to const value type, where value type is the user-provided particle readout class - */ + /** + * Convert iterator to const value type, where value type is the user-provided + * particle readout class + */ const ParticleInterfaceType& operator*() const { return static_cast<const ParticleInterfaceType&>(*this); } @@ -176,7 +177,9 @@ namespace corsika::stack { /// Get current const user particle StackDataType object inline const StackDataType& GetStackData() const { return fData->GetStackData(); } /// Get data index as mapped in Stack class - inline unsigned int GetIndexFromIterator() const { std::cout << "GetIndexFromIterator " << fIndex << " " << fData->GetIndexFromIterator(fIndex) << std::endl; return fData->GetIndexFromIterator(fIndex); } + inline unsigned int GetIndexFromIterator() const { + return fData->GetIndexFromIterator(fIndex); + } ///@} }; // end class StackIterator @@ -264,7 +267,9 @@ namespace corsika::stack { inline const StackType& GetStack() const { return *fData; } inline const StackDataType& GetStackData() const { return fData->GetStackData(); } /// Get data index as mapped in Stack class - inline unsigned int GetIndexFromIterator() const { std::cout << "GetIndexFromIterator " << fIndex << " " << fData->GetIndexFromIterator(fIndex) << std::endl; return fData->GetIndexFromIterator(fIndex); } + inline unsigned int GetIndexFromIterator() const { + return fData->GetIndexFromIterator(fIndex); + } ///@} }; // end class ConstStackIterator diff --git a/Framework/StackInterface/testStackInterface.cc b/Framework/StackInterface/testStackInterface.cc index 3094e17ae3efec73965042807ac63c7a4441afbb..293aa591463e3255aaa246f3f57ad4bf470bcab3 100644 --- a/Framework/StackInterface/testStackInterface.cc +++ b/Framework/StackInterface/testStackInterface.cc @@ -202,7 +202,12 @@ TEST_CASE("Stack", "[Stack]") { typedef SecondaryView<TestStackData, TestParticleInterface> StackTestView; StackTestView v(particle); REQUIRE(v.GetSize() == 0); - //auto proj = v.GetProjectile(); + + { + auto proj = v.GetProjectile(); + REQUIRE(proj.GetData() == particle.GetData()); + } + v.AddSecondary(4.4); v.AddSecondary(4.5); v.AddSecondary(4.6); @@ -213,11 +218,7 @@ TEST_CASE("Stack", "[Stack]") { auto sumView = [](const StackTestView& stack) { double v = 0; - for (const auto& p : stack) { - cout << " sumView " << p.GetData() << " "; - v += p.GetData(); - } - cout << endl; + for (const auto& p : stack) { v += p.GetData(); } return v; }; @@ -227,17 +228,26 @@ TEST_CASE("Stack", "[Stack]") { v.DeleteLast(); REQUIRE(v.GetSize() == 2); REQUIRE(s.GetSize() == 4); - + REQUIRE(sum(s) == sumS + 4.4 + 4.5); REQUIRE(sumView(v) == 4.4 + 4.5); - v.Delete(v.GetNextParticle()); + auto pDel = v.GetNextParticle(); + v.Delete(pDel); REQUIRE(v.GetSize() == 1); REQUIRE(s.GetSize() == 3); - + + REQUIRE(sum(s) == sumS + 4.4 + 4.5 - pDel.GetData()); + REQUIRE(sumView(v) == 4.4 + 4.5 - pDel.GetData()); + v.Delete(v.GetNextParticle()); REQUIRE(sum(s) == sumS); REQUIRE(sumView(v) == 0); REQUIRE(v.IsEmpty()); + + { + auto proj = v.GetProjectile(); + REQUIRE(proj.GetData() == particle.GetData()); + } } }