2013-07-16 20:11:24 +00:00
|
|
|
/*
|
2013-07-19 17:29:33 +00:00
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
2013-07-16 20:11:24 +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 20:11:24 +00:00
|
|
|
*/
|
|
|
|
#include <memory>
|
2013-09-13 10:35:29 +00:00
|
|
|
#include "util/numerics/mpz.h"
|
2013-07-16 20:11:24 +00:00
|
|
|
|
|
|
|
namespace lean {
|
|
|
|
|
|
|
|
unsigned mpz::log2() const {
|
|
|
|
if (is_nonpos())
|
|
|
|
return 0;
|
|
|
|
unsigned r = mpz_sizeinbase(m_val, 2);
|
|
|
|
lean_assert(r > 0);
|
|
|
|
return r - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned mpz::mlog2() const {
|
|
|
|
if (is_nonneg())
|
|
|
|
return 0;
|
|
|
|
mpz * _this = const_cast<mpz*>(this);
|
|
|
|
_this->neg();
|
|
|
|
lean_assert(is_pos());
|
|
|
|
unsigned r = mpz_sizeinbase(m_val, 2);
|
|
|
|
_this->neg();
|
|
|
|
lean_assert(is_neg());
|
|
|
|
return r - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool mpz::is_power_of_two(unsigned & shift) const {
|
|
|
|
if (is_nonpos())
|
|
|
|
return false;
|
|
|
|
if (mpz_popcount(m_val) == 1) {
|
|
|
|
shift = log2();
|
|
|
|
return true;
|
2013-08-07 15:17:33 +00:00
|
|
|
} else {
|
2013-07-16 20:11:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2013-07-19 17:29:33 +00:00
|
|
|
|
|
|
|
mpz operator%(mpz const & a, mpz const & b) {
|
2013-07-16 20:11:24 +00:00
|
|
|
mpz r(rem(a, b));
|
|
|
|
if (r.is_neg()) {
|
|
|
|
if (b.is_pos())
|
|
|
|
r += b;
|
|
|
|
else
|
|
|
|
r -= b;
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2013-07-19 17:29:33 +00:00
|
|
|
bool root(mpz & root, mpz const & a, unsigned k) {
|
2013-07-17 21:24:35 +00:00
|
|
|
static thread_local mpz rem;
|
2013-07-19 17:29:33 +00:00
|
|
|
mpz_rootrem(root.m_val, rem.m_val, a.m_val, k);
|
2013-07-17 21:24:35 +00:00
|
|
|
return rem.is_zero();
|
|
|
|
}
|
|
|
|
|
2013-07-16 22:54:36 +00:00
|
|
|
void display(std::ostream & out, __mpz_struct const * v) {
|
|
|
|
size_t sz = mpz_sizeinbase(v, 10) + 2;
|
2013-07-16 20:11:24 +00:00
|
|
|
if (sz < 1024) {
|
|
|
|
char buffer[1024];
|
2013-07-16 22:54:36 +00:00
|
|
|
mpz_get_str(buffer, 10, v);
|
2013-07-16 20:11:24 +00:00
|
|
|
out << buffer;
|
2013-08-07 15:17:33 +00:00
|
|
|
} else {
|
2013-07-16 20:11:24 +00:00
|
|
|
std::unique_ptr<char> buffer(new char[sz]);
|
2013-07-16 22:54:36 +00:00
|
|
|
mpz_get_str(buffer.get(), 10, v);
|
2013-07-16 20:11:24 +00:00
|
|
|
out << buffer.get();
|
|
|
|
}
|
2013-07-16 22:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream & operator<<(std::ostream & out, mpz const & v) {
|
|
|
|
display(out, v.m_val);
|
2013-07-16 20:11:24 +00:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2013-10-16 23:53:41 +00:00
|
|
|
static mpz g_zero;
|
|
|
|
|
|
|
|
mpz const & numeric_traits<mpz>::zero() {
|
|
|
|
lean_assert(is_zero(g_zero));
|
|
|
|
return g_zero;
|
|
|
|
}
|
2013-07-16 20:11:24 +00:00
|
|
|
}
|
2013-07-17 19:43:05 +00:00
|
|
|
|
2013-08-07 19:10:10 +00:00
|
|
|
void print(lean::mpz const & n) { std::cout << n << std::endl; }
|