-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrejecter.h
72 lines (58 loc) · 1.85 KB
/
rejecter.h
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
69
70
71
72
#pragma once
#include "forger.h"
#include <cassert>
#include <iostream>
struct Builder;
struct RejecterDecorator : public ForgerBase {
friend struct Builder;
using SourceCounts = std::vector<size_t>;
RejecterDecorator(ForgerBase&& f, SourceCounts sourceCounts)
: ForgerBase(std::move(f))
, sourceCounts(std::move(sourceCounts)) {
}
RejecterDecorator(const RejecterDecorator&) = default;
RejecterDecorator(RejecterDecorator&&) = default;
~RejecterDecorator() override = default;
RejecterDecorator& operator=(const RejecterDecorator&) = default;
RejecterDecorator& operator=(RejecterDecorator&&) = default;
Tokens operator()(size_t count) const override {
Tokens tokens;
do {
tokens = ForgerBase::operator()(count);
} while(!isBalanced(tokens));
return tokens;
}
private:
bool isBalanced(const Tokens& tokens) const {
decltype(sourceCounts) tokenSourceCounts(sourceCounts.size(), 0);
for(auto&& t : tokens) {
assert(t.sourceIdx < tokenSourceCounts.size());
++tokenSourceCounts[t.sourceIdx];
}
for(size_t i = 0; i < sourceCounts.size(); ++i) {
auto sourceRatio = static_cast<double>(sourceCounts[i]) / this->states.size();
auto tokenRatio = static_cast<double>(tokenSourceCounts[i]) / tokens.size();
if(!isBalanced(sourceRatio, tokenRatio)) {
#ifdef DEBUG_REJECT
COUT << "rejecting: \n\t" << tokens << "\n\n";
#endif // DEBUG_REJECT
return false;
}
}
return true;
}
static bool isBalanced(double sourceRatio, double tokenRatio) {
return (sourceRatio < tokenRatio * 2);
}
SourceCounts sourceCounts;
};
std::ostream& operator<<(std::ostream& os, const RejecterDecorator::SourceCounts& sc) {
os << sc.size() << " sources with ";
auto sep = "";
for(auto&& s : sc) {
os << sep << s;
sep = "/";
}
os << " states";
return os;
}