[sequence_generator] Fix parameters and span boundary checking
This commit is contained in:
parent
661b4de5de
commit
0c3c5f6c1e
@ -14,12 +14,12 @@ namespace {
|
|||||||
uint64_t size,
|
uint64_t size,
|
||||||
uint64_t step)
|
uint64_t step)
|
||||||
: begin_(begin),
|
: begin_(begin),
|
||||||
end_(begin + (size / step) * step),
|
|
||||||
step_(step),
|
step_(step),
|
||||||
current_(begin),
|
current_(begin),
|
||||||
rounds_(0) {
|
rounds_(0)
|
||||||
if (size < step)
|
{
|
||||||
throw std::runtime_error("size must be greater than the step");
|
verify_parameters(size, step);
|
||||||
|
end_ = begin + (size / step) * step;
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_sequence_generator()
|
forward_sequence_generator()
|
||||||
@ -38,6 +38,8 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void reset(uint64_t begin, uint64_t size, uint64_t step = 1) {
|
void reset(uint64_t begin, uint64_t size, uint64_t step = 1) {
|
||||||
|
verify_parameters(size, step);
|
||||||
|
|
||||||
begin_ = begin;
|
begin_ = begin;
|
||||||
end_ = begin + (size / step) * step;
|
end_ = begin + (size / step) * step;
|
||||||
step_ = step;
|
step_ = step;
|
||||||
@ -45,6 +47,14 @@ namespace {
|
|||||||
rounds_ = 0;
|
rounds_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void verify_parameters(uint64_t size, uint64_t step) {
|
||||||
|
if (!size || !step)
|
||||||
|
throw std::runtime_error("size or step must be non-zero");
|
||||||
|
|
||||||
|
if (size < step)
|
||||||
|
throw std::runtime_error("size must be greater than the step");
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t get_rounds() {
|
uint64_t get_rounds() {
|
||||||
return rounds_;
|
return rounds_;
|
||||||
}
|
}
|
||||||
@ -68,11 +78,18 @@ namespace {
|
|||||||
uint64_t step,
|
uint64_t step,
|
||||||
unsigned seq_nr = 1)
|
unsigned seq_nr = 1)
|
||||||
: begin_(begin),
|
: begin_(begin),
|
||||||
nr_steps_(size / step),
|
|
||||||
step_(step),
|
step_(step),
|
||||||
max_forward_steps_(seq_nr),
|
max_forward_steps_(seq_nr),
|
||||||
nr_generated_(0)
|
nr_generated_(0)
|
||||||
{
|
{
|
||||||
|
if (!size || !step || !seq_nr)
|
||||||
|
throw std::runtime_error("size, step, or forward steps must be non-zero");
|
||||||
|
|
||||||
|
if (size < step)
|
||||||
|
throw std::runtime_error("size must be greater than the step");
|
||||||
|
|
||||||
|
nr_steps_ = size / step;
|
||||||
|
|
||||||
if (!max_forward_steps_ || max_forward_steps_ > nr_steps_)
|
if (!max_forward_steps_ || max_forward_steps_ > nr_steps_)
|
||||||
throw std::runtime_error("invalid number of forward steps");
|
throw std::runtime_error("invalid number of forward steps");
|
||||||
|
|
||||||
@ -84,7 +101,44 @@ namespace {
|
|||||||
// FIXME: eliminate if-else
|
// FIXME: eliminate if-else
|
||||||
uint64_t step_idx = (max_forward_steps_ > 1) ?
|
uint64_t step_idx = (max_forward_steps_ > 1) ?
|
||||||
next_forward_step() : next_random_step();
|
next_forward_step() : next_random_step();
|
||||||
|
|
||||||
|
return begin_ + step_idx * step_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void reset_forward_generator() {
|
||||||
|
uint64_t begin = peek_random_step();
|
||||||
|
|
||||||
|
unsigned seq_nr = (std::rand() % max_forward_steps_) + 1;
|
||||||
|
base::run_set<uint64_t>::const_iterator it = rand_map_.upper_bound(begin);
|
||||||
|
if (it != rand_map_.end())
|
||||||
|
seq_nr = std::min<uint64_t>(seq_nr, *it->begin_ - begin);
|
||||||
|
else
|
||||||
|
seq_nr = std::min<uint64_t>(seq_nr, nr_steps_ - begin);
|
||||||
|
|
||||||
|
forward_gen_.reset(begin, seq_nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t next_forward_step() {
|
||||||
|
uint64_t step_idx = forward_gen_.next();
|
||||||
|
consume_random_map(step_idx);
|
||||||
|
|
||||||
|
if (forward_gen_.get_rounds())
|
||||||
|
reset_forward_generator();
|
||||||
|
|
||||||
|
return step_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t next_random_step() {
|
||||||
|
uint64_t step_idx = peek_random_step();
|
||||||
|
consume_random_map(step_idx);
|
||||||
|
|
||||||
|
return step_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void consume_random_map(uint64_t step_idx) {
|
||||||
rand_map_.add(step_idx);
|
rand_map_.add(step_idx);
|
||||||
|
|
||||||
++nr_generated_;
|
++nr_generated_;
|
||||||
|
|
||||||
// wrap-around
|
// wrap-around
|
||||||
@ -92,33 +146,9 @@ namespace {
|
|||||||
rand_map_.clear();
|
rand_map_.clear();
|
||||||
nr_generated_ = 0;
|
nr_generated_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return begin_ + step_idx * step_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
uint64_t peek_random_step() const {
|
||||||
void reset_forward_generator() {
|
|
||||||
uint64_t begin = next_random_step();
|
|
||||||
unsigned seq_nr = (std::rand() % max_forward_steps_) + 1;
|
|
||||||
forward_gen_.reset(begin, seq_nr);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t next_forward_step() {
|
|
||||||
uint64_t step_idx;
|
|
||||||
|
|
||||||
bool found = true;
|
|
||||||
while (found) {
|
|
||||||
step_idx = forward_gen_.next();
|
|
||||||
found = rand_map_.member(step_idx);
|
|
||||||
|
|
||||||
if (found || forward_gen_.get_rounds())
|
|
||||||
reset_forward_generator();
|
|
||||||
}
|
|
||||||
|
|
||||||
return step_idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t next_random_step() const {
|
|
||||||
uint64_t step_idx;
|
uint64_t step_idx;
|
||||||
|
|
||||||
bool found = true;
|
bool found = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user