1#[allow(unused_imports)]
4use crate::prelude::*;
5use core::ops::Not;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
9pub struct Var(pub u32);
10
11impl Var {
12 #[must_use]
14 pub const fn new(idx: u32) -> Self {
15 Self(idx)
16 }
17
18 #[must_use]
20 pub const fn index(self) -> usize {
21 self.0 as usize
22 }
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
27pub struct Lit(u32);
28
29impl Lit {
30 #[must_use]
32 pub const fn pos(var: Var) -> Self {
33 Self(var.0 << 1)
34 }
35
36 #[must_use]
38 pub const fn neg(var: Var) -> Self {
39 Self((var.0 << 1) | 1)
40 }
41
42 #[must_use]
45 pub fn from_dimacs(lit: i32) -> Self {
46 debug_assert!(lit != 0);
47 let var = Var::new(lit.unsigned_abs() - 1);
48 if lit > 0 {
49 Self::pos(var)
50 } else {
51 Self::neg(var)
52 }
53 }
54
55 #[must_use]
57 pub fn to_dimacs(self) -> i32 {
58 let var = (self.var().0 + 1) as i32;
59 if self.is_pos() { var } else { -var }
60 }
61
62 #[must_use]
64 pub const fn var(self) -> Var {
65 Var(self.0 >> 1)
66 }
67
68 #[must_use]
70 pub const fn is_pos(self) -> bool {
71 (self.0 & 1) == 0
72 }
73
74 #[must_use]
76 pub const fn is_neg(self) -> bool {
77 (self.0 & 1) == 1
78 }
79
80 #[must_use]
82 pub const fn negate(self) -> Self {
83 Self(self.0 ^ 1)
84 }
85
86 #[must_use]
88 pub const fn sign(self) -> bool {
89 self.is_pos()
90 }
91
92 #[must_use]
94 pub const fn code(self) -> u32 {
95 self.0
96 }
97
98 #[must_use]
100 pub const fn from_code(code: u32) -> Self {
101 Self(code)
102 }
103
104 #[must_use]
106 pub const fn index(self) -> usize {
107 self.0 as usize
108 }
109}
110
111impl Not for Lit {
112 type Output = Self;
113
114 fn not(self) -> Self::Output {
115 self.negate()
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
121pub enum LBool {
122 True,
124 False,
126 Undef,
128}
129
130impl LBool {
131 #[must_use]
133 pub const fn from_bool(b: bool) -> Self {
134 if b { Self::True } else { Self::False }
135 }
136
137 #[must_use]
139 pub const fn is_defined(self) -> bool {
140 !matches!(self, Self::Undef)
141 }
142
143 #[must_use]
145 pub const fn is_true(self) -> bool {
146 matches!(self, Self::True)
147 }
148
149 #[must_use]
151 pub const fn is_false(self) -> bool {
152 matches!(self, Self::False)
153 }
154
155 #[must_use]
157 pub const fn negate(self) -> Self {
158 match self {
159 Self::True => Self::False,
160 Self::False => Self::True,
161 Self::Undef => Self::Undef,
162 }
163 }
164}
165
166impl From<bool> for LBool {
167 fn from(b: bool) -> Self {
168 Self::from_bool(b)
169 }
170}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175
176 #[test]
177 fn test_literal_creation() {
178 let var = Var::new(0);
179 let pos = Lit::pos(var);
180 let neg = Lit::neg(var);
181
182 assert!(pos.is_pos());
183 assert!(neg.is_neg());
184 assert_eq!(pos.var(), var);
185 assert_eq!(neg.var(), var);
186 assert_eq!(pos.negate(), neg);
187 assert_eq!(neg.negate(), pos);
188 }
189
190 #[test]
191 fn test_dimacs_conversion() {
192 let lit = Lit::from_dimacs(1);
193 assert!(lit.is_pos());
194 assert_eq!(lit.var(), Var::new(0));
195 assert_eq!(lit.to_dimacs(), 1);
196
197 let lit = Lit::from_dimacs(-2);
198 assert!(lit.is_neg());
199 assert_eq!(lit.var(), Var::new(1));
200 assert_eq!(lit.to_dimacs(), -2);
201 }
202
203 #[test]
204 fn test_lbool() {
205 assert!(LBool::True.is_true());
206 assert!(LBool::False.is_false());
207 assert!(!LBool::Undef.is_defined());
208
209 assert_eq!(LBool::True.negate(), LBool::False);
210 assert_eq!(LBool::False.negate(), LBool::True);
211 assert_eq!(LBool::Undef.negate(), LBool::Undef);
212 }
213}