Skip to main content

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