// Save for later.
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
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};
}
#define INTERNAL_BASE 10
typedef struct {
int *digit;
int count;
int sign;
} Bigint;
int _digit_add(int *x, int m, const int *y, int n)
{
int carry = 0;
int i;
for (i = 0; i < n; i++)
{
carry = x[i] + y[i] + carry;
x[i] = carry % INTERNAL_BASE;
carry /= INTERNAL_BASE;
}
for (; carry && i < m; i++)
{
carry = x[i] + carry;
x[i] = carry % INTERNAL_BASE;
carry /= INTERNAL_BASE;
}
return carry;
}
int _digit_sub(int *x, int m, const int *y, int n)
{
int borrow = 0;
int i;
for (i = 0; i < n; i++)
{
borrow = x[i] - y[i] - borrow;
div_t d = floordiv(borrow, INTERNAL_BASE);
x[i] = d.rem;
borrow = d.quot & 1;
}
for (; borrow && i < m; i++)
{
borrow = x[i] - borrow;
div_t d = floordiv(borrow, INTERNAL_BASE);
x[i] = d.rem;
borrow = d.quot & 1;
}
return borrow;
}
void _bigint_resize_noinit(Bigint* a, int n)
{
a
->digit
= realloc(a
->digit
, n
* sizeof *a
->digit
); a->count = n;
}
void _bigint_resize(Bigint* a, int n, int v)
{
assert(0 <= v
&& v
< INTERNAL_BASE
);
int m = a->count;
_bigint_resize_noinit(a, n);
for (int i = m; i < n; i++)
a->digit[i] = v;
}
void _bigint_append(Bigint* a, int v)
{
_bigint_resize(a, a->count + 1, v);
}
void _bigint_normalize(Bigint *a)
{
while (a->count > 1 && a->digit[a->count-1] == 0)
a->count--;
if (a->count == 1 && a->digit[0] == 0)
a->sign = 0;
}
// ..
void bigint_clear(Bigint *a)
{
a->digit = 0;
a->count = 0;
a->sign = 0;
}
void bigint_init(Bigint *a)
{
a->digit = 0;
a->count = 0;
a->sign = 0;
_bigint_append(a, 0);
}
void bigint_init_set_si(Bigint *a, int v)
{
a->digit = 0;
a->count = 0;
a->sign = v < 0;
do
{
_bigint_append
(a
, abs(v
% INTERNAL_BASE
)); v /= INTERNAL_BASE;
}
while (v != 0);
}
void bigint_set(Bigint *a, const Bigint *b)
{
_bigint_resize_noinit(a, b->count);
memmove(a
->digit
, b
->digit
, b
->count
* sizeof *a
->digit
); a->sign = b->sign;
}
void bigint_swap(Bigint *a, Bigint *b)
{
Bigint t = *a; *a = *b; *b = t;
}
int _bigint_compare(const Bigint *a, const Bigint *b)
{
int m = a->count;
int n = b->count;
if (m != n)
return (m < n) ? -1 : 1;
for (int i = m; i > 0; i--)
{
int x = a->digit[i-1];
int y = b->digit[i-1];
if (x != y)
return (x < y) ? -1 : 1;
}
return 0;
}
void _bigint_add_lower(Bigint *c, const Bigint *a, const Bigint *b)
{
if (a->count < b->count)
{
const Bigint *t = a; a = b; b = t;
}
bigint_set(c, a);
int carry = _digit_add(c->digit, c->count, b->digit, b->count);
if (carry != 0)
_bigint_append(c, carry);
_bigint_normalize(c);
}
void _bigint_sub_lower(Bigint *c, const Bigint *a, const Bigint *b)
{
int sign = 0;
if (_bigint_compare(a, b) < 0)
{
const Bigint *t = a; a = b; b = t;
sign = 1;
}
bigint_set(c, a);
_digit_sub(c->digit, c->count, b->digit, b->count);
c->sign = sign;
_bigint_normalize(c);
}
void _bigint_add_or_sub(Bigint *c, const Bigint *a, const Bigint *b, int invert)
{
if ((a->sign == b->sign) ^ invert)
{
_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);
}
}
void bigint_add(Bigint *c, const Bigint *a, const Bigint *b)
{
_bigint_add_or_sub(c, a, b, 0);
}
void bigint_sub(Bigint *c, const Bigint *a, const Bigint *b)
{
_bigint_add_or_sub(c, a, b, 1);
}
void bigint_print(const Bigint *a)
{
if (a->sign)
for (int i = a->count; i > 0; i--)
printf("%d", a
->digit
[i
-1]); // Base-10 }
// ..
void fatalerror(const char *msg)
{
fprintf(stderr
, "Error: %s\n", msg
); }
int _bigint_to_si(const Bigint *a)
{
int result = 0;
for (int i = a->count; i > 0; i--)
{
if (__builtin_mul_overflow(result, INTERNAL_BASE, &result) ||
__builtin_add_overflow(result, a->digit[i-1], &result))
fatalerror("overflow");
}
return a->sign ? -result : result;
}
void test(int n)
{
Bigint t; bigint_init(&t);
for (int x = -n; x <= n; x++)
for (int y = -n; y <= n; y++)
{
Bigint a; bigint_init_set_si(&a, x);
Bigint b; bigint_init_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_clear(&a);
bigint_clear(&b);
}
bigint_clear(&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_clear(&a);
bigint_clear(&b);
bigint_clear(&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_clear(&a);
bigint_clear(&b);
bigint_clear(&c);
return 0;
}
Ly8gU2F2ZSBmb3IgbGF0ZXIuCgojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8c3RkaW8uaD4KCmRpdl90IGZsb29yZGl2KGludCB4LCBpbnQgeSkgewogICAgaW50IHEgPSB4IC8geSAtICgoeCAlIHkpICYmICh4IF4geSkgPCAwKTsKICAgIGludCByID0geCAtIHkgKiBxOwogICAgcmV0dXJuIChkaXZfdCkge3EsIHJ9Owp9CgojZGVmaW5lIElOVEVSTkFMX0JBU0UgMTAKCnR5cGVkZWYgc3RydWN0IHsKICAgIGludCAqZGlnaXQ7CiAgICBpbnQgIGNvdW50OwogICAgaW50ICBzaWduOwp9IEJpZ2ludDsKCmludCBfZGlnaXRfYWRkKGludCAqeCwgaW50IG0sIGNvbnN0IGludCAqeSwgaW50IG4pCnsKICAgIGFzc2VydChtID49IG4pOwoKICAgIGludCBjYXJyeSA9IDA7CiAgICBpbnQgaTsKCiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKQogICAgewogICAgICAgIGNhcnJ5ID0geFtpXSArIHlbaV0gKyBjYXJyeTsKICAgICAgICB4W2ldID0gY2FycnkgJSBJTlRFUk5BTF9CQVNFOwogICAgICAgIGNhcnJ5IC89IElOVEVSTkFMX0JBU0U7CiAgICB9CiAgICBmb3IgKDsgY2FycnkgJiYgaSA8IG07IGkrKykKICAgIHsKICAgICAgICBjYXJyeSA9IHhbaV0gKyBjYXJyeTsKICAgICAgICB4W2ldID0gY2FycnkgJSBJTlRFUk5BTF9CQVNFOwogICAgICAgIGNhcnJ5IC89IElOVEVSTkFMX0JBU0U7CiAgICB9CiAgICByZXR1cm4gY2Fycnk7Cn0KCmludCBfZGlnaXRfc3ViKGludCAqeCwgaW50IG0sIGNvbnN0IGludCAqeSwgaW50IG4pCnsKICAgIGFzc2VydChtID49IG4pOwoKICAgIGludCBib3Jyb3cgPSAwOwogICAgaW50IGk7CgogICAgZm9yIChpID0gMDsgaSA8IG47IGkrKykKICAgIHsKICAgICAgICBib3Jyb3cgPSB4W2ldIC0geVtpXSAtIGJvcnJvdzsKICAgICAgICBkaXZfdCBkID0gZmxvb3JkaXYoYm9ycm93LCBJTlRFUk5BTF9CQVNFKTsKICAgICAgICB4W2ldID0gZC5yZW07CiAgICAgICAgYm9ycm93ID0gZC5xdW90ICYgMTsKICAgIH0KICAgIGZvciAoOyBib3Jyb3cgJiYgaSA8IG07IGkrKykKICAgIHsKICAgICAgICBib3Jyb3cgPSB4W2ldIC0gYm9ycm93OwogICAgICAgIGRpdl90IGQgPSBmbG9vcmRpdihib3Jyb3csIElOVEVSTkFMX0JBU0UpOwogICAgICAgIHhbaV0gPSBkLnJlbTsKICAgICAgICBib3Jyb3cgPSBkLnF1b3QgJiAxOwogICAgfQogICAgcmV0dXJuIGJvcnJvdzsKfQoKdm9pZCBfYmlnaW50X3Jlc2l6ZV9ub2luaXQoQmlnaW50KiBhLCBpbnQgbikKewogICAgYXNzZXJ0KG4gPiAwKTsKICAgIGEtPmRpZ2l0ID0gcmVhbGxvYyhhLT5kaWdpdCwgbiAqIHNpemVvZiAqYS0+ZGlnaXQpOwogICAgYS0+Y291bnQgPSBuOwp9Cgp2b2lkIF9iaWdpbnRfcmVzaXplKEJpZ2ludCogYSwgaW50IG4sIGludCB2KQp7CiAgICBhc3NlcnQoMCA8PSB2ICYmIHYgPCBJTlRFUk5BTF9CQVNFKTsKCiAgICBpbnQgbSA9IGEtPmNvdW50OwogICAgX2JpZ2ludF9yZXNpemVfbm9pbml0KGEsIG4pOwogICAgZm9yIChpbnQgaSA9IG07IGkgPCBuOyBpKyspCiAgICAgICAgYS0+ZGlnaXRbaV0gPSB2Owp9Cgp2b2lkIF9iaWdpbnRfYXBwZW5kKEJpZ2ludCogYSwgaW50IHYpCnsKICAgIF9iaWdpbnRfcmVzaXplKGEsIGEtPmNvdW50ICsgMSwgdik7Cn0KCnZvaWQgX2JpZ2ludF9ub3JtYWxpemUoQmlnaW50ICphKQp7CiAgICB3aGlsZSAoYS0+Y291bnQgPiAxICYmIGEtPmRpZ2l0W2EtPmNvdW50LTFdID09IDApCiAgICAgICAgYS0+Y291bnQtLTsKICAgIGlmIChhLT5jb3VudCA9PSAxICYmIGEtPmRpZ2l0WzBdID09IDApCiAgICAgICAgYS0+c2lnbiA9IDA7Cn0KCi8vIC4uCgp2b2lkIGJpZ2ludF9jbGVhcihCaWdpbnQgKmEpCnsKICAgIGZyZWUoYS0+ZGlnaXQpOwogICAgYS0+ZGlnaXQgPSAwOwogICAgYS0+Y291bnQgPSAwOwogICAgYS0+c2lnbiAgPSAwOwp9Cgp2b2lkIGJpZ2ludF9pbml0KEJpZ2ludCAqYSkKewogICAgYS0+ZGlnaXQgPSAwOwogICAgYS0+Y291bnQgPSAwOwogICAgYS0+c2lnbiAgPSAwOwogICAgX2JpZ2ludF9hcHBlbmQoYSwgMCk7Cn0KCnZvaWQgYmlnaW50X2luaXRfc2V0X3NpKEJpZ2ludCAqYSwgaW50IHYpCnsKICAgIGEtPmRpZ2l0ID0gMDsKICAgIGEtPmNvdW50ID0gMDsKICAgIGEtPnNpZ24gID0gdiA8IDA7CiAgICBkbwogICAgewogICAgICAgIF9iaWdpbnRfYXBwZW5kKGEsIGFicyh2ICUgSU5URVJOQUxfQkFTRSkpOwogICAgICAgIHYgLz0gSU5URVJOQUxfQkFTRTsKICAgIH0KICAgIHdoaWxlICh2ICE9IDApOwp9Cgp2b2lkIGJpZ2ludF9zZXQoQmlnaW50ICphLCBjb25zdCBCaWdpbnQgKmIpCnsKICAgIF9iaWdpbnRfcmVzaXplX25vaW5pdChhLCBiLT5jb3VudCk7CiAgICBtZW1tb3ZlKGEtPmRpZ2l0LCBiLT5kaWdpdCwgYi0+Y291bnQgKiBzaXplb2YgKmEtPmRpZ2l0KTsKICAgIGEtPnNpZ24gPSBiLT5zaWduOwp9Cgp2b2lkIGJpZ2ludF9zd2FwKEJpZ2ludCAqYSwgQmlnaW50ICpiKQp7CiAgICBCaWdpbnQgdCA9ICphOyAqYSA9ICpiOyAqYiA9IHQ7Cn0KCmludCBfYmlnaW50X2NvbXBhcmUoY29uc3QgQmlnaW50ICphLCBjb25zdCBCaWdpbnQgKmIpCnsKICAgIGludCBtID0gYS0+Y291bnQ7CiAgICBpbnQgbiA9IGItPmNvdW50OwogICAgaWYgKG0gIT0gbikKICAgICAgICByZXR1cm4gKG0gPCBuKSA/IC0xIDogMTsKCiAgICBmb3IgKGludCBpID0gbTsgaSA+IDA7IGktLSkKICAgIHsKICAgICAgICBpbnQgeCA9IGEtPmRpZ2l0W2ktMV07CiAgICAgICAgaW50IHkgPSBiLT5kaWdpdFtpLTFdOwogICAgICAgIGlmICh4ICE9IHkpCiAgICAgICAgICAgIHJldHVybiAoeCA8IHkpID8gLTEgOiAxOwogICAgfQogICAgcmV0dXJuIDA7Cn0KCnZvaWQgX2JpZ2ludF9hZGRfbG93ZXIoQmlnaW50ICpjLCBjb25zdCBCaWdpbnQgKmEsIGNvbnN0IEJpZ2ludCAqYikKewogICAgaWYgKGEtPmNvdW50IDwgYi0+Y291bnQpCiAgICB7CiAgICAgICAgY29uc3QgQmlnaW50ICp0ID0gYTsgYSA9IGI7IGIgPSB0OwogICAgfQoKICAgIGJpZ2ludF9zZXQoYywgYSk7CiAgICBpbnQgY2FycnkgPSBfZGlnaXRfYWRkKGMtPmRpZ2l0LCBjLT5jb3VudCwgYi0+ZGlnaXQsIGItPmNvdW50KTsKICAgIGlmIChjYXJyeSAhPSAwKQogICAgICAgIF9iaWdpbnRfYXBwZW5kKGMsIGNhcnJ5KTsKICAgIF9iaWdpbnRfbm9ybWFsaXplKGMpOwp9Cgp2b2lkIF9iaWdpbnRfc3ViX2xvd2VyKEJpZ2ludCAqYywgY29uc3QgQmlnaW50ICphLCBjb25zdCBCaWdpbnQgKmIpCnsKICAgIGludCBzaWduID0gMDsKCiAgICBpZiAoX2JpZ2ludF9jb21wYXJlKGEsIGIpIDwgMCkKICAgIHsKICAgICAgICBjb25zdCBCaWdpbnQgKnQgPSBhOyBhID0gYjsgYiA9IHQ7CiAgICAgICAgc2lnbiA9IDE7CiAgICB9CgogICAgYmlnaW50X3NldChjLCBhKTsKICAgIF9kaWdpdF9zdWIoYy0+ZGlnaXQsIGMtPmNvdW50LCBiLT5kaWdpdCwgYi0+Y291bnQpOwogICAgYy0+c2lnbiA9IHNpZ247CiAgICBfYmlnaW50X25vcm1hbGl6ZShjKTsKfQoKdm9pZCBfYmlnaW50X2FkZF9vcl9zdWIoQmlnaW50ICpjLCBjb25zdCBCaWdpbnQgKmEsIGNvbnN0IEJpZ2ludCAqYiwgaW50IGludmVydCkKewogICAgaWYgKChhLT5zaWduID09IGItPnNpZ24pIF4gaW52ZXJ0KQogICAgewogICAgICAgIF9iaWdpbnRfYWRkX2xvd2VyKGMsIGEsIGIpOwogICAgICAgIGMtPnNpZ24gPSBhLT5zaWduOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIGlmIChhLT5zaWduKQogICAgICAgICAgICBfYmlnaW50X3N1Yl9sb3dlcihjLCBiLCBhKTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIF9iaWdpbnRfc3ViX2xvd2VyKGMsIGEsIGIpOwogICAgfQp9Cgp2b2lkIGJpZ2ludF9hZGQoQmlnaW50ICpjLCBjb25zdCBCaWdpbnQgKmEsIGNvbnN0IEJpZ2ludCAqYikKewogICAgX2JpZ2ludF9hZGRfb3Jfc3ViKGMsIGEsIGIsIDApOwp9Cgp2b2lkIGJpZ2ludF9zdWIoQmlnaW50ICpjLCBjb25zdCBCaWdpbnQgKmEsIGNvbnN0IEJpZ2ludCAqYikKewogICAgX2JpZ2ludF9hZGRfb3Jfc3ViKGMsIGEsIGIsIDEpOwp9Cgp2b2lkIGJpZ2ludF9wcmludChjb25zdCBCaWdpbnQgKmEpCnsKICAgIGlmIChhLT5zaWduKQogICAgICAgIHB1dGNoYXIoJy0nKTsKICAgIGZvciAoaW50IGkgPSBhLT5jb3VudDsgaSA+IDA7IGktLSkKICAgICAgICBwcmludGYoIiVkIiwgYS0+ZGlnaXRbaS0xXSk7IC8vIEJhc2UtMTAKICAgIHB1dGNoYXIoJ1xuJyk7Cn0KCi8vIC4uCgp2b2lkIGZhdGFsZXJyb3IoY29uc3QgY2hhciAqbXNnKQp7CiAgICBmcHJpbnRmKHN0ZGVyciwgIkVycm9yOiAlc1xuIiwgbXNnKTsKICAgIGV4aXQoMSk7Cn0KCmludCBfYmlnaW50X3RvX3NpKGNvbnN0IEJpZ2ludCAqYSkKewogICAgaW50IHJlc3VsdCA9IDA7CiAgICBmb3IgKGludCBpID0gYS0+Y291bnQ7IGkgPiAwOyBpLS0pCiAgICB7CiAgICAgICAgaWYgKF9fYnVpbHRpbl9tdWxfb3ZlcmZsb3cocmVzdWx0LCBJTlRFUk5BTF9CQVNFLCAmcmVzdWx0KSB8fAogICAgICAgICAgICBfX2J1aWx0aW5fYWRkX292ZXJmbG93KHJlc3VsdCwgYS0+ZGlnaXRbaS0xXSwgJnJlc3VsdCkpCiAgICAgICAgICAgIGZhdGFsZXJyb3IoIm92ZXJmbG93Iik7CiAgICB9CiAgICByZXR1cm4gYS0+c2lnbiA/IC1yZXN1bHQgOiByZXN1bHQ7Cn0KCnZvaWQgdGVzdChpbnQgbikKewogICAgQmlnaW50IHQ7IGJpZ2ludF9pbml0KCZ0KTsKCiAgICBmb3IgKGludCB4ID0gLW47IHggPD0gbjsgeCsrKQogICAgICAgIGZvciAoaW50IHkgPSAtbjsgeSA8PSBuOyB5KyspCiAgICAgICAgewogICAgICAgICAgICBCaWdpbnQgYTsgYmlnaW50X2luaXRfc2V0X3NpKCZhLCB4KTsKICAgICAgICAgICAgQmlnaW50IGI7IGJpZ2ludF9pbml0X3NldF9zaSgmYiwgeSk7CiAgICAgICAgICAgIGJpZ2ludF9hZGQoJnQsICZhLCAmYik7CiAgICAgICAgICAgIGFzc2VydChfYmlnaW50X3RvX3NpKCZ0KSA9PSB4K3kpOwogICAgICAgICAgICBiaWdpbnRfc3ViKCZ0LCAmYSwgJmIpOwogICAgICAgICAgICBhc3NlcnQoX2JpZ2ludF90b19zaSgmdCkgPT0geC15KTsKICAgICAgICAgICAgYmlnaW50X2NsZWFyKCZhKTsKICAgICAgICAgICAgYmlnaW50X2NsZWFyKCZiKTsKICAgICAgICB9CgogICAgYmlnaW50X2NsZWFyKCZ0KTsKfQoKdm9pZCBmaWJvbmFjY2koaW50IG4sIEJpZ2ludCAqcmVzdWx0KQp7CiAgICBCaWdpbnQgYTsgYmlnaW50X2luaXRfc2V0X3NpKCZhLCAwKTsKICAgIEJpZ2ludCBiOyBiaWdpbnRfaW5pdF9zZXRfc2koJmIsIDEpOwogICAgQmlnaW50IHQ7IGJpZ2ludF9pbml0KCZ0KTsKCiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykKICAgIHsKICAgICAgICBiaWdpbnRfYWRkKCZ0LCAmYSwgJmIpOwogICAgICAgIGJpZ2ludF9zd2FwKCZiLCAmYSk7IC8vIGEgLT4gYgogICAgICAgIGJpZ2ludF9zd2FwKCZhLCAmdCk7IC8vIHQgLT4gYQogICAgfQoKICAgIGJpZ2ludF9zd2FwKCZhLCByZXN1bHQpOwoKICAgIGJpZ2ludF9jbGVhcigmYSk7CiAgICBiaWdpbnRfY2xlYXIoJmIpOwogICAgYmlnaW50X2NsZWFyKCZ0KTsKfQoKaW50IG1haW4odm9pZCkKewogICAgdGVzdCgxMjMpOwoKICAgIEJpZ2ludCBhOyBiaWdpbnRfaW5pdCgmYSk7CiAgICBCaWdpbnQgYjsgYmlnaW50X2luaXQoJmIpOwogICAgQmlnaW50IGM7IGJpZ2ludF9pbml0KCZjKTsKCiAgICBmaWJvbmFjY2koMjAyLCAmYSk7CiAgICBmaWJvbmFjY2koMTAxLCAmYik7CgogICAgYmlnaW50X3N1YigmYywgJmEsICZiKTsKCiAgICBiaWdpbnRfcHJpbnQoJmEpOwogICAgYmlnaW50X3ByaW50KCZiKTsKICAgIGJpZ2ludF9wcmludCgmYyk7CgogICAgYmlnaW50X2NsZWFyKCZhKTsKICAgIGJpZ2ludF9jbGVhcigmYik7CiAgICBiaWdpbnRfY2xlYXIoJmMpOwogICAgcmV0dXJuIDA7Cn0=