decaf377/ark_curve/r1cs/
fqvar_ext.rs1use ark_r1cs_std::eq::EqGadget;
2use ark_r1cs_std::prelude::{AllocVar, Boolean, FieldVar};
3use ark_r1cs_std::select::CondSelectGadget;
4use ark_r1cs_std::{R1CSVar, ToBitsGadget};
5use ark_relations::r1cs::SynthesisError;
6
7use crate::ark_curve::{constants::ZETA, r1cs::FqVar};
8use crate::Fq;
9
10pub trait FqVarExtension: Sized {
11 fn isqrt(&self) -> Result<(Boolean<Fq>, FqVar), SynthesisError>;
12
13 fn is_negative(&self) -> Result<Boolean<Fq>, SynthesisError>;
17 fn is_nonnegative(&self) -> Result<Boolean<Fq>, SynthesisError>;
18 fn abs(self) -> Result<Self, SynthesisError>;
19}
20
21impl FqVarExtension for FqVar {
22 fn isqrt(&self) -> Result<(Boolean<Fq>, FqVar), SynthesisError> {
30 let den = self.value().unwrap_or(Fq::ONE);
32
33 let (was_square, y) = Fq::sqrt_ratio_zeta(&Fq::ONE, &den);
37
38 let cs = self.cs();
39 let was_square_var = Boolean::new_witness(cs.clone(), || Ok(was_square))?;
40 let y_var = FqVar::new_witness(cs.clone(), || Ok(y))?;
41 let y_squared_var = y_var.square()?;
43
44 let den_var_is_zero = self.is_eq(&FqVar::zero())?;
49 let den_var = FqVar::conditionally_select(&den_var_is_zero, &FqVar::one(), self)?;
50 let den_var_inv = den_var.inverse()?;
51 let in_case_1 = was_square_var.clone();
54 y_squared_var.conditional_enforce_equal(&den_var_inv, &in_case_1)?;
56
57 let was_not_square_var = was_square_var.not();
59 let in_case_3 = was_not_square_var.and(&den_var_is_zero)?;
60 y_squared_var.conditional_enforce_equal(&FqVar::zero(), &in_case_3)?;
62
63 let zeta_var = FqVar::new_constant(cs, ZETA)?;
65 let zeta_times_one_over_den_var = zeta_var * den_var_inv;
66 let in_case_4 = was_not_square_var.and(&den_var_is_zero.not())?;
67 y_squared_var.conditional_enforce_equal(&zeta_times_one_over_den_var, &in_case_4)?;
69
70 let in_case = in_case_1.or(&in_case_3)?.or(&in_case_4)?;
72 in_case.enforce_equal(&Boolean::TRUE)?;
73
74 Ok((was_square_var, y_var))
75 }
76
77 fn is_negative(&self) -> Result<Boolean<Fq>, SynthesisError> {
78 Ok(self.is_nonnegative()?.not())
79 }
80
81 fn is_nonnegative(&self) -> Result<Boolean<Fq>, SynthesisError> {
82 let bitvars = self.to_bits_le()?;
83
84 let true_var = Boolean::<Fq>::TRUE;
86 let false_var = Boolean::<Fq>::FALSE;
87
88 let lhs = bitvars[0].and(&true_var)?;
90 let is_nonnegative_var = lhs.is_eq(&false_var)?;
91
92 Ok(is_nonnegative_var)
93 }
94
95 fn abs(self) -> Result<Self, SynthesisError> {
96 let absolute_value =
97 FqVar::conditionally_select(&self.is_nonnegative()?, &self, &self.negate()?)?;
98 Ok(absolute_value)
99 }
100}