From a173a4bb77799fbe85a481b427f1a915487b09b9 Mon Sep 17 00:00:00 2001 From: ralfulrich <ralf.ulrich@kit.edu> Date: Mon, 28 Jan 2019 21:14:30 +0100 Subject: [PATCH] first workin version of testStackInterface --- Framework/StackInterface/ParticleBase.h | 11 +- Framework/StackInterface/Stack.h | 20 ++- Framework/StackInterface/StackIterator.h | 137 +++++++++++++++--- .../StackInterface/testStackInterface.cc | 77 ++++++---- Stack/SuperStupidStack/SuperStupidStack.h | 3 + 5 files changed, 199 insertions(+), 49 deletions(-) diff --git a/Framework/StackInterface/ParticleBase.h b/Framework/StackInterface/ParticleBase.h index 5ef6ca662..1a854a90b 100644 --- a/Framework/StackInterface/ParticleBase.h +++ b/Framework/StackInterface/ParticleBase.h @@ -31,10 +31,15 @@ namespace corsika::stack { class ParticleBase { public: - ParticleBase() {} + ParticleBase() = default; private: - ParticleBase(ParticleBase&); + ParticleBase(ParticleBase&) = delete; + ParticleBase operator=(ParticleBase&) = delete; + ParticleBase(ParticleBase&&) = delete; + ParticleBase operator=(ParticleBase&&) = delete; + ParticleBase(const ParticleBase&) = delete; + ParticleBase operator=(const ParticleBase&) = delete; public: /// delete this particle on the stack. The corresponding iterator @@ -52,6 +57,8 @@ namespace corsika::stack { /// access to underling stack data auto& GetStackData() { return GetIterator().GetStackData(); } const auto& GetStackData() const { return GetIterator().GetStackData(); } + auto& GetStack() { return GetIterator().GetStack(); } + const auto& GetStack() const { return GetIterator().GetStack(); } /// return the index number of the underlying iterator object int GetIndex() const { return GetIterator().GetIndex(); } diff --git a/Framework/StackInterface/Stack.h b/Framework/StackInterface/Stack.h index f47c15d3d..9d57b7b3c 100644 --- a/Framework/StackInterface/Stack.h +++ b/Framework/StackInterface/Stack.h @@ -14,6 +14,8 @@ #include <corsika/stack/StackIterator.h> // include here, to help application programmres +#include <stdexcept> + /** All classes around management of particles on a stack. */ @@ -35,9 +37,11 @@ namespace corsika::stack { public: typedef Stack<StackData, PI> StackType; typedef StackIteratorInterface<StackData, PI> StackIterator; - typedef const StackIterator ConstStackIterator; + typedef ConstStackIteratorInterface<StackData, PI> ConstStackIterator; + // typedef const StackIterator ConstStackIterator; typedef typename StackIterator::ParticleInterfaceType ParticleType; friend class StackIteratorInterface<StackData, PI>; + friend class ConstStackIteratorInterface<StackData, PI>; public: using StackData::GetCapacity; @@ -57,20 +61,28 @@ namespace corsika::stack { StackIterator end() { return StackIterator(*this, GetSize()); } StackIterator last() { return StackIterator(*this, GetSize() - 1); } - /// these are functions required by std containers and std loops + ConstStackIterator begin() const { return ConstStackIterator(*this, 0); } + ConstStackIterator end() const { return ConstStackIterator(*this, GetSize()); } + ConstStackIterator last() const { return ConstStackIterator(*this, GetSize() - 1); } + ConstStackIterator cbegin() const { return ConstStackIterator(*this, 0); } ConstStackIterator cend() const { return ConstStackIterator(*this, GetSize()); } ConstStackIterator clast() const { return ConstStackIterator(*this, GetSize() - 1); } /// increase stack size, create new particle at end of stack - StackIterator NewParticle() { + template <typename... Args> + StackIterator AddParticle(Args... v) { IncrementSize(); - return StackIterator(*this, GetSize() - 1); + return StackIterator(*this, GetSize() - 1, v...); + // auto p = StackIterator(*this, GetSize() - 1); + // p.SetParticleData(v...); + // return p; } void Copy(StackIterator& a, StackIterator& b) { Copy(a.GetIndex(), b.GetIndex()); } /// delete this particle void Delete(StackIterator& p) { if (GetSize() == 0) { /*error*/ + throw std::runtime_error("Stack, cannot delete entry since size is zero"); } if (p.GetIndex() < GetSize() - 1) Copy(GetSize() - 1, p.GetIndex()); DeleteLast(); diff --git a/Framework/StackInterface/StackIterator.h b/Framework/StackInterface/StackIterator.h index 47424f60d..266492094 100644 --- a/Framework/StackInterface/StackIterator.h +++ b/Framework/StackInterface/StackIterator.h @@ -14,6 +14,8 @@ #include <corsika/stack/ParticleBase.h> +#include <type_traits> + class StackData; // forward decl namespace corsika::stack { @@ -47,10 +49,15 @@ namespace corsika::stack { template <typename StackData, template <typename> typename ParticleInterface> class StackIteratorInterface - : public ParticleInterface<StackIteratorInterface<StackData, ParticleInterface> > { + : public ParticleInterface<StackIteratorInterface< + StackData /*typename std::decay<StackData>::type*/, ParticleInterface>> { typedef Stack<StackData, ParticleInterface> StackType; - typedef ParticleInterface<StackIteratorInterface<StackData, ParticleInterface> > + /*typedef + typename std::conditional<std::is_const<StackData>::value, + const Stack<const StackData, ParticleInterface>&, + Stack<StackData, ParticleInterface>&>::type StackType;*/ + typedef ParticleInterface<StackIteratorInterface<StackData, ParticleInterface>> ParticleInterfaceType; // friend class ParticleInterface<StackIterator<StackData>>; // to access GetStackData @@ -59,24 +66,33 @@ namespace corsika::stack { private: int fIndex = 0; - StackType* fData = 0; // todo is this problematic, when stacks are copied? + StackType* fData = 0; // info: Particles and StackIterators become invalid when parent + // Stack is copied or deleted! + + StackIteratorInterface() = delete; public: - // StackIterator() : fData(0), fIndex(0) { } + /* + StackIteratorInterface(const StackType& data, const int index) + : fIndex(index) + , fData(&data) {}*/ StackIteratorInterface(StackType& data, const int index) : fIndex(index) , fData(&data) {} - - private: - StackIteratorInterface(const StackIteratorInterface& mit) - : fIndex(mit.fIndex) - , fData(mit.fData) {} - - public: - StackIteratorInterface& operator=(const StackIteratorInterface& mit) { - fIndex = mit.fIndex; - fData = mit.fData; - return *this; + /* + StackIteratorInterface(StackType& data, const int index, typename + std::enable_if<!std::is_const<StackData>::value>::type* = 0) : fIndex(index) , + fData(&data) {} + + StackIteratorInterface(const StackType& data, const int index, typename + std::enable_if<std::is_const<StackData>::value>::type* = 0) : fIndex(index) , + fData(&data) {} + */ + template <typename... Args> + StackIteratorInterface(StackType& data, const int index, const Args... args) + : fIndex(index) + , fData(&data) { + (**this).SetParticleData(args...); } public: @@ -103,11 +119,96 @@ namespace corsika::stack { int GetIndex() const { return fIndex; } StackType& GetStack() { return *fData; } const StackType& GetStack() const { return *fData; } - StackData& GetStackData() { return fData->GetStackData(); } - const StackData& GetStackData() const { return fData->GetStackData(); } - + StackData& /*typename std::decay<StackData>::type&*/ GetStackData() { + return fData->GetStackData(); + } + const StackData& /*typename std::decay<StackData>::type&*/ GetStackData() const { + return fData->GetStackData(); + } }; // end class StackIterator + template <typename StackData, template <typename> typename ParticleInterface> + class ConstStackIteratorInterface + : public ParticleInterface<ConstStackIteratorInterface< + StackData /*typename std::decay<StackData>::type*/, ParticleInterface>> { + + typedef Stack<StackData, ParticleInterface> StackType; + /*typedef + typename std::conditional<std::is_const<StackData>::value, + const Stack<const StackData, ParticleInterface>&, + Stack<StackData, ParticleInterface>&>::type StackType;*/ + typedef ParticleInterface<ConstStackIteratorInterface<StackData, ParticleInterface>> + ParticleInterfaceType; + + // friend class ParticleInterface<StackIterator<StackData>>; // to access GetStackData + friend class Stack<StackData, ParticleInterface>; // for access to GetIndex + friend class ParticleBase<ConstStackIteratorInterface>; // for access to GetStackData + + private: + int fIndex = 0; + const StackType* fData = 0; // info: Particles and StackIterators become invalid when + // parent Stack is copied or deleted! + + ConstStackIteratorInterface() = delete; + + public: + // StackIteratorInterface(const StackType& data, const int index) + // : fIndex(index) + // , fData(&data) {} + ConstStackIteratorInterface(const StackType& data, const int index) + : fIndex(index) + , fData(&data) {} + /* + StackIteratorInterface(StackType& data, const int index, typename + std::enable_if<!std::is_const<StackData>::value>::type* = 0) : fIndex(index) , + fData(&data) {} + + StackIteratorInterface(const StackType& data, const int index, typename + std::enable_if<std::is_const<StackData>::value>::type* = 0) : fIndex(index) , + fData(&data) {} + */ + template <typename... Args> + ConstStackIteratorInterface(StackType data, const int index, const Args... args) + : fIndex(index) + , fData(data) { + (**this).SetParticleData(args...); + } + + public: + ConstStackIteratorInterface& operator++() { + ++fIndex; + return *this; + } + ConstStackIteratorInterface operator++(int) { + ConstStackIteratorInterface tmp(*this); + ++fIndex; + return tmp; + } + bool operator==(const ConstStackIteratorInterface& rhs) { + return fIndex == rhs.fIndex; + } + bool operator!=(const ConstStackIteratorInterface& rhs) { + return fIndex != rhs.fIndex; + } + + ParticleInterfaceType& operator*() { + return static_cast<ParticleInterfaceType&>(*this); + } + const ParticleInterfaceType& operator*() const { + return static_cast<const ParticleInterfaceType&>(*this); + } + + protected: + int GetIndex() const { return fIndex; } + // StackType GetStack() { return *fData; } + const StackType& GetStack() const { return *fData; } + // StackData& /*typename std::decay<StackData>::type&*/ GetStackData() { return + // fData->GetStackData(); } + const StackData& /*typename std::decay<StackData>::type&*/ GetStackData() const { + return fData->GetStackData(); + } + }; // end class ConstStackIterator + } // namespace corsika::stack #endif diff --git a/Framework/StackInterface/testStackInterface.cc b/Framework/StackInterface/testStackInterface.cc index 078a09407..8e165d5c9 100644 --- a/Framework/StackInterface/testStackInterface.cc +++ b/Framework/StackInterface/testStackInterface.cc @@ -23,7 +23,7 @@ using namespace corsika::stack; using namespace std; // definition of stack-data object -class StackOneData { +class TestStackData { public: // these functions are needed for the Stack interface @@ -57,22 +57,38 @@ private: // defintion of a stack-readout object, the iteractor dereference // operator will deliver access to these function template <typename StackIteratorInterface> -class ParticleInterface : public ParticleBase<StackIteratorInterface> { - // using ParticleBase<StackIteratorInterface>::Delete; +class TestParticleInterface : public ParticleBase<StackIteratorInterface> { + using ParticleBase<StackIteratorInterface>::GetStack; using ParticleBase<StackIteratorInterface>::GetStackData; using ParticleBase<StackIteratorInterface>::GetIndex; public: + // one version + void AddSecondary(const double v) { GetStack().AddParticle(v); } + // another version + void AddSecondary(const double v, const double p) { GetStack().AddParticle(v + p); } + + void SetParticleData(const double v) { SetData(v); } + void SetData(const double v) { GetStackData().SetData(GetIndex(), v); } double GetData() const { return GetStackData().GetData(GetIndex()); } }; +typedef Stack<TestStackData, TestParticleInterface> StackTest; +typedef StackTest::ParticleType Particle; + TEST_CASE("Stack", "[Stack]") { + // helper function for sum over stack data + auto sum = [](const StackTest& stack) { + double v = 0; + for (const auto&& p : stack) v += p.GetData(); + return v; + }; + SECTION("StackInterface") { // construct a valid Stack object - typedef Stack<StackOneData, ParticleInterface> StackTest; StackTest s; s.Init(); s.Clear(); @@ -85,44 +101,55 @@ TEST_CASE("Stack", "[Stack]") { REQUIRE(s.GetSize() == 0); } - SECTION("write") { + SECTION("construct") { - // construct a valid Stack object - typedef Stack<StackOneData, ParticleInterface> StackTest; + // construct a valid, empty Stack object StackTest s; } - SECTION("read") { + SECTION("write and read") { - typedef Stack<StackOneData, ParticleInterface> StackTest; StackTest s; - s.NewParticle().SetData(9.9); - cout << "kk" << endl; - double v = 0; - for (auto& p : s) { - cout << typeid(p).name() << endl; - v += p.GetData(); - } - cout << "k222k" << endl; - + s.AddParticle(9.9); + const double v = sum(s); REQUIRE(v == 9.9); } - SECTION("delete_stack") { + SECTION("delete from stack") { - typedef Stack<StackOneData, ParticleInterface> StackTest; StackTest s; - auto p = s.NewParticle(); + REQUIRE(s.GetSize() == 0); + StackTest::StackIterator p = s.AddParticle(0.); // valid way to access particle data p.SetData(9.9); + REQUIRE(s.GetSize() == 1); s.Delete(p); + REQUIRE(s.GetSize() == 0); } - SECTION("delete_particle") { + SECTION("delete particle") { - typedef Stack<StackOneData, ParticleInterface> StackTest; StackTest s; - auto p = s.NewParticle(); - p.SetData(9.9); + REQUIRE(s.GetSize() == 0); + auto p = + s.AddParticle(9.9); // also valid way to access particle data, identical to above + REQUIRE(s.GetSize() == 1); p.Delete(); + REQUIRE(s.GetSize() == 0); + } + + SECTION("create secondaries") { + + StackTest s; + REQUIRE(s.GetSize() == 0); + auto iter = s.AddParticle(9.9); + Particle& p = *iter; // also this is valid to access particle data + REQUIRE(s.GetSize() == 1); + p.AddSecondary(4.4); + REQUIRE(s.GetSize() == 2); + p.AddSecondary(3.3, 2.2); + REQUIRE(s.GetSize() == 3); + double v = 0; + for (auto& p : s) { v += p.GetData(); } + REQUIRE(v == 9.9 + 4.4 + 3.3 + 2.2); } } diff --git a/Stack/SuperStupidStack/SuperStupidStack.h b/Stack/SuperStupidStack/SuperStupidStack.h index 044ae32a1..5e314fd4a 100644 --- a/Stack/SuperStupidStack/SuperStupidStack.h +++ b/Stack/SuperStupidStack/SuperStupidStack.h @@ -38,10 +38,12 @@ namespace corsika::stack { template <typename StackIteratorInterface> class ParticleInterface : public ParticleBase<StackIteratorInterface> { + using corsika::stack::ParticleBase<StackIteratorInterface>::GetStack; using corsika::stack::ParticleBase<StackIteratorInterface>::GetStackData; using corsika::stack::ParticleBase<StackIteratorInterface>::GetIndex; public: + /// individual setters void SetPID(const corsika::particles::Code id) { GetStackData().SetPID(GetIndex(), id); } @@ -62,6 +64,7 @@ namespace corsika::stack { GetStackData().SetTime(GetIndex(), v); } + /// individual getters corsika::particles::Code GetPID() const { return GetStackData().GetPID(GetIndex()); } -- GitLab