Skip to content

Commit

Permalink
FIX: shuffled: efficiency improvements
Browse files Browse the repository at this point in the history
1. There was a bug. When we approximate, for example 10 with power of
two - we got 16 (2^4). So register size must be 4. But instead register
if size 5 was used. It's not efficient.

2. Even we have efficient std::distance and operator+(int n) functions
dumb_advanced and dumb_size doesn't uses them, so they was replaced with
std::advance and std::distance accordingly
  • Loading branch information
hoxnox committed May 18, 2016
1 parent 2dffbd9 commit 56e3045
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 19 deletions.
14 changes: 8 additions & 6 deletions shuffled.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
* implemented through advance of the first (begin) iterator of the
* container, so random access iterator is desirable. In the constructor
* we have to calculate the total size of the container, so
* dumb_distance will be used.*/
* std::distance will be used. User can define more effective
* std::distance for the container.*/

namespace iter {
namespace impl {
Expand All @@ -33,7 +34,7 @@ namespace iter {
impl::ShuffledView<Container, Distance> shuffled(Container&&, int seed = 1);
}

// power of 2 approximation
// power of 2 approximation (val < pow(2, get_approx(val)+1))
uint16_t iter::impl::lfsr::get_approx(uint64_t val) {
if (val == 0)
return 0;
Expand All @@ -49,7 +50,7 @@ uint16_t iter::impl::lfsr::get_approx(uint64_t val) {
break;
}
}
return pow2_approx + 1;
return pow2_approx;
}

uint64_t iter::impl::lfsr::shift(uint64_t reg, uint8_t reg_size) {
Expand Down Expand Up @@ -77,12 +78,13 @@ class iter::impl::ShuffledView {
using IterDeref = typename std::remove_reference<iterator_deref<Container>>;
ShuffledView(ShuffledView&&) : size(0) {};
ShuffledView(Container&& container, int seed)
: size(dumb_size(container)), size_approx(lfsr::get_approx(size)),
: size(std::distance(std::begin(container), std::end(container))),
size_approx(lfsr::get_approx(size)),
in_begin(std::begin(container)), seed(seed) {
if (size > 0)
{
uint64_t mask = 0xFFFFFFFFFFFFFFFFULL;
mask >> (64-size_approx);
mask = (mask >> (64-size_approx));
this->seed = seed & mask;
this->seed = lfsr::shift(this->seed, size_approx);
while(this->seed >= size)
Expand Down Expand Up @@ -133,7 +135,7 @@ class iter::impl::ShuffledView {

auto operator*() -> decltype(*copy) {
copy = owner->in_begin;
dumb_advance(copy, static_cast<Distance>(state-1));
std::advance(copy, static_cast<Distance>(state-1));
return *copy;
}

Expand Down
26 changes: 13 additions & 13 deletions test/test_shuffled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ TEST_CASE("shuffled: iterates through a vector in shuffled order", "[shuffled]")
Vec ns = {4, 0, 5, 1, 6, 7, 9, 3, 2, 8};
auto s = shuffled(ns);
Vec v(std::begin(s), std::end(s));
Vec vc = {2, 7, 5, 9, 8, 6, 3, 1, 0, 4};
Vec vc = {2, 9, 8, 6, 7, 5, 3, 1, 0, 4};
REQUIRE(v == vc);
}

Expand All @@ -41,27 +41,27 @@ TEST_CASE("shuffled: restore iteration through a vector in shuffled order "

// overflow - same as default
Vec v10(s.restore(10), std::end(s));
Vec vc10 = {2, 7, 5, 9, 8, 6, 3, 1, 0, 4};
Vec vc10 = {2, 9, 8, 6, 7, 5, 3, 1, 0, 4};
REQUIRE(v10 == vc10);

Vec v1(s.restore(5), std::end(s));
Vec vc1 = {7, 5, 9, 8, 6, 3, 1, 0, 4};
Vec v1(s.restore(6), std::end(s));
Vec vc1 = {9, 8, 6, 7, 5, 3, 1, 0, 4};
REQUIRE(v1 == vc1);

Vec v2(s.restore(2), std::end(s));
Vec vc2 = {5, 9, 8, 6, 3, 1, 0, 4};
Vec v2(s.restore(9), std::end(s));
Vec vc2 = {8, 6, 7, 5, 3, 1, 0, 4};
REQUIRE(v2 == vc2);

Vec v3(s.restore(6), std::end(s));
Vec vc3 = {9, 8, 6, 3, 1, 0, 4};
Vec v3(s.restore(4), std::end(s));
Vec vc3 = {6, 7, 5, 3, 1, 0, 4};
REQUIRE(v3 == vc3);

Vec v4(s.restore(9), std::end(s));
Vec vc4 = {8, 6, 3, 1, 0, 4};
Vec v4(s.restore(5), std::end(s));
Vec vc4 = {7, 5, 3, 1, 0, 4};
REQUIRE(v4 == vc4);

Vec v5(s.restore(4), std::end(s));
Vec vc5 = {6, 3, 1, 0, 4};
Vec v5(s.restore(2), std::end(s));
Vec vc5 = {5, 3, 1, 0, 4};
REQUIRE(v5 == vc5);

Vec v6(s.restore(7), std::end(s));
Expand Down Expand Up @@ -96,7 +96,7 @@ TEST_CASE("shuffled: iterates through a vector in shuffled order with non"
Vec ns = {4, 0, 5, 1, 6, 7, 9, 3, 2, 8};
auto s = shuffled(ns, 1234);
Vec v(std::begin(s), std::end(s));
Vec vc = {9, 8, 6, 3, 1, 0, 4, 2, 7, 5};
Vec vc = {4, 2, 9, 8, 6, 7, 5, 3, 1, 0};
REQUIRE(v == vc);
}

Expand Down

0 comments on commit 56e3045

Please sign in to comment.