1use std::{
2 borrow::Cow,
3 fmt::{Debug, Display},
4 ops::{Index, IndexMut},
5 slice::SliceIndex,
6 str::FromStr,
7};
8
9use crate::Net;
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub enum Trit {
18 Undef = -1,
19 Zero = 0,
20 One = 1,
21}
22
23impl Trit {
24 pub fn from_char(chr: char) -> Result<Self, ()> {
25 match chr {
26 '0' => Ok(Trit::Zero),
27 '1' => Ok(Trit::One),
28 'X' => Ok(Trit::Undef),
29 _ => Err(()),
30 }
31 }
32
33 pub fn lit(chr: char) -> Self {
34 Self::from_char(chr).unwrap()
35 }
36
37 pub fn combine(lft: Trit, rgt: Trit) -> Option<Trit> {
38 match (lft, rgt) {
39 (Trit::Undef, trit) | (trit, Trit::Undef) => Some(trit),
40 _ if lft == rgt => Some(lft),
41 _ => None,
42 }
43 }
44
45 pub fn mux<'a, 'b>(self, arg1: impl Into<Cow<'a, Const>>, arg2: impl Into<Cow<'b, Const>>) -> Const {
46 let arg1 = arg1.into();
47 let arg2 = arg2.into();
48 match self {
49 Trit::One => arg1.into_owned(),
50 Trit::Zero => arg2.into_owned(),
51 Trit::Undef => {
52 Const::from_iter(arg1.iter().zip(arg2.iter()).map(|(x, y)| if x == y { x } else { Trit::Undef }))
53 }
54 }
55 }
56}
57
58impl Display for Trit {
59 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
60 match self {
61 Trit::Undef => write!(f, "X"),
62 Trit::Zero => write!(f, "0"),
63 Trit::One => write!(f, "1"),
64 }
65 }
66}
67
68impl FromStr for Trit {
69 type Err = ();
70
71 fn from_str(s: &str) -> Result<Self, Self::Err> {
72 match s {
73 "X" => Ok(Trit::Undef),
74 "0" => Ok(Trit::Zero),
75 "1" => Ok(Trit::One),
76 _ => Err(()),
77 }
78 }
79}
80
81impl From<bool> for Trit {
82 fn from(value: bool) -> Self {
83 match value {
84 false => Trit::Zero,
85 true => Trit::One,
86 }
87 }
88}
89
90impl TryFrom<Net> for Trit {
91 type Error = ();
92
93 fn try_from(value: Net) -> Result<Self, Self::Error> {
94 if value == Net::UNDEF {
95 Ok(Trit::Undef)
96 } else if value == Net::ZERO {
97 Ok(Trit::Zero)
98 } else if value == Net::ONE {
99 Ok(Trit::One)
100 } else {
101 Err(())
102 }
103 }
104}
105
106impl std::ops::Not for Trit {
107 type Output = Trit;
108
109 fn not(self) -> Self::Output {
110 match self {
111 Trit::One => Trit::Zero,
112 Trit::Zero => Trit::One,
113 Trit::Undef => Trit::Undef,
114 }
115 }
116}
117
118impl std::ops::BitAnd<Trit> for Trit {
119 type Output = Trit;
120
121 fn bitand(self, rhs: Trit) -> Self::Output {
122 match (self, rhs) {
123 (Trit::Zero, _) => Trit::Zero,
124 (_, Trit::Zero) => Trit::Zero,
125 (Trit::Undef, _) => Trit::Undef,
126 (_, Trit::Undef) => Trit::Undef,
127 (Trit::One, Trit::One) => Trit::One,
128 }
129 }
130}
131
132impl std::ops::BitOr<Trit> for Trit {
133 type Output = Trit;
134
135 fn bitor(self, rhs: Trit) -> Self::Output {
136 match (self, rhs) {
137 (Trit::One, _) => Trit::One,
138 (_, Trit::One) => Trit::One,
139 (Trit::Undef, _) => Trit::Undef,
140 (_, Trit::Undef) => Trit::Undef,
141 (Trit::Zero, Trit::Zero) => Trit::Zero,
142 }
143 }
144}
145
146impl std::ops::BitXor<Trit> for Trit {
147 type Output = Trit;
148
149 fn bitxor(self, rhs: Trit) -> Self::Output {
150 match (self, rhs) {
151 (Trit::Undef, _) => Trit::Undef,
152 (_, Trit::Undef) => Trit::Undef,
153 (Trit::One, Trit::One) => Trit::Zero,
154 (Trit::One, Trit::Zero) => Trit::One,
155 (Trit::Zero, Trit::One) => Trit::One,
156 (Trit::Zero, Trit::Zero) => Trit::Zero,
157 }
158 }
159}
160
161#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
163pub struct Const {
164 trits: Vec<Trit>,
165}
166
167impl Const {
168 pub const fn new() -> Self {
170 Self { trits: vec![] }
171 }
172
173 pub fn zero(width: usize) -> Self {
175 Self::from_iter(std::iter::repeat_n(Trit::Zero, width))
176 }
177
178 pub fn ones(width: usize) -> Self {
180 Self::from_iter(std::iter::repeat_n(Trit::One, width))
181 }
182
183 pub fn undef(width: usize) -> Self {
185 Self::from_iter(std::iter::repeat_n(Trit::Undef, width))
186 }
187
188 pub fn one_hot(width: usize, hot_at: usize) -> Self {
190 assert!(hot_at < width);
191 Self::from_iter((0..width).map(|index| if index == hot_at { Trit::One } else { Trit::Zero }))
192 }
193
194 pub fn push(&mut self, trit: impl Into<Trit>) {
196 self.trits.push(trit.into());
197 }
198
199 pub fn from_uint(val: u128, bits: usize) -> Self {
200 let mut trits = vec![];
201 if bits < 128 {
202 assert!(val < (1 << bits));
203 }
204 for i in 0..bits {
205 let trit = if i < u128::BITS as usize && ((val >> i) & 1) != 0 { Trit::One } else { Trit::Zero };
206 trits.push(trit);
207 }
208 Self { trits }
209 }
210
211 pub fn lit(value: &str) -> Self {
212 value.parse().unwrap()
213 }
214
215 pub fn len(&self) -> usize {
216 self.trits.len()
217 }
218
219 pub fn is_empty(&self) -> bool {
220 self.trits.is_empty()
221 }
222
223 pub fn iter(&self) -> impl DoubleEndedIterator<Item = Trit> + ExactSizeIterator + '_ {
224 self.trits.iter().copied()
225 }
226
227 pub fn lsb(&self) -> Trit {
228 self.trits[0]
229 }
230
231 pub fn msb(&self) -> Trit {
232 self.trits[self.len() - 1]
233 }
234
235 pub fn is_zero(&self) -> bool {
236 self.trits.iter().all(|&trit| trit == Trit::Zero)
237 }
238
239 pub fn is_ones(&self) -> bool {
240 self.trits.iter().all(|&trit| trit == Trit::One)
241 }
242
243 pub fn is_undef(&self) -> bool {
244 self.trits.iter().all(|&trit| trit == Trit::Undef)
245 }
246
247 pub fn has_undef(&self) -> bool {
248 self.trits.iter().any(|&trit| trit == Trit::Undef)
249 }
250
251 pub fn as_power_of_two(&self) -> Option<u32> {
252 let mut result = None;
253 for (offset, trit) in self.trits.iter().copied().enumerate() {
254 if trit == Trit::Undef {
255 return None;
256 }
257 if trit == Trit::One {
258 if result.is_some() {
259 return None;
260 }
261 result = Some(offset as u32);
262 }
263 }
264 result
265 }
266
267 pub fn concat<'a>(&self, other: impl Into<Cow<'a, Const>>) -> Self {
268 Self::from_iter(self.iter().chain(other.into().iter()))
269 }
270
271 pub fn repeat(&self, count: usize) -> Self {
272 Const::from_iter((0..count).flat_map(|_| self))
273 }
274
275 pub fn slice(&self, range: impl std::ops::RangeBounds<usize>) -> Const {
276 Const::from_iter(self[(range.start_bound().cloned(), range.end_bound().cloned())].iter().copied())
277 }
278
279 pub fn combine<'a, 'b>(lft: impl Into<Cow<'a, Const>>, rgt: impl Into<Cow<'b, Const>>) -> Option<Const> {
280 let (lft, rgt) = (lft.into(), rgt.into());
281 assert_eq!(lft.len(), rgt.len());
282 let mut trits = vec![];
283 for (lft, rgt) in std::iter::zip(lft.iter(), rgt.iter()) {
284 trits.push(Trit::combine(lft, rgt)?);
285 }
286 Some(Const { trits })
287 }
288
289 pub fn not(&self) -> Const {
290 Const::from_iter(self.iter().map(|x| !x))
291 }
292
293 pub fn and<'a>(&self, other: impl Into<Cow<'a, Const>>) -> Const {
294 let other = other.into();
295 assert_eq!(self.len(), other.len());
296 Const::from_iter(self.iter().zip(other.iter()).map(|(x, y)| x & y))
297 }
298
299 pub fn or<'a>(&self, other: impl Into<Cow<'a, Const>>) -> Const {
300 let other = other.into();
301 assert_eq!(self.len(), other.len());
302 Const::from_iter(self.iter().zip(other.iter()).map(|(x, y)| x | y))
303 }
304
305 pub fn xor<'a>(&self, other: impl Into<Cow<'a, Const>>) -> Const {
306 let other = other.into();
307 assert_eq!(self.len(), other.len());
308 Const::from_iter(self.iter().zip(other.iter()).map(|(x, y)| x ^ y))
309 }
310
311 pub fn adc<'a>(&self, other: impl Into<Cow<'a, Const>>, ci: Trit) -> Const {
312 let other = other.into();
313 assert_eq!(self.len(), other.len());
314 let mut sum = vec![];
315 let mut carry = ci;
316 for (a, b) in self.iter().zip(other.iter()) {
317 let (y, co) = match (a, b, carry) {
318 (Trit::Undef, _, _) => (Trit::Undef, Trit::Undef),
319 (_, Trit::Undef, _) => (Trit::Undef, Trit::Undef),
320 (_, _, Trit::Undef) => (Trit::Undef, Trit::Undef),
321 (Trit::Zero, Trit::Zero, s) => (s, Trit::Zero),
322 (Trit::Zero, s, Trit::Zero) => (s, Trit::Zero),
323 (s, Trit::Zero, Trit::Zero) => (s, Trit::Zero),
324 (Trit::One, Trit::One, s) => (s, Trit::One),
325 (Trit::One, s, Trit::One) => (s, Trit::One),
326 (s, Trit::One, Trit::One) => (s, Trit::One),
327 };
328 carry = co;
329 sum.push(y);
330 }
331 sum.push(carry);
332 Const::from_iter(sum)
333 }
334
335 pub fn eq<'a>(&self, other: impl Into<Cow<'a, Const>>) -> Trit {
336 let other = other.into();
337 assert_eq!(self.len(), other.len());
338 let mut undef = false;
339 for (x, y) in self.iter().zip(other.iter()) {
340 if x == Trit::Undef || y == Trit::Undef {
341 undef = true;
342 } else if x != y {
343 return Trit::Zero;
344 }
345 }
346 if undef {
347 Trit::Undef
348 } else {
349 Trit::One
350 }
351 }
352
353 pub fn ult<'a>(&self, other: impl Into<Cow<'a, Const>>) -> Trit {
354 let other = other.into();
355 assert_eq!(self.len(), other.len());
356 if self.has_undef() || other.has_undef() {
357 Trit::Undef
358 } else {
359 for (x, y) in self.iter().zip(other.iter()).rev() {
360 if x != y {
361 return Trit::from(x < y);
362 }
363 }
364 Trit::Zero
365 }
366 }
367
368 pub fn slt<'a>(&self, other: impl Into<Cow<'a, Const>>) -> Trit {
369 let other = other.into();
370 assert_eq!(self.len(), other.len());
371 if self.has_undef() || other.has_undef() {
372 Trit::Undef
373 } else if self.msb() != other.msb() {
374 Trit::from(self.msb() > other.msb())
375 } else {
376 for (x, y) in self.iter().zip(other.iter()).rev() {
377 if x != y {
378 return Trit::from(x < y);
379 }
380 }
381 Trit::Zero
382 }
383 }
384
385 pub fn mul<'a>(&self, other: impl Into<Cow<'a, Const>>) -> Const {
386 let other = other.into();
387 assert_eq!(self.len(), other.len());
388 if self.has_undef() || other.has_undef() {
389 Const::undef(self.len())
390 } else {
391 let mut res = Const::zero(self.len());
392 for (i, bit) in other.iter().enumerate() {
393 if bit == Trit::One {
394 res = res.adc(Const::zero(i).concat(self), Trit::Zero);
395 } else {
396 res.trits.push(Trit::Zero);
397 }
398 }
399 res.slice(..self.len())
400 }
401 }
402}
403
404impl Debug for Const {
405 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
406 write!(f, "Const::from_iter([")?;
407 for (index, trit) in self.trits.iter().enumerate() {
408 if index != 0 {
409 write!(f, ", ")?;
410 }
411 write!(f, "{:?}", trit)?;
412 }
413 write!(f, "])")?;
414 Ok(())
415 }
416}
417
418impl Display for Const {
419 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
420 for trit in self.trits.iter().rev() {
421 write!(f, "{}", trit)?;
422 }
423 Ok(())
424 }
425}
426
427impl FromStr for Const {
428 type Err = ();
429
430 fn from_str(s: &str) -> Result<Self, Self::Err> {
431 let mut trits = vec![];
432 for char in s.chars().rev() {
433 trits.push(Trit::from_char(char)?)
434 }
435 Ok(Const { trits })
436 }
437}
438
439impl TryFrom<&Const> for u64 {
440 type Error = ();
441
442 fn try_from(value: &Const) -> Result<Self, Self::Error> {
443 if value.has_undef() {
444 return Err(());
445 }
446 let mut result = 0;
447 for (index, trit) in value.iter().enumerate() {
448 if trit == Trit::One {
449 if index >= 64 {
450 return Err(());
451 }
452 result |= 1 << index;
453 }
454 }
455 Ok(result)
456 }
457}
458
459impl TryFrom<&Const> for i64 {
460 type Error = ();
461
462 fn try_from(value: &Const) -> Result<Self, Self::Error> {
463 if value.has_undef() {
464 return Err(());
465 }
466 let mut width = value.len();
467 while width > 1 && value[width - 1] == value[width - 2] {
468 width -= 1;
469 }
470 if width > Self::BITS as usize {
471 return Err(());
472 }
473 let mut result = 0;
474 for (index, trit) in value.iter().enumerate() {
475 if trit == Trit::One {
476 if index == width - 1 {
477 result |= -1 << index;
478 } else {
479 result |= 1 << index;
480 }
481 }
482 }
483 Ok(result)
484 }
485}
486
487impl<I: SliceIndex<[Trit]>> Index<I> for Const {
488 type Output = I::Output;
489
490 fn index(&self, index: I) -> &Self::Output {
491 &self.trits[index]
492 }
493}
494
495impl<I: SliceIndex<[Trit]>> IndexMut<I> for Const {
496 fn index_mut(&mut self, index: I) -> &mut Self::Output {
497 &mut self.trits[index]
498 }
499}
500
501impl Extend<Trit> for Const {
502 fn extend<T: IntoIterator<Item = Trit>>(&mut self, iter: T) {
503 for trit in iter {
504 self.trits.push(trit);
505 }
506 }
507}
508
509impl From<Trit> for Const {
510 fn from(trit: Trit) -> Self {
511 Const { trits: vec![trit] }
512 }
513}
514
515impl From<Vec<Trit>> for Const {
516 fn from(trits: Vec<Trit>) -> Self {
517 Const { trits }
518 }
519}
520
521impl From<Trit> for Cow<'_, Const> {
522 fn from(value: Trit) -> Self {
523 Cow::Owned(Const::from(value))
524 }
525}
526
527impl From<Const> for Cow<'_, Const> {
528 fn from(value: Const) -> Self {
529 Cow::Owned(value)
530 }
531}
532
533impl<'a> From<&'a Const> for Cow<'a, Const> {
534 fn from(value: &'a Const) -> Self {
535 Cow::Borrowed(value)
536 }
537}
538
539impl FromIterator<Trit> for Const {
540 fn from_iter<T: IntoIterator<Item = Trit>>(iter: T) -> Self {
541 Const { trits: iter.into_iter().collect() }
542 }
543}
544
545impl IntoIterator for &Const {
546 type Item = Trit;
547 type IntoIter = std::vec::IntoIter<Trit>;
548
549 fn into_iter(self) -> Self::IntoIter {
550 self.trits.clone().into_iter()
551 }
552}
553
554impl IntoIterator for Const {
555 type Item = Trit;
556 type IntoIter = std::vec::IntoIter<Trit>;
557
558 fn into_iter(self) -> Self::IntoIter {
559 self.trits.into_iter()
560 }
561}
562
563#[cfg(test)]
564mod test {
565 use crate::{Const, Trit};
566
567 #[test]
568 fn test_not() {
569 for (a, y) in [("", ""), ("01", "10"), ("X10", "X01")] {
570 assert_eq!(Const::lit(a).not(), Const::lit(y));
571 }
572 }
573
574 #[test]
575 fn test_and() {
576 for (a, b, y) in [("", "", ""), ("1010", "1100", "1000"), ("X0X0", "XX00", "X000"), ("X1X1", "XX11", "XXX1")] {
577 assert_eq!(Const::lit(a).and(Const::lit(b)), Const::lit(y));
578 }
579 }
580
581 #[test]
582 fn test_or() {
583 for (a, b, y) in [("", "", ""), ("1010", "1100", "1110"), ("X0X0", "XX00", "XXX0"), ("X1X1", "XX11", "X111")] {
584 assert_eq!(Const::lit(a).or(Const::lit(b)), Const::lit(y));
585 }
586 }
587
588 #[test]
589 fn test_xor() {
590 for (a, b, y) in [("", "", ""), ("1010", "1100", "0110"), ("X0X0", "XX00", "XXX0"), ("X1X1", "XX11", "XXX0")] {
591 assert_eq!(Const::lit(a).xor(Const::lit(b)), Const::lit(y));
592 }
593 }
594
595 #[test]
596 fn test_mux() {
597 for (s, a, b, y) in [
598 ('0', "", "", ""),
599 ('0', "XXX101010", "X10XX1100", "X10XX1100"),
600 ('1', "XXX101010", "X10XX1100", "XXX101010"),
601 ('X', "XXX101010", "X10XX1100", "XXXXX1XX0"),
602 ] {
603 assert_eq!(Trit::lit(s).mux(Const::lit(a), Const::lit(b)), Const::lit(y));
604 }
605 }
606
607 #[test]
608 fn test_adc() {
609 for (a, b, c, y) in [
610 ("", "", '0', "0"),
611 ("", "", '1', "1"),
612 ("10101010", "11001100", '0', "101110110"),
613 ("1101", "1111", '1', "11101"),
614 ("1010X010", "11001100", '0', "XXXXXX110"),
615 ] {
616 assert_eq!(Const::lit(a).adc(Const::lit(b), Trit::lit(c)), Const::lit(y));
617 }
618 }
619
620 #[test]
621 fn test_mul() {
622 for (a, b, y) in [("", "", ""), ("0011", "0011", "1001"), ("0X11", "0011", "XXXX"), ("1101", "1101", "1001")] {
623 assert_eq!(Const::lit(a).mul(Const::lit(b)), Const::lit(y));
624 }
625 }
626}