2016-11-19 20:55:11 +01:00
|
|
|
#ifndef _KNOTKIT_ALGEBRA_Z_H
|
|
|
|
#define _KNOTKIT_ALGEBRA_Z_H
|
|
|
|
#include<gmpxx.h>
|
|
|
|
#include<tuple>
|
|
|
|
#include<memory>
|
|
|
|
#include<iostream>
|
|
|
|
#include<cassert>
|
2011-12-09 21:50:25 +01:00
|
|
|
|
|
|
|
class Z
|
|
|
|
{
|
|
|
|
public:
|
2016-11-19 20:55:11 +01:00
|
|
|
using linear_combination = ::linear_combination<Z>;
|
|
|
|
using linear_combination_const_iter = ::linear_combination_const_iter<Z>;
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::shared_ptr<mpz_class> impl;
|
2016-11-28 09:26:41 +01:00
|
|
|
#ifdef DEBUG_Z
|
2016-11-19 20:55:11 +01:00
|
|
|
void write_state() const {
|
|
|
|
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"; */
|
|
|
|
}
|
2016-11-28 09:26:41 +01:00
|
|
|
#endif
|
2011-12-09 21:50:25 +01:00
|
|
|
|
|
|
|
public:
|
2016-11-19 20:55:11 +01:00
|
|
|
Z() : impl(new mpz_class) {
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "Z()" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Z(mpz_t z) : impl(new mpz_class(z)) {
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "Z(mpz_t)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Z(mpz_class z) : impl(new mpz_class(z)) {
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "Z(mpz_class)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Z(int init) : impl(new mpz_class(init)) {
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "Z(int)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Z(const Z& z) : impl(z.impl) {
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "Z(const Z& z)" << "\n";
|
|
|
|
write_state();
|
2016-11-28 09:26:41 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Z(copy, const Z& z) : impl(z.impl) {
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "Z(COPY, const Z& z)\n";
|
|
|
|
write_state();
|
2016-11-19 20:55:11 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Z(Z&& z) : impl(std::move(z.impl)) {
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "Z(Z&& z)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
z.impl = std::make_shared<mpz_class>(mpz_class(0));
|
|
|
|
}
|
|
|
|
~Z() {
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "~Z()" << "\n";
|
|
|
|
write_state();
|
|
|
|
if(impl.use_count() == 1)
|
|
|
|
std::cout << "Destroying..." << "\n";
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
Z& operator = (const Z& z) {
|
|
|
|
impl = z.impl;
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "Z& operator = (const Z&)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
return *this;
|
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
Z& operator = (const int x) {
|
|
|
|
impl = std::make_shared<mpz_class>(mpz_class(x));
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "Z& operator = (int)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
Z& operator = (Z&& z) {
|
|
|
|
impl = std::move(z.impl);
|
|
|
|
z.impl = std::make_shared<mpz_class>(mpz_class(0));
|
|
|
|
#ifdef DEBUG_Z
|
|
|
|
std::cout << "Z& operator = (Z&&)" << "\n";
|
|
|
|
write_state();
|
|
|
|
#endif
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator == (const Z& z) const {
|
|
|
|
return *impl.get() == *z.impl.get();
|
|
|
|
}
|
|
|
|
bool operator != (const Z& z) const {
|
|
|
|
return !operator == (z);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator == (const int y) const {
|
|
|
|
return *impl.get() == mpz_class(y);
|
|
|
|
}
|
|
|
|
bool operator != (const int y) const {
|
|
|
|
return ! operator == (y);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator < (const Z& z) const {
|
|
|
|
return *impl.get() < *z.impl.get();
|
|
|
|
}
|
|
|
|
|
2016-11-28 09:26:41 +01:00
|
|
|
bool operator <= (const Z& z) const {
|
|
|
|
return *this < z || *this == z;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator > (const Z& z) const {
|
|
|
|
return !(*this <= z);
|
|
|
|
}
|
|
|
|
bool operator >= (const Z& z) const {
|
|
|
|
return !(*this < z);
|
|
|
|
}
|
|
|
|
|
2011-12-09 21:50:25 +01:00
|
|
|
bool is_unit () const
|
|
|
|
{
|
|
|
|
return *this == 1 || *this == -1;
|
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z operator + (const Z& z) const {
|
|
|
|
return Z(*impl.get() + *z.impl.get());
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z operator - () const {
|
|
|
|
return Z(-*impl.get());
|
2011-12-14 19:07:53 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z operator - (const Z& z) const {
|
|
|
|
return Z(*impl.get() - *z.impl.get());
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z operator * (const Z& z) const {
|
|
|
|
return Z(*impl.get() * *z.impl.get());
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z operator / (const Z& z) const {
|
|
|
|
if(z == 0)
|
2011-12-09 21:50:25 +01:00
|
|
|
return *this;
|
2016-11-19 20:55:11 +01:00
|
|
|
else {
|
|
|
|
assert(z != 0);
|
|
|
|
return Z(*impl.get() / *z.impl.get());
|
|
|
|
}
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
2016-11-19 21:01:10 +01:00
|
|
|
Z operator % (const Z& z) const {
|
|
|
|
if(Z(0) < z) {
|
|
|
|
// return Z(*impl.get() % *z.impl.get());
|
|
|
|
mpz_class r;
|
|
|
|
mpz_fdiv_r(r.get_mpz_t(), impl.get()->get_mpz_t(), z.impl.get()->get_mpz_t());
|
|
|
|
return Z(r);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Z operator % (unsigned p) const {
|
|
|
|
if(p != 0)
|
|
|
|
return operator % (Z(p));
|
|
|
|
else
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
Z recip () const {
|
|
|
|
assert(is_unit());
|
2011-12-27 19:40:59 +01:00
|
|
|
return *this;
|
2011-12-22 21:35:49 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z& muladdeq(const Z& z1, const Z& z2) {
|
|
|
|
return *this += z1 * z2;
|
|
|
|
}
|
|
|
|
|
|
|
|
Z& operator += (const Z& z) {
|
|
|
|
*this = *this + z;
|
2011-12-09 21:50:25 +01:00
|
|
|
return *this;
|
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z& operator -= (const Z& z) {
|
|
|
|
*this = *this - z;
|
2011-12-09 21:50:25 +01:00
|
|
|
return *this;
|
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z& operator *= (const Z& z) {
|
|
|
|
*this = *this * z;
|
2011-12-09 21:50:25 +01:00
|
|
|
return *this;
|
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z& operator /= (const Z& z) {
|
|
|
|
*this = *this / z;
|
2011-12-09 21:50:25 +01:00
|
|
|
return *this;
|
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
bool divides(const Z& num) const {
|
|
|
|
return mpz_divisible_p(num.impl.get()->get_mpz_t(),impl.get()->get_mpz_t());
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
2016-11-19 20:46:39 +01:00
|
|
|
|
2016-11-19 20:55:11 +01:00
|
|
|
bool operator | (const Z& num) const {
|
|
|
|
return divides(num);
|
|
|
|
}
|
|
|
|
|
|
|
|
Z divide_exact(const Z& denom) const {
|
2011-12-09 21:50:25 +01:00
|
|
|
mpz_t q;
|
2016-11-19 20:55:11 +01:00
|
|
|
mpz_init(q);
|
|
|
|
mpz_divexact(q,impl.get()->get_mpz_t(), denom.impl.get()->get_mpz_t());
|
|
|
|
return Z(q);
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
std::tuple<Z,Z> divide_with_remainder(const Z& denom) const {
|
|
|
|
mpz_t q,r;
|
|
|
|
mpz_init(q);
|
|
|
|
mpz_init(r);
|
|
|
|
mpz_tdiv_qr(q, r, impl.get()->get_mpz_t(), denom.impl.get()->get_mpz_t());
|
|
|
|
return std::make_tuple(Z(q), Z(r));
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z gcd (const Z& z) const {
|
2011-12-09 21:50:25 +01:00
|
|
|
mpz_t d;
|
2016-11-19 20:55:11 +01:00
|
|
|
mpz_init(d);
|
|
|
|
mpz_gcd(d, impl.get()->get_mpz_t(), z.impl.get()->get_mpz_t());
|
|
|
|
return Z(d);
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
Z lcm (const Z& z) const {
|
2011-12-09 21:50:25 +01:00
|
|
|
mpz_t m;
|
2016-11-19 20:55:11 +01:00
|
|
|
mpz_init(m);
|
|
|
|
mpz_lcm(m, impl.get()->get_mpz_t(), z.impl.get()->get_mpz_t());
|
|
|
|
return Z(m);
|
2011-12-09 21:50:25 +01:00
|
|
|
}
|
2016-11-19 20:55:11 +01:00
|
|
|
|
|
|
|
std::tuple<Z, Z, Z> extended_gcd(const Z& z) const {
|
|
|
|
mpz_t d,s,t;
|
|
|
|
mpz_init(d);
|
|
|
|
mpz_init(s);
|
|
|
|
mpz_init(t);
|
|
|
|
mpz_gcdext(d, s, t, impl.get()->get_mpz_t(), z.impl.get()->get_mpz_t());
|
|
|
|
return std::make_tuple<Z, Z, Z>(Z(d), Z(s), Z(t));
|
2012-07-27 21:37:47 +02:00
|
|
|
}
|
|
|
|
|
2011-12-09 21:50:25 +01:00
|
|
|
static void show_ring () { printf ("Z"); }
|
2016-11-19 20:55:11 +01:00
|
|
|
void show_self () const {
|
|
|
|
std::cout << *this;
|
|
|
|
}
|
|
|
|
void display_self () const {
|
|
|
|
std::cout << *this << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
friend std::ostream& operator << (std::ostream& os, const Z& z) {
|
|
|
|
return os << *z.impl;
|
|
|
|
}
|
|
|
|
int get_count() const {
|
|
|
|
return impl.use_count();
|
|
|
|
}
|
|
|
|
|
2016-11-19 21:01:10 +01:00
|
|
|
unsigned get_ui() const {
|
|
|
|
return impl.get()->get_ui();
|
|
|
|
}
|
|
|
|
};
|
2016-11-19 20:55:11 +01:00
|
|
|
#endif // _KNOTKIT_ALGEBRA_Z_H
|