You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gate.rs 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. use crate::gate_type::GateType;
  2. #[derive(Debug, Clone)]
  3. pub struct Gate {
  4. pub gate_type: GateType,
  5. pub input_gates_indices: Vec<usize>, // Which previous gates to use
  6. pub input_bits_indices: Vec<usize>, // Which input bits to use
  7. }
  8. impl Gate {
  9. pub fn new(
  10. gate_type: GateType,
  11. input_gates_indices: Vec<usize>,
  12. input_bits_indices: Vec<usize>,
  13. ) -> Self {
  14. let num_input_wires = input_bits_indices.len() + input_gates_indices.len();
  15. if num_input_wires == 0 {
  16. panic!("A gate without inputs is invalid");
  17. }
  18. if gate_type == GateType::Bigger && num_input_wires != 2 {
  19. if num_input_wires != 2 {
  20. panic!("Bigger gates need exactly two inputs")
  21. }
  22. }
  23. if gate_type == GateType::Equal && num_input_wires != 2 {
  24. if num_input_wires != 2 {
  25. panic!("Equal gates need exactly two inputs")
  26. }
  27. }
  28. Self {
  29. gate_type,
  30. input_gates_indices,
  31. input_bits_indices,
  32. }
  33. }
  34. pub fn eval(&self, input_bits: &Vec<bool>, evaluated_gates: &Vec<bool>) -> bool {
  35. /*
  36. The goal is to perform short-circuit evaluation with the minimum number of vector lookups.
  37. */
  38. match self.gate_type {
  39. /*
  40. A multi-input gate that outputs 1 if all input bits are 1, and 0 otherwise
  41. */
  42. GateType::And => {
  43. for &index in self.input_bits_indices.iter(){
  44. if !input_bits[index] {
  45. return false;
  46. }
  47. }
  48. for &index in self.input_gates_indices.iter(){
  49. if !evaluated_gates[index] {
  50. return false;
  51. }
  52. }
  53. return true;
  54. }
  55. /*
  56. A multi-input gate that outputs 1 if at least one input bit is 1, and 0 otherwise.
  57. */
  58. GateType::Or => {
  59. for &index in self.input_bits_indices.iter(){
  60. if input_bits[index] {
  61. return true;
  62. }
  63. }
  64. for &index in self.input_gates_indices.iter(){
  65. if evaluated_gates[index] {
  66. return true;
  67. }
  68. }
  69. return false;
  70. },
  71. /*
  72. A gate with exactly two inputs. It outputs 1 if the two input bits are equal
  73. (i.e., both 0 or both 1), and 0 otherwise
  74. */
  75. GateType::Equal => match self.input_bits_indices.len() {
  76. 0 => evaluated_gates[self.input_gates_indices[0]] == evaluated_gates[self.input_gates_indices[1]],
  77. 1 => input_bits[self.input_bits_indices[0]] == evaluated_gates[self.input_gates_indices[0]],
  78. 2 => {
  79. input_bits[self.input_bits_indices[0]] == input_bits[self.input_bits_indices[1]]
  80. },
  81. _ => panic!{"How'd we get here?"}
  82. },
  83. /*
  84. A gate with exactly two inputs. It outputs 1 if the first input is 1 and the second
  85. input is 0; otherwise, it outputs 0. This gate is used to compare individual bits a_i > b_i
  86. A B | A > B | A && !B
  87. --------------------
  88. 0 0 | 0 | 0 0 1
  89. 0 1 | 0 | 0 0 0
  90. 1 0 | 1 | 1 1 1
  91. 1 1 | 0 | 1 0 0
  92. */
  93. GateType::Bigger => match self.input_bits_indices.len() {
  94. // bits: [] gates: [A,B]
  95. 0 => evaluated_gates[self.input_gates_indices[0]] && !evaluated_gates[self.input_gates_indices[1]],
  96. // bits: [A] gates: [B]
  97. 1 => input_bits[self.input_bits_indices[0]] && !evaluated_gates[self.input_gates_indices[0]],
  98. // bits: [A,B] gates: []
  99. 2 => {
  100. input_bits[self.input_bits_indices[0]] && !input_bits[self.input_bits_indices[1]]
  101. },
  102. _ => panic!{"How'd we get here? {}", input_bits.len()}
  103. },
  104. }
  105. }
  106. }