2013-07-16 22:54:36 +00:00
|
|
|
/*
|
2013-07-19 17:29:33 +00:00
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
2013-07-16 22:54:36 +00:00
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
2013-07-19 17:29:33 +00:00
|
|
|
Author: Leonardo de Moura
|
2013-07-16 22:54:36 +00:00
|
|
|
*/
|
2013-09-13 03:04:10 +00:00
|
|
|
#include "util/numerics/mpq.h"
|
|
|
|
#include "util/numerics/mpbq.h"
|
2013-07-16 22:54:36 +00:00
|
|
|
|
|
|
|
namespace lean {
|
|
|
|
|
2013-08-08 02:26:10 +00:00
|
|
|
const mpq numeric_traits<mpq>::pi_l((3373259426.0 + 273688.0 / (1<<21)) / (1<<30));
|
|
|
|
const mpq numeric_traits<mpq>::pi_n((3373259426.0 + 273688.0 / (1<<21)) / (1<<30));
|
|
|
|
const mpq numeric_traits<mpq>::pi_u((3373259426.0 + 273688.0 / (1<<21)) / (1<<30));
|
|
|
|
|
2013-07-22 03:12:04 +00:00
|
|
|
mpq & mpq::operator=(mpbq const & b) {
|
|
|
|
*this = 2;
|
|
|
|
power(*this, *this, b.get_k());
|
|
|
|
inv();
|
|
|
|
*this *= b.get_numerator();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-07-17 21:24:35 +00:00
|
|
|
int cmp(mpq const & a, mpz const & b) {
|
|
|
|
if (a.is_integer()) {
|
|
|
|
return mpz_cmp(mpq_numref(a.m_val), mpq::zval(b));
|
2013-08-07 15:17:33 +00:00
|
|
|
} else {
|
2013-07-17 21:24:35 +00:00
|
|
|
static thread_local mpz tmp;
|
|
|
|
mpz_mul(mpq::zval(tmp), mpq_denref(a.m_val), mpq::zval(b));
|
|
|
|
return mpz_cmp(mpq_numref(a.m_val), mpq::zval(tmp));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-16 22:54:36 +00:00
|
|
|
void mpq::floor() {
|
|
|
|
if (is_integer())
|
|
|
|
return;
|
|
|
|
bool neg = is_neg();
|
|
|
|
mpz_tdiv_q(mpq_numref(m_val), mpq_numref(m_val), mpq_denref(m_val));
|
|
|
|
mpz_set_ui(mpq_denref(m_val), 1);
|
|
|
|
if (neg)
|
|
|
|
mpz_sub_ui(mpq_numref(m_val), mpq_numref(m_val), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mpq::ceil() {
|
|
|
|
if (is_integer())
|
|
|
|
return;
|
|
|
|
bool pos = is_pos();
|
|
|
|
mpz_tdiv_q(mpq_numref(m_val), mpq_numref(m_val), mpq_denref(m_val));
|
|
|
|
mpz_set_ui(mpq_denref(m_val), 1);
|
|
|
|
if (pos)
|
|
|
|
mpz_add_ui(mpq_numref(m_val), mpq_numref(m_val), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
mpz floor(mpq const & a) {
|
|
|
|
if (a.is_integer())
|
|
|
|
return a.get_numerator();
|
|
|
|
mpz r;
|
|
|
|
mpz_tdiv_q(mpq::zval(r), mpq_numref(a.m_val), mpq_denref(a.m_val));
|
|
|
|
if (a.is_neg())
|
2013-07-17 00:20:24 +00:00
|
|
|
--r;
|
2013-07-16 22:54:36 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
mpz ceil(mpq const & a) {
|
|
|
|
if (a.is_integer())
|
|
|
|
return a.get_numerator();
|
|
|
|
mpz r;
|
|
|
|
mpz_tdiv_q(mpq::zval(r), mpq_numref(a.m_val), mpq_denref(a.m_val));
|
|
|
|
if (a.is_pos())
|
2013-07-17 00:20:24 +00:00
|
|
|
++r;
|
2013-07-16 22:54:36 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2013-07-19 23:50:50 +00:00
|
|
|
void power(mpq & a, mpq const & b, unsigned k) {
|
|
|
|
mpz_pow_ui(mpq_numref(a.m_val), mpq_numref(b.m_val), k);
|
|
|
|
mpz_pow_ui(mpq_denref(a.m_val), mpq_denref(b.m_val), k);
|
|
|
|
mpq_canonicalize(a.m_val);
|
|
|
|
}
|
|
|
|
|
2013-07-16 22:54:36 +00:00
|
|
|
extern void display(std::ostream & out, __mpz_struct const * v);
|
|
|
|
|
|
|
|
std::ostream & operator<<(std::ostream & out, mpq const & v) {
|
|
|
|
if (v.is_integer()) {
|
|
|
|
display(out, mpq_numref(v.m_val));
|
2013-08-07 15:17:33 +00:00
|
|
|
} else {
|
2013-07-16 22:54:36 +00:00
|
|
|
display(out, mpq_numref(v.m_val));
|
|
|
|
out << "/";
|
|
|
|
display(out, mpq_denref(v.m_val));
|
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2013-07-17 21:24:35 +00:00
|
|
|
void display_decimal(std::ostream & out, mpq const & a, unsigned prec) {
|
|
|
|
mpz n1, d1, v1;
|
|
|
|
numerator(n1, a);
|
|
|
|
denominator(d1, a);
|
|
|
|
if (a.is_neg()) {
|
|
|
|
out << "-";
|
2013-08-22 22:35:18 +00:00
|
|
|
n1.neg();
|
2013-07-17 21:24:35 +00:00
|
|
|
}
|
|
|
|
v1 = n1 / d1;
|
|
|
|
out << v1;
|
|
|
|
n1 = rem(n1, d1);
|
|
|
|
if (n1.is_zero())
|
|
|
|
return;
|
|
|
|
out << ".";
|
|
|
|
for (unsigned i = 0; i < prec; i++) {
|
|
|
|
n1 *= 10;
|
|
|
|
v1 = n1 / d1;
|
|
|
|
lean_assert(v1 < 10);
|
|
|
|
out << v1;
|
|
|
|
n1 = rem(n1, d1);
|
|
|
|
if (n1.is_zero())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
out << "?";
|
|
|
|
}
|
2013-07-16 22:54:36 +00:00
|
|
|
}
|
2013-07-17 19:43:05 +00:00
|
|
|
|
2013-08-07 19:10:10 +00:00
|
|
|
void print(lean::mpq const & v) { std::cout << v << std::endl; }
|