frontend/components/binary_operations/
binary_adder.rs1use std::cmp::max;
4
5use shared_types::Field;
6
7use crate::{
8 abstract_expr::AbstractExpression,
9 components::binary_operations::logical_shift::ShiftNode,
10 layouter::builder::{CircuitBuilder, NodeRef},
11};
12#[derive(Clone, Debug)]
22pub struct BinaryAdder<F: Field> {
23 adder_sector: NodeRef<F>,
24}
25
26impl<F: Field> BinaryAdder<F> {
27 pub fn new(
30 builder_ref: &mut CircuitBuilder<F>,
31 lhs_bits: &NodeRef<F>,
32 rhs_bits: &NodeRef<F>,
33 carry_bits: &NodeRef<F>,
34 ) -> Self {
35 let num_vars = max(
36 carry_bits.get_num_vars(),
37 max(lhs_bits.get_num_vars(), rhs_bits.get_num_vars()),
38 );
39
40 let shifted_carries = ShiftNode::new(builder_ref, num_vars, -1, carry_bits);
43
44 let b0 = lhs_bits;
45 let b1 = rhs_bits;
46 let c = shifted_carries.get_output();
47
48 let b0_c = AbstractExpression::products(vec![b0.id(), c.id()]);
49 let b1_c = AbstractExpression::products(vec![b1.id(), c.id()]);
50 let b0_b1 = AbstractExpression::products(vec![b0.id(), b1.id()]);
51 let b0_b1_c = AbstractExpression::products(vec![b0.id(), b1.id(), c.id()]);
52
53 let two_b0_c = AbstractExpression::scaled(b0_c, F::from(2));
54 let two_b1_c = AbstractExpression::scaled(b1_c, F::from(2));
55 let two_b0_b1 = AbstractExpression::scaled(b0_b1, F::from(2));
56 let four_b0_b1_c = AbstractExpression::scaled(b0_b1_c, F::from(4));
57
58 let full_adder_result_sector = builder_ref.add_sector(
59 b0.expr() + b1.expr() + c.expr() - two_b0_c - two_b1_c - two_b0_b1 + four_b0_b1_c,
61 );
62
63 let b0 = lhs_bits;
64 let b1 = rhs_bits;
65 let c = shifted_carries.get_output();
66 let expected_c = carry_bits;
67
68 let carry_check_sector = builder_ref.add_sector(
69 b0.expr() * b1.expr() * c.expr()
73 + b0.expr() * b1.expr() * -(c.expr() - F::ONE)
74 + b0.expr() * -(b1.expr() - F::ONE) * c.expr()
75 + -(b0.expr() - F::ONE) * b1.expr() * c.expr()
76 - expected_c.expr(),
77 );
78
79 builder_ref.set_output(&carry_check_sector);
80
81 Self {
82 adder_sector: full_adder_result_sector,
83 }
84 }
85
86 pub fn get_output(&self) -> NodeRef<F> {
88 self.adder_sector.clone()
89 }
90}