openvm_ecc_circuit/weierstrass_chip/
double.rs
1use std::{cell::RefCell, rc::Rc};
2
3use num_bigint::BigUint;
4use num_traits::One;
5use openvm_circuit_primitives::var_range::VariableRangeCheckerBus;
6use openvm_mod_circuit_builder::{ExprBuilder, ExprBuilderConfig, FieldExpr, FieldVariable};
7
8pub fn ec_double_ne_expr(
9 config: ExprBuilderConfig, range_bus: VariableRangeCheckerBus,
11 a_biguint: BigUint,
12) -> FieldExpr {
13 config.check_valid();
14 let builder = ExprBuilder::new(config, range_bus.range_max_bits);
15 let builder = Rc::new(RefCell::new(builder));
16
17 let mut x1 = ExprBuilder::new_input(builder.clone());
18 let mut y1 = ExprBuilder::new_input(builder.clone());
19 let a = ExprBuilder::new_const(builder.clone(), a_biguint.clone());
20 let is_double_flag = builder.borrow_mut().new_flag();
21 let lambda_denom = FieldVariable::select(
24 is_double_flag,
25 &y1.int_mul(2),
26 &ExprBuilder::new_const(builder.clone(), BigUint::one()),
27 );
28 let mut lambda = (x1.square().int_mul(3) + a) / lambda_denom;
29 let mut x3 = lambda.square() - x1.int_mul(2);
30 x3.save_output();
31 let mut y3 = lambda * (x1 - x3.clone()) - y1;
32 y3.save_output();
33
34 let builder = builder.borrow().clone();
35 FieldExpr::new_with_setup_values(builder, range_bus, true, vec![a_biguint])
36}