logic_circus/
implemented.rs1use std::{
2 convert::Infallible,
3 ops::{BitAnd, BitOr, BitXor, Not},
4};
5
6use crate::{util::ContainerSizeGames, Bit, GateLike};
7
8#[cfg(test)]
9mod tests;
10
11#[derive(Clone, Debug, Copy)]
12pub(super) enum RustImpls<Rust = Infallible> {
13 Dup(usize),
14 Mem(Bit),
15 Not,
16 Nand,
17 And,
18 Or,
19 Nor,
20 Xor,
21 User(Rust),
22}
23
24impl<Rust> GateLike for RustImpls<Rust>
25where
26 Rust: GateLike,
27{
28 unsafe fn compute(&mut self, mut input: Vec<Bit>) -> Vec<Bit> {
34 debug_assert_eq!(input.len(), self.num_of_inputs());
35
36 match self {
37 RustImpls::Dup(ref amount) => {
38 let value = *input.get_unchecked(0);
39 input.change_len(*amount, value)
40 }
41 RustImpls::Mem(current) => {
42 std::mem::swap(current, input.get_unchecked_mut(0));
43 input
44 }
45 RustImpls::Not => {
46 input.get_unchecked_mut(0).action_assign(Bit::not);
47 input
48 }
49 RustImpls::Nand => compute_binary_operation(input, |x, y| !(x && y)),
50 RustImpls::And => compute_binary_operation(input, Bit::bitand),
51 RustImpls::Or => compute_binary_operation(input, Bit::bitor),
52 RustImpls::Nor => compute_binary_operation(input, |x, y| !(x || y)),
53 RustImpls::Xor => compute_binary_operation(input, Bit::bitxor),
54 RustImpls::User(logic) => logic.compute(input),
55 }
56 }
57
58 fn num_of_inputs(&self) -> usize {
59 match self {
60 RustImpls::Dup(_) => 1,
61 RustImpls::Mem(_) => 1,
62 RustImpls::Not => 1,
63 RustImpls::Nand => 2,
64 RustImpls::And => 2,
65 RustImpls::Or => 2,
66 RustImpls::Nor => 2,
67 RustImpls::Xor => 2,
68 RustImpls::User(gate) => gate.num_of_inputs(),
69 }
70 }
71
72 fn reset(&mut self, full: bool) {
73 match self {
74 RustImpls::Mem(mem) if full => *mem = bool::default(),
75 RustImpls::User(gate) => gate.reset(full),
76 _ => {} }
78 }
79}
80
81unsafe fn compute_binary_operation<O>(input: Vec<Bit>, operation: O) -> Vec<Bit>
84where
85 O: FnOnce(Bit, Bit) -> Bit,
86{
87 let value = operation(*input.get_unchecked(0), *input.get_unchecked(1));
88 input.shorten(1, value)
89}
90
91trait ActionAssign: Sized + Copy {
92 fn action_assign<F>(&mut self, action: F) -> &mut Self
93 where
94 F: FnOnce(Self) -> Self,
95 {
96 *self = action(*self);
97 self
98 }
99}
100impl<T> ActionAssign for T where T: Sized + Copy {}