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