-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsparse_matrix_value_generator.hh
68 lines (59 loc) · 1.99 KB
/
sparse_matrix_value_generator.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#pragma once
#include <random>
#include <memory>
#include "matrix_value_generator.hh"
#include "matrix_value_factory.hh"
#include "utils/int_math.hh"
class no_next_value_exception: public std::exception {
const char* what() const noexcept override {
return "no_next_value_exception";
}
};
template <class V>
class sparse_matrix_value_generator : public matrix_value_generator<V> {
private:
size_t _width, _height;
size_t _suggested_max;
std::mt19937 _rng;
std::shared_ptr<matrix_value_factory<V>> _matrix_value_factory;
size_t _last_pos, _next_pos, _currently_generated;
void _calc_next_pos() {
size_t _max_pos = height() * width();
std::uniform_int_distribution<size_t>
_dist(1, 1 + 2 * (_max_pos - _last_pos) / (_suggested_max - _currently_generated));
_next_pos = _last_pos + _dist(_rng);
}
public:
sparse_matrix_value_generator(int height, int width, size_t suggested_number_of_values,
int seed, std::shared_ptr<matrix_value_factory<V>> matrix_value_factory) {
this->_height = height;
this->_width = width;
this->_suggested_max = suggested_number_of_values;
this->_rng = std::mt19937(seed);
this->_matrix_value_factory = matrix_value_factory;
_last_pos = 0;
_next_pos = 0;
_currently_generated = 0;
_calc_next_pos();
}
bool has_next() {
return _next_pos <= height() * width() && _currently_generated < _suggested_max;
}
matrix_value<V> next() {
if (!has_next()) {
throw no_next_value_exception();
}
_currently_generated++;
_last_pos = _next_pos;
if (has_next()) {
_calc_next_pos();
}
return matrix_value(IntMath::floor_div(_last_pos, width()), 1 + (_last_pos - 1) % width(), _matrix_value_factory->next());
}
size_t height() {
return this->_height;
}
size_t width() {
return this->_width;
}
};