Skip to main content

yui_link/braid/
braid_gen.rs

1//! [`BraidGen`]: a signed Artin generator `σ_i^{±1}`, stored as a single `i8`
2//! whose absolute value is the 1-based strand index.
3
4use derive_more::{Display, Debug};
5use num_traits::Zero;
6use yui_core::num::{GetSign, Sign};
7
8#[derive(Clone, Copy, PartialEq, Eq, Display, Debug)]
9#[display("{}", _0)]
10#[  debug("{}", _0)]
11pub struct BraidGen(i8);
12
13impl BraidGen {
14    pub fn new(val: i8) -> Self {
15        Self::from(val)
16    }
17
18    pub fn index(&self) -> usize {
19        self.0.unsigned_abs() as usize
20    }
21
22    pub fn sign(&self) -> Sign {
23        self.0.sign()
24    }
25
26    pub fn inv(&self) -> Self {
27        Self(-self.0)
28    }
29}
30
31macro_rules! impl_from_int {
32    ($($t:ty),* $(,)?) => {
33        $(
34            impl From<$t> for BraidGen {
35                fn from(value: $t) -> Self {
36                    assert!(!value.is_zero());
37                    let v = i8::try_from(value).expect("BraidGen value must fit in i8");
38                    Self(v)
39                }
40            }
41        )*
42    };
43}
44
45impl_from_int!(i8, i16, i32, i64);
46
47pub(super) fn from_raw(value: i8) -> BraidGen {
48    BraidGen(value)
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn new_pos() {
57        let g = BraidGen::new(1);
58        assert_eq!(g.index(), 1);
59        assert!(g.sign().is_positive());
60    }
61
62    #[test]
63    fn new_neg() {
64        let g = BraidGen::new(-2);
65        assert_eq!(g.index(), 2);
66        assert!(g.sign().is_negative());
67    }
68
69    #[test]
70    #[should_panic]
71    fn new_zero_panics() {
72        BraidGen::new(0);
73    }
74
75    #[test]
76    fn from_i32() {
77        let g = BraidGen::from(3);
78        assert_eq!(g.index(), 3);
79        assert!(g.sign().is_positive());
80
81        let g = BraidGen::from(-3);
82        assert_eq!(g.index(), 3);
83        assert!(g.sign().is_negative());
84    }
85
86    #[test]
87    #[should_panic]
88    fn from_zero_panics() {
89        let _ = BraidGen::from(0);
90    }
91
92    #[test]
93    fn inv() {
94        let g = BraidGen::from(2);
95        let h = g.inv();
96        assert_eq!(h.index(), 2);
97        assert!(h.sign().is_negative());
98        assert_eq!(h.inv(), g);
99    }
100
101    #[test]
102    fn to_string() {
103        assert_eq!(BraidGen::from(3).to_string(), "3");
104        assert_eq!(BraidGen::from(-3).to_string(), "-3");
105    }
106}