Skip to content

Commit

Permalink
interleave, nextByDistribution
Browse files Browse the repository at this point in the history
  • Loading branch information
ifsmirnov committed Jan 28, 2018
1 parent 3091813 commit d91503f
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 0 deletions.
51 changes: 51 additions & 0 deletions jngen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1725,6 +1725,21 @@ class Random {
return choice(container.begin(), container.end());
}

template<typename Numeric>
size_t nextByDistribution(const std::vector<Numeric>& distribution) {
ensure(!distribution.empty(), "Cannot sample by empty distribution");
Numeric sum = std::accumulate(
distribution.begin(), distribution.end(), Numeric(0));
auto x = next(sum);
for (size_t i = 0; i < distribution.size(); ++i) {
if (x < distribution[i]) {
return i;
}
x -= distribution[i];
}
return distribution.size() - 1;
}

private:
template<typename T, typename ...Args>
T smallWnext(int w, Args... args) {
Expand Down Expand Up @@ -3053,6 +3068,7 @@ using namespace jngen::namespace_for_fake_operator_ltlt;

#include <algorithm>
#include <iterator>
#include <numeric>

namespace jngen {

Expand Down Expand Up @@ -3084,10 +3100,45 @@ T choice(std::initializer_list<T> ilist) {
return choice(ilist.begin(), ilist.end());
}

namespace detail {

template<typename Collection2D>
typename Collection2D::value_type interleave(const Collection2D& collection) {
std::vector<size_t> sizes;
for (const auto& c: collection) {
sizes.push_back(c.size());
}
size_t size = std::accumulate(sizes.begin(), sizes.end(), 0u);

typename Collection2D::value_type result;
while (size > 0) {
size_t id = rnd.nextByDistribution(sizes);
result.emplace_back(collection[id][collection[id].size() - sizes[id]]);
--sizes[id];

--size;
}

return result;
}

} // namespace detail

template<typename Collection2D>
typename Collection2D::value_type interleave(const Collection2D& collection) {
return detail::interleave(collection);
}

template<typename Collection>
Collection interleave(const std::initializer_list<Collection>& ilist) {
return detail::interleave<std::vector<Collection>>(ilist);
}

} // namespace jngen

using jngen::shuffle;
using jngen::choice;
using jngen::interleave;


#include <algorithm>
Expand Down
15 changes: 15 additions & 0 deletions random.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,21 @@ class Random {
return choice(container.begin(), container.end());
}

template<typename Numeric>
size_t nextByDistribution(const std::vector<Numeric>& distribution) {
ensure(!distribution.empty(), "Cannot sample by empty distribution");
Numeric sum = std::accumulate(
distribution.begin(), distribution.end(), Numeric(0));
auto x = next(sum);
for (size_t i = 0; i < distribution.size(); ++i) {
if (x < distribution[i]) {
return i;
}
x -= distribution[i];
}
return distribution.size() - 1;
}

private:
template<typename T, typename ...Args>
T smallWnext(int w, Args... args) {
Expand Down
36 changes: 36 additions & 0 deletions sequence_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <algorithm>
#include <iterator>
#include <numeric>

namespace jngen {

Expand Down Expand Up @@ -36,7 +37,42 @@ T choice(std::initializer_list<T> ilist) {
return choice(ilist.begin(), ilist.end());
}

namespace detail {

template<typename Collection2D>
typename Collection2D::value_type interleave(const Collection2D& collection) {
std::vector<size_t> sizes;
for (const auto& c: collection) {
sizes.push_back(c.size());
}
size_t size = std::accumulate(sizes.begin(), sizes.end(), 0u);

typename Collection2D::value_type result;
while (size > 0) {
size_t id = rnd.nextByDistribution(sizes);
result.emplace_back(collection[id][collection[id].size() - sizes[id]]);
--sizes[id];

--size;
}

return result;
}

} // namespace detail

template<typename Collection2D>
typename Collection2D::value_type interleave(const Collection2D& collection) {
return detail::interleave(collection);
}

template<typename Collection>
Collection interleave(const std::initializer_list<Collection>& ilist) {
return detail::interleave<std::vector<Collection>>(ilist);
}

} // namespace jngen

using jngen::shuffle;
using jngen::choice;
using jngen::interleave;
10 changes: 10 additions & 0 deletions tests/array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,14 @@ BOOST_AUTO_TEST_CASE(print_matrix) {
BOOST_TEST(out.str() == "0 0\n");
}

BOOST_AUTO_TEST_CASE(interleave) {
auto a = Array::id(3, 1);
auto b = Array::id(3, 11);
auto expected = Array{11, 1, 2, 12, 13, 3};

rnd.seed(10);

BOOST_TEST(jngen::interleave({a, b}) == expected);
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit d91503f

Please sign in to comment.