+ double LogE() const
+ {
+ // log(a/b) = log(a) - log(b)
+ // And if a is represented in base B as:
+ // a = a_N B^N + a_{N-1} B^{N-1} + ... + a_0
+ // => log(a) \approx log(a_N B^N)
+ // = log(a_N) + N log(B)
+ // where B is the base; ie number of values representable with one digit, ie: ULONG_MAX
+
+ static double logB = log(ULONG_MAX); // compiler should optimise this anyway?
+
+ // Undefined logs (should probably return NAN if -ve, not -INFINITY, but meh)
+ if (mpz_get_ui(mpq_numref(m_op)) == 0 || mpz_sgn(mpq_numref(m_op)) < 0)
+ return -INFINITY;
+
+ // Log of numerator
+ double lognum = log(mpq_numref(m_op)->_mp_d[abs(mpq_numref(m_op)->_mp_size) - 1]);
+ lognum += (abs(mpq_numref(m_op)->_mp_size)-1) * logB;
+
+ // Subtract log of denominator, if it exists
+ // Note that denominator is not explicitly set to 1, this caused a lot of headache
+ if (abs(mpq_denref(m_op)->_mp_size) > 0)
+ {
+ lognum -= log(mpq_denref(m_op)->_mp_d[abs(mpq_denref(m_op)->_mp_size)-1]);
+ lognum -= (abs(mpq_denref(m_op)->_mp_size)-1) * logB;
+ }
+ return lognum;
+ }
+
+ double Log10() const {return LogE() / log(10.0);}
+
+ bool Negative() const {return (mpz_sgn(mpq_numref(m_op)) < 0);}
+