Skip to content

Commit

Permalink
Add range generator
Browse files Browse the repository at this point in the history
See: #12
  • Loading branch information
thejohnfreeman committed Sep 4, 2015
1 parent 57bb37d commit e99d418
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 14 deletions.
24 changes: 13 additions & 11 deletions include/autocheck/apply.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ namespace autocheck {
/* To extend for more fixed-size containers, just overload result_of_apply,
* std::tuple_size, and std::get. */

template <int N, int... Is>
struct range : range<N - 1, N - 1, Is...> {};
namespace detail {
template <int N, int... Is>
struct range : range<N - 1, N - 1, Is...> {};

template <int... Is>
struct range<0, Is...> {};
template <int... Is>
struct range<0, Is...> {};
}

template <typename F, typename Tuple>
struct result_of_apply {};
Expand All @@ -23,18 +25,18 @@ namespace autocheck {
typedef typename std::result_of<F(Args&...)>::type type;
};

template <typename F, typename Tuple, int... Is>
typename result_of_apply<F, typename std::decay<Tuple>::type>::type
subapply(F f, Tuple&& args, const detail::range<0, Is...>&) {
return f(std::get<Is>(std::forward<Tuple>(args))...);
}

template <typename F, typename Tuple>
typename result_of_apply<F, typename std::decay<Tuple>::type>::type
apply(F f, Tuple&& args) {
return subapply(f,
std::forward<Tuple>(args),
range<std::tuple_size<typename std::decay<Tuple>::type>::value>());
}

template <typename F, typename Tuple, int... Is>
typename result_of_apply<F, typename std::decay<Tuple>::type>::type
subapply(F f, Tuple&& args, const range<0, Is...>&) {
return f(std::get<Is>(std::forward<Tuple>(args))...);
detail::range<std::tuple_size<typename std::decay<Tuple>::type>::value>());
}

}
Expand Down
44 changes: 41 additions & 3 deletions include/autocheck/generator.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef AUTOCHECK_GENERATOR_HPP
#define AUTOCHECK_GENERATOR_HPP

#include <cassert>
#include <random>
#include <vector>
#include <iterator>
Expand All @@ -23,14 +24,15 @@ namespace autocheck {

template <typename T, typename... Gens, int... Is>
T generate(std::tuple<Gens...>& gens, size_t size,
const range<0, Is...>&)
const detail::range<0, Is...>&)
{
return T(std::get<Is>(gens)(size)...);
}

template <typename T, typename... Gens>
T generate(std::tuple<Gens...>& gens, size_t size) {
return autocheck::generate<T>(gens, size, range<sizeof...(Gens)>());
return autocheck::generate<T>(gens, size,
detail::range<sizeof...(Gens)>());
}

/* Generators produce an infinite sequence. */
Expand Down Expand Up @@ -144,6 +146,42 @@ namespace autocheck {
}
};

/** Generate values in the range [low, high). */
template <typename SignedIntegral>
class range_generator {
private:
SignedIntegral low;
SignedIntegral len;
generator<SignedIntegral> igen;

public:
range_generator(const SignedIntegral& low, const SignedIntegral& high) :
low(low), len(high - low)
{
assert(len > 0);
}

typedef SignedIntegral result_type;

result_type operator() (size_t size = 0) {
auto i = igen(size) % len;
i = (i > 0) ? i : (i + len);
return low + i;
}
};

template <typename SignedIntegral>
range_generator<SignedIntegral> range(
const SignedIntegral& low, const SignedIntegral& high)
{
return range_generator<SignedIntegral>(low, high);
}

template <typename SignedIntegral>
range_generator<SignedIntegral> range(const SignedIntegral& high) {
return range(0, high);
}

template <typename Floating>
class generator<
Floating,
Expand Down Expand Up @@ -271,7 +309,7 @@ namespace autocheck {
std::tuple<Gens...> gens;

public:
cons_generator()
cons_generator()
#ifndef _MSC_VER
: gens(Gens()...)
#endif
Expand Down

0 comments on commit e99d418

Please sign in to comment.