2016-11-19 20:55:11 +01:00
|
|
|
#ifndef _KNOTKIT_ALGEBRA_Q_H
|
|
|
|
#define _KNOTKIT_ALGEBRA_Q_H
|
|
|
|
#include <gmpxx.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include <memory>
|
|
|
|
#include <tuple>
|
|
|
|
#include <cassert>
|
2011-12-09 21:50:25 +01:00
|
|
|
|
|
|
|
class Q
|
|
|
|
{
|
|
|
|
public:
|
2016-11-19 20:55:11 +01:00
|
|
|
using linear_combination = ::linear_combination<Q>;
|
|
|
|
using linear_combination_const_iter = ::linear_combination_const_iter<Q>;
|
2011-12-27 19:40:59 +01:00
|
|
|
|
2011-12-09 21:50:25 +01:00
|
|
|
private:
|
2016-11-19 20:55:11 +01:00
|
|
|
std::shared_ptr<mpq_class> impl;
|
2016-11-19 21:01:10 +01:00
|
|
|
void write_state() const {
|
2016-11-19 20:55:11 +01:00
|
|
|
std::cout << "I store the following value " << *this << "\n";
|
|
|
|
std::cout << "Number of objects pointing to the same value " << impl.use_count() << "\n";
|
|
|
|
/* std::cout << "I point to " << impl.get() << "\n"; */
|
|
|
|
/* std::cout << "My size " << sizeof(*this) << "\n"; */
|
|
|
|
/* std::cout << "Size of std::shared_ptr<mpz_class> " << sizeof(impl) << "\n"; */
|
|
|
|
/* std::cout << "Size of mpz_class " << sizeof(*impl) << "\n"; */
|
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
|
|
|
|
public:
|
2016-11-19 20:55:11 +01:00
|
|
|
Q() : impl(new mpq_class()) {
|
|
|
|
#ifdef DEBUG_Q
|
|
|
|
std::cout << "Q()" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Q(mpq_t q) : impl(new mpq_class(q)) {
|
|
|
|
#ifdef DEBUG_Q
|
|
|
|
std::cout << "Q(mpq_t)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Q(mpq_class q) : impl(new mpq_class(q)) {
|
|
|
|
#ifdef DEBUG_Q
|
|
|
|
std::cout << "Q(mpq_class)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Q(int init) : impl(new mpq_class (init)) {
|
|
|
|
#ifdef DEBUG_Q
|
|
|
|
std::cout << "Q(int)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Q(const Q& q) : impl(q.impl) {
|
|
|
|
#ifdef DEBUG_Q
|
|
|
|
std::cout << "Q(const Q&)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Q(Q&& q) : impl(std::move (q.impl)) {
|
|
|
|
q.impl = std::make_shared<mpq_class>(0);
|
|
|
|
#ifdef DEBUG_Q
|
|
|
|
std::cout << "Q(Q&& q)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Q(copy, const Q &q) : impl(new mpq_class (*q.impl.get())) {
|
|
|
|
#ifdef DEBUG_Q
|
|
|
|
std::cout << "Q(copy, const Q&)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
//Q(reader &r) : impl(new Q_impl (r)) { }
|
|
|
|
~Q() {
|
|
|
|
#ifdef DEBUG_Q
|
|
|
|
std::cout << "~Q()" << "\n";
|
|
|
|
write_state();
|
|
|
|
if(get_count() == 1)
|
|
|
|
std::cout << "Destroying..." << "\n";
|
|
|
|
#endif
|
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
Q &operator = (const Q &q) {
|
|
|
|
impl = q.impl;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
Q& operator = (Q&& q) {
|
|
|
|
impl = std::move(q.impl);
|
|
|
|
q.impl = std::make_shared<mpq_class>(0);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
Q &operator = (int x) {
|
|
|
|
impl = std::make_shared<mpq_class>(0);
|
|
|
|
return *this;
|
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
bool operator == (const Q &q) const {
|
|
|
|
return *impl.get() == *q.impl.get();
|
|
|
|
}
|
|
|
|
bool operator == (const int r) const {
|
|
|
|
return *impl.get() == mpq_class(r);
|
|
|
|
}
|
|
|
|
bool operator != (const Q& q) const {
|
|
|
|
return ! operator == (q);
|
|
|
|
}
|
|
|
|
bool operator != (const int r) const {
|
|
|
|
return !operator == (r);
|
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
bool operator < (const Q &q) const {
|
|
|
|
return *impl.get() < *q.impl.get();
|
|
|
|
}
|
|
|
|
// bool operator > (const Q& q) const {
|
|
|
|
// return *impl.get() > *q.impl.get();
|
|
|
|
// }
|
2011-12-09 21:50:25 +01:00
|
|
|
|
2011-12-27 19:40:59 +01:00
|
|
|
bool is_unit () const
|
|
|
|
{
|
|
|
|
return *this != 0;
|
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
|
2011-12-27 19:40:59 +01:00
|
|
|
Q operator - () const
|
|
|
|
{
|
2016-11-19 20:55:11 +01:00
|
|
|
return Q(-*impl.get());
|
2011-12-27 19:40:59 +01:00
|
|
|
}
|
|
|
|
|
2011-12-09 21:50:25 +01:00
|
|
|
Q recip () const
|
|
|
|
{
|
2016-11-19 20:55:11 +01:00
|
|
|
mpq_t q;
|
|
|
|
mpq_init(q);
|
|
|
|
mpq_inv(q, impl.get()->get_mpq_t());
|
|
|
|
return Q(q);
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
Q operator + (const Q& q) const
|
2011-12-27 19:40:59 +01:00
|
|
|
{
|
2016-11-19 20:55:11 +01:00
|
|
|
return Q(*impl.get() + *q.impl.get());
|
2011-12-27 19:40:59 +01:00
|
|
|
}
|
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
Q operator - (const Q& q) const
|
2011-12-27 19:40:59 +01:00
|
|
|
{
|
2016-11-19 20:55:11 +01:00
|
|
|
return Q(*impl.get() - *q.impl.get());
|
2011-12-27 19:40:59 +01:00
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
Q operator * (const Q& q) const
|
2011-12-27 19:40:59 +01:00
|
|
|
{
|
2016-11-19 20:55:11 +01:00
|
|
|
return Q(*impl.get() * (*q.impl.get()));
|
2011-12-27 19:40:59 +01:00
|
|
|
}
|
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
Q operator / (const Q& q) const
|
2011-12-27 19:40:59 +01:00
|
|
|
{
|
2016-11-19 20:55:11 +01:00
|
|
|
return Q(*impl.get() / *q.impl.get());
|
2011-12-27 19:40:59 +01:00
|
|
|
}
|
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
Q &muladdeq (const Q& q1, const Q& q2)
|
2011-12-27 19:40:59 +01:00
|
|
|
{
|
|
|
|
return operator += (q1 * q2);
|
|
|
|
}
|
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
Q &operator += (const Q& q)
|
2011-12-27 19:40:59 +01:00
|
|
|
{
|
2016-11-19 20:55:11 +01:00
|
|
|
return *this = *this + q;
|
2011-12-27 19:40:59 +01:00
|
|
|
}
|
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
Q &operator -= (const Q& q)
|
2011-12-27 19:40:59 +01:00
|
|
|
{
|
2016-11-19 20:55:11 +01:00
|
|
|
return *this = *this - q;
|
2011-12-27 19:40:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Q &operator *= (const Q &q)
|
|
|
|
{
|
2016-11-19 20:55:11 +01:00
|
|
|
return *this = *this * q;
|
2011-12-27 19:40:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Q &operator /= (const Q &q)
|
|
|
|
{
|
|
|
|
assert (q != 0);
|
2016-11-19 20:55:11 +01:00
|
|
|
return *this = *this / q;
|
2011-12-27 19:40:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool divides (const Q &num) const
|
|
|
|
{
|
|
|
|
return *this != 0 || num == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator | (const Q &num) const { return divides (num); }
|
|
|
|
|
|
|
|
Q div (const Q &d) const { return operator / (d); }
|
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
std::tuple<Q, Q, Q> extended_gcd (const Q &q) const
|
2011-12-27 19:40:59 +01:00
|
|
|
{
|
|
|
|
if (*this != 0)
|
2016-11-19 20:55:11 +01:00
|
|
|
return std::tuple<Q, Q, Q> (*this, 1, 0);
|
2011-12-27 19:40:59 +01:00
|
|
|
else
|
2016-11-19 20:55:11 +01:00
|
|
|
return std::tuple<Q, Q, Q> (q, 0, 1);
|
2011-12-27 19:40:59 +01:00
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
|
|
|
|
Q gcd (const Q &q) const
|
|
|
|
{
|
2011-12-27 19:40:59 +01:00
|
|
|
assert (*this != 0 || q != 0);
|
|
|
|
return 1;
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
friend std::ostream& operator << (std::ostream& os, const Q& q) {
|
|
|
|
return os << *q.impl.get();
|
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
static void show_ring () { printf ("Q"); }
|
2016-11-19 20:55:11 +01:00
|
|
|
void show_self () const { std::cout << *this; }
|
|
|
|
void display_self () const { std::cout << *this << "\n"; }
|
|
|
|
// void write_self (writer &w) const { write (w, *impl); }
|
|
|
|
int get_count() const {
|
|
|
|
return impl.use_count();
|
|
|
|
}
|
2016-11-19 21:01:10 +01:00
|
|
|
Z get_num() const {
|
|
|
|
return Z(impl.get()->get_num());
|
|
|
|
}
|
|
|
|
Z get_den() const {
|
|
|
|
return Z(impl.get()->get_den());
|
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
};
|
2016-11-19 20:55:11 +01:00
|
|
|
#endif // _KNOTKIT_ALGEBRA_Q_H
|