#[derive(Debug, Clone, PartialEq)]
pub struct Manifold3 {
pub name: String,
pub genus: Option<u32>,
pub is_orientable: bool,
pub is_closed: bool,
pub boundary_components: u32,
}
impl Manifold3 {
pub fn new(
name: impl Into<String>,
genus: Option<u32>,
is_orientable: bool,
is_closed: bool,
boundary_components: u32,
) -> Self {
Self {
name: name.into(),
genus,
is_orientable,
is_closed,
boundary_components,
}
}
pub fn s3() -> Self {
Self::new("S^3", Some(0), true, true, 0)
}
pub fn t3() -> Self {
Self::new("T^3", Some(3), true, true, 0)
}
pub fn rp3() -> Self {
Self::new("RP^3", None, false, true, 0)
}
pub fn solid_torus() -> Self {
Self::new("D^2 x S^1", Some(1), true, false, 1)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct HeegaardSplitting {
pub genus: usize,
pub manifold: String,
}
impl HeegaardSplitting {
pub fn new(genus: usize, manifold: impl Into<String>) -> Self {
Self {
genus,
manifold: manifold.into(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct DehnSurgery {
pub manifold: String,
pub knot: String,
pub slope: (i64, i64),
}
impl DehnSurgery {
pub fn new(manifold: impl Into<String>, knot: impl Into<String>, slope: (i64, i64)) -> Self {
Self {
manifold: manifold.into(),
knot: knot.into(),
slope,
}
}
}
#[derive(Debug, Clone)]
pub struct JSJDecomposition {
pub pieces: Vec<ManifoldPiece>,
pub gluing: Vec<(usize, usize, Matrix2x2)>,
}
impl JSJDecomposition {
pub fn new(pieces: Vec<ManifoldPiece>, gluing: Vec<(usize, usize, Matrix2x2)>) -> Self {
Self { pieces, gluing }
}
pub fn num_pieces(&self) -> usize {
self.pieces.len()
}
}
#[derive(Debug, Clone)]
pub enum ManifoldPiece {
Seifert(SeifertFibered),
Hyperbolic(HyperbolicPiece),
IBundle,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SeifertFibered {
pub base_orbifold: String,
pub exceptional_fibers: Vec<(i64, i64)>,
}
impl SeifertFibered {
pub fn new(base_orbifold: impl Into<String>, exceptional_fibers: Vec<(i64, i64)>) -> Self {
Self {
base_orbifold: base_orbifold.into(),
exceptional_fibers,
}
}
pub fn lens_space_seifert(p: i64, q: i64) -> Self {
Self::new("S^2", vec![(p, q), (1, 0)])
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct HyperbolicPiece {
pub volume: f64,
pub cusps: u32,
}
impl HyperbolicPiece {
pub fn new(volume: f64, cusps: u32) -> Self {
Self { volume, cusps }
}
pub fn figure_eight_complement() -> Self {
Self::new(2.029_883_212_819_307_5, 1)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Matrix2x2 {
pub a: i64,
pub b: i64,
pub c: i64,
pub d: i64,
}
impl Matrix2x2 {
pub fn new(a: i64, b: i64, c: i64, d: i64) -> Self {
Self { a, b, c, d }
}
pub fn identity() -> Self {
Self::new(1, 0, 0, 1)
}
pub fn det(&self) -> i64 {
self.a * self.d - self.b * self.c
}
pub fn surgery_matrix(p: i64, q: i64) -> Self {
let (s, t) = bezout_coefficients(p, q);
Self::new(p, -t, q, s)
}
}
pub(super) fn bezout_coefficients(a: i64, b: i64) -> (i64, i64) {
if b == 0 {
return (1, 0);
}
let (s1, t1) = bezout_coefficients(b, a % b);
(t1, s1 - (a / b) * t1)
}