[DEV] add v1.66.0

This commit is contained in:
2018-01-12 21:47:58 +01:00
parent 87059bb1af
commit a97e9ae7d4
49032 changed files with 7668950 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
mt19937ar-files = [ glob mt19937ar.c ] ;
if $(mt19937ar-files)
{
alias mt19937ar : $(mt19937ar-files) : : <define>HAVE_MT19937AR_C ;
}
else
{
alias mt19937ar ;
}
exe random_speed.exe : random_speed.cpp mt19937ar : release ;
exe generate_table.exe : generate_table.cpp /boost//regex : <link>static ;
exe nondet_random_speed.exe : nondet_random_speed.cpp /boost//random : release <link>static ;
install random_speed : random_speed.exe : <install-type>EXE <location>. ;
install nondet_random_speed : nondet_random_speed.exe : <install-type>EXE <location>. ;
install generate_table : generate_table.exe : <install-type>EXE <location>. ;

View File

@@ -0,0 +1,133 @@
// generate_table.cpp
//
// Copyright (c) 2009
// Steven Watanabe
//
// 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)
#include <vector>
#include <utility>
#include <iostream>
#include <cstring>
#include <fstream>
#include <boost/regex.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
boost::regex generator_regex("(?:fixed-range )?([^:]+): (\\d+(?:\\.\\d+)?) nsec/loop = \\d+(?:\\.\\d+)? CPU cycles");
boost::regex distribution_regex("([^\\s]+)( virtual function)? ([^:]+): (\\d+(?:\\.\\d+)?) nsec/loop = \\d+(?:\\.\\d+)? CPU cycles");
std::string template_name(std::string arg) {
return boost::regex_replace(arg, boost::regex("[^\\w]"), "_");
}
struct compare_second {
template<class Pair>
bool operator()(const Pair& p1, const Pair& p2) const {
return (p1.second < p2.second);
}
};
typedef boost::multi_index_container<
std::string,
boost::mpl::vector<
boost::multi_index::sequenced<>,
boost::multi_index::hashed_unique<boost::multi_index::identity<std::string> >
>
> unique_list;
int main(int argc, char** argv) {
std::string suffix;
std::string id;
if(argc >= 2 && std::strcmp(argv[1], "-linux") == 0) {
suffix = "linux";
id = "Linux";
} else {
suffix = "windows";
id = "Windows";
}
std::vector<std::pair<std::string, double> > generator_info;
std::string line;
while(std::getline(std::cin, line)) {
boost::smatch match;
if(std::strncmp(line.c_str(), "counting ", 9) == 0) break;
if(boost::regex_match(line, match, generator_regex)) {
std::string generator(match[1]);
double time = boost::lexical_cast<double>(match[2]);
if(generator != "counting") {
generator_info.push_back(std::make_pair(generator, time));
}
} else {
std::cerr << "oops: " << line << std::endl;
}
}
double min = std::min_element(generator_info.begin(), generator_info.end(), compare_second())->second;
std::ofstream generator_defs("performance_data.qbk");
std::ofstream generator_performance(("generator_performance_" + suffix + ".qbk").c_str());
generator_performance << "[table Basic Generators (" << id << ")\n";
generator_performance << " [[generator] [M rn/sec] [time per random number \\[nsec\\]] "
"[relative speed compared to fastest \\[percent\\]]]\n";
typedef std::pair<std::string, double> pair_type;
BOOST_FOREACH(const pair_type& pair, generator_info) {
generator_defs << boost::format("[template %s_speed[] %d%%]\n")
% template_name(pair.first) % static_cast<int>(100*min/pair.second);
generator_performance << boost::format(" [[%s][%g][%g][%d%%]]\n")
% pair.first % (1000/pair.second) % pair.second % static_cast<int>(100*min/pair.second);
}
generator_performance << "]\n";
std::map<std::pair<std::string, std::string>, double> distribution_info;
unique_list generator_names;
unique_list distribution_names;
do {
boost::smatch match;
if(boost::regex_match(line, match, distribution_regex)) {
if(!match[2].matched && match[1] != "counting") {
std::string generator(match[1]);
std::string distribution(match[3]);
double time = boost::lexical_cast<double>(match[4]);
generator_names.push_back(generator);
distribution_names.push_back(distribution);
distribution_info.insert(std::make_pair(std::make_pair(distribution, generator), time));
}
} else {
std::cerr << "oops: " << line << std::endl;
}
} while(std::getline(std::cin, line));
std::ofstream distribution_performance(("distribution_performance_" + suffix + ".qbk").c_str());
distribution_performance << "[table Distributions (" << id << ")\n";
distribution_performance << " [[\\[M rn/sec\\]]";
BOOST_FOREACH(const std::string& generator, generator_names) {
distribution_performance << boost::format("[%s]") % generator;
}
distribution_performance << "]\n";
BOOST_FOREACH(const std::string& distribution, distribution_names) {
distribution_performance << boost::format(" [[%s]") % distribution;
BOOST_FOREACH(const std::string& generator, generator_names) {
std::map<std::pair<std::string, std::string>, double>::iterator pos =
distribution_info.find(std::make_pair(distribution, generator));
if(pos != distribution_info.end()) {
distribution_performance << boost::format("[%g]") % (1000/pos->second);
} else {
distribution_performance << "[-]";
}
}
distribution_performance << "]\n";
}
distribution_performance << "]\n";
}

View File

@@ -0,0 +1,60 @@
/* boost nondet_random_speed.cpp performance test
*
* Copyright Jens Maurer 2000
* 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)
*
* $Id$
*
*/
#include <iostream>
#include <string>
#include <boost/timer.hpp>
#include <boost/random/random_device.hpp>
// set to your CPU frequency
static const double cpu_frequency = 1.87 * 1e9;
static void show_elapsed(double end, int iter, const std::string & name)
{
double usec = end/iter*1e6;
double cycles = usec * cpu_frequency/1e6;
std::cout << name << ": "
<< usec*1e3 << " nsec/loop = "
<< cycles << " CPU cycles"
<< std::endl;
}
template<class Result, class RNG>
static void timing(RNG & rng, int iter, const std::string& name)
{
volatile Result tmp; // make sure we're not optimizing too much
boost::timer t;
for(int i = 0; i < iter; i++)
tmp = rng();
show_elapsed(t.elapsed(), iter, name);
}
template<class RNG>
void run(int iter, const std::string & name)
{
RNG rng;
timing<long>(rng, iter, name);
}
int main(int argc, char*argv[])
{
if(argc != 2) {
std::cerr << "usage: " << argv[0] << " iterations" << std::endl;
return 1;
}
int iter = std::atoi(argv[1]);
boost::random::random_device dev;
timing<unsigned int>(dev, iter, "random_device");
return 0;
}

View File

@@ -0,0 +1,399 @@
/* boost random_speed.cpp performance measurements
*
* Copyright Jens Maurer 2000
* 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)
*
* $Id$
*/
#include <iostream>
#include <cstdlib>
#include <string>
#include <boost/config.hpp>
#include <boost/random.hpp>
#include <boost/progress.hpp>
#include <boost/shared_ptr.hpp>
/*
* Configuration Section
*/
// define if your C library supports the non-standard drand48 family
//#define HAVE_DRAND48
// define if you have the original mt19937int.c (with commented out main())
#undef HAVE_MT19937INT_C
// define if you have the original mt19937ar.c (with commented out main())
// #define HAVE_MT19937AR_C
// set to your CPU frequency
static const double cpu_frequency = 1.87 * 1e9;
/*
* End of Configuration Section
*/
/*
* General portability note:
* MSVC mis-compiles explicit function template instantiations.
* For example, f<A>() and f<B>() are both compiled to call f<A>().
* BCC is unable to implicitly convert a "const char *" to a std::string
* when using explicit function template instantiations.
*
* Therefore, avoid explicit function template instantiations.
*/
// provides a run-time configurable linear congruential generator, just
// for comparison
template<class IntType>
class linear_congruential
{
public:
typedef IntType result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
linear_congruential(IntType x0, IntType a, IntType c, IntType m)
: _x(x0), _a(a), _c(c), _m(m) { }
// compiler-generated copy ctor and assignment operator are fine
void seed(IntType x0, IntType a, IntType c, IntType m)
{ _x = x0; _a = a; _c = c; _m = m; }
void seed(IntType x0) { _x = x0; }
result_type operator()() { _x = (_a*_x+_c) % _m; return _x; }
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _c == 0 ? 1 : 0; }
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _m -1; }
private:
IntType _x, _a, _c, _m;
};
// simplest "random" number generator possible, to check on overhead
class counting
{
public:
typedef int result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
counting() : _x(0) { }
result_type operator()() { return ++_x; }
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 1; }
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (std::numeric_limits<result_type>::max)(); }
private:
int _x;
};
// decoration of variate_generator to make it runtime-exchangeable
// for speed comparison
template<class Ret>
class RandomGenBase
{
public:
virtual Ret operator()() = 0;
virtual ~RandomGenBase() { }
};
template<class URNG, class Dist, class Ret = typename Dist::result_type>
class DynamicRandomGenerator
: public RandomGenBase<Ret>
{
public:
DynamicRandomGenerator(URNG& urng, const Dist& d) : _rng(urng, d) { }
Ret operator()() { return _rng(); }
private:
boost::variate_generator<URNG&, Dist> _rng;
};
template<class Ret>
class GenericRandomGenerator
{
public:
typedef Ret result_type;
GenericRandomGenerator() { };
void set(boost::shared_ptr<RandomGenBase<Ret> > p) { _p = p; }
// takes over ownership
void set(RandomGenBase<Ret> * p) { _p.reset(p); }
Ret operator()() { return (*_p)(); }
private:
boost::shared_ptr<RandomGenBase<Ret> > _p;
};
// start implementation of measuring timing
void show_elapsed(double end, int iter, const std::string & name)
{
double usec = end/iter*1e6;
double cycles = usec * cpu_frequency/1e6;
std::cout << name << ": "
<< usec*1e3 << " nsec/loop = "
<< cycles << " CPU cycles"
<< std::endl;
}
#if 0
template<class RNG>
void timing(RNG & rng, int iter, const std::string& name)
{
// make sure we're not optimizing too much
volatile typename RNG::result_type tmp;
boost::timer t;
for(int i = 0; i < iter; i++)
tmp = rng();
show_elapsed(t.elapsed(), iter, name);
}
#endif
// overload for using a copy, allows more concise invocation
template<class RNG>
void timing(RNG rng, int iter, const std::string& name)
{
// make sure we're not optimizing too much
volatile typename RNG::result_type tmp;
boost::timer t;
for(int i = 0; i < iter; i++)
tmp = rng();
show_elapsed(t.elapsed(), iter, name);
}
template<class RNG>
void timing_sphere(RNG rng, int iter, const std::string & name)
{
boost::timer t;
for(int i = 0; i < iter; i++) {
// the special return value convention of uniform_on_sphere saves 20% CPU
const std::vector<double> & tmp = rng();
(void) tmp[0];
}
show_elapsed(t.elapsed(), iter, name);
}
template<class RNG>
void run(int iter, const std::string & name, RNG rng)
{
std::cout << (RNG::has_fixed_range ? "fixed-range " : "");
// BCC has trouble with string autoconversion for explicit specializations
// make sure we're not optimizing too much
volatile typename RNG::result_type tmp;
boost::timer t;
for(int i = 0; i < iter; i++)
tmp = rng();
show_elapsed(t.elapsed(), iter, name);
}
#ifdef HAVE_DRAND48
// requires non-standard C library support for srand48/lrand48
struct lrand48_ {
static const bool has_fixed_range = false;
typedef long result_type;
lrand48_() {
using namespace std;
srand48(1);
}
result_type operator()() {
using namespace std;
return lrand48();
}
};
#endif
#ifdef HAVE_MT19937INT_C // requires the original mt19937int.c
extern "C" void sgenrand(unsigned long);
extern "C" unsigned long genrand();
void run(int iter, const std::string & name, float)
{
sgenrand(4357);
timing(genrand, iter, name, 0u);
}
#endif
#ifdef HAVE_MT19937AR_C
extern "C" {
void init_genrand(unsigned long s);
unsigned long genrand_int32(void);
}
struct mt19937_c {
static const bool has_fixed_range = false;
mt19937_c() {
init_genrand(5489);
}
typedef unsigned long result_type;
result_type operator()() {
return genrand_int32();
}
};
#endif
template<class PRNG, class Dist>
inline boost::variate_generator<PRNG&, Dist> make_gen(PRNG & rng, Dist d)
{
return boost::variate_generator<PRNG&, Dist>(rng, d);
}
template<class Gen>
void distrib(int iter, const std::string & name, const Gen &)
{
Gen gen;
timing(make_gen(gen, boost::random::uniform_int_distribution<>(-2, 4)),
iter, name + " uniform_int");
timing(make_gen(gen, boost::random::uniform_smallint<>(-2, 4)),
iter, name + " uniform_smallint");
timing(make_gen(gen, boost::random::bernoulli_distribution<>(0.5)),
iter, name + " bernoulli");
timing(make_gen(gen, boost::random::geometric_distribution<>(0.5)),
iter, name + " geometric");
timing(make_gen(gen, boost::random::binomial_distribution<int>(4, 0.8)),
iter, name + " binomial");
timing(make_gen(gen, boost::random::negative_binomial_distribution<int>(4, 0.8)),
iter, name + " negative_binomial");
timing(make_gen(gen, boost::random::poisson_distribution<>(1)),
iter, name + " poisson");
timing(make_gen(gen, boost::random::uniform_real_distribution<>(-5.3, 4.8)),
iter, name + " uniform_real");
timing(make_gen(gen, boost::random::uniform_01<>()),
iter, name + " uniform_01");
timing(make_gen(gen, boost::random::triangle_distribution<>(1, 2, 7)),
iter, name + " triangle");
timing(make_gen(gen, boost::random::exponential_distribution<>(3)),
iter, name + " exponential");
timing(make_gen(gen, boost::random::normal_distribution<>()),
iter, name + " normal polar");
timing(make_gen(gen, boost::random::lognormal_distribution<>()),
iter, name + " lognormal");
timing(make_gen(gen, boost::random::chi_squared_distribution<>(4)),
iter, name + " chi squared");
timing(make_gen(gen, boost::random::cauchy_distribution<>()),
iter, name + " cauchy");
timing(make_gen(gen, boost::random::fisher_f_distribution<>(4, 5)),
iter, name + " fisher f");
timing(make_gen(gen, boost::random::student_t_distribution<>(7)),
iter, name + " student t");
timing(make_gen(gen, boost::random::gamma_distribution<>(2.8)),
iter, name + " gamma");
timing(make_gen(gen, boost::random::weibull_distribution<>(3)),
iter, name + " weibull");
timing(make_gen(gen, boost::random::extreme_value_distribution<>()),
iter, name + " extreme value");
timing_sphere(make_gen(gen, boost::random::uniform_on_sphere<>(3)),
iter/10, name + " uniform_on_sphere");
}
int main(int argc, char*argv[])
{
if(argc != 2) {
std::cerr << "usage: " << argv[0] << " iterations" << std::endl;
return 1;
}
// okay, it's ugly, but it's only used here
int iter =
#ifndef BOOST_NO_STDC_NAMESPACE
std::
#endif
atoi(argv[1]);
#if !defined(BOOST_NO_INT64_T) && \
!defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
run(iter, "rand48", boost::rand48());
linear_congruential<boost::uint64_t>
lcg48(boost::uint64_t(1)<<16 | 0x330e,
boost::uint64_t(0xDEECE66DUL) | (boost::uint64_t(0x5) << 32), 0xB,
boost::uint64_t(1)<<48);
timing(lcg48, iter, "lrand48 run-time");
#endif
#ifdef HAVE_DRAND48
// requires non-standard C library support for srand48/lrand48
run(iter, "lrand48", lrand48_()); // coded for lrand48()
#endif
run(iter, "minstd_rand0", boost::minstd_rand0());
run(iter, "minstd_rand", boost::minstd_rand());
run(iter, "ecuyer combined", boost::ecuyer1988());
run(iter, "kreutzer1986", boost::kreutzer1986());
run(iter, "taus88", boost::taus88());
run(iter, "knuth_b", boost::random::knuth_b());
run(iter, "hellekalek1995 (inversive)", boost::hellekalek1995());
run(iter, "mt11213b", boost::mt11213b());
run(iter, "mt19937", boost::mt19937());
#if !defined(BOOST_NO_INT64_T)
run(iter, "mt19937_64", boost::mt19937_64());
#endif
run(iter, "lagged_fibonacci607", boost::lagged_fibonacci607());
run(iter, "lagged_fibonacci1279", boost::lagged_fibonacci1279());
run(iter, "lagged_fibonacci2281", boost::lagged_fibonacci2281());
run(iter, "lagged_fibonacci3217", boost::lagged_fibonacci3217());
run(iter, "lagged_fibonacci4423", boost::lagged_fibonacci4423());
run(iter, "lagged_fibonacci9689", boost::lagged_fibonacci9689());
run(iter, "lagged_fibonacci19937", boost::lagged_fibonacci19937());
run(iter, "lagged_fibonacci23209", boost::lagged_fibonacci23209());
run(iter, "lagged_fibonacci44497", boost::lagged_fibonacci44497());
run(iter, "subtract_with_carry", boost::random::ranlux_base());
run(iter, "subtract_with_carry_01", boost::random::ranlux_base_01());
run(iter, "ranlux3", boost::ranlux3());
run(iter, "ranlux4", boost::ranlux4());
run(iter, "ranlux3_01", boost::ranlux3_01());
run(iter, "ranlux4_01", boost::ranlux4_01());
run(iter, "ranlux64_3", boost::ranlux3());
run(iter, "ranlux64_4", boost::ranlux4());
run(iter, "ranlux64_3_01", boost::ranlux3_01());
run(iter, "ranlux64_4_01", boost::ranlux4_01());
run(iter, "ranlux24", boost::ranlux3());
run(iter, "ranlux48", boost::ranlux4());
run(iter, "counting", counting());
#ifdef HAVE_MT19937INT_C
// requires the original mt19937int.c
run<float>(iter, "mt19937 original"); // coded for sgenrand()/genrand()
#endif
#ifdef HAVE_MT19937AR_C
run(iter, "mt19937ar.c", mt19937_c());
#endif
distrib(iter, "counting", counting());
distrib(iter, "minstd_rand", boost::minstd_rand());
distrib(iter, "kreutzer1986", boost::kreutzer1986());
distrib(iter, "mt19937", boost::mt19937());
distrib(iter, "lagged_fibonacci607", boost::lagged_fibonacci607());
}