// Ideas
// 1. Hidden header style array.
// 2. Playing around with Bigint add/subtract.
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// Utility.
#define SWAP(a, b) \
({ __auto_type _x = &(a); __auto_type _y = &(b); \
__auto_type _t = *_x; *_x = *_y; *_y = _t; \
(void) 0; })
div_t floordiv(int x, int y) {
int q = x / y - ((x % y) && (x ^ y) < 0);
int r = x - y * q;
return (div_t) {q, r};
}
// Shadow array (private).
typedef struct {
int count, capacity;
} _ArrHeader;
#define _PTR_TO_HDR(p) ((_ArrHeader*)((char*)p - sizeof(_ArrHeader)))
#define _HDR_TO_PTR(h) ((void*)((char*)h + sizeof(_ArrHeader)))
void *_arr_reserve(void *p, int capacity, int itemsize)
{
_ArrHeader *self = _PTR_TO_HDR(p);
if (self->capacity < capacity)
{
self
= realloc(self
, itemsize
*capacity
+ sizeof *self
); self->capacity = capacity;
}
return _HDR_TO_PTR(self);
}
void *_arr_resize(void *p, int count, int itemsize)
{
p = _arr_reserve(p, count, itemsize);
_PTR_TO_HDR(p)->count = count;
return p;
}
void _arr_free(void *p)
{
if (p != 0)
}
void *_arr_init(void)
{
_ArrHeader
*self
= malloc(sizeof *self
); self->count = 0;
self->capacity = 0;
return _HDR_TO_PTR(self);
}
void *_arr_at(void *p, ptrdiff_t i, int itemsize)
{
int count = _PTR_TO_HDR(p)->count;
if (i < 0)
i += count;
return (char*)p + i*itemsize;
}
void *_arr_append(void *p, const void *v, int itemsize)
{
_ArrHeader *self = _PTR_TO_HDR(p);
if (self->count == self->capacity)
{
int capacity = self->capacity ? 2*self->capacity : 1;
p = _arr_reserve(p, capacity, itemsize);
self = _PTR_TO_HDR(p);
}
self->count++;
memcpy(_arr_at
(p
, -1, itemsize
), v
, itemsize
); return p;
}
// Shadow array (public).
#define arr_init(a) ((a) = _arr_init())
#define arr_free(a) (_arr_free(a), (a) = 0)
#define arr_resize(a, n) ((a) = _arr_resize(a, n, sizeof *(a)))
#define arr_at(a, i) (((__typeof__(a))_arr_at(a, i, sizeof *(a)))[0])
#define arr_append(a, v) ((a) = _arr_append(a, (__typeof__(*(a))[]){v}, sizeof *(a)))
void arr_pop(void *p)
{
_ArrHeader *self = _PTR_TO_HDR(p);
self->count--;
}
void arr_clear(void *p)
{
_PTR_TO_HDR(p)->count = 0;
}
int arr_count(void *p)
{
return _PTR_TO_HDR(p)->count;
}
int arr_capacity(void *p)
{
return _PTR_TO_HDR(p)->capacity;
}
// Bigint.
#define INTERNAL_BASE 10
typedef struct {
int *digit;
int sign;
} Bigint;
int _digit_adc(int *x, int m, const int *y, int n, int (*op)(int, int))
{
int carry = 0;
int i;
for (i = 0; i < n; i++)
{
carry = op(x[i], y[i] + carry);
div_t d = floordiv(carry, INTERNAL_BASE);
x[i] = d.rem;
carry = d.quot & 1;
}
for (; carry && i < m; i++)
{
carry = op(x[i], carry);
div_t d = floordiv(carry, INTERNAL_BASE);
x[i] = d.rem;
carry = d.quot & 1;
}
return carry;
}
int _op_add(int x, int y)
{
return x + y;
}
int _op_sub(int x, int y)
{
return x - y;
}
int _digit_add(int *x, int m, const int *y, int n)
{
return _digit_adc(x, m, y, n, _op_add);
}
int _digit_sub(int *x, int m, const int *y, int n)
{
return _digit_adc(x, m, y, n, _op_sub);
}
int _digit_cmp(const int *x, int m, const int *y, int n)
{
if (m != n)
return (m < n) ? -1 : 1;
for (int i = m; i > 0; i--)
{
int s = x[i-1];
int t = y[i-1];
if (s != t)
return (s < t) ? -1 : 1;
}
return 0;
}
void _bigint_normalize(Bigint *a)
{
// Strip leading zeros; ensure zero is unsigned.
while (arr_count(a->digit) > 1 && arr_at(a->digit, -1) == 0)
arr_pop(a->digit);
if (arr_at(a->digit, -1) == 0)
a->sign = 0;
}
void _bigint_set(Bigint* a, const Bigint* b)
{
int n = arr_count(b->digit);
arr_resize(a->digit, n);
memmove(a
->digit
, b
->digit
, n
* sizeof *a
->digit
); a->sign = b->sign;
}
void _bigint_set_si(Bigint *a, int v)
{
arr_clear(a->digit);
a->sign = v < 0;
do
{
arr_append
(a
->digit
, abs(v
% INTERNAL_BASE
)); v /= INTERNAL_BASE;
}
while (v != 0);
}
void _bigint_add_lower(Bigint *c, const Bigint *a, const Bigint *b)
{
int m = arr_count(a->digit);
int n = arr_count(b->digit);
if (m < n)
{
SWAP(a, b);
SWAP(m, n);
}
_bigint_set(c, a);
int carry = _digit_add(c->digit, m, b->digit, n);
if (carry != 0)
arr_append(c->digit, carry);
_bigint_normalize(c);
}
void _bigint_sub_lower(Bigint *c, const Bigint *a, const Bigint *b)
{
int m = arr_count(a->digit);
int n = arr_count(b->digit);
int sign = 0;
if (_digit_cmp(a->digit, m, b->digit, n) < 0)
{
SWAP(a, b);
SWAP(m, n);
sign = 1;
}
_bigint_set(c, a);
int borrow = _digit_sub(c->digit, m, b->digit, n);
c->sign = sign;
_bigint_normalize(c);
}
void _bigint_add(Bigint *c, const Bigint *a, const Bigint *b, int bsign)
{
if (a->sign == bsign)
{
_bigint_add_lower(c, a, b);
c->sign = a->sign;
}
else
{
if (a->sign)
_bigint_sub_lower(c, b, a);
else
_bigint_sub_lower(c, a, b);
}
}
// Bigint (public).
void bigint_free(Bigint *a)
{
arr_free(a->digit);
}
void bigint_init(Bigint *a)
{
a->digit = 0;
a->sign = 0;
arr_init(a->digit);
arr_append(a->digit, 0);
}
void bigint_init_set_si(Bigint *a, int v)
{
a->digit = 0;
arr_init(a->digit);
_bigint_set_si(a, v);
}
void bigint_set(Bigint *a, const Bigint *b)
{
_bigint_set(a, b);
}
void bigint_set_si(Bigint *a, int v)
{
_bigint_set_si(a, v);
}
void bigint_swap(Bigint *a, Bigint *b)
{
Bigint t = *a; *a = *b; *b = t;
}
void bigint_add(Bigint *c, const Bigint *a, const Bigint *b)
{
_bigint_add(c, a, b, b->sign);
}
void bigint_sub(Bigint *c, const Bigint *a, const Bigint *b)
{
_bigint_add(c, a, b, !b->sign);
}
void bigint_print(const Bigint *a)
{
if (a->sign)
for (int i = arr_count(a->digit); i > 0; i--)
printf("%d", a
->digit
[i
-1]); // Base 10 }
// Main.
void errorabort(const char *msg)
{
fprintf(stderr
, "Error: %s\n", msg
); }
int _bigint_to_si(const Bigint *a)
{
int result = 0;
for (int i = arr_count(a->digit); i > 0; i--)
{
if (__builtin_mul_overflow(result, INTERNAL_BASE, &result) ||
__builtin_add_overflow(result, a->digit[i-1], &result))
errorabort("overflow");
}
return a->sign ? -result : result;
}
void test(int n)
{
Bigint a; bigint_init(&a);
Bigint b; bigint_init(&b);
Bigint t; bigint_init(&t);
for (int x = -n; x <= n; x++)
for (int y = -n; y <= n; y++)
{
bigint_set_si(&a, x);
bigint_set_si(&b, y);
bigint_add(&t, &a, &b);
assert(_bigint_to_si
(&t
) == x
+y
); bigint_sub(&t, &a, &b);
assert(_bigint_to_si
(&t
) == x
-y
); }
bigint_free(&a);
bigint_free(&b);
bigint_free(&t);
}
void fibonacci(int n, Bigint *result)
{
Bigint a; bigint_init_set_si(&a, 0);
Bigint b; bigint_init_set_si(&b, 1);
Bigint t; bigint_init(&t);
for (int i = 0; i < n; i++)
{
bigint_add(&t, &a, &b);
bigint_swap(&b, &a); // a -> b
bigint_swap(&a, &t); // t -> a
}
bigint_swap(&a, result);
bigint_free(&a);
bigint_free(&b);
bigint_free(&t);
}
int main(void)
{
test(123);
Bigint a; bigint_init(&a);
Bigint b; bigint_init(&b);
Bigint c; bigint_init(&c);
fibonacci(202, &a);
fibonacci(101, &b);
bigint_sub(&c, &a, &b);
bigint_print(&a);
bigint_print(&b);
bigint_print(&c);
bigint_free(&a);
bigint_free(&b);
bigint_free(&c);
return 0;
}
Ly8gSWRlYXMKLy8gMS4gSGlkZGVuIGhlYWRlciBzdHlsZSBhcnJheS4KLy8gMi4gUGxheWluZyBhcm91bmQgd2l0aCBCaWdpbnQgYWRkL3N1YnRyYWN0LgoKI2luY2x1ZGUgPGFzc2VydC5oPgojaW5jbHVkZSA8c3RkZGVmLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8c3RkaW8uaD4KCi8vIFV0aWxpdHkuCgojZGVmaW5lIFNXQVAoYSwgYikgXAooeyBfX2F1dG9fdHlwZSBfeCA9ICYoYSk7IF9fYXV0b190eXBlIF95ID0gJihiKTsgXAogICBfX2F1dG9fdHlwZSBfdCA9ICpfeDsgKl94ID0gKl95OyAqX3kgPSBfdDsgXAogICAodm9pZCkgMDsgfSkKCmRpdl90IGZsb29yZGl2KGludCB4LCBpbnQgeSkgewogICAgaW50IHEgPSB4IC8geSAtICgoeCAlIHkpICYmICh4IF4geSkgPCAwKTsKICAgIGludCByID0geCAtIHkgKiBxOwogICAgcmV0dXJuIChkaXZfdCkge3EsIHJ9Owp9CgovLyBTaGFkb3cgYXJyYXkgKHByaXZhdGUpLgoKdHlwZWRlZiBzdHJ1Y3QgewogICAgaW50IGNvdW50LCBjYXBhY2l0eTsKfSBfQXJySGVhZGVyOwoKI2RlZmluZSBfUFRSX1RPX0hEUihwKSAoKF9BcnJIZWFkZXIqKSgoY2hhciopcCAtIHNpemVvZihfQXJySGVhZGVyKSkpCiNkZWZpbmUgX0hEUl9UT19QVFIoaCkgKCh2b2lkKikoKGNoYXIqKWggKyBzaXplb2YoX0FyckhlYWRlcikpKQoKdm9pZCAqX2Fycl9yZXNlcnZlKHZvaWQgKnAsIGludCBjYXBhY2l0eSwgaW50IGl0ZW1zaXplKQp7CiAgICBfQXJySGVhZGVyICpzZWxmID0gX1BUUl9UT19IRFIocCk7CgogICAgaWYgKHNlbGYtPmNhcGFjaXR5IDwgY2FwYWNpdHkpCiAgICB7CiAgICAgICAgc2VsZiA9IHJlYWxsb2Moc2VsZiwgaXRlbXNpemUqY2FwYWNpdHkgKyBzaXplb2YgKnNlbGYpOwogICAgICAgIHNlbGYtPmNhcGFjaXR5ID0gY2FwYWNpdHk7CiAgICB9CiAgICByZXR1cm4gX0hEUl9UT19QVFIoc2VsZik7Cn0KCnZvaWQgKl9hcnJfcmVzaXplKHZvaWQgKnAsIGludCBjb3VudCwgaW50IGl0ZW1zaXplKQp7CiAgICBwID0gX2Fycl9yZXNlcnZlKHAsIGNvdW50LCBpdGVtc2l6ZSk7CiAgICBfUFRSX1RPX0hEUihwKS0+Y291bnQgPSBjb3VudDsKICAgIHJldHVybiBwOwp9Cgp2b2lkIF9hcnJfZnJlZSh2b2lkICpwKQp7CiAgICBpZiAocCAhPSAwKQogICAgICAgIGZyZWUoX1BUUl9UT19IRFIocCkpOwp9Cgp2b2lkICpfYXJyX2luaXQodm9pZCkKewogICAgX0FyckhlYWRlciAqc2VsZiA9IG1hbGxvYyhzaXplb2YgKnNlbGYpOwogICAgc2VsZi0+Y291bnQgPSAwOwogICAgc2VsZi0+Y2FwYWNpdHkgPSAwOwogICAgcmV0dXJuIF9IRFJfVE9fUFRSKHNlbGYpOwp9Cgp2b2lkICpfYXJyX2F0KHZvaWQgKnAsIHB0cmRpZmZfdCBpLCBpbnQgaXRlbXNpemUpCnsKICAgIGludCBjb3VudCA9IF9QVFJfVE9fSERSKHApLT5jb3VudDsKICAgIGlmIChpIDwgMCkKICAgICAgICBpICs9IGNvdW50OwogICAgYXNzZXJ0KDAgPD0gaSAmJiBpIDwgY291bnQpOwogICAgcmV0dXJuIChjaGFyKilwICsgaSppdGVtc2l6ZTsKfQoKdm9pZCAqX2Fycl9hcHBlbmQodm9pZCAqcCwgY29uc3Qgdm9pZCAqdiwgaW50IGl0ZW1zaXplKQp7CiAgICBfQXJySGVhZGVyICpzZWxmID0gX1BUUl9UT19IRFIocCk7CgogICAgaWYgKHNlbGYtPmNvdW50ID09IHNlbGYtPmNhcGFjaXR5KQogICAgewogICAgICAgIGludCBjYXBhY2l0eSA9IHNlbGYtPmNhcGFjaXR5ID8gMipzZWxmLT5jYXBhY2l0eSA6IDE7CiAgICAgICAgcCA9IF9hcnJfcmVzZXJ2ZShwLCBjYXBhY2l0eSwgaXRlbXNpemUpOwogICAgICAgIHNlbGYgPSBfUFRSX1RPX0hEUihwKTsKICAgIH0KICAgIHNlbGYtPmNvdW50Kys7CiAgICBtZW1jcHkoX2Fycl9hdChwLCAtMSwgaXRlbXNpemUpLCB2LCBpdGVtc2l6ZSk7CiAgICByZXR1cm4gcDsKfQoKLy8gU2hhZG93IGFycmF5IChwdWJsaWMpLgoKI2RlZmluZSBhcnJfaW5pdChhKSAoKGEpID0gX2Fycl9pbml0KCkpCiNkZWZpbmUgYXJyX2ZyZWUoYSkgKF9hcnJfZnJlZShhKSwgKGEpID0gMCkKI2RlZmluZSBhcnJfcmVzaXplKGEsIG4pICgoYSkgPSBfYXJyX3Jlc2l6ZShhLCBuLCBzaXplb2YgKihhKSkpCiNkZWZpbmUgYXJyX2F0KGEsIGkpICgoKF9fdHlwZW9mX18oYSkpX2Fycl9hdChhLCBpLCBzaXplb2YgKihhKSkpWzBdKQojZGVmaW5lIGFycl9hcHBlbmQoYSwgdikgKChhKSA9IF9hcnJfYXBwZW5kKGEsIChfX3R5cGVvZl9fKCooYSkpW10pe3Z9LCBzaXplb2YgKihhKSkpCgp2b2lkIGFycl9wb3Aodm9pZCAqcCkKewogICAgX0FyckhlYWRlciAqc2VsZiA9IF9QVFJfVE9fSERSKHApOwogICAgYXNzZXJ0KHNlbGYtPmNvdW50ID4gMCk7CiAgICBzZWxmLT5jb3VudC0tOwp9Cgp2b2lkIGFycl9jbGVhcih2b2lkICpwKQp7CiAgICBfUFRSX1RPX0hEUihwKS0+Y291bnQgPSAwOwp9CgppbnQgYXJyX2NvdW50KHZvaWQgKnApCnsKICAgIHJldHVybiBfUFRSX1RPX0hEUihwKS0+Y291bnQ7Cn0KCmludCBhcnJfY2FwYWNpdHkodm9pZCAqcCkKewogICAgcmV0dXJuIF9QVFJfVE9fSERSKHApLT5jYXBhY2l0eTsKfQoKLy8gQmlnaW50LgoKI2RlZmluZSBJTlRFUk5BTF9CQVNFIDEwCgp0eXBlZGVmIHN0cnVjdCB7CiAgICBpbnQgKmRpZ2l0OwogICAgaW50ICBzaWduOwp9IEJpZ2ludDsKCmludCBfZGlnaXRfYWRjKGludCAqeCwgaW50IG0sIGNvbnN0IGludCAqeSwgaW50IG4sIGludCAoKm9wKShpbnQsIGludCkpCnsKICAgIGFzc2VydChtID49IG4pOwoKICAgIGludCBjYXJyeSA9IDA7CiAgICBpbnQgaTsKCiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKQogICAgewogICAgICAgIGNhcnJ5ID0gb3AoeFtpXSwgeVtpXSArIGNhcnJ5KTsKICAgICAgICBkaXZfdCBkID0gZmxvb3JkaXYoY2FycnksIElOVEVSTkFMX0JBU0UpOwogICAgICAgIHhbaV0gPSBkLnJlbTsKICAgICAgICBjYXJyeSA9IGQucXVvdCAmIDE7CiAgICB9CiAgICBmb3IgKDsgY2FycnkgJiYgaSA8IG07IGkrKykKICAgIHsKICAgICAgICBjYXJyeSA9IG9wKHhbaV0sIGNhcnJ5KTsKICAgICAgICBkaXZfdCBkID0gZmxvb3JkaXYoY2FycnksIElOVEVSTkFMX0JBU0UpOwogICAgICAgIHhbaV0gPSBkLnJlbTsKICAgICAgICBjYXJyeSA9IGQucXVvdCAmIDE7CiAgICB9CiAgICByZXR1cm4gY2Fycnk7Cn0KCmludCBfb3BfYWRkKGludCB4LCBpbnQgeSkKewogICAgcmV0dXJuIHggKyB5Owp9CgppbnQgX29wX3N1YihpbnQgeCwgaW50IHkpCnsKICAgIHJldHVybiB4IC0geTsKfQoKaW50IF9kaWdpdF9hZGQoaW50ICp4LCBpbnQgbSwgY29uc3QgaW50ICp5LCBpbnQgbikKewogICAgcmV0dXJuIF9kaWdpdF9hZGMoeCwgbSwgeSwgbiwgX29wX2FkZCk7Cn0KCmludCBfZGlnaXRfc3ViKGludCAqeCwgaW50IG0sIGNvbnN0IGludCAqeSwgaW50IG4pCnsKICAgIHJldHVybiBfZGlnaXRfYWRjKHgsIG0sIHksIG4sIF9vcF9zdWIpOwp9CgppbnQgX2RpZ2l0X2NtcChjb25zdCBpbnQgKngsIGludCBtLCBjb25zdCBpbnQgKnksIGludCBuKQp7CiAgICBpZiAobSAhPSBuKQogICAgICAgIHJldHVybiAobSA8IG4pID8gLTEgOiAxOwoKICAgIGZvciAoaW50IGkgPSBtOyBpID4gMDsgaS0tKQogICAgewogICAgICAgIGludCBzID0geFtpLTFdOwogICAgICAgIGludCB0ID0geVtpLTFdOwoKICAgICAgICBpZiAocyAhPSB0KQogICAgICAgICAgICByZXR1cm4gKHMgPCB0KSA/IC0xIDogMTsKICAgIH0KICAgIHJldHVybiAwOwp9Cgp2b2lkIF9iaWdpbnRfbm9ybWFsaXplKEJpZ2ludCAqYSkKewogICAgLy8gU3RyaXAgbGVhZGluZyB6ZXJvczsgZW5zdXJlIHplcm8gaXMgdW5zaWduZWQuCiAgICB3aGlsZSAoYXJyX2NvdW50KGEtPmRpZ2l0KSA+IDEgJiYgYXJyX2F0KGEtPmRpZ2l0LCAtMSkgPT0gMCkKICAgICAgICBhcnJfcG9wKGEtPmRpZ2l0KTsKICAgIGlmIChhcnJfYXQoYS0+ZGlnaXQsIC0xKSA9PSAwKQogICAgICAgIGEtPnNpZ24gPSAwOwp9Cgp2b2lkIF9iaWdpbnRfc2V0KEJpZ2ludCogYSwgY29uc3QgQmlnaW50KiBiKQp7CiAgICBpbnQgbiA9IGFycl9jb3VudChiLT5kaWdpdCk7CiAgICBhcnJfcmVzaXplKGEtPmRpZ2l0LCBuKTsKICAgIG1lbW1vdmUoYS0+ZGlnaXQsIGItPmRpZ2l0LCBuICogc2l6ZW9mICphLT5kaWdpdCk7CiAgICBhLT5zaWduID0gYi0+c2lnbjsKfQoKdm9pZCBfYmlnaW50X3NldF9zaShCaWdpbnQgKmEsIGludCB2KQp7CiAgICBhcnJfY2xlYXIoYS0+ZGlnaXQpOwogICAgYS0+c2lnbiA9IHYgPCAwOwoKICAgIGRvCiAgICB7CiAgICAgICAgYXJyX2FwcGVuZChhLT5kaWdpdCwgYWJzKHYgJSBJTlRFUk5BTF9CQVNFKSk7CiAgICAgICAgdiAvPSBJTlRFUk5BTF9CQVNFOwogICAgfQogICAgd2hpbGUgKHYgIT0gMCk7Cn0KCnZvaWQgX2JpZ2ludF9hZGRfbG93ZXIoQmlnaW50ICpjLCBjb25zdCBCaWdpbnQgKmEsIGNvbnN0IEJpZ2ludCAqYikKewogICAgaW50IG0gPSBhcnJfY291bnQoYS0+ZGlnaXQpOwogICAgaW50IG4gPSBhcnJfY291bnQoYi0+ZGlnaXQpOwoKICAgIGlmIChtIDwgbikKICAgIHsKICAgICAgICBTV0FQKGEsIGIpOwogICAgICAgIFNXQVAobSwgbik7CiAgICB9CgogICAgX2JpZ2ludF9zZXQoYywgYSk7CgogICAgaW50IGNhcnJ5ID0gX2RpZ2l0X2FkZChjLT5kaWdpdCwgbSwgYi0+ZGlnaXQsIG4pOwoKICAgIGlmIChjYXJyeSAhPSAwKQogICAgICAgIGFycl9hcHBlbmQoYy0+ZGlnaXQsIGNhcnJ5KTsKICAgIF9iaWdpbnRfbm9ybWFsaXplKGMpOwp9Cgp2b2lkIF9iaWdpbnRfc3ViX2xvd2VyKEJpZ2ludCAqYywgY29uc3QgQmlnaW50ICphLCBjb25zdCBCaWdpbnQgKmIpCnsKICAgIGludCBtID0gYXJyX2NvdW50KGEtPmRpZ2l0KTsKICAgIGludCBuID0gYXJyX2NvdW50KGItPmRpZ2l0KTsKICAgIGludCBzaWduID0gMDsKCiAgICBpZiAoX2RpZ2l0X2NtcChhLT5kaWdpdCwgbSwgYi0+ZGlnaXQsIG4pIDwgMCkKICAgIHsKICAgICAgICBTV0FQKGEsIGIpOwogICAgICAgIFNXQVAobSwgbik7CiAgICAgICAgc2lnbiA9IDE7CiAgICB9CgogICAgX2JpZ2ludF9zZXQoYywgYSk7CgogICAgaW50IGJvcnJvdyA9IF9kaWdpdF9zdWIoYy0+ZGlnaXQsIG0sIGItPmRpZ2l0LCBuKTsKCiAgICBhc3NlcnQoYm9ycm93ID09IDApOwogICAgYy0+c2lnbiA9IHNpZ247CiAgICBfYmlnaW50X25vcm1hbGl6ZShjKTsKfQoKdm9pZCBfYmlnaW50X2FkZChCaWdpbnQgKmMsIGNvbnN0IEJpZ2ludCAqYSwgY29uc3QgQmlnaW50ICpiLCBpbnQgYnNpZ24pCnsKICAgIGlmIChhLT5zaWduID09IGJzaWduKQogICAgewogICAgICAgIF9iaWdpbnRfYWRkX2xvd2VyKGMsIGEsIGIpOwogICAgICAgIGMtPnNpZ24gPSBhLT5zaWduOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIGlmIChhLT5zaWduKQogICAgICAgICAgICBfYmlnaW50X3N1Yl9sb3dlcihjLCBiLCBhKTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIF9iaWdpbnRfc3ViX2xvd2VyKGMsIGEsIGIpOwogICAgfQp9CgovLyBCaWdpbnQgKHB1YmxpYykuCgp2b2lkIGJpZ2ludF9mcmVlKEJpZ2ludCAqYSkKewogICAgYXJyX2ZyZWUoYS0+ZGlnaXQpOwp9Cgp2b2lkIGJpZ2ludF9pbml0KEJpZ2ludCAqYSkKewogICAgYS0+ZGlnaXQgPSAwOwogICAgYS0+c2lnbiAgPSAwOwogICAgYXJyX2luaXQoYS0+ZGlnaXQpOwogICAgYXJyX2FwcGVuZChhLT5kaWdpdCwgMCk7Cn0KCnZvaWQgYmlnaW50X2luaXRfc2V0X3NpKEJpZ2ludCAqYSwgaW50IHYpCnsKICAgIGEtPmRpZ2l0ID0gMDsKICAgIGFycl9pbml0KGEtPmRpZ2l0KTsKICAgIF9iaWdpbnRfc2V0X3NpKGEsIHYpOwp9Cgp2b2lkIGJpZ2ludF9zZXQoQmlnaW50ICphLCBjb25zdCBCaWdpbnQgKmIpCnsKICAgIF9iaWdpbnRfc2V0KGEsIGIpOwp9Cgp2b2lkIGJpZ2ludF9zZXRfc2koQmlnaW50ICphLCBpbnQgdikKewogICAgX2JpZ2ludF9zZXRfc2koYSwgdik7Cn0KCnZvaWQgYmlnaW50X3N3YXAoQmlnaW50ICphLCBCaWdpbnQgKmIpCnsKICAgIEJpZ2ludCB0ID0gKmE7ICphID0gKmI7ICpiID0gdDsKfQoKdm9pZCBiaWdpbnRfYWRkKEJpZ2ludCAqYywgY29uc3QgQmlnaW50ICphLCBjb25zdCBCaWdpbnQgKmIpCnsKICAgIF9iaWdpbnRfYWRkKGMsIGEsIGIsIGItPnNpZ24pOwp9Cgp2b2lkIGJpZ2ludF9zdWIoQmlnaW50ICpjLCBjb25zdCBCaWdpbnQgKmEsIGNvbnN0IEJpZ2ludCAqYikKewogICAgX2JpZ2ludF9hZGQoYywgYSwgYiwgIWItPnNpZ24pOwp9Cgp2b2lkIGJpZ2ludF9wcmludChjb25zdCBCaWdpbnQgKmEpCnsKICAgIGlmIChhLT5zaWduKQogICAgICAgIHB1dGNoYXIoJy0nKTsKICAgIGZvciAoaW50IGkgPSBhcnJfY291bnQoYS0+ZGlnaXQpOyBpID4gMDsgaS0tKQogICAgICAgIHByaW50ZigiJWQiLCBhLT5kaWdpdFtpLTFdKTsgLy8gQmFzZSAxMAogICAgcHV0Y2hhcignXG4nKTsKfQoKLy8gTWFpbi4KCnZvaWQgZXJyb3JhYm9ydChjb25zdCBjaGFyICptc2cpCnsKICAgIGZwcmludGYoc3RkZXJyLCAiRXJyb3I6ICVzXG4iLCBtc2cpOwogICAgZXhpdCgxKTsKfQoKaW50IF9iaWdpbnRfdG9fc2koY29uc3QgQmlnaW50ICphKQp7CiAgICBpbnQgcmVzdWx0ID0gMDsKICAgIGZvciAoaW50IGkgPSBhcnJfY291bnQoYS0+ZGlnaXQpOyBpID4gMDsgaS0tKQogICAgewogICAgICAgIGlmIChfX2J1aWx0aW5fbXVsX292ZXJmbG93KHJlc3VsdCwgSU5URVJOQUxfQkFTRSwgJnJlc3VsdCkgfHwKICAgICAgICAgICAgX19idWlsdGluX2FkZF9vdmVyZmxvdyhyZXN1bHQsIGEtPmRpZ2l0W2ktMV0sICZyZXN1bHQpKQogICAgICAgICAgICBlcnJvcmFib3J0KCJvdmVyZmxvdyIpOwogICAgfQogICAgcmV0dXJuIGEtPnNpZ24gPyAtcmVzdWx0IDogcmVzdWx0Owp9Cgp2b2lkIHRlc3QoaW50IG4pCnsKICAgIEJpZ2ludCBhOyBiaWdpbnRfaW5pdCgmYSk7CiAgICBCaWdpbnQgYjsgYmlnaW50X2luaXQoJmIpOwogICAgQmlnaW50IHQ7IGJpZ2ludF9pbml0KCZ0KTsKCiAgICBmb3IgKGludCB4ID0gLW47IHggPD0gbjsgeCsrKQogICAgICAgIGZvciAoaW50IHkgPSAtbjsgeSA8PSBuOyB5KyspCiAgICAgICAgewogICAgICAgICAgICBiaWdpbnRfc2V0X3NpKCZhLCB4KTsKICAgICAgICAgICAgYmlnaW50X3NldF9zaSgmYiwgeSk7CiAgICAgICAgICAgIGJpZ2ludF9hZGQoJnQsICZhLCAmYik7CiAgICAgICAgICAgIGFzc2VydChfYmlnaW50X3RvX3NpKCZ0KSA9PSB4K3kpOwogICAgICAgICAgICBiaWdpbnRfc3ViKCZ0LCAmYSwgJmIpOwogICAgICAgICAgICBhc3NlcnQoX2JpZ2ludF90b19zaSgmdCkgPT0geC15KTsKICAgICAgICB9CgogICAgYmlnaW50X2ZyZWUoJmEpOwogICAgYmlnaW50X2ZyZWUoJmIpOwogICAgYmlnaW50X2ZyZWUoJnQpOwp9Cgp2b2lkIGZpYm9uYWNjaShpbnQgbiwgQmlnaW50ICpyZXN1bHQpCnsKICAgIEJpZ2ludCBhOyBiaWdpbnRfaW5pdF9zZXRfc2koJmEsIDApOwogICAgQmlnaW50IGI7IGJpZ2ludF9pbml0X3NldF9zaSgmYiwgMSk7CiAgICBCaWdpbnQgdDsgYmlnaW50X2luaXQoJnQpOwoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKQogICAgewogICAgICAgIGJpZ2ludF9hZGQoJnQsICZhLCAmYik7CiAgICAgICAgYmlnaW50X3N3YXAoJmIsICZhKTsgLy8gYSAtPiBiCiAgICAgICAgYmlnaW50X3N3YXAoJmEsICZ0KTsgLy8gdCAtPiBhCiAgICB9CgogICAgYmlnaW50X3N3YXAoJmEsIHJlc3VsdCk7CgogICAgYmlnaW50X2ZyZWUoJmEpOwogICAgYmlnaW50X2ZyZWUoJmIpOwogICAgYmlnaW50X2ZyZWUoJnQpOwp9CgppbnQgbWFpbih2b2lkKQp7CiAgICB0ZXN0KDEyMyk7CgogICAgQmlnaW50IGE7IGJpZ2ludF9pbml0KCZhKTsKICAgIEJpZ2ludCBiOyBiaWdpbnRfaW5pdCgmYik7CiAgICBCaWdpbnQgYzsgYmlnaW50X2luaXQoJmMpOwoKICAgIGZpYm9uYWNjaSgyMDIsICZhKTsKICAgIGZpYm9uYWNjaSgxMDEsICZiKTsKCiAgICBiaWdpbnRfc3ViKCZjLCAmYSwgJmIpOwoKICAgIGJpZ2ludF9wcmludCgmYSk7CiAgICBiaWdpbnRfcHJpbnQoJmIpOwogICAgYmlnaW50X3ByaW50KCZjKTsKCiAgICBiaWdpbnRfZnJlZSgmYSk7CiAgICBiaWdpbnRfZnJlZSgmYik7CiAgICBiaWdpbnRfZnJlZSgmYyk7CiAgICByZXR1cm4gMDsKfQ==