#include <limits.h>
#include <float.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#if CHAR_BIT != 8
#error currently supported only CHAR_BIT = 8
#endif
#if FLT_RADIX != 2
#error currently supported only FLT_RADIX = 2
#endif
#ifndef M_PI
#define M_PI 3.14159265358979324
#endif
typedef unsigned char uint8;
/*
10-byte little-endian serialized format for double:
- normalized mantissa stored as 64-bit (8-byte) signed integer:
negative range: (-2^53, -2^52]
zero: 0
positive range: [+2^52, +2^53)
- 16-bit (2-byte) signed exponent:
range: [-0x7FFE, +0x7FFE]
Represented value = mantissa * 2^(exponent - 53)
Special cases:
- +infinity: mantissa = 0x7FFFFFFFFFFFFFFF, exp = 0x7FFF
- -infinity: mantissa = 0x8000000000000000, exp = 0x7FFF
- NaN: mantissa = 0x0000000000000000, exp = 0x7FFF
- +/-0: only one zero supported
*/
void Double2Bytes(uint8 buf[10], double x)
{
double m;
long long im; // at least 64 bits
int ie;
int i;
if (isnan(x))
{
// NaN
memcpy(buf
, "\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\x7F", 10); return;
}
else if (isinf(x))
{
if (signbit(x))
// -inf
memcpy(buf
, "\x00\x00\x00\x00\x00\x00\x00\x80" "\xFF\x7F", 10); else
// +inf
memcpy(buf
, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F" "\xFF\x7F", 10); return;
}
// Split double into normalized mantissa (range: (-1, -0.5], 0, [+0.5, +1))
// and base-2 exponent
m
= frexp(x
, &ie
); // x = m * 2^ie exactly for FLT_RADIX=2 // frexp() can't fail
// Extract most significant 53 bits of mantissa as integer
m
= ldexp(m
, 53); // can't overflow because // DBL_MAX_10_EXP >= 37 equivalent to DBL_MAX_2_EXP >= 122
im = trunc(m); // exact unless DBL_MANT_DIG > 53
// If the exponent is too small or too big, reduce the number to 0 or
// +/- infinity
if (ie > 0x7FFE)
{
if (im < 0)
// -inf
memcpy(buf
, "\x00\x00\x00\x00\x00\x00\x00\x80" "\xFF\x7F", 10); else
// +inf
memcpy(buf
, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F" "\xFF\x7F", 10); return;
}
else if (ie < -0x7FFE)
{
// 0
memcpy(buf
, "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00", 10); return;
}
// Store im as signed 64-bit little-endian integer
for (i = 0; i < 8; i++, im >>= 8)
buf[i] = (uint8)im;
// Store ie as signed 16-bit little-endian integer
for (i = 8; i < 10; i++, ie >>= 8)
buf[i] = (uint8)ie;
}
void Bytes2Double(double* x, const uint8 buf[10])
{
unsigned long long uim; // at least 64 bits
long long im; // ditto
unsigned uie;
int ie;
double m;
int i;
int negative = 0;
int maxe;
if (!memcmp(buf
, "\x00\x00\x00\x00\x00\x00\x00\x00" "\xFF\x7F", 10)) {
#ifdef NAN
*x = NAN;
#else
*x = 0; // NaN is not supported, use 0 instead (we could return an error)
#endif
return;
}
if (!memcmp(buf
, "\x00\x00\x00\x00\x00\x00\x00\x80" "\xFF\x7F", 10)) {
*x = -INFINITY;
return;
}
else if (!memcmp(buf
, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F" "\xFF\x7F", 10)) {
*x = INFINITY;
return;
}
// Load im as signed 64-bit little-endian integer
uim = 0;
for (i = 0; i < 8; i++)
{
uim >>= 8;
uim |= (unsigned long long)buf[i] << (64 - 8);
}
if (uim <= 0x7FFFFFFFFFFFFFFFLL)
im = uim;
else
im = (long long)(uim - 0x7FFFFFFFFFFFFFFFLL - 1) - 0x7FFFFFFFFFFFFFFFLL - 1;
// Obtain the absolute value of the mantissa, make sure it's
// normalized and fits into 53 bits, else the input is invalid
if (im > 0)
{
if (im < (1LL << 52) || im >= (1LL << 53))
{
#ifdef NAN
*x = NAN;
#else
*x = 0; // NaN is not supported, use 0 instead (we could return an error)
#endif
return;
}
}
else if (im < 0)
{
if (im > -(1LL << 52) || im <= -(1LL << 53))
{
#ifdef NAN
*x = NAN;
#else
*x = 0; // NaN is not supported, use 0 instead (we could return an error)
#endif
return;
}
negative = 1;
im = -im;
}
// Load ie as signed 16-bit little-endian integer
uie = 0;
for (i = 8; i < 10; i++)
{
uie >>= 8;
uie |= (unsigned)buf[i] << (16 - 8);
}
if (uie <= 0x7FFF)
ie = uie;
else
ie = (int)(uie - 0x7FFF - 1) - 0x7FFF - 1;
// If DBL_MANT_DIG < 53, truncate the mantissa
im >>= (53 > DBL_MANT_DIG) ? (53 - DBL_MANT_DIG) : 0;
m = im;
m
= ldexp(m
, (53 > DBL_MANT_DIG
) ? -DBL_MANT_DIG
: -53); // can't overflow // because DBL_MAX_10_EXP >= 37 equivalent to DBL_MAX_2_EXP >= 122
// Find out the maximum base-2 exponent and
// if ours is greater, return +/- infinity
if (ie > maxe)
m = INFINITY;
else
m
= ldexp(m
, ie
); // underflow may cause a floating-point exception
*x = negative ? -m : m;
}
int test(double x, const char* name)
{
uint8 buf[10], buf2[10];
double x2;
int error1, error2;
Double2Bytes(buf, x);
Bytes2Double(&x2, buf);
Double2Bytes(buf2, x2);
printf("%+.15E '%s' -> %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", x,
name,
buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9]);
if ((error1
= memcmp(&x
, &x2
, sizeof(x
))) != 0) puts("Bytes2Double(Double2Bytes(x)) != x");
if ((error2
= memcmp(buf
, buf2
, sizeof(buf
))) != 0) puts("Double2Bytes(Bytes2Double(Double2Bytes(x))) != Double2Bytes(x)");
return error1 || error2;
}
int testInf(void)
{
uint8 buf[10];
double x, x2;
int error;
x = DBL_MAX;
Double2Bytes(buf, x);
if (!++buf[8])
++buf[9]; // increment the exponent beyond the maximum
Bytes2Double(&x2, buf);
printf("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X -> %+.15E\n", buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],
x2);
if ((error = !isinf(x2)) != 0)
puts("Bytes2Double(Double2Bytes(DBL_MAX) * 2) != INF");
return error;
}
#define VALUE_AND_NAME(V) { V, #V }
const struct
{
double value;
const char* name;
} testData[] =
{
#ifdef NAN
VALUE_AND_NAME(NAN),
#endif
VALUE_AND_NAME(0.0),
VALUE_AND_NAME(+DBL_MIN),
VALUE_AND_NAME(-DBL_MIN),
VALUE_AND_NAME(+1.0),
VALUE_AND_NAME(-1.0),
VALUE_AND_NAME(+M_PI),
VALUE_AND_NAME(-M_PI),
VALUE_AND_NAME(+DBL_MAX),
VALUE_AND_NAME(-DBL_MAX),
VALUE_AND_NAME(+INFINITY),
VALUE_AND_NAME(-INFINITY),
};
int main(void)
{
unsigned i;
int errors = 0;
for (i = 0; i < sizeof(testData) / sizeof(testData[0]); i++)
errors += test(testData[i].value, testData[i].name);
errors += testInf();
// Test subnormal values. A floating-point exception may be raised.
errors += test(+DBL_MIN / 2, "+DBL_MIN / 2");
errors += test(-DBL_MIN / 2, "-DBL_MIN / 2");
printf("%d error(s)\n", errors
);
return 0;
}
I2luY2x1ZGUgPGxpbWl0cy5oPgojaW5jbHVkZSA8ZmxvYXQuaD4KI2luY2x1ZGUgPG1hdGguaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8c3RkaW8uaD4KCiNpZiBDSEFSX0JJVCAhPSA4CiNlcnJvciBjdXJyZW50bHkgc3VwcG9ydGVkIG9ubHkgQ0hBUl9CSVQgPSA4CiNlbmRpZgoKI2lmIEZMVF9SQURJWCAhPSAyCiNlcnJvciBjdXJyZW50bHkgc3VwcG9ydGVkIG9ubHkgRkxUX1JBRElYID0gMgojZW5kaWYKCiNpZm5kZWYgTV9QSQojZGVmaW5lIE1fUEkgMy4xNDE1OTI2NTM1ODk3OTMyNAojZW5kaWYKCnR5cGVkZWYgdW5zaWduZWQgY2hhciB1aW50ODsKCi8qCiAgMTAtYnl0ZSBsaXR0bGUtZW5kaWFuIHNlcmlhbGl6ZWQgZm9ybWF0IGZvciBkb3VibGU6CiAgLSBub3JtYWxpemVkIG1hbnRpc3NhIHN0b3JlZCBhcyA2NC1iaXQgKDgtYnl0ZSkgc2lnbmVkIGludGVnZXI6CiAgICAgIG5lZ2F0aXZlIHJhbmdlOiAoLTJeNTMsIC0yXjUyXQogICAgICB6ZXJvOiAwCiAgICAgIHBvc2l0aXZlIHJhbmdlOiBbKzJeNTIsICsyXjUzKQogIC0gMTYtYml0ICgyLWJ5dGUpIHNpZ25lZCBleHBvbmVudDoKICAgICAgcmFuZ2U6IFstMHg3RkZFLCArMHg3RkZFXQoKICBSZXByZXNlbnRlZCB2YWx1ZSA9IG1hbnRpc3NhICogMl4oZXhwb25lbnQgLSA1MykKCiAgU3BlY2lhbCBjYXNlczoKICAtICtpbmZpbml0eTogbWFudGlzc2EgPSAweDdGRkZGRkZGRkZGRkZGRkYsIGV4cCA9IDB4N0ZGRgogIC0gLWluZmluaXR5OiBtYW50aXNzYSA9IDB4ODAwMDAwMDAwMDAwMDAwMCwgZXhwID0gMHg3RkZGCiAgLSBOYU46ICAgICAgIG1hbnRpc3NhID0gMHgwMDAwMDAwMDAwMDAwMDAwLCBleHAgPSAweDdGRkYKICAtICsvLTA6ICAgICAgb25seSBvbmUgemVybyBzdXBwb3J0ZWQKKi8KCnZvaWQgRG91YmxlMkJ5dGVzKHVpbnQ4IGJ1ZlsxMF0sIGRvdWJsZSB4KQp7CiAgZG91YmxlIG07CiAgbG9uZyBsb25nIGltOyAvLyBhdCBsZWFzdCA2NCBiaXRzCiAgaW50IGllOwogIGludCBpOwoKICBpZiAoaXNuYW4oeCkpCiAgewogICAgLy8gTmFOCiAgICBtZW1jcHkoYnVmLCAiXHgwMFx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDAiICJceEZGXHg3RiIsIDEwKTsKICAgIHJldHVybjsKICB9CiAgZWxzZSBpZiAoaXNpbmYoeCkpCiAgewogICAgaWYgKHNpZ25iaXQoeCkpCiAgICAgIC8vIC1pbmYKICAgICAgbWVtY3B5KGJ1ZiwgIlx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDBceDgwIiAiXHhGRlx4N0YiLCAxMCk7CiAgICBlbHNlCiAgICAgIC8vICtpbmYKICAgICAgbWVtY3B5KGJ1ZiwgIlx4RkZceEZGXHhGRlx4RkZceEZGXHhGRlx4RkZceDdGIiAiXHhGRlx4N0YiLCAxMCk7CiAgICByZXR1cm47CiAgfQoKICAvLyBTcGxpdCBkb3VibGUgaW50byBub3JtYWxpemVkIG1hbnRpc3NhIChyYW5nZTogKC0xLCAtMC41XSwgMCwgWyswLjUsICsxKSkKICAvLyBhbmQgYmFzZS0yIGV4cG9uZW50CiAgbSA9IGZyZXhwKHgsICZpZSk7IC8vIHggPSBtICogMl5pZSBleGFjdGx5IGZvciBGTFRfUkFESVg9MgogICAgICAgICAgICAgICAgICAgICAvLyBmcmV4cCgpIGNhbid0IGZhaWwKICAvLyBFeHRyYWN0IG1vc3Qgc2lnbmlmaWNhbnQgNTMgYml0cyBvZiBtYW50aXNzYSBhcyBpbnRlZ2VyCiAgbSA9IGxkZXhwKG0sIDUzKTsgLy8gY2FuJ3Qgb3ZlcmZsb3cgYmVjYXVzZQogICAgICAgICAgICAgICAgICAgIC8vIERCTF9NQVhfMTBfRVhQID49IDM3IGVxdWl2YWxlbnQgdG8gREJMX01BWF8yX0VYUCA+PSAxMjIKICBpbSA9IHRydW5jKG0pOyAvLyBleGFjdCB1bmxlc3MgREJMX01BTlRfRElHID4gNTMKCiAgLy8gSWYgdGhlIGV4cG9uZW50IGlzIHRvbyBzbWFsbCBvciB0b28gYmlnLCByZWR1Y2UgdGhlIG51bWJlciB0byAwIG9yCiAgLy8gKy8tIGluZmluaXR5CiAgaWYgKGllID4gMHg3RkZFKQogIHsKICAgIGlmIChpbSA8IDApCiAgICAgIC8vIC1pbmYKICAgICAgbWVtY3B5KGJ1ZiwgIlx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDBceDgwIiAiXHhGRlx4N0YiLCAxMCk7CiAgICBlbHNlCiAgICAgIC8vICtpbmYKICAgICAgbWVtY3B5KGJ1ZiwgIlx4RkZceEZGXHhGRlx4RkZceEZGXHhGRlx4RkZceDdGIiAiXHhGRlx4N0YiLCAxMCk7CiAgICByZXR1cm47CiAgfQogIGVsc2UgaWYgKGllIDwgLTB4N0ZGRSkKICB7CiAgICAvLyAwCiAgICBtZW1jcHkoYnVmLCAiXHgwMFx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDAiICJceDAwXHgwMCIsIDEwKTsKICAgIHJldHVybjsKICB9CgogIC8vIFN0b3JlIGltIGFzIHNpZ25lZCA2NC1iaXQgbGl0dGxlLWVuZGlhbiBpbnRlZ2VyCiAgZm9yIChpID0gMDsgaSA8IDg7IGkrKywgaW0gPj49IDgpCiAgICBidWZbaV0gPSAodWludDgpaW07CgogIC8vIFN0b3JlIGllIGFzIHNpZ25lZCAxNi1iaXQgbGl0dGxlLWVuZGlhbiBpbnRlZ2VyCiAgZm9yIChpID0gODsgaSA8IDEwOyBpKyssIGllID4+PSA4KQogICAgYnVmW2ldID0gKHVpbnQ4KWllOwp9Cgp2b2lkIEJ5dGVzMkRvdWJsZShkb3VibGUqIHgsIGNvbnN0IHVpbnQ4IGJ1ZlsxMF0pCnsKICB1bnNpZ25lZCBsb25nIGxvbmcgdWltOyAvLyBhdCBsZWFzdCA2NCBiaXRzCiAgbG9uZyBsb25nIGltOyAvLyBkaXR0bwogIHVuc2lnbmVkIHVpZTsKICBpbnQgaWU7CiAgZG91YmxlIG07CiAgaW50IGk7CiAgaW50IG5lZ2F0aXZlID0gMDsKICBpbnQgbWF4ZTsKCiAgaWYgKCFtZW1jbXAoYnVmLCAiXHgwMFx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDAiICJceEZGXHg3RiIsIDEwKSkKICB7CiNpZmRlZiBOQU4KICAgICp4ID0gTkFOOwojZWxzZQogICAgKnggPSAwOyAvLyBOYU4gaXMgbm90IHN1cHBvcnRlZCwgdXNlIDAgaW5zdGVhZCAod2UgY291bGQgcmV0dXJuIGFuIGVycm9yKQojZW5kaWYKICAgIHJldHVybjsKICB9CgogIGlmICghbWVtY21wKGJ1ZiwgIlx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDBceDgwIiAiXHhGRlx4N0YiLCAxMCkpCiAgewogICAgKnggPSAtSU5GSU5JVFk7CiAgICByZXR1cm47CiAgfQogIGVsc2UgaWYgKCFtZW1jbXAoYnVmLCAiXHhGRlx4RkZceEZGXHhGRlx4RkZceEZGXHhGRlx4N0YiICJceEZGXHg3RiIsIDEwKSkKICB7CiAgICAqeCA9IElORklOSVRZOwogICAgcmV0dXJuOwogIH0KCiAgLy8gTG9hZCBpbSBhcyBzaWduZWQgNjQtYml0IGxpdHRsZS1lbmRpYW4gaW50ZWdlcgogIHVpbSA9IDA7CiAgZm9yIChpID0gMDsgaSA8IDg7IGkrKykKICB7CiAgICB1aW0gPj49IDg7CiAgICB1aW0gfD0gKHVuc2lnbmVkIGxvbmcgbG9uZylidWZbaV0gPDwgKDY0IC0gOCk7CiAgfQogIGlmICh1aW0gPD0gMHg3RkZGRkZGRkZGRkZGRkZGTEwpCiAgICBpbSA9IHVpbTsKICBlbHNlCiAgICBpbSA9IChsb25nIGxvbmcpKHVpbSAtIDB4N0ZGRkZGRkZGRkZGRkZGRkxMIC0gMSkgLSAweDdGRkZGRkZGRkZGRkZGRkZMTCAtIDE7CgogIC8vIE9idGFpbiB0aGUgYWJzb2x1dGUgdmFsdWUgb2YgdGhlIG1hbnRpc3NhLCBtYWtlIHN1cmUgaXQncwogIC8vIG5vcm1hbGl6ZWQgYW5kIGZpdHMgaW50byA1MyBiaXRzLCBlbHNlIHRoZSBpbnB1dCBpcyBpbnZhbGlkCiAgaWYgKGltID4gMCkKICB7CiAgICBpZiAoaW0gPCAoMUxMIDw8IDUyKSB8fCBpbSA+PSAoMUxMIDw8IDUzKSkKICAgIHsKI2lmZGVmIE5BTgogICAgICAqeCA9IE5BTjsKI2Vsc2UKICAgICAgKnggPSAwOyAvLyBOYU4gaXMgbm90IHN1cHBvcnRlZCwgdXNlIDAgaW5zdGVhZCAod2UgY291bGQgcmV0dXJuIGFuIGVycm9yKQojZW5kaWYKICAgICAgcmV0dXJuOwogICAgfQogIH0KICBlbHNlIGlmIChpbSA8IDApCiAgewogICAgaWYgKGltID4gLSgxTEwgPDwgNTIpIHx8IGltIDw9IC0oMUxMIDw8IDUzKSkKICAgIHsKI2lmZGVmIE5BTgogICAgICAqeCA9IE5BTjsKI2Vsc2UKICAgICAgKnggPSAwOyAvLyBOYU4gaXMgbm90IHN1cHBvcnRlZCwgdXNlIDAgaW5zdGVhZCAod2UgY291bGQgcmV0dXJuIGFuIGVycm9yKQojZW5kaWYKICAgICAgcmV0dXJuOwogICAgfQogICAgbmVnYXRpdmUgPSAxOwogICAgaW0gPSAtaW07CiAgfQoKICAvLyBMb2FkIGllIGFzIHNpZ25lZCAxNi1iaXQgbGl0dGxlLWVuZGlhbiBpbnRlZ2VyCiAgdWllID0gMDsKICBmb3IgKGkgPSA4OyBpIDwgMTA7IGkrKykKICB7CiAgICB1aWUgPj49IDg7CiAgICB1aWUgfD0gKHVuc2lnbmVkKWJ1ZltpXSA8PCAoMTYgLSA4KTsKICB9CiAgaWYgKHVpZSA8PSAweDdGRkYpCiAgICBpZSA9IHVpZTsKICBlbHNlCiAgICBpZSA9IChpbnQpKHVpZSAtIDB4N0ZGRiAtIDEpIC0gMHg3RkZGIC0gMTsKCiAgLy8gSWYgREJMX01BTlRfRElHIDwgNTMsIHRydW5jYXRlIHRoZSBtYW50aXNzYQogIGltID4+PSAoNTMgPiBEQkxfTUFOVF9ESUcpID8gKDUzIC0gREJMX01BTlRfRElHKSA6IDA7CgogIG0gPSBpbTsKICBtID0gbGRleHAobSwgKDUzID4gREJMX01BTlRfRElHKSA/IC1EQkxfTUFOVF9ESUcgOiAtNTMpOyAvLyBjYW4ndCBvdmVyZmxvdwogICAgICAgICAgIC8vIGJlY2F1c2UgREJMX01BWF8xMF9FWFAgPj0gMzcgZXF1aXZhbGVudCB0byBEQkxfTUFYXzJfRVhQID49IDEyMgoKICAvLyBGaW5kIG91dCB0aGUgbWF4aW11bSBiYXNlLTIgZXhwb25lbnQgYW5kCiAgLy8gaWYgb3VycyBpcyBncmVhdGVyLCByZXR1cm4gKy8tIGluZmluaXR5CiAgZnJleHAoREJMX01BWCwgJm1heGUpOwogIGlmIChpZSA+IG1heGUpCiAgICBtID0gSU5GSU5JVFk7CiAgZWxzZQogICAgbSA9IGxkZXhwKG0sIGllKTsgLy8gdW5kZXJmbG93IG1heSBjYXVzZSBhIGZsb2F0aW5nLXBvaW50IGV4Y2VwdGlvbgoKICAqeCA9IG5lZ2F0aXZlID8gLW0gOiBtOwp9CgppbnQgdGVzdChkb3VibGUgeCwgY29uc3QgY2hhciogbmFtZSkKewogIHVpbnQ4IGJ1ZlsxMF0sIGJ1ZjJbMTBdOwogIGRvdWJsZSB4MjsKICBpbnQgZXJyb3IxLCBlcnJvcjI7CgogIERvdWJsZTJCeXRlcyhidWYsIHgpOwogIEJ5dGVzMkRvdWJsZSgmeDIsIGJ1Zik7CiAgRG91YmxlMkJ5dGVzKGJ1ZjIsIHgyKTsKCiAgcHJpbnRmKCIlKy4xNUUgJyVzJyAtPiAlMDJYICUwMlggJTAyWCAlMDJYICUwMlggJTAyWCAlMDJYICUwMlggICUwMlggJTAyWFxuIiwKICAgICAgICAgeCwKICAgICAgICAgbmFtZSwKICAgICAgICAgYnVmWzBdLGJ1ZlsxXSxidWZbMl0sYnVmWzNdLGJ1Zls0XSxidWZbNV0sYnVmWzZdLGJ1Zls3XSxidWZbOF0sYnVmWzldKTsKCiAgaWYgKChlcnJvcjEgPSBtZW1jbXAoJngsICZ4Miwgc2l6ZW9mKHgpKSkgIT0gMCkKICAgIHB1dHMoIkJ5dGVzMkRvdWJsZShEb3VibGUyQnl0ZXMoeCkpICE9IHgiKTsKCiAgaWYgKChlcnJvcjIgPSBtZW1jbXAoYnVmLCBidWYyLCBzaXplb2YoYnVmKSkpICE9IDApCiAgICBwdXRzKCJEb3VibGUyQnl0ZXMoQnl0ZXMyRG91YmxlKERvdWJsZTJCeXRlcyh4KSkpICE9IERvdWJsZTJCeXRlcyh4KSIpOwoKICBwdXRzKCIiKTsKCiAgcmV0dXJuIGVycm9yMSB8fCBlcnJvcjI7Cn0KCmludCB0ZXN0SW5mKHZvaWQpCnsKICB1aW50OCBidWZbMTBdOwogIGRvdWJsZSB4LCB4MjsKICBpbnQgZXJyb3I7CgogIHggPSBEQkxfTUFYOwogIERvdWJsZTJCeXRlcyhidWYsIHgpOwogIGlmICghKytidWZbOF0pCiAgICArK2J1Zls5XTsgLy8gaW5jcmVtZW50IHRoZSBleHBvbmVudCBiZXlvbmQgdGhlIG1heGltdW0KICBCeXRlczJEb3VibGUoJngyLCBidWYpOwoKICBwcmludGYoIiUwMlggJTAyWCAlMDJYICUwMlggJTAyWCAlMDJYICUwMlggJTAyWCAgJTAyWCAlMDJYIC0+ICUrLjE1RVxuIiwKICAgICAgICAgYnVmWzBdLGJ1ZlsxXSxidWZbMl0sYnVmWzNdLGJ1Zls0XSxidWZbNV0sYnVmWzZdLGJ1Zls3XSxidWZbOF0sYnVmWzldLAogICAgICAgICB4Mik7CgogIGlmICgoZXJyb3IgPSAhaXNpbmYoeDIpKSAhPSAwKQogICAgcHV0cygiQnl0ZXMyRG91YmxlKERvdWJsZTJCeXRlcyhEQkxfTUFYKSAqIDIpICE9IElORiIpOwoKICBwdXRzKCIiKTsKCiAgcmV0dXJuIGVycm9yOwp9CgojZGVmaW5lIFZBTFVFX0FORF9OQU1FKFYpIHsgViwgI1YgfQoKY29uc3Qgc3RydWN0CnsKICBkb3VibGUgdmFsdWU7CiAgY29uc3QgY2hhciogbmFtZTsKfSB0ZXN0RGF0YVtdID0KewojaWZkZWYgTkFOCiAgVkFMVUVfQU5EX05BTUUoTkFOKSwKI2VuZGlmCiAgVkFMVUVfQU5EX05BTUUoMC4wKSwKICBWQUxVRV9BTkRfTkFNRSgrREJMX01JTiksCiAgVkFMVUVfQU5EX05BTUUoLURCTF9NSU4pLAogIFZBTFVFX0FORF9OQU1FKCsxLjApLAogIFZBTFVFX0FORF9OQU1FKC0xLjApLAogIFZBTFVFX0FORF9OQU1FKCtNX1BJKSwKICBWQUxVRV9BTkRfTkFNRSgtTV9QSSksCiAgVkFMVUVfQU5EX05BTUUoK0RCTF9NQVgpLAogIFZBTFVFX0FORF9OQU1FKC1EQkxfTUFYKSwKICBWQUxVRV9BTkRfTkFNRSgrSU5GSU5JVFkpLAogIFZBTFVFX0FORF9OQU1FKC1JTkZJTklUWSksCn07CgppbnQgbWFpbih2b2lkKQp7CiAgdW5zaWduZWQgaTsKICBpbnQgZXJyb3JzID0gMDsKCiAgZm9yIChpID0gMDsgaSA8IHNpemVvZih0ZXN0RGF0YSkgLyBzaXplb2YodGVzdERhdGFbMF0pOyBpKyspCiAgICBlcnJvcnMgKz0gdGVzdCh0ZXN0RGF0YVtpXS52YWx1ZSwgdGVzdERhdGFbaV0ubmFtZSk7CgogIGVycm9ycyArPSB0ZXN0SW5mKCk7CgogIC8vIFRlc3Qgc3Vibm9ybWFsIHZhbHVlcy4gQSBmbG9hdGluZy1wb2ludCBleGNlcHRpb24gbWF5IGJlIHJhaXNlZC4KICBlcnJvcnMgKz0gdGVzdCgrREJMX01JTiAvIDIsICIrREJMX01JTiAvIDIiKTsKICBlcnJvcnMgKz0gdGVzdCgtREJMX01JTiAvIDIsICItREJMX01JTiAvIDIiKTsKCiAgcHJpbnRmKCIlZCBlcnJvcihzKVxuIiwgZXJyb3JzKTsKCiAgcmV0dXJuIDA7Cn0K