1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use crate::{Bit, Gate, GateLike, Sequal};
pub(super) trait SequalsExtension<Rust> {
unsafe fn run(
&self,
for_gate: usize,
output: &[Bit],
gates: &mut [Gate<Rust>],
outputs: &mut [Bit],
);
}
impl<Rust> SequalsExtension<Rust> for [Vec<Sequal>]
where
Rust: GateLike,
{
/// # Safety
/// this function is only safe if:
/// - the index of the gate in `for_gate` is in bounds for (`self`)
/// - the amount of sequals in `self[for_gate]` is equal to the amount of
/// `output`s received from the last gate
/// - all `Sequal::End`s point to outputs that exist - guaranteed if
/// constructed with [`ComponentBuilder`] and used outputs from 0 up to
/// the number of outputs
/// - all `Sequal::Gate`s must point to actual inputs of actual gates
/// - component is clean (right after construction or after a call to
/// `Component::reset()`)
unsafe fn run(
&self,
for_gate: usize,
output: &[Bit],
gates: &mut [Gate<Rust>],
outputs: &mut [Bit],
) {
debug_assert!(
for_gate < self.len(),
"this gate (index: {}) doesn't have documented sequals",
for_gate
);
let sequals = unsafe { self.get_unchecked(for_gate) };
debug_assert_eq!(
sequals.len(),
output.len(),
"not every output bit has a matching sequal (gate index: {})",
for_gate
);
for (sequal, data) in sequals.iter().copied().zip(output.iter().copied()) {
match sequal {
Sequal::End { output } => {
debug_assert!(
output < outputs.len(),
"this component output is out of bounds (in sequal of gate {})",
for_gate
);
// this blocks having one less vectors because the index in
// `output` isn't necessarily the same as the index of data
// in output
*unsafe { outputs.get_unchecked_mut(output) } = data;
}
Sequal::Gate { index, entry } => {
if let Some(output) = unsafe {
debug_assert!(index < gates.len());
unsafe { gates.get_unchecked_mut(index) }.fill_input(data, entry)
} {
self.run(index, &output, gates, outputs);
drop(output); // just want to emphasize this is where deallocation happens for Gate.inputs
}
}
}
}
}
}