yui_link/braid/
braid_gen.rs1use 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}