#include <iostream>
#include <cstdlib>
#include <cstdint>
#include <cassert>
#include <string>
typedef int64_t CONTAINER;
unsigned int BIT = 62; /* BIT <= 64bit - 2bit = 62bit */
CONTAINER CMASK = 1ULL << BIT;
CONTAINER BMASK = CMASK - 1;
namespace QZ {
class mpz_base_class {
private:
unsigned int n;
CONTAINER *b;
private:
static void LeftShift(mpz_base_class &a);
static void RightShift(mpz_base_class &a, int &lsb_out);
static void LeftShift2(int &msb, mpz_base_class &a);
static void LeftShift3(mpz_base_class &a, int msb);
protected:
static bool iszero(mpz_base_class const &n);
public:
mpz_base_class(); //
virtual ~mpz_base_class();
mpz_base_class(const signed long c);
mpz_base_class(mpz_base_class const &ob);
mpz_base_class &operator=(mpz_base_class const &ob);
friend bool operator==(mpz_base_class const &a, mpz_base_class const &b);
friend bool operator!=(mpz_base_class const &a, mpz_base_class const &b) { return !(a == b); }
friend std::ostream &operator<<(std::ostream &stream, mpz_base_class c);
friend mpz_base_class operator+(mpz_base_class const &a, mpz_base_class const &b);
friend mpz_base_class operator-(mpz_base_class const &a, mpz_base_class const &b);
friend bool operator<(mpz_base_class const &a, mpz_base_class const &b);
friend bool operator<=(mpz_base_class const &a, mpz_base_class const &b) { return (a < b) ? true : (a == b) ? true : false; }
friend bool operator>(mpz_base_class const &a, mpz_base_class const &b) { return (a < b) ? false : (a == b) ? false : true; }
friend bool operator>=(mpz_base_class const &a, mpz_base_class const &b) { return (a < b) ? false : (a == b) ? true : true; }
friend mpz_base_class operator*(mpz_base_class const &a, mpz_base_class const &b);
friend void div2(mpz_base_class const &a, mpz_base_class const &b, mpz_base_class &q, mpz_base_class &r);
friend mpz_base_class operator/(mpz_base_class const &a, mpz_base_class const &b) { mpz_base_class q, r; div2(a, b, q, r); return q; }
friend mpz_base_class operator%(mpz_base_class const &a, mpz_base_class const &b) { mpz_base_class q, r; div2(a, b, q, r); return r; }
bool testBit(int n);
mpz_base_class operator>>(int n) { int dmy; mpz_base_class r = *this; for (int i = 0; i < n; i++) RightShift(r, dmy); return r; }
mpz_base_class operator<<(int n) { mpz_base_class r = *this; for (int i = 0; i < n; i++) LeftShift(r); return r; }
int bitLength();
unsigned int get_mpzclass_n() { return this->n; }
CONTAINER *get_mpzclass_b() { return this->b; }
virtual void dump() const {
std::cout << "n = " << this->n << ": ";
for (unsigned int i = 0; i < this->n; i++)
std::cout << i << ":" << this->b[i] << ",";
std::cout << std::endl;
}
void test42() {
// *this == 4 + 256;
this->b[2] = 0;
}
};
class mpz_class : public mpz_base_class {
private:
bool negative;
public:
mpz_class();
~mpz_class();
mpz_class(const signed long c);
mpz_class(mpz_class const &ob);
mpz_class &operator=(mpz_class const &ob);
mpz_class &operator=(mpz_base_class const &ob);
friend bool operator==(mpz_class const &a, mpz_class const &b);
friend bool operator!=(mpz_class const &a, mpz_class const &b) { return !(a == b); }
friend std::ostream &operator<<(std::ostream &stream, mpz_class c);
friend mpz_class operator-(mpz_class const &a);
friend bool operator<(mpz_class const &a, mpz_class const &b);
friend bool operator<=(mpz_class const &a, mpz_class const &b) { return (a < b) ? true : (a == b) ? true : false; }
friend bool operator>(mpz_class const &a, mpz_class const &b) { return (a < b) ? false : (a == b) ? false : true; }
friend bool operator>=(mpz_class const &a, mpz_class const &b) { return (a < b) ? false : (a == b) ? true : true; }
friend mpz_class operator+(mpz_class const &a, mpz_class const &b);
friend mpz_class operator-(mpz_class const &a, mpz_class const &b);
friend mpz_class operator*(mpz_class const &a, mpz_class const &b);
friend mpz_class operator/(mpz_class const &a, mpz_class const &b);
friend mpz_class operator%(mpz_class const &a, mpz_class const &b);
mpz_class &operator+=(mpz_class const &n) { *this = *this + n; return *this; }
mpz_class &operator-=(mpz_class const &n) { *this = *this - n; return *this; }
mpz_class &operator*=(mpz_class const &n) { *this = *this * n; return *this; }
mpz_class &operator/=(mpz_class const &n) { *this = *this / n; return *this; }
mpz_class &operator%=(mpz_class const &n) { *this = *this % n; return *this; }
mpz_class operator>>(int n) { mpz_class r; r = this->mpz_base_class::operator>>(n); return r; }
mpz_class operator<<(int n) { mpz_class r; r = this->mpz_base_class::operator<<(n); return r; }
bool get_mpzclass_negative() { return this->negative; }
virtual void dump() const {
mpz_base_class::dump();
std::cout << "sign = " << this->negative << std::endl;
}
};
mpz_base_class::mpz_base_class() {
// std::cout << "mpz_base_class constructor1" << std::endl;
this->n = 0;
this->b = 0;
}
mpz_base_class::~mpz_base_class() {
// std::cout << "mpz_base_class destructor" << std::endl;
if (this->b) delete [] this->b;
this->n = 0;
this->b = 0;
}
mpz_base_class::mpz_base_class(const signed long c) {
// std::cout << "mpz_base_class constructor2" << std::endl;
signed long cc;
cc = c;
if (c == 0) {
this->n = 1;
this->b = new CONTAINER [1];
this->b[0] = 0;
return;
}
if (c < 0) {
cc = -c; /* for mpz_class not for mpz_base_class */
}
assert(cc > 0);
CONTAINER *newbody;
unsigned int i, j, r, pos;
this->b = 0;
this->n = 0;
while (cc > 0) {
r = 0;
pos = 1;
for (i = 0; i < BIT; i++) {
if ((cc & 1) != 0) {
r = (r | pos);
} else {
}
pos = pos * 2;
cc = cc / 2;
}
newbody = new CONTAINER [this->n + 1];
for (j = 0; j < this->n; j++)
newbody[j] = this->b[j];
newbody[j] = r;
delete [] this->b;
this->b = newbody;
this->n++;
}
assert(this->n != 0);
}
mpz_base_class::mpz_base_class(const mpz_base_class &ob) {
// std::cout << "mpz_base_class constructor3" << std::endl;
this->n = ob.n;
if (ob.n == 0) {
this->b = 0;
} else {
this->b = new CONTAINER [ob.n];
for (unsigned int i = 0; i < ob.n; i++)
this->b[i] = ob.b[i];
}
assert((this->n == 0 && this->b == 0) || (this->n > 0 && this->b != 0));
}
mpz_base_class &mpz_base_class::operator=(const mpz_base_class &ob) {
// std::cout << "mpz_base_class operator=" << std::endl;
CONTAINER *org_b = this->b; // for checking self-assignment
this->n = ob.n;
if (ob.n == 0) {
this->b = 0;
delete [] org_b;
} else {
this->b = new CONTAINER [ob.n];
for (unsigned int i = 0; i < ob.n; i++)
this->b[i] = ob.b[i];
delete [] org_b;
}
assert((this->n == 0 && this->b == 0) || (this->n > 0 && this->b != 0));
return *this;
}
bool operator==(mpz_base_class const &a, mpz_base_class const &b) {
// std::cout << "mpz_base_class operator==" << std::endl;
unsigned int i, less;
bool isEqual = true;
if (a.n < b.n)
less = a.n;
else
less = b.n;
for (i = 0; i < less; i++)
if (a.b[i] != b.b[i]) {
isEqual = false;
goto label;
}
if (a.n < b.n) {
for (; i < b.n; i++)
if (b.b[i] != 0) {
isEqual = false;
goto label;
}
} else {
for (; i < a.n; i++)
if (a.b[i] != 0) { // be carefull! not b.b[] but a.b[]
isEqual = false;
goto label;
}
}
label:
return isEqual;
}
std::ostream &operator<<(std::ostream &stream, mpz_base_class c) {
// std::cout << "mpz_base_class operator<<" << std::endl;
std::basic_string<char> mod10;
mpz_base_class q, n;
int mod;
bool fzero;
fzero = true;
n = c;
for(;;) {
/* div10(n, q, mod); */
{
q = n;
mod = 0;
for (unsigned int i = 0; i < n.n * BIT; i++) {
/* shift_div(mod, q); */
{
unsigned int cy, i;
cy = 0;
for (i = 0; i < n.n; i++) {
q.b[i] = q.b[i] << 1;
if (cy)
q.b[i] = q.b[i] | 0x01;
cy = (q.b[i] >> BIT);
q.b[i] = q.b[i] & BMASK;
}
mod = mod << 1;
if (cy)
mod = mod | 0x01;
}
if (mod >= 10) {
q.b[0] = q.b[0] | 0x01;
mod = mod - 10;
}
}
}
if (mpz_class::iszero(q) && mod == 0)
break;
mod10 = (char)('0' + mod) + mod10;
fzero = false;
n = q;
}
if (fzero)
stream << '0';
else
stream << mod10;
return stream;
}
mpz_base_class operator+(mpz_base_class const &a, mpz_base_class const &b) {
mpz_base_class r;
mpz_base_class const * more_ab;
unsigned int less_n;
if (a.n > b.n) {
r.n = a.n;
more_ab = &a;
less_n = b.n;
} else {
r.n = b.n;
more_ab = &b;
less_n = a.n;
}
r.b = new CONTAINER [r.n];
unsigned int i, carry = 0;
for (i = 0; i < less_n; i++) {
CONTAINER s = a.b[i] + b.b[i] + carry;
if (s >= CMASK) {
carry = 1;
r.b[i] = (s & BMASK);
} else {
carry = 0;
r.b[i] = s; /* need */
}
}
for (;i < r.n; i++) {
CONTAINER s = more_ab->b[i] + carry;
if (s >= CMASK) {
carry = 1;
r.b[i] = (s & BMASK); /* need */
} else {
carry = 0;
r.b[i] = (s & BMASK); /* need */ /* do not to insert break keyword.*/
}
}
if (carry) {
CONTAINER *new_body = new CONTAINER [r.n + 1];
for (i = 0; i < r.n; i++)
new_body[i] = r.b[i];
new_body[i] = carry;
delete [] r.b;
r.b = new_body;
// r.b[r.n] = 1; /* NOT need */
r.n++;
}
return r;
}
bool mpz_base_class::iszero(mpz_base_class const &n) {
bool isZero = true;
for (unsigned int i = 0; i < n.n; i++)
if (n.b[i] != 0) {
isZero = false;
break;
}
return isZero;
}
mpz_base_class operator-(mpz_base_class const &a, mpz_base_class const &b) {
int vCount, moreCount, i;
CONTAINER diff;
int borrowR = 0;
bool flagMore, flagLess;
mpz_base_class r;
flagMore = false;
flagLess = false;
moreCount = a.n;
vCount = a.n;
r = a;
if (a.n > b.n) {
flagMore = true;
vCount = b.n;
moreCount = a.n;
r = a;
}
if (a.n < b.n) {
flagLess = true;
vCount = a.n;
moreCount = b.n;
r = b;
}
borrowR = 0;
for (i = 0; i < vCount; i++) {
diff = a.b[i] - b.b[i] - borrowR;
if (diff < 0) {
borrowR = 1;
r.b[i] = diff + CMASK;
} else {
borrowR = 0;
r.b[i] = diff;
}
}
if (flagMore) {
for (;i < moreCount; i++) {
diff = a.b[i] - borrowR;
if (diff < 0) {
borrowR = 1;
r.b[i] = diff + CMASK;
} else {
borrowR = 0;
r.b[i] = diff;
}
}
}
if (flagLess) {
for (;i < moreCount; i++) {
if (b.b[i] > 0) {
borrowR = 1;
}
}
}
if (borrowR > 0) throw std::underflow_error("negative value.");
return r;
}
bool operator<(mpz_base_class const &a, mpz_base_class const &b) { // if a < b then true
try {
mpz_base_class r = a - b;
} catch (std::underflow_error &e) {
return true;
}
return false;
}
mpz_base_class operator*(mpz_base_class const &a, mpz_base_class const &b) {
mpz_base_class Rshift = b;
mpz_base_class Lshift = a;
mpz_base_class r = 0;
int lsb;
while (!mpz_base_class::iszero(Rshift)) {
mpz_base_class::RightShift(Rshift, lsb);
if (lsb) {
r = r + Lshift;
}
mpz_base_class::LeftShift(Lshift);
}
return r;
}
void mpz_base_class::LeftShift(mpz_base_class &a) {
unsigned int i, msb;
msb = 0;
for (i = 0; i < a.n; i++) {
a.b[i] *= 2;
if (msb > 0)
a.b[i] = (a.b[i] | 0x01);
if (a.b[i] > BMASK) {
msb = 1;
a.b[i] -= CMASK;
} else {
msb = 0;
}
}
if (msb > 0) {
CONTAINER *newbody;
newbody = new CONTAINER [a.n + 1];
newbody[a.n] = 1;
for (unsigned int i = 0; i < a.n; i++) {
newbody[i] = a.b[i];
}
a.n++;
delete [] a.b;
a.b = newbody;
}
}
void mpz_base_class::RightShift(mpz_base_class &a, int &lsb_out) {
int i, lsb;
lsb = 0;
for (i = a.n - 1; i >= 0; --i) {
if (lsb > 0)
a.b[i] = (a.b[i] | CMASK);
if ((a.b[i] & 0x01) > 0)
lsb = 1;
else
lsb = 0;
a.b[i] /= 2;
}
lsb_out = lsb;
if (a.b[a.n - 1] == 0) {
CONTAINER *newbody;
newbody = new CONTAINER [a.n - 1];
for (unsigned int i = 0; i < a.n - 1; i++)
newbody[i] = a.b[i];
a.n--;
delete [] a.b;
a.b = newbody;
}
}
void mpz_base_class::LeftShift2(int &msb, mpz_base_class &a) {
unsigned int i, msb_v;
msb_v = 0;
for (i = 0; i < a.n; i++) {
a.b[i] *= 2;
if (msb_v > 0)
a.b[i] = (a.b[i] | 0x01);
if (a.b[i] > BMASK) {
msb_v = 1;
a.b[i] -= CMASK;
} else {
msb_v = 0;
}
}
msb = msb_v;
}
void mpz_base_class::LeftShift3(mpz_base_class &a, int msb) {
unsigned int i, msb_v;
msb_v = msb;
for (i = 0; i < a.n; i++) {
a.b[i] *= 2;
if (msb_v > 0)
a.b[i] = (a.b[i] | 0x01);
if (a.b[i] > BMASK) {
msb_v = 1;
a.b[i] -= CMASK;
} else {
msb_v = 0;
}
}
if (msb_v > 0) {
CONTAINER *newbody;
newbody = new CONTAINER [a.n + 1];
newbody[a.n] = 1;
for (unsigned int i = 0; i < a.n; i++) {
newbody[i] = a.b[i];
}
a.n++;
delete [] a.b;
a.b = newbody;
}
}
void div2(mpz_base_class const &a, mpz_base_class const &b, mpz_base_class &q, mpz_base_class &r) {
if (b == mpz_base_class(0)) {
std::cout << "null devided." << std::endl;
return;
}
/* LeftRest <- LeftShiftBuff */
mpz_base_class LeftRest(0);
mpz_base_class LeftShiftBuff = a;
mpz_base_class Quotient(0);
int msb, lsb;
msb = 0;
int n = a.n * BIT;
while (n > 0) {
// std::cout << "LeftShiftBuff=" << LeftShiftBuff << std::endl;
// std::cout << "LeftRest=" << LeftRest << std::endl;
mpz_base_class::LeftShift2(msb, LeftShiftBuff);
mpz_base_class::LeftShift3(LeftRest, msb);
lsb = 0;
if (b < LeftRest || b == LeftRest) {
LeftRest = LeftRest - b;
lsb = 1;
}
mpz_base_class::LeftShift3(Quotient, lsb);
// std::cout << "Quotient=" << Quotient << std::endl;
n--;
}
q = Quotient;
r = LeftRest;
}
bool mpz_base_class::testBit(int n) {
unsigned int test_byte = n / BIT;
int test_mask = 1 << (n % BIT);
if (test_byte >= this->n) return false;
if ((this->b[test_byte] & test_mask) > 0) return true;
return false;
}
/*----------------------------------------------*/
mpz_class::mpz_class() : mpz_base_class() {
// std::cout << "mpz_class constructor1" << std::endl;
this->negative = false;
}
mpz_class::~mpz_class() {
// std::cout << "mpz_class destructor1" << std::endl;
this->negative = false;
}
mpz_class::mpz_class(const signed long c) : mpz_base_class(c) {
// std::cout << "mpz_class costructor2" << std::endl;
if (c >= 0) {
this->negative = false;
} else {
this->negative = true;
}
}
mpz_class::mpz_class(const mpz_class &ob) : mpz_base_class(ob) {
// std::cout << "mpz_class constructor3" << std::endl;
this->negative = ob.negative;
}
mpz_class &mpz_class::operator=(mpz_class const &ob) {
// std::cout << "mpz_class operator=(mpz_class&)" << std::endl;
this->mpz_base_class::operator=(ob);
this->negative = ob.negative;
return *this;
}
mpz_class &mpz_class::operator=(mpz_base_class const &ob) {
// std::cout << "mpz_class operator=(mpz_base_class&)" << std::endl;
this->mpz_base_class::operator=(ob);
this->negative = false;
return *this;
}
bool operator==(mpz_class const &a, mpz_class const &b) {
// std::cout << "mpz_class::operator==" << std::endl;
if (a.negative == b.negative)
return operator==((mpz_base_class)a, (mpz_base_class)b);
return false;
}
std::ostream &operator<<(std::ostream &stream, mpz_class c) {
if (c.negative)
stream << '-';
return operator<<(stream, (mpz_base_class)c);
}
mpz_class operator-(mpz_class const &a) {
mpz_class r = a;
r.negative = !r.negative;
return r;
}
mpz_class operator+(mpz_class const &a, mpz_class const &b) {
mpz_class r;
if (!a.negative && !b.negative) {
r = (mpz_base_class)a + (mpz_base_class)b; /* operator=(mpz_class, mpz_base_class) */
r.negative = false;
} else if (a.negative && !b.negative) {
mpz_class t = -a; assert(t.negative == false);
if (operator<((mpz_base_class)t, (mpz_base_class)b) == true) { /* t < b */
r = (mpz_base_class)b - (mpz_base_class)t;
r.negative = false;
} else { /* b < t */
r = (mpz_base_class)t - (mpz_base_class)b;
r.negative = true;
}
if (mpz_base_class::iszero(r))
r.negative = false;
} else if (!a.negative && b.negative) {
mpz_class t = -b; assert(t.negative == false);
if (operator<((mpz_base_class)t, (mpz_base_class)a) == true) { /* t < a */
r = (mpz_base_class)a - (mpz_base_class)t;
r.negative = false;
} else { /* a < t */
r = (mpz_base_class)t - (mpz_base_class)a;
r.negative = true;
}
if (mpz_base_class::iszero(r))
r.negative = false;
} else if (a.negative && b.negative) {
QZ::mpz_class aa = a, bb = b;
aa = -aa; bb = -bb;
r = (mpz_base_class)aa + (mpz_base_class)bb;
r.negative = true;
if (mpz_base_class::iszero(r))
r.negative = false;
}
return r;
}
mpz_class operator-(mpz_class const &a, mpz_class const &b) {
QZ::mpz_class r = -b;
return a + r;
}
bool operator<(mpz_class const &a, mpz_class const &b) {
QZ::mpz_class r = a - b;
if (r.negative)
return true;
return false;
}
mpz_class operator*(mpz_class const &a, mpz_class const &b) {
mpz_class x = (a > 0) ? a : -a;
mpz_class y = (b > 0) ? b : -b;
assert(x >= 0 && y >= 0);
mpz_class r;
r = (mpz_base_class)x * (mpz_base_class)y;
if (a >= 0 && b >= 0) {
} else if (a < 0 && b >= 0) {
r = -r;
} else if (a >= 0 && b < 0) {
r = -r;
} if (a < 0 && b < 0) {
}
if (mpz_base_class::iszero(r)) r.negative = false;
return r;
}
mpz_class operator/(mpz_class const &a, mpz_class const &b) {
mpz_class x = (a >= 0) ? a : -a;
mpz_class y = (b >= 0) ? b : -b;
mpz_class q, r;
div2(x, y, q, r);
if (a >= 0 && b >= 0) {
} else if (a < 0 && b >= 0) {
q = -q; r = -r;
if (mpz_base_class::iszero(q)) q.negative = false;
if (mpz_base_class::iszero(r)) r.negative = false;
} else if (a >= 0 && b < 0) {
q = -q;
if (mpz_base_class::iszero(q)) q.negative = false;
if (mpz_base_class::iszero(r)) r.negative = false;
} else if (a < 0 && b < 0) {
r = -r;
if (mpz_base_class::iszero(q)) q.negative = false;
if (mpz_base_class::iszero(r)) q.negative = false;
}
return q;
}
mpz_class operator%(mpz_class const &a, mpz_class const &b) {
mpz_class x = (a >= 0) ? a : -a;
mpz_class y = (b >= 0) ? b : -b;
mpz_class q, r;
div2(x, y, q, r);
if (a >= 0 && b >= 0) {
} else if (a < 0 && b >= 0) {
q = -q; r = -r;
if (mpz_base_class::iszero(q)) q.negative = false;
if (mpz_base_class::iszero(r)) r.negative = false;
} else if (a >= 0 && b < 0) {
q = -q;
if (mpz_base_class::iszero(q)) q.negative = false;
if (mpz_base_class::iszero(r)) r.negative = false;
} else if (a < 0 && b < 0) {
r = -r;
if (mpz_base_class::iszero(q)) q.negative = false;
if (mpz_base_class::iszero(r)) r.negative = false;
}
return r;
}
int mpz_base_class::bitLength() {
if (this->n == 0)
return 0;
int n = this->n;
int i;
for (i = n - 1; !(b[i] > 0); --i) {}
CONTAINER msb = this->b[i];
int j = 0;
while (msb > 0) {
j++;
msb = msb >> 1;
}
return BIT * i + j;
}
} /* namespace QZ */
/*-----------------------------------------------------------------*/
QZ::mpz_class euclid(QZ::mpz_class a, QZ::mpz_class b) {
if (b == 0) return a;
return euclid(b, a % b);
}
class Ratio {
QZ::mpz_class a;
QZ::mpz_class b;
public:
Ratio() : a(0), b(0) {}
Ratio(QZ::mpz_class x, QZ::mpz_class y) : a(x), b(y) {}
friend std::ostream &operator<<(std::ostream &s, Ratio r) {
if (r.b == 1)
s << r.a;
else
s << "(" << r.a << "/" << r.b << ")";
return s;
}
friend Ratio operator+(Ratio const &x, Ratio const &y) {
Ratio r;
QZ::mpz_class c = euclid(x.b, y.b);
QZ::mpz_class zy = x.b / c;
QZ::mpz_class zx = y.b / c;
r.b = y.b * zy;
assert(r.b == x.b * zx);
r.a = x.a * zx + y.a * zy;
c = euclid(r.a, r.b);
r.a = r.a / c;
r.b = r.b / c;
return r;
}
friend Ratio operator-(Ratio const &x, Ratio const &y) {
Ratio r;
QZ::mpz_class c = euclid(x.b, y.b);
QZ::mpz_class zy = x.b / c;
QZ::mpz_class zx = y.b / c;
r.b = y.b * zy;
assert(r.b == x.b * zx);
r.a = x.a * zx - y.a * zy;
c = euclid(r.a, r.b);
r.a = r.a / c;
r.b = r.b / c;
return r;
}
friend Ratio operator*(Ratio const &x, Ratio const &y) {
Ratio r;
QZ::mpz_class xa, xb, ya, yb;
QZ::mpz_class c1 = euclid(x.a, y.b);
QZ::mpz_class c2 = euclid(x.b, y.a);
xa = x.a / c1; yb = y.b / c1;
xb = x.b / c2; ya = y.a / c2;
r.a = xa * ya;
r.b = xb * yb;
return r;
}
};
class Field5 {
Ratio a;
Ratio b;
public:
Field5() : a(Ratio()), b(Ratio()) {}
Field5(Ratio x, Ratio y) : a(x), b(y) {}
friend std::ostream &operator<<(std::ostream &s, Field5 r) {
// s << "(" << r.a << "," << r.b << ")";
s << r.b;
return s;
}
friend Field5 operator-(Field5 const &x, Field5 const &y) {
Field5 r;
r.a = x.a - y.a; r.b = x.b - y.b;
return r;
}
friend Field5 operator*(Field5 const &x, Field5 const &y) {
Field5 r;
r.a = x.a * y.a + Ratio(5, 1) * x.b * y.b;
r.b = x.a * y.b + x.b * y.a;
return r;
}
};
QZ::mpz_class fib(int n) {
static QZ::mpz_class t1 = 1, t2 = 1;
if (n == 1 || n == 2)
return 1;
QZ::mpz_class s = t1 + t2;
t1 = t2; t2 = s;
return s;
}
Field5 Field5Power(Field5 a, int n) { /* =a^n */
unsigned int mask = 1 << (sizeof(int) * 8 - 1);
Field5 r(Ratio(1, 1), Ratio(0, 1));
for (;;) {
if ((n & mask) > 0)
r = r * a;
mask = (mask >> 1);
/* out of loop */
if (mask == 0)
break;
r = r * r;
}
return r;
}
int const M = 200;
int main() {
Field5 phi1(Ratio(1, 2), Ratio(1, 2));
Field5 phi2(Ratio(1, 2), Ratio(-1, 2));
for (int n = 1; n <= M; n++) {
QZ::mpz_class s = fib(n);
Field5 r1, r2, r3;
r1 = Field5Power(phi1, n);
r2 = Field5Power(phi2, n);
r3 = r1 - r2;
std::cout << n << ":: " << s << " : " << r3 << std::endl;
}
return 0;
}
/* end */