#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <iterator>
#include <vector>
#include <cstdlib>
#include <cstddef>
#include <stdint.h>
#include <iomanip>
enum {
// Config
ZERO_POS = 2,
INDEX_SIZE = 5,
VALUE_LIMIT = -100,
// Constants
NUM_ROWS = 37,
NUM_COLUMNS = 73,
VALUE_LIMIT_POS = -VALUE_LIMIT,
NUM_BIN_OUTLIERS = 8,
NUM_VALUES = NUM_ROWS * (NUM_COLUMNS - 1),
INDEX_PLUS = INDEX_SIZE - ZERO_POS - 1,
BIN4 = 0,
BIN12 = 1,
INDEX_FULL_SIZE = INDEX_SIZE + 2
};
int16_t my_array[NUM_ROWS][NUM_COLUMNS] = {
{150,145,140,135,130,125,120,115,110,105,100,95,90,85,80,75,70,65,60,55,50,45,40,35,30,25,20,15,10,5,0,-4,-9,-14,-19,-24,-29,-34,-39,-44,-49,-54,-59,-64,-69,-74,-79,-84,-89,-94,-99,104,109,114,119,124,129,134,139,144,149,154,159,164,169,174,179,175,170,165,160,155,150}, \
{143,137,131,126,120,115,110,105,100,95,90,85,80,75,71,66,62,57,53,48,44,39,35,31,27,22,18,14,9,5,1,-3,-7,-11,-16,-20,-25,-29,-34,-38,-43,-47,-52,-57,-61,-66,-71,-76,-81,-86,-91,-96,101,107,112,117,123,128,134,140,146,151,157,163,169,175,178,172,166,160,154,148,143}, \
{130,124,118,112,107,101,96,92,87,82,78,74,70,65,61,57,54,50,46,42,38,34,31,27,23,19,16,12,8,4,1,-2,-6,-10,-14,-18,-22,-26,-30,-34,-38,-43,-47,-51,-56,-61,-65,-70,-75,-79,-84,-89,-94,100,105,111,116,122,128,135,141,148,155,162,170,177,174,166,159,151,144,137,130}, \
{111,104,99,94,89,85,81,77,73,70,66,63,60,56,53,50,46,43,40,36,33,30,26,23,20,16,13,10,6,3,0,-3,-6,-9,-13,-16,-20,-24,-28,-32,-36,-40,-44,-48,-52,-57,-61,-65,-70,-74,-79,-84,-88,-93,-98,103,109,115,121,128,135,143,152,162,172,176,165,154,144,134,125,118,111}, \
{85,81,77,74,71,68,65,63,60,58,56,53,51,49,46,43,41,38,35,32,29,26,23,19,16,13,10,7,4,1,-1,-3,-6,-9,-13,-16,-19,-23,-26,-30,-34,-38,-42,-46,-50,-54,-58,-62,-66,-70,-74,-78,-83,-87,-91,-95,100,105,110,117,124,133,144,159,178,160,141,125,112,103,96,90,85}, \
{62,60,58,57,55,54,52,51,50,48,47,46,44,42,41,39,36,34,31,28,25,22,19,16,13,10,7,4,2,0,-3,-5,-8,-10,-13,-16,-19,-22,-26,-29,-33,-37,-41,-45,-49,-53,-56,-60,-64,-67,-70,-74,-77,-80,-83,-86,-89,-91,-94,-97,101,105,111,130,109,84,77,74,71,68,66,64,62}, \
{46,46,45,44,44,43,42,42,41,41,40,39,38,37,36,35,33,31,28,26,23,20,16,13,10,7,4,1,-1,-3,-5,-7,-9,-12,-14,-16,-19,-22,-26,-29,-33,-36,-40,-44,-48,-51,-55,-58,-61,-64,-66,-68,-71,-72,-74,-74,-75,-74,-72,-68,-61,-48,-25,2,22,33,40,43,45,46,47,46,46}, \
{36,36,36,36,36,35,35,35,35,34,34,34,34,33,32,31,30,28,26,23,20,17,14,10,6,3,0,-2,-4,-7,-9,-10,-12,-14,-15,-17,-20,-23,-26,-29,-32,-36,-40,-43,-47,-50,-53,-56,-58,-60,-62,-63,-64,-64,-63,-62,-59,-55,-49,-41,-30,-17,-4,6,15,22,27,31,33,34,35,36,36}, \
{30,30,30,30,30,30,30,29,29,29,29,29,29,29,29,28,27,26,24,21,18,15,11,7,3,0,-3,-6,-9,-11,-12,-14,-15,-16,-17,-19,-21,-23,-26,-29,-32,-35,-39,-42,-45,-48,-51,-53,-55,-56,-57,-57,-56,-55,-53,-49,-44,-38,-31,-23,-14,-6,0,7,13,17,21,24,26,27,29,29,30}, \
{25,25,26,26,26,25,25,25,25,25,25,25,25,26,25,25,24,23,21,19,16,12,8,4,0,-3,-7,-10,-13,-15,-16,-17,-18,-19,-20,-21,-22,-23,-25,-28,-31,-34,-37,-40,-43,-46,-48,-49,-50,-51,-51,-50,-48,-45,-42,-37,-32,-26,-19,-13,-7,-1,3,7,11,14,17,19,21,23,24,25,25}, \
{21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,21,20,18,16,13,9,5,1,-3,-7,-11,-14,-17,-18,-20,-21,-21,-22,-22,-22,-23,-23,-25,-27,-29,-32,-35,-37,-40,-42,-44,-45,-45,-45,-44,-42,-40,-36,-32,-27,-22,-17,-12,-7,-3,0,3,7,9,12,14,16,18,19,20,21,21}, \
{18,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,18,17,16,14,10,7,2,-1,-6,-10,-14,-17,-19,-21,-22,-23,-24,-24,-24,-24,-23,-23,-23,-24,-26,-28,-30,-33,-35,-37,-38,-39,-39,-38,-36,-34,-31,-28,-24,-19,-15,-10,-6,-3,0,1,4,6,8,10,12,14,15,16,17,18,18}, \
{16,16,17,17,17,17,17,17,17,17,17,16,16,16,16,16,16,15,13,11,8,4,0,-4,-9,-13,-16,-19,-21,-23,-24,-25,-25,-25,-25,-24,-23,-21,-20,-20,-21,-22,-24,-26,-28,-30,-31,-32,-31,-30,-29,-27,-24,-21,-17,-13,-9,-6,-3,-1,0,2,4,5,7,9,10,12,13,14,15,16,16}, \
{14,14,14,15,15,15,15,15,15,15,14,14,14,14,14,14,13,12,11,9,5,2,-2,-6,-11,-15,-18,-21,-23,-24,-25,-25,-25,-25,-24,-22,-21,-18,-16,-15,-15,-15,-17,-19,-21,-22,-24,-24,-24,-23,-22,-20,-18,-15,-12,-9,-5,-3,-1,0,1,2,4,5,6,8,9,10,11,12,13,14,14}, \
{12,13,13,13,13,13,13,13,13,13,13,13,12,12,12,12,11,10,9,6,3,0,-4,-8,-12,-16,-19,-21,-23,-24,-24,-24,-24,-23,-22,-20,-17,-15,-12,-10,-9,-9,-10,-12,-13,-15,-17,-17,-18,-17,-16,-15,-13,-11,-8,-5,-3,-1,0,1,1,2,3,4,6,7,8,9,10,11,12,12,12}, \
{11,11,11,11,11,12,12,12,12,12,11,11,11,11,11,10,10,9,7,5,2,-1,-5,-9,-13,-17,-20,-22,-23,-23,-23,-23,-22,-20,-18,-16,-14,-11,-9,-6,-5,-4,-5,-6,-8,-9,-11,-12,-12,-12,-12,-11,-9,-8,-6,-3,-1,0,0,1,1,2,3,4,5,6,7,8,9,10,11,11,11}, \
{10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,7,6,3,0,-3,-6,-10,-14,-17,-20,-21,-22,-22,-22,-21,-19,-17,-15,-13,-10,-8,-6,-4,-2,-2,-2,-2,-4,-5,-7,-8,-8,-9,-8,-8,-7,-5,-4,-2,0,0,1,1,1,2,2,3,4,5,6,7,8,9,10,10,10}, \
{9,9,9,9,9,9,9,10,10,9,9,9,9,9,9,8,8,6,5,2,0,-4,-7,-11,-15,-17,-19,-21,-21,-21,-20,-18,-16,-14,-12,-10,-8,-6,-4,-2,-1,0,0,0,-1,-2,-4,-5,-5,-6,-6,-5,-5,-4,-3,-1,0,0,1,1,1,1,2,3,3,5,6,7,8,8,9,9,9}, \
{9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,7,5,4,1,-1,-5,-8,-12,-15,-17,-19,-20,-20,-19,-18,-16,-14,-11,-9,-7,-5,-4,-2,-1,0,0,1,1,0,0,-2,-3,-3,-4,-4,-4,-3,-3,-2,-1,0,0,0,0,0,1,1,2,3,4,5,6,7,8,8,9,9}, \
{9,9,9,8,8,8,9,9,9,9,9,8,8,8,8,7,6,5,3,0,-2,-5,-9,-12,-15,-17,-18,-19,-19,-18,-16,-14,-12,-9,-7,-5,-4,-2,-1,0,0,1,1,1,1,0,0,-1,-2,-2,-3,-3,-2,-2,-1,-1,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8,9}, \
{8,8,8,8,8,8,9,9,9,9,9,9,8,8,8,7,6,4,2,0,-3,-6,-9,-12,-15,-17,-18,-18,-17,-16,-14,-12,-10,-8,-6,-4,-2,-1,0,0,1,2,2,2,2,1,0,0,-1,-1,-1,-2,-2,-1,-1,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8}, \
{8,8,8,8,9,9,9,9,9,9,9,9,9,8,8,7,5,3,1,-1,-4,-7,-10,-13,-15,-16,-17,-17,-16,-15,-13,-11,-9,-6,-5,-3,-2,0,0,0,1,2,2,2,2,1,1,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,-1,-1,-1,-1,-1,0,0,1,3,4,5,7,7,8}, \
{8,8,9,9,9,9,10,10,10,10,10,10,10,9,8,7,5,3,0,-2,-5,-8,-11,-13,-15,-16,-16,-16,-15,-13,-12,-10,-8,-6,-4,-2,-1,0,0,1,2,2,3,3,2,2,1,0,0,0,0,0,0,0,0,0,0,-1,-1,-2,-2,-2,-2,-2,-1,0,0,1,3,4,6,7,8}, \
{7,8,9,9,9,10,10,11,11,11,11,11,10,10,9,7,5,3,0,-2,-6,-9,-11,-13,-15,-16,-16,-15,-14,-13,-11,-9,-7,-5,-3,-2,0,0,1,1,2,3,3,3,3,2,2,1,1,0,0,0,0,0,0,0,-1,-1,-2,-3,-3,-4,-4,-4,-3,-2,-1,0,1,3,5,6,7}, \
{6,8,9,9,10,11,11,12,12,12,12,12,11,11,9,7,5,2,0,-3,-7,-10,-12,-14,-15,-16,-15,-15,-13,-12,-10,-8,-7,-5,-3,-1,0,0,1,2,2,3,3,4,3,3,3,2,2,1,1,1,0,0,0,0,-1,-2,-3,-4,-4,-5,-5,-5,-5,-4,-2,-1,0,2,3,5,6}, \
{6,7,8,10,11,12,12,13,13,14,14,13,13,11,10,8,5,2,0,-4,-8,-11,-13,-15,-16,-16,-16,-15,-13,-12,-10,-8,-6,-5,-3,-1,0,0,1,2,3,3,4,4,4,4,4,3,3,3,2,2,1,1,0,0,-1,-2,-3,-5,-6,-7,-7,-7,-6,-5,-4,-3,-1,0,2,4,6}, \
{5,7,8,10,11,12,13,14,15,15,15,14,14,12,11,8,5,2,-1,-5,-9,-12,-14,-16,-17,-17,-16,-15,-14,-12,-11,-9,-7,-5,-3,-1,0,0,1,2,3,4,4,5,5,5,5,5,5,4,4,3,3,2,1,0,-1,-2,-4,-6,-7,-8,-8,-8,-8,-7,-6,-4,-2,0,1,3,5}, \
{4,6,8,10,12,13,14,15,16,16,16,16,15,13,11,9,5,2,-2,-6,-10,-13,-16,-17,-18,-18,-17,-16,-15,-13,-11,-9,-7,-5,-4,-2,0,0,1,3,3,4,5,6,6,7,7,7,7,7,6,5,4,3,2,0,-1,-3,-5,-7,-8,-9,-10,-10,-10,-9,-7,-5,-4,-1,0,2,4}, \
{4,6,8,10,12,14,15,16,17,18,18,17,16,15,12,9,5,1,-3,-8,-12,-15,-18,-19,-20,-20,-19,-18,-16,-15,-13,-11,-8,-6,-4,-2,-1,0,1,3,4,5,6,7,8,9,9,9,9,9,9,8,7,5,3,1,-1,-3,-6,-8,-10,-11,-12,-12,-11,-10,-9,-7,-5,-2,0,1,4}, \
{4,6,8,11,13,15,16,18,19,19,19,19,18,16,13,10,5,0,-5,-10,-15,-18,-21,-22,-23,-22,-22,-20,-18,-17,-14,-12,-10,-8,-5,-3,-1,0,1,3,5,6,8,9,10,11,12,12,13,12,12,11,9,7,5,2,0,-3,-6,-9,-11,-12,-13,-13,-12,-11,-10,-8,-6,-3,-1,1,4}, \
{3,6,9,11,14,16,17,19,20,21,21,21,19,17,14,10,4,-1,-8,-14,-19,-22,-25,-26,-26,-26,-25,-23,-21,-19,-17,-14,-12,-9,-7,-4,-2,0,1,3,5,7,9,11,13,14,15,16,16,16,16,15,13,10,7,4,0,-3,-7,-10,-12,-14,-15,-14,-14,-12,-11,-9,-6,-4,-1,1,3}, \
{4,6,9,12,14,17,19,21,22,23,23,23,21,19,15,9,2,-5,-13,-20,-25,-28,-30,-31,-31,-30,-29,-27,-25,-22,-20,-17,-14,-11,-9,-6,-3,0,1,4,6,9,11,13,15,17,19,20,21,21,21,20,18,15,11,6,2,-2,-7,-11,-13,-15,-16,-16,-15,-13,-11,-9,-7,-4,-1,1,4}, \
{4,7,10,13,15,18,20,22,24,25,25,25,23,20,15,7,-2,-12,-22,-29,-34,-37,-38,-38,-37,-36,-34,-31,-29,-26,-23,-20,-17,-13,-10,-7,-4,-1,2,5,8,11,13,16,18,21,23,24,26,26,26,26,24,21,17,12,5,0,-6,-10,-14,-16,-16,-16,-15,-14,-12,-10,-7,-4,-1,1,4}, \
{4,7,10,13,16,19,22,24,26,27,27,26,24,19,11,-1,-15,-28,-37,-43,-46,-47,-47,-45,-44,-41,-39,-36,-32,-29,-26,-22,-19,-15,-11,-8,-4,-1,2,5,9,12,15,19,22,24,27,29,31,33,33,33,32,30,26,21,14,6,0,-6,-11,-14,-15,-16,-15,-14,-12,-9,-7,-4,-1,1,4}, \
{6,9,12,15,18,21,23,25,27,28,27,24,17,4,-14,-34,-49,-56,-60,-60,-60,-58,-56,-53,-50,-47,-43,-40,-36,-32,-28,-25,-21,-17,-13,-9,-5,-1,2,6,10,14,17,21,24,28,31,34,37,39,41,42,43,43,41,38,33,25,17,8,0,-4,-8,-10,-10,-10,-8,-7,-4,-2,0,3,6}, \
{22,24,26,28,30,32,33,31,23,-18,-81,-96,-99,-98,-95,-93,-89,-86,-82,-78,-74,-70,-66,-62,-57,-53,-49,-44,-40,-36,-32,-27,-23,-19,-14,-10,-6,-1,2,6,10,15,19,23,27,31,35,38,42,45,49,52,55,57,60,61,63,63,62,61,57,53,47,40,33,28,23,21,19,19,19,20,22}, \
{168,173,178,176,171,166,161,156,151,146,141,136,131,126,121,116,111,106,101,-96,-91,-86,-81,-76,-71,-66,-61,-56,-51,-46,-41,-36,-31,-26,-21,-16,-11,-6,-1,3,8,13,18,23,28,33,38,43,48,53,58,63,68,73,78,83,88,93,98,103,108,113,118,123,128,133,138,143,148,153,158,163,168}};
using namespace std;
class Entropy
{
uint16_t total;
public:
Entropy(uint16_t add): total(add + NUM_VALUES) {}
double operator ()(double acc, uint16_t val)
{
double part = static_cast<double>(val) / total;
return acc - (part? part * log(part) / log(2.): 0.);
}
};
struct Taylor
{
int16_t d[2];
Taylor()
{
fill(d, d + 2, 0);
}
Taylor(int16_t val, const Taylor& other)
{
d[0] = val;
update(other);
}
int16_t predict()
{
return accumulate(d, d + 2, 0);
}
void copyFrom(const Taylor& other, size_t end = 2)
{
copy(other.d, other.d + end, d);
}
void update(const Taylor& other)
{
d[1] = d[0] - other.d[0];
}
void negate()
{
d[0] = -d[0];
d[1] = -d[1];
}
void clear()
{
fill(d, d + 2, 0);
}
};
class NibbleWriter
{
uint16_t* stream;
uint16_t* limit;
uint16_t block;
uint16_t pos;
public:
NibbleWriter(uint16_t* p, uint16_t x)
{
x &= 0x0FFF;
stream = p;
block = x;
limit = p + x;
pos = 12;
}
void write4(uint16_t x)
{
block |= (x & 15) << pos;
pos += 4;
if (pos == 16)
flush();
}
void write12(uint16_t x)
{
write4(x);
write4(x >> 4);
write4(x >> 8);
}
void flush()
{
if (pos)
{
if (stream >= limit)
{
cerr << "Internal error: nibble buffer overflow\n";
exit(1);
}
*stream++ = block;
}
block = 0;
pos = 0;
}
};
class ArWriter
{ // http://w...content-available-to-author-only...s.com/ac_arithmetic.html
uint16_t* stream;
uint16_t* table;
uint16_t* tableEnd;
uint16_t high;
uint16_t low;
uint16_t result;
uint16_t resultUsed;
uint16_t underflows;
public:
ArWriter(uint16_t* p, uint16_t* t, uint16_t* e)
: stream(p)
, table(t) // Zero value in *(t-1) expected
, tableEnd(e)
, high(0xFFFF)
, low(0)
, result(0)
, resultUsed(0)
, underflows(0)
{}
void write(uint16_t value)
{
uint32_t range = static_cast<uint32_t>(high) - low + 1;
high = low + ((range * table[value]) / *(tableEnd - 1)) - 1;
low = low + (range * table[value - 1]) / *(tableEnd - 1);
while (true) {
if ((high ^ low) & 0x8000) // different msb
{
if ((high & 0x4000) < (low & 0x4000))
{
++underflows;
low &= 0x3FFF;
high |= 0x4000;
shift();
}
else
{
break;
}
}
else // equal msb
{
writeBit((low >> 15) & 1);
while (underflows)
{
writeBit((~low >> 15) & 1);
--underflows;
}
shift();
}
}
}
void shift()
{
low <<= 1;
high <<= 1;
high |= 1;
}
void writeBit(uint16_t bit)
{
result <<= 1;
result |= bit;
++resultUsed;
if (resultUsed == 16)
flushResult();
}
void flushResult()
{
*stream++ = result;
result = 0;
resultUsed = 0;
}
void flush()
{
writeBit((low >> 14) & 1);
++underflows;
while (underflows--)
writeBit((~low >> 14) & 1);
while (resultUsed)
writeBit(0);
}
uint16_t* getStreamPos() const
{
return stream;
}
};
void encoder()
{
// Pass 1: calculate frequencies
vector<uint16_t> freq(1024);
uint16_t binary4 = 0;
uint16_t binary12 = 0;
Taylor lastTaylor;
for (size_t row = 0; row < NUM_ROWS; ++row)
{
for (size_t col = 0; col < NUM_COLUMNS - 1; ++col)
{ // last column is not encoded
Taylor taylor(my_array[row][col], lastTaylor);
int16_t fixup = taylor.d[0] - lastTaylor.predict();
// Hack for values, jumping from -100 to 100
if (taylor.d[0] >= VALUE_LIMIT_POS && lastTaylor.d[0] < 0)
fixup -= 2 * taylor.d[0];
// Value too big for arithmetic codec, use nibbles
if (fixup > INDEX_PLUS + NUM_BIN_OUTLIERS ||
fixup < -ZERO_POS - NUM_BIN_OUTLIERS)
{
++binary12;
}
else if (fixup > INDEX_PLUS || fixup < -ZERO_POS)
{
++binary4;
}
// Hack for values, jumping from -100 to 100
if (taylor.d[0] >= VALUE_LIMIT_POS && lastTaylor.d[0] < 0)
{
lastTaylor.negate();
taylor.update(lastTaylor);
}
// This will be used to predict the next value
// (derivative is not updated for the first column)
lastTaylor.copyFrom(taylor, col? 3: 1);
// Update table of frequencies
++freq[512 + fixup];
}
}
cout << "fixup: ";
ostream_iterator<int> out_it (cout, " ");
std::copy(freq.begin()+480, freq.end()-480, out_it);
cout << "\n";
cout << "binary4=" << binary4 << "\n";
cout << "binary12=" << binary12 << "\n";
cout << "-----------\n";
double bitsPerValue =
accumulate(freq.begin(), freq.end(), 0., Entropy(0));
cout
<< " Entropy=" << NUM_VALUES * bitsPerValue / 8.
<< " bits=" << bitsPerValue << "\n";
Entropy entropy(binary4 + binary12);
cout << "Static="
<< 2 * (INDEX_FULL_SIZE +
(2 + binary4 + binary12*3 + 3) / 4)
<< "\n";
// Add nibble frequencies
freq[512 - ZERO_POS + INDEX_SIZE] = binary4;
freq[512 - ZERO_POS + INDEX_SIZE + 1] = binary12;
bitsPerValue =
accumulate(freq.begin() + 512 - ZERO_POS,
freq.begin() + 512 - ZERO_POS + INDEX_FULL_SIZE,
0., entropy);
cout
<< "Entropy2=" << NUM_VALUES * bitsPerValue / 8.
<< " bits=" << bitsPerValue << "\n";
// Pass 2: encode arithmetic coder bitstream & nibbles
vector<uint16_t> compacted(1024);
// Cumulative sum of frequencies
partial_sum(freq.begin() + 512 - ZERO_POS,
freq.begin() + 512 - ZERO_POS + INDEX_FULL_SIZE,
compacted.begin() + 1);
// Configure nibble writer
uint16_t* pNibbles = &compacted[INDEX_FULL_SIZE + 1];
uint16_t nibbles = (3 + binary4 + binary12*3 + 3) / 4;
NibbleWriter nibbleWriter(pNibbles, nibbles);
uint16_t* pData = pNibbles + nibbles;
// Configure arithmetic coder
ArWriter arWriter(pData,
&compacted[1],
&compacted[1 + INDEX_FULL_SIZE]);
lastTaylor.clear();
for (size_t row = 0; row < NUM_ROWS; ++row)
{
for (size_t col = 0; col < NUM_COLUMNS - 1; ++col)
{ // last column is not encoded
Taylor taylor(my_array[row][col], lastTaylor);
int16_t fixup = taylor.d[0] - lastTaylor.predict();
// Hack for values, jumping from -100 to 100
if (taylor.d[0] >= VALUE_LIMIT_POS && lastTaylor.d[0] < 0)
fixup -= 2 * taylor.d[0];
// Value too big for arithmetic codec, use nibbles
if (fixup > INDEX_PLUS + NUM_BIN_OUTLIERS ||
fixup < -ZERO_POS - NUM_BIN_OUTLIERS)
{
nibbleWriter.write12(fixup);
arWriter.write(INDEX_SIZE + BIN12);
}
else if (fixup > INDEX_PLUS || fixup < -ZERO_POS)
{
if (fixup > 0)
nibbleWriter.write4(fixup - INDEX_PLUS - 1);
else
nibbleWriter.write4((-fixup - ZERO_POS - 1) | 0x8);
arWriter.write(INDEX_SIZE + BIN4);
}
else
{
arWriter.write(ZERO_POS + fixup);
}
// Hack for values, jumping from -100 to 100
if (taylor.d[0] >= VALUE_LIMIT_POS && lastTaylor.d[0] < 0)
{
lastTaylor.negate();
taylor.update(lastTaylor);
}
// This will be used to predict the next value
// (derivative is not updated for the first column)
lastTaylor.copyFrom(taylor, col? 3: 1);
}
}
nibbleWriter.flush();
arWriter.flush();
size_t size = arWriter.getStreamPos() - &compacted[0];
cout
<< "ArEnc="
<< (arWriter.getStreamPos() - pNibbles - nibbles) * 2
<< "\nTotal=" << size * 2 << "\n---------\n";
for (size_t i = 0; i < size; i += 8)
{
cout << " " << hex << showbase;
ostream_iterator<int> out_it (cout, ", ");
std::copy(compacted.begin() + i,
(i + 8 < size)?
compacted.begin() + i + 8: compacted.begin() + size,
out_it);
cout << "\n";
}
}
int main()
{
encoder();
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y21hdGg+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDxudW1lcmljPgojaW5jbHVkZSA8aXRlcmF0b3I+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxjc3RkbGliPiAKI2luY2x1ZGUgPGNzdGRkZWY+CiNpbmNsdWRlIDxzdGRpbnQuaD4KI2luY2x1ZGUgPGlvbWFuaXA+CgplbnVtIHsKICAvLyBDb25maWcKICBaRVJPX1BPUyA9IDIsCiAgSU5ERVhfU0laRSA9IDUsCiAgVkFMVUVfTElNSVQgPSAtMTAwLAoKICAvLyBDb25zdGFudHMKICBOVU1fUk9XUyA9IDM3LAogIE5VTV9DT0xVTU5TID0gNzMsCiAgVkFMVUVfTElNSVRfUE9TID0gLVZBTFVFX0xJTUlULAogIE5VTV9CSU5fT1VUTElFUlMgPSA4LAogIE5VTV9WQUxVRVMgPSBOVU1fUk9XUyAqIChOVU1fQ09MVU1OUyAtIDEpLAogIElOREVYX1BMVVMgPSBJTkRFWF9TSVpFIC0gWkVST19QT1MgLSAxLAogIEJJTjQgPSAwLAogIEJJTjEyID0gMSwKICBJTkRFWF9GVUxMX1NJWkUgPSBJTkRFWF9TSVpFICsgMgp9OwoKaW50MTZfdCBteV9hcnJheVtOVU1fUk9XU11bTlVNX0NPTFVNTlNdID0gewp7MTUwLDE0NSwxNDAsMTM1LDEzMCwxMjUsMTIwLDExNSwxMTAsMTA1LDEwMCw5NSw5MCw4NSw4MCw3NSw3MCw2NSw2MCw1NSw1MCw0NSw0MCwzNSwzMCwyNSwyMCwxNSwxMCw1LDAsLTQsLTksLTE0LC0xOSwtMjQsLTI5LC0zNCwtMzksLTQ0LC00OSwtNTQsLTU5LC02NCwtNjksLTc0LC03OSwtODQsLTg5LC05NCwtOTksMTA0LDEwOSwxMTQsMTE5LDEyNCwxMjksMTM0LDEzOSwxNDQsMTQ5LDE1NCwxNTksMTY0LDE2OSwxNzQsMTc5LDE3NSwxNzAsMTY1LDE2MCwxNTUsMTUwfSwgXAp7MTQzLDEzNywxMzEsMTI2LDEyMCwxMTUsMTEwLDEwNSwxMDAsOTUsOTAsODUsODAsNzUsNzEsNjYsNjIsNTcsNTMsNDgsNDQsMzksMzUsMzEsMjcsMjIsMTgsMTQsOSw1LDEsLTMsLTcsLTExLC0xNiwtMjAsLTI1LC0yOSwtMzQsLTM4LC00MywtNDcsLTUyLC01NywtNjEsLTY2LC03MSwtNzYsLTgxLC04NiwtOTEsLTk2LDEwMSwxMDcsMTEyLDExNywxMjMsMTI4LDEzNCwxNDAsMTQ2LDE1MSwxNTcsMTYzLDE2OSwxNzUsMTc4LDE3MiwxNjYsMTYwLDE1NCwxNDgsMTQzfSwgXAp7MTMwLDEyNCwxMTgsMTEyLDEwNywxMDEsOTYsOTIsODcsODIsNzgsNzQsNzAsNjUsNjEsNTcsNTQsNTAsNDYsNDIsMzgsMzQsMzEsMjcsMjMsMTksMTYsMTIsOCw0LDEsLTIsLTYsLTEwLC0xNCwtMTgsLTIyLC0yNiwtMzAsLTM0LC0zOCwtNDMsLTQ3LC01MSwtNTYsLTYxLC02NSwtNzAsLTc1LC03OSwtODQsLTg5LC05NCwxMDAsMTA1LDExMSwxMTYsMTIyLDEyOCwxMzUsMTQxLDE0OCwxNTUsMTYyLDE3MCwxNzcsMTc0LDE2NiwxNTksMTUxLDE0NCwxMzcsMTMwfSwgXAp7MTExLDEwNCw5OSw5NCw4OSw4NSw4MSw3Nyw3Myw3MCw2Niw2Myw2MCw1Niw1Myw1MCw0Niw0Myw0MCwzNiwzMywzMCwyNiwyMywyMCwxNiwxMywxMCw2LDMsMCwtMywtNiwtOSwtMTMsLTE2LC0yMCwtMjQsLTI4LC0zMiwtMzYsLTQwLC00NCwtNDgsLTUyLC01NywtNjEsLTY1LC03MCwtNzQsLTc5LC04NCwtODgsLTkzLC05OCwxMDMsMTA5LDExNSwxMjEsMTI4LDEzNSwxNDMsMTUyLDE2MiwxNzIsMTc2LDE2NSwxNTQsMTQ0LDEzNCwxMjUsMTE4LDExMX0sIFwKezg1LDgxLDc3LDc0LDcxLDY4LDY1LDYzLDYwLDU4LDU2LDUzLDUxLDQ5LDQ2LDQzLDQxLDM4LDM1LDMyLDI5LDI2LDIzLDE5LDE2LDEzLDEwLDcsNCwxLC0xLC0zLC02LC05LC0xMywtMTYsLTE5LC0yMywtMjYsLTMwLC0zNCwtMzgsLTQyLC00NiwtNTAsLTU0LC01OCwtNjIsLTY2LC03MCwtNzQsLTc4LC04MywtODcsLTkxLC05NSwxMDAsMTA1LDExMCwxMTcsMTI0LDEzMywxNDQsMTU5LDE3OCwxNjAsMTQxLDEyNSwxMTIsMTAzLDk2LDkwLDg1fSwgXAp7NjIsNjAsNTgsNTcsNTUsNTQsNTIsNTEsNTAsNDgsNDcsNDYsNDQsNDIsNDEsMzksMzYsMzQsMzEsMjgsMjUsMjIsMTksMTYsMTMsMTAsNyw0LDIsMCwtMywtNSwtOCwtMTAsLTEzLC0xNiwtMTksLTIyLC0yNiwtMjksLTMzLC0zNywtNDEsLTQ1LC00OSwtNTMsLTU2LC02MCwtNjQsLTY3LC03MCwtNzQsLTc3LC04MCwtODMsLTg2LC04OSwtOTEsLTk0LC05NywxMDEsMTA1LDExMSwxMzAsMTA5LDg0LDc3LDc0LDcxLDY4LDY2LDY0LDYyfSwgXAp7NDYsNDYsNDUsNDQsNDQsNDMsNDIsNDIsNDEsNDEsNDAsMzksMzgsMzcsMzYsMzUsMzMsMzEsMjgsMjYsMjMsMjAsMTYsMTMsMTAsNyw0LDEsLTEsLTMsLTUsLTcsLTksLTEyLC0xNCwtMTYsLTE5LC0yMiwtMjYsLTI5LC0zMywtMzYsLTQwLC00NCwtNDgsLTUxLC01NSwtNTgsLTYxLC02NCwtNjYsLTY4LC03MSwtNzIsLTc0LC03NCwtNzUsLTc0LC03MiwtNjgsLTYxLC00OCwtMjUsMiwyMiwzMyw0MCw0Myw0NSw0Niw0Nyw0Niw0Nn0sIFwKezM2LDM2LDM2LDM2LDM2LDM1LDM1LDM1LDM1LDM0LDM0LDM0LDM0LDMzLDMyLDMxLDMwLDI4LDI2LDIzLDIwLDE3LDE0LDEwLDYsMywwLC0yLC00LC03LC05LC0xMCwtMTIsLTE0LC0xNSwtMTcsLTIwLC0yMywtMjYsLTI5LC0zMiwtMzYsLTQwLC00MywtNDcsLTUwLC01MywtNTYsLTU4LC02MCwtNjIsLTYzLC02NCwtNjQsLTYzLC02MiwtNTksLTU1LC00OSwtNDEsLTMwLC0xNywtNCw2LDE1LDIyLDI3LDMxLDMzLDM0LDM1LDM2LDM2fSwgXAp7MzAsMzAsMzAsMzAsMzAsMzAsMzAsMjksMjksMjksMjksMjksMjksMjksMjksMjgsMjcsMjYsMjQsMjEsMTgsMTUsMTEsNywzLDAsLTMsLTYsLTksLTExLC0xMiwtMTQsLTE1LC0xNiwtMTcsLTE5LC0yMSwtMjMsLTI2LC0yOSwtMzIsLTM1LC0zOSwtNDIsLTQ1LC00OCwtNTEsLTUzLC01NSwtNTYsLTU3LC01NywtNTYsLTU1LC01MywtNDksLTQ0LC0zOCwtMzEsLTIzLC0xNCwtNiwwLDcsMTMsMTcsMjEsMjQsMjYsMjcsMjksMjksMzB9LCBcCnsyNSwyNSwyNiwyNiwyNiwyNSwyNSwyNSwyNSwyNSwyNSwyNSwyNSwyNiwyNSwyNSwyNCwyMywyMSwxOSwxNiwxMiw4LDQsMCwtMywtNywtMTAsLTEzLC0xNSwtMTYsLTE3LC0xOCwtMTksLTIwLC0yMSwtMjIsLTIzLC0yNSwtMjgsLTMxLC0zNCwtMzcsLTQwLC00MywtNDYsLTQ4LC00OSwtNTAsLTUxLC01MSwtNTAsLTQ4LC00NSwtNDIsLTM3LC0zMiwtMjYsLTE5LC0xMywtNywtMSwzLDcsMTEsMTQsMTcsMTksMjEsMjMsMjQsMjUsMjV9LCBcCnsyMSwyMiwyMiwyMiwyMiwyMiwyMiwyMiwyMiwyMiwyMiwyMiwyMiwyMiwyMiwyMiwyMSwyMCwxOCwxNiwxMyw5LDUsMSwtMywtNywtMTEsLTE0LC0xNywtMTgsLTIwLC0yMSwtMjEsLTIyLC0yMiwtMjIsLTIzLC0yMywtMjUsLTI3LC0yOSwtMzIsLTM1LC0zNywtNDAsLTQyLC00NCwtNDUsLTQ1LC00NSwtNDQsLTQyLC00MCwtMzYsLTMyLC0yNywtMjIsLTE3LC0xMiwtNywtMywwLDMsNyw5LDEyLDE0LDE2LDE4LDE5LDIwLDIxLDIxfSwgXAp7MTgsMTksMTksMTksMTksMTksMTksMTksMTksMTksMTksMTksMTksMTksMTksMTksMTgsMTcsMTYsMTQsMTAsNywyLC0xLC02LC0xMCwtMTQsLTE3LC0xOSwtMjEsLTIyLC0yMywtMjQsLTI0LC0yNCwtMjQsLTIzLC0yMywtMjMsLTI0LC0yNiwtMjgsLTMwLC0zMywtMzUsLTM3LC0zOCwtMzksLTM5LC0zOCwtMzYsLTM0LC0zMSwtMjgsLTI0LC0xOSwtMTUsLTEwLC02LC0zLDAsMSw0LDYsOCwxMCwxMiwxNCwxNSwxNiwxNywxOCwxOH0sIFwKezE2LDE2LDE3LDE3LDE3LDE3LDE3LDE3LDE3LDE3LDE3LDE2LDE2LDE2LDE2LDE2LDE2LDE1LDEzLDExLDgsNCwwLC00LC05LC0xMywtMTYsLTE5LC0yMSwtMjMsLTI0LC0yNSwtMjUsLTI1LC0yNSwtMjQsLTIzLC0yMSwtMjAsLTIwLC0yMSwtMjIsLTI0LC0yNiwtMjgsLTMwLC0zMSwtMzIsLTMxLC0zMCwtMjksLTI3LC0yNCwtMjEsLTE3LC0xMywtOSwtNiwtMywtMSwwLDIsNCw1LDcsOSwxMCwxMiwxMywxNCwxNSwxNiwxNn0sIFwKezE0LDE0LDE0LDE1LDE1LDE1LDE1LDE1LDE1LDE1LDE0LDE0LDE0LDE0LDE0LDE0LDEzLDEyLDExLDksNSwyLC0yLC02LC0xMSwtMTUsLTE4LC0yMSwtMjMsLTI0LC0yNSwtMjUsLTI1LC0yNSwtMjQsLTIyLC0yMSwtMTgsLTE2LC0xNSwtMTUsLTE1LC0xNywtMTksLTIxLC0yMiwtMjQsLTI0LC0yNCwtMjMsLTIyLC0yMCwtMTgsLTE1LC0xMiwtOSwtNSwtMywtMSwwLDEsMiw0LDUsNiw4LDksMTAsMTEsMTIsMTMsMTQsMTR9LCBcCnsxMiwxMywxMywxMywxMywxMywxMywxMywxMywxMywxMywxMywxMiwxMiwxMiwxMiwxMSwxMCw5LDYsMywwLC00LC04LC0xMiwtMTYsLTE5LC0yMSwtMjMsLTI0LC0yNCwtMjQsLTI0LC0yMywtMjIsLTIwLC0xNywtMTUsLTEyLC0xMCwtOSwtOSwtMTAsLTEyLC0xMywtMTUsLTE3LC0xNywtMTgsLTE3LC0xNiwtMTUsLTEzLC0xMSwtOCwtNSwtMywtMSwwLDEsMSwyLDMsNCw2LDcsOCw5LDEwLDExLDEyLDEyLDEyfSwgXAp7MTEsMTEsMTEsMTEsMTEsMTIsMTIsMTIsMTIsMTIsMTEsMTEsMTEsMTEsMTEsMTAsMTAsOSw3LDUsMiwtMSwtNSwtOSwtMTMsLTE3LC0yMCwtMjIsLTIzLC0yMywtMjMsLTIzLC0yMiwtMjAsLTE4LC0xNiwtMTQsLTExLC05LC02LC01LC00LC01LC02LC04LC05LC0xMSwtMTIsLTEyLC0xMiwtMTIsLTExLC05LC04LC02LC0zLC0xLDAsMCwxLDEsMiwzLDQsNSw2LDcsOCw5LDEwLDExLDExLDExfSwgXAp7MTAsMTAsMTAsMTAsMTAsMTAsMTAsMTAsMTAsMTAsMTAsMTAsMTAsMTAsOSw5LDksNyw2LDMsMCwtMywtNiwtMTAsLTE0LC0xNywtMjAsLTIxLC0yMiwtMjIsLTIyLC0yMSwtMTksLTE3LC0xNSwtMTMsLTEwLC04LC02LC00LC0yLC0yLC0yLC0yLC00LC01LC03LC04LC04LC05LC04LC04LC03LC01LC00LC0yLDAsMCwxLDEsMSwyLDIsMyw0LDUsNiw3LDgsOSwxMCwxMCwxMH0sIFwKezksOSw5LDksOSw5LDksMTAsMTAsOSw5LDksOSw5LDksOCw4LDYsNSwyLDAsLTQsLTcsLTExLC0xNSwtMTcsLTE5LC0yMSwtMjEsLTIxLC0yMCwtMTgsLTE2LC0xNCwtMTIsLTEwLC04LC02LC00LC0yLC0xLDAsMCwwLC0xLC0yLC00LC01LC01LC02LC02LC01LC01LC00LC0zLC0xLDAsMCwxLDEsMSwxLDIsMywzLDUsNiw3LDgsOCw5LDksOX0sIFwKezksOSw5LDksOSw5LDksOSw5LDksOSw5LDgsOCw4LDgsNyw1LDQsMSwtMSwtNSwtOCwtMTIsLTE1LC0xNywtMTksLTIwLC0yMCwtMTksLTE4LC0xNiwtMTQsLTExLC05LC03LC01LC00LC0yLC0xLDAsMCwxLDEsMCwwLC0yLC0zLC0zLC00LC00LC00LC0zLC0zLC0yLC0xLDAsMCwwLDAsMCwxLDEsMiwzLDQsNSw2LDcsOCw4LDksOX0sIFwKezksOSw5LDgsOCw4LDksOSw5LDksOSw4LDgsOCw4LDcsNiw1LDMsMCwtMiwtNSwtOSwtMTIsLTE1LC0xNywtMTgsLTE5LC0xOSwtMTgsLTE2LC0xNCwtMTIsLTksLTcsLTUsLTQsLTIsLTEsMCwwLDEsMSwxLDEsMCwwLC0xLC0yLC0yLC0zLC0zLC0yLC0yLC0xLC0xLDAsMCwwLDAsMCwwLDAsMSwyLDMsNCw1LDYsNyw4LDgsOX0sIFwKezgsOCw4LDgsOCw4LDksOSw5LDksOSw5LDgsOCw4LDcsNiw0LDIsMCwtMywtNiwtOSwtMTIsLTE1LC0xNywtMTgsLTE4LC0xNywtMTYsLTE0LC0xMiwtMTAsLTgsLTYsLTQsLTIsLTEsMCwwLDEsMiwyLDIsMiwxLDAsMCwtMSwtMSwtMSwtMiwtMiwtMSwtMSwwLDAsMCwwLDAsMCwwLDAsMCwxLDIsMyw0LDUsNiw3LDgsOH0sIFwKezgsOCw4LDgsOSw5LDksOSw5LDksOSw5LDksOCw4LDcsNSwzLDEsLTEsLTQsLTcsLTEwLC0xMywtMTUsLTE2LC0xNywtMTcsLTE2LC0xNSwtMTMsLTExLC05LC02LC01LC0zLC0yLDAsMCwwLDEsMiwyLDIsMiwxLDEsMCwwLDAsLTEsLTEsLTEsLTEsLTEsMCwwLDAsMCwtMSwtMSwtMSwtMSwtMSwwLDAsMSwzLDQsNSw3LDcsOH0sIFwKezgsOCw5LDksOSw5LDEwLDEwLDEwLDEwLDEwLDEwLDEwLDksOCw3LDUsMywwLC0yLC01LC04LC0xMSwtMTMsLTE1LC0xNiwtMTYsLTE2LC0xNSwtMTMsLTEyLC0xMCwtOCwtNiwtNCwtMiwtMSwwLDAsMSwyLDIsMywzLDIsMiwxLDAsMCwwLDAsMCwwLDAsMCwwLDAsLTEsLTEsLTIsLTIsLTIsLTIsLTIsLTEsMCwwLDEsMyw0LDYsNyw4fSwgXAp7Nyw4LDksOSw5LDEwLDEwLDExLDExLDExLDExLDExLDEwLDEwLDksNyw1LDMsMCwtMiwtNiwtOSwtMTEsLTEzLC0xNSwtMTYsLTE2LC0xNSwtMTQsLTEzLC0xMSwtOSwtNywtNSwtMywtMiwwLDAsMSwxLDIsMywzLDMsMywyLDIsMSwxLDAsMCwwLDAsMCwwLDAsLTEsLTEsLTIsLTMsLTMsLTQsLTQsLTQsLTMsLTIsLTEsMCwxLDMsNSw2LDd9LCBcCns2LDgsOSw5LDEwLDExLDExLDEyLDEyLDEyLDEyLDEyLDExLDExLDksNyw1LDIsMCwtMywtNywtMTAsLTEyLC0xNCwtMTUsLTE2LC0xNSwtMTUsLTEzLC0xMiwtMTAsLTgsLTcsLTUsLTMsLTEsMCwwLDEsMiwyLDMsMyw0LDMsMywzLDIsMiwxLDEsMSwwLDAsMCwwLC0xLC0yLC0zLC00LC00LC01LC01LC01LC01LC00LC0yLC0xLDAsMiwzLDUsNn0sIFwKezYsNyw4LDEwLDExLDEyLDEyLDEzLDEzLDE0LDE0LDEzLDEzLDExLDEwLDgsNSwyLDAsLTQsLTgsLTExLC0xMywtMTUsLTE2LC0xNiwtMTYsLTE1LC0xMywtMTIsLTEwLC04LC02LC01LC0zLC0xLDAsMCwxLDIsMywzLDQsNCw0LDQsNCwzLDMsMywyLDIsMSwxLDAsMCwtMSwtMiwtMywtNSwtNiwtNywtNywtNywtNiwtNSwtNCwtMywtMSwwLDIsNCw2fSwgXAp7NSw3LDgsMTAsMTEsMTIsMTMsMTQsMTUsMTUsMTUsMTQsMTQsMTIsMTEsOCw1LDIsLTEsLTUsLTksLTEyLC0xNCwtMTYsLTE3LC0xNywtMTYsLTE1LC0xNCwtMTIsLTExLC05LC03LC01LC0zLC0xLDAsMCwxLDIsMyw0LDQsNSw1LDUsNSw1LDUsNCw0LDMsMywyLDEsMCwtMSwtMiwtNCwtNiwtNywtOCwtOCwtOCwtOCwtNywtNiwtNCwtMiwwLDEsMyw1fSwgXAp7NCw2LDgsMTAsMTIsMTMsMTQsMTUsMTYsMTYsMTYsMTYsMTUsMTMsMTEsOSw1LDIsLTIsLTYsLTEwLC0xMywtMTYsLTE3LC0xOCwtMTgsLTE3LC0xNiwtMTUsLTEzLC0xMSwtOSwtNywtNSwtNCwtMiwwLDAsMSwzLDMsNCw1LDYsNiw3LDcsNyw3LDcsNiw1LDQsMywyLDAsLTEsLTMsLTUsLTcsLTgsLTksLTEwLC0xMCwtMTAsLTksLTcsLTUsLTQsLTEsMCwyLDR9LCBcCns0LDYsOCwxMCwxMiwxNCwxNSwxNiwxNywxOCwxOCwxNywxNiwxNSwxMiw5LDUsMSwtMywtOCwtMTIsLTE1LC0xOCwtMTksLTIwLC0yMCwtMTksLTE4LC0xNiwtMTUsLTEzLC0xMSwtOCwtNiwtNCwtMiwtMSwwLDEsMyw0LDUsNiw3LDgsOSw5LDksOSw5LDksOCw3LDUsMywxLC0xLC0zLC02LC04LC0xMCwtMTEsLTEyLC0xMiwtMTEsLTEwLC05LC03LC01LC0yLDAsMSw0fSwgXAp7NCw2LDgsMTEsMTMsMTUsMTYsMTgsMTksMTksMTksMTksMTgsMTYsMTMsMTAsNSwwLC01LC0xMCwtMTUsLTE4LC0yMSwtMjIsLTIzLC0yMiwtMjIsLTIwLC0xOCwtMTcsLTE0LC0xMiwtMTAsLTgsLTUsLTMsLTEsMCwxLDMsNSw2LDgsOSwxMCwxMSwxMiwxMiwxMywxMiwxMiwxMSw5LDcsNSwyLDAsLTMsLTYsLTksLTExLC0xMiwtMTMsLTEzLC0xMiwtMTEsLTEwLC04LC02LC0zLC0xLDEsNH0sIFwKezMsNiw5LDExLDE0LDE2LDE3LDE5LDIwLDIxLDIxLDIxLDE5LDE3LDE0LDEwLDQsLTEsLTgsLTE0LC0xOSwtMjIsLTI1LC0yNiwtMjYsLTI2LC0yNSwtMjMsLTIxLC0xOSwtMTcsLTE0LC0xMiwtOSwtNywtNCwtMiwwLDEsMyw1LDcsOSwxMSwxMywxNCwxNSwxNiwxNiwxNiwxNiwxNSwxMywxMCw3LDQsMCwtMywtNywtMTAsLTEyLC0xNCwtMTUsLTE0LC0xNCwtMTIsLTExLC05LC02LC00LC0xLDEsM30sIFwKezQsNiw5LDEyLDE0LDE3LDE5LDIxLDIyLDIzLDIzLDIzLDIxLDE5LDE1LDksMiwtNSwtMTMsLTIwLC0yNSwtMjgsLTMwLC0zMSwtMzEsLTMwLC0yOSwtMjcsLTI1LC0yMiwtMjAsLTE3LC0xNCwtMTEsLTksLTYsLTMsMCwxLDQsNiw5LDExLDEzLDE1LDE3LDE5LDIwLDIxLDIxLDIxLDIwLDE4LDE1LDExLDYsMiwtMiwtNywtMTEsLTEzLC0xNSwtMTYsLTE2LC0xNSwtMTMsLTExLC05LC03LC00LC0xLDEsNH0sIFwKezQsNywxMCwxMywxNSwxOCwyMCwyMiwyNCwyNSwyNSwyNSwyMywyMCwxNSw3LC0yLC0xMiwtMjIsLTI5LC0zNCwtMzcsLTM4LC0zOCwtMzcsLTM2LC0zNCwtMzEsLTI5LC0yNiwtMjMsLTIwLC0xNywtMTMsLTEwLC03LC00LC0xLDIsNSw4LDExLDEzLDE2LDE4LDIxLDIzLDI0LDI2LDI2LDI2LDI2LDI0LDIxLDE3LDEyLDUsMCwtNiwtMTAsLTE0LC0xNiwtMTYsLTE2LC0xNSwtMTQsLTEyLC0xMCwtNywtNCwtMSwxLDR9LCBcCns0LDcsMTAsMTMsMTYsMTksMjIsMjQsMjYsMjcsMjcsMjYsMjQsMTksMTEsLTEsLTE1LC0yOCwtMzcsLTQzLC00NiwtNDcsLTQ3LC00NSwtNDQsLTQxLC0zOSwtMzYsLTMyLC0yOSwtMjYsLTIyLC0xOSwtMTUsLTExLC04LC00LC0xLDIsNSw5LDEyLDE1LDE5LDIyLDI0LDI3LDI5LDMxLDMzLDMzLDMzLDMyLDMwLDI2LDIxLDE0LDYsMCwtNiwtMTEsLTE0LC0xNSwtMTYsLTE1LC0xNCwtMTIsLTksLTcsLTQsLTEsMSw0fSwgXAp7Niw5LDEyLDE1LDE4LDIxLDIzLDI1LDI3LDI4LDI3LDI0LDE3LDQsLTE0LC0zNCwtNDksLTU2LC02MCwtNjAsLTYwLC01OCwtNTYsLTUzLC01MCwtNDcsLTQzLC00MCwtMzYsLTMyLC0yOCwtMjUsLTIxLC0xNywtMTMsLTksLTUsLTEsMiw2LDEwLDE0LDE3LDIxLDI0LDI4LDMxLDM0LDM3LDM5LDQxLDQyLDQzLDQzLDQxLDM4LDMzLDI1LDE3LDgsMCwtNCwtOCwtMTAsLTEwLC0xMCwtOCwtNywtNCwtMiwwLDMsNn0sIFwKezIyLDI0LDI2LDI4LDMwLDMyLDMzLDMxLDIzLC0xOCwtODEsLTk2LC05OSwtOTgsLTk1LC05MywtODksLTg2LC04MiwtNzgsLTc0LC03MCwtNjYsLTYyLC01NywtNTMsLTQ5LC00NCwtNDAsLTM2LC0zMiwtMjcsLTIzLC0xOSwtMTQsLTEwLC02LC0xLDIsNiwxMCwxNSwxOSwyMywyNywzMSwzNSwzOCw0Miw0NSw0OSw1Miw1NSw1Nyw2MCw2MSw2Myw2Myw2Miw2MSw1Nyw1Myw0Nyw0MCwzMywyOCwyMywyMSwxOSwxOSwxOSwyMCwyMn0sIFwKezE2OCwxNzMsMTc4LDE3NiwxNzEsMTY2LDE2MSwxNTYsMTUxLDE0NiwxNDEsMTM2LDEzMSwxMjYsMTIxLDExNiwxMTEsMTA2LDEwMSwtOTYsLTkxLC04NiwtODEsLTc2LC03MSwtNjYsLTYxLC01NiwtNTEsLTQ2LC00MSwtMzYsLTMxLC0yNiwtMjEsLTE2LC0xMSwtNiwtMSwzLDgsMTMsMTgsMjMsMjgsMzMsMzgsNDMsNDgsNTMsNTgsNjMsNjgsNzMsNzgsODMsODgsOTMsOTgsMTAzLDEwOCwxMTMsMTE4LDEyMywxMjgsMTMzLDEzOCwxNDMsMTQ4LDE1MywxNTgsMTYzLDE2OH19OwoKICAgICAgdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCiAgICAgIGNsYXNzIEVudHJvcHkKICAgICAgewogICAgICAgIHVpbnQxNl90IHRvdGFsOwogICAgICBwdWJsaWM6CiAgICAgICAgRW50cm9weSh1aW50MTZfdCBhZGQpOiB0b3RhbChhZGQgKyBOVU1fVkFMVUVTKSB7fQogICAgICAgIGRvdWJsZSBvcGVyYXRvciAoKShkb3VibGUgYWNjLCB1aW50MTZfdCB2YWwpCiAgICAgICAgewoJICBkb3VibGUgcGFydCA9IHN0YXRpY19jYXN0PGRvdWJsZT4odmFsKSAvIHRvdGFsOwoJICByZXR1cm4gYWNjIC0gKHBhcnQ/IHBhcnQgKiBsb2cocGFydCkgLyBsb2coMi4pOiAwLik7CiAgICAgICAgfQogICAgICB9OwoKICAgICAgc3RydWN0IFRheWxvcgogICAgICB7CglpbnQxNl90IGRbMl07CglUYXlsb3IoKQoJewoJICBmaWxsKGQsIGQgKyAyLCAwKTsKCX0KCVRheWxvcihpbnQxNl90IHZhbCwgY29uc3QgVGF5bG9yJiBvdGhlcikKCXsKCSAgZFswXSA9IHZhbDsKCSAgdXBkYXRlKG90aGVyKTsKCX0KCWludDE2X3QgcHJlZGljdCgpCgl7CgkgIHJldHVybiBhY2N1bXVsYXRlKGQsIGQgKyAyLCAwKTsKCX0KCXZvaWQgY29weUZyb20oY29uc3QgVGF5bG9yJiBvdGhlciwgc2l6ZV90IGVuZCA9IDIpCgl7CgkgIGNvcHkob3RoZXIuZCwgb3RoZXIuZCArIGVuZCwgZCk7Cgl9Cgl2b2lkIHVwZGF0ZShjb25zdCBUYXlsb3ImIG90aGVyKQoJewoJICBkWzFdID0gZFswXSAtIG90aGVyLmRbMF07Cgl9Cgl2b2lkIG5lZ2F0ZSgpCgl7CgkgIGRbMF0gPSAtZFswXTsKCSAgZFsxXSA9IC1kWzFdOwoJfQoJdm9pZCBjbGVhcigpCgl7CgkgIGZpbGwoZCwgZCArIDIsIDApOwoJfQogICAgICB9OwoKICAgICAgY2xhc3MgTmliYmxlV3JpdGVyCiAgICAgIHsKCXVpbnQxNl90KiBzdHJlYW07Cgl1aW50MTZfdCogbGltaXQ7Cgl1aW50MTZfdCBibG9jazsKCXVpbnQxNl90IHBvczsKICAgICAgcHVibGljOgoJTmliYmxlV3JpdGVyKHVpbnQxNl90KiBwLCB1aW50MTZfdCB4KQoJewoJICB4ICY9IDB4MEZGRjsKCSAgc3RyZWFtID0gcDsKCSAgYmxvY2sgPSB4OwoJICBsaW1pdCA9IHAgKyB4OwoJICBwb3MgPSAxMjsKCX0KCXZvaWQgd3JpdGU0KHVpbnQxNl90IHgpCgl7CgkgIGJsb2NrIHw9ICh4ICYgMTUpIDw8IHBvczsKCSAgcG9zICs9IDQ7CgkgIGlmIChwb3MgPT0gMTYpCgkgICAgZmx1c2goKTsKCX0KCXZvaWQgd3JpdGUxMih1aW50MTZfdCB4KQoJewoJICB3cml0ZTQoeCk7CgkgIHdyaXRlNCh4ID4+IDQpOwoJICB3cml0ZTQoeCA+PiA4KTsKCX0KCXZvaWQgZmx1c2goKQoJewoJICBpZiAocG9zKQoJICB7CgkgICAgaWYgKHN0cmVhbSA+PSBsaW1pdCkKCSAgICB7CgkgICAgICBjZXJyIDw8ICJJbnRlcm5hbCBlcnJvcjogbmliYmxlIGJ1ZmZlciBvdmVyZmxvd1xuIjsKCSAgICAgIGV4aXQoMSk7CgkgICAgfQoKCSAgICAqc3RyZWFtKysgPSBibG9jazsKCSAgfQoKCSAgYmxvY2sgPSAwOwoJICBwb3MgPSAwOwoJfQogICAgICB9OwoKICAgICAgY2xhc3MgQXJXcml0ZXIKICAgICAgeyAvLyBodHRwOi8vdy4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4ucy5jb20vYWNfYXJpdGhtZXRpYy5odG1sCgl1aW50MTZfdCogc3RyZWFtOwoJdWludDE2X3QqIHRhYmxlOwoJdWludDE2X3QqIHRhYmxlRW5kOwoJdWludDE2X3QgaGlnaDsKCXVpbnQxNl90IGxvdzsKCXVpbnQxNl90IHJlc3VsdDsKCXVpbnQxNl90IHJlc3VsdFVzZWQ7Cgl1aW50MTZfdCB1bmRlcmZsb3dzOwogICAgICBwdWJsaWM6CglBcldyaXRlcih1aW50MTZfdCogcCwgdWludDE2X3QqIHQsIHVpbnQxNl90KiBlKQoJOiBzdHJlYW0ocCkKCSwgdGFibGUodCkgLy8gWmVybyB2YWx1ZSBpbiAqKHQtMSkgZXhwZWN0ZWQKCSwgdGFibGVFbmQoZSkKCSwgaGlnaCgweEZGRkYpCgksIGxvdygwKQoJLCByZXN1bHQoMCkKCSwgcmVzdWx0VXNlZCgwKQoJLCB1bmRlcmZsb3dzKDApCgl7fQoJdm9pZCB3cml0ZSh1aW50MTZfdCB2YWx1ZSkKCXsKCSAgdWludDMyX3QgcmFuZ2UgPSBzdGF0aWNfY2FzdDx1aW50MzJfdD4oaGlnaCkgLSBsb3cgKyAxOwoJICBoaWdoID0gbG93ICsgKChyYW5nZSAqIHRhYmxlW3ZhbHVlXSkgLyAqKHRhYmxlRW5kIC0gMSkpIC0gMTsKCSAgbG93ID0gbG93ICsgKHJhbmdlICogdGFibGVbdmFsdWUgLSAxXSkgLyAqKHRhYmxlRW5kIC0gMSk7CgoJICB3aGlsZSAodHJ1ZSkgewoJICAgIGlmICgoaGlnaCBeIGxvdykgJiAweDgwMDApIC8vIGRpZmZlcmVudCBtc2IKCSAgICB7CgkgICAgICBpZiAoKGhpZ2ggJiAweDQwMDApIDwgKGxvdyAmIDB4NDAwMCkpCgkgICAgICB7CgkJKyt1bmRlcmZsb3dzOwoJCWxvdyAmPSAweDNGRkY7CgkJaGlnaCB8PSAweDQwMDA7CgkJc2hpZnQoKTsKCSAgICAgIH0KCSAgICAgIGVsc2UKCSAgICAgIHsKCQlicmVhazsKCSAgICAgIH0KCSAgICB9CgkgICAgZWxzZSAvLyBlcXVhbCBtc2IKCSAgICB7CgkgICAgICB3cml0ZUJpdCgobG93ID4+IDE1KSAmIDEpOwoJICAgICAgd2hpbGUgKHVuZGVyZmxvd3MpCgkgICAgICB7CgkJd3JpdGVCaXQoKH5sb3cgPj4gMTUpICYgMSk7CgkJLS11bmRlcmZsb3dzOwoJICAgICAgfQoJICAgICAgc2hpZnQoKTsKCSAgICB9CgkgIH0KCX0KCXZvaWQgc2hpZnQoKQoJewoJICBsb3cgPDw9IDE7CgkgIGhpZ2ggPDw9IDE7CgkgIGhpZ2ggfD0gMTsKCX0KCXZvaWQgd3JpdGVCaXQodWludDE2X3QgYml0KQoJewoJICByZXN1bHQgPDw9IDE7CgkgIHJlc3VsdCB8PSBiaXQ7CgkgICsrcmVzdWx0VXNlZDsKCSAgaWYgKHJlc3VsdFVzZWQgPT0gMTYpCgkgICAgZmx1c2hSZXN1bHQoKTsKCX0KCXZvaWQgZmx1c2hSZXN1bHQoKQoJewoJICAqc3RyZWFtKysgPSByZXN1bHQ7CgkgIHJlc3VsdCA9IDA7CgkgIHJlc3VsdFVzZWQgPSAwOwoJfQoJdm9pZCBmbHVzaCgpCgl7CgkgIHdyaXRlQml0KChsb3cgPj4gMTQpICYgMSk7CgkgICsrdW5kZXJmbG93czsKCgkgIHdoaWxlICh1bmRlcmZsb3dzLS0pCgkgICAgd3JpdGVCaXQoKH5sb3cgPj4gMTQpICYgMSk7CgoJICB3aGlsZSAocmVzdWx0VXNlZCkKCSAgICB3cml0ZUJpdCgwKTsKCX0KCXVpbnQxNl90KiBnZXRTdHJlYW1Qb3MoKSBjb25zdAoJewoJICByZXR1cm4gc3RyZWFtOwoJfQogICAgICB9OwoKICAgICAgdm9pZCBlbmNvZGVyKCkKICAgICAgewoJLy8gUGFzcyAxOiBjYWxjdWxhdGUgZnJlcXVlbmNpZXMKCXZlY3Rvcjx1aW50MTZfdD4gZnJlcSgxMDI0KTsKCXVpbnQxNl90IGJpbmFyeTQgPSAwOwoJdWludDE2X3QgYmluYXJ5MTIgPSAwOwoJVGF5bG9yIGxhc3RUYXlsb3I7CgoJZm9yIChzaXplX3Qgcm93ID0gMDsgcm93IDwgTlVNX1JPV1M7ICsrcm93KQoJewoJICBmb3IgKHNpemVfdCBjb2wgPSAwOyBjb2wgPCBOVU1fQ09MVU1OUyAtIDE7ICsrY29sKQoJICAgIHsgLy8gbGFzdCBjb2x1bW4gaXMgbm90IGVuY29kZWQKCSAgICBUYXlsb3IgdGF5bG9yKG15X2FycmF5W3Jvd11bY29sXSwgbGFzdFRheWxvcik7CgkgICAgaW50MTZfdCBmaXh1cCA9IHRheWxvci5kWzBdIC0gbGFzdFRheWxvci5wcmVkaWN0KCk7CgoJICAgIC8vIEhhY2sgZm9yIHZhbHVlcywganVtcGluZyBmcm9tIC0xMDAgdG8gMTAwCgkgICAgaWYgKHRheWxvci5kWzBdID49IFZBTFVFX0xJTUlUX1BPUyAmJiBsYXN0VGF5bG9yLmRbMF0gPCAwKQoJICAgICAgZml4dXAgLT0gMiAqIHRheWxvci5kWzBdOwoKCSAgICAvLyBWYWx1ZSB0b28gYmlnIGZvciBhcml0aG1ldGljIGNvZGVjLCB1c2UgbmliYmxlcwoJICAgIGlmIChmaXh1cCA+IElOREVYX1BMVVMgKyBOVU1fQklOX09VVExJRVJTIHx8CgkJZml4dXAgPCAtWkVST19QT1MgLSBOVU1fQklOX09VVExJRVJTKQoJICAgIHsKCSAgICAgICsrYmluYXJ5MTI7CgkgICAgfQoJICAgIGVsc2UgaWYgKGZpeHVwID4gSU5ERVhfUExVUyB8fCBmaXh1cCA8IC1aRVJPX1BPUykKCSAgICB7CgkgICAgICArK2JpbmFyeTQ7CgkgICAgfQoKCSAgICAvLyBIYWNrIGZvciB2YWx1ZXMsIGp1bXBpbmcgZnJvbSAtMTAwIHRvIDEwMAoJICAgIGlmICh0YXlsb3IuZFswXSA+PSBWQUxVRV9MSU1JVF9QT1MgJiYgbGFzdFRheWxvci5kWzBdIDwgMCkKCSAgICB7CgkgICAgICBsYXN0VGF5bG9yLm5lZ2F0ZSgpOwoJICAgICAgdGF5bG9yLnVwZGF0ZShsYXN0VGF5bG9yKTsKCSAgICB9CgoJICAgIC8vIFRoaXMgd2lsbCBiZSB1c2VkIHRvIHByZWRpY3QgdGhlIG5leHQgdmFsdWUKCSAgICAvLyAoZGVyaXZhdGl2ZSBpcyBub3QgdXBkYXRlZCBmb3IgdGhlIGZpcnN0IGNvbHVtbikKCSAgICBsYXN0VGF5bG9yLmNvcHlGcm9tKHRheWxvciwgY29sPyAzOiAxKTsKCgkgICAgLy8gVXBkYXRlIHRhYmxlIG9mIGZyZXF1ZW5jaWVzCgkgICAgKytmcmVxWzUxMiArIGZpeHVwXTsKCSAgfQoJfQoKCWNvdXQgPDwgImZpeHVwOiAiOwoJb3N0cmVhbV9pdGVyYXRvcjxpbnQ+IG91dF9pdCAoY291dCwgIiAiKTsKCXN0ZDo6Y29weShmcmVxLmJlZ2luKCkrNDgwLCBmcmVxLmVuZCgpLTQ4MCwgb3V0X2l0KTsKCWNvdXQgPDwgIlxuIjsKCWNvdXQgPDwgImJpbmFyeTQ9IiA8PCBiaW5hcnk0IDw8ICJcbiI7Cgljb3V0IDw8ICJiaW5hcnkxMj0iIDw8IGJpbmFyeTEyIDw8ICJcbiI7Cgljb3V0IDw8ICItLS0tLS0tLS0tLVxuIjsKCglkb3VibGUgYml0c1BlclZhbHVlID0KCSAgYWNjdW11bGF0ZShmcmVxLmJlZ2luKCksIGZyZXEuZW5kKCksIDAuLCBFbnRyb3B5KDApKTsKCgljb3V0CgkgIDw8ICIgRW50cm9weT0iIDw8IE5VTV9WQUxVRVMgKiBiaXRzUGVyVmFsdWUgLyA4LgoJICA8PCAiIGJpdHM9IiA8PCBiaXRzUGVyVmFsdWUgPDwgIlxuIjsKCglFbnRyb3B5IGVudHJvcHkoYmluYXJ5NCArIGJpbmFyeTEyKTsKCgljb3V0IDw8ICJTdGF0aWM9IgoJICAgICA8PCAyICogKElOREVYX0ZVTExfU0laRSArCgkJICAgICAoMiArIGJpbmFyeTQgKyBiaW5hcnkxMiozICsgMykgLyA0KQoJICAgICA8PCAiXG4iOwoKCS8vIEFkZCBuaWJibGUgZnJlcXVlbmNpZXMKCWZyZXFbNTEyIC0gWkVST19QT1MgKyBJTkRFWF9TSVpFXSA9IGJpbmFyeTQ7CglmcmVxWzUxMiAtIFpFUk9fUE9TICsgSU5ERVhfU0laRSArIDFdID0gYmluYXJ5MTI7CgoJYml0c1BlclZhbHVlID0KCSAgYWNjdW11bGF0ZShmcmVxLmJlZ2luKCkgKyA1MTIgLSBaRVJPX1BPUywKCQkgICAgIGZyZXEuYmVnaW4oKSArIDUxMiAtIFpFUk9fUE9TICsgSU5ERVhfRlVMTF9TSVpFLAoJCSAgICAgMC4sIGVudHJvcHkpOwoJY291dAoJICA8PCAiRW50cm9weTI9IiA8PCBOVU1fVkFMVUVTICogYml0c1BlclZhbHVlIC8gOC4KCSAgPDwgIiBiaXRzPSIgPDwgYml0c1BlclZhbHVlIDw8ICJcbiI7CgoJLy8gUGFzcyAyOiBlbmNvZGUgYXJpdGhtZXRpYyBjb2RlciBiaXRzdHJlYW0gJiBuaWJibGVzCgl2ZWN0b3I8dWludDE2X3Q+IGNvbXBhY3RlZCgxMDI0KTsKCgkvLyBDdW11bGF0aXZlIHN1bSBvZiBmcmVxdWVuY2llcwoJcGFydGlhbF9zdW0oZnJlcS5iZWdpbigpICsgNTEyIC0gWkVST19QT1MsCgkgICAgIGZyZXEuYmVnaW4oKSArIDUxMiAtIFpFUk9fUE9TICsgSU5ERVhfRlVMTF9TSVpFLAoJICAgICBjb21wYWN0ZWQuYmVnaW4oKSArIDEpOwoKCS8vIENvbmZpZ3VyZSBuaWJibGUgd3JpdGVyCgl1aW50MTZfdCogcE5pYmJsZXMgPSAmY29tcGFjdGVkW0lOREVYX0ZVTExfU0laRSArIDFdOwoJdWludDE2X3QgbmliYmxlcyA9ICgzICsgYmluYXJ5NCArIGJpbmFyeTEyKjMgKyAzKSAvIDQ7CglOaWJibGVXcml0ZXIgbmliYmxlV3JpdGVyKHBOaWJibGVzLCBuaWJibGVzKTsKCXVpbnQxNl90KiBwRGF0YSA9IHBOaWJibGVzICsgbmliYmxlczsKCgkvLyBDb25maWd1cmUgYXJpdGhtZXRpYyBjb2RlcgoJQXJXcml0ZXIgYXJXcml0ZXIocERhdGEsCgkJCSAgJmNvbXBhY3RlZFsxXSwKCQkJICAmY29tcGFjdGVkWzEgKyBJTkRFWF9GVUxMX1NJWkVdKTsKCglsYXN0VGF5bG9yLmNsZWFyKCk7CgoJZm9yIChzaXplX3Qgcm93ID0gMDsgcm93IDwgTlVNX1JPV1M7ICsrcm93KQoJewoJICBmb3IgKHNpemVfdCBjb2wgPSAwOyBjb2wgPCBOVU1fQ09MVU1OUyAtIDE7ICsrY29sKQoJICB7IC8vIGxhc3QgY29sdW1uIGlzIG5vdCBlbmNvZGVkCgkgICAgVGF5bG9yIHRheWxvcihteV9hcnJheVtyb3ddW2NvbF0sIGxhc3RUYXlsb3IpOwoJICAgIGludDE2X3QgZml4dXAgPSB0YXlsb3IuZFswXSAtIGxhc3RUYXlsb3IucHJlZGljdCgpOwoKCSAgICAvLyBIYWNrIGZvciB2YWx1ZXMsIGp1bXBpbmcgZnJvbSAtMTAwIHRvIDEwMAoJICAgIGlmICh0YXlsb3IuZFswXSA+PSBWQUxVRV9MSU1JVF9QT1MgJiYgbGFzdFRheWxvci5kWzBdIDwgMCkKCSAgICAgIGZpeHVwIC09IDIgKiB0YXlsb3IuZFswXTsKCgkgICAgLy8gVmFsdWUgdG9vIGJpZyBmb3IgYXJpdGhtZXRpYyBjb2RlYywgdXNlIG5pYmJsZXMKCSAgICBpZiAoZml4dXAgPiBJTkRFWF9QTFVTICsgTlVNX0JJTl9PVVRMSUVSUyB8fAoJCWZpeHVwIDwgLVpFUk9fUE9TIC0gTlVNX0JJTl9PVVRMSUVSUykKCSAgICB7CgkgICAgICBuaWJibGVXcml0ZXIud3JpdGUxMihmaXh1cCk7CgkgICAgICBhcldyaXRlci53cml0ZShJTkRFWF9TSVpFICsgQklOMTIpOwoJICAgIH0KCSAgICBlbHNlIGlmIChmaXh1cCA+IElOREVYX1BMVVMgfHwgZml4dXAgPCAtWkVST19QT1MpCgkgICAgewoJICAgICAgaWYgKGZpeHVwID4gMCkKCQluaWJibGVXcml0ZXIud3JpdGU0KGZpeHVwIC0gSU5ERVhfUExVUyAtIDEpOwoJICAgICAgZWxzZQoJCW5pYmJsZVdyaXRlci53cml0ZTQoKC1maXh1cCAtIFpFUk9fUE9TIC0gMSkgfCAweDgpOwoKCSAgICAgIGFyV3JpdGVyLndyaXRlKElOREVYX1NJWkUgKyBCSU40KTsKCSAgICB9CgkgICAgZWxzZQoJICAgIHsKCSAgICAgIGFyV3JpdGVyLndyaXRlKFpFUk9fUE9TICsgZml4dXApOwoJICAgIH0KCgkgICAgLy8gSGFjayBmb3IgdmFsdWVzLCBqdW1waW5nIGZyb20gLTEwMCB0byAxMDAKCSAgICBpZiAodGF5bG9yLmRbMF0gPj0gVkFMVUVfTElNSVRfUE9TICYmIGxhc3RUYXlsb3IuZFswXSA8IDApCgkgICAgewoJICAgICAgbGFzdFRheWxvci5uZWdhdGUoKTsKCSAgICAgIHRheWxvci51cGRhdGUobGFzdFRheWxvcik7CgkgICAgfQoKCSAgICAvLyBUaGlzIHdpbGwgYmUgdXNlZCB0byBwcmVkaWN0IHRoZSBuZXh0IHZhbHVlCgkgICAgLy8gKGRlcml2YXRpdmUgaXMgbm90IHVwZGF0ZWQgZm9yIHRoZSBmaXJzdCBjb2x1bW4pCgkgICAgbGFzdFRheWxvci5jb3B5RnJvbSh0YXlsb3IsIGNvbD8gMzogMSk7CgkgIH0KCX0KCgluaWJibGVXcml0ZXIuZmx1c2goKTsKCWFyV3JpdGVyLmZsdXNoKCk7CgoJc2l6ZV90IHNpemUgPSBhcldyaXRlci5nZXRTdHJlYW1Qb3MoKSAtICZjb21wYWN0ZWRbMF07CgoJY291dAoJICA8PCAiQXJFbmM9IgoJICA8PCAoYXJXcml0ZXIuZ2V0U3RyZWFtUG9zKCkgLSBwTmliYmxlcyAtIG5pYmJsZXMpICogMgoJICA8PCAiXG5Ub3RhbD0iIDw8IHNpemUgKiAyIDw8ICJcbi0tLS0tLS0tLVxuIjsKCglmb3IgKHNpemVfdCBpID0gMDsgaSA8IHNpemU7IGkgKz0gOCkKCXsKCSAgY291dCA8PCAiICAgICIgPDwgaGV4IDw8IHNob3diYXNlOwoJICBvc3RyZWFtX2l0ZXJhdG9yPGludD4gb3V0X2l0IChjb3V0LCAiLCAiKTsKCgkgIHN0ZDo6Y29weShjb21wYWN0ZWQuYmVnaW4oKSArIGksCgkJICAgIChpICsgOCA8IHNpemUpPwoJCSAgICBjb21wYWN0ZWQuYmVnaW4oKSArIGkgKyA4OiBjb21wYWN0ZWQuYmVnaW4oKSArIHNpemUsCgkJICAgIG91dF9pdCk7CgoJICBjb3V0IDw8ICJcbiI7Cgl9CiAgICAgIH0KCiAgICAgIGludCBtYWluKCkKICAgICAgewoJZW5jb2RlcigpOwoJcmV0dXJuIDA7CiAgICAgIH0K