IAP GITLAB

Skip to content
Snippets Groups Projects
Commit 3348f208 authored by ralfulrich's avatar ralfulrich
Browse files

fixed secondarystack

parent fb7d2162
No related branches found
No related tags found
1 merge request!71Resolve "Need "StackView" object"
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#define _include_particleBase_h_ #define _include_particleBase_h_
#include <type_traits> #include <type_traits>
#include <iostream>
namespace corsika::stack { namespace corsika::stack {
...@@ -92,8 +91,8 @@ namespace corsika::stack { ...@@ -92,8 +91,8 @@ namespace corsika::stack {
/** /**
@name Access to underlying stack data, these are service @name Access to underlying stack data, these are service
function for user classes. User code can only rely on GetIndex 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(); } auto& GetStackData() { return GetIterator().GetStackData(); }
const auto& GetStackData() const { return GetIterator().GetStackData(); } const auto& GetStackData() const { return GetIterator().GetStackData(); }
...@@ -103,7 +102,7 @@ namespace corsika::stack { ...@@ -103,7 +102,7 @@ namespace corsika::stack {
/** /**
* return the index number of the underlying iterator object * 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(); }
///@} ///@}
}; };
......
...@@ -3,65 +3,86 @@ ...@@ -3,65 +3,86 @@
#include <corsika/stack/Stack.h> #include <corsika/stack/Stack.h>
#include <iostream>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
namespace corsika::stack { namespace corsika::stack {
/** /**
* @class SecondaryView
*
* SecondaryView can only be constructed by giving a valid * SecondaryView can only be constructed by giving a valid
* Projectile particle, following calls to AddSecondary will * Projectile particle, following calls to AddSecondary will
* populate the original Stack, but will be directly accessible via * populate the original Stack, but will be directly accessible via
* the SecondaryView * the SecondaryView, e.g.
@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.
This allows to write code like This allows to write code like
\verbatim \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 \endverbatim
The template argument Stack determines the type of Stack object All operations possible on a Stack object are also possible on a
the data is stored in. A pointer to the Stack object is part of SecondaryView object. This means you can add, delete, copy, swap,
the StackIteratorInterface. In addition to Stack the iterator only knows iterate, etc.
the index fIndex in the Stack data. */
The template argument Particles acts as a policy to provide /* INTERNAL NOTE FOR DEVELOPERS The secondary particle indices are
readout function of Particle data from the stack. The Particle stored in a std::vector fIndices, the index of the primary projectle
class must know how to retrieve information from the Stack data particle is explicitly stored in fProjectileIndex. StackIterator
for a particle entry at any index fIndex. 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> template <typename StackDataType, template <typename> typename ParticleInterface>
class SecondaryView : public Stack<StackData&, ParticleInterface> { class SecondaryView : public Stack<StackDataType&, ParticleInterface> {
using ViewType = SecondaryView<StackDataType, ParticleInterface>;
private: private:
/** /**
* Helper type for inside this class * 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 * @name We need this "special" types with non-reference StackData for
* the constructor of the SecondaryView class * the constructor of the SecondaryView class
* @{ * @{
*/ */
using InnerStackTypeV = Stack<StackData, ParticleInterface>; using InnerStackTypeV = Stack<StackDataType, ParticleInterface>;
typedef StackIteratorInterface<typename std::remove_reference<StackData>::type, typedef StackIteratorInterface<typename std::remove_reference<StackDataType>::type,
ParticleInterface, InnerStackTypeV> ParticleInterface, InnerStackTypeV>
StackIteratorV; StackIteratorV;
/// @} /// @}
public: public:
friend typename InnerStackType::StackIterator; using StackIterator =
friend typename InnerStackType::ConstStackIterator; 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: private:
/** /**
* This is not accessible, since we don't want to allow creating a * This is not accessible, since we don't want to allow creating a
...@@ -72,65 +93,68 @@ namespace corsika::stack { ...@@ -72,65 +93,68 @@ namespace corsika::stack {
public: public:
SecondaryView(StackIteratorV& vP) SecondaryView(StackIteratorV& vP)
: Stack<StackData&, ParticleInterface>(vP.GetStackData()) : Stack<StackDataType&, ParticleInterface>(vP.GetStackData())
, fProjectileIndex(vP.GetIndex()) {} , fProjectileIndex(vP.GetIndex()) {}
auto GetProjectile() { auto GetProjectile() {
return typename InnerStackType::StackIterator(static_cast<InnerStackType&>(*this), // NOTE: 0 is special marker here for PROJECTILE, see GetIndexFromIterator
fProjectileIndex); return StackIterator(*this, 0);
} }
template <typename... Args> template <typename... Args>
auto AddSecondary(const Args... v) { auto AddSecondary(const Args... v) {
InnerStackType::GetStackData().IncrementSize(); InnerStackType::GetStackData().IncrementSize();
const unsigned int idSec = GetSize();
const unsigned int index = InnerStackType::GetStackData().GetSize() - 1; const unsigned int index = InnerStackType::GetStackData().GetSize() - 1;
fIndices.push_back(index); fIndices.push_back(index);
typename InnerStackType::StackIterator proj = GetProjectile(); StackIterator proj = GetProjectile();
return typename InnerStackType::StackIterator(static_cast<InnerStackType&>(*this), // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see
index, proj, v...); // GetIndexFromIterator
return StackIterator(*this, idSec + 1, proj, v...);
} }
/** /**
* overwrite Stack::GetSize to return actual number of secondaries * overwrite Stack::GetSize to return actual number of secondaries
*/ */
unsigned int GetSize() const { unsigned int GetSize() const { return fIndices.size(); }
for (const auto& V : fIndices) std::cout << V << " " << std::endl;
return fIndices.size(); }
/** /**
* @name These are functions required by std containers and std loops * @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); } // NOTE: the "+1" is since "0" is special marker here for PROJECTILE, see
auto end() { return typename InnerStackType::StackIterator(*this, GetSize()); } // GetIndexFromIterator
auto last() { return typename InnerStackType::StackIterator(*this, GetSize() - 1); } auto begin() { return StackIterator(*this, 0 + 1); }
auto end() { return StackIterator(*this, GetSize() + 1); }
auto begin() const { return typename InnerStackType::ConstStackIterator(*this, 0); } auto last() { return StackIterator(*this, GetSize() - 1 + 1); }
auto end() const { return typename InnerStackType::ConstStackIterator(*this, GetSize()); }
auto last() const { return typename InnerStackType::ConstStackIterator(*this, GetSize() - 1); } auto begin() const { return ConstStackIterator(*this, 0 + 1); }
auto end() const { return ConstStackIterator(*this, GetSize() + 1); }
auto cbegin() const { return typename InnerStackType::ConstStackIterator(*this, 0); } auto last() const { return ConstStackIterator(*this, GetSize() - 1 + 1); }
auto cend() const { return typename InnerStackType::ConstStackIterator(*this, GetSize()); }
auto clast() const { return typename InnerStackType::ConstStackIterator(*this, GetSize() - 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 * need overwrite Stack::Delete, since we want to call SecondaryView::DeleteLast
*/ */
void Delete(typename InnerStackType::StackIterator p) { void Delete(StackIterator p) {
if (IsEmpty()) { /* error */ if (IsEmpty()) { /* error */
throw std::runtime_error("Stack, cannot delete entry since size is zero"); 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(); DeleteLast();
} }
/** /**
* need overwrite Stack::Delete, since we want to call SecondaryView::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 * delete last particle on stack by decrementing stack size
...@@ -140,15 +164,21 @@ namespace corsika::stack { ...@@ -140,15 +164,21 @@ namespace corsika::stack {
InnerStackType::GetStackData().DecrementSize(); 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 * check if there are no further particles on stack
*/ */
bool IsEmpty() { return GetSize() == 0; } bool IsEmpty() { return GetSize() == 0; }
protected: protected:
unsigned int GetIndexFromIterator(const unsigned int vI) const { unsigned int GetIndexFromIterator(const unsigned int vI) const {
std::cout << "SecondaryView::GetIndexFromIterator " << vI << " " << fIndices[vI] << std::endl; if (vI == 0) return fProjectileIndex;
return fIndices[vI]; return fIndices[vI - 1];
} }
private: private:
......
...@@ -19,26 +19,22 @@ ...@@ -19,26 +19,22 @@
#include <corsika/stack/SecondaryView.h> #include <corsika/stack/SecondaryView.h>
// SFINAE test // SFINAE test
template <typename T> template <typename T>
class HasGetIndexFromIterator class HasGetIndexFromIterator {
{
private: private:
typedef char YesType[1]; typedef char YesType[1];
typedef char NoType[2]; typedef char NoType[2];
template <typename C> static YesType& test( decltype(&C::GetIndexFromIterator) ) ;
template <typename C> static NoType& test(...);
template <typename C>
static YesType& test(decltype(&C::GetIndexFromIterator));
template <typename C>
static NoType& test(...);
public: 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. All classes around management of particles on a stack.
*/ */
...@@ -117,12 +113,12 @@ namespace corsika::stack { ...@@ -117,12 +113,12 @@ namespace corsika::stack {
* object. Using CRTP, this also determines the type of * object. Using CRTP, this also determines the type of
* ParticleInterface template class simultaneously. * ParticleInterface template class simultaneously.
*/ */
typedef StackIteratorInterface<typename std::remove_reference<StackDataType>::type, using StackIterator =
ParticleInterface, StackType> StackIteratorInterface<typename std::remove_reference<StackDataType>::type,
StackIterator; ParticleInterface, StackType>;
typedef ConstStackIteratorInterface< using ConstStackIterator =
typename std::remove_reference<StackDataType>::type, ParticleInterface, StackType> ConstStackIteratorInterface<typename std::remove_reference<StackDataType>::type,
ConstStackIterator; ParticleInterface, StackType>;
/** /**
* this is the full type of the declared ParticleInterface: typedef typename * this is the full type of the declared ParticleInterface: typedef typename
...@@ -136,7 +132,7 @@ namespace corsika::stack { ...@@ -136,7 +132,7 @@ namespace corsika::stack {
friend class ConstStackIteratorInterface< friend class ConstStackIteratorInterface<
typename std::remove_reference<StackDataType>::type, ParticleInterface, typename std::remove_reference<StackDataType>::type, ParticleInterface,
StackType>; StackType>;
public: public:
unsigned int GetCapacity() const { return fData.GetCapacity(); } unsigned int GetCapacity() const { return fData.GetCapacity(); }
unsigned int GetSize() const { return fData.GetSize(); } unsigned int GetSize() const { return fData.GetSize(); }
...@@ -232,13 +228,10 @@ namespace corsika::stack { ...@@ -232,13 +228,10 @@ namespace corsika::stack {
StackIterator GetNextParticle() { return last(); } StackIterator GetNextParticle() { return last(); }
protected: protected:
// typename std::enable_if<HasGetIndexFromIterator<T>::value, unsigned int>::type
//typename std::enable_if<HasGetIndexFromIterator<T>::value, unsigned int>::type // typename std::enable_if<std::is_base_of<decltype(*this)>,
//typename std::enable_if<std::is_base_of<decltype(*this)>, SecondaryView<StackDataType, ParticleInterface>>::value, unsigned int>::type // SecondaryView<StackDataType, ParticleInterface>>::value, unsigned int>::type
unsigned int unsigned int GetIndexFromIterator(const unsigned int vI) const { return vI; }
GetIndexFromIterator(const unsigned int vI) const {
std::cout << "Stack::GetIndexFromIterator " << vI << std::endl;
return vI; }
typename std::remove_reference<StackDataType>::type& GetStackData() { return fData; } typename std::remove_reference<StackDataType>::type& GetStackData() { return fData; }
const typename std::remove_reference<StackDataType>::type& GetStackData() const { const typename std::remove_reference<StackDataType>::type& GetStackData() const {
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <corsika/stack/ParticleBase.h> #include <corsika/stack/ParticleBase.h>
#include <iostream>
#include <type_traits> #include <type_traits>
namespace corsika::stack { namespace corsika::stack {
...@@ -146,15 +145,17 @@ 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; }
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*() { ParticleInterfaceType& operator*() {
return static_cast<ParticleInterfaceType&>(*this); 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 { const ParticleInterfaceType& operator*() const {
return static_cast<const ParticleInterfaceType&>(*this); return static_cast<const ParticleInterfaceType&>(*this);
} }
...@@ -176,7 +177,9 @@ namespace corsika::stack { ...@@ -176,7 +177,9 @@ namespace corsika::stack {
/// Get current const user particle StackDataType object /// Get current const user particle StackDataType object
inline const StackDataType& GetStackData() const { return fData->GetStackData(); } inline const StackDataType& GetStackData() const { return fData->GetStackData(); }
/// Get data index as mapped in Stack class /// 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 }; // end class StackIterator
...@@ -264,7 +267,9 @@ namespace corsika::stack { ...@@ -264,7 +267,9 @@ namespace corsika::stack {
inline const StackType& GetStack() const { return *fData; } inline const StackType& GetStack() const { return *fData; }
inline const StackDataType& GetStackData() const { return fData->GetStackData(); } inline const StackDataType& GetStackData() const { return fData->GetStackData(); }
/// Get data index as mapped in Stack class /// 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 }; // end class ConstStackIterator
......
...@@ -202,7 +202,12 @@ TEST_CASE("Stack", "[Stack]") { ...@@ -202,7 +202,12 @@ TEST_CASE("Stack", "[Stack]") {
typedef SecondaryView<TestStackData, TestParticleInterface> StackTestView; typedef SecondaryView<TestStackData, TestParticleInterface> StackTestView;
StackTestView v(particle); StackTestView v(particle);
REQUIRE(v.GetSize() == 0); REQUIRE(v.GetSize() == 0);
//auto proj = v.GetProjectile();
{
auto proj = v.GetProjectile();
REQUIRE(proj.GetData() == particle.GetData());
}
v.AddSecondary(4.4); v.AddSecondary(4.4);
v.AddSecondary(4.5); v.AddSecondary(4.5);
v.AddSecondary(4.6); v.AddSecondary(4.6);
...@@ -213,11 +218,7 @@ TEST_CASE("Stack", "[Stack]") { ...@@ -213,11 +218,7 @@ TEST_CASE("Stack", "[Stack]") {
auto sumView = [](const StackTestView& stack) { auto sumView = [](const StackTestView& stack) {
double v = 0; double v = 0;
for (const auto& p : stack) { for (const auto& p : stack) { v += p.GetData(); }
cout << " sumView " << p.GetData() << " ";
v += p.GetData();
}
cout << endl;
return v; return v;
}; };
...@@ -227,17 +228,26 @@ TEST_CASE("Stack", "[Stack]") { ...@@ -227,17 +228,26 @@ TEST_CASE("Stack", "[Stack]") {
v.DeleteLast(); v.DeleteLast();
REQUIRE(v.GetSize() == 2); REQUIRE(v.GetSize() == 2);
REQUIRE(s.GetSize() == 4); REQUIRE(s.GetSize() == 4);
REQUIRE(sum(s) == sumS + 4.4 + 4.5); REQUIRE(sum(s) == sumS + 4.4 + 4.5);
REQUIRE(sumView(v) == 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(v.GetSize() == 1);
REQUIRE(s.GetSize() == 3); 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()); v.Delete(v.GetNextParticle());
REQUIRE(sum(s) == sumS); REQUIRE(sum(s) == sumS);
REQUIRE(sumView(v) == 0); REQUIRE(sumView(v) == 0);
REQUIRE(v.IsEmpty()); REQUIRE(v.IsEmpty());
{
auto proj = v.GetProjectile();
REQUIRE(proj.GetData() == particle.GetData());
}
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment