From 35e305937fb28ed8a8e0214f9fb689fdeb612161 Mon Sep 17 00:00:00 2001 From: AAAlvesJr <aalvesju@gmail.com> Date: Fri, 4 Dec 2020 14:15:45 +0100 Subject: [PATCH] [refactory-2020] stack implementations: more cleaning up. Moving implemententations to inl. SecondaryView.hpp --- .../detail/framework/stack/CombinedStack.inl | 131 +--- .../detail/framework/stack/SecondaryView.inl | 649 +++++------------- corsika/framework/stack/CombinedStack.hpp | 48 +- corsika/framework/stack/SecondaryView.hpp | 150 +--- 4 files changed, 247 insertions(+), 731 deletions(-) diff --git a/corsika/detail/framework/stack/CombinedStack.inl b/corsika/detail/framework/stack/CombinedStack.inl index f109f67ce..400684153 100644 --- a/corsika/detail/framework/stack/CombinedStack.inl +++ b/corsika/detail/framework/stack/CombinedStack.inl @@ -16,114 +16,56 @@ namespace corsika { - /** - * CombinedParticleInterface can be used to combine the data of several StackData - * objects. - * - * You may combine two StackData object, see class CombinedStackImpl - * below, into one Stack, using a combined StackIterator (aka - * CombinedParticleInterface) interface class. - * - * This allows to add specific information to a given Stack, could - * be special information on a subset of entries - * (e.g. NuclearStackExtension) or also (multi) thinning weights for - * all particles. - * - * Many Stacks can be combined into more complex object. - * - * The two sub-stacks must both provide their independent - * ParticleInterface classes. - * - */ - template <template <typename> typename TParticleInterfaceA, - template <typename> class TParticleInterfaceB, typename TStackIterator> - struct CombinedParticleInterface - : public TParticleInterfaceB<TParticleInterfaceA<TStackIterator>> { - - typedef CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, - TStackIterator> - pi_c_type; - typedef TParticleInterfaceA<TStackIterator> pi_a_type; - typedef TParticleInterfaceB<TParticleInterfaceA<TStackIterator>> pi_b_type; - - protected: - using pi_b_type::getIndex; // choose B, A would also work - using pi_b_type::getStackData; // choose B, A would also work - - public: - /** - * @name wrapper for user functions - * @{ - * - * In this set of functions we call the user-provide - * TParticleInterface setParticleData(...) methods, either with - * parent particle reference, or w/o. - * - * There is one implicit assumption here: if only one data tuple - * is provided for setParticleData, the data is passed on to - * TParticleInterfaceA and the TParticleInterfaceB is - * default-initialized. There are many occasions where this is the - * desired behaviour, e.g. for thinning etc. - * - */ - + template <template <typename> class TParticleInterfaceA, + template <typename> class TParticleInterfaceB, typename TStackIterator> template <typename... TArgs1> - void setParticleData(std::tuple<TArgs1...> const vA) { + void CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, TStackIterator>::setParticleData(std::tuple<TArgs1...> const vA) { pi_a_type::setParticleData(vA); pi_b_type::setParticleData(); } + + template <template <typename> class TParticleInterfaceA, + template <typename> class TParticleInterfaceB, typename TStackIterator> template <typename... TArgs1, typename... TArgs2> - void setParticleData(std::tuple<TArgs1...> const vA, std::tuple<TArgs2...> const vB) { + void CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, TStackIterator>::setParticleData(std::tuple<TArgs1...> const vA, std::tuple<TArgs2...> const vB) { pi_a_type::setParticleData(vA); pi_b_type::setParticleData(vB); } + template <template <typename> class TParticleInterfaceA, + template <typename> class TParticleInterfaceB, typename TStackIterator> template <typename... TArgs1> - void setParticleData(pi_a_type& p, std::tuple<TArgs1...> const vA) { + void CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, TStackIterator>::setParticleData(pi_a_type& p, std::tuple<TArgs1...> const vA) { // static_assert(MT<I>::has_not, "error"); pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA); // original stack pi_b_type::setParticleData(static_cast<pi_b_type&>(p)); // addon stack } + + template <template <typename> class TParticleInterfaceA, + template <typename> class TParticleInterfaceB,typename TStackIterator> template <typename... TArgs1, typename... TArgs2> - void setParticleData(pi_c_type& p, std::tuple<TArgs1...> const vA, + void CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, TStackIterator>::setParticleData(pi_c_type& p, std::tuple<TArgs1...> const vA, std::tuple<TArgs2...> const vB) { pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA); pi_b_type::setParticleData(static_cast<pi_b_type&>(p), vB); } + ///@} - std::string as_string() const { + template <template <typename> class TParticleInterfaceA, + template <typename> class TParticleInterfaceB, typename TStackIterator> + std::string CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, TStackIterator>::as_string() const { return fmt::format("[[{}][{}]]", pi_a_type::as_string(), pi_b_type::as_string()); } - protected: - }; - - /** - * @class CombinedStackImpl - * - * Memory implementation of a combined data stack. - * - * The two stack data user objects Stack1Impl and Stack2Impl are - * merged into one consistent Stack container object providing - * access to the combined number of data entries. - */ - template <typename Stack1Impl, typename Stack2Impl> - class CombinedStackImpl : public Stack1Impl, public Stack2Impl { - - public: - void clear() { + + template <typename Stack1Impl, typename Stack2Impl> + void CombinedStackImpl< Stack1Impl, Stack2Impl>::clear() { Stack1Impl::clear(); Stack2Impl::clear(); } - - unsigned int getSize() const { return Stack1Impl::getSize(); } - unsigned int getCapacity() const { return Stack1Impl::getCapacity(); } - - /** - * Function to copy particle at location i1 in stack to i2 - */ - void copy(const unsigned int i1, const unsigned int i2) { + template <typename Stack1Impl, typename Stack2Impl> + void CombinedStackImpl< Stack1Impl, Stack2Impl>::copy(const unsigned int i1, const unsigned int i2) { if (i1 >= getSize() || i2 >= getSize()) { std::ostringstream err; err << "CombinedStack: trying to access data beyond size of stack!"; @@ -133,10 +75,8 @@ namespace corsika { Stack2Impl::copy(i1, i2); } - /** - * Function to copy particle at location i2 in stack to i1 - */ - void swap(const unsigned int i1, const unsigned int i2) { + template <typename Stack1Impl, typename Stack2Impl> + void CombinedStackImpl< Stack1Impl, Stack2Impl>::swap(const unsigned int i1, const unsigned int i2) { if (i1 >= getSize() || i2 >= getSize()) { std::ostringstream err; err << "CombinedStack: trying to access data beyond size of stack!"; @@ -146,30 +86,17 @@ namespace corsika { Stack2Impl::swap(i1, i2); } - void incrementSize() { + template <typename Stack1Impl, typename Stack2Impl> + void CombinedStackImpl< Stack1Impl, Stack2Impl>::incrementSize() { Stack1Impl::incrementSize(); Stack2Impl::incrementSize(); } - void decrementSize() { + template <typename Stack1Impl, typename Stack2Impl> + void CombinedStackImpl< Stack1Impl, Stack2Impl>::decrementSize() { Stack1Impl::decrementSize(); Stack2Impl::decrementSize(); } - }; // end class CombinedStackImpl - - /** - * Helper template alias `CombinedStack` to construct new combined - * stack from two stack data objects and a particle readout interface. - * - * Note that the Stack2Impl provides only /additional/ data to - * Stack1Impl. This is important (see above) since tuple data for - * initialization are forwarded to Stack1Impl (first). - */ - - template <typename Stack1Impl, typename Stack2Impl, template <typename> typename _PI> - using CombinedStack = Stack<CombinedStackImpl<Stack1Impl, Stack2Impl>, _PI>; } // namespace corsika - -//#include <corsika/detail/framework/stack/CombinedStack.inl> diff --git a/corsika/detail/framework/stack/SecondaryView.inl b/corsika/detail/framework/stack/SecondaryView.inl index 576f6406d..a21c8b2d0 100644 --- a/corsika/detail/framework/stack/SecondaryView.inl +++ b/corsika/detail/framework/stack/SecondaryView.inl @@ -14,521 +14,214 @@ #include <vector> namespace corsika { - - // forward-decl: - template <class T1, template <class> class T2> - class DefaultSecondaryProducer; - - /** - * @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, e.g. - - This allows to write code like - \verbatim - 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 - - All operations possible on a Stack object are also possible on a - SecondaryView object. This means you can add, delete, copy, swap, - iterate, etc. - - *Further information about implementation (for developers):* All - data is stored in the original stack privided at construction - time. The secondary particle (view) indices are stored in an - extra std::vector of SecondaryView class 'indices_' referring to - the original stack slot indices. The index of the primary - projectle particle is also explicitly stored in - 'projectile_index_'. StackIterator indices - 'i = StackIterator::getIndex()' are referring to those numbers, - where 'i==0' refers to the 'projectile_index_', and - 'StackIterator::getIndex()>0' to 'indices_[i-1]', see function - getIndexFromIterator. - */ - - template <typename TStackDataType, template <typename> typename TParticleInterface, - template <typename T1, template <class> class T2> class MSecondaryProducer = - DefaultSecondaryProducer> - class SecondaryView : public Stack<TStackDataType&, TParticleInterface>, - public MSecondaryProducer<TStackDataType, TParticleInterface> { - - typedef SecondaryView<TStackDataType, TParticleInterface, MSecondaryProducer> - view_type; - /** - * Helper type for inside this class - */ - typedef Stack<TStackDataType&, TParticleInterface> inner_stack_reference_type; - - /** - * @name We need this "value" types with non-reference TStackData for - * the constructor of the SecondaryView class - * @{ - */ - typedef Stack<TStackDataType, TParticleInterface> inner_stack_value_type; - - public: - - typedef StackIteratorInterface<typename std::remove_reference<TStackDataType>::type, - TParticleInterface, inner_stack_value_type> - stack_value_iterator; - - typedef ConstStackIteratorInterface< - typename std::remove_reference<TStackDataType>::type, TParticleInterface, - inner_stack_value_type> - const_stack_value_iterator; - /// @} - - typedef StackIteratorInterface<typename std::remove_reference<TStackDataType>::type, - TParticleInterface, view_type> stack_view_iterator; - - typedef ConstStackIteratorInterface< - typename std::remove_reference<TStackDataType>::type, TParticleInterface, - view_type> - const_stack_view_iterator; - - /** - * this is the full type of the declared TParticleInterface: - */ - using ParticleType = stack_view_iterator; - using ParticleInterfaceType = typename stack_view_iterator::particle_interface_type; - - /** - * This is not accessible, since we don't want to allow creating a - * new stack. - */ - - template <typename... TArgs> - SecondaryView(TArgs... args) = delete; - SecondaryView() = delete; - - /** - SecondaryView can only be constructed passing it a valid - stack_view_iterator to another Stack object (here: lvalue) - **/ - SecondaryView(stack_value_iterator& particle) - : Stack<TStackDataType&, TParticleInterface>(particle.getStackData()) - , MSecondaryProducer<TStackDataType, TParticleInterface>{particle} - , inner_stack_(particle.getStack()) - , projectile_index_(particle.getIndex()) { - CORSIKA_LOG_TRACE("SecondaryView::SecondaryView(particle&)"); - } - /** - SecondaryView can only be constructed passing it a valid - stack_view_iterator to another Stack object (here: rvalue) - **/ - SecondaryView(stack_value_iterator&& particle) - : Stack<TStackDataType&, TParticleInterface>(particle.getStackData()) - , MSecondaryProducer<TStackDataType, TParticleInterface>{particle} - , inner_stack_(particle.getStack()) - , projectile_index_(particle.getIndex()) { - CORSIKA_LOG_TRACE("SecondaryView::SecondaryView(particle&&)"); - } - /** - * Also allow to create a new View from a Projectile (stack_view_iterator on View) - * - * Note, the view generated this way will be equivalent to the orignal view in - * terms of reference to the underlying data stack. It is not a "view to a view". - */ - SecondaryView(view_type& view, stack_view_iterator& projectile) - - : Stack<TStackDataType&, TParticleInterface>{view.getStackData()} - , MSecondaryProducer<TStackDataType, TParticleInterface>{stack_value_iterator{ - view.inner_stack_, view.getIndexFromIterator(projectile.getIndex())}} - , inner_stack_{view.inner_stack_} - , projectile_index_{view.getIndexFromIterator(projectile.getIndex())} { - CORSIKA_LOG_TRACE("SecondaryView::SecondaryView(view, projectile)"); - } - - /** - * This returns the projectile/parent in the original Stack, where this - * SecondaryView is derived from. This projectile should not be - * used to modify the Stack! - */ - stack_value_iterator parent() - const { // todo: check if this can't be Conststack_value_iterator - return stack_value_iterator(inner_stack_, projectile_index_); - } - - /** - * This returns the projectile/parent in the original Stack, where this - * SecondaryView is derived from. This projectile should not be - * used to modify the Stack! - */ - stack_value_iterator asNewParent() const { - return stack_value_iterator(inner_stack_, projectile_index_); - } - - /** - * This return a projectile of this SecondaryView, which can be - * used to modify the SecondaryView - */ - stack_view_iterator getProjectile() { - // NOTE: 0 is special marker here for PROJECTILE, see getIndexFromIterator - return stack_view_iterator(*this, 0); - } - /** - * Method to add a new secondary particle on this SecondaryView - */ - template <typename... Args> - stack_view_iterator addSecondary(const Args... v) { +/* +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>:: + +*/ +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +template <typename... Args> +typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::stack_view_iterator +SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::addSecondary(const Args... v) { CORSIKA_LOG_TRACE("SecondaryView::addSecondary(Args&&)"); stack_view_iterator proj = getProjectile(); // make this const return addSecondary(proj, v...); } - /** - * overwrite Stack::getSize to return actual number of secondaries - */ - unsigned int getSize() const { return indices_.size(); } - unsigned int getEntries() const { - return getSize() - inner_stack_reference_type::getErased(); - } - - bool isEmpty() const { return getEntries() == 0; } - /** - * @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 - * @{ - */ - // NOTE: the "+1" is since "0" is special marker here for PROJECTILE, see - // getIndexFromIterator - stack_view_iterator begin() { - unsigned int i = 0; - for (; i < getSize(); ++i) { +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::stack_view_iterator +SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::begin() { + unsigned int i = 0; + for (; i < getSize(); ++i) { - if (!isErased(i)) break; - } - return stack_view_iterator(*this, i + 1); + if (!isErased(i)) break; + } + return stack_view_iterator(*this, i + 1); } - auto end() { return stack_view_iterator(*this, getSize() + 1); } +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::const_stack_view_iterator +SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::begin() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isErased(i)) break; + } - auto last() { - unsigned int i = 0; - for (; i < getSize(); ++i) { - if (!isErased(getSize() - 1 - i)) break; - } - return stack_view_iterator(*this, getSize() - 1 - i + 1); + return const_stack_view_iterator(*this, i + 1); } - auto begin() const { - unsigned int i = 0; - for (; i < getSize(); ++i) { - if (!isErased(i)) break; - } - return const_stack_view_iterator(*this, i + 1); - } +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::const_stack_view_iterator +SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::cbegin() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isErased(i)) break; + } - auto end() const { return const_stack_view_iterator(*this, getSize() + 1); } - auto last() const { - unsigned int i = 0; - for (; i < getSize(); ++i) { - - if (!isErased(getSize() - 1 - i)) break; - } - return const_stack_view_iterator(*this, getSize() - 1 - i + 1); + return const_stack_view_iterator(*this, i + 1); } - auto cbegin() const { - unsigned int i = 0; - for (; i < getSize(); ++i) { - - if (!isErased(i)) break; - } - return const_stack_view_iterator(*this, i + 1); +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::stack_view_iterator +SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::last() { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isErased(getSize() - 1 - i)) break; + } + return stack_view_iterator(*this, getSize() - 1 - i + 1); } - - auto cend() const { return const_stack_view_iterator(*this, getSize()); } - - auto clast() const { - unsigned int i = 0; - for (; i < getSize(); ++i) { - - if (!isErased(getSize() - 1 - i)) break; - } - return const_stack_view_iterator(*this, getSize() - 1 - i + 1); +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::const_stack_view_iterator +SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::last() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isErased(getSize() - 1 - i)) break; + } + return stack_view_iterator(*this, getSize() - 1 - i + 1); } - stack_view_iterator at(unsigned int i) { return stack_view_iterator(*this, i); } - - const_stack_view_iterator at(unsigned int i) const { - return const_stack_view_iterator(*this, i); +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::const_stack_view_iterator +SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::last() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isErased(getSize() - 1 - i)) break; + } + return stack_view_iterator(*this, getSize() - 1 - i + 1); } - stack_view_iterator first() { return stack_view_iterator{*this, 0}; } +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::const_stack_view_iterator +SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::clast() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { - const_stack_view_iterator cfirst() const { - return const_stack_view_iterator{*this, 0}; + if (!isErased(getSize() - 1 - i)) break; } - /// @} - - void swap(stack_view_iterator a, stack_view_iterator b) { - - CORSIKA_LOG_TRACE("View::swap"); - inner_stack_.swap(getIndexFromIterator(a.getIndex()), - getIndexFromIterator(b.getIndex())); + return const_stack_view_iterator(*this, getSize() - 1 - i + 1); } - void copy(stack_view_iterator a, stack_view_iterator b) { - CORSIKA_LOG_TRACE("View::copy"); - inner_stack_.copy(getIndexFromIterator(a.getIndex()), - getIndexFromIterator(b.getIndex())); - } - void copy(const_stack_view_iterator a, stack_view_iterator b) { - CORSIKA_LOG_TRACE("View::copy"); - inner_stack_.copy(getIndexFromIterator(a.getIndex()), - getIndexFromIterator(b.getIndex())); - } +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +void SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::swap(stack_view_iterator a, stack_view_iterator b) { - /** - * need overwrite Stack::Delete, since we want to call - * SecondaryView::DeleteLast - * - * The particle is deleted on the underlying (internal) stack. The - * local references in SecondaryView in indices_ must be fixed, - * too. The approach is to a) check if the particle 'p' is at the - * very end of the internal stack, b) if not: move it there by - * copying the last particle to the current particle location, c) - * remove the last particle. - * - */ - void erase(stack_view_iterator p) { - - CORSIKA_LOG_TRACE("SecondaryView::Delete"); - if (isEmpty()) { /*error*/ - throw std::runtime_error("Stack, cannot delete entry since size is zero"); - } - if (isErased(p.getIndex() - 1)) { /*error*/ - throw std::runtime_error("Stack, cannot delete entry since already deleted"); - } - inner_stack_.erase(getIndexFromIterator(p.getIndex())); - inner_stack_reference_type::nDeleted_++; // also count in SecondaryView - } - - /** - * return next particle from stack, need to overwrtie Stack::getNextParticle to get - * right reference - */ - stack_view_iterator getNextParticle() { - while (purgeLastIfDeleted()) {} - return last(); - } - - /** - * check if this particle was already deleted - * - * need to re-implement for SecondaryView since stack_view_iterator types are a bit - * different - */ - bool isErased(const stack_view_iterator& p) const { - return isErased(p.getIndex() - 1); - } - - bool isErased(const const_stack_view_iterator& p) const { - return isErased(p.getIndex() - 1); - } - /** - * delete this particle - */ - bool isErased(const ParticleInterfaceType& p) const { - return isErased(p.getIterator()); + CORSIKA_LOG_TRACE("View::swap"); + inner_stack_.swap(getIndexFromIterator(a.getIndex()), + getIndexFromIterator(b.getIndex())); } - bool isDeleted(const const_stack_view_iterator& p) const { - return isDeleted(p.getIndex() - 1); - } - /** - * Function to ultimatively remove the last entry from the stack, - * if it was marked as deleted before. If this is not the case, - * the function will just return false and do nothing. - */ - bool purgeLastIfDeleted() { - CORSIKA_LOG_TRACE("SecondaryView::purgeLastIfDeleted"); - if (!isErased(getSize() - 1)) - return false; // the last particle is not marked for deletion. Do nothing. - inner_stack_.purge(getIndexFromIterator(getSize())); - inner_stack_reference_type::nDeleted_--; - indices_.pop_back(); - return true; - } +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +void SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::copy(stack_view_iterator a, stack_view_iterator b) { - /** - * Function to ultimatively remove all entries from the stack - * marked as deleted. - * - * Careful: this will re-order the entries on the stack, since - * "gaps" in the stack are filled with entries from the back - * (copied). - */ - void purge() { - unsigned int iStack = 0; - unsigned int size = getSize(); - while (iStack < size) { - - if (isErased(iStack)) { - inner_stack_.purge(iStack); - indices_.erase(indices_.begin() + iStack); - } - size = getSize(); - iStack++; - } - inner_stack_reference_type::nDeleted_ = 0; - } - std::string as_string() const { - std::string str(fmt::format("size {}\n", getSize())); - // we make our own begin/end since we want ALL entries - std::string new_line = " "; - for (unsigned int iPart = 0; iPart != getSize(); ++iPart) { - const_stack_view_iterator itPart(*this, iPart); - str += fmt::format( - "{}{}{}", new_line, itPart.as_string(), - (inner_stack_.deleted_[getIndexFromIterator(itPart.getIndex())] ? " [deleted]" - : "")); - new_line = "\n "; - } - return str; - } + CORSIKA_LOG_TRACE("View::copy"); + inner_stack_.copy(getIndexFromIterator(a.getIndex()), + getIndexFromIterator(b.getIndex())); + } - protected: - - friend class StackIteratorInterface< - typename std::remove_reference<TStackDataType>::type, TParticleInterface, - view_type>; - - friend class ConstStackIteratorInterface< - typename std::remove_reference<TStackDataType>::type, TParticleInterface, - view_type>; - - friend class ParticleBase<stack_view_iterator>; - - /** - * Overwrite of Stack::stack_view_iterator - * - * increase stack size, create new particle at end of stack, - * related to parent particle/projectile - * - * This should only get internally called from a - * stack_view_iterator::addSecondary via ParticleBase - */ - template <typename... Args> - stack_view_iterator addSecondary(stack_view_iterator& proj, const Args... v) { - CORSIKA_LOG_TRACE("SecondaryView::addSecondary(stack_view_iterator&, Args&&)"); - // make space on stack - inner_stack_reference_type::getStackData().incrementSize(); - inner_stack_.deleted_.push_back(false); - // get current number of secondaries on stack - const unsigned int idSec = getSize(); - // determine index on (inner) stack where new particle will be located - const unsigned int index = inner_stack_reference_type::getStackData().getSize() - 1; - indices_.push_back(index); - // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see - // getIndexFromIterator - auto sec = stack_view_iterator(*this, idSec + 1, proj, v...); - MSecondaryProducer<TStackDataType, TParticleInterface>::new_secondary(sec); - return sec; - } +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +void SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::copy(const_stack_view_iterator a, stack_view_iterator b) { - // forward to inner stack - // this also checks the allowed bounds of 'i' - bool isErased(unsigned int i) const { - if (i >= indices_.size()) return false; - return inner_stack_.isErased(getIndexFromIterator(i + 1)); + CORSIKA_LOG_TRACE("View::copy"); + inner_stack_.copy(getIndexFromIterator(a.getIndex()), + getIndexFromIterator(b.getIndex())); } - /** - * We only want to 'see' secondaries indexed in indices_. In this - * function the conversion form iterator-index to stack-index is - * performed. - */ - unsigned int getIndexFromIterator(const unsigned int vI) const { - // this is too much: CORSIKA_LOG_TRACE("SecondaryView::getIndexFromIterator({})={}", - // vI, (vI?indices_[vI-1]:projectile_index_)); - if (vI == 0) return projectile_index_; - return indices_[vI - 1]; - } +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +void SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::erase(stack_view_iterator p) { - private: - inner_stack_value_type& inner_stack_; - unsigned int projectile_index_; - std::vector<unsigned int> indices_; - }; - - - /** - * Class to handle the generation of new secondaries. Used as default mix-in for - * SecondaryView. - */ - template <class T1, template <class> class T2> - class DefaultSecondaryProducer { - using View = SecondaryView<T1, T2, DefaultSecondaryProducer>; - - public: - static bool constexpr has_event{false}; - - /** - * Method is called after a new secondary has been created on the - * SecondaryView. Extra logic can be introduced here. - * - * The input Particle is the new secondary that was produced and - * is of course a reference into the SecondaryView itself. - */ - template <typename Particle> - auto new_secondary(Particle&&) const { - CORSIKA_LOG_TRACE("DefaultSecondaryProducer::new_secondary(Particle&&)"); - } + CORSIKA_LOG_TRACE("SecondaryView::Delete"); + if (isEmpty()) { /*error*/ + throw std::runtime_error("Stack, cannot delete entry since size is zero"); + } + if (isErased(p.getIndex() - 1)) { /*error*/ + throw std::runtime_error("Stack, cannot delete entry since already deleted"); + } + inner_stack_.erase(getIndexFromIterator(p.getIndex())); + inner_stack_reference_type::nDeleted_++; // also count in SecondaryView + } + +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +bool SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::purgeLastIfDeleted() { + CORSIKA_LOG_TRACE("SecondaryView::purgeLastIfDeleted"); + if (!isErased(getSize() - 1)) + return false; // the last particle is not marked for deletion. Do nothing. + inner_stack_.purge(getIndexFromIterator(getSize())); + inner_stack_reference_type::nDeleted_--; + indices_.pop_back(); + return true; + } + +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +void SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::purge() { + unsigned int iStack = 0; + unsigned int size = getSize(); + while (iStack < size) { - /** - * Method is called when a new SecondaryView is being created - * created. Extra logic can be introduced here. - * - * The input Particle is a reference object into the original - * parent stack! It is not a reference into the SecondaryView - * itself. - */ - template <typename Particle> - DefaultSecondaryProducer(Particle const&) { - - CORSIKA_LOG_TRACE("DefaultSecondaryProducer::DefaultSecondaryProducer(Particle&)"); - } - }; - - /* - See Issue 161 - - unfortunately clang does not support this in the same way (yet) as - gcc, so we have to distinguish here. If clang cataches up, we - could remove the #if here and elsewhere. The gcc code is much more - generic and universal. - */ -#if not defined(__clang__) && defined(__GNUC__) || defined(__GNUG__) - template <typename TStack, - - template <class TStack_, template <class> class pi_type_> - class MSecondaryProducer = corsika::DefaultSecondaryProducer, - template <typename> typename pi_type_ = TStack::template pi_type> - struct MakeView { - using type = corsika::SecondaryView<typename TStack::stack_implementation_type, - pi_type_, MSecondaryProducer>; - }; -#endif + if (isErased(iStack)) { + inner_stack_.purge(iStack); + indices_.erase(indices_.begin() + iStack); + } + size = getSize(); + iStack++; + } + inner_stack_reference_type::nDeleted_ = 0; + } + +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +std::string SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::as_string() const { + std::string str(fmt::format("size {}\n", getSize())); + // we make our own begin/end since we want ALL entries + std::string new_line = " "; + for (unsigned int iPart = 0; iPart != getSize(); ++iPart) { + const_stack_view_iterator itPart(*this, iPart); + str += fmt::format( + "{}{}{}", new_line, itPart.as_string(), + (inner_stack_.deleted_[getIndexFromIterator(itPart.getIndex())] ? " [deleted]" + : "")); + new_line = "\n "; + } + return str; + } + +template <typename TStackDataType, template <typename> typename TParticleInterface, + template <typename T1, template <class> class T2> class MSecondaryProducer> +template <typename... Args> +typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::stack_view_iterator +SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::addSecondary(stack_view_iterator& proj, const Args... v) { + CORSIKA_LOG_TRACE("SecondaryView::addSecondary(stack_view_iterator&, Args&&)"); + // make space on stack + inner_stack_reference_type::getStackData().incrementSize(); + inner_stack_.deleted_.push_back(false); + // get current number of secondaries on stack + const unsigned int idSec = getSize(); + // determine index on (inner) stack where new particle will be located + const unsigned int index = inner_stack_reference_type::getStackData().getSize() - 1; + indices_.push_back(index); + // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see + // getIndexFromIterator + auto sec = stack_view_iterator(*this, idSec + 1, proj, v...); + MSecondaryProducer<TStackDataType, TParticleInterface>::new_secondary(sec); + return sec; + } } // namespace corsika - -//#include <corsika/detail/framework/stack/SecondaryView.inl> diff --git a/corsika/framework/stack/CombinedStack.hpp b/corsika/framework/stack/CombinedStack.hpp index 0df3532f4..da77f01d1 100644 --- a/corsika/framework/stack/CombinedStack.hpp +++ b/corsika/framework/stack/CombinedStack.hpp @@ -67,34 +67,37 @@ namespace corsika { */ template <typename... TArgs1> - void setParticleData(std::tuple<TArgs1...> const vA) { + void setParticleData(std::tuple<TArgs1...> const vA); + /* { pi_a_type::setParticleData(vA); pi_b_type::setParticleData(); - } + }*/ + template <typename... TArgs1, typename... TArgs2> - void setParticleData(std::tuple<TArgs1...> const vA, std::tuple<TArgs2...> const vB) { + void setParticleData(std::tuple<TArgs1...> const vA, std::tuple<TArgs2...> const vB); /*{ pi_a_type::setParticleData(vA); pi_b_type::setParticleData(vB); - } + }*/ template <typename... TArgs1> - void setParticleData(pi_a_type& p, std::tuple<TArgs1...> const vA) { + void setParticleData(pi_a_type& p, std::tuple<TArgs1...> const vA);/* { // static_assert(MT<I>::has_not, "error"); pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA); // original stack pi_b_type::setParticleData(static_cast<pi_b_type&>(p)); // addon stack - } + }*/ + template <typename... TArgs1, typename... TArgs2> void setParticleData(pi_c_type& p, std::tuple<TArgs1...> const vA, - std::tuple<TArgs2...> const vB) { + std::tuple<TArgs2...> const vB);/* { pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA); pi_b_type::setParticleData(static_cast<pi_b_type&>(p), vB); - } + }*/ ///@} - std::string as_string() const { + std::string as_string() const;/* { return fmt::format("[[{}][{}]]", pi_a_type::as_string(), pi_b_type::as_string()); - } + }*/ private: protected: @@ -110,13 +113,14 @@ namespace corsika { * access to the combined number of data entries. */ template <typename Stack1Impl, typename Stack2Impl> - class CombinedStackImpl : public Stack1Impl, public Stack2Impl { + struct CombinedStackImpl : public Stack1Impl, public Stack2Impl { public: - void clear() { + + void clear();/* { Stack1Impl::clear(); Stack2Impl::clear(); - } + }*/ unsigned int getSize() const { return Stack1Impl::getSize(); } unsigned int getCapacity() const { return Stack1Impl::getCapacity(); } @@ -124,7 +128,7 @@ namespace corsika { /** * Function to copy particle at location i1 in stack to i2 */ - void copy(const unsigned int i1, const unsigned int i2) { + void copy(const unsigned int i1, const unsigned int i2);/* { if (i1 >= getSize() || i2 >= getSize()) { std::ostringstream err; err << "CombinedStack: trying to access data beyond size of stack!"; @@ -132,12 +136,12 @@ namespace corsika { } Stack1Impl::copy(i1, i2); Stack2Impl::copy(i1, i2); - } + }*/ /** * Function to copy particle at location i2 in stack to i1 */ - void swap(const unsigned int i1, const unsigned int i2) { + void swap(const unsigned int i1, const unsigned int i2);/* { if (i1 >= getSize() || i2 >= getSize()) { std::ostringstream err; err << "CombinedStack: trying to access data beyond size of stack!"; @@ -145,17 +149,17 @@ namespace corsika { } Stack1Impl::swap(i1, i2); Stack2Impl::swap(i1, i2); - } + }*/ - void incrementSize() { + void incrementSize();/* { Stack1Impl::incrementSize(); Stack2Impl::incrementSize(); - } + }*/ - void decrementSize() { + void decrementSize();/* { Stack1Impl::decrementSize(); Stack2Impl::decrementSize(); - } + }*/ }; // end class CombinedStackImpl @@ -173,4 +177,4 @@ namespace corsika { } // namespace corsika -//#include <corsika/detail/framework/stack/CombinedStack.inl> +#include <corsika/detail/framework/stack/CombinedStack.inl> diff --git a/corsika/framework/stack/SecondaryView.hpp b/corsika/framework/stack/SecondaryView.hpp index 79abc168f..45369e0e9 100644 --- a/corsika/framework/stack/SecondaryView.hpp +++ b/corsika/framework/stack/SecondaryView.hpp @@ -200,11 +200,8 @@ namespace corsika { * Method to add a new secondary particle on this SecondaryView */ template <typename... Args> - stack_view_iterator addSecondary(const Args... v) { - CORSIKA_LOG_TRACE("SecondaryView::addSecondary(Args&&)"); - stack_view_iterator proj = getProjectile(); // make this const - return addSecondary(proj, v...); - } + stack_view_iterator addSecondary(const Args... v); + /** * overwrite Stack::getSize to return actual number of secondaries */ @@ -224,60 +221,23 @@ namespace corsika { */ // NOTE: the "+1" is since "0" is special marker here for PROJECTILE, see // getIndexFromIterator - stack_view_iterator begin() { - unsigned int i = 0; - for (; i < getSize(); ++i) { - if (!isErased(i)) break; - } - return stack_view_iterator(*this, i + 1); - } + stack_view_iterator begin(); - auto end() { return stack_view_iterator(*this, getSize() + 1); } - - auto last() { - unsigned int i = 0; - for (; i < getSize(); ++i) { - if (!isErased(getSize() - 1 - i)) break; - } - return stack_view_iterator(*this, getSize() - 1 - i + 1); - } + stack_view_iterator end() { return stack_view_iterator(*this, getSize() + 1); } - auto begin() const { - unsigned int i = 0; - for (; i < getSize(); ++i) { - if (!isErased(i)) break; - } + stack_view_iterator last(); - return const_stack_view_iterator(*this, i + 1); - } + const_stack_view_iterator begin() const ; - auto end() const { return const_stack_view_iterator(*this, getSize() + 1); } + const_stack_view_iterator end() const { return const_stack_view_iterator(*this, getSize() + 1); } - auto last() const { - unsigned int i = 0; - for (; i < getSize(); ++i) { - if (!isErased(getSize() - 1 - i)) break; - } - return const_stack_view_iterator(*this, getSize() - 1 - i + 1); - } + const_stack_view_iterator last() const; - auto cbegin() const { - unsigned int i = 0; - for (; i < getSize(); ++i) { - if (!isErased(i)) break; - } - return const_stack_view_iterator(*this, i + 1); - } + const_stack_view_iterator cbegin() const; auto cend() const { return const_stack_view_iterator(*this, getSize()); } - auto clast() const { - unsigned int i = 0; - for (; i < getSize(); ++i) { - if (!isErased(getSize() - 1 - i)) break; - } - return const_stack_view_iterator(*this, getSize() - 1 - i + 1); - } + const_stack_view_iterator clast() const; stack_view_iterator at(unsigned int i) { return stack_view_iterator(*this, i); } @@ -292,21 +252,11 @@ namespace corsika { } /// @} - void swap(stack_view_iterator a, stack_view_iterator b) { - CORSIKA_LOG_TRACE("View::swap"); - inner_stack_.swap(getIndexFromIterator(a.getIndex()), - getIndexFromIterator(b.getIndex())); - } - void copy(stack_view_iterator a, stack_view_iterator b) { - CORSIKA_LOG_TRACE("View::copy"); - inner_stack_.copy(getIndexFromIterator(a.getIndex()), - getIndexFromIterator(b.getIndex())); - } - void copy(const_stack_view_iterator a, stack_view_iterator b) { - CORSIKA_LOG_TRACE("View::copy"); - inner_stack_.copy(getIndexFromIterator(a.getIndex()), - getIndexFromIterator(b.getIndex())); - } + void swap(stack_view_iterator a, stack_view_iterator b) ; + + void copy(stack_view_iterator a, stack_view_iterator b); + + void copy(const_stack_view_iterator a, stack_view_iterator b); /** * need overwrite Stack::Delete, since we want to call @@ -320,17 +270,7 @@ namespace corsika { * remove the last particle. * */ - void erase(stack_view_iterator p) { - CORSIKA_LOG_TRACE("SecondaryView::Delete"); - if (isEmpty()) { /*error*/ - throw std::runtime_error("Stack, cannot delete entry since size is zero"); - } - if (isErased(p.getIndex() - 1)) { /*error*/ - throw std::runtime_error("Stack, cannot delete entry since already deleted"); - } - inner_stack_.erase(getIndexFromIterator(p.getIndex())); - inner_stack_reference_type::nDeleted_++; // also count in SecondaryView - } + void erase(stack_view_iterator p); /** * return next particle from stack, need to overwrtie Stack::getNextParticle to get @@ -366,15 +306,7 @@ namespace corsika { * if it was marked as deleted before. If this is not the case, * the function will just return false and do nothing. */ - bool purgeLastIfDeleted() { - CORSIKA_LOG_TRACE("SecondaryView::purgeLastIfDeleted"); - if (!isErased(getSize() - 1)) - return false; // the last particle is not marked for deletion. Do nothing. - inner_stack_.purge(getIndexFromIterator(getSize())); - inner_stack_reference_type::nDeleted_--; - indices_.pop_back(); - return true; - } + bool purgeLastIfDeleted(); /** * Function to ultimatively remove all entries from the stack @@ -384,34 +316,9 @@ namespace corsika { * "gaps" in the stack are filled with entries from the back * (copied). */ - void purge() { - unsigned int iStack = 0; - unsigned int size = getSize(); - while (iStack < size) { - if (isErased(iStack)) { - inner_stack_.purge(iStack); - indices_.erase(indices_.begin() + iStack); - } - size = getSize(); - iStack++; - } - inner_stack_reference_type::nDeleted_ = 0; - } + void purge() ; - std::string as_string() const { - std::string str(fmt::format("size {}\n", getSize())); - // we make our own begin/end since we want ALL entries - std::string new_line = " "; - for (unsigned int iPart = 0; iPart != getSize(); ++iPart) { - const_stack_view_iterator itPart(*this, iPart); - str += fmt::format( - "{}{}{}", new_line, itPart.as_string(), - (inner_stack_.deleted_[getIndexFromIterator(itPart.getIndex())] ? " [deleted]" - : "")); - new_line = "\n "; - } - return str; - } + std::string as_string() const; protected: friend class StackIteratorInterface< @@ -434,22 +341,7 @@ namespace corsika { * stack_view_iterator::addSecondary via ParticleBase */ template <typename... Args> - stack_view_iterator addSecondary(stack_view_iterator& proj, const Args... v) { - CORSIKA_LOG_TRACE("SecondaryView::addSecondary(stack_view_iterator&, Args&&)"); - // make space on stack - inner_stack_reference_type::getStackData().incrementSize(); - inner_stack_.deleted_.push_back(false); - // get current number of secondaries on stack - const unsigned int idSec = getSize(); - // determine index on (inner) stack where new particle will be located - const unsigned int index = inner_stack_reference_type::getStackData().getSize() - 1; - indices_.push_back(index); - // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see - // getIndexFromIterator - auto sec = stack_view_iterator(*this, idSec + 1, proj, v...); - MSecondaryProducer<TStackDataType, TParticleInterface>::new_secondary(sec); - return sec; - } + stack_view_iterator addSecondary(stack_view_iterator& proj, const Args... v) ; // forward to inner stack // this also checks the allowed bounds of 'i' @@ -534,4 +426,4 @@ namespace corsika { } // namespace corsika -//#include <corsika/detail/framework/stack/SecondaryView.inl> +#include <corsika/detail/framework/stack/SecondaryView.inl> -- GitLab