3 * @brief Wraps to GMP mpq_t type using inlines
16 Gmprat(double d=0) {mpq_init(m_op); mpq_set_d(m_op, d);}
17 //Gmprat(int64_t p = 0, int64_t q = 1) {mpq_init(m_op); mpq_set_si(m_op, p, q);}
18 //Gmprat(const std::string & str, int base=10) {mpq_init_set_str(m_op, str.c_str(), base);}
19 Gmprat(const Gmprat & cpy) {mpq_init(m_op); mpq_set(m_op, cpy.m_op);}
20 virtual ~Gmprat() {mpq_clear(m_op);}
22 //operator int64_t() const {return mpq_get_si(m_op);}
23 //operator uint64_t() const {return mpq_get_ui(m_op);}
24 operator double() const {return mpq_get_d(m_op);}
25 //operator float() const {return (float)ToDouble();}
26 double ToDouble() const {return mpq_get_d(m_op);}
27 std::string Str() const
29 //TODO: Make less hacky, if we care.
30 // Convert to scientific notation
33 return "-" + operator-().Str();
40 double C = pow(10.0, p - P);
45 //s << "("<<ToDouble()<<")";
51 // log(a/b) = log(a) - log(b)
52 // And if a is represented in base B as:
53 // a = a_N B^N + a_{N-1} B^{N-1} + ... + a_0
54 // => log(a) \approx log(a_N B^N)
55 // = log(a_N) + N log(B)
56 // where B is the base; ie number of values representable with one digit, ie: ULONG_MAX
58 static double logB = log(ULONG_MAX); // compiler should optimise this anyway?
60 // Undefined logs (should probably return NAN if -ve, not -INFINITY, but meh)
61 if (mpz_get_ui(mpq_numref(m_op)) == 0 || mpz_sgn(mpq_numref(m_op)) < 0)
65 double lognum = log(mpq_numref(m_op)->_mp_d[abs(mpq_numref(m_op)->_mp_size) - 1]);
66 lognum += (abs(mpq_numref(m_op)->_mp_size)-1) * logB;
68 // Subtract log of denominator, if it exists
69 // Note that denominator is not explicitly set to 1, this caused a lot of headache
70 if (abs(mpq_denref(m_op)->_mp_size) > 0)
72 lognum -= log(mpq_denref(m_op)->_mp_d[abs(mpq_denref(m_op)->_mp_size)-1]);
73 lognum -= (abs(mpq_denref(m_op)->_mp_size)-1) * logB;
78 double Log10() const {return LogE() / log(10.0);}
80 bool Negative() const {return (mpz_sgn(mpq_numref(m_op)) < 0);}
82 Gmprat & operator=(const Gmprat & equ) {mpq_set(m_op, equ.m_op); return *this;}
83 Gmprat & operator=(const double & equ) {mpq_set_d(m_op, equ); return *this;}
84 Gmprat & operator+=(const Gmprat & add) {mpq_add(m_op, m_op, add.m_op); return *this;}
85 Gmprat & operator-=(const Gmprat & sub) {mpq_sub(m_op, m_op, sub.m_op); return *this;}
86 Gmprat & operator*=(const Gmprat & mul) {mpq_mul(m_op, m_op, mul.m_op); return *this;}
87 Gmprat & operator/=(const Gmprat & div) {mpq_div(m_op, m_op, div.m_op); return *this;}
89 Gmprat operator+(const Gmprat & add) const {Gmprat a(*this); a += add; return a;}
90 Gmprat operator-(const Gmprat & sub) const {Gmprat a(*this); a -= sub; return a;}
91 Gmprat operator*(const Gmprat & mul) const {Gmprat a(*this); a *= mul; return a;}
92 Gmprat operator/(const Gmprat & div) const {Gmprat a(*this); a /= div; return a;}
93 //Gmprat operator%(const Gmprat & div) const {Gmprat a(*this); mpq_mod(a.m_op, a.m_op, div.m_op); return a;}
94 Gmprat operator-() const {return (Gmprat(0L)-*this);}
97 bool operator==(const Gmprat & cmp) const {return mpq_cmp(m_op, cmp.m_op) == 0;}
98 bool operator!=(const Gmprat & cmp) const {return mpq_cmp(m_op, cmp.m_op) != 0;}
99 bool operator<(const Gmprat & cmp) const {return mpq_cmp(m_op, cmp.m_op) < 0;}
100 bool operator>(const Gmprat & cmp) const {return mpq_cmp(m_op, cmp.m_op) > 0;}
101 bool operator<=(const Gmprat & cmp) const {return mpq_cmp(m_op, cmp.m_op) <= 0;}
102 bool operator>=(const Gmprat & cmp) const {return mpq_cmp(m_op, cmp.m_op) >= 0;}
104 Gmprat Abs() const {Gmprat a(*this); mpq_abs(a.m_op, a.m_op); return a;}
108 return sizeof(uint64_t) * (mpq_numref(m_op)->_mp_alloc + mpq_denref(m_op)->_mp_alloc);
112 friend std::ostream& operator<<(std::ostream& os, const Gmprat & fith);
116 inline std::ostream & operator<<(std::ostream & os, const Gmprat & fith)
122 inline std::string Str(const Gmprat & g) {return g.Str();}
123 inline double Log10(const Gmprat & g) {return g.Log10();}
124 inline size_t Size(const Gmprat & g) {return g.Size();}
125 inline Gmprat Abs(const Gmprat & g) {return g.Abs();}