Added Zp and unary minus to ring classes. Added *~ to .gitignore.
Added unsigned_extended_gcd. There are ring/field tests that should be separated.
This commit is contained in:
parent
1d63f2195f
commit
53a139416c
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
*~
|
||||
*.o
|
||||
/gss
|
||||
/main
|
||||
|
3
Makefile
3
Makefile
@ -31,7 +31,8 @@ LIB_HEADERS = lib/lib.h lib/show.h lib/refcount.h lib/pair.h lib/maybe.h lib/vec
|
||||
lib/unionfind.h lib/priority_queue.h lib/io.h \
|
||||
lib/directed_multigraph.h
|
||||
ALGEBRA_HEADERS = algebra/algebra.h algebra/grading.h algebra/module.h \
|
||||
algebra/Z2.h algebra/linear_combination.h algebra/Z.h algebra/Q.h \
|
||||
algebra/Z2.h algebra/linear_combination.h \
|
||||
algebra/Z.h algebra/Zp.h algebra/Q.h \
|
||||
algebra/polynomial.h algebra/multivariate_polynomial.h \
|
||||
algebra/laurentpoly.h algebra/fraction_field.h
|
||||
KNOTKIT_HEADERS = knotkit.h planar_diagram.h dt_code.h knot_diagram.h \
|
||||
|
@ -55,6 +55,14 @@ class Z
|
||||
return Z (STEAL, x);
|
||||
}
|
||||
|
||||
Z operator - () const
|
||||
{
|
||||
mpz_t x;
|
||||
mpz_init (x);
|
||||
mpz_neg (x, impl->x);
|
||||
return Z (STEAL, x);
|
||||
}
|
||||
|
||||
Z operator - (const Z &z) const
|
||||
{
|
||||
mpz_t x;
|
||||
|
@ -27,6 +27,7 @@ class Z2
|
||||
|
||||
Z2 operator + (const Z2 &x) const { return Z2 (v ^ x.v); }
|
||||
Z2 operator - (const Z2 &x) const { return Z2 (v ^ x.v); }
|
||||
Z2 operator - () const { return *this; }
|
||||
Z2 operator * (const Z2 &x) const { return Z2 (v & x.v); }
|
||||
Z2 operator / (const Z2 &x) const { assert (x.v); return *this; }
|
||||
|
||||
|
112
algebra/Zp.h
Normal file
112
algebra/Zp.h
Normal file
@ -0,0 +1,112 @@
|
||||
|
||||
template<unsigned p>
|
||||
class Zp
|
||||
{
|
||||
public:
|
||||
typedef linear_combination<Zp<p> > linear_combination;
|
||||
typedef linear_combination_const_iter<Zp<p> > linear_combination_const_iter;
|
||||
|
||||
private:
|
||||
unsigned v;
|
||||
|
||||
public:
|
||||
Zp () : v(0) { }
|
||||
Zp (unsigned init) : v(init % p) { }
|
||||
Zp (int init)
|
||||
{
|
||||
int i = init % (int)p;
|
||||
if (i < 0)
|
||||
i += p;
|
||||
assert (i >= 0 && i < (int)p);
|
||||
v = i;
|
||||
}
|
||||
|
||||
Zp (const Zp &x) : v(x.v) { }
|
||||
Zp (copy, const Zp &x) : v(x.v) { }
|
||||
~Zp () { }
|
||||
|
||||
Zp &operator = (const Zp &x) { v = x.v; return *this; }
|
||||
Zp &operator = (int x)
|
||||
{
|
||||
return operator = (Zp (x));
|
||||
}
|
||||
|
||||
bool operator == (const Zp &x) const { return v == x.v; }
|
||||
|
||||
bool operator == (int x) const { return operator == (Zp (x)); }
|
||||
bool operator != (int x) const { return !operator == (x); }
|
||||
|
||||
bool operator < (const Zp &x) const { return v < x.v; }
|
||||
|
||||
bool is_unit () const
|
||||
{
|
||||
return v != 0;
|
||||
}
|
||||
|
||||
Zp operator + (const Zp &x) const { return Zp (v + x.v); }
|
||||
Zp operator - (const Zp &x) const { return Zp ((int)v - (int)x.v); }
|
||||
Zp operator - () const { return Zp (- (int)v); }
|
||||
|
||||
Zp operator * (const Zp &x) const { return Zp (v * x.v); }
|
||||
|
||||
Zp operator / (const Zp &x) const
|
||||
{
|
||||
return operator * (x.recip ());
|
||||
}
|
||||
|
||||
Zp recip () const
|
||||
{
|
||||
triple<unsigned, int, int> t = unsigned_extended_gcd (v, p);
|
||||
assert (t.first == 1);
|
||||
assert ((int)t.first == t.second*(int)v + t.third*(int)p);
|
||||
|
||||
return Zp (t.second);
|
||||
}
|
||||
|
||||
Zp &operator += (const Zp &x)
|
||||
{
|
||||
v = (v + x.v) % p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Zp &operator -= (const Zp &x) { return operator = (Zp ((int)v - (int)x.v)); }
|
||||
|
||||
Zp &operator *= (const Zp &x)
|
||||
{
|
||||
v = (v * x.v) % p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Zp &operator /= (const Zp &x)
|
||||
{
|
||||
return operator *= (x.recip ());
|
||||
}
|
||||
|
||||
// d | n, d.divides (n)
|
||||
bool divides (const Zp &n) const
|
||||
{
|
||||
return v || !n.v;
|
||||
}
|
||||
|
||||
bool operator | (const Zp &n) const { return divides (n); }
|
||||
|
||||
Zp div (const Zp &d) const { return operator / (d); }
|
||||
|
||||
triple<Zp, Zp, Zp> extended_gcd (const Zp &x) const
|
||||
{
|
||||
if (v)
|
||||
return triple<Zp, Zp, Zp> (v, 1, 0);
|
||||
else
|
||||
return triple<Zp, Zp, Zp> (x, 0, 1);
|
||||
}
|
||||
|
||||
Zp gcd (const Zp &x) const
|
||||
{
|
||||
assert (v || x.v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void show_ring () { printf ("Z%d", p); }
|
||||
void show_self () const { printf ("%d (%d)", v, p); }
|
||||
void display_self () const { show_self (); newline (); }
|
||||
};
|
@ -40,7 +40,7 @@ int64_gcd (int64 a, int64 b)
|
||||
}
|
||||
|
||||
static triple<unsigned, int, int>
|
||||
extended_gcd_1 (unsigned a, unsigned b)
|
||||
extended_gcd_1 (int a, int b)
|
||||
{
|
||||
if (b == 0)
|
||||
return triple<unsigned, int, int> (a, 1, 0);
|
||||
@ -50,18 +50,24 @@ extended_gcd_1 (unsigned a, unsigned b)
|
||||
return triple<unsigned, int, int> (b, 0, 1);
|
||||
else
|
||||
{
|
||||
triple<unsigned, int, int> s = extended_gcd (b, t);
|
||||
triple<unsigned, int, int> s = unsigned_extended_gcd (b, t);
|
||||
|
||||
unsigned d = s.first;
|
||||
int x = s.third,
|
||||
y = s.second - s.third * (a / b);
|
||||
|
||||
assert ((int)d == (int)a*x + (int)b*y);
|
||||
assert ((int)d == a*x + b*y);
|
||||
|
||||
return triple<unsigned, int, int> (d, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
triple<unsigned, int, int>
|
||||
unsigned_extended_gcd (unsigned a, unsigned b)
|
||||
{
|
||||
return extended_gcd_1 ((int)a, (int)b);
|
||||
}
|
||||
|
||||
triple<unsigned, int, int>
|
||||
extended_gcd (int a, int b)
|
||||
{
|
||||
|
@ -44,6 +44,8 @@ uint64 int64_lcm (int64 a, int64 b);
|
||||
// (d, x, y) = gcd (a, b) where x*a + y*b = d
|
||||
triple<unsigned, int, int> extended_gcd (int a, int b);
|
||||
|
||||
triple<unsigned, int, int> unsigned_extended_gcd (unsigned a, unsigned b);
|
||||
|
||||
template<class R> class linear_combination;
|
||||
template<class R> class linear_combination_const_iter;
|
||||
|
||||
@ -60,6 +62,7 @@ template<class R> class module;
|
||||
#include <algebra/linear_combination.h>
|
||||
|
||||
#include <algebra/Z.h>
|
||||
#include <algebra/Zp.h>
|
||||
#include <algebra/Q.h>
|
||||
#include <algebra/polynomial.h>
|
||||
|
||||
|
118
main.cpp
118
main.cpp
@ -1,8 +1,126 @@
|
||||
|
||||
#include <knotkit.h>
|
||||
|
||||
// test for ring
|
||||
|
||||
template<class R> void
|
||||
test_ring (int p)
|
||||
{
|
||||
R zero (0);
|
||||
R one (1);
|
||||
R minus_one (-1);
|
||||
|
||||
assert (zero == 0);
|
||||
assert (zero | zero);
|
||||
assert (one | zero);
|
||||
assert (minus_one | zero);
|
||||
assert (! (zero | one));
|
||||
assert (! (zero | minus_one));
|
||||
|
||||
assert (one.is_unit ());
|
||||
assert (minus_one.is_unit ());
|
||||
assert (one.recip () == one);
|
||||
assert (minus_one.recip () == minus_one);
|
||||
|
||||
if (p)
|
||||
assert (R (p) == 0);
|
||||
|
||||
if (p != 2)
|
||||
assert (one != minus_one);
|
||||
|
||||
int n = (p
|
||||
? std::min (p, 20)
|
||||
: 20);
|
||||
for (int i = -n; i <= n; i ++)
|
||||
{
|
||||
R x (i);
|
||||
if (x.is_unit ())
|
||||
{
|
||||
assert (x * x.recip () == one);
|
||||
assert (x.recip () * x == one);
|
||||
assert (x.recip ().recip () == x);
|
||||
}
|
||||
|
||||
assert (one | x);
|
||||
assert (minus_one | x);
|
||||
|
||||
if (x != 0)
|
||||
{
|
||||
assert (x | zero);
|
||||
assert (! (zero | x));
|
||||
}
|
||||
|
||||
for (int j = -n; j <= n; j ++)
|
||||
{
|
||||
R y (j);
|
||||
|
||||
assert (- (-x) == x);
|
||||
assert (x + y == y + x);
|
||||
assert (x * y == y * x);
|
||||
|
||||
if (x != 0 && x | y)
|
||||
{
|
||||
R q = y.div (x);
|
||||
assert (y == q * x);
|
||||
}
|
||||
|
||||
if (x != 0 || y != 0)
|
||||
{
|
||||
triple<R, R, R> t = x.extended_gcd (y);
|
||||
assert (t.first == t.second*x + t.third*y);
|
||||
}
|
||||
|
||||
for (int k = -n; k <= n; k ++)
|
||||
{
|
||||
R z (k);
|
||||
|
||||
assert ((x + y) + z == x + (y + z));
|
||||
assert ((x * y) * z == x * (y * z));
|
||||
assert (x*(y + z) == x*y + x*z);
|
||||
assert ((x + y)*z == x*z + y*z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class F> void
|
||||
test_field ()
|
||||
{
|
||||
for (unsigned i = 1; i <= 8; i ++)
|
||||
for (unsigned j = 1; j <= rolfsen_crossing_knots (i); j ++)
|
||||
{
|
||||
knot_diagram kd (rolfsen_knot (i, j));
|
||||
|
||||
show (kd); newline ();
|
||||
|
||||
cube<F> c (kd);
|
||||
mod_map<F> d = c.compute_d (1, 0, 0, 0, 0);
|
||||
|
||||
assert (d.compose (d) == 0);
|
||||
|
||||
ptr<const quotient_module<F> > H = d.homology ();
|
||||
display ("H:\n", *H);
|
||||
|
||||
chain_complex_simplifier<F> s (c.khC, d, 1);
|
||||
display ("s.new_C:\n", *s.new_C);
|
||||
|
||||
assert (H->dim () == s.new_C->dim ());
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
test_ring<Z2> (2);
|
||||
test_ring<Z> (0);
|
||||
test_ring<Zp<2> > (2);
|
||||
test_ring<Zp<3> > (3);
|
||||
test_ring<Zp<5> > (5);
|
||||
test_ring<Zp<7> > (7);
|
||||
|
||||
test_field<Zp<7> > ();
|
||||
test_field<Zp<5> > ();
|
||||
test_field<Zp<3> > ();
|
||||
test_field<Z2> ();
|
||||
test_field<Zp<2> > ();
|
||||
}
|
||||
|
3
todo.txt
3
todo.txt
@ -17,10 +17,11 @@ in lib/
|
||||
|
||||
in algebra/
|
||||
- Q should use gmp
|
||||
- laurentpoly interface needs to be cleand up
|
||||
- laurentpoly interface needs to be cleaned up
|
||||
- add Zp
|
||||
- linear_combnation can be more efficient (eg no searching when
|
||||
coefficients die)
|
||||
- monomial ideals and maybe groebner bases
|
||||
- cleaner interface for gcd, etc. in fraction_field
|
||||
- support kernel, cokernel of torsion modules
|
||||
- change gcd et al so gcd is always positive
|
||||
|
Loading…
Reference in New Issue
Block a user