IAP GITLAB

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

added singleton, make RNGManager singleton

parent 334037ba
No related branches found
No related tags found
No related merge requests found
add_subdirectory (Utilities)
add_subdirectory (Units) add_subdirectory (Units)
add_subdirectory (Geometry) add_subdirectory (Geometry)
add_subdirectory (Particles) add_subdirectory (Particles)
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#ifndef _include_RNGManager_h_ #ifndef _include_RNGManager_h_
#define _include_RNGManager_h_ #define _include_RNGManager_h_
#include <corsika/utl/Singleton.h>
#include <map> #include <map>
#include <random> #include <random>
#include <sstream> #include <sstream>
...@@ -25,10 +27,16 @@ namespace corsika::random { ...@@ -25,10 +27,16 @@ namespace corsika::random {
using RNG = std::mt19937; //!< the actual RNG type that will be used using RNG = std::mt19937; //!< the actual RNG type that will be used
class RNGManager { class RNGManager : public corsika::utl::Singleton<RNGManager> {
friend class corsika::utl::Singleton<RNGManager>;
std::map<std::string, RNG> rngs; std::map<std::string, RNG> rngs;
std::map<std::string, std::seed_seq> seeds; std::map<std::string, std::seed_seq> seeds;
protected:
RNGManager() {}
public: public:
/*! /*!
* This function is to be called by a module requiring a random-number * This function is to be called by a module requiring a random-number
......
...@@ -20,7 +20,7 @@ using namespace corsika::random; ...@@ -20,7 +20,7 @@ using namespace corsika::random;
SCENARIO("random-number streams can be registered and retrieved") { SCENARIO("random-number streams can be registered and retrieved") {
GIVEN("a RNGManager") { GIVEN("a RNGManager") {
RNGManager rngManager; RNGManager& rngManager = RNGManager::GetInstance();
WHEN("a sequence is registered by name") { WHEN("a sequence is registered by name") {
rngManager.RegisterRandomStream("stream_A"); rngManager.RegisterRandomStream("stream_A");
......
#ifndef _corsika_utl_Bit_h_
#define _corsika_utl_Bit_h_
/**
\author Hans Dembinski
\author Lukas Nellen
\author Darko Veberic
\date 27 Jan 2014
\version $Id: Bit.h 25126 2014-02-03 22:13:10Z darko $
*/
#include <exception>
// #include <utl/AugerException.h>
namespace corsika::utl {
namespace Bit {
template<typename T>
class Array {
public:
Array(T& target) : fTarget(target) { }
class Bit {
public:
Bit(T& target, T mask) : fTarget(target), fMask(mask) { }
operator bool() const { return fTarget & fMask; }
bool operator~() const { return !bool(*this); }
Bit&
operator=(const bool value)
{
if (value)
fTarget |= fMask;
else
fTarget &= ~fMask;
return *this;
}
Bit& Flip() { return *this = ~(*this); }
private:
T& fTarget;
T fMask;
};
Bit operator[](unsigned int position)
{ return Bit(fTarget, T(1) << position); }
Bit
At(unsigned int position)
{
if (position >= 8*sizeof(T))
//throw std::exceptionOutOfBoundException("Running out of bits.");
throw std::exception("Running out of bits.");
return (*this)[position];
}
template<typename M>
Array& Mask(const M mask, const bool value)
{ Bit(fTarget, mask) = value; return *this; }
template<typename M>
T Get(const M mask) { return fTarget & T(mask); }
private:
T& fTarget;
};
}
// helper
template<typename T>
inline
Bit::Array<T>
AsBitArray(T& target)
{
return Bit::Array<T>(target);
}
}
#endif
set (
UTILITIES_SOURCES
Dummy.cc
)
set (
UTILITIES_HEADERS
Dummy.h
Bit.h
Test.h
Singleton.h
)
set (
UTILITIES_NAMESPACE
corsika/utl
)
add_library (CORSIKAutilities STATIC ${UTILITIES_SOURCES})
CORSIKA_COPY_HEADERS_TO_NAMESPACE (CORSIKAutilities ${UTILITIES_NAMESPACE} ${UTILITIES_HEADERS})
set_target_properties (
CORSIKAutilities
PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION 1
PUBLIC_HEADER "${UTILITIES_HEADERS}"
)
# target dependencies on other libraries (also the header onlys)
#target_link_libraries (
# )
target_include_directories (
CORSIKAutilities
PUBLIC
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:include/include>
)
install (
TARGETS CORSIKAutilities
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include/${UTILITIES_NAMESPACE}
)
# --------------------
# code unit testing
# add_executable (testBit testBit.cc)
# target_link_libraries (
# testBit
# CORSIKAutilities
# CORSIKAthirdparty # for catch2
# )
# add_test (NAME testBit COMMAND testBit)
#include <corsika/utl/Dummy.h>
using namespace corsika::utl;
// big void...
#ifndef _include_corsika_utilties_dummy_h_
#define _include_corsika_utilties_dummy_h_
namespace corsika::utl {
// void....
}
#endif
#ifndef _corsika_utl_Singleton_h_
#define _corsika_utl_Singleton_h_
//#define OFFLINE_USE_GAMMA_SINGLETON
namespace corsika::utl {
#ifndef OFFLINE_USE_GAMMA_SINGLETON
/**
* \class Singleton Singleton.h utl/Singleton.h
*
* \brief Curiously Recurring Template Pattern (CRTP) for Meyers singleton
*
* The singleton class is implemented as follows
* \code
* #include <utl/Singleton.h>
*
* class SomeClass : public utl::Singleton<SomeClass> {
* ...
* private:
* // prevent creation, destruction
* SomeClass() { }
* ~SomeClass() { }
*
* friend class utl::Singleton<SomeClass>;
* };
* \endcode
* Singleton automatically prevents copying of the derived class.
*
* \author Darko Veberic
* \date 9 Aug 2006
* \version $Id: Singleton.h 25091 2014-01-30 09:49:57Z darko $
* \ingroup stl
*/
template<typename T>
class Singleton {
public:
static
T&
GetInstance()
# ifdef __MAKECINT__
;
# else
{
static T instance;
return instance;
}
# endif
protected:
// derived class can call ctor and dtor
Singleton() { }
~Singleton() { }
private:
// no one should do copies
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
};
#else
/// classical Gamma singleton
template<typename T>
class Singleton {
public:
static
T&
GetInstance()
{
if (!fgInstance)
fgInstance = new T;
return *fgInstance;
}
protected:
// derived class can call ctor and dtor
Singleton() { }
~Singleton() { }
private:
// no one should do copies
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
static T* fgInstance = 0;
};
#endif
/**
* \class LeakingSingleton Singleton.h utl/Singleton.h
*
* \brief CRTP for leaking singleton
*
* This type of creation (Gamma singleton) leaks the object at
* the end of the run, i.e. class T destructor does not get called
* in at_exit().
*
* This singleton can be implemented as follows
* \code
* #include <utl/Singleton.h>
*
* class SomeClass : public utl::LeakingSingleton<SomeClass> {
* ...
* private:
* // prevent creation, destruction
* SomeClass() { }
* ~SomeClass() { }
*
* friend class utl::LeakingSingleton<SomeClass>;
* };
* \endcode
* LeakingSingleton automatically prevents copying of the derived
* class.
*
* \author Darko Veberic
* \date 9 Aug 2006
* \version $Id: Singleton.h 25091 2014-01-30 09:49:57Z darko $
* \ingroup stl
*/
template<class T>
class LeakingSingleton {
public:
static
T&
GetInstance()
{
static T* const instance = new T;
return *instance;
}
protected:
// derived class can call ctor and dtor
LeakingSingleton() { }
~LeakingSingleton() { }
private:
// no one should do copies
LeakingSingleton(const LeakingSingleton&);
LeakingSingleton& operator=(const LeakingSingleton&);
};
}
#endif
#ifndef _utl_Test_h_
#define _utl_Test_h_
/**
\file
Tools to do simple testing in a readable way
\author Lukas Nellen
\author Darko Veberic
\version $Id: Test.h 31925 2018-09-25 16:02:12Z darko $
\date 08 Feb 2004
\ingroup testing
*/
#include <cmath>
#include <boost/format.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <utl/Triple.h>
namespace utl {
//! Predicate used in STL for searching for whitespace
struct IsSpace {
bool operator()(const char x) const
{ return x == ' ' || x == '\r' || x == '\n' || x == '\t'; }
};
/// Predicate for equality
class Equal {
public:
template<typename T>
bool operator()(const T& lhs, const T& rhs) const
{ return lhs == rhs; }
static const char* Name() { return "equal"; }
};
/// Predicate for less
class Less {
public:
template<typename T>
bool operator()(const T& lhs, const T& rhs) const
{ return lhs < rhs; }
static const char* Name() { return "less"; }
};
/// Predicate for less or equal
class LessOrEqual {
public:
template<typename T>
bool operator()(const T& lhs, const T& rhs) const
{ return lhs <= rhs; }
static const char* Name() { return "less or equal"; }
};
/// Predicate for greater
class Greater {
public:
template<typename T>
bool operator()(const T& lhs, const T& rhs) const
{ return lhs > rhs; }
static const char* Name() { return "greater"; }
};
/// Predicate for greater or equal
class GreaterOrEqual {
public:
template<typename T>
bool operator()(const T& lhs, const T& rhs) const
{ return lhs >= rhs; }
static const char* Name() { return "greater or equal"; }
};
/// Predicate for approximate equality (for floating point)
/** The default precision is 1e-6, but it can be changed at
construction time.
*/
class CloseTo {
public:
CloseTo(const double eps = 1e-6) : fEpsilon(eps) { }
template<typename T>
bool operator()(const T& lhs, const T& rhs) const
{ return IsCloseTo(lhs, rhs); }
boost::format Name() const
{ return boost::format("close (@%g) to") % fEpsilon; }
protected:
template<typename T>
bool IsCloseAbs(const T& lhs, const T& rhs) const
{ return std::abs(double(lhs) - double(rhs)) < fEpsilon; }
bool IsCloseAbs(const utl::Triple& lhs, const utl::Triple& rhs) const
{ return std::sqrt(TupleDist2(lhs, rhs)) < fEpsilon; }
template<typename T>
bool IsCloseRel(const T& lhs, const T& rhs) const
{ return 2*std::abs(double(lhs) - double(rhs)) / (std::abs(double(lhs)) + std::abs(double(rhs))) < fEpsilon; }
bool
IsCloseRel(const utl::Triple& lhs, const utl::Triple& rhs)
const
{
return (2*sqrt(TupleDist2(lhs, rhs)) /
(sqrt(TupleDist2(lhs, utl::Triple(0,0,0))) +
sqrt(TupleDist2(rhs, utl::Triple(0,0,0))))) < fEpsilon;
}
template<typename T>
bool
IsCloseTo(const T& lhs, const T& rhs)
const
{
if (IsCloseAbs(lhs, rhs))
return true;
else
return IsCloseRel(lhs, rhs);
}
// tuple distance
template<typename Head, typename Tail>
static
double
TupleDist2(const boost::tuples::cons<Head, Tail>& lhs,
const boost::tuples::cons<Head, Tail>& rhs)
{
const double t = lhs.get_head() - rhs.get_head();
return t*t + TupleDist2(lhs.get_tail(), rhs.get_tail());
}
static double TupleDist2(const boost::tuples::null_type& /*lhs*/,
const boost::tuples::null_type& /*rhs*/)
{ return 0; }
double fEpsilon;
};
class CloseAbs : public CloseTo {
public:
CloseAbs(const double eps = 1e-6) : CloseTo(eps) { }
template<typename T>
bool operator()(const T& lhs, const T& rhs) const
{ return IsCloseAbs(lhs, rhs); }
boost::format Name() const
{ return boost::format("absolutely close (@%g) to") % fEpsilon; }
};
class CloseRel : public CloseTo {
public:
CloseRel(const double eps = 1e-6) : CloseTo(eps) { }
template<typename T>
bool operator()(const T& lhs, const T& rhs) const
{ return IsCloseRel(lhs, rhs); }
boost::format Name() const
{ return boost::format("relatively close (@%g) to") % fEpsilon; }
};
template<typename Predicate>
class Not : public Predicate {
public:
Not() : Predicate() { }
Not(const double eps) : Predicate(eps) { }
template<typename T>
bool operator()(const T& x) const
{ return !Predicate::operator()(x); }
template<typename T, typename U>
bool operator()(const T& x, const U& y) const
{ return !Predicate::operator()(x, y); }
template<typename T, typename U, typename W>
bool operator()(const T& x, const U& y, const W& z) const
{ return !Predicate::operator()(x, y, z); }
static boost::format Name()
{ return boost::format("not-%s") % Predicate().Name(); }
};
inline
utl::Triple
Diff(const utl::Triple& lhs, const utl::Triple& rhs)
{
return utl::Triple(lhs.get<0>() - rhs.get<0>(),
lhs.get<1>() - rhs.get<1>(),
lhs.get<2>() - rhs.get<2>());
}
/// Test condition by evaluating a predicate
/** If the predicate evaluates to false, we print a failure message
with the values of the left- and right-hand side and the name of
the predicate. This information is normally not available when
using the CPPUNIT_ASSERT macro.
*/
template<class Predicate, typename T>
inline bool Test(const Predicate& pred, const T& lhs, const T& rhs)
{ return pred(lhs, rhs); }
/// Main test function
template<class Predicate, typename T>
inline bool Test(const T& lhs, const T& rhs)
{ return Test(Predicate(), lhs, rhs); }
/// Test function for predicates that take an option
template<class Predicate, typename T, typename U>
inline bool Test(const T& lhs, const T& rhs, const U& eps)
{ return Test(Predicate(eps), lhs, rhs); }
}
#endif
/**
\file
Test Bit functions
\author Hans Dembinski
\version $Id: testBit.cc 25126 2014-02-03 22:13:10Z darko $
\date 27 Jan 2014
\ingroup testing
*/
#include <corsika/utl/Test.h>
#include <tst/Verify.h>
#include <utl/Bit.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cstdio>
#include <iostream>
#include <bitset>
using namespace tst;
using namespace utl;
using namespace std;
/**
\ingroup testing
*/
class TestBit : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(TestBit);
CPPUNIT_TEST(TestGet);
CPPUNIT_TEST(TestSet);
CPPUNIT_TEST(TestMask);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() { }
void tearDown() { }
void
TestGet()
{
const int size = sizeof(int)*8;
const int bc2 = 12345;
int b2 = bc2;
bitset<size> b1(bc2);
ostringstream out1;
ostringstream out2;
ostringstream out3;
for (int i = 0; i < size; ++i) {
out1 << (b1[i] ? '^' : '.');
out2 << (AsBitArray(bc2)[i] ? '^' : '.');
out3 << (AsBitArray(b2)[i] ? '^' : '.');
}
CPPUNIT_ASSERT(Verify<Equal>(out1.str(), out2.str()));
CPPUNIT_ASSERT(Verify<Equal>(out1.str(), out3.str()));
}
void
TestSet()
{
const int size = sizeof(int)*8;
const int number = 12345;
bitset<size> b1(number);
int b2 = 11111;
for (int i = 0; i < size; ++i)
AsBitArray(b2)[i] = b1[i];
CPPUNIT_ASSERT(Verify<Equal>(b2, number));
}
void
TestMask()
{
const int n = (1 << 18) | (1 << 5);
int m = 0;
AsBitArray(m)[18] = true;
AsBitArray(m)[5] = true;
CPPUNIT_ASSERT(Verify<Equal>(n, m));
for (unsigned int i = 0; i < 8*sizeof(int); ++i)
AsBitArray(m)[i] = 0;
CPPUNIT_ASSERT(Verify<Equal>(m, 0));
m = 1;
AsBitArray(m).Mask(n, true);
CPPUNIT_ASSERT(Verify<Equal>(m, n+1));
AsBitArray(m).Mask(n, false);
CPPUNIT_ASSERT(Verify<Equal>(m, 1));
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestBit);
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