importPackage(java.io);
importPackage(java.lang);
// +----------------------------------------------------------------------+
// | murmurHash3.js v2.1.2 (http://g...content-available-to-author-only...b.com/karanlyons/murmurHash.js) |
// | A javascript implementation of MurmurHash3's x86 hashing algorithms. |
// |----------------------------------------------------------------------|
// | Copyright (c) 2012 Karan Lyons |
// | Freely distributable under the MIT license. |
// +----------------------------------------------------------------------+
;(function (root, undefined) {
'use strict';
// Create a local object that'll be exported or referenced globally.
var library = {
'version': '2.1.2',
'x86': {},
'x64': {}
};
// PRIVATE FUNCTIONS
// -----------------
function _x86Multiply(m, n) {
//
// Given two 32bit ints, returns the two multiplied together as a
// 32bit int.
//
return ((m & 0xffff) * n) + ((((m >>> 16) * n) & 0xffff) << 16);
}
function _x86Rotl(m, n) {
//
// Given a 32bit int and an int representing a number of bit positions,
// returns the 32bit int rotated left by that number of positions.
//
return (m << n) | (m >>> (32 - n));
}
function _x86Fmix(h) {
//
// Given a block, returns murmurHash3's final x86 mix of that block.
//
h ^= h >>> 16;
h = _x86Multiply(h, 0x85ebca6b);
h ^= h >>> 13;
h = _x86Multiply(h, 0xc2b2ae35);
h ^= h >>> 16;
return h;
}
function _x64Add(m, n) {
//
// Given two 64bit ints (as an array of two 32bit ints) returns the two
// added together as a 64bit int (as an array of two 32bit ints).
//
m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
var o = [0, 0, 0, 0];
o[3] += m[3] + n[3];
o[2] += o[3] >>> 16;
o[3] &= 0xffff;
o[2] += m[2] + n[2];
o[1] += o[2] >>> 16;
o[2] &= 0xffff;
o[1] += m[1] + n[1];
o[0] += o[1] >>> 16;
o[1] &= 0xffff;
o[0] += m[0] + n[0];
o[0] &= 0xffff;
return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
}
function _x64Multiply(m, n) {
//
// Given two 64bit ints (as an array of two 32bit ints) returns the two
// multiplied together as a 64bit int (as an array of two 32bit ints).
//
m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
var o = [0, 0, 0, 0];
o[3] += m[3] * n[3];
o[2] += o[3] >>> 16;
o[3] &= 0xffff;
o[2] += m[2] * n[3];
o[1] += o[2] >>> 16;
o[2] &= 0xffff;
o[2] += m[3] * n[2];
o[1] += o[2] >>> 16;
o[2] &= 0xffff;
o[1] += m[1] * n[3];
o[0] += o[1] >>> 16;
o[1] &= 0xffff;
o[1] += m[2] * n[2];
o[0] += o[1] >>> 16;
o[1] &= 0xffff;
o[1] += m[3] * n[1];
o[0] += o[1] >>> 16;
o[1] &= 0xffff;
o[0] += (m[0] * n[3]) + (m[1] * n[2]) + (m[2] * n[1]) + (m[3] * n[0]);
o[0] &= 0xffff;
return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
}
function _x64Rotl(m, n) {
//
// Given a 64bit int (as an array of two 32bit ints) and an int
// representing a number of bit positions, returns the 64bit int (as an
// array of two 32bit ints) rotated left by that number of positions.
//
n %= 64;
if (n === 32) {
return [m[1], m[0]];
}
else if (n < 32) {
return [(m[0] << n) | (m[1] >>> (32 - n)), (m[1] << n) | (m[0] >>> (32 - n))];
}
else {
n -= 32;
return [(m[1] << n) | (m[0] >>> (32 - n)), (m[0] << n) | (m[1] >>> (32 - n))];
}
}
function _x64LeftShift(m, n) {
//
// Given a 64bit int (as an array of two 32bit ints) and an int
// representing a number of bit positions, returns the 64bit int (as an
// array of two 32bit ints) shifted left by that number of positions.
//
n %= 64;
if (n === 0) {
return m;
}
else if (n < 32) {
return [(m[0] << n) | (m[1] >>> (32 - n)), m[1] << n];
}
else {
return [m[1] << (n - 32), 0];
}
}
function _x64Xor(m, n) {
//
// Given two 64bit ints (as an array of two 32bit ints) returns the two
// xored together as a 64bit int (as an array of two 32bit ints).
//
return [m[0] ^ n[0], m[1] ^ n[1]];
}
function _x64Fmix(h) {
//
// Given a block, returns murmurHash3's final x64 mix of that block.
// (`[0, h[0] >>> 1]` is a 33 bit unsigned right shift. This is the
// only place where we need to right shift 64bit ints.)
//
h = _x64Xor(h, [0, h[0] >>> 1]);
h = _x64Multiply(h, [0xff51afd7, 0xed558ccd]);
h = _x64Xor(h, [0, h[0] >>> 1]);
h = _x64Multiply(h, [0xc4ceb9fe, 0x1a85ec53]);
h = _x64Xor(h, [0, h[0] >>> 1]);
return h;
}
// PUBLIC FUNCTIONS
// ----------------
library.x86.hash32 = function (key, seed) {
//
// Given a string and an optional seed as an int, returns a 32 bit hash
// using the x86 flavor of MurmurHash3, as an unsigned int.
//
key = key || '';
seed = seed || 0;
var remainder = key.length % 4;
var bytes = key.length - remainder;
var h1 = seed;
var k1 = 0;
var c1 = 0xcc9e2d51;
var c2 = 0x1b873593;
for (var i = 0; i < bytes; i = i + 4) {
k1 = ((key.charCodeAt(i) & 0xff)) | ((key.charCodeAt(i + 1) & 0xff) << 8) | ((key.charCodeAt(i + 2) & 0xff) << 16) | ((key.charCodeAt(i + 3) & 0xff) << 24);
k1 = _x86Multiply(k1, c1);
k1 = _x86Rotl(k1, 15);
k1 = _x86Multiply(k1, c2);
h1 ^= k1;
h1 = _x86Rotl(h1, 13);
h1 = _x86Multiply(h1, 5) + 0xe6546b64;
}
k1 = 0;
switch (remainder) {
case 3:
k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
case 2:
k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
case 1:
k1 ^= (key.charCodeAt(i) & 0xff);
k1 = _x86Multiply(k1, c1);
k1 = _x86Rotl(k1, 15);
k1 = _x86Multiply(k1, c2);
h1 ^= k1;
}
h1 ^= key.length;
h1 = _x86Fmix(h1);
return h1 >>> 0;
};
library.x86.hash128 = function (key, seed) {
//
// Given a string and an optional seed as an int, returns a 128 bit
// hash using the x86 flavor of MurmurHash3, as an unsigned hex.
//
key = key || '';
seed = seed || 0;
var remainder = key.length % 16;
var bytes = key.length - remainder;
var h1 = seed;
var h2 = seed;
var h3 = seed;
var h4 = seed;
var k1 = 0;
var k2 = 0;
var k3 = 0;
var k4 = 0;
var c1 = 0x239b961b;
var c2 = 0xab0e9789;
var c3 = 0x38b34ae5;
var c4 = 0xa1e38b93;
for (var i = 0; i < bytes; i = i + 16) {
k1 = ((key.charCodeAt(i) & 0xff)) | ((key.charCodeAt(i + 1) & 0xff) << 8) | ((key.charCodeAt(i + 2) & 0xff) << 16) | ((key.charCodeAt(i + 3) & 0xff) << 24);
k2 = ((key.charCodeAt(i + 4) & 0xff)) | ((key.charCodeAt(i + 5) & 0xff) << 8) | ((key.charCodeAt(i + 6) & 0xff) << 16) | ((key.charCodeAt(i + 7) & 0xff) << 24);
k3 = ((key.charCodeAt(i + 8) & 0xff)) | ((key.charCodeAt(i + 9) & 0xff) << 8) | ((key.charCodeAt(i + 10) & 0xff) << 16) | ((key.charCodeAt(i + 11) & 0xff) << 24);
k4 = ((key.charCodeAt(i + 12) & 0xff)) | ((key.charCodeAt(i + 13) & 0xff) << 8) | ((key.charCodeAt(i + 14) & 0xff) << 16) | ((key.charCodeAt(i + 15) & 0xff) << 24);
k1 = _x86Multiply(k1, c1);
k1 = _x86Rotl(k1, 15);
k1 = _x86Multiply(k1, c2);
h1 ^= k1;
h1 = _x86Rotl(h1, 19);
h1 += h2;
h1 = _x86Multiply(h1, 5) + 0x561ccd1b;
k2 = _x86Multiply(k2, c2);
k2 = _x86Rotl(k2, 16);
k2 = _x86Multiply(k2, c3);
h2 ^= k2;
h2 = _x86Rotl(h2, 17);
h2 += h3;
h2 = _x86Multiply(h2, 5) + 0x0bcaa747;
k3 = _x86Multiply(k3, c3);
k3 = _x86Rotl(k3, 17);
k3 = _x86Multiply(k3, c4);
h3 ^= k3;
h3 = _x86Rotl(h3, 15);
h3 += h4;
h3 = _x86Multiply(h3, 5) + 0x96cd1c35;
k4 = _x86Multiply(k4, c4);
k4 = _x86Rotl(k4, 18);
k4 = _x86Multiply(k4, c1);
h4 ^= k4;
h4 = _x86Rotl(h4, 13);
h4 += h1;
h4 = _x86Multiply(h4, 5) + 0x32ac3b17;
}
k1 = 0;
k2 = 0;
k3 = 0;
k4 = 0;
switch (remainder) {
case 15:
k4 ^= key.charCodeAt(i + 14) << 16;
case 14:
k4 ^= key.charCodeAt(i + 13) << 8;
case 13:
k4 ^= key.charCodeAt(i + 12);
k4 = _x86Multiply(k4, c4);
k4 = _x86Rotl(k4, 18);
k4 = _x86Multiply(k4, c1);
h4 ^= k4;
case 12:
k3 ^= key.charCodeAt(i + 11) << 24;
case 11:
k3 ^= key.charCodeAt(i + 10) << 16;
case 10:
k3 ^= key.charCodeAt(i + 9) << 8;
case 9:
k3 ^= key.charCodeAt(i + 8);
k3 = _x86Multiply(k3, c3);
k3 = _x86Rotl(k3, 17);
k3 = _x86Multiply(k3, c4);
h3 ^= k3;
case 8:
k2 ^= key.charCodeAt(i + 7) << 24;
case 7:
k2 ^= key.charCodeAt(i + 6) << 16;
case 6:
k2 ^= key.charCodeAt(i + 5) << 8;
case 5:
k2 ^= key.charCodeAt(i + 4);
k2 = _x86Multiply(k2, c2);
k2 = _x86Rotl(k2, 16);
k2 = _x86Multiply(k2, c3);
h2 ^= k2;
case 4:
k1 ^= key.charCodeAt(i + 3) << 24;
case 3:
k1 ^= key.charCodeAt(i + 2) << 16;
case 2:
k1 ^= key.charCodeAt(i + 1) << 8;
case 1:
k1 ^= key.charCodeAt(i);
k1 = _x86Multiply(k1, c1);
k1 = _x86Rotl(k1, 15);
k1 = _x86Multiply(k1, c2);
h1 ^= k1;
}
h1 ^= key.length;
h2 ^= key.length;
h3 ^= key.length;
h4 ^= key.length;
h1 += h2;
h1 += h3;
h1 += h4;
h2 += h1;
h3 += h1;
h4 += h1;
h1 = _x86Fmix(h1);
h2 = _x86Fmix(h2);
h3 = _x86Fmix(h3);
h4 = _x86Fmix(h4);
h1 += h2;
h1 += h3;
h1 += h4;
h2 += h1;
h3 += h1;
h4 += h1;
return ("00000000" + (h1 >>> 0).toString(16)).slice(-8) + ("00000000" + (h2 >>> 0).toString(16)).slice(-8) + ("00000000" + (h3 >>> 0).toString(16)).slice(-8) + ("00000000" + (h4 >>> 0).toString(16)).slice(-8);
};
library.x64.hash128 = function (key, seed) {
//
// Given a string and an optional seed as an int, returns a 128 bit
// hash using the x64 flavor of MurmurHash3, as an unsigned hex.
//
key = key || '';
seed = seed || 0;
var remainder = key.length % 16;
var bytes = key.length - remainder;
var h1 = [0, seed];
var h2 = [0, seed];
var k1 = [0, 0];
var k2 = [0, 0];
var c1 = [0x87c37b91, 0x114253d5];
var c2 = [0x4cf5ad43, 0x2745937f];
for (var i = 0; i < bytes; i = i + 16) {
k1 = [((key.charCodeAt(i + 4) & 0xff)) | ((key.charCodeAt(i + 5) & 0xff) << 8) | ((key.charCodeAt(i + 6) & 0xff) << 16) | ((key.charCodeAt(i + 7) & 0xff) << 24), ((key.charCodeAt(i) & 0xff)) | ((key.charCodeAt(i + 1) & 0xff) << 8) | ((key.charCodeAt(i + 2) & 0xff) << 16) | ((key.charCodeAt(i + 3) & 0xff) << 24)];
k2 = [((key.charCodeAt(i + 12) & 0xff)) | ((key.charCodeAt(i + 13) & 0xff) << 8) | ((key.charCodeAt(i + 14) & 0xff) << 16) | ((key.charCodeAt(i + 15) & 0xff) << 24), ((key.charCodeAt(i + 8) & 0xff)) | ((key.charCodeAt(i + 9) & 0xff) << 8) | ((key.charCodeAt(i + 10) & 0xff) << 16) | ((key.charCodeAt(i + 11) & 0xff) << 24)];
k1 = _x64Multiply(k1, c1);
k1 = _x64Rotl(k1, 31);
k1 = _x64Multiply(k1, c2);
h1 = _x64Xor(h1, k1);
h1 = _x64Rotl(h1, 27);
h1 = _x64Add(h1, h2);
h1 = _x64Add(_x64Multiply(h1, [0, 5]), [0, 0x52dce729]);
k2 = _x64Multiply(k2, c2);
k2 = _x64Rotl(k2, 33);
k2 = _x64Multiply(k2, c1);
h2 = _x64Xor(h2, k2);
h2 = _x64Rotl(h2, 31);
h2 = _x64Add(h2, h1);
h2 = _x64Add(_x64Multiply(h2, [0, 5]), [0, 0x38495ab5]);
}
k1 = [0, 0];
k2 = [0, 0];
switch(remainder) {
case 15:
k2 = _x64Xor(k2, _x64LeftShift([0, key.charCodeAt(i + 14)], 48));
case 14:
k2 = _x64Xor(k2, _x64LeftShift([0, key.charCodeAt(i + 13)], 40));
case 13:
k2 = _x64Xor(k2, _x64LeftShift([0, key.charCodeAt(i + 12)], 32));
case 12:
k2 = _x64Xor(k2, _x64LeftShift([0, key.charCodeAt(i + 11)], 24));
case 11:
k2 = _x64Xor(k2, _x64LeftShift([0, key.charCodeAt(i + 10)], 16));
case 10:
k2 = _x64Xor(k2, _x64LeftShift([0, key.charCodeAt(i + 9)], 8));
case 9:
k2 = _x64Xor(k2, [0, key.charCodeAt(i + 8)]);
k2 = _x64Multiply(k2, c2);
k2 = _x64Rotl(k2, 33);
k2 = _x64Multiply(k2, c1);
h2 = _x64Xor(h2, k2);
case 8:
k1 = _x64Xor(k1, _x64LeftShift([0, key.charCodeAt(i + 7)], 56));
case 7:
k1 = _x64Xor(k1, _x64LeftShift([0, key.charCodeAt(i + 6)], 48));
case 6:
k1 = _x64Xor(k1, _x64LeftShift([0, key.charCodeAt(i + 5)], 40));
case 5:
k1 = _x64Xor(k1, _x64LeftShift([0, key.charCodeAt(i + 4)], 32));
case 4:
k1 = _x64Xor(k1, _x64LeftShift([0, key.charCodeAt(i + 3)], 24));
case 3:
k1 = _x64Xor(k1, _x64LeftShift([0, key.charCodeAt(i + 2)], 16));
case 2:
k1 = _x64Xor(k1, _x64LeftShift([0, key.charCodeAt(i + 1)], 8));
case 1:
k1 = _x64Xor(k1, [0, key.charCodeAt(i)]);
k1 = _x64Multiply(k1, c1);
k1 = _x64Rotl(k1, 31);
k1 = _x64Multiply(k1, c2);
h1 = _x64Xor(h1, k1);
}
h1 = _x64Xor(h1, [0, key.length]);
h2 = _x64Xor(h2, [0, key.length]);
h1 = _x64Add(h1, h2);
h2 = _x64Add(h2, h1);
h1 = _x64Fmix(h1);
h2 = _x64Fmix(h2);
h1 = _x64Add(h1, h2);
h2 = _x64Add(h2, h1);
return ("00000000" + (h1[0] >>> 0).toString(16)).slice(-8) + ("00000000" + (h1[1] >>> 0).toString(16)).slice(-8) + ("00000000" + (h2[0] >>> 0).toString(16)).slice(-8) + ("00000000" + (h2[1] >>> 0).toString(16)).slice(-8);
};
// INITIALIZATION
// --------------
// Export murmurHash3 for CommonJS, either as an AMD module or just as part
// of the global object.
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = library;
}
exports.murmurHash3 = library;
}
else if (typeof define === 'function' && define.amd) {
define([], function() {
return library;
});
}
else {
// Use murmurHash3.noConflict to restore `murmurHash3` back to its
// original value. Returns a reference to the library object, to allow
// it to be used under a different name.
library._murmurHash3 = root.murmurHash3
library.noConflict = function () {
root.murmurHash3 = library._murmurHash3;
library._murmurHash3 = undefined;
library.noConflict = undefined;
return library;
};
root.murmurHash3 = library;
}
})(this);
aW1wb3J0UGFja2FnZShqYXZhLmlvKTsKaW1wb3J0UGFja2FnZShqYXZhLmxhbmcpOwoKLy8gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rCi8vIHwgbXVybXVySGFzaDMuanMgdjIuMS4yIChodHRwOi8vZy4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4uYi5jb20va2FyYW5seW9ucy9tdXJtdXJIYXNoLmpzKSAgIHwKLy8gfCBBIGphdmFzY3JpcHQgaW1wbGVtZW50YXRpb24gb2YgTXVybXVySGFzaDMncyB4ODYgaGFzaGluZyBhbGdvcml0aG1zLiB8Ci8vIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAovLyB8IENvcHlyaWdodCAoYykgMjAxMiBLYXJhbiBMeW9ucyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKLy8gfCBGcmVlbHkgZGlzdHJpYnV0YWJsZSB1bmRlciB0aGUgTUlUIGxpY2Vuc2UuICAgICAgICAgICAgICAgICAgICAgICAgICB8Ci8vICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKwoKCjsoZnVuY3Rpb24gKHJvb3QsIHVuZGVmaW5lZCkgewoJJ3VzZSBzdHJpY3QnOwoJCgkvLyBDcmVhdGUgYSBsb2NhbCBvYmplY3QgdGhhdCdsbCBiZSBleHBvcnRlZCBvciByZWZlcmVuY2VkIGdsb2JhbGx5LgoJdmFyIGxpYnJhcnkgPSB7CgkJJ3ZlcnNpb24nOiAnMi4xLjInLAoJCSd4ODYnOiB7fSwKCQkneDY0Jzoge30KCX07CgkKCQoJCgkKCS8vIFBSSVZBVEUgRlVOQ1RJT05TCgkvLyAtLS0tLS0tLS0tLS0tLS0tLQoJCglmdW5jdGlvbiBfeDg2TXVsdGlwbHkobSwgbikgewoJCS8vCgkJLy8gR2l2ZW4gdHdvIDMyYml0IGludHMsIHJldHVybnMgdGhlIHR3byBtdWx0aXBsaWVkIHRvZ2V0aGVyIGFzIGEKCQkvLyAzMmJpdCBpbnQuCgkJLy8KCQkKCQlyZXR1cm4gKChtICYgMHhmZmZmKSAqIG4pICsgKCgoKG0gPj4+IDE2KSAqIG4pICYgMHhmZmZmKSA8PCAxNik7Cgl9CgkKCQoJZnVuY3Rpb24gX3g4NlJvdGwobSwgbikgewoJCS8vCgkJLy8gR2l2ZW4gYSAzMmJpdCBpbnQgYW5kIGFuIGludCByZXByZXNlbnRpbmcgYSBudW1iZXIgb2YgYml0IHBvc2l0aW9ucywKCQkvLyByZXR1cm5zIHRoZSAzMmJpdCBpbnQgcm90YXRlZCBsZWZ0IGJ5IHRoYXQgbnVtYmVyIG9mIHBvc2l0aW9ucy4KCQkvLwoJCQoJCXJldHVybiAobSA8PCBuKSB8IChtID4+PiAoMzIgLSBuKSk7Cgl9CgkKCQoJZnVuY3Rpb24gX3g4NkZtaXgoaCkgewoJCS8vCgkJLy8gR2l2ZW4gYSBibG9jaywgcmV0dXJucyBtdXJtdXJIYXNoMydzIGZpbmFsIHg4NiBtaXggb2YgdGhhdCBibG9jay4KCQkvLwoJCQoJCWggXj0gaCA+Pj4gMTY7CgkJaCAgPSBfeDg2TXVsdGlwbHkoaCwgMHg4NWViY2E2Yik7CgkJaCBePSBoID4+PiAxMzsKCQloICA9IF94ODZNdWx0aXBseShoLCAweGMyYjJhZTM1KTsKCQloIF49IGggPj4+IDE2OwoJCQoJCXJldHVybiBoOwoJfQoJCgkKCWZ1bmN0aW9uIF94NjRBZGQobSwgbikgewoJCS8vCgkJLy8gR2l2ZW4gdHdvIDY0Yml0IGludHMgKGFzIGFuIGFycmF5IG9mIHR3byAzMmJpdCBpbnRzKSByZXR1cm5zIHRoZSB0d28KCQkvLyBhZGRlZCB0b2dldGhlciBhcyBhIDY0Yml0IGludCAoYXMgYW4gYXJyYXkgb2YgdHdvIDMyYml0IGludHMpLgoJCS8vCgkJCgkJbSA9IFttWzBdID4+PiAxNiwgbVswXSAmIDB4ZmZmZiwgbVsxXSA+Pj4gMTYsIG1bMV0gJiAweGZmZmZdOwoJCW4gPSBbblswXSA+Pj4gMTYsIG5bMF0gJiAweGZmZmYsIG5bMV0gPj4+IDE2LCBuWzFdICYgMHhmZmZmXTsKCQl2YXIgbyA9IFswLCAwLCAwLCAwXTsKCQkKCQlvWzNdICs9IG1bM10gKyBuWzNdOwoJCW9bMl0gKz0gb1szXSA+Pj4gMTY7CgkJb1szXSAmPSAweGZmZmY7CgkJCgkJb1syXSArPSBtWzJdICsgblsyXTsKCQlvWzFdICs9IG9bMl0gPj4+IDE2OwoJCW9bMl0gJj0gMHhmZmZmOwoJCQoJCW9bMV0gKz0gbVsxXSArIG5bMV07CgkJb1swXSArPSBvWzFdID4+PiAxNjsKCQlvWzFdICY9IDB4ZmZmZjsKCQkKCQlvWzBdICs9IG1bMF0gKyBuWzBdOwoJCW9bMF0gJj0gMHhmZmZmOwoJCQoJCXJldHVybiBbKG9bMF0gPDwgMTYpIHwgb1sxXSwgKG9bMl0gPDwgMTYpIHwgb1szXV07Cgl9CgkKCQoJZnVuY3Rpb24gX3g2NE11bHRpcGx5KG0sIG4pIHsKCQkvLwoJCS8vIEdpdmVuIHR3byA2NGJpdCBpbnRzIChhcyBhbiBhcnJheSBvZiB0d28gMzJiaXQgaW50cykgcmV0dXJucyB0aGUgdHdvCgkJLy8gbXVsdGlwbGllZCB0b2dldGhlciBhcyBhIDY0Yml0IGludCAoYXMgYW4gYXJyYXkgb2YgdHdvIDMyYml0IGludHMpLgoJCS8vCgkJCgkJbSA9IFttWzBdID4+PiAxNiwgbVswXSAmIDB4ZmZmZiwgbVsxXSA+Pj4gMTYsIG1bMV0gJiAweGZmZmZdOwoJCW4gPSBbblswXSA+Pj4gMTYsIG5bMF0gJiAweGZmZmYsIG5bMV0gPj4+IDE2LCBuWzFdICYgMHhmZmZmXTsKCQl2YXIgbyA9IFswLCAwLCAwLCAwXTsKCQkKCQlvWzNdICs9IG1bM10gKiBuWzNdOwoJCW9bMl0gKz0gb1szXSA+Pj4gMTY7CgkJb1szXSAmPSAweGZmZmY7CgkJCgkJb1syXSArPSBtWzJdICogblszXTsKCQlvWzFdICs9IG9bMl0gPj4+IDE2OwoJCW9bMl0gJj0gMHhmZmZmOwoJCQoJCW9bMl0gKz0gbVszXSAqIG5bMl07CgkJb1sxXSArPSBvWzJdID4+PiAxNjsKCQlvWzJdICY9IDB4ZmZmZjsKCQkKCQlvWzFdICs9IG1bMV0gKiBuWzNdOwoJCW9bMF0gKz0gb1sxXSA+Pj4gMTY7CgkJb1sxXSAmPSAweGZmZmY7CgkJCgkJb1sxXSArPSBtWzJdICogblsyXTsKCQlvWzBdICs9IG9bMV0gPj4+IDE2OwoJCW9bMV0gJj0gMHhmZmZmOwoJCQoJCW9bMV0gKz0gbVszXSAqIG5bMV07CgkJb1swXSArPSBvWzFdID4+PiAxNjsKCQlvWzFdICY9IDB4ZmZmZjsKCQkKCQlvWzBdICs9IChtWzBdICogblszXSkgKyAobVsxXSAqIG5bMl0pICsgKG1bMl0gKiBuWzFdKSArIChtWzNdICogblswXSk7CgkJb1swXSAmPSAweGZmZmY7CgkJCgkJcmV0dXJuIFsob1swXSA8PCAxNikgfCBvWzFdLCAob1syXSA8PCAxNikgfCBvWzNdXTsKCX0KCQoJCglmdW5jdGlvbiBfeDY0Um90bChtLCBuKSB7CgkJLy8KCQkvLyBHaXZlbiBhIDY0Yml0IGludCAoYXMgYW4gYXJyYXkgb2YgdHdvIDMyYml0IGludHMpIGFuZCBhbiBpbnQKCQkvLyByZXByZXNlbnRpbmcgYSBudW1iZXIgb2YgYml0IHBvc2l0aW9ucywgcmV0dXJucyB0aGUgNjRiaXQgaW50IChhcyBhbgoJCS8vIGFycmF5IG9mIHR3byAzMmJpdCBpbnRzKSByb3RhdGVkIGxlZnQgYnkgdGhhdCBudW1iZXIgb2YgcG9zaXRpb25zLgoJCS8vCgkJCgkJbiAlPSA2NDsKCQkKCQlpZiAobiA9PT0gMzIpIHsKCQkJcmV0dXJuIFttWzFdLCBtWzBdXTsKCQl9CgkJCgkJZWxzZSBpZiAobiA8IDMyKSB7CgkJCXJldHVybiBbKG1bMF0gPDwgbikgfCAobVsxXSA+Pj4gKDMyIC0gbikpLCAobVsxXSA8PCBuKSB8IChtWzBdID4+PiAoMzIgLSBuKSldOwoJCX0KCQkKCQllbHNlIHsKCQkJbiAtPSAzMjsKCQkJcmV0dXJuIFsobVsxXSA8PCBuKSB8IChtWzBdID4+PiAoMzIgLSBuKSksIChtWzBdIDw8IG4pIHwgKG1bMV0gPj4+ICgzMiAtIG4pKV07CgkJfQoJfQoJCgkKCWZ1bmN0aW9uIF94NjRMZWZ0U2hpZnQobSwgbikgewoJCS8vCgkJLy8gR2l2ZW4gYSA2NGJpdCBpbnQgKGFzIGFuIGFycmF5IG9mIHR3byAzMmJpdCBpbnRzKSBhbmQgYW4gaW50CgkJLy8gcmVwcmVzZW50aW5nIGEgbnVtYmVyIG9mIGJpdCBwb3NpdGlvbnMsIHJldHVybnMgdGhlIDY0Yml0IGludCAoYXMgYW4KCQkvLyBhcnJheSBvZiB0d28gMzJiaXQgaW50cykgc2hpZnRlZCBsZWZ0IGJ5IHRoYXQgbnVtYmVyIG9mIHBvc2l0aW9ucy4KCQkvLwoJCQoJCW4gJT0gNjQ7CgkJCgkJaWYgKG4gPT09IDApIHsKCQkJcmV0dXJuIG07CgkJfQoJCQoJCWVsc2UgaWYgKG4gPCAzMikgewoJCQlyZXR1cm4gWyhtWzBdIDw8IG4pIHwgKG1bMV0gPj4+ICgzMiAtIG4pKSwgbVsxXSA8PCBuXTsKCQl9CgkJCgkJZWxzZSB7CgkJCXJldHVybiBbbVsxXSA8PCAobiAtIDMyKSwgMF07CgkJfQoJfQoJCgkKCWZ1bmN0aW9uIF94NjRYb3IobSwgbikgewoJCS8vCgkJLy8gR2l2ZW4gdHdvIDY0Yml0IGludHMgKGFzIGFuIGFycmF5IG9mIHR3byAzMmJpdCBpbnRzKSByZXR1cm5zIHRoZSB0d28KCQkvLyB4b3JlZCB0b2dldGhlciBhcyBhIDY0Yml0IGludCAoYXMgYW4gYXJyYXkgb2YgdHdvIDMyYml0IGludHMpLgoJCS8vCgkJCgkJcmV0dXJuIFttWzBdIF4gblswXSwgbVsxXSBeIG5bMV1dOwoJfQoJCgkKCWZ1bmN0aW9uIF94NjRGbWl4KGgpIHsKCQkvLwoJCS8vIEdpdmVuIGEgYmxvY2ssIHJldHVybnMgbXVybXVySGFzaDMncyBmaW5hbCB4NjQgbWl4IG9mIHRoYXQgYmxvY2suCgkJLy8gKGBbMCwgaFswXSA+Pj4gMV1gIGlzIGEgMzMgYml0IHVuc2lnbmVkIHJpZ2h0IHNoaWZ0LiBUaGlzIGlzIHRoZQoJCS8vIG9ubHkgcGxhY2Ugd2hlcmUgd2UgbmVlZCB0byByaWdodCBzaGlmdCA2NGJpdCBpbnRzLikKCQkvLwoJCQoJCWggPSBfeDY0WG9yKGgsIFswLCBoWzBdID4+PiAxXSk7CgkJaCA9IF94NjRNdWx0aXBseShoLCBbMHhmZjUxYWZkNywgMHhlZDU1OGNjZF0pOwoJCWggPSBfeDY0WG9yKGgsIFswLCBoWzBdID4+PiAxXSk7CgkJaCA9IF94NjRNdWx0aXBseShoLCBbMHhjNGNlYjlmZSwgMHgxYTg1ZWM1M10pOwoJCWggPSBfeDY0WG9yKGgsIFswLCBoWzBdID4+PiAxXSk7CgkJCgkJcmV0dXJuIGg7Cgl9CgkKCQoJCgkKCS8vIFBVQkxJQyBGVU5DVElPTlMKCS8vIC0tLS0tLS0tLS0tLS0tLS0KCQoJbGlicmFyeS54ODYuaGFzaDMyID0gZnVuY3Rpb24gKGtleSwgc2VlZCkgewoJCS8vCgkJLy8gR2l2ZW4gYSBzdHJpbmcgYW5kIGFuIG9wdGlvbmFsIHNlZWQgYXMgYW4gaW50LCByZXR1cm5zIGEgMzIgYml0IGhhc2gKCQkvLyB1c2luZyB0aGUgeDg2IGZsYXZvciBvZiBNdXJtdXJIYXNoMywgYXMgYW4gdW5zaWduZWQgaW50LgoJCS8vCgkJCgkJa2V5ID0ga2V5IHx8ICcnOwoJCXNlZWQgPSBzZWVkIHx8IDA7CgkJCgkJdmFyIHJlbWFpbmRlciA9IGtleS5sZW5ndGggJSA0OwoJCXZhciBieXRlcyA9IGtleS5sZW5ndGggLSByZW1haW5kZXI7CgkJCgkJdmFyIGgxID0gc2VlZDsKCQkKCQl2YXIgazEgPSAwOwoJCQoJCXZhciBjMSA9IDB4Y2M5ZTJkNTE7CgkJdmFyIGMyID0gMHgxYjg3MzU5MzsKCQkKCQlmb3IgKHZhciBpID0gMDsgaSA8IGJ5dGVzOyBpID0gaSArIDQpIHsKCQkJazEgPSAoKGtleS5jaGFyQ29kZUF0KGkpICYgMHhmZikpIHwgKChrZXkuY2hhckNvZGVBdChpICsgMSkgJiAweGZmKSA8PCA4KSB8ICgoa2V5LmNoYXJDb2RlQXQoaSArIDIpICYgMHhmZikgPDwgMTYpIHwgKChrZXkuY2hhckNvZGVBdChpICsgMykgJiAweGZmKSA8PCAyNCk7CgkJCQoJCQlrMSA9IF94ODZNdWx0aXBseShrMSwgYzEpOwoJCQlrMSA9IF94ODZSb3RsKGsxLCAxNSk7CgkJCWsxID0gX3g4Nk11bHRpcGx5KGsxLCBjMik7CgkJCQoJCQloMSBePSBrMTsKCQkJaDEgPSBfeDg2Um90bChoMSwgMTMpOwoJCQloMSA9IF94ODZNdWx0aXBseShoMSwgNSkgKyAweGU2NTQ2YjY0OwoJCX0KCQkKCQlrMSA9IDA7CgkJCgkJc3dpdGNoIChyZW1haW5kZXIpIHsKCQkJY2FzZSAzOgoJCQkJazEgXj0gKGtleS5jaGFyQ29kZUF0KGkgKyAyKSAmIDB4ZmYpIDw8IDE2OwoJCQkKCQkJY2FzZSAyOgoJCQkJazEgXj0gKGtleS5jaGFyQ29kZUF0KGkgKyAxKSAmIDB4ZmYpIDw8IDg7CgkJCQoJCQljYXNlIDE6CgkJCQlrMSBePSAoa2V5LmNoYXJDb2RlQXQoaSkgJiAweGZmKTsKCQkJCWsxID0gX3g4Nk11bHRpcGx5KGsxLCBjMSk7CgkJCQlrMSA9IF94ODZSb3RsKGsxLCAxNSk7CgkJCQlrMSA9IF94ODZNdWx0aXBseShrMSwgYzIpOwoJCQkJaDEgXj0gazE7CgkJfQoJCQoJCWgxIF49IGtleS5sZW5ndGg7CgkJaDEgPSBfeDg2Rm1peChoMSk7CgkJCgkJcmV0dXJuIGgxID4+PiAwOwoJfTsKCQoJCglsaWJyYXJ5Lng4Ni5oYXNoMTI4ID0gZnVuY3Rpb24gKGtleSwgc2VlZCkgewoJCS8vCgkJLy8gR2l2ZW4gYSBzdHJpbmcgYW5kIGFuIG9wdGlvbmFsIHNlZWQgYXMgYW4gaW50LCByZXR1cm5zIGEgMTI4IGJpdAoJCS8vIGhhc2ggdXNpbmcgdGhlIHg4NiBmbGF2b3Igb2YgTXVybXVySGFzaDMsIGFzIGFuIHVuc2lnbmVkIGhleC4KCQkvLwoJCQoJCWtleSA9IGtleSB8fCAnJzsKCQlzZWVkID0gc2VlZCB8fCAwOwoJCQoJCXZhciByZW1haW5kZXIgPSBrZXkubGVuZ3RoICUgMTY7CgkJdmFyIGJ5dGVzID0ga2V5Lmxlbmd0aCAtIHJlbWFpbmRlcjsKCQkKCQl2YXIgaDEgPSBzZWVkOwoJCXZhciBoMiA9IHNlZWQ7CgkJdmFyIGgzID0gc2VlZDsKCQl2YXIgaDQgPSBzZWVkOwoJCQoJCXZhciBrMSA9IDA7CgkJdmFyIGsyID0gMDsKCQl2YXIgazMgPSAwOwoJCXZhciBrNCA9IDA7CgkJCgkJdmFyIGMxID0gMHgyMzliOTYxYjsKCQl2YXIgYzIgPSAweGFiMGU5Nzg5OwoJCXZhciBjMyA9IDB4MzhiMzRhZTU7CgkJdmFyIGM0ID0gMHhhMWUzOGI5MzsKCQkKCQlmb3IgKHZhciBpID0gMDsgaSA8IGJ5dGVzOyBpID0gaSArIDE2KSB7CgkJCWsxID0gKChrZXkuY2hhckNvZGVBdChpKSAmIDB4ZmYpKSB8ICgoa2V5LmNoYXJDb2RlQXQoaSArIDEpICYgMHhmZikgPDwgOCkgfCAoKGtleS5jaGFyQ29kZUF0KGkgKyAyKSAmIDB4ZmYpIDw8IDE2KSB8ICgoa2V5LmNoYXJDb2RlQXQoaSArIDMpICYgMHhmZikgPDwgMjQpOwoJCQlrMiA9ICgoa2V5LmNoYXJDb2RlQXQoaSArIDQpICYgMHhmZikpIHwgKChrZXkuY2hhckNvZGVBdChpICsgNSkgJiAweGZmKSA8PCA4KSB8ICgoa2V5LmNoYXJDb2RlQXQoaSArIDYpICYgMHhmZikgPDwgMTYpIHwgKChrZXkuY2hhckNvZGVBdChpICsgNykgJiAweGZmKSA8PCAyNCk7CgkJCWszID0gKChrZXkuY2hhckNvZGVBdChpICsgOCkgJiAweGZmKSkgfCAoKGtleS5jaGFyQ29kZUF0KGkgKyA5KSAmIDB4ZmYpIDw8IDgpIHwgKChrZXkuY2hhckNvZGVBdChpICsgMTApICYgMHhmZikgPDwgMTYpIHwgKChrZXkuY2hhckNvZGVBdChpICsgMTEpICYgMHhmZikgPDwgMjQpOwoJCQlrNCA9ICgoa2V5LmNoYXJDb2RlQXQoaSArIDEyKSAmIDB4ZmYpKSB8ICgoa2V5LmNoYXJDb2RlQXQoaSArIDEzKSAmIDB4ZmYpIDw8IDgpIHwgKChrZXkuY2hhckNvZGVBdChpICsgMTQpICYgMHhmZikgPDwgMTYpIHwgKChrZXkuY2hhckNvZGVBdChpICsgMTUpICYgMHhmZikgPDwgMjQpOwoJCQkKCQkJazEgPSBfeDg2TXVsdGlwbHkoazEsIGMxKTsKCQkJazEgPSBfeDg2Um90bChrMSwgMTUpOwoJCQlrMSA9IF94ODZNdWx0aXBseShrMSwgYzIpOwoJCQloMSBePSBrMTsKCQkJCgkJCWgxID0gX3g4NlJvdGwoaDEsIDE5KTsKCQkJaDEgKz0gaDI7CgkJCWgxID0gX3g4Nk11bHRpcGx5KGgxLCA1KSArIDB4NTYxY2NkMWI7CgkJCQoJCQlrMiA9IF94ODZNdWx0aXBseShrMiwgYzIpOwoJCQlrMiA9IF94ODZSb3RsKGsyLCAxNik7CgkJCWsyID0gX3g4Nk11bHRpcGx5KGsyLCBjMyk7CgkJCWgyIF49IGsyOwoJCQkKCQkJaDIgPSBfeDg2Um90bChoMiwgMTcpOwoJCQloMiArPSBoMzsKCQkJaDIgPSBfeDg2TXVsdGlwbHkoaDIsIDUpICsgMHgwYmNhYTc0NzsKCQkJCgkJCWszID0gX3g4Nk11bHRpcGx5KGszLCBjMyk7CgkJCWszID0gX3g4NlJvdGwoazMsIDE3KTsKCQkJazMgPSBfeDg2TXVsdGlwbHkoazMsIGM0KTsKCQkJaDMgXj0gazM7CgkJCQoJCQloMyA9IF94ODZSb3RsKGgzLCAxNSk7CgkJCWgzICs9IGg0OwoJCQloMyA9IF94ODZNdWx0aXBseShoMywgNSkgKyAweDk2Y2QxYzM1OwoJCQkKCQkJazQgPSBfeDg2TXVsdGlwbHkoazQsIGM0KTsKCQkJazQgPSBfeDg2Um90bChrNCwgMTgpOwoJCQlrNCA9IF94ODZNdWx0aXBseShrNCwgYzEpOwoJCQloNCBePSBrNDsKCQkJCgkJCWg0ID0gX3g4NlJvdGwoaDQsIDEzKTsKCQkJaDQgKz0gaDE7CgkJCWg0ID0gX3g4Nk11bHRpcGx5KGg0LCA1KSArIDB4MzJhYzNiMTc7CgkJfQoJCQoJCWsxID0gMDsKCQlrMiA9IDA7CgkJazMgPSAwOwoJCWs0ID0gMDsKCQkKCQlzd2l0Y2ggKHJlbWFpbmRlcikgewoJCQljYXNlIDE1OgoJCQkJazQgXj0ga2V5LmNoYXJDb2RlQXQoaSArIDE0KSA8PCAxNjsKCQkJCgkJCWNhc2UgMTQ6CgkJCQlrNCBePSBrZXkuY2hhckNvZGVBdChpICsgMTMpIDw8IDg7CgkJCQoJCQljYXNlIDEzOgoJCQkJazQgXj0ga2V5LmNoYXJDb2RlQXQoaSArIDEyKTsKCQkJCWs0ID0gX3g4Nk11bHRpcGx5KGs0LCBjNCk7CgkJCQlrNCA9IF94ODZSb3RsKGs0LCAxOCk7CgkJCQlrNCA9IF94ODZNdWx0aXBseShrNCwgYzEpOwoJCQkJaDQgXj0gazQ7CgkJCQoJCQljYXNlIDEyOgoJCQkJazMgXj0ga2V5LmNoYXJDb2RlQXQoaSArIDExKSA8PCAyNDsKCQkJCgkJCWNhc2UgMTE6CgkJCQlrMyBePSBrZXkuY2hhckNvZGVBdChpICsgMTApIDw8IDE2OwoJCQkKCQkJY2FzZSAxMDoKCQkJCWszIF49IGtleS5jaGFyQ29kZUF0KGkgKyA5KSA8PCA4OwoJCQkKCQkJY2FzZSA5OgoJCQkJazMgXj0ga2V5LmNoYXJDb2RlQXQoaSArIDgpOwoJCQkJazMgPSBfeDg2TXVsdGlwbHkoazMsIGMzKTsKCQkJCWszID0gX3g4NlJvdGwoazMsIDE3KTsKCQkJCWszID0gX3g4Nk11bHRpcGx5KGszLCBjNCk7CgkJCQloMyBePSBrMzsKCQkJCgkJCWNhc2UgODoKCQkJCWsyIF49IGtleS5jaGFyQ29kZUF0KGkgKyA3KSA8PCAyNDsKCQkJCgkJCWNhc2UgNzoKCQkJCWsyIF49IGtleS5jaGFyQ29kZUF0KGkgKyA2KSA8PCAxNjsKCQkJCgkJCWNhc2UgNjoKCQkJCWsyIF49IGtleS5jaGFyQ29kZUF0KGkgKyA1KSA8PCA4OwoJCQkKCQkJY2FzZSA1OgoJCQkJazIgXj0ga2V5LmNoYXJDb2RlQXQoaSArIDQpOwoJCQkJazIgPSBfeDg2TXVsdGlwbHkoazIsIGMyKTsKCQkJCWsyID0gX3g4NlJvdGwoazIsIDE2KTsKCQkJCWsyID0gX3g4Nk11bHRpcGx5KGsyLCBjMyk7CgkJCQloMiBePSBrMjsKCQkJCgkJCWNhc2UgNDoKCQkJCWsxIF49IGtleS5jaGFyQ29kZUF0KGkgKyAzKSA8PCAyNDsKCQkJCgkJCWNhc2UgMzoKCQkJCWsxIF49IGtleS5jaGFyQ29kZUF0KGkgKyAyKSA8PCAxNjsKCQkJCgkJCWNhc2UgMjoKCQkJCWsxIF49IGtleS5jaGFyQ29kZUF0KGkgKyAxKSA8PCA4OwoJCQkKCQkJY2FzZSAxOgoJCQkJazEgXj0ga2V5LmNoYXJDb2RlQXQoaSk7CgkJCQlrMSA9IF94ODZNdWx0aXBseShrMSwgYzEpOwoJCQkJazEgPSBfeDg2Um90bChrMSwgMTUpOwoJCQkJazEgPSBfeDg2TXVsdGlwbHkoazEsIGMyKTsKCQkJCWgxIF49IGsxOwoJCX0KCQkKCQloMSBePSBrZXkubGVuZ3RoOwoJCWgyIF49IGtleS5sZW5ndGg7CgkJaDMgXj0ga2V5Lmxlbmd0aDsKCQloNCBePSBrZXkubGVuZ3RoOwoJCQoJCWgxICs9IGgyOwoJCWgxICs9IGgzOwoJCWgxICs9IGg0OwoJCWgyICs9IGgxOwoJCWgzICs9IGgxOwoJCWg0ICs9IGgxOwoJCQoJCWgxID0gX3g4NkZtaXgoaDEpOwoJCWgyID0gX3g4NkZtaXgoaDIpOwoJCWgzID0gX3g4NkZtaXgoaDMpOwoJCWg0ID0gX3g4NkZtaXgoaDQpOwoJCQoJCWgxICs9IGgyOwoJCWgxICs9IGgzOwoJCWgxICs9IGg0OwoJCWgyICs9IGgxOwoJCWgzICs9IGgxOwoJCWg0ICs9IGgxOwoJCQoJCXJldHVybiAoIjAwMDAwMDAwIiArIChoMSA+Pj4gMCkudG9TdHJpbmcoMTYpKS5zbGljZSgtOCkgKyAoIjAwMDAwMDAwIiArIChoMiA+Pj4gMCkudG9TdHJpbmcoMTYpKS5zbGljZSgtOCkgKyAoIjAwMDAwMDAwIiArIChoMyA+Pj4gMCkudG9TdHJpbmcoMTYpKS5zbGljZSgtOCkgKyAoIjAwMDAwMDAwIiArIChoNCA+Pj4gMCkudG9TdHJpbmcoMTYpKS5zbGljZSgtOCk7Cgl9OwoJCgkKCWxpYnJhcnkueDY0Lmhhc2gxMjggPSBmdW5jdGlvbiAoa2V5LCBzZWVkKSB7CgkJLy8KCQkvLyBHaXZlbiBhIHN0cmluZyBhbmQgYW4gb3B0aW9uYWwgc2VlZCBhcyBhbiBpbnQsIHJldHVybnMgYSAxMjggYml0CgkJLy8gaGFzaCB1c2luZyB0aGUgeDY0IGZsYXZvciBvZiBNdXJtdXJIYXNoMywgYXMgYW4gdW5zaWduZWQgaGV4LgoJCS8vCgkJCgkJa2V5ID0ga2V5IHx8ICcnOwoJCXNlZWQgPSBzZWVkIHx8IDA7CgkJCgkJdmFyIHJlbWFpbmRlciA9IGtleS5sZW5ndGggJSAxNjsKCQl2YXIgYnl0ZXMgPSBrZXkubGVuZ3RoIC0gcmVtYWluZGVyOwoJCQoJCXZhciBoMSA9IFswLCBzZWVkXTsKCQl2YXIgaDIgPSBbMCwgc2VlZF07CgkJCgkJdmFyIGsxID0gWzAsIDBdOwoJCXZhciBrMiA9IFswLCAwXTsKCQkKCQl2YXIgYzEgPSBbMHg4N2MzN2I5MSwgMHgxMTQyNTNkNV07CgkJdmFyIGMyID0gWzB4NGNmNWFkNDMsIDB4Mjc0NTkzN2ZdOwoJCQoJCWZvciAodmFyIGkgPSAwOyBpIDwgYnl0ZXM7IGkgPSBpICsgMTYpIHsKCQkJazEgPSBbKChrZXkuY2hhckNvZGVBdChpICsgNCkgJiAweGZmKSkgfCAoKGtleS5jaGFyQ29kZUF0KGkgKyA1KSAmIDB4ZmYpIDw8IDgpIHwgKChrZXkuY2hhckNvZGVBdChpICsgNikgJiAweGZmKSA8PCAxNikgfCAoKGtleS5jaGFyQ29kZUF0KGkgKyA3KSAmIDB4ZmYpIDw8IDI0KSwgKChrZXkuY2hhckNvZGVBdChpKSAmIDB4ZmYpKSB8ICgoa2V5LmNoYXJDb2RlQXQoaSArIDEpICYgMHhmZikgPDwgOCkgfCAoKGtleS5jaGFyQ29kZUF0KGkgKyAyKSAmIDB4ZmYpIDw8IDE2KSB8ICgoa2V5LmNoYXJDb2RlQXQoaSArIDMpICYgMHhmZikgPDwgMjQpXTsKCQkJazIgPSBbKChrZXkuY2hhckNvZGVBdChpICsgMTIpICYgMHhmZikpIHwgKChrZXkuY2hhckNvZGVBdChpICsgMTMpICYgMHhmZikgPDwgOCkgfCAoKGtleS5jaGFyQ29kZUF0KGkgKyAxNCkgJiAweGZmKSA8PCAxNikgfCAoKGtleS5jaGFyQ29kZUF0KGkgKyAxNSkgJiAweGZmKSA8PCAyNCksICgoa2V5LmNoYXJDb2RlQXQoaSArIDgpICYgMHhmZikpIHwgKChrZXkuY2hhckNvZGVBdChpICsgOSkgJiAweGZmKSA8PCA4KSB8ICgoa2V5LmNoYXJDb2RlQXQoaSArIDEwKSAmIDB4ZmYpIDw8IDE2KSB8ICgoa2V5LmNoYXJDb2RlQXQoaSArIDExKSAmIDB4ZmYpIDw8IDI0KV07CgkJCQoJCQlrMSA9IF94NjRNdWx0aXBseShrMSwgYzEpOwoJCQlrMSA9IF94NjRSb3RsKGsxLCAzMSk7CgkJCWsxID0gX3g2NE11bHRpcGx5KGsxLCBjMik7CgkJCWgxID0gX3g2NFhvcihoMSwgazEpOwoJCQkKCQkJaDEgPSBfeDY0Um90bChoMSwgMjcpOwoJCQloMSA9IF94NjRBZGQoaDEsIGgyKTsKCQkJaDEgPSBfeDY0QWRkKF94NjRNdWx0aXBseShoMSwgWzAsIDVdKSwgWzAsIDB4NTJkY2U3MjldKTsKCQkJCgkJCWsyID0gX3g2NE11bHRpcGx5KGsyLCBjMik7CgkJCWsyID0gX3g2NFJvdGwoazIsIDMzKTsKCQkJazIgPSBfeDY0TXVsdGlwbHkoazIsIGMxKTsKCQkJaDIgPSBfeDY0WG9yKGgyLCBrMik7CgkJCQoJCQloMiA9IF94NjRSb3RsKGgyLCAzMSk7CgkJCWgyID0gX3g2NEFkZChoMiwgaDEpOwoJCQloMiA9IF94NjRBZGQoX3g2NE11bHRpcGx5KGgyLCBbMCwgNV0pLCBbMCwgMHgzODQ5NWFiNV0pOwoJCX0KCQkKCQlrMSA9IFswLCAwXTsKCQlrMiA9IFswLCAwXTsKCQkKCQlzd2l0Y2gocmVtYWluZGVyKSB7CgkJCWNhc2UgMTU6CgkJCQlrMiA9IF94NjRYb3IoazIsIF94NjRMZWZ0U2hpZnQoWzAsIGtleS5jaGFyQ29kZUF0KGkgKyAxNCldLCA0OCkpOwoJCQkKCQkJY2FzZSAxNDoKCQkJCWsyID0gX3g2NFhvcihrMiwgX3g2NExlZnRTaGlmdChbMCwga2V5LmNoYXJDb2RlQXQoaSArIDEzKV0sIDQwKSk7CgkJCQoJCQljYXNlIDEzOgoJCQkJazIgPSBfeDY0WG9yKGsyLCBfeDY0TGVmdFNoaWZ0KFswLCBrZXkuY2hhckNvZGVBdChpICsgMTIpXSwgMzIpKTsKCQkJCgkJCWNhc2UgMTI6CgkJCQlrMiA9IF94NjRYb3IoazIsIF94NjRMZWZ0U2hpZnQoWzAsIGtleS5jaGFyQ29kZUF0KGkgKyAxMSldLCAyNCkpOwoJCQkKCQkJY2FzZSAxMToKCQkJCWsyID0gX3g2NFhvcihrMiwgX3g2NExlZnRTaGlmdChbMCwga2V5LmNoYXJDb2RlQXQoaSArIDEwKV0sIDE2KSk7CgkJCQoJCQljYXNlIDEwOgoJCQkJazIgPSBfeDY0WG9yKGsyLCBfeDY0TGVmdFNoaWZ0KFswLCBrZXkuY2hhckNvZGVBdChpICsgOSldLCA4KSk7CgkJCQoJCQljYXNlIDk6CgkJCQlrMiA9IF94NjRYb3IoazIsIFswLCBrZXkuY2hhckNvZGVBdChpICsgOCldKTsKCQkJCWsyID0gX3g2NE11bHRpcGx5KGsyLCBjMik7CgkJCQlrMiA9IF94NjRSb3RsKGsyLCAzMyk7CgkJCQlrMiA9IF94NjRNdWx0aXBseShrMiwgYzEpOwoJCQkJaDIgPSBfeDY0WG9yKGgyLCBrMik7CgkJCQoJCQljYXNlIDg6CgkJCQlrMSA9IF94NjRYb3IoazEsIF94NjRMZWZ0U2hpZnQoWzAsIGtleS5jaGFyQ29kZUF0KGkgKyA3KV0sIDU2KSk7CgkJCQoJCQljYXNlIDc6CgkJCQlrMSA9IF94NjRYb3IoazEsIF94NjRMZWZ0U2hpZnQoWzAsIGtleS5jaGFyQ29kZUF0KGkgKyA2KV0sIDQ4KSk7CgkJCQoJCQljYXNlIDY6CgkJCQlrMSA9IF94NjRYb3IoazEsIF94NjRMZWZ0U2hpZnQoWzAsIGtleS5jaGFyQ29kZUF0KGkgKyA1KV0sIDQwKSk7CgkJCQoJCQljYXNlIDU6CgkJCQlrMSA9IF94NjRYb3IoazEsIF94NjRMZWZ0U2hpZnQoWzAsIGtleS5jaGFyQ29kZUF0KGkgKyA0KV0sIDMyKSk7CgkJCQoJCQljYXNlIDQ6CgkJCQlrMSA9IF94NjRYb3IoazEsIF94NjRMZWZ0U2hpZnQoWzAsIGtleS5jaGFyQ29kZUF0KGkgKyAzKV0sIDI0KSk7CgkJCQoJCQljYXNlIDM6CgkJCQlrMSA9IF94NjRYb3IoazEsIF94NjRMZWZ0U2hpZnQoWzAsIGtleS5jaGFyQ29kZUF0KGkgKyAyKV0sIDE2KSk7CgkJCQoJCQljYXNlIDI6CgkJCQlrMSA9IF94NjRYb3IoazEsIF94NjRMZWZ0U2hpZnQoWzAsIGtleS5jaGFyQ29kZUF0KGkgKyAxKV0sIDgpKTsKCQkJCgkJCWNhc2UgMToKCQkJCWsxID0gX3g2NFhvcihrMSwgWzAsIGtleS5jaGFyQ29kZUF0KGkpXSk7CgkJCQlrMSA9IF94NjRNdWx0aXBseShrMSwgYzEpOwoJCQkJazEgPSBfeDY0Um90bChrMSwgMzEpOwoJCQkJazEgPSBfeDY0TXVsdGlwbHkoazEsIGMyKTsKCQkJCWgxID0gX3g2NFhvcihoMSwgazEpOwoJCX0KCQkKCQloMSA9IF94NjRYb3IoaDEsIFswLCBrZXkubGVuZ3RoXSk7CgkJaDIgPSBfeDY0WG9yKGgyLCBbMCwga2V5Lmxlbmd0aF0pOwoJCQoJCWgxID0gX3g2NEFkZChoMSwgaDIpOwoJCWgyID0gX3g2NEFkZChoMiwgaDEpOwoJCQoJCWgxID0gX3g2NEZtaXgoaDEpOwoJCWgyID0gX3g2NEZtaXgoaDIpOwoJCQoJCWgxID0gX3g2NEFkZChoMSwgaDIpOwoJCWgyID0gX3g2NEFkZChoMiwgaDEpOwoJCQoJCXJldHVybiAoIjAwMDAwMDAwIiArIChoMVswXSA+Pj4gMCkudG9TdHJpbmcoMTYpKS5zbGljZSgtOCkgKyAoIjAwMDAwMDAwIiArIChoMVsxXSA+Pj4gMCkudG9TdHJpbmcoMTYpKS5zbGljZSgtOCkgKyAoIjAwMDAwMDAwIiArIChoMlswXSA+Pj4gMCkudG9TdHJpbmcoMTYpKS5zbGljZSgtOCkgKyAoIjAwMDAwMDAwIiArIChoMlsxXSA+Pj4gMCkudG9TdHJpbmcoMTYpKS5zbGljZSgtOCk7Cgl9OwoJCgkKCQoJCgkvLyBJTklUSUFMSVpBVElPTgoJLy8gLS0tLS0tLS0tLS0tLS0KCQoJLy8gRXhwb3J0IG11cm11ckhhc2gzIGZvciBDb21tb25KUywgZWl0aGVyIGFzIGFuIEFNRCBtb2R1bGUgb3IganVzdCBhcyBwYXJ0CgkvLyBvZiB0aGUgZ2xvYmFsIG9iamVjdC4KCWlmICh0eXBlb2YgZXhwb3J0cyAhPT0gJ3VuZGVmaW5lZCcpIHsKCQlpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbW9kdWxlLmV4cG9ydHMpIHsKCQkJZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gbGlicmFyeTsKCQl9CgkJCgkJZXhwb3J0cy5tdXJtdXJIYXNoMyA9IGxpYnJhcnk7Cgl9CgkKCWVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkgewoJCWRlZmluZShbXSwgZnVuY3Rpb24oKSB7CgkJCXJldHVybiBsaWJyYXJ5OwoJCX0pOwoJfQoJCgllbHNlIHsKCQkvLyBVc2UgbXVybXVySGFzaDMubm9Db25mbGljdCB0byByZXN0b3JlIGBtdXJtdXJIYXNoM2AgYmFjayB0byBpdHMKCQkvLyBvcmlnaW5hbCB2YWx1ZS4gUmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGUgbGlicmFyeSBvYmplY3QsIHRvIGFsbG93CgkJLy8gaXQgdG8gYmUgdXNlZCB1bmRlciBhIGRpZmZlcmVudCBuYW1lLgoJCWxpYnJhcnkuX211cm11ckhhc2gzID0gcm9vdC5tdXJtdXJIYXNoMwoJCQoJCWxpYnJhcnkubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHsKCQkJcm9vdC5tdXJtdXJIYXNoMyA9IGxpYnJhcnkuX211cm11ckhhc2gzOwoJCQlsaWJyYXJ5Ll9tdXJtdXJIYXNoMyA9IHVuZGVmaW5lZDsKCQkJbGlicmFyeS5ub0NvbmZsaWN0ID0gdW5kZWZpbmVkOwoJCQkKCQkJcmV0dXJuIGxpYnJhcnk7CgkJfTsKCQkKCQlyb290Lm11cm11ckhhc2gzID0gbGlicmFyeTsKCX0KfSkodGhpcyk7