|
@@ -1,6 +1,5 @@
|
1
|
1
|
use crate::{gate::Gate, gate_type::GateType};
|
2
|
2
|
|
3
|
|
-
|
4
|
3
|
#[derive(Debug, Clone)]
|
5
|
4
|
pub struct Circuit {
|
6
|
5
|
pub input_bits: Vec<bool>, // Input wires
|
|
@@ -9,7 +8,7 @@ pub struct Circuit {
|
9
|
8
|
|
10
|
9
|
impl Circuit {
|
11
|
10
|
pub fn eval(self) -> bool {
|
12
|
|
- let mut evaluated_gates = vec!();
|
|
11
|
+ let mut evaluated_gates = vec![];
|
13
|
12
|
|
14
|
13
|
for gate in self.gates {
|
15
|
14
|
let result = gate.eval(&self.input_bits, &evaluated_gates);
|
|
@@ -18,8 +17,8 @@ impl Circuit {
|
18
|
17
|
|
19
|
18
|
match evaluated_gates.pop() {
|
20
|
19
|
Some(result) => result,
|
21
|
|
- None => panic!("Bruh moment")
|
22
|
|
- }
|
|
20
|
+ None => panic!("Bruh moment"),
|
|
21
|
+ }
|
23
|
22
|
}
|
24
|
23
|
|
25
|
24
|
/*
|
|
@@ -27,13 +26,17 @@ impl Circuit {
|
27
|
26
|
bits) is greater than the second number B (encoded in the next n bits) .
|
28
|
27
|
*/
|
29
|
28
|
pub fn compare_n_bit_numbers(input_bits: Vec<bool>, n: usize) -> Self {
|
30
|
|
- if input_bits.len() < 2*n {
|
31
|
|
- panic!("Expected input_bits to be of at least length {}, but it was {}", 2*n, input_bits.len())
|
|
29
|
+ if input_bits.len() < 2 * n {
|
|
30
|
+ panic!(
|
|
31
|
+ "Expected input_bits to be of at least length {}, but it was {}",
|
|
32
|
+ 2 * n,
|
|
33
|
+ input_bits.len()
|
|
34
|
+ )
|
32
|
35
|
}
|
33
|
36
|
|
34
|
37
|
/*
|
35
|
|
- base case n=1: 1-bit:
|
36
|
|
-
|
|
38
|
+ base case n=1: 1-bit:
|
|
39
|
+
|
37
|
40
|
A B | A > B
|
38
|
41
|
-----------
|
39
|
42
|
0 0 | 0
|
|
@@ -62,81 +65,82 @@ impl Circuit {
|
62
|
65
|
1 1 1 0 | 1 | 1
|
63
|
66
|
1 1 1 1 | 0 | 0
|
64
|
67
|
|
65
|
|
- The inductive pattern should become apparent now.
|
66
|
|
- For illustration here's the case for n=4, which should show the
|
67
|
|
- recursive characteristics of the formula.
|
|
68
|
+ The inductive pattern should become apparent now.
|
|
69
|
+ For illustration here's the case for n=4, which should show the
|
|
70
|
+ recursive characteristics of the formula.
|
68
|
71
|
|
69
|
|
- (A3 > B3) ||
|
70
|
|
- ((A3 == B3) && (A2 > B2)) ||
|
|
72
|
+ (A3 > B3) ||
|
|
73
|
+ ((A3 == B3) && (A2 > B2)) ||
|
71
|
74
|
((A3 == B3) && (A2 == B2) && (A1 > B1)) ||
|
72
|
75
|
((A3 == B3) && (A2 == B2) && (A1 == B1)) && (A0 > B0))
|
73
|
76
|
|
74
|
77
|
*/
|
75
|
78
|
|
76
|
79
|
let gates = create_n_bit_comparator_gates(n);
|
77
|
|
- return Circuit { input_bits, gates }
|
|
80
|
+ return Circuit { input_bits, gates };
|
78
|
81
|
}
|
79
|
82
|
}
|
80
|
83
|
|
81
|
|
-
|
82
|
|
-fn create_n_bit_comparator_gates(n: usize) -> Vec<Gate>{
|
|
84
|
+fn create_n_bit_comparator_gates(n: usize) -> Vec<Gate> {
|
83
|
85
|
let mut indices: Vec<usize> = vec![0; n];
|
84
|
|
- let mut all_gates: Vec<Gate> = vec!();
|
85
|
|
- let mut and_gate_indices: Vec<usize> = vec!();
|
86
|
|
-
|
87
|
|
-
|
88
|
|
-
|
89
|
|
- rec_n_bit_comperator_gates(0, n, &mut all_gates, &mut and_gate_indices, &mut indices, );
|
90
|
|
-
|
91
|
|
- // the OR spanning all ANDs
|
92
|
|
- let or_gate = Gate::new( GateType::Or, and_gate_indices, vec!());
|
93
|
|
-
|
94
|
|
- all_gates.push(or_gate);
|
95
|
|
-
|
96
|
|
- return all_gates;
|
97
|
|
-}
|
98
|
|
-
|
99
|
|
-fn rec_n_bit_comperator_gates(curr: usize, max: usize, all_gates: &mut Vec<Gate>, and_gate_incides: &mut Vec<usize>, indices: &mut Vec<usize>){
|
100
|
|
- // Incrementing gate index
|
101
|
|
- let a_curr_gt_b_curr_gate_index = all_gates.len();
|
102
|
|
-
|
103
|
|
- // Gate(A_current > B_current)
|
104
|
|
- let a_curr_gt_b_curr_gate = Gate::new(GateType::Bigger, vec!(), vec!(curr, curr+max));
|
105
|
|
-
|
106
|
|
- // A_current>B_current
|
107
|
|
- //print!(" ( ({}) ", format!("{} > {}", format!("A{}", max-1-curr), format!("B{}", max-1-curr)));
|
108
|
|
-
|
109
|
|
- all_gates.push(a_curr_gt_b_curr_gate);
|
110
|
|
-
|
111
|
|
- let mut this_recursion_gate_indices: Vec<usize> = vec!(a_curr_gt_b_curr_gate_index);
|
|
86
|
+ let mut all_gates: Vec<Gate> = Vec::with_capacity(1+3*n);
|
|
87
|
+ let mut and_gate_indices: Vec<usize> = vec![0; n];
|
|
88
|
+
|
|
89
|
+ for curr in 0..n {
|
|
90
|
+ // Gate(A_current > B_current)
|
|
91
|
+ let gt_gate = Gate::new(GateType::Bigger, vec![], vec![curr, curr + n]);
|
|
92
|
+ let gt_gate_index = all_gates.len();
|
|
93
|
+ all_gates.push(gt_gate);
|
|
94
|
+
|
|
95
|
+ // print!("( ({}) ", format!("{} > {}", format!("A{}", n-1-curr), format!("B{}", n-1-curr)));
|
|
96
|
+
|
|
97
|
+ let mut current_bit_gate_indices: Vec<usize> = Vec::with_capacity(curr+1);
|
|
98
|
+ current_bit_gate_indices.push(gt_gate_index);
|
|
99
|
+
|
|
100
|
+ // Bit to the left of curr. The one at array-index 0 doesn't have one.
|
|
101
|
+ if curr != 0 {
|
|
102
|
+ // Gate(A_i = B_i)
|
|
103
|
+ let eq_gate = Gate::new(GateType::Equal, vec![], vec![curr - 1, curr - 1 + n]);
|
|
104
|
+ // remember which gate-index this bit belongs to.
|
|
105
|
+ indices[n - curr] = all_gates.len();
|
|
106
|
+ all_gates.push(eq_gate);
|
|
107
|
+ }
|
112
|
108
|
|
113
|
|
- for i in 0..curr {
|
114
|
|
- let key = max-1-i;
|
115
|
|
- if i == curr-1 {
|
116
|
|
- // Gate(A_current > B_current)
|
117
|
|
- let a_i_eq_b_i_gate = Gate::new(GateType::Equal, vec!(), vec!(i, i+max));
|
118
|
|
- let a_curr_gt_b_curr_gate_index = all_gates.len();
|
119
|
|
- indices[key] = a_curr_gt_b_curr_gate_index;
|
120
|
|
- all_gates.push(a_i_eq_b_i_gate);
|
|
109
|
+ for i in 0..curr {
|
|
110
|
+ // Translate i to the key'th bit position because the array index does not match the bit index
|
|
111
|
+ // i.e.
|
|
112
|
+ //
|
|
113
|
+ // let input_bits = vec![
|
|
114
|
+ // A2 A1 A0 <- A_key
|
|
115
|
+ // 0 1 2 <- i iterates all array indices less than curr
|
|
116
|
+ // false, false, true,
|
|
117
|
+ //
|
|
118
|
+ // B2 B1 B0
|
|
119
|
+ // 3 4 5
|
|
120
|
+ // false, true, false
|
|
121
|
+ // ];
|
|
122
|
+ let key = n - 1 - i;
|
|
123
|
+
|
|
124
|
+ // print!("&& ({}) ", format!("{} = {}", format!("A{}", key), format!("B{}", key)));
|
|
125
|
+
|
|
126
|
+ // Index of Gate(A_i = B_i).
|
|
127
|
+ // You could maybe find a solution without the indices vector but it's insanely cheap anyway and maybe even better
|
|
128
|
+ let eq_gate_index = indices[key];
|
|
129
|
+ current_bit_gate_indices.push(eq_gate_index);
|
121
|
130
|
}
|
122
|
|
- let eq_gate_index = indices[key];
|
123
|
131
|
|
124
|
|
- //print!("&& ({}) ", format!("{} = {}", format!("A{}", key), format!("B{}", key)));
|
|
132
|
+ // The AND spanning all gates for this bit
|
|
133
|
+ let and_gate_index = all_gates.len();
|
|
134
|
+ let and_gate = Gate::new(GateType::And, current_bit_gate_indices, vec![]);
|
125
|
135
|
|
126
|
|
- // Index of this equality gate
|
127
|
|
- this_recursion_gate_indices.push(eq_gate_index);
|
|
136
|
+ // println!(")");
|
|
137
|
+ all_gates.push(and_gate);
|
|
138
|
+ and_gate_indices.push(and_gate_index);
|
128
|
139
|
}
|
129
|
140
|
|
130
|
|
- let and_curr_index = all_gates.len();
|
131
|
|
- let and_curr_gate = Gate::new(GateType::And, this_recursion_gate_indices, vec!());
|
132
|
|
-
|
133
|
|
- all_gates.push(and_curr_gate);
|
134
|
|
- and_gate_incides.push(and_curr_index);
|
|
141
|
+ // the OR spanning all ANDs
|
|
142
|
+ let or_gate = Gate::new(GateType::Or, and_gate_indices, vec![]);
|
|
143
|
+ all_gates.push(or_gate);
|
135
|
144
|
|
136
|
|
- if curr+1 == max {
|
137
|
|
- //println!(")");
|
138
|
|
- return;
|
139
|
|
- }
|
140
|
|
- //println!(") ||");
|
141
|
|
- return rec_n_bit_comperator_gates(curr+1, max, all_gates, and_gate_incides, indices);
|
142
|
|
-}
|
|
145
|
+ return all_gates;
|
|
146
|
+}
|