...
 
Commits (2)
......@@ -3,6 +3,9 @@ this is <CHANGELOG>
Recent development in Seitosh (bug fixes, new features, etc)
------------------------------------------------------------
01.11.2019: libtfxx
- commit 27491f4: let RNGgaussian support selection of rng type
28.06.2019: any2matlab
- commit 7efe5ac: fix variable declaration to make compiler happy
......
......@@ -96,7 +96,7 @@ SRC=$(wildcard $(addsuffix /*.cc,$(DIRSTOINCLUDE)))
TESTS=tests/commandlinetest.cc tests/fortraniotest.cc \
tests/stringtest.cc tests/handletest.cc tests/regextest.cc \
tests/filetest.cc tests/rangetest.cc tests/fstest.cc \
tests/exceptiontest.cc tests/misctest.cc
tests/exceptiontest.cc tests/misctest.cc tests/rngtest.cc
#tests/blitztest.cc
FTESTS=$(wildcard tests/*.f)
DOXYTXT=$(wildcard doxygen*.txt)
......
......@@ -28,52 +28,125 @@
*
* REVISIONS and CHANGES
* - 19/12/2007 V1.0 Thomas Forbriger
* - 01/11/2019 V1.1 support selection of random number generator type
*
* ============================================================================
*/
#define TF_RNG_CC_VERSION \
"TF_RNG_CC V1.0 "
"TF_RNG_CC V1.1"
#include <iostream>
#include <tfxx/rng.h>
#include <time.h>
#include <gsl/gsl_rng.h>
#include <string>
namespace tfxx {
namespace numeric {
/* ---------------------------------------------------------------------- */
// class RNGgaussian
// constructor
RNGgaussian::RNGgaussian(const double& std,
const double& mean):
const double& mean,
const char* type):
Mstd(std), Mmean(mean)
{
gsl_rng_env_setup();
const gsl_rng_type* T=gsl_rng_default;
MR=gsl_rng_alloc(T);
this->set();
if (std::string(type) == "default")
{
gsl_rng_env_setup();
const gsl_rng_type* T=gsl_rng_default;
MR=gsl_rng_alloc(T);
TFXX_assert(MR!=NULL, "gsl_rng_alloc(T) failed to initialize RNG");
}
else
{
const gsl_rng_type* T=NULL;
const gsl_rng_type **t, **t0;
t0 = gsl_rng_types_setup ();
for (t = t0; *t != 0; t++)
{
if (std::string((*t)->name)==std::string(type)) { T=(*t); }
}
TFXX_Xassert(T!=NULL, type, UTException);
MR=gsl_rng_alloc(T);
TFXX_assert(MR!=NULL, "gsl_rng_alloc(T) failed to initialize RNG");
}
this->set(gsl_rng_default_seed);
}
/* ---------------------------------------------------------------------- */
// destructor
RNGgaussian::~RNGgaussian()
{
gsl_rng_free(MR);
}
/* ---------------------------------------------------------------------- */
// return value
double RNGgaussian::value() const
{ return(Mmean+Mstd*gsl_ran_ugaussian(MR)); }
/* ---------------------------------------------------------------------- */
// return value
double RNGgaussian::operator()() const
{ return(this->value()); }
/* ---------------------------------------------------------------------- */
// set seed
void RNGgaussian::set(const unsigned long int& seed) const
{ gsl_rng_set(MR, seed); }
void RNGgaussian::set(const unsigned long int& seed)
{
gsl_rng_set(MR, seed);
Mseed=seed;
}
/* ---------------------------------------------------------------------- */
// set seed using time
void RNGgaussian::set() const
void RNGgaussian::set()
{ this->set(time(0)); }
/* ---------------------------------------------------------------------- */
/*! \brief Print list of random number generators to stream.
*
* \sa https://www.gnu.org/software/gsl/doc/html/rng.html#random-number-generator-algorithms
*/
void RNGgaussian::rng_list_types(std::ostream& os)
{
const gsl_rng_type **t, **t0;
t0 = gsl_rng_types_setup ();
for (t = t0; *t != 0; t++)
{
os << std::string((*t)->name) << std::endl;
}
} // RNGgaussian::rng_list_types(std::ostream* os)
/* ====================================================================== */
RNGgaussian::UTException::UTException(const char* type,
const char* file,
const int& line,
const char* condition):
TBase("unkown RNG type requested", file, line, condition),
Mtype(type)
{
if (this->report_on_construct_is_true())
{
std::cerr << " Requested RNG type: " << Mtype << std::endl;
}
} // RNGgaussian::UTException::UTException
} // namespace numeric
} // namespace tfxx
......
......@@ -28,6 +28,7 @@
*
* REVISIONS and CHANGES
* - 19/12/2007 V1.0 Thomas Forbriger
* - 01/11/2019 V1.1 support selection of random number generator type
*
* ============================================================================
*/
......@@ -36,8 +37,11 @@
#ifndef TF_RNG_H_VERSION
#define TF_RNG_H_VERSION \
"TF_RNG_H V1.0 "
"TF_RNG_H V1.1"
#include <tfxx/error.h>
#include <ostream>
#include <string>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
......@@ -56,28 +60,75 @@ namespace tfxx {
*/
namespace numeric {
/* ---------------------------------------------------------------------- */
/*! \brief Provide random numbers with Gaussian distribution.
* \ingroup group_numeric
*
* This class is an interface to the GSL random number generator.
* \sa https://www.gnu.org/software/gsl/doc/html/rng.html
*
* \note
* This class specifically returns values based on a normal distribution.
* If for some reason a second class shall be provided to return values
* based on a uniform distribution, only the value() member function will
* be different. It then would be appropriate to define an abstract base
* class from which RNGgaussion and RNGuniform are derived.
*/
class RNGgaussian {
public:
//! initialize random number generator
explicit RNGgaussian(const double& std=1.,
const double& mean=0.);
const double& mean=0.,
const char* type="default");
~RNGgaussian();
//! returns a random number
double operator()() const;
//! returns a random number
double value() const;
//! feed with seed value
void set(const unsigned long int& seed) const;
void set(const unsigned long int& seed);
//! use time as seed value
void set() const;
void set();
//! return type of random number generator
std::string type() const {return std::string(MR->type->name); }
//! return last seed value
unsigned long int seed() const { return Mseed; }
//! return standard deviation
double std() const { return Mstd; }
//! return mean
double mean() const { return Mmean; }
//! print list of random number generators to stream.
static void rng_list_types(std::ostream& os);
private:
//! store standard deviation and mean value
double Mstd, Mmean;
//! pointer to RNG
gsl_rng* MR;
//! memorize last seed value
unsigned long int Mseed;
public:
/*! \brief exception class for RNG indicating request for unkown type
*
* \sa TFXX_Xassert
* \sa tfxx::error::Exception
*/
class UTException: public tfxx::error::Exception
{
public:
//! base class
typedef tfxx::error::Exception TBase;
//! Create with message, failed assertion, and code position
UTException(const char* type,
const char* file,
const int& line,
const char* condition);
//! provide explicit virtual destructor
virtual ~UTException() { }
private:
//! pointer name string of requested RNG type
const char* Mtype;
}; // class UTException
}; // class RNGgaussian
} // namespace numeric
......
......@@ -72,7 +72,9 @@ STANDARDTEST=
# all that need the binary library
BINARYTEST=commandlinetest fortraniotest blitztest stringtest \
handletest regextest filetest rangetest fstest exceptiontest \
misctest
misctest
# all that need the binary library and libgsl
GSLTEST=rngtest
# F77 part of the I/O test
FORTRANTEST=fortranF77
......@@ -92,6 +94,7 @@ $(addsuffix .o,$(CXXTESTS)): %.o: %.cc
$(STANDARDTEST): %: %.o; $(CXX) -o $@ $< $(LDFLAGS)
$(BINARYTEST): %: %.o; $(CXX) -o $@ $< -ltfxx $(LDFLAGS)
$(GSLTEST): %: %.o; $(CXX) -o $@ $< -ltfxx -lgsl -lgslcblas $(LDFLAGS)
$(FORTRANTEST): %: %.o; $(CC) -o $@ $< -ltf $(LDFLAGS) -lf2c -lm
$(addsuffix .g77,$(FORTRANTEST)): %.g77: %.o77
$(FC) -o $@ $< $(LDFLAGS) -ltf77
......
/*! \file rngtest.cc
* \brief test random number generator module
*
* ----------------------------------------------------------------------------
*
* \author Thomas Forbriger
* \date 31/10/2019
*
* test random number generator module
*
* Copyright (c) 2019 by Thomas Forbriger (BFO Schiltach)
*
* REVISIONS and CHANGES
* - 31/10/2019 V1.0 Thomas Forbriger
*
* ============================================================================
*/
#define RNGTEST_VERSION \
"RNGTEST V1.0 test random number generator module"
#include <iostream>
#include <tfxx/commandline.h>
#include <tfxx/rng.h>
using std::cout;
using std::cerr;
using std::endl;
/* ---------------------------------------------------------------------- */
struct Options {
double mean,std;
unsigned long int seed;
bool seedset,verbose,listtypes;
std::string type;
int nsamples;
}; // struct Options
/* ---------------------------------------------------------------------- */
void report(const tfxx::numeric::RNGgaussian& rng)
{
cout << "RNG parameters:\n"
<< " type: " << rng.type() << "\n"
<< " seed: " << rng.seed() << "\n"
<< " mean: " << rng.mean() << "\n"
<< " std: " << rng.std() << endl;
} // void report(const tfxx::numeric::RNGgaussian& rng)
/* ---------------------------------------------------------------------- */
int main(int iargc, char* argv[])
{
// define usage information
char usage_text[]=
{
RNGTEST_VERSION "\n"
"usage: rngtest [-l] [-v] [-t type] [-seed v] [-mean v]\n"
" [-std v] [-n n] [run]\n"
" or: rngtest --help|-h" "\n"
};
// define full help text
char help_text[]=
{
"run run the program\n"
"-l print list of random number generators and exit\n"
"-v be verbose\n"
"-t type select random number generator of type \"type\"\n"
" use option -l for a list of available types\n"
" type \"default\" will make selection based on\n"
" environment variables\n"
"-seed v initialize RNG with seed value v\n"
"-mean v set mean value\n"
"-std v set standard deviation\n"
"-n n print n random numbers\n"
"\n"
"In case of no type selected or type set to \"default\" type\n"
"and seed value can be specified through environment variables.\n"
"Simply try\n"
"\n"
"GSL_RNG_TYPE=ranlux GSL_RNG_SEED=125 rngtest -v run\n"
};
// define commandline options
using namespace tfxx::cmdline;
static Declare options[]=
{
// 0: print help
{"help",arg_no,"-"},
// 1: verbose mode
{"v",arg_no,"-"},
// 2: print list of random number generators
{"l",arg_no,"-"},
// 3: type of RNG
{"t",arg_yes,"default"},
// 4: seed value
{"seed",arg_yes,"0."},
// 5: mean value
{"mean",arg_yes,"0."},
// 6: standard deviation
{"std",arg_yes,"1."},
// 7: number of samples to be printed
{"n",arg_yes,"10"},
{NULL}
};
// no arguments? print usage...
if (iargc<2)
{
cerr << usage_text << endl;
exit(0);
}
// collect options from commandline
Commandline cmdline(iargc, argv, options);
// help requested? print full help text...
if (cmdline.optset(0))
{
cerr << usage_text << endl;
cerr << help_text << endl;
exit(0);
}
Options opt;
opt.verbose=cmdline.optset(1);
opt.listtypes=cmdline.optset(2);
opt.type=cmdline.string_arg(3);
opt.seedset=cmdline.optset(4);
opt.seed=cmdline.long_arg(4);
opt.mean=cmdline.double_arg(5);
opt.std=cmdline.double_arg(6);
opt.nsamples=cmdline.int_arg(7);
if (opt.listtypes)
{
tfxx::numeric::RNGgaussian::rng_list_types(cout);
}
else
{
cout << RNGTEST_VERSION << endl;
if (opt.verbose)
{
cout << "Parameters specified on command line (maybe default):\n"
<< " type: " << opt.type << "\n"
<< " mean: " << opt.mean << "\n"
<< " std: " << opt.std << "\n"
<< " n: " << opt.nsamples << endl;
if (opt.seedset)
{
cout << " seed: " << opt.seed << endl;
}
else
{
cout << " no seed value specified" << endl;
}
}
// create RNG
tfxx::numeric::RNGgaussian rng(opt.std, opt.mean, opt.type.c_str());
if (opt.seedset) { rng.set(opt.seed); }
// report
if (opt.verbose) { report(rng); }
cout << "\nRandom numbers:" << endl;
for (int i=0; i<opt.nsamples; ++i)
{
cout << i << " " << rng.value() << endl;
}
cout << endl << "set new seed" << endl;
rng.set();
if (opt.verbose) { report(rng); }
cout << "\nRandom numbers:" << endl;
for (int i=0; i<opt.nsamples; ++i)
{
cout << i << " " << rng.value() << endl;
}
}
}
/* ----- END OF rngtest.cc ----- */