openvm_algebra_circuit/fp2_chip/
addsub.rs1use 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
51fn 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
90pub 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}