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_executor<const BLOCKS: usize, const BLOCK_SIZE: usize>(
91 config: ExprBuilderConfig,
92 range_checker_bus: VariableRangeCheckerBus,
93 pointer_max_bits: usize,
94 offset: usize,
95) -> Fp2Executor<BLOCKS, BLOCK_SIZE> {
96 let (expr, local_opcode_idx, opcode_flag_idx) = gen_base_expr(config, range_checker_bus);
97
98 FieldExprVecHeapExecutor::new(FieldExpressionExecutor::new(
99 Rv32VecHeapAdapterExecutor::new(pointer_max_bits),
100 expr,
101 offset,
102 local_opcode_idx,
103 opcode_flag_idx,
104 "Fp2AddSub",
105 ))
106}
107
108pub fn get_fp2_addsub_chip<F, const BLOCKS: usize, const BLOCK_SIZE: usize>(
109 config: ExprBuilderConfig,
110 mem_helper: SharedMemoryHelper<F>,
111 range_checker: SharedVariableRangeCheckerChip,
112 bitwise_lookup_chip: SharedBitwiseOperationLookupChip<RV32_CELL_BITS>,
113 pointer_max_bits: usize,
114) -> Fp2Chip<F, BLOCKS, BLOCK_SIZE> {
115 let (expr, local_opcode_idx, opcode_flag_idx) = gen_base_expr(config, range_checker.bus());
116 Fp2Chip::new(
117 FieldExpressionFiller::new(
118 Rv32VecHeapAdapterFiller::new(pointer_max_bits, bitwise_lookup_chip),
119 expr,
120 local_opcode_idx,
121 opcode_flag_idx,
122 range_checker,
123 false,
124 ),
125 mem_helper,
126 )
127}