relp_num/
binary.rs

1//! # Binary data
2//!
3//! A number type that is either zero or one.
4use std::fmt;
5use std::ops::{Add, AddAssign, Mul};
6
7use crate::NonZero;
8
9/// # Binary
10///
11/// A zero-one data type used primarily for the cost in the artificial tableau.
12///
13/// Note that addition works like addition in the group GF(2).
14///
15/// See also the documentation in relp::algorithm::two_phase::tableau::kind::artificial::Cost.
16#[derive(Eq, PartialEq, Copy, Clone, Debug)]
17#[allow(missing_docs)]
18pub enum Binary {
19    Zero,
20    One,
21}
22
23impl NonZero for Binary {
24    fn is_not_zero(&self) -> bool {
25        match self {
26            Binary::Zero => false,
27            Binary::One => true,
28        }
29    }
30}
31
32impl num_traits::Zero for Binary {
33    fn zero() -> Self {
34        Self::Zero
35    }
36
37    fn is_zero(&self) -> bool {
38        self == &Binary::Zero
39    }
40}
41
42impl num_traits::One for Binary {
43    fn one() -> Self {
44        Self::One
45    }
46}
47
48impl Default for Binary {
49    fn default() -> Self {
50        Self::Zero
51    }
52}
53
54impl fmt::Display for Binary {
55    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56        f.write_str(match self {
57            Binary::Zero => "0",
58            Binary::One => "1",
59        })
60    }
61}
62
63impl Add<Binary> for Binary {
64    type Output = Self;
65
66    fn add(self, rhs: Binary) -> Self::Output {
67        match (self, rhs) {
68            (Binary::Zero, Binary::Zero) => Binary::Zero,
69            (Binary::Zero, Binary::One) => Binary::One,
70            (Binary::One, Binary::Zero) => Binary::One,
71            (Binary::One, Binary::One) => Binary::Zero,
72        }
73    }
74}
75
76impl Mul<Binary> for Binary {
77    type Output = Self;
78
79    fn mul(self, rhs: Binary) -> Self::Output {
80        match (self, rhs) {
81            (Binary::One, Binary::One) => Binary::One,
82            _ => Binary::Zero,
83        }
84    }
85}
86
87macro_rules! define_ops {
88    ($primitive:ident) => {
89        impl From<Binary> for $primitive {
90            fn from(other: Binary) -> Self {
91                From::from(&other)
92            }
93        }
94
95        impl From<&Binary> for $primitive {
96            fn from(other: &Binary) -> Self {
97                match other {
98                    Binary::Zero => 0,
99                    Binary::One => 1,
100                }
101            }
102        }
103
104        impl Add<Binary> for $primitive {
105            type Output = Self;
106
107            fn add(self, rhs: Binary) -> Self::Output {
108                Add::add(self, &rhs)
109            }
110        }
111
112        impl Add<&Binary> for $primitive {
113            type Output = Self;
114
115            fn add(self, rhs: &Binary) -> Self::Output {
116                match rhs {
117                    Binary::Zero => self,
118                    Binary::One => self + 1,
119                }
120            }
121        }
122
123        impl AddAssign<&Binary> for $primitive {
124            fn add_assign(&mut self, rhs: &Binary) {
125                match rhs {
126                    Binary::Zero => {},
127                    Binary::One => *self += 1,
128                }
129            }
130        }
131
132        impl Mul<Binary> for $primitive {
133            type Output = Self;
134
135            fn mul(self, rhs: Binary) -> Self::Output {
136                Mul::mul(self, &rhs)
137            }
138        }
139
140        impl Mul<&Binary> for $primitive {
141            type Output = Self;
142
143            fn mul(self, rhs: &Binary) -> Self::Output {
144                match rhs {
145                    Binary::Zero => 0,
146                    Binary::One => self,
147                }
148            }
149        }
150
151        impl Mul<&Binary> for &$primitive {
152            type Output = $primitive;
153
154            fn mul(self, rhs: &Binary) -> Self::Output {
155                match rhs {
156                    Binary::Zero => 0,
157                    Binary::One => *self,
158                }
159            }
160        }
161    }
162}
163
164define_ops!(i8);
165define_ops!(i16);
166define_ops!(i32);
167define_ops!(i64);
168define_ops!(i128);
169define_ops!(u8);
170define_ops!(u16);
171define_ops!(u32);
172define_ops!(u64);
173define_ops!(u128);
174
175#[cfg(test)]
176mod test {
177    use crate::Binary;
178
179    #[test]
180    fn test_integer() {
181        assert_eq!(1 + Binary::One, 2);
182        assert_eq!(-1 + Binary::One, 0);
183        assert_eq!(894 * Binary::One, 894);
184        assert_eq!(-894 * &Binary::One, -894);
185        assert_eq!(0_u8 * &Binary::One, 0);
186
187        assert_eq!(1 + Binary::Zero, 1);
188        assert_eq!(-1 + Binary::Zero, -1);
189        assert_eq!(894 * Binary::Zero, 0);
190        assert_eq!(-894 * &Binary::Zero, 0);
191        assert_eq!(0_u8 * &Binary::Zero, 0);
192    }
193}