IAP GITLAB

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • AirShowerPhysics/corsika
  • rulrich/corsika
  • AAAlvesJr/corsika
  • Andre/corsika
  • arrabito/corsika
  • Nikos/corsika
  • olheiser73/corsika
  • AirShowerPhysics/papers/corsika
  • pranav/corsika
9 results
Show changes
Showing
with 0 additions and 2304 deletions
add_subdirectory (DummyStack)
add_subdirectory (SuperStupidStack)
add_subdirectory (NuclearStackExtension)
set (DummyStack_HEADERS DummyStack.h)
set (DummyStack_NAMESPACE corsika/stack/dummy)
add_library (DummyStack INTERFACE)
CORSIKA_COPY_HEADERS_TO_NAMESPACE (DummyStack ${DummyStack_NAMESPACE} ${DummyStack_HEADERS})
target_link_libraries (
DummyStack
INTERFACE
CORSIKAstackinterface
CORSIKAunits
CORSIKAparticles
)
target_include_directories (
DummyStack
INTERFACE
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:include>
)
install (
FILES
${DummyStack_HEADERS}
DESTINATION
include/${DummyStack_NAMESPACE}
)
/*
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _include_dummystack_h_
#define _include_dummystack_h_
#include <corsika/particles/ParticleProperties.h>
#include <corsika/stack/Stack.h>
#include <corsika/units/PhysicalUnits.h>
#include <string>
#include <vector>
namespace corsika::stack {
namespace dummy {
/**
* Example of a particle object on the stack.
*/
template <typename _Stack>
class ParticleRead : public StackIteratorInfo<_Stack, ParticleRead<_Stack> > {
using StackIteratorInfo<_Stack, ParticleRead>::GetIndex;
using StackIteratorInfo<_Stack, ParticleRead>::GetStack;
public:
};
/**
*
* Memory implementation of the most simple (stupid) particle stack object.
*/
class DummyStackImpl {
public:
void Init() {}
void Clear() {}
int GetSize() const { return 0; }
int GetCapacity() const { return 0; }
/**
* Function to copy particle at location i2 in stack to i1
*/
void Copy(const int i1, const int i2) {}
protected:
void IncrementSize() {}
void DecrementSize() {}
}; // end class DummyStackImpl
typedef StackIterator<DummyStackImpl, ParticleRead<DummyStackImpl> > Particle;
typedef Stack<DummyStackImpl, Particle> DummyStack;
} // namespace dummy
} // namespace corsika::stack
#endif
set (NuclearStackExtension_HEADERS NuclearStackExtension.h)
set (NuclearStackExtension_NAMESPACE corsika/stack/nuclear_extension)
add_library (NuclearStackExtension INTERFACE)
CORSIKA_COPY_HEADERS_TO_NAMESPACE (NuclearStackExtension ${NuclearStackExtension_NAMESPACE} ${NuclearStackExtension_HEADERS})
target_link_libraries (
NuclearStackExtension
INTERFACE
CORSIKAstackinterface
CORSIKAunits
CORSIKAparticles
CORSIKAgeometry
)
target_include_directories (
NuclearStackExtension
INTERFACE
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:include>
)
install (
FILES
${NuclearStackExtension_HEADERS}
DESTINATION
include/${NuclearStackExtension_NAMESPACE}
)
# ----------------
# code unit testing
add_executable (
testNuclearStackExtension
testNuclearStackExtension.cc
)
target_link_libraries (
testNuclearStackExtension
SuperStupidStack
NuclearStackExtension
CORSIKAparticles
CORSIKAgeometry
CORSIKAunits
CORSIKAthirdparty # for catch2
)
CORSIKA_ADD_TEST(testNuclearStackExtension)
/*
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _include_stack_nuclearstackextension_h_
#define _include_stack_nuclearstackextension_h_
#include <corsika/particles/ParticleProperties.h>
#include <corsika/stack/Stack.h>
#include <corsika/units/PhysicalUnits.h>
#include <corsika/geometry/Point.h>
#include <corsika/geometry/Vector.h>
#include <algorithm>
#include <tuple>
#include <vector>
namespace corsika::stack {
/**
* @namespace nuclear_extension
*
* Add A and Z data to existing stack of particle properties.
*
* Only for Code::Nucleus particles A and Z are stored, not for all
* normal elementary particles.
*
* Thus in your code, make sure to always check <code>
* particle.GetPID()==Code::Nucleus </code> before attempting to
* read any nuclear information.
*
*
*/
typedef corsika::geometry::Vector<corsika::units::si::hepmomentum_d> MomentumVector;
namespace nuclear_extension {
/**
* @class NuclearParticleInterface
*
* Define ParticleInterface for NuclearStackExtension Stack derived from
* ParticleInterface of Inner stack class
*/
template <template <typename> typename InnerParticleInterface,
typename StackIteratorInterface>
class NuclearParticleInterface
: public InnerParticleInterface<StackIteratorInterface> {
protected:
using InnerParticleInterface<StackIteratorInterface>::GetStackData;
using InnerParticleInterface<StackIteratorInterface>::GetIndex;
public:
void SetParticleData(
const std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
corsika::stack::MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType>& v) {
if (std::get<0>(v) == corsika::particles::Code::Nucleus) {
std::ostringstream err;
err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
throw std::runtime_error(err.str());
}
InnerParticleInterface<StackIteratorInterface>::SetParticleData(v);
SetNucleusRef(-1); // this is not a nucleus
}
void SetParticleData(
const std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
corsika::stack::MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType, unsigned short, unsigned short>&
v) {
const unsigned short A = std::get<5>(v);
const unsigned short Z = std::get<6>(v);
if (std::get<0>(v) != corsika::particles::Code::Nucleus || A == 0 || Z == 0) {
std::ostringstream err;
err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
throw std::runtime_error(err.str());
}
SetNucleusRef(GetStackData().GetNucleusNextRef()); // store this nucleus data ref
SetNuclearA(A);
SetNuclearZ(Z);
InnerParticleInterface<StackIteratorInterface>::SetParticleData(
std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
corsika::stack::MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType>{std::get<0>(v), std::get<1>(v),
std::get<2>(v), std::get<3>(v),
std::get<4>(v)});
}
void SetParticleData(
InnerParticleInterface<StackIteratorInterface>& p,
const std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
corsika::stack::MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType>& v) {
if (std::get<0>(v) == corsika::particles::Code::Nucleus) {
std::ostringstream err;
err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
throw std::runtime_error(err.str());
}
InnerParticleInterface<StackIteratorInterface>::SetParticleData(
p, std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
corsika::stack::MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType>{std::get<0>(v), std::get<1>(v),
std::get<2>(v), std::get<3>(v),
std::get<4>(v)});
SetNucleusRef(-1); // this is not a nucleus
}
void SetParticleData(
InnerParticleInterface<StackIteratorInterface>& p,
const std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
corsika::stack::MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType, unsigned short, unsigned short>&
v) {
const unsigned short A = std::get<5>(v);
const unsigned short Z = std::get<6>(v);
if (std::get<0>(v) != corsika::particles::Code::Nucleus || A == 0 || Z == 0) {
std::ostringstream err;
err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
throw std::runtime_error(err.str());
}
SetNucleusRef(GetStackData().GetNucleusNextRef()); // store this nucleus data ref
SetNuclearA(A);
SetNuclearZ(Z);
InnerParticleInterface<StackIteratorInterface>::SetParticleData(
p, std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
corsika::stack::MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType>{std::get<0>(v), std::get<1>(v),
std::get<2>(v), std::get<3>(v),
std::get<4>(v)});
}
/**
* @name individual setters
* @{
*/
void SetNuclearA(const unsigned short vA) {
GetStackData().SetNuclearA(GetIndex(), vA);
}
void SetNuclearZ(const unsigned short vZ) {
GetStackData().SetNuclearZ(GetIndex(), vZ);
}
/// @}
/**
* @name individual getters
* @{
*/
int GetNuclearA() const { return GetStackData().GetNuclearA(GetIndex()); }
int GetNuclearZ() const { return GetStackData().GetNuclearZ(GetIndex()); }
/// @}
/**
* Overwrite normal GetParticleMass function with nuclear version
*/
corsika::units::si::HEPMassType GetMass() const {
if (InnerParticleInterface<StackIteratorInterface>::GetPID() ==
corsika::particles::Code::Nucleus)
return corsika::particles::GetNucleusMass(GetNuclearA(), GetNuclearZ());
return InnerParticleInterface<StackIteratorInterface>::GetMass();
}
/**
* Overwirte normal GetChargeNumber function with nuclear version
**/
int16_t GetChargeNumber() const {
if (InnerParticleInterface<StackIteratorInterface>::GetPID() ==
corsika::particles::Code::Nucleus)
return GetNuclearZ();
return InnerParticleInterface<StackIteratorInterface>::GetChargeNumber();
}
int GetNucleusRef() const { return GetStackData().GetNucleusRef(GetIndex()); }
protected:
void SetNucleusRef(const int vR) { GetStackData().SetNucleusRef(GetIndex(), vR); }
};
/**
* @class NuclearStackExtension
*
* Memory implementation of adding nuclear inforamtion to the
* existing particle stack defined in class InnerStackImpl.
*
* Inside the NuclearStackExtension class there is a dedicated
* fNucleusRef index, where fNucleusRef[i] is referring to the
* correct A and Z for a specific particle index i. fNucleusRef[i]
* == -1 means that this is not a nucleus, and a subsequent call to
* GetNucleusA would produce an exception.
*/
template <typename InnerStackImpl>
class NuclearStackExtensionImpl : public InnerStackImpl {
public:
void Init() { InnerStackImpl::Init(); }
void Dump() { InnerStackImpl::Dump(); }
void Clear() {
InnerStackImpl::Clear();
fNucleusRef.clear();
fNuclearA.clear();
fNuclearZ.clear();
}
unsigned int GetSize() const { return fNucleusRef.size(); }
unsigned int GetCapacity() const { return fNucleusRef.capacity(); }
void SetNuclearA(const unsigned int i, const unsigned short vA) {
fNuclearA[GetNucleusRef(i)] = vA;
}
void SetNuclearZ(const unsigned int i, const unsigned short vZ) {
fNuclearZ[GetNucleusRef(i)] = vZ;
}
void SetNucleusRef(const unsigned int i, const int v) { fNucleusRef[i] = v; }
int GetNuclearA(const unsigned int i) const { return fNuclearA[GetNucleusRef(i)]; }
int GetNuclearZ(const unsigned int i) const { return fNuclearZ[GetNucleusRef(i)]; }
// this function will create new storage for Nuclear Properties, and return the
// reference to it
int GetNucleusNextRef() {
fNuclearA.push_back(0);
fNuclearZ.push_back(0);
return fNuclearA.size() - 1;
}
int GetNucleusRef(const unsigned int i) const {
if (fNucleusRef[i] >= 0) return fNucleusRef[i];
std::ostringstream err;
err << "NuclearStackExtension: no nucleus at ref=" << i;
throw std::runtime_error(err.str());
}
/**
* Function to copy particle at location i1 in stack to i2
*/
void Copy(const unsigned int i1, const unsigned int i2) {
// index range check
if (i1 >= GetSize() || i2 >= GetSize()) {
std::ostringstream err;
err << "NuclearStackExtension: trying to access data beyond size of stack!";
throw std::runtime_error(err.str());
}
// copy internal particle data p[i2] = p[i1]
InnerStackImpl::Copy(i1, i2);
// check if any of p[i1] or p[i2] was a Code::Nucleus
const int ref1 = fNucleusRef[i1];
const int ref2 = fNucleusRef[i2];
if (ref2 < 0) {
if (ref1 >= 0) {
// i1 is nucleus, i2 is not
fNucleusRef[i2] = GetNucleusNextRef();
fNuclearA[fNucleusRef[i2]] = fNuclearA[ref1];
fNuclearZ[fNucleusRef[i2]] = fNuclearZ[ref1];
} else {
// neither i1 nor i2 are nuclei
}
} else {
if (ref1 >= 0) {
// both are nuclei, i2 is overwritten with nucleus i1
// fNucleusRef stays the same, but A and Z data is overwritten
fNuclearA[ref2] = fNuclearA[ref1];
fNuclearZ[ref2] = fNuclearZ[ref1];
} else {
// i2 is overwritten with non-nucleus i1
fNucleusRef[i2] = -1; // flag as non-nucleus
fNuclearA.erase(fNuclearA.cbegin() + ref2); // remove data for i2
fNuclearZ.erase(fNuclearZ.cbegin() + ref2); // remove data for i2
const int n = fNucleusRef.size(); // update fNucleusRef: indices above ref2
// must be decremented by 1
for (int i = 0; i < n; ++i) {
if (fNucleusRef[i] > ref2) { fNucleusRef[i] -= 1; }
}
}
}
}
/**
* Function to copy particle at location i2 in stack to i1
*/
void Swap(const unsigned int i1, const unsigned int i2) {
// index range check
if (i1 >= GetSize() || i2 >= GetSize()) {
std::ostringstream err;
err << "NuclearStackExtension: trying to access data beyond size of stack!";
throw std::runtime_error(err.str());
}
// swap original particle data
InnerStackImpl::Swap(i1, i2);
// swap corresponding nuclear reference data
std::swap(fNucleusRef[i2], fNucleusRef[i1]);
}
void IncrementSize() {
InnerStackImpl::IncrementSize();
fNucleusRef.push_back(-1);
}
void DecrementSize() {
InnerStackImpl::DecrementSize();
if (fNucleusRef.size() > 0) {
const int ref = fNucleusRef.back();
fNucleusRef.pop_back();
if (ref >= 0) {
fNuclearA.erase(fNuclearA.begin() + ref);
fNuclearZ.erase(fNuclearZ.begin() + ref);
const int n = fNucleusRef.size();
for (int i = 0; i < n; ++i) {
if (fNucleusRef[i] >= ref) { fNucleusRef[i] -= 1; }
}
}
}
}
private:
/// the actual memory to store particle data
std::vector<int> fNucleusRef;
std::vector<unsigned short> fNuclearA;
std::vector<unsigned short> fNuclearZ;
}; // end class NuclearStackExtensionImpl
// template<typename StackIteratorInterface>
// using NuclearParticleInterfaceType<StackIteratorInterface> =
// NuclearParticleInterface< ,StackIteratorInterface>
// works, but requires stupd _PI class
// template<typename SS> using TEST =
// NuclearParticleInterface<corsika::stack::super_stupid::SuperStupidStack::PIType,
// SS>;
template <typename InnerStack, template <typename> typename _PI>
using NuclearStackExtension =
Stack<NuclearStackExtensionImpl<typename InnerStack::StackImpl>, _PI>;
// ----
// I'm dont't manage to do this properly.......
/*
template<typename TT, typename SS> using TESTi = typename
NuclearParticleInterface<TT::template PIType, SS>::ExtendedParticleInterface;
template<typename TT, typename SS> using TEST1 = TESTi<TT, SS>;
template<typename SS> using TEST2 = TEST1<typename
corsika::stack::super_stupid::SuperStupidStack, SS>;
using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename
InnerStack::StackImpl>, TEST2>;
*/
/*
// .... this should be fixed ....
template <typename InnerStack, typename SS=StackIteratorInterface>
//using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename
InnerStack::StackImpl>, NuclearParticleInterface<typename InnerStack::template PIType,
StackIteratorInterface>::ExtendedParticleInterface>; using NuclearStackExtension =
Stack<NuclearStackExtensionImpl<typename InnerStack::StackImpl>, TEST1<typename
corsika::stack::super_stupid::SuperStupidStack, SS> >;
//template <typename InnerStack>
// using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename
InnerStack::StackImpl>, TEST<typename
corsika::stack::super_stupid::SuperStupidStack::PIType>>;
//using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename
InnerStack::StackImpl>, TEST>;
*/
} // namespace nuclear_extension
} // namespace corsika::stack
#endif
/*
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#include <corsika/geometry/RootCoordinateSystem.h>
#include <corsika/stack/nuclear_extension/NuclearStackExtension.h>
#include <corsika/stack/super_stupid/SuperStupidStack.h>
#include <corsika/units/PhysicalUnits.h>
#include <boost/type_index.hpp>
using boost::typeindex::type_id_with_cvr;
using namespace corsika;
using namespace corsika::stack::nuclear_extension;
using namespace corsika::geometry;
using namespace corsika::units::si;
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one
// cpp file
#include <catch2/catch.hpp>
// this is an auxiliary help typedef, which I don't know how to put
// into NuclearStackExtension.h where it belongs...
template <typename StackIter>
using ExtendedParticleInterfaceType =
corsika::stack::nuclear_extension::NuclearParticleInterface<
corsika::stack::super_stupid::SuperStupidStack::template PIType, StackIter>;
using ExtStack = NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack,
ExtendedParticleInterfaceType>;
#include <iostream>
using namespace std;
TEST_CASE("NuclearStackExtension", "[stack]") {
geometry::CoordinateSystem& dummyCS =
geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
SECTION("write non nucleus") {
NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack,
ExtendedParticleInterfaceType>
s;
s.AddParticle(
std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
particles::Code::Electron, 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s});
REQUIRE(s.GetSize() == 1);
}
SECTION("write nucleus") {
NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack,
ExtendedParticleInterfaceType>
s;
s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point,
units::si::TimeType, unsigned short, unsigned short>{
particles::Code::Nucleus, 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 10});
REQUIRE(s.GetSize() == 1);
}
SECTION("write invalid nucleus") {
ExtStack s;
REQUIRE_THROWS(
s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point,
units::si::TimeType, unsigned short, unsigned short>{
particles::Code::Nucleus, 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 0, 0}));
}
SECTION("read non nucleus") {
ExtStack s;
s.AddParticle(
std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
particles::Code::Electron, 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s});
const auto pout = s.GetNextParticle();
REQUIRE(pout.GetPID() == particles::Code::Electron);
REQUIRE(pout.GetEnergy() == 1.5_GeV);
REQUIRE(pout.GetTime() == 100_s);
}
SECTION("read nucleus") {
ExtStack s;
s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point,
units::si::TimeType, unsigned short, unsigned short>{
particles::Code::Nucleus, 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 9});
const auto pout = s.GetNextParticle();
REQUIRE(pout.GetPID() == particles::Code::Nucleus);
REQUIRE(pout.GetEnergy() == 1.5_GeV);
REQUIRE(pout.GetTime() == 100_s);
REQUIRE(pout.GetNuclearA() == 10);
REQUIRE(pout.GetNuclearZ() == 9);
}
SECTION("read invalid nucleus") {
ExtStack s;
s.AddParticle(
std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
particles::Code::Electron, 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s});
const auto pout = s.GetNextParticle();
REQUIRE_THROWS(pout.GetNuclearA());
REQUIRE_THROWS(pout.GetNuclearZ());
}
SECTION("stack fill and cleanup") {
ExtStack s;
// add 99 particles, each 10th particle is a nucleus with A=i and Z=A/2!
for (int i = 0; i < 99; ++i) {
if ((i + 1) % 10 == 0) {
s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point,
units::si::TimeType, unsigned short, unsigned short>{
particles::Code::Nucleus, 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, i, i / 2});
} else {
s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point,
units::si::TimeType>{
particles::Code::Electron, 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s});
}
}
REQUIRE(s.GetSize() == 99);
for (int i = 0; i < 99; ++i) s.GetNextParticle().Delete();
REQUIRE(s.GetSize() == 0);
}
SECTION("stack operations") {
ExtStack s;
// add 99 particles, each 10th particle is a nucleus with A=i and Z=A/2!
for (int i = 0; i < 99; ++i) {
if ((i + 1) % 10 == 0) {
s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point,
units::si::TimeType, unsigned short, unsigned short>{
particles::Code::Nucleus, i * 15_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, i, i / 2});
} else {
s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point,
units::si::TimeType>{
particles::Code::Electron, i * 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s});
}
}
// copy
{
s.Copy(s.begin() + 9, s.begin() + 10); // nuclei to non-nuclei
const auto& p9 = s.cbegin() + 9;
const auto& p10 = s.cbegin() + 10;
REQUIRE(p9.GetPID() == particles::Code::Nucleus);
REQUIRE(p9.GetEnergy() == 9 * 15_GeV);
REQUIRE(p9.GetTime() == 100_s);
REQUIRE(p9.GetNuclearA() == 9);
REQUIRE(p9.GetNuclearZ() == 9 / 2);
REQUIRE(p10.GetPID() == particles::Code::Nucleus);
REQUIRE(p10.GetEnergy() == 9 * 15_GeV);
REQUIRE(p10.GetTime() == 100_s);
REQUIRE(p10.GetNuclearA() == 9);
REQUIRE(p10.GetNuclearZ() == 9 / 2);
}
// copy
{
s.Copy(s.begin() + 93, s.begin() + 9); // non-nuclei to nuclei
const auto& p93 = s.cbegin() + 93;
const auto& p9 = s.cbegin() + 9;
REQUIRE(p9.GetPID() == particles::Code::Electron);
REQUIRE(p9.GetEnergy() == 93 * 1.5_GeV);
REQUIRE(p9.GetTime() == 100_s);
REQUIRE(p93.GetPID() == particles::Code::Electron);
REQUIRE(p93.GetEnergy() == 93 * 1.5_GeV);
REQUIRE(p93.GetTime() == 100_s);
}
// swap
{
s.Swap(s.begin() + 11, s.begin() + 10);
const auto& p11 = s.cbegin() + 11; // now: nucleus
const auto& p10 = s.cbegin() + 10; // now: electron
REQUIRE(p11.GetPID() == particles::Code::Nucleus);
REQUIRE(p11.GetEnergy() == 9 * 15_GeV);
REQUIRE(p11.GetTime() == 100_s);
REQUIRE(p11.GetNuclearA() == 9);
REQUIRE(p11.GetNuclearZ() == 9 / 2);
REQUIRE(p10.GetPID() == particles::Code::Electron);
REQUIRE(p10.GetEnergy() == 11 * 1.5_GeV);
REQUIRE(p10.GetTime() == 100_s);
}
// swap two nuclei
{
s.Swap(s.begin() + 29, s.begin() + 59);
const auto& p29 = s.cbegin() + 29;
const auto& p59 = s.cbegin() + 59;
REQUIRE(p29.GetPID() == particles::Code::Nucleus);
REQUIRE(p29.GetEnergy() == 59 * 15_GeV);
REQUIRE(p29.GetTime() == 100_s);
REQUIRE(p29.GetNuclearA() == 59);
REQUIRE(p29.GetNuclearZ() == 59 / 2);
REQUIRE(p59.GetPID() == particles::Code::Nucleus);
REQUIRE(p59.GetEnergy() == 29 * 15_GeV);
REQUIRE(p59.GetTime() == 100_s);
REQUIRE(p59.GetNuclearA() == 29);
REQUIRE(p59.GetNuclearZ() == 29 / 2);
}
for (int i = 0; i < 99; ++i) s.DeleteLast();
REQUIRE(s.GetSize() == 0);
}
}
set (SuperStupidStack_HEADERS SuperStupidStack.h)
set (SuperStupidStack_NAMESPACE corsika/stack/super_stupid)
add_library (SuperStupidStack INTERFACE)
CORSIKA_COPY_HEADERS_TO_NAMESPACE (SuperStupidStack ${SuperStupidStack_NAMESPACE} ${SuperStupidStack_HEADERS})
target_link_libraries (
SuperStupidStack
INTERFACE
CORSIKAstackinterface
CORSIKAunits
CORSIKAparticles
CORSIKAgeometry
)
target_include_directories (
SuperStupidStack
INTERFACE
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:include>
)
install (
FILES
${SuperStupidStack_HEADERS}
DESTINATION
include/${SuperStupidStack_NAMESPACE}
)
# ----------------
# code unit testing
add_executable (
testSuperStupidStack
testSuperStupidStack.cc
)
target_link_libraries (
testSuperStupidStack
CORSIKAgeometry
CORSIKAparticles
CORSIKAunits
CORSIKAthirdparty # for catch2
)
CORSIKA_ADD_TEST(testSuperStupidStack)
/*
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _include_superstupidstack_h_
#define _include_superstupidstack_h_
#include <corsika/particles/ParticleProperties.h>
#include <corsika/stack/Stack.h>
#include <corsika/units/PhysicalUnits.h>
#include <corsika/geometry/Point.h>
#include <corsika/geometry/RootCoordinateSystem.h> // remove
#include <corsika/geometry/Vector.h>
#include <algorithm>
#include <vector>
namespace corsika::stack {
typedef corsika::geometry::Vector<corsika::units::si::hepmomentum_d> MomentumVector;
namespace super_stupid {
/**
* Example of a particle object on the stack.
*/
template <typename StackIteratorInterface>
class ParticleInterface : public ParticleBase<StackIteratorInterface> {
protected:
using corsika::stack::ParticleBase<StackIteratorInterface>::GetStack;
using corsika::stack::ParticleBase<StackIteratorInterface>::GetStackData;
public:
using corsika::stack::ParticleBase<StackIteratorInterface>::GetIndex;
public:
void SetParticleData(
const std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType>& v) {
SetPID(std::get<0>(v));
SetEnergy(std::get<1>(v));
SetMomentum(std::get<2>(v));
SetPosition(std::get<3>(v));
SetTime(std::get<4>(v));
}
/*
void SetParticleData(const corsika::particles::Code vDataPID,
const corsika::units::si::HEPEnergyType vDataE,
const MomentumVector& vMomentum,
const corsika::geometry::Point& vPosition,
const corsika::units::si::TimeType vTime) {
}*/
void SetParticleData(
ParticleInterface<StackIteratorInterface>&,
const std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType>& v) {
SetPID(std::get<0>(v));
SetEnergy(std::get<1>(v));
SetMomentum(std::get<2>(v));
SetPosition(std::get<3>(v));
SetTime(std::get<4>(v));
}
/* void SetParticleData(ParticleInterface<StackIteratorInterface>&,
const corsika::particles::Code vDataPID,
const corsika::units::si::HEPEnergyType vDataE,
const MomentumVector& vMomentum,
const corsika::geometry::Point& vPosition,
const corsika::units::si::TimeType vTime) {
SetPID(vDataPID);
SetEnergy(vDataE);
SetMomentum(vMomentum);
SetPosition(vPosition);
SetTime(vTime);
}*/
/// individual setters
void SetPID(const corsika::particles::Code id) {
GetStackData().SetPID(GetIndex(), id);
}
void SetEnergy(const corsika::units::si::HEPEnergyType& e) {
GetStackData().SetEnergy(GetIndex(), e);
}
void SetMomentum(const MomentumVector& v) {
GetStackData().SetMomentum(GetIndex(), v);
}
void SetPosition(const corsika::geometry::Point& v) {
GetStackData().SetPosition(GetIndex(), v);
}
void SetTime(const corsika::units::si::TimeType& v) {
GetStackData().SetTime(GetIndex(), v);
}
/// individual getters
corsika::particles::Code GetPID() const {
return GetStackData().GetPID(GetIndex());
}
corsika::units::si::HEPEnergyType GetEnergy() const {
return GetStackData().GetEnergy(GetIndex());
}
MomentumVector GetMomentum() const {
return GetStackData().GetMomentum(GetIndex());
}
corsika::geometry::Point GetPosition() const {
return GetStackData().GetPosition(GetIndex());
}
corsika::units::si::TimeType GetTime() const {
return GetStackData().GetTime(GetIndex());
}
/**
* @name derived quantities
*
* @{
*/
corsika::geometry::Vector<corsika::units::si::dimensionless_d> GetDirection()
const {
return GetMomentum() / GetEnergy();
}
corsika::units::si::HEPMassType GetMass() const {
return corsika::particles::GetMass(GetPID());
}
int16_t GetChargeNumber() const {
return corsika::particles::GetChargeNumber(GetPID());
}
///@}
};
/**
* Memory implementation of the most simple (stupid) particle stack object.
*/
class SuperStupidStackImpl {
public:
void Init() {}
void Dump() const {}
void Clear() {
fDataPID.clear();
fDataE.clear();
fMomentum.clear();
fPosition.clear();
fTime.clear();
}
unsigned int GetSize() const { return fDataPID.size(); }
unsigned int GetCapacity() const { return fDataPID.size(); }
void SetPID(const unsigned int i, const corsika::particles::Code id) {
fDataPID[i] = id;
}
void SetEnergy(const unsigned int i, const corsika::units::si::HEPEnergyType e) {
fDataE[i] = e;
}
void SetMomentum(const unsigned int i, const MomentumVector& v) {
fMomentum[i] = v;
}
void SetPosition(const unsigned int i, const corsika::geometry::Point& v) {
fPosition[i] = v;
}
void SetTime(const unsigned int i, const corsika::units::si::TimeType& v) {
fTime[i] = v;
}
corsika::particles::Code GetPID(const unsigned int i) const { return fDataPID[i]; }
corsika::units::si::HEPEnergyType GetEnergy(const unsigned int i) const {
return fDataE[i];
}
MomentumVector GetMomentum(const unsigned int i) const { return fMomentum[i]; }
corsika::geometry::Point GetPosition(const unsigned int i) const {
return fPosition[i];
}
corsika::units::si::TimeType GetTime(const unsigned int i) const {
return fTime[i];
}
/**
* Function to copy particle at location i2 in stack to i1
*/
void Copy(const unsigned int i1, const unsigned int i2) {
fDataPID[i2] = fDataPID[i1];
fDataE[i2] = fDataE[i1];
fMomentum[i2] = fMomentum[i1];
fPosition[i2] = fPosition[i1];
fTime[i2] = fTime[i1];
}
/**
* Function to copy particle at location i2 in stack to i1
*/
void Swap(const unsigned int i1, const unsigned int i2) {
std::swap(fDataPID[i2], fDataPID[i1]);
std::swap(fDataE[i2], fDataE[i1]);
std::swap(fMomentum[i2], fMomentum[i1]);
std::swap(fPosition[i2], fPosition[i1]);
std::swap(fTime[i2], fTime[i1]);
}
void IncrementSize() {
using corsika::geometry::Point;
using corsika::particles::Code;
fDataPID.push_back(Code::Unknown);
fDataE.push_back(0 * corsika::units::si::electronvolt);
geometry::CoordinateSystem& dummyCS =
geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
fMomentum.push_back(MomentumVector(
dummyCS,
{0 * corsika::units::si::electronvolt, 0 * corsika::units::si::electronvolt,
0 * corsika::units::si::electronvolt}));
fPosition.push_back(
Point(dummyCS, {0 * corsika::units::si::meter, 0 * corsika::units::si::meter,
0 * corsika::units::si::meter}));
fTime.push_back(0 * corsika::units::si::second);
}
void DecrementSize() {
if (fDataE.size() > 0) {
fDataPID.pop_back();
fDataE.pop_back();
fMomentum.pop_back();
fPosition.pop_back();
fTime.pop_back();
}
}
private:
/// the actual memory to store particle data
std::vector<corsika::particles::Code> fDataPID;
std::vector<corsika::units::si::HEPEnergyType> fDataE;
std::vector<MomentumVector> fMomentum;
std::vector<corsika::geometry::Point> fPosition;
std::vector<corsika::units::si::TimeType> fTime;
}; // end class SuperStupidStackImpl
typedef Stack<SuperStupidStackImpl, ParticleInterface> SuperStupidStack;
} // namespace super_stupid
} // namespace corsika::stack
#endif
/*
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#include <corsika/geometry/RootCoordinateSystem.h>
#include <corsika/stack/super_stupid/SuperStupidStack.h>
#include <corsika/units/PhysicalUnits.h>
using namespace corsika::geometry;
using namespace corsika::units::si;
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one
// cpp file
#include <catch2/catch.hpp>
using namespace corsika;
using namespace corsika::stack::super_stupid;
#include <iostream>
using namespace std;
TEST_CASE("SuperStupidStack", "[stack]") {
geometry::CoordinateSystem& dummyCS =
geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
SECTION("read+write") {
SuperStupidStack s;
s.AddParticle(std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
corsika::stack::MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType>{
particles::Code::Electron, 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s});
// read
REQUIRE(s.GetSize() == 1);
auto pout = s.GetNextParticle();
REQUIRE(pout.GetPID() == particles::Code::Electron);
REQUIRE(pout.GetEnergy() == 1.5_GeV);
// REQUIRE(pout.GetMomentum() == stack::MomentumVector(dummyCS, {1_GeV,
// 1_GeV, 1_GeV})); REQUIRE(pout.GetPosition() == Point(dummyCS, {1 * meter, 1 *
// meter, 1 * meter}));
REQUIRE(pout.GetTime() == 100_s);
}
SECTION("write+delete") {
SuperStupidStack s;
for (int i = 0; i < 99; ++i)
s.AddParticle(
std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
corsika::stack::MomentumVector, corsika::geometry::Point,
corsika::units::si::TimeType>{
particles::Code::Electron, 1.5_GeV,
corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s});
REQUIRE(s.GetSize() == 99);
for (int i = 0; i < 99; ++i) s.GetNextParticle().Delete();
REQUIRE(s.GetSize() == 0);
}
}
add_library (CORSIKAthirdparty INTERFACE)
target_include_directories (CORSIKAthirdparty SYSTEM
INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty>
$<INSTALL_INTERFACE:include/ThirdParty>
)
install (DIRECTORY phys DESTINATION include/ThirdParty/)
install (DIRECTORY catch2 DESTINATION include/ThirdParty/)
install (DIRECTORY boost DESTINATION include/ThirdParty/boost/)
\ No newline at end of file
/**
@page ThirdParty Third party software
@tableofcontents
In the directory ThirdParty we provide simple dependencies. This
minimizes the need to install additional software for the user. Note
the individual copyrights and licences here!
@section PhysUnits
The PhysUnits library is an external dependency included here just for
convenience:
Original source code from:
https://github.com/martinmoene/PhysUnits-CT-Cpp11#references
Licence: BSL-1.0
(https://github.com/martinmoene/PhysUnits-CT-Cpp11/blob/master/LICENSE_1_0.txt)
References: https://github.com/martinmoene/PhysUnits-CT-Cpp11#references
@section catch2
The catch2 unit testing library is from:
https://github.com/catchorg/Catch2
Licence: BSL-1.0
(https://github.com/martinmoene/PhysUnits-CT-Cpp11/blob/master/LICENSE_1_0.txt)
References: https://github.com/catchorg/Catch2
@section eigen3
eigen3 ....
@section bitset2
see https://github.com/ClaasBontus/bitset2, this package was obtained
from a Boost Software License 1.0.
@section Boost
A subset of header-only Boost libraries. Boost is from:
https://www.boost.org
License: BSL-1.0
(https://www.boost.org/LICENSE_1_0.txt)
The subset was generated with the bcp tool:
https://www.boost.org/doc/libs/1_70_0/tools/bcp/doc/html/index.html
Instructions on how to update Boost with this tool:
Download the latest tarball from www.boost.org.
Unpack source code somewhere, go to into the folder.
Run these commands:
./bootstrap && ./b2 tools/bcp
./dist/bin/bcp mp11 iterator core format interval optional type_index ./dist
mv ./dist/boost <CORSIKA-path>/ThirdParty/boost
*/
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/// \file all_of.hpp
/// \brief Test ranges to see if all elements match a value or predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_ALL_OF_HPP
#define BOOST_ALGORITHM_ALL_OF_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn all_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if all elements in [first, last) satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the sequence
///
/// \note This function is part of the C++2011 standard library.
template<typename InputIterator, typename Predicate>
BOOST_CXX14_CONSTEXPR bool all_of ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( !p(*first))
return false;
return true;
}
/// \fn all_of ( const Range &r, Predicate p )
/// \return true if all elements in the range satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
BOOST_CXX14_CONSTEXPR bool all_of ( const Range &r, Predicate p )
{
return boost::algorithm::all_of ( boost::begin (r), boost::end (r), p );
}
/// \fn all_of_equal ( InputIterator first, InputIterator last, const T &val )
/// \return true if all elements in [first, last) are equal to 'val'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param val A value to compare against
///
template<typename InputIterator, typename T>
BOOST_CXX14_CONSTEXPR bool all_of_equal ( InputIterator first, InputIterator last, const T &val )
{
for ( ; first != last; ++first )
if ( val != *first )
return false;
return true;
}
/// \fn all_of_equal ( const Range &r, const T &val )
/// \return true if all elements in the range are equal to 'val'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param val A value to compare against
///
template<typename Range, typename T>
BOOST_CXX14_CONSTEXPR bool all_of_equal ( const Range &r, const T &val )
{
return boost::algorithm::all_of_equal ( boost::begin (r), boost::end (r), val );
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_ALL_OF_HPP
// Boost string_algo library string_algo.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_ALGO_HPP
#define BOOST_STRING_ALGO_HPP
/*! \file
Cumulative include for string_algo library
*/
#include <boost/algorithm/string/std_containers_traits.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/find_iterator.hpp>
#endif // BOOST_STRING_ALGO_HPP
// Boost string_algo library case_conv.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CASE_CONV_HPP
#define BOOST_STRING_CASE_CONV_HPP
#include <boost/algorithm/string/config.hpp>
#include <algorithm>
#include <locale>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
#include <boost/algorithm/string/detail/case_conv.hpp>
/*! \file
Defines sequence case-conversion algorithms.
Algorithms convert each element in the input sequence to the
desired case using provided locales.
*/
namespace boost {
namespace algorithm {
// to_lower -----------------------------------------------//
//! Convert to lower case
/*!
Each element of the input sequence is converted to lower
case. The result is a copy of the input converted to lower case.
It is returned as a sequence or copied to the output iterator.
\param Output An output iterator to which the result will be copied
\param Input An input range
\param Loc A locale used for conversion
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename RangeT>
inline OutputIteratorT
to_lower_copy(
OutputIteratorT Output,
const RangeT& Input,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::detail::transform_range_copy(
Output,
::boost::as_literal(Input),
::boost::algorithm::detail::to_lowerF<
typename range_value<RangeT>::type >(Loc));
}
//! Convert to lower case
/*!
\overload
*/
template<typename SequenceT>
inline SequenceT to_lower_copy(
const SequenceT& Input,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::detail::transform_range_copy<SequenceT>(
Input,
::boost::algorithm::detail::to_lowerF<
typename range_value<SequenceT>::type >(Loc));
}
//! Convert to lower case
/*!
Each element of the input sequence is converted to lower
case. The input sequence is modified in-place.
\param Input A range
\param Loc a locale used for conversion
*/
template<typename WritableRangeT>
inline void to_lower(
WritableRangeT& Input,
const std::locale& Loc=std::locale())
{
::boost::algorithm::detail::transform_range(
::boost::as_literal(Input),
::boost::algorithm::detail::to_lowerF<
typename range_value<WritableRangeT>::type >(Loc));
}
// to_upper -----------------------------------------------//
//! Convert to upper case
/*!
Each element of the input sequence is converted to upper
case. The result is a copy of the input converted to upper case.
It is returned as a sequence or copied to the output iterator
\param Output An output iterator to which the result will be copied
\param Input An input range
\param Loc A locale used for conversion
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename RangeT>
inline OutputIteratorT
to_upper_copy(
OutputIteratorT Output,
const RangeT& Input,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::detail::transform_range_copy(
Output,
::boost::as_literal(Input),
::boost::algorithm::detail::to_upperF<
typename range_value<RangeT>::type >(Loc));
}
//! Convert to upper case
/*!
\overload
*/
template<typename SequenceT>
inline SequenceT to_upper_copy(
const SequenceT& Input,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::detail::transform_range_copy<SequenceT>(
Input,
::boost::algorithm::detail::to_upperF<
typename range_value<SequenceT>::type >(Loc));
}
//! Convert to upper case
/*!
Each element of the input sequence is converted to upper
case. The input sequence is modified in-place.
\param Input An input range
\param Loc a locale used for conversion
*/
template<typename WritableRangeT>
inline void to_upper(
WritableRangeT& Input,
const std::locale& Loc=std::locale())
{
::boost::algorithm::detail::transform_range(
::boost::as_literal(Input),
::boost::algorithm::detail::to_upperF<
typename range_value<WritableRangeT>::type >(Loc));
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::to_lower;
using algorithm::to_lower_copy;
using algorithm::to_upper;
using algorithm::to_upper_copy;
} // namespace boost
#endif // BOOST_STRING_CASE_CONV_HPP
// Boost string_algo library classification.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CLASSIFICATION_HPP
#define BOOST_STRING_CLASSIFICATION_HPP
#include <algorithm>
#include <locale>
#include <boost/range/value_type.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/detail/classification.hpp>
#include <boost/algorithm/string/predicate_facade.hpp>
/*! \file
Classification predicates are included in the library to give
some more convenience when using algorithms like \c trim() and \c all().
They wrap functionality of STL classification functions ( e.g. \c std::isspace() )
into generic functors.
*/
namespace boost {
namespace algorithm {
// classification functor generator -------------------------------------//
//! is_classified predicate
/*!
Construct the \c is_classified predicate. This predicate holds if the input is
of specified \c std::ctype category.
\param Type A \c std::ctype category
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_classified(std::ctype_base::mask Type, const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(Type, Loc);
}
//! is_space predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::space category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_space(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::space, Loc);
}
//! is_alnum predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::alnum category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_alnum(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::alnum, Loc);
}
//! is_alpha predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::alpha category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_alpha(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::alpha, Loc);
}
//! is_cntrl predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::cntrl category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_cntrl(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::cntrl, Loc);
}
//! is_digit predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::digit category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_digit(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::digit, Loc);
}
//! is_graph predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::graph category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_graph(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::graph, Loc);
}
//! is_lower predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::lower category.
\param Loc A locale used for classification
\return An instance of \c is_classified predicate
*/
inline detail::is_classifiedF
is_lower(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::lower, Loc);
}
//! is_print predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::print category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_print(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::print, Loc);
}
//! is_punct predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::punct category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_punct(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::punct, Loc);
}
//! is_upper predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::upper category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_upper(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::upper, Loc);
}
//! is_xdigit predicate
/*!
Construct the \c is_classified predicate for the \c ctype_base::xdigit category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
*/
inline detail::is_classifiedF
is_xdigit(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::xdigit, Loc);
}
//! is_any_of predicate
/*!
Construct the \c is_any_of predicate. The predicate holds if the input
is included in the specified set of characters.
\param Set A set of characters to be recognized
\return An instance of the \c is_any_of predicate
*/
template<typename RangeT>
inline detail::is_any_ofF<
BOOST_STRING_TYPENAME range_value<RangeT>::type>
is_any_of( const RangeT& Set )
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_set(boost::as_literal(Set));
return detail::is_any_ofF<BOOST_STRING_TYPENAME range_value<RangeT>::type>(lit_set);
}
//! is_from_range predicate
/*!
Construct the \c is_from_range predicate. The predicate holds if the input
is included in the specified range. (i.e. From <= Ch <= To )
\param From The start of the range
\param To The end of the range
\return An instance of the \c is_from_range predicate
*/
template<typename CharT>
inline detail::is_from_rangeF<CharT> is_from_range(CharT From, CharT To)
{
return detail::is_from_rangeF<CharT>(From,To);
}
// predicate combinators ---------------------------------------------------//
//! predicate 'and' composition predicate
/*!
Construct the \c class_and predicate. This predicate can be used
to logically combine two classification predicates. \c class_and holds,
if both predicates return true.
\param Pred1 The first predicate
\param Pred2 The second predicate
\return An instance of the \c class_and predicate
*/
template<typename Pred1T, typename Pred2T>
inline detail::pred_andF<Pred1T, Pred2T>
operator&&(
const predicate_facade<Pred1T>& Pred1,
const predicate_facade<Pred2T>& Pred2 )
{
// Doing the static_cast with the pointer instead of the reference
// is a workaround for some compilers which have problems with
// static_cast's of template references, i.e. CW8. /grafik/
return detail::pred_andF<Pred1T,Pred2T>(
*static_cast<const Pred1T*>(&Pred1),
*static_cast<const Pred2T*>(&Pred2) );
}
//! predicate 'or' composition predicate
/*!
Construct the \c class_or predicate. This predicate can be used
to logically combine two classification predicates. \c class_or holds,
if one of the predicates return true.
\param Pred1 The first predicate
\param Pred2 The second predicate
\return An instance of the \c class_or predicate
*/
template<typename Pred1T, typename Pred2T>
inline detail::pred_orF<Pred1T, Pred2T>
operator||(
const predicate_facade<Pred1T>& Pred1,
const predicate_facade<Pred2T>& Pred2 )
{
// Doing the static_cast with the pointer instead of the reference
// is a workaround for some compilers which have problems with
// static_cast's of template references, i.e. CW8. /grafik/
return detail::pred_orF<Pred1T,Pred2T>(
*static_cast<const Pred1T*>(&Pred1),
*static_cast<const Pred2T*>(&Pred2));
}
//! predicate negation operator
/*!
Construct the \c class_not predicate. This predicate represents a negation.
\c class_or holds if of the predicates return false.
\param Pred The predicate to be negated
\return An instance of the \c class_not predicate
*/
template<typename PredT>
inline detail::pred_notF<PredT>
operator!( const predicate_facade<PredT>& Pred )
{
// Doing the static_cast with the pointer instead of the reference
// is a workaround for some compilers which have problems with
// static_cast's of template references, i.e. CW8. /grafik/
return detail::pred_notF<PredT>(*static_cast<const PredT*>(&Pred));
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::is_classified;
using algorithm::is_space;
using algorithm::is_alnum;
using algorithm::is_alpha;
using algorithm::is_cntrl;
using algorithm::is_digit;
using algorithm::is_graph;
using algorithm::is_lower;
using algorithm::is_upper;
using algorithm::is_print;
using algorithm::is_punct;
using algorithm::is_xdigit;
using algorithm::is_any_of;
using algorithm::is_from_range;
} // namespace boost
#endif // BOOST_STRING_PREDICATE_HPP
// Boost string_algo library compare.hpp header file -------------------------//
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_COMPARE_HPP
#define BOOST_STRING_COMPARE_HPP
#include <boost/algorithm/string/config.hpp>
#include <locale>
/*! \file
Defines element comparison predicates. Many algorithms in this library can
take an additional argument with a predicate used to compare elements.
This makes it possible, for instance, to have case insensitive versions
of the algorithms.
*/
namespace boost {
namespace algorithm {
// is_equal functor -----------------------------------------------//
//! is_equal functor
/*!
Standard STL equal_to only handle comparison between arguments
of the same type. This is a less restrictive version which wraps operator ==.
*/
struct is_equal
{
//! Function operator
/*!
Compare two operands for equality
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
return Arg1==Arg2;
}
};
//! case insensitive version of is_equal
/*!
Case insensitive comparison predicate. Comparison is done using
specified locales.
*/
struct is_iequal
{
//! Constructor
/*!
\param Loc locales used for comparison
*/
is_iequal( const std::locale& Loc=std::locale() ) :
m_Loc( Loc ) {}
//! Function operator
/*!
Compare two operands. Case is ignored.
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper(Arg1)==std::toupper(Arg2);
#else
return std::toupper<T1>(Arg1,m_Loc)==std::toupper<T2>(Arg2,m_Loc);
#endif
}
private:
std::locale m_Loc;
};
// is_less functor -----------------------------------------------//
//! is_less functor
/*!
Convenient version of standard std::less. Operation is templated, therefore it is
not required to specify the exact types upon the construction
*/
struct is_less
{
//! Functor operation
/*!
Compare two operands using > operator
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
return Arg1<Arg2;
}
};
//! case insensitive version of is_less
/*!
Case insensitive comparison predicate. Comparison is done using
specified locales.
*/
struct is_iless
{
//! Constructor
/*!
\param Loc locales used for comparison
*/
is_iless( const std::locale& Loc=std::locale() ) :
m_Loc( Loc ) {}
//! Function operator
/*!
Compare two operands. Case is ignored.
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper(Arg1)<std::toupper(Arg2);
#else
return std::toupper<T1>(Arg1,m_Loc)<std::toupper<T2>(Arg2,m_Loc);
#endif
}
private:
std::locale m_Loc;
};
// is_not_greater functor -----------------------------------------------//
//! is_not_greater functor
/*!
Convenient version of standard std::not_greater_to. Operation is templated, therefore it is
not required to specify the exact types upon the construction
*/
struct is_not_greater
{
//! Functor operation
/*!
Compare two operands using > operator
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
return Arg1<=Arg2;
}
};
//! case insensitive version of is_not_greater
/*!
Case insensitive comparison predicate. Comparison is done using
specified locales.
*/
struct is_not_igreater
{
//! Constructor
/*!
\param Loc locales used for comparison
*/
is_not_igreater( const std::locale& Loc=std::locale() ) :
m_Loc( Loc ) {}
//! Function operator
/*!
Compare two operands. Case is ignored.
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper(Arg1)<=std::toupper(Arg2);
#else
return std::toupper<T1>(Arg1,m_Loc)<=std::toupper<T2>(Arg2,m_Loc);
#endif
}
private:
std::locale m_Loc;
};
} // namespace algorithm
// pull names to the boost namespace
using algorithm::is_equal;
using algorithm::is_iequal;
using algorithm::is_less;
using algorithm::is_iless;
using algorithm::is_not_greater;
using algorithm::is_not_igreater;
} // namespace boost
#endif // BOOST_STRING_COMPARE_HPP
// Boost string_algo library concept.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CONCEPT_HPP
#define BOOST_STRING_CONCEPT_HPP
#include <boost/concept_check.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
/*! \file
Defines concepts used in string_algo library
*/
namespace boost {
namespace algorithm {
//! Finder concept
/*!
Defines the Finder concept. Finder is a functor which selects
an arbitrary part of a string. Search is performed on
the range specified by starting and ending iterators.
Result of the find operation must be convertible to iterator_range.
*/
template<typename FinderT, typename IteratorT>
struct FinderConcept
{
private:
typedef iterator_range<IteratorT> range;
public:
void constraints()
{
// Operation
r=(*pF)(i,i);
}
private:
range r;
IteratorT i;
FinderT* pF;
}; // Finder_concept
//! Formatter concept
/*!
Defines the Formatter concept. Formatter is a functor, which
takes a result from a finder operation and transforms it
in a specific way.
Result must be a container supported by container_traits,
or a reference to it.
*/
template<typename FormatterT, typename FinderT, typename IteratorT>
struct FormatterConcept
{
public:
void constraints()
{
// Operation
::boost::begin((*pFo)( (*pF)(i,i) ));
::boost::end((*pFo)( (*pF)(i,i) ));
}
private:
IteratorT i;
FinderT* pF;
FormatterT *pFo;
}; // FormatterConcept;
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_CONCEPT_HPP
// Boost string_algo library config.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CONFIG_HPP
#define BOOST_STRING_CONFIG_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#ifdef BOOST_STRING_DEDUCED_TYPENAME
# error "macro already defined!"
#endif
#define BOOST_STRING_TYPENAME BOOST_DEDUCED_TYPENAME
// Metrowerks workaround
#if BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x
#pragma parse_func_templ off
#endif
#endif // BOOST_STRING_CONFIG_HPP
// Boost string_algo library constants.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CONSTANTS_HPP
#define BOOST_STRING_CONSTANTS_HPP
namespace boost {
namespace algorithm {
//! Token compression mode
/*!
Specifies token compression mode for the token_finder.
*/
enum token_compress_mode_type
{
token_compress_on, //!< Compress adjacent tokens
token_compress_off //!< Do not compress adjacent tokens
};
} // namespace algorithm
// pull the names to the boost namespace
using algorithm::token_compress_on;
using algorithm::token_compress_off;
} // namespace boost
#endif // BOOST_STRING_CONSTANTS_HPP
// Boost string_algo library string_funct.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CASE_CONV_DETAIL_HPP
#define BOOST_STRING_CASE_CONV_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <locale>
#include <functional>
#include <boost/type_traits/make_unsigned.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// case conversion functors -----------------------------------------------//
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif
// a tolower functor
template<typename CharT>
struct to_lowerF
{
typedef CharT argument_type;
typedef CharT result_type;
// Constructor
to_lowerF( const std::locale& Loc ) : m_Loc( &Loc ) {}
// Operation
CharT operator ()( CharT Ch ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::tolower( static_cast<typename boost::make_unsigned <CharT>::type> ( Ch ));
#else
return std::tolower<CharT>( Ch, *m_Loc );
#endif
}
private:
const std::locale* m_Loc;
};
// a toupper functor
template<typename CharT>
struct to_upperF
{
typedef CharT argument_type;
typedef CharT result_type;
// Constructor
to_upperF( const std::locale& Loc ) : m_Loc( &Loc ) {}
// Operation
CharT operator ()( CharT Ch ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper( static_cast<typename boost::make_unsigned <CharT>::type> ( Ch ));
#else
return std::toupper<CharT>( Ch, *m_Loc );
#endif
}
private:
const std::locale* m_Loc;
};
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
// algorithm implementation -------------------------------------------------------------------------
// Transform a range
template<typename OutputIteratorT, typename RangeT, typename FunctorT>
OutputIteratorT transform_range_copy(
OutputIteratorT Output,
const RangeT& Input,
FunctorT Functor)
{
return std::transform(
::boost::begin(Input),
::boost::end(Input),
Output,
Functor);
}
// Transform a range (in-place)
template<typename RangeT, typename FunctorT>
void transform_range(
const RangeT& Input,
FunctorT Functor)
{
std::transform(
::boost::begin(Input),
::boost::end(Input),
::boost::begin(Input),
Functor);
}
template<typename SequenceT, typename RangeT, typename FunctorT>
inline SequenceT transform_range_copy(
const RangeT& Input,
FunctorT Functor)
{
return SequenceT(
::boost::make_transform_iterator(
::boost::begin(Input),
Functor),
::boost::make_transform_iterator(
::boost::end(Input),
Functor));
}
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_CASE_CONV_DETAIL_HPP