#include <string.h>
#include <stdio.h>
/* triple-single functions adapted from ENS of Lyon's CRlibm,
http://l...content-available-to-author-only...n.fr/projects/crlibm */
void Add12(float *s, float *r, float a, float b)
{
float _z, _a=a, _b=b;
*s = _a + _b;
_z = *s - _a;
*r = _b - _z;
}
void Add22(float *zh, float *zl, float xh, float xl, float yh, float yl)
{
float _r,_s;
_r = (xh)+(yh);
_s = ((((xh)-_r) +(yh)) + (yl)) + (xl);
*zh = _r+_s;
*zl = (_r - (*zh)) + _s;
}
#define ABS(x) (((x)>0) ? (x) : (-(x)))
void Sub22Cond(float *zh, float *zl, float xh, float xl, float yh, float yl)
{
float _r,_s;
_r = (xh)+(-yh);
_s = ((ABS(xh)) > (ABS(yh)))?
((xh)-_r+(-yh)+(-yl)+(xl)) : ((-yh)-_r+(xh)+(xl)+(-yl));
*zh = _r+_s;
*zl = (_r - (*zh)) + _s;
}
void Add12Cond(float *s, float *r, float a, float b)
{
float _z, _a=a, _b=b;
*s = _a + _b;
if (ABS(a) > ABS(b)){
_z = *s - _a;
*r = _b - _z;
}else {
_z = *s - _b;
*r = _a - _z;}
}
void Mul12(float *rh, float *rl, float u, float v)
{
const float c = 4097.0f; /* 1<<12 + 1 */
float up, u1, u2, vp, v1, v2;
float _u=u, _v=v;
up = _u*c; vp = _v*c;
u1 = (_u-up)+up; v1 = (_v-vp)+vp;
u2 = _u-u1; v2 = _v-v1;
*rh = _u*_v;
*rl = (((u1*v1-*rh)+(u1*v2))+(u2*v1))+(u2*v2);
}
void Mul23(float *resh, float *resm, float *resl,
float ah, float al, float bh, float bl)
{
float _t1, _t2, _t3, _t4, _t5, _t6, _t7, _t8, _t9, _t10;
Mul12((resh),&_t1,(ah),(bh));
Mul12(&_t2,&_t3,(ah),(bl));
Mul12(&_t4,&_t5,(al),(bh));
_t6 = (al) * (bl);
Add22(&_t7,&_t8,_t2,_t3,_t4,_t5);
Add12(&_t9,&_t10,_t1,_t6);
Add22((resm),(resl),_t7,_t8,_t9,_t10);
}
void Add33Cond(float *resh, float *resm, float *resl,
float ah, float am, float al, float bh, float bm, float bl)
{
float _t1, _t2, _t3, _t4, _t5, _t6, _t7, _t8;
Add12Cond(resh,&_t1,(ah),(bh));
Add12Cond(&_t2,&_t3,(am),(bm));
_t6 = (al) + (bl);
Add12Cond(&_t7,&_t4,_t1,_t2);
_t5 = _t3 + _t4;
_t8 = _t5 + _t6;
Add12Cond(resm,resl,_t7,_t8);
}
void DoRenormalize3(float *resh, float *resm, float *resl,
float ah, float am, float al)
{
float _t1h, _t1l, _t2l;
Add12(&_t1h, &_t1l, (am), (al));
Add12(resh, &_t2l, (ah), (_t1h));
Add12(resm, resl, _t2l, _t1l);
}
/* Parse an integer into a double-single. */
void parse(float *h, float *l, const char *s)
{
float acc = 0;
for ( ; ; )
{
acc = 10.0f * acc + (*s - '0');
s++;
if (*s == 0)
{
*h = acc;
*l = 0;
break;
}
/* test acc rather than s; Regehr is the sort of
person to test long suites of leading zeroes: */
if (acc >= 100000.0f)
{
float acc2 = 0;
float factor = 1;
for ( ; ; )
{
/* XXX I'll bet this can be simplified by computing
acc *= 10.0f; instead of factor *= 10.0f; and a simple
Add12 of acc and acc2 at the end, for the right threshold
instead of 100000. */
factor *= 10.0f;
acc2 = 10.0f * acc2 + (*s - '0');
s++;
if (*s == 0) break;
}
Mul12(h, l, acc, factor);
Add22(h, l, *h, *l, acc2, 0);
break;
}
}
}
int main(int c, char **v)
{
if (c != 7)
{
return 1;
}
float xh1, xl1, yh1, yl1, xh2, xl2, yh2, yl2, xh3, xl3, yh3, yl3;
parse(&xh1, &xl1, v[1]);
parse(&yh1, &yl1, v[2]);
parse(&xh2, &xl2, v[3]);
parse(&yh2, &yl2, v[4]);
parse(&xh3, &xl3, v[5]);
parse(&yh3, &yl3, v[6]);
float dxh1, dxl1, dyh1, dyl1, dxh2, dxl2, dyh2, dyl2, dxh3, dxl3, dyh3, dyl3;
Sub22Cond(&dxh1, &dxl1, xh1, xl1, xh2, xl2);
Sub22Cond(&dyh1, &dyl1, yh1, yl1, yh2, yl2);
Sub22Cond(&dxh2, &dxl2, xh2, xl2, xh3, xl3);
Sub22Cond(&dyh2, &dyl2, yh2, yl2, yh3, yl3);
Sub22Cond(&dxh3, &dxl3, xh3, xl3, xh1, xl1);
Sub22Cond(&dyh3, &dyl3, yh3, yl3, yh1, yl1);
float sdxh1, sdxm1, sdxl1, sdyh1, sdym1, sdyl1;
float sdxh2, sdxm2, sdxl2, sdyh2, sdym2, sdyl2;
float sdxh3, sdxm3, sdxl3, sdyh3, sdym3, sdyl3;
// Are vectors colinear? Use cross-product v1x*v2y == v2x*v1y
Mul23(&sdxh1, &sdxm1, &sdxl1, dxh1, dxl1, dyh2, dyl2);
Mul23(&sdxh2, &sdxm2, &sdxl2, dxh2, dxl2, dyh1, dyl1);
DoRenormalize3(&sdxh1, &sdxm1, &sdxl1, sdxh1, sdxm1, sdxl1);
DoRenormalize3(&sdxh2, &sdxm2, &sdxl2, sdxh2, sdxm2, sdxl2);
/* XXX Compare. Products may be acurate to 2^-68 or so
if we interpolate from CRlibm's error computations for
double. We need 2^62. Can we compare for exact equality
or do we need to COMPARE UP TO EPSILON? */
// Now reuse the six triple-singles to compute squares of lengths of sides
Mul23(&sdxh1, &sdxm1, &sdxl1, dxh1, dxl1, dxh1, dxl1);
Mul23(&sdyh1, &sdym1, &sdyl1, dyh1, dyl1, dyh1, dyl1);
Mul23(&sdxh2, &sdxm2, &sdxl2, dxh2, dxl2, dxh2, dxl2);
Mul23(&sdyh2, &sdym2, &sdyl2, dyh2, dyl2, dyh2, dyl2);
Mul23(&sdxh3, &sdxm3, &sdxl3, dxh3, dxl3, dxh3, dxl3);
Mul23(&sdyh3, &sdym3, &sdyl3, dyh3, dyl3, dyh3, dyl3);
DoRenormalize3(&sdxh1, &sdxm1, &sdxl1, sdxh1, sdxm1, sdxl1);
DoRenormalize3(&sdxh2, &sdxm2, &sdxl2, sdxh2, sdxm2, sdxl2);
DoRenormalize3(&sdxh3, &sdxm3, &sdxl3, sdxh3, sdxm3, sdxl3);
DoRenormalize3(&sdyh1, &sdym1, &sdyl1, sdyh1, sdym1, sdyl1);
DoRenormalize3(&sdyh2, &sdym2, &sdyl2, sdyh2, sdym2, sdyl2);
DoRenormalize3(&sdyh3, &sdym3, &sdyl3, sdyh3, sdym3, sdyl3);
Add33Cond(&sdxh1, &sdxm1, &sdxl1, sdxh1, sdxm1, sdxl1, sdyh1, sdym1, sdyl1);
Add33Cond(&sdxh2, &sdxm2, &sdxl2, sdxh2, sdxm2, sdxl2, sdyh2, sdym2, sdyl2);
Add33Cond(&sdxh3, &sdxm3, &sdxl3, sdxh3, sdxm3, sdxl3, sdyh3, sdym3, sdyl3);
DoRenormalize3(&sdxh1, &sdxm1, &sdxl1, sdxh1, sdxm1, sdxl1);
DoRenormalize3(&sdxh2, &sdxm2, &sdxl2, sdxh2, sdxm2, sdxl2);
DoRenormalize3(&sdxh3, &sdxm3, &sdxl3, sdxh3, sdxm3, sdxl3);
// We have the squares of the lengths of each side, test them for equality:
float n = 0.0f;
if (sdxh1 == sdxh2 && sdxm1 == sdxm2 && sdxl1 == sdxl2)
// See XXX above.
n = 1.0f;
if (sdxh1 == sdxh3 && sdxm1 == sdxm3 && sdxl1 == sdxl3)
n++;
if (sdxh2 == sdxh3 && sdxm2 == sdxm3 && sdxl2 == sdxl3)
n++;
if (n
== 1.0f) printf("isosceles"); else if (n
== 3.0f) printf("equilateral");
#define GT(n, p) \
(sdxh##n > sdxh##p || \
(sdxh##n == sdxh##p && (sdxm##n > sdxm##p || \
(sdxm##n == sdxm##p && sdxl##n > sdxl##p))))
float tmp;
#define SWAP(n, p) \
tmp = sdxh##n; sdxh##n = sdxh##p; sdxh##p = tmp; \
tmp = sdxm##n; sdxm##n = sdxm##p; sdxm##p = tmp; \
tmp = sdxl##n; sdxl##n = sdxl##p; sdxl##p = tmp;
if (GT(2, 1))
{
SWAP(1, 2)
}
if (GT(3, 1))
{
SWAP(1, 3)
}
/* (sdxh1, sdxm1, sdxl1) contains the longest square of side length,
the other two triple-singles contain the other two sides. */
Add33Cond(&sdxh2, &sdxm2, &sdxl2, sdxh2, sdxm2, sdxl2, sdxh3, sdxm3, sdxl3);
DoRenormalize3(&sdxh2, &sdxm2, &sdxl2, sdxh2, sdxm2, sdxl2);
if (GT(2, 1))
else if (GT(1, 2))
return 0;
}
I2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8c3RkaW8uaD4KCi8qIHRyaXBsZS1zaW5nbGUgZnVuY3Rpb25zIGFkYXB0ZWQgZnJvbSBFTlMgb2YgTHlvbidzIENSbGlibSwgCiAgIGh0dHA6Ly9sLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5uLmZyL3Byb2plY3RzL2NybGlibSAqLwoKdm9pZCBBZGQxMihmbG9hdCAqcywgZmxvYXQgKnIsIGZsb2F0IGEsIGZsb2F0IGIpICAgICAgICAgIAp7CiAgZmxvYXQgX3osIF9hPWEsIF9iPWI7ICAgIAogICpzID0gX2EgKyBfYjsgICAgICAgICAgICAgIAogIF96ID0gKnMgLSBfYTsgICAgICAgICAgICAgIAogICpyID0gX2IgLSBfejsgICAKfQoKdm9pZCBBZGQyMihmbG9hdCAqemgsIGZsb2F0ICp6bCwgZmxvYXQgeGgsIGZsb2F0IHhsLCBmbG9hdCB5aCwgZmxvYXQgeWwpICAKewogIGZsb2F0IF9yLF9zOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICBfciA9ICh4aCkrKHloKTsgICAgICAgICAgICAgICAgICAgICAgICAgIAogIF9zID0gKCgoKHhoKS1fcikgKyh5aCkpICsgKHlsKSkgKyAoeGwpOyAgCiAgKnpoID0gX3IrX3M7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAqemwgPSAoX3IgLSAoKnpoKSkgKyBfczsgICAgCn0KCiNkZWZpbmUgQUJTKHgpICgoKHgpPjApID8gKHgpIDogKC0oeCkpKQoKdm9pZCBTdWIyMkNvbmQoZmxvYXQgKnpoLCBmbG9hdCAqemwsIGZsb2F0IHhoLCBmbG9hdCB4bCwgZmxvYXQgeWgsIGZsb2F0IHlsKSAgCnsKICBmbG9hdCBfcixfczsKICBfciA9ICh4aCkrKC15aCk7CiAgX3MgPSAoKEFCUyh4aCkpID4gKEFCUyh5aCkpKT8gCiAgICAgICAoKHhoKS1fcisoLXloKSsoLXlsKSsoeGwpKSA6ICgoLXloKS1fcisoeGgpKyh4bCkrKC15bCkpOwogICp6aCA9IF9yK19zOwogICp6bCA9IChfciAtICgqemgpKSArIF9zOwp9Cgp2b2lkIEFkZDEyQ29uZChmbG9hdCAqcywgZmxvYXQgKnIsIGZsb2F0IGEsIGZsb2F0IGIpCnsKICBmbG9hdCBfeiwgX2E9YSwgX2I9YjsKICAqcyA9IF9hICsgX2I7CiAgaWYgKEFCUyhhKSA+IEFCUyhiKSl7ICAgICAgICAgICAgCiAgICBfeiA9ICpzIC0gX2E7ICAgICAgICAgICAgICAgICAgIAogICAgKnIgPSBfYiAtIF96OyAgICAgICAgICAgICAgICAgICAKICB9ZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgIF96ID0gKnMgLSBfYjsgICAgICAgICAgICAgICAgICAgCiAgICAqciA9IF9hIC0gX3o7fQp9ICAgCgp2b2lkIE11bDEyKGZsb2F0ICpyaCwgZmxvYXQgKnJsLCBmbG9hdCB1LCBmbG9hdCB2KSAgICAgICAgICAgICAgICAgICAgICAgIAp7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICBjb25zdCBmbG9hdCBjICA9IDQwOTcuMGY7IC8qIDE8PDEyICsgMSAqLyAgIAogIGZsb2F0IHVwLCB1MSwgdTIsIHZwLCB2MSwgdjI7ICAgICAgICAgICAgICAgIAogIGZsb2F0IF91PXUsIF92PXY7ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogIHVwID0gX3UqYzsgICAgICAgIHZwID0gX3YqYzsgICAgICAgICAgICAgICAgICAKICB1MSA9IChfdS11cCkrdXA7ICB2MSA9IChfdi12cCkrdnA7ICAgICAgICAgICAgCiAgdTIgPSBfdS11MTsgICAgICAgdjIgPSBfdi12MTsgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAqcmggPSBfdSpfdjsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgKnJsID0gKCgodTEqdjEtKnJoKSsodTEqdjIpKSsodTIqdjEpKSsodTIqdjIpOwp9CgoKdm9pZCBNdWwyMyhmbG9hdCAqcmVzaCwgZmxvYXQgKnJlc20sIGZsb2F0ICpyZXNsLCAKICAgICAgICAgICBmbG9hdCBhaCwgZmxvYXQgYWwsIGZsb2F0IGJoLCBmbG9hdCBibCkgICAgICAgICAgICAgICAgCnsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgZmxvYXQgX3QxLCBfdDIsIF90MywgX3Q0LCBfdDUsIF90NiwgX3Q3LCBfdDgsIF90OSwgX3QxMDsgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgIE11bDEyKChyZXNoKSwmX3QxLChhaCksKGJoKSk7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICBNdWwxMigmX3QyLCZfdDMsKGFoKSwoYmwpKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgTXVsMTIoJl90NCwmX3Q1LChhbCksKGJoKSk7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgIF90NiA9IChhbCkgKiAoYmwpOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICBBZGQyMigmX3Q3LCZfdDgsX3QyLF90MyxfdDQsX3Q1KTsgICAgICAgICAgICAgICAgICAgICAgCiAgICBBZGQxMigmX3Q5LCZfdDEwLF90MSxfdDYpOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICBBZGQyMigocmVzbSksKHJlc2wpLF90NyxfdDgsX3Q5LF90MTApOyAgICAgICAgICAgICAgICAgCn0KCnZvaWQgQWRkMzNDb25kKGZsb2F0ICpyZXNoLCBmbG9hdCAqcmVzbSwgZmxvYXQgKnJlc2wsCiAgICAgICAgICAgICAgIGZsb2F0IGFoLCBmbG9hdCBhbSwgZmxvYXQgYWwsIGZsb2F0IGJoLCBmbG9hdCBibSwgZmxvYXQgYmwpICAgICAgCnsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgIGZsb2F0IF90MSwgX3QyLCBfdDMsIF90NCwgX3Q1LCBfdDYsIF90NywgX3Q4OyAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgIEFkZDEyQ29uZChyZXNoLCZfdDEsKGFoKSwoYmgpKTsgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgQWRkMTJDb25kKCZfdDIsJl90MywoYW0pLChibSkpOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgIF90NiA9IChhbCkgKyAoYmwpOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgQWRkMTJDb25kKCZfdDcsJl90NCxfdDEsX3QyKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgIF90NSA9IF90MyArIF90NDsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgX3Q4ID0gX3Q1ICsgX3Q2OyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICBBZGQxMkNvbmQocmVzbSxyZXNsLF90NyxfdDgpOyAgICAgICAgICAgICAgICAgIAp9Cgp2b2lkIERvUmVub3JtYWxpemUzKGZsb2F0ICpyZXNoLCBmbG9hdCAqcmVzbSwgZmxvYXQgKnJlc2wsIAogICAgICAgICAgICAgICAgICAgIGZsb2F0IGFoLCBmbG9hdCBhbSwgZmxvYXQgYWwpICAgICAKeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgZmxvYXQgX3QxaCwgX3QxbCwgX3QybDsgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgQWRkMTIoJl90MWgsICZfdDFsLCAoYW0pLCAoYWwpKTsgICAgICAgICAgICAgICAgICAgICAKICAgIEFkZDEyKHJlc2gsICZfdDJsLCAoYWgpLCAoX3QxaCkpOyAgICAgICAgICAgICAgCiAgICBBZGQxMihyZXNtLCByZXNsLCBfdDJsLCBfdDFsKTsgICAgICAgICAgIAp9CgovKiBQYXJzZSBhbiBpbnRlZ2VyIGludG8gYSBkb3VibGUtc2luZ2xlLiAqLwp2b2lkIHBhcnNlKGZsb2F0ICpoLCBmbG9hdCAqbCwgY29uc3QgY2hhciAqcykKewogIGZsb2F0IGFjYyA9IDA7CgogIGZvciAoIDsgOyApCiAgICB7CiAgICAgIGFjYyA9IDEwLjBmICogYWNjICsgKCpzIC0gJzAnKTsKCiAgICAgIHMrKzsKCiAgICAgIGlmICgqcyA9PSAwKSAKICAgICAgICB7CiAgICAgICAgICAqaCA9IGFjYzsKICAgICAgICAgICpsID0gMDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KCiAgICAgIC8qIHRlc3QgYWNjIHJhdGhlciB0aGFuIHM7IFJlZ2VociBpcyB0aGUgc29ydCBvZgogICAgICAgICBwZXJzb24gdG8gdGVzdCBsb25nIHN1aXRlcyBvZiBsZWFkaW5nIHplcm9lczogKi8KICAgICAgaWYgKGFjYyA+PSAxMDAwMDAuMGYpCiAgICAgICAgewogICAgICAgICAgZmxvYXQgYWNjMiA9IDA7CiAgICAgICAgICBmbG9hdCBmYWN0b3IgPSAxOwogICAgICAgICAgZm9yICggOyA7ICkKICAgICAgICAgICAgewogICAgICAgICAgICAgIC8qIFhYWCBJJ2xsIGJldCB0aGlzIGNhbiBiZSBzaW1wbGlmaWVkIGJ5IGNvbXB1dGluZwogICAgICAgICAgICAgICAgIGFjYyAqPSAxMC4wZjsgaW5zdGVhZCBvZiBmYWN0b3IgKj0gMTAuMGY7IGFuZCBhIHNpbXBsZQogICAgICAgICAgICAgICAgIEFkZDEyIG9mIGFjYyBhbmQgYWNjMiBhdCB0aGUgZW5kLCBmb3IgdGhlIHJpZ2h0IHRocmVzaG9sZAogICAgICAgICAgICAgICAgIGluc3RlYWQgb2YgMTAwMDAwLiAqLwogICAgICAgICAgICAgIGZhY3RvciAqPSAxMC4wZjsKICAgICAgICAgICAgICBhY2MyID0gMTAuMGYgKiBhY2MyICsgKCpzIC0gJzAnKTsKICAgICAgICAgICAgICBzKys7CiAgICAgICAgICAgICAgaWYgKCpzID09IDApIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICBNdWwxMihoLCBsLCBhY2MsIGZhY3Rvcik7CiAgICAgICAgICBBZGQyMihoLCBsLCAqaCwgKmwsIGFjYzIsIDApOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSAKICAgIH0KfQoKaW50IG1haW4oaW50IGMsIGNoYXIgKip2KQp7CiAgaWYgKGMgIT0gNykKICAgIHsKICAgICAgcHJpbnRmKCJVc2FnZSFcbiIpOwogICAgICByZXR1cm4gMTsKICAgIH0KICBmbG9hdCB4aDEsIHhsMSwgeWgxLCB5bDEsIHhoMiwgeGwyLCB5aDIsIHlsMiwgeGgzLCB4bDMsIHloMywgeWwzOwogIHBhcnNlKCZ4aDEsICZ4bDEsIHZbMV0pOwogIHBhcnNlKCZ5aDEsICZ5bDEsIHZbMl0pOwogIHBhcnNlKCZ4aDIsICZ4bDIsIHZbM10pOwogIHBhcnNlKCZ5aDIsICZ5bDIsIHZbNF0pOwogIHBhcnNlKCZ4aDMsICZ4bDMsIHZbNV0pOwogIHBhcnNlKCZ5aDMsICZ5bDMsIHZbNl0pOwoKICBmbG9hdCBkeGgxLCBkeGwxLCBkeWgxLCBkeWwxLCBkeGgyLCBkeGwyLCBkeWgyLCBkeWwyLCBkeGgzLCBkeGwzLCBkeWgzLCBkeWwzOwoKICBTdWIyMkNvbmQoJmR4aDEsICZkeGwxLCB4aDEsIHhsMSwgeGgyLCB4bDIpOwogIFN1YjIyQ29uZCgmZHloMSwgJmR5bDEsIHloMSwgeWwxLCB5aDIsIHlsMik7CiAgU3ViMjJDb25kKCZkeGgyLCAmZHhsMiwgeGgyLCB4bDIsIHhoMywgeGwzKTsKICBTdWIyMkNvbmQoJmR5aDIsICZkeWwyLCB5aDIsIHlsMiwgeWgzLCB5bDMpOwogIFN1YjIyQ29uZCgmZHhoMywgJmR4bDMsIHhoMywgeGwzLCB4aDEsIHhsMSk7CiAgU3ViMjJDb25kKCZkeWgzLCAmZHlsMywgeWgzLCB5bDMsIHloMSwgeWwxKTsKCiAgZmxvYXQgc2R4aDEsIHNkeG0xLCBzZHhsMSwgc2R5aDEsIHNkeW0xLCBzZHlsMTsKICBmbG9hdCBzZHhoMiwgc2R4bTIsIHNkeGwyLCBzZHloMiwgc2R5bTIsIHNkeWwyOwogIGZsb2F0IHNkeGgzLCBzZHhtMywgc2R4bDMsIHNkeWgzLCBzZHltMywgc2R5bDM7CgogIC8vIEFyZSB2ZWN0b3JzIGNvbGluZWFyPyBVc2UgY3Jvc3MtcHJvZHVjdCB2MXgqdjJ5ID09IHYyeCp2MXkgCgogIE11bDIzKCZzZHhoMSwgJnNkeG0xLCAmc2R4bDEsIGR4aDEsIGR4bDEsIGR5aDIsIGR5bDIpOwogIE11bDIzKCZzZHhoMiwgJnNkeG0yLCAmc2R4bDIsIGR4aDIsIGR4bDIsIGR5aDEsIGR5bDEpOwogIERvUmVub3JtYWxpemUzKCZzZHhoMSwgJnNkeG0xLCAmc2R4bDEsIHNkeGgxLCBzZHhtMSwgc2R4bDEpOwogIERvUmVub3JtYWxpemUzKCZzZHhoMiwgJnNkeG0yLCAmc2R4bDIsIHNkeGgyLCBzZHhtMiwgc2R4bDIpOwogIAogIC8qIFhYWCBDb21wYXJlLiBQcm9kdWN0cyBtYXkgYmUgYWN1cmF0ZSB0byAyXi02OCBvciBzbwogICAgIGlmIHdlIGludGVycG9sYXRlIGZyb20gQ1JsaWJtJ3MgZXJyb3IgY29tcHV0YXRpb25zIGZvcgogICAgIGRvdWJsZS4gV2UgbmVlZCAyXjYyLiBDYW4gd2UgY29tcGFyZSBmb3IgZXhhY3QgZXF1YWxpdHkKICAgICBvciBkbyB3ZSBuZWVkIHRvIENPTVBBUkUgVVAgVE8gRVBTSUxPTj8gKi8KCiAgLy8gTm93IHJldXNlIHRoZSBzaXggdHJpcGxlLXNpbmdsZXMgdG8gY29tcHV0ZSBzcXVhcmVzIG9mIGxlbmd0aHMgb2Ygc2lkZXMKCiAgTXVsMjMoJnNkeGgxLCAmc2R4bTEsICZzZHhsMSwgZHhoMSwgZHhsMSwgZHhoMSwgZHhsMSk7CiAgTXVsMjMoJnNkeWgxLCAmc2R5bTEsICZzZHlsMSwgZHloMSwgZHlsMSwgZHloMSwgZHlsMSk7CiAgTXVsMjMoJnNkeGgyLCAmc2R4bTIsICZzZHhsMiwgZHhoMiwgZHhsMiwgZHhoMiwgZHhsMik7CiAgTXVsMjMoJnNkeWgyLCAmc2R5bTIsICZzZHlsMiwgZHloMiwgZHlsMiwgZHloMiwgZHlsMik7CiAgTXVsMjMoJnNkeGgzLCAmc2R4bTMsICZzZHhsMywgZHhoMywgZHhsMywgZHhoMywgZHhsMyk7CiAgTXVsMjMoJnNkeWgzLCAmc2R5bTMsICZzZHlsMywgZHloMywgZHlsMywgZHloMywgZHlsMyk7CgogIERvUmVub3JtYWxpemUzKCZzZHhoMSwgJnNkeG0xLCAmc2R4bDEsIHNkeGgxLCBzZHhtMSwgc2R4bDEpOwogIERvUmVub3JtYWxpemUzKCZzZHhoMiwgJnNkeG0yLCAmc2R4bDIsIHNkeGgyLCBzZHhtMiwgc2R4bDIpOwogIERvUmVub3JtYWxpemUzKCZzZHhoMywgJnNkeG0zLCAmc2R4bDMsIHNkeGgzLCBzZHhtMywgc2R4bDMpOwogIERvUmVub3JtYWxpemUzKCZzZHloMSwgJnNkeW0xLCAmc2R5bDEsIHNkeWgxLCBzZHltMSwgc2R5bDEpOwogIERvUmVub3JtYWxpemUzKCZzZHloMiwgJnNkeW0yLCAmc2R5bDIsIHNkeWgyLCBzZHltMiwgc2R5bDIpOwogIERvUmVub3JtYWxpemUzKCZzZHloMywgJnNkeW0zLCAmc2R5bDMsIHNkeWgzLCBzZHltMywgc2R5bDMpOwoKICBBZGQzM0NvbmQoJnNkeGgxLCAmc2R4bTEsICZzZHhsMSwgc2R4aDEsIHNkeG0xLCBzZHhsMSwgc2R5aDEsIHNkeW0xLCBzZHlsMSk7CiAgQWRkMzNDb25kKCZzZHhoMiwgJnNkeG0yLCAmc2R4bDIsIHNkeGgyLCBzZHhtMiwgc2R4bDIsIHNkeWgyLCBzZHltMiwgc2R5bDIpOwogIEFkZDMzQ29uZCgmc2R4aDMsICZzZHhtMywgJnNkeGwzLCBzZHhoMywgc2R4bTMsIHNkeGwzLCBzZHloMywgc2R5bTMsIHNkeWwzKTsKCiAgRG9SZW5vcm1hbGl6ZTMoJnNkeGgxLCAmc2R4bTEsICZzZHhsMSwgc2R4aDEsIHNkeG0xLCBzZHhsMSk7CiAgRG9SZW5vcm1hbGl6ZTMoJnNkeGgyLCAmc2R4bTIsICZzZHhsMiwgc2R4aDIsIHNkeG0yLCBzZHhsMik7CiAgRG9SZW5vcm1hbGl6ZTMoJnNkeGgzLCAmc2R4bTMsICZzZHhsMywgc2R4aDMsIHNkeG0zLCBzZHhsMyk7CgogIC8vIFdlIGhhdmUgdGhlIHNxdWFyZXMgb2YgdGhlIGxlbmd0aHMgb2YgZWFjaCBzaWRlLCB0ZXN0IHRoZW0gZm9yIGVxdWFsaXR5OgoKICBmbG9hdCBuID0gMC4wZjsKICAKICBpZiAoc2R4aDEgPT0gc2R4aDIgJiYgc2R4bTEgPT0gc2R4bTIgJiYgc2R4bDEgPT0gc2R4bDIpCiAgICAvLyBTZWUgWFhYIGFib3ZlLgogICAgbiA9IDEuMGY7CgogIGlmIChzZHhoMSA9PSBzZHhoMyAmJiBzZHhtMSA9PSBzZHhtMyAmJiBzZHhsMSA9PSBzZHhsMykKICAgIG4rKzsKCiAgaWYgKHNkeGgyID09IHNkeGgzICYmIHNkeG0yID09IHNkeG0zICYmIHNkeGwyID09IHNkeGwzKQogICAgbisrOwogCiAgaWYgKG4gPT0gMS4wZikgcHJpbnRmKCJpc29zY2VsZXMiKTsKICBlbHNlIGlmIChuID09IDMuMGYpIHByaW50ZigiZXF1aWxhdGVyYWwiKTsKICBlbHNlIHByaW50Zigic2NhbGVuZSIpOwogCiAgcHJpbnRmKCIgIik7CgojZGVmaW5lIEdUKG4sIHApIFwKICAoc2R4aCMjbiA+IHNkeGgjI3AgfHwgIFwKICAgICAgKHNkeGgjI24gPT0gc2R4aCMjcCAmJiAoc2R4bSMjbiA+IHNkeG0jI3AgfHwgIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAoc2R4bSMjbiA9PSBzZHhtIyNwICYmIHNkeGwjI24gPiBzZHhsIyNwKSkpKQoKICBmbG9hdCB0bXA7CgojZGVmaW5lIFNXQVAobiwgcCkgXAogIHRtcCA9IHNkeGgjI247IHNkeGgjI24gPSBzZHhoIyNwOyBzZHhoIyNwID0gdG1wOyBcCiAgdG1wID0gc2R4bSMjbjsgc2R4bSMjbiA9IHNkeG0jI3A7IHNkeG0jI3AgPSB0bXA7IFwKICB0bXAgPSBzZHhsIyNuOyBzZHhsIyNuID0gc2R4bCMjcDsgc2R4bCMjcCA9IHRtcDsKCiAgaWYgKEdUKDIsIDEpKQogICAgewogICAgICBTV0FQKDEsIDIpCiAgICB9CgogIGlmIChHVCgzLCAxKSkKICAgIHsKICAgICAgU1dBUCgxLCAzKQogICAgfQoKICAvKiAoc2R4aDEsIHNkeG0xLCBzZHhsMSkgY29udGFpbnMgdGhlIGxvbmdlc3Qgc3F1YXJlIG9mIHNpZGUgbGVuZ3RoLAogICAgIHRoZSBvdGhlciB0d28gdHJpcGxlLXNpbmdsZXMgY29udGFpbiB0aGUgb3RoZXIgdHdvIHNpZGVzLiAqLwoKICBBZGQzM0NvbmQoJnNkeGgyLCAmc2R4bTIsICZzZHhsMiwgc2R4aDIsIHNkeG0yLCBzZHhsMiwgc2R4aDMsIHNkeG0zLCBzZHhsMyk7CiAgRG9SZW5vcm1hbGl6ZTMoJnNkeGgyLCAmc2R4bTIsICZzZHhsMiwgc2R4aDIsIHNkeG0yLCBzZHhsMik7CiAgIAogIGlmIChHVCgyLCAxKSkKICAgIHByaW50ZigiYWN1dGUiKTsKICBlbHNlIGlmIChHVCgxLCAyKSkKICAgIHByaW50Zigib2J0dXNlIik7CiAgZWxzZSBwcmludGYoInJpZ2h0Iik7CgogIHByaW50ZigiXG4iKTsKICByZXR1cm4gMDsKfQo=