Skip to content

Commit

Permalink
Replace boost by std (issue #6)
Browse files Browse the repository at this point in the history
  • Loading branch information
philipp-classen committed Mar 31, 2018
1 parent 1941a57 commit 310f21b
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 67 deletions.
6 changes: 3 additions & 3 deletions examples/src/sampleOutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
using namespace cppqc;

// clang-format off
const std::map<std::string, boost::function<void ()> >
sampleOutputCommand = boost::assign::map_list_of<std::string, boost::function<void ()> >
const std::map<std::string, std::function<void ()> >
sampleOutputCommand = boost::assign::map_list_of<std::string, std::function<void ()> >
("bool", boost::bind(sampleOutput<bool>, Arbitrary<bool>(), boost::ref(std::cout), 0, 0))
("char", boost::bind(sampleOutput<char>, Arbitrary<char>(), boost::ref(std::cout), 0, 0))
("wchar_t", boost::bind(sampleOutput<wchar_t>, Arbitrary<wchar_t>(), boost::ref(std::cout), 0, 0))
Expand All @@ -54,7 +54,7 @@ sampleOutputCommand = boost::assign::map_list_of<std::string, boost::function<vo
("double", boost::bind(sampleOutput<double>, Arbitrary<double>(), boost::ref(std::cout), 0, 0))
("long double", boost::bind(sampleOutput<long double>, Arbitrary<long double>(), boost::ref(std::cout), 0, 0))
("pair", boost::bind(sampleOutput<std::pair<int,int> >, Arbitrary<std::pair<int,int> >(), boost::ref(std::cout), 0, 0))
("tuple", boost::bind(sampleOutput<std::tuple<int,int,int> >, tupleOf<int,int,int>(), boost::ref(std::cout), 0, 0))
("tuple", boost::bind(sampleOutput<std::tuple<int,int,int> >, tupleOf<int,int,int>(), boost::ref(std::cout), 0, 0))
("string", boost::bind(sampleOutput<std::string>, Arbitrary<std::string>(), boost::ref(std::cout), 0, 0));
// clang-format on

Expand Down
6 changes: 3 additions & 3 deletions examples/src/sampleShrinkOutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ std::ostream& operator<<(std::ostream& out, const std::pair<T1, T2>& x) {
} // namespace std

// clang-format off
const std::map<std::string, boost::function<void ()> >
sampleShrinkOutputCommand = boost::assign::map_list_of<std::string, boost::function<void ()> >
const std::map<std::string, std::function<void ()> >
sampleShrinkOutputCommand = boost::assign::map_list_of<std::string, std::function<void ()> >
("bool", boost::bind(sampleShrinkOutput<bool>, Arbitrary<bool>(), boost::ref(std::cout), 0, true, 0))
("char", boost::bind(sampleShrinkOutput<char>, Arbitrary<char>(), boost::ref(std::cout), 0, true, 0))
("wchar_t", boost::bind(sampleShrinkOutput<wchar_t>, Arbitrary<wchar_t>(), boost::ref(std::cout), 0, true, 0))
Expand All @@ -61,7 +61,7 @@ sampleShrinkOutputCommand = boost::assign::map_list_of<std::string, boost::funct
("double", boost::bind(sampleShrinkOutput<double>, Arbitrary<double>(), boost::ref(std::cout), 0, true, 0))
("long double", boost::bind(sampleShrinkOutput<long double>, Arbitrary<long double>(), boost::ref(std::cout), 0, true, 0))
("pair", boost::bind(sampleShrinkOutput<std::pair<int,int> >, Arbitrary<std::pair<int,int> >(), boost::ref(std::cout), 0, true, 0))
("tuple", boost::bind(sampleShrinkOutput<std::tuple<int,int,int> >, tupleOf<int,int,int>(), boost::ref(std::cout), 0, true, 0))
("tuple", boost::bind(sampleShrinkOutput<std::tuple<int,int,int> >, tupleOf<int,int,int>(), boost::ref(std::cout), 0, true, 0))
("string", boost::bind(sampleShrinkOutput<std::string>, Arbitrary<std::string>(), boost::ref(std::cout), 0, true, 0));
// clang-format on

Expand Down
80 changes: 49 additions & 31 deletions include/cppqc/Arbitrary.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,50 +29,70 @@
#include "Generator.h"

#include <limits>

#include <boost/random/poisson_distribution.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/uniform_smallint.hpp>
#include <boost/random/variate_generator.hpp>
#include <random>

namespace cppqc {

// default generators

/*
* Generates an integral number from a bounded domain defined by
* the integer type.
* The number will be chosen uniformly, that means big numbers
* are equally likely as numbers near 0.
*/
template <class Integral>
Integral arbitrarySizedIntegral(RngEngine& rng, std::size_t size) {
boost::uniform_int<Integral> dist(std::numeric_limits<Integral>::is_signed
? -Integral(size)
: Integral(size),
Integral(size));
Integral arbitraryBoundedIntegral(RngEngine& rng, std::size_t /*size*/) {
std::uniform_int_distribution<Integral> dist{
std::numeric_limits<Integral>::lowest(),
std::numeric_limits<Integral>::max()};
return dist(rng);
}

template <class Integral>
Integral arbitraryBoundedIntegral(RngEngine& rng, std::size_t /*size*/) {
boost::uniform_int<Integral> dist(std::numeric_limits<Integral>::min(),
std::numeric_limits<Integral>::max());
Integral arbitrarySizedIntegral(RngEngine& rng, std::size_t size) {
if (size > std::numeric_limits<Integral>::max()) {
return arbitraryBoundedIntegral<Integral>(rng, size);
}

std::uniform_int_distribution<Integral> dist(
std::numeric_limits<Integral>::is_signed ? -Integral(size)
: Integral(size),
Integral(size));
return dist(rng);
}

/*
* Generates an integral number from a bounded domain. The number is
* chosen from the entire range of the type, but numbers near 0 are
* generated more often than big numbers.
*/
template <class Integral>
Integral arbitrarySizedBoundedIntegral(RngEngine& rng, std::size_t size) {
boost::poisson_distribution<Integral> dist(size == 0 ? 1 : size);
boost::variate_generator<RngEngine&, boost::uniform_01<>> gen(
rng, boost::uniform_01<>());
Integral r = dist(gen);
if (std::numeric_limits<Integral>::is_signed) {
if (boost::uniform_smallint<int>(0, 1)(rng))
r = -r;
const double limit =
std::min(double(size), double(std::numeric_limits<Integral>::max()));

// When dividing by 3, about 99% of the values should be
// in the interval [-limit, limit]
std::normal_distribution<> dist{0, 1.0 + limit / 3};
for (;;) {
double r = dist(rng);

if (!std::numeric_limits<Integral>::is_signed) {
r = std::abs(r);
}

if (r >= std::numeric_limits<Integral>::lowest() &&
r <= std::numeric_limits<Integral>::max()) {
return static_cast<Integral>(r);
}
}
return r;
}

template <class Real>
Real arbitrarySizedReal(RngEngine& rng, std::size_t size) {
boost::uniform_real<Real> dist(-Real(size + 1.0), Real(size + 1.0));
std::uniform_real_distribution<Real> dist{-Real(size + 1.0),
Real(size + 1.0)};
return dist(rng);
}

Expand Down Expand Up @@ -123,8 +143,8 @@ std::vector<Real> shrinkReal(Real x) {

template <class T>
struct Arbitrary {
typedef boost::function<T(RngEngine&, std::size_t)> unGenType;
typedef boost::function<std::vector<T>(T)> shrinkType;
using unGenType = std::function<T(RngEngine&, std::size_t)>;
using shrinkType = std::function<std::vector<T>(T)>;

static const unGenType unGen;
static const shrinkType shrink;
Expand Down Expand Up @@ -160,9 +180,7 @@ const typename Arbitrary<T>::shrinkType Arbitrary<T>::shrink =
// included specializations

inline bool arbitraryBool(RngEngine& rng, std::size_t /*size*/) {
if (boost::uniform_smallint<int>(0, 1)(rng))
return true;
return false;
return std::uniform_int_distribution<int>(0, 1)(rng) != 0;
}
inline std::vector<bool> shrinkBool(bool x) {
std::vector<bool> ret;
Expand Down Expand Up @@ -255,7 +273,7 @@ struct ArbitraryImpl<long double> {
};

inline char arbitraryChar(RngEngine& rng, std::size_t) {
boost::uniform_int<char> dist(0x20, 0x7f);
std::uniform_int_distribution<char> dist{0x20, 0x7f};
return dist(rng);
}
inline std::vector<char> shrinkChar(char c) {
Expand Down Expand Up @@ -285,7 +303,7 @@ struct ArbitraryImpl<wchar_t> {

template <class String>
String arbitraryString(RngEngine& rng, std::size_t size) {
boost::uniform_int<std::size_t> dist(0, size);
std::uniform_int_distribution<std::size_t> dist{0, size};
std::size_t n = dist(rng);
String ret;
ret.reserve(n);
Expand Down
55 changes: 26 additions & 29 deletions include/cppqc/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@
#define CPPQC_GEN_H

#include <algorithm>
#include <boost/function.hpp>
#include <boost/random/uniform_int.hpp>
#include <cassert>
#include <cstddef>
#include <functional>
#include <iosfwd>
#include <map>
#include <ostream>
#include <random>
#include <stdexcept>
#include <tuple>
Expand Down Expand Up @@ -362,7 +363,7 @@ namespace detail {
template <class T>
class SizedGenerator {
public:
SizedGenerator(boost::function<Generator<T>(std::size_t)> f)
SizedGenerator(std::function<Generator<T>(std::size_t)> f)
: m_genfun(f), m_lastgen(f(0)) {}

T unGen(RngEngine& rng, std::size_t size) {
Expand All @@ -373,14 +374,14 @@ class SizedGenerator {
std::vector<T> shrink(const T& x) { return m_lastgen.shrink(x); }

private:
const boost::function<Generator<T>(std::size_t)> m_genfun;
const std::function<Generator<T>(std::size_t)> m_genfun;
Generator<T> m_lastgen;
};
} // namespace detail

/// Used to create generators that depend on the size parameter.
template <class T>
Generator<T> sized(boost::function<Generator<T>(std::size_t)> f) {
Generator<T> sized(std::function<Generator<T>(std::size_t)> f) {
return detail::SizedGenerator<T>(f);
}

Expand Down Expand Up @@ -438,7 +439,7 @@ class ChooseStatelessGenerator {
}

Integer unGen(RngEngine& rng, std::size_t) const {
boost::uniform_int<Integer> dist(m_min, m_max);
std::uniform_int_distribution<Integer> dist{m_min, m_max};
return dist(rng);
}

Expand Down Expand Up @@ -472,7 +473,7 @@ namespace detail {
template <class T>
class SuchThatGenerator {
public:
SuchThatGenerator(const Generator<T>& g, boost::function<bool(T)> pred)
SuchThatGenerator(const Generator<T>& g, std::function<bool(T)> pred)
: m_gen(g), m_pred(pred) {}

T unGen(RngEngine& rng, std::size_t size) {
Expand All @@ -492,14 +493,14 @@ class SuchThatGenerator {

private:
const Generator<T> m_gen;
const boost::function<bool(T)> m_pred;
const std::function<bool(T)> m_pred;
};

template <class T>
class SuchThatStatelessGenerator {
public:
SuchThatStatelessGenerator(const StatelessGenerator<T>& g,
boost::function<bool(T)> pred)
std::function<bool(T)> pred)
: m_gen(g), m_pred(pred) {}

T unGen(RngEngine& rng, std::size_t size) const {
Expand All @@ -519,7 +520,7 @@ class SuchThatStatelessGenerator {

private:
const StatelessGenerator<T> m_gen;
const boost::function<bool(T)> m_pred;
const std::function<bool(T)> m_pred;
};
} // namespace detail

Expand All @@ -543,7 +544,7 @@ class OneOfGenerator {
}

T unGen(RngEngine& rng, std::size_t size) {
boost::uniform_int<std::size_t> dist(0, m_gens.size() - 1);
std::uniform_int_distribution<std::size_t> dist{0, m_gens.size() - 1};
m_last_index = dist(rng);
return m_gens[m_last_index].unGen(rng, size);
}
Expand Down Expand Up @@ -578,10 +579,9 @@ class FrequencyGenerator {
}

T unGen(RngEngine& rng, std::size_t size) {
boost::uniform_int<std::size_t> dist(1, m_tot);
std::uniform_int_distribution<std::size_t> dist{1, m_tot};
std::size_t weight = dist(rng);
typename std::map<std::size_t, Generator<T>>::iterator it =
m_gens.lower_bound(weight);
auto it = m_gens.lower_bound(weight);
if (it == m_gens.end()) {
throw std::logic_error("frequency: all generators have weight 0");
} else {
Expand All @@ -591,8 +591,7 @@ class FrequencyGenerator {
}

std::vector<T> shrink(const T& x) {
typename std::map<std::size_t, Generator<T>>::iterator it =
m_gens.find(m_last_index);
auto it = m_gens.find(m_last_index);
assert(it != m_gens.end());
return it->second.shrink(x);
}
Expand Down Expand Up @@ -628,7 +627,7 @@ class ElementsGenerator {
}

T unGen(RngEngine& rng, std::size_t /*size*/) {
boost::uniform_int<std::size_t> dist(0, m_elems.size() - 1);
std::uniform_int_distribution<std::size_t> dist{0, m_elems.size() - 1};
m_last_index = dist(rng);
return m_elems[m_last_index];
}
Expand Down Expand Up @@ -734,7 +733,7 @@ namespace detail {
template <class T, class U>
class ConvertGenerator {
public:
ConvertGenerator(boost::function<T(U)> f, const Generator<U>& g)
ConvertGenerator(std::function<T(U)> f, const Generator<U>& g)
: m_convert(f), m_gen(g) {}

T unGen(RngEngine& rng, std::size_t size) {
Expand All @@ -746,8 +745,7 @@ class ConvertGenerator {
}

std::vector<T> shrink(const T& x) {
typename std::vector<T>::iterator it =
std::find(m_lastgen_t.begin(), m_lastgen_t.end(), x);
auto it = std::find(m_lastgen_t.begin(), m_lastgen_t.end(), x);
assert(it != m_lastgen_t.end());
U last_u = m_lastgen_u[it - m_lastgen_t.begin()];
m_lastgen_t.clear();
Expand All @@ -759,7 +757,7 @@ class ConvertGenerator {
}

private:
boost::function<T(U)> m_convert;
std::function<T(U)> m_convert;
const Generator<U> m_gen;
std::vector<T> m_lastgen_t;
std::vector<U> m_lastgen_u;
Expand All @@ -769,14 +767,14 @@ class ConvertGenerator {
/// Converts a generator of U's into a generator of T's by passing the results
/// through a function which converts U's into T's.
template <class T, class U>
Generator<T> convert(boost::function<T(U)> f,
Generator<T> convert(std::function<T(U)> f,
const Generator<U>& g = Arbitrary<U>()) {
return detail::ConvertGenerator<T, U>(f, g);
}

/// Convenience function to aid generic programming, equivalent to convert.
template <class T, class U1>
Generator<T> combine(boost::function<T(U1)> f,
Generator<T> combine(std::function<T(U1)> f,
const Generator<U1>& g1 = Arbitrary<U1>()) {
return detail::ConvertGenerator<T, U1>(f, g1);
}
Expand All @@ -785,7 +783,7 @@ namespace detail {
template <class T, class U1, class U2>
class CombineGenerator {
public:
CombineGenerator(boost::function<T(U1, U2)> f,
CombineGenerator(std::function<T(U1, U2)> f,
const Generator<U1>& g1,
const Generator<U2>& g2)
: m_combine(f), m_gen1(g1), m_gen2(g2) {}
Expand All @@ -801,8 +799,7 @@ class CombineGenerator {
}

std::vector<T> shrink(const T& x) {
typename std::vector<T>::const_iterator it =
std::find(m_lastgen_t.begin(), m_lastgen_t.end(), x);
auto it = std::find(m_lastgen_t.begin(), m_lastgen_t.end(), x);
assert(it != m_lastgen_t.end());
std::size_t dist = it - m_lastgen_t.begin();
U1 last_u1 = m_lastgen_u1[dist];
Expand All @@ -823,7 +820,7 @@ class CombineGenerator {
}

private:
boost::function<T(U1, U2)> m_combine;
std::function<T(U1, U2)> m_combine;
const Generator<U1> m_gen1;
const Generator<U2> m_gen2;
std::vector<T> m_lastgen_t;
Expand All @@ -836,7 +833,7 @@ class CombineGenerator {
/// results through a function which converts U1's and U2's into T's. Ie. the
/// same as convert for functions taking more than one argument.
template <class T, class U1, class U2>
Generator<T> combine(boost::function<T(U1, U2)> f,
Generator<T> combine(std::function<T(U1, U2)> f,
const Generator<U1>& g1 = Arbitrary<U1>(),
const Generator<U2>& g2 = Arbitrary<U2>()) {
return detail::CombineGenerator<T, U1, U2>(f, g1, g2);
Expand All @@ -849,7 +846,7 @@ class ListOfStatelessGenerator {
ListOfStatelessGenerator(const StatelessGenerator<T>& g) : m_gen(g) {}

std::vector<T> unGen(RngEngine& rng, std::size_t size) const {
boost::uniform_int<std::size_t> dist(0, size);
std::uniform_int_distribution<std::size_t> dist{0, size};
std::size_t n = dist(rng);
std::vector<T> ret;
ret.reserve(n);
Expand Down
Loading

0 comments on commit 310f21b

Please sign in to comment.