203477c3a8
Verification of Przytycki's congruence works fine, however there are some small modifications that could be made. The, naive, approach to the verification of periodicity congruence for the Khovanov polynomial didn't work. There are just too many cases to check. Generation of all of them can exhaust the memory.
250 lines
5.7 KiB
C++
250 lines
5.7 KiB
C++
#ifndef _KNOTKIT_ALGEBRA_FRACTION_FIELD_H
|
|
#define _KNOTKIT_ALGEBRA_FRACTION_FIELD_H
|
|
|
|
template<class T> class fraction_field
|
|
{
|
|
public:
|
|
typedef ::linear_combination<fraction_field> linear_combination;
|
|
typedef ::linear_combination_const_iter<fraction_field> linear_combination_const_iter;
|
|
|
|
private:
|
|
T num;
|
|
T denom;
|
|
|
|
enum reduced { REDUCED };
|
|
|
|
void reduce ();
|
|
void check ();
|
|
|
|
public:
|
|
fraction_field () : num(0), denom(1) { }
|
|
fraction_field (int x) : num(x), denom(1) { }
|
|
fraction_field (T num_) : num(num_), denom(1) { }
|
|
fraction_field (T num_, T denom_) : num(num_), denom(denom_) { assert (denom != 0); reduce (); }
|
|
fraction_field (reduced, T num_, T denom_)
|
|
: num(num_), denom(denom_)
|
|
{
|
|
assert (denom != 0);
|
|
#ifndef NDEBUG
|
|
check ();
|
|
#endif
|
|
}
|
|
|
|
fraction_field (const fraction_field &q) : num(q.num), denom(q.denom) { }
|
|
fraction_field (copy, const fraction_field &q) : num(COPY, q.num), denom(COPY, q.denom) { }
|
|
~fraction_field () { }
|
|
|
|
fraction_field &operator = (const fraction_field &q) { num = q.num; denom = q.denom; return *this; }
|
|
fraction_field &operator = (int x) { num = x; denom = 1; return *this; }
|
|
|
|
bool operator == (const fraction_field &q) const { return num * q.denom == q.num * denom; }
|
|
bool operator != (const fraction_field &q) const { return !operator == (q); }
|
|
|
|
bool operator == (int x) const { return num == denom * T (x); }
|
|
bool operator != (int x) const { return !operator == (x); }
|
|
|
|
bool is_unit () const { return num != 0; }
|
|
|
|
fraction_field operator + (const fraction_field &x) const
|
|
{
|
|
T d = denom.gcd (x.denom);
|
|
T e = denom.divide_exact (d),
|
|
xe = x.denom.divide_exact (d);
|
|
|
|
T new_num = num * xe;
|
|
new_num += x.num * e;
|
|
|
|
return fraction_field (new_num, denom*xe);
|
|
}
|
|
|
|
fraction_field operator - (const fraction_field &x) const
|
|
{
|
|
T d = denom.gcd (x.denom);
|
|
T e = denom.divide_exact (d),
|
|
xe = x.denom.divide_exact (d);
|
|
|
|
T new_num = num * xe;
|
|
new_num -= x.num * e;
|
|
|
|
return fraction_field (new_num, denom*xe);
|
|
}
|
|
|
|
fraction_field operator - () const
|
|
{
|
|
return fraction_field (-num, denom);
|
|
}
|
|
|
|
fraction_field operator * (const fraction_field &x) const
|
|
{
|
|
T d1 = num.gcd (x.denom);
|
|
T d2 = denom.gcd (x.num);
|
|
return fraction_field (REDUCED,
|
|
num.divide_exact (d1) * x.num.divide_exact (d2),
|
|
denom.divide_exact (d2) * x.denom.divide_exact (d1));
|
|
}
|
|
|
|
fraction_field operator / (const fraction_field &x) const
|
|
{
|
|
assert (x.num != 0);
|
|
|
|
T d1 = num.gcd (x.num);
|
|
T d2 = denom.gcd (x.denom);
|
|
return fraction_field (REDUCED,
|
|
num.divide_exact (d1) * x.denom.divide_exact (d2),
|
|
denom.divide_exact (d2) * x.num.divide_exact (d1));
|
|
}
|
|
|
|
fraction_field &invert ()
|
|
{
|
|
assert (num != 0);
|
|
T t = num;
|
|
num = denom;
|
|
denom = t;
|
|
return *this;
|
|
}
|
|
|
|
fraction_field recip () const
|
|
{
|
|
assert (num != 0);
|
|
return fraction_field (T (COPY, denom),
|
|
T (COPY, num));
|
|
}
|
|
|
|
fraction_field &operator += (const fraction_field &x)
|
|
{
|
|
T d = denom.gcd (x.denom);
|
|
T e = denom.divide_exact (d),
|
|
xe = x.denom.divide_exact (d);
|
|
|
|
num *= xe;
|
|
num += x.num * e;
|
|
denom *= xe;
|
|
|
|
reduce ();
|
|
|
|
return *this;
|
|
}
|
|
|
|
fraction_field &operator -= (const fraction_field &x)
|
|
{
|
|
T d = denom.gcd (x.denom);
|
|
T e = denom.divide_exact (d),
|
|
xe = x.denom.divide_exact (d);
|
|
|
|
num *= xe;
|
|
num -= x.num * e;
|
|
denom *= xe;
|
|
|
|
reduce ();
|
|
|
|
return *this;
|
|
}
|
|
|
|
fraction_field &operator *= (const fraction_field &x)
|
|
{
|
|
T d1 = num.gcd (x.denom);
|
|
num = num.divide_exact (d1);
|
|
|
|
T d2 = denom.gcd (x.num);
|
|
denom = denom.divide_exact (d2);
|
|
|
|
num *= x.num.divide_exact (d2);
|
|
denom *= x.denom.divide_exact (d1);
|
|
|
|
#ifndef NDEBUG
|
|
check ();
|
|
#endif
|
|
|
|
return *this;
|
|
}
|
|
|
|
fraction_field &operator /= (const fraction_field &x)
|
|
{
|
|
assert (x.num != 0);
|
|
|
|
T d1 = num.gcd (x.num);
|
|
num = num.divide_exact (d1);
|
|
|
|
T d2 = denom.gcd (x.denom);
|
|
denom = denom.divide_exact (d2);
|
|
|
|
num *= x.denom.divide_exact (d2);
|
|
denom *= x.num.divide_exact (d1);
|
|
|
|
#ifndef NDEBUG
|
|
check ();
|
|
#endif
|
|
|
|
return *this;
|
|
}
|
|
|
|
// d | n, d.divides (n)
|
|
bool divides (const fraction_field &n) const
|
|
{
|
|
// d = *this
|
|
return (num != 0) || (n.num == 0);
|
|
}
|
|
|
|
bool operator | (const fraction_field &q) const { return divides (q); }
|
|
|
|
fraction_field div (const fraction_field &d) const { return operator / (d); }
|
|
|
|
fraction_field gcd (const fraction_field &q) const
|
|
{
|
|
assert (num != 0 && q.num != 0);
|
|
return fraction_field (1);
|
|
}
|
|
|
|
tuple<fraction_field, fraction_field, fraction_field> extended_gcd (const fraction_field &x) const
|
|
{
|
|
if (*this != 0)
|
|
return make_tuple (*this, fraction_field (1), fraction_field (0));
|
|
else
|
|
return make_tuple (x, fraction_field (0), fraction_field (1));
|
|
}
|
|
|
|
static void show_ring () { printf ("fraction_field("); T::show_ring (); printf (")"); }
|
|
void show_self () const;
|
|
void display_self () const { show_self (); newline (); }
|
|
};
|
|
|
|
template<class T> void
|
|
fraction_field<T>::reduce ()
|
|
{
|
|
if (num == 0)
|
|
{
|
|
denom = 1;
|
|
return;
|
|
}
|
|
|
|
T d = num.gcd (denom);
|
|
num = num.divide_exact (d);
|
|
denom = denom.divide_exact (d);
|
|
}
|
|
|
|
template<class T> void
|
|
fraction_field<T>::check ()
|
|
{
|
|
if (num == 0)
|
|
return;
|
|
|
|
// assert (num.gcd (denom) == 1);
|
|
}
|
|
|
|
template<class T> void
|
|
fraction_field<T>::show_self () const
|
|
{
|
|
if (denom == 1)
|
|
show (num);
|
|
else
|
|
{
|
|
printf ("(");
|
|
show (num);
|
|
printf (")/(");
|
|
show (denom);
|
|
printf (")");
|
|
}
|
|
}
|
|
|
|
#endif // _KNOTKIT_ALGEBRA_FRACTION_FIELD_H
|