15#include <unordered_map>
16#include <unordered_set>
28constexpr int kNumBits = 2;
31constexpr int kNumValues = (1 << kNumBits) - 1;
32constexpr int kDataPerByte = 8 / kNumBits;
43 std::array<int, kNumValues> v = {};
44 std::vector<int>
data;
47 std::vector<int>
data;
50using TransitionSet = std::unordered_set<int>;
52static int add_compact_entry(
const TransitionSet& transitionSet,
53 const std::vector<int>&
data,
54 std::vector<CompactEntry>* entries) {
58 assert(transitionSet.size() <=
result.v.size());
59 std::copy(transitionSet.begin(), transitionSet.end(),
result.v.begin());
63 std::unordered_map<int, int> translationTable;
64 for (
size_t index = 0; index <
result.v.size(); ++index) {
65 translationTable[
result.v[index]] = index;
67 translationTable[0] =
result.v.size();
70 for (
size_t index = 0; index <
data.size(); ++index) {
72 assert(translationTable.find(
value) != translationTable.end());
77 for (
size_t index = 0; index < entries->size(); ++index) {
78 if (entries->at(index).v ==
result.v && entries->at(index).data ==
result.data) {
84 entries->push_back(std::move(
result));
85 return (
int)(entries->size() - 1);
88static int add_full_entry(
const TransitionSet& transitionMap,
89 const std::vector<int>&
data,
90 std::vector<FullEntry>* entries) {
96 for (
size_t index = 0; index < entries->size(); ++index) {
97 if (entries->at(index).data ==
result.data) {
103 entries->push_back(std::move(
result));
104 return (
int)(entries->size() - 1);
113 std::vector<CompactEntry> compactEntries;
114 std::vector<FullEntry> fullEntries;
115 std::vector<IndexEntry> indices;
116 for (
size_t s = 0;
s < states; ++
s) {
120 TransitionSet transitionSet;
121 std::vector<int>
data(numTransitions);
122 for (
int t = 0; t < numTransitions; ++t) {
127 transitionSet.insert(
value);
131 transitionSet.erase(0);
132 if (transitionSet.size() <= kNumValues) {
135 int index = add_compact_entry(transitionSet,
data, &compactEntries);
136 indices.push_back(
IndexEntry{kCompactEntry, index});
139 int index = add_full_entry(transitionSet,
data, &fullEntries);
140 indices.push_back(
IndexEntry{kFullEntry, index});
146 for (
const CompactEntry& entry : compactEntries) {
147 for (
int index=0; index < kNumValues; ++index) {
148 maxValue =
std::max(maxValue, entry.v[index]);
153 int bitsPerValue =
std::ceil(std::log2(maxValue));
154 maxValue = (1 << bitsPerValue) - 1;
158 assert(bitsPerValue <= 10);
161 out <<
"using IndexEntry = int16_t;\n"
162 <<
"struct FullEntry {\n"
163 <<
" State data[" << numTransitions <<
"];\n"
168 static_assert(kNumBits == 2);
169 out <<
"struct CompactEntry {\n"
170 <<
" uint32_t values;\n"
171 <<
" uint8_t data[" <<
std::ceil(
float(numTransitions) /
float(kDataPerByte)) <<
"];\n"
175 out <<
"static constexpr FullEntry kFull[] = {\n";
176 for (
const FullEntry& entry : fullEntries) {
178 for (
int value : entry.data) {
186 out <<
"static constexpr CompactEntry kCompact[] = {\n";
187 for (
const CompactEntry& entry : compactEntries) {
192 static_assert(kNumBits == 2);
195 out <<
" | (" << entry.v[1] <<
" << " << bitsPerValue <<
")";
198 out <<
" | (" << entry.v[2] <<
" << " << (2 * bitsPerValue) <<
")";
202 unsigned int shiftBits = 0, combinedBits = 0;
203 for (
int index = 0; index < numTransitions; index++) {
204 combinedBits |= entry.data[index] << shiftBits;
205 shiftBits += kNumBits;
206 assert(shiftBits <= 8);
207 if (shiftBits == 8) {
208 out << combinedBits <<
", ";
220 <<
"static constexpr IndexEntry kIndices[] = {\n";
222 if (entry.type == kFullEntry) {
224 out << ~entry.pos <<
", ";
227 out << entry.pos <<
", ";
231 <<
"static State get_transition(uint8_t transition, State state) {\n"
232 <<
" IndexEntry index = kIndices[state];\n"
233 <<
" if (index < 0) { return kFull[~index].data[transition]; }\n"
234 <<
" const CompactEntry& entry = kCompact[index];\n"
235 <<
" int v = entry.data[transition >> " << std::log2(kDataPerByte) <<
"];\n"
236 <<
" v >>= " << kNumBits <<
" * (transition & " << kDataPerByte - 1 <<
");\n"
237 <<
" v &= " << kNumValues <<
";\n"
238 <<
" v *= " << bitsPerValue <<
";\n"
239 <<
" return (entry.values >> v) & " << maxValue <<
";\n"
static std::vector< SkPDFIndirectReference > sort(const THashSet< SkPDFIndirectReference > &src)
static void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
void WriteTransitionTable(std::ofstream &out, const DFA &dfa, size_t states)
static float max(float r, float g, float b)
SIN Vec< N, float > ceil(const Vec< N, float > &x)
std::vector< std::vector< int > > fTransitions
std::shared_ptr< const fml::Mapping > data