openvm_algebra_circuit/fp2_chip/
addsub.rs

1use std::{cell::RefCell, rc::Rc};
2
3use openvm_algebra_transpiler::Fp2Opcode;
4use openvm_circuit::{
5    arch::ExecutionBridge,
6    system::memory::{offline_checker::MemoryBridge, SharedMemoryHelper},
7};
8use openvm_circuit_primitives::{
9    bitwise_op_lookup::{BitwiseOperationLookupBus, SharedBitwiseOperationLookupChip},
10    var_range::{SharedVariableRangeCheckerChip, VariableRangeCheckerBus},
11};
12use openvm_instructions::riscv::RV32_CELL_BITS;
13use openvm_mod_circuit_builder::{
14    ExprBuilder, ExprBuilderConfig, FieldExpr, FieldExpressionCoreAir, FieldExpressionExecutor,
15    FieldExpressionFiller,
16};
17use openvm_rv32_adapters::{
18    Rv32VecHeapAdapterAir, Rv32VecHeapAdapterExecutor, Rv32VecHeapAdapterFiller,
19};
20
21use super::{Fp2Air, Fp2Chip, Fp2Executor};
22use crate::{FieldExprVecHeapExecutor, Fp2};
23
24pub fn fp2_addsub_expr(
25    config: ExprBuilderConfig,
26    range_bus: VariableRangeCheckerBus,
27) -> (FieldExpr, usize, usize) {
28    config.check_valid();
29    let builder = ExprBuilder::new(config, range_bus.range_max_bits);
30    let builder = Rc::new(RefCell::new(builder));
31
32    let mut x = Fp2::new(builder.clone());
33    let mut y = Fp2::new(builder.clone());
34    let add = x.add(&mut y);
35    let sub = x.sub(&mut y);
36
37    let is_add_flag = builder.borrow_mut().new_flag();
38    let is_sub_flag = builder.borrow_mut().new_flag();
39    let diff = Fp2::select(is_sub_flag, &sub, &x);
40    let mut z = Fp2::select(is_add_flag, &add, &diff);
41    z.save_output();
42
43    let builder = builder.borrow().clone();
44    (
45        FieldExpr::new(builder, range_bus, true),
46        is_add_flag,
47        is_sub_flag,
48    )
49}
50
51// Input: Fp2 * 2
52// Output: Fp2
53fn gen_base_expr(
54    config: ExprBuilderConfig,
55    range_checker_bus: VariableRangeCheckerBus,
56) -> (FieldExpr, Vec<usize>, Vec<usize>) {
57    let (expr, is_add_flag, is_sub_flag) = fp2_addsub_expr(config, range_checker_bus);
58
59    let local_opcode_idx = vec![
60        Fp2Opcode::ADD as usize,
61        Fp2Opcode::SUB as usize,
62        Fp2Opcode::SETUP_ADDSUB as usize,
63    ];
64    let opcode_flag_idx = vec![is_add_flag, is_sub_flag];
65
66    (expr, local_opcode_idx, opcode_flag_idx)
67}
68
69pub fn get_fp2_addsub_air<const BLOCKS: usize, const BLOCK_SIZE: usize>(
70    exec_bridge: ExecutionBridge,
71    mem_bridge: MemoryBridge,
72    config: ExprBuilderConfig,
73    range_checker_bus: VariableRangeCheckerBus,
74    bitwise_lookup_bus: BitwiseOperationLookupBus,
75    pointer_max_bits: usize,
76    offset: usize,
77) -> Fp2Air<BLOCKS, BLOCK_SIZE> {
78    let (expr, local_opcode_idx, opcode_flag_idx) = gen_base_expr(config, range_checker_bus);
79    Fp2Air::new(
80        Rv32VecHeapAdapterAir::new(
81            exec_bridge,
82            mem_bridge,
83            bitwise_lookup_bus,
84            pointer_max_bits,
85        ),
86        FieldExpressionCoreAir::new(expr, offset, local_opcode_idx, opcode_flag_idx),
87    )
88}
89
90// TODO[arayi]: rename step->executor (for all algebra and ecc functions)
91pub fn get_fp2_addsub_step<const BLOCKS: usize, const BLOCK_SIZE: usize>(
92    config: ExprBuilderConfig,
93    range_checker_bus: VariableRangeCheckerBus,
94    pointer_max_bits: usize,
95    offset: usize,
96) -> Fp2Executor<BLOCKS, BLOCK_SIZE> {
97    let (expr, local_opcode_idx, opcode_flag_idx) = gen_base_expr(config, range_checker_bus);
98
99    FieldExprVecHeapExecutor(FieldExpressionExecutor::new(
100        Rv32VecHeapAdapterExecutor::new(pointer_max_bits),
101        expr,
102        offset,
103        local_opcode_idx,
104        opcode_flag_idx,
105        "Fp2AddSub",
106    ))
107}
108
109pub fn get_fp2_addsub_chip<F, const BLOCKS: usize, const BLOCK_SIZE: usize>(
110    config: ExprBuilderConfig,
111    mem_helper: SharedMemoryHelper<F>,
112    range_checker: SharedVariableRangeCheckerChip,
113    bitwise_lookup_chip: SharedBitwiseOperationLookupChip<RV32_CELL_BITS>,
114    pointer_max_bits: usize,
115) -> Fp2Chip<F, BLOCKS, BLOCK_SIZE> {
116    let (expr, local_opcode_idx, opcode_flag_idx) = gen_base_expr(config, range_checker.bus());
117    Fp2Chip::new(
118        FieldExpressionFiller::new(
119            Rv32VecHeapAdapterFiller::new(pointer_max_bits, bitwise_lookup_chip),
120            expr,
121            local_opcode_idx,
122            opcode_flag_idx,
123            range_checker,
124            false,
125        ),
126        mem_helper,
127    )
128}