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 @@
#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(); }
///@}
};
......
......@@ -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:
......
......@@ -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 {
......
......@@ -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
......
......@@ -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());
}
}
}
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