ark_r1cs_std/poly/domain/
mod.rs1use crate::{
2 boolean::Boolean,
3 eq::EqGadget,
4 fields::{fp::FpVar, FieldVar},
5};
6use ark_ff::PrimeField;
7use ark_relations::r1cs::SynthesisError;
8use ark_std::vec::Vec;
9
10pub mod vanishing_poly;
11
12#[derive(Clone, Debug)]
13pub struct Radix2DomainVar<F: PrimeField> {
20 pub gen: F,
22 offset: FpVar<F>,
24 pub dim: u64,
26}
27impl<F: PrimeField> Radix2DomainVar<F> {
28 pub fn new(gen: F, dimension: u64, offset: FpVar<F>) -> Result<Self, SynthesisError> {
30 offset.enforce_not_equal(&FpVar::zero())?;
31 Ok(Self {
32 gen,
33 offset,
34 dim: dimension,
35 })
36 }
37
38 pub fn offset(&self) -> &FpVar<F> {
40 &self.offset
41 }
42}
43
44impl<F: PrimeField> EqGadget<F> for Radix2DomainVar<F> {
45 fn is_eq(&self, other: &Self) -> Result<Boolean<F>, SynthesisError> {
46 if self.gen != other.gen || self.dim != other.dim {
47 Ok(Boolean::FALSE)
48 } else {
49 self.offset.is_eq(&other.offset)
50 }
51 }
52}
53
54impl<F: PrimeField> Radix2DomainVar<F> {
55 pub fn order(&self) -> usize {
57 1 << self.dim
58 }
59
60 pub fn elements(&self) -> Vec<FpVar<F>> {
62 let mut result = Vec::new();
63 result.push(self.offset.clone());
64 for _ in 1..(1 << self.dim) {
65 let new_element = result.last().unwrap() * self.gen;
66 result.push(new_element);
67 }
68 result
69 }
70
71 pub fn size(&self) -> u64 {
73 1 << self.dim
74 }
75
76 pub fn query_position_to_coset_elements(
85 &self,
86 query_pos: &[Boolean<F>],
87 coset_dim: u64,
88 ) -> Result<Vec<FpVar<F>>, SynthesisError> {
89 Ok(self
90 .query_position_to_coset(query_pos, coset_dim)?
91 .elements())
92 }
93
94 pub fn query_position_to_coset(
101 &self,
102 query_pos: &[Boolean<F>],
103 coset_dim: u64,
104 ) -> Result<Self, SynthesisError> {
105 let coset_index = truncate_to_coset_index(query_pos, self.dim, coset_dim);
106 let offset_var = &self.offset * FpVar::Constant(self.gen).pow_le(&coset_index)?;
107 Ok(Self {
108 gen: self.gen.pow(&[1 << (self.dim - coset_dim)]), offset: offset_var,
110 dim: coset_dim,
111 })
112 }
113}
114
115fn truncate_to_coset_index<F: PrimeField>(
116 query_pos: &[Boolean<F>],
117 codeword_dim: u64,
118 coset_dim: u64,
119) -> Vec<Boolean<F>> {
120 let log2_num_cosets = (codeword_dim - coset_dim) as usize;
121 assert!(query_pos.len() >= log2_num_cosets);
122 query_pos[0..log2_num_cosets].to_vec()
123}
124
125#[cfg(test)]
126mod tests {
127 use crate::prelude::*;
128 use ark_ff::PrimeField;
129 use ark_relations::r1cs::ConstraintSystem;
130 use ark_std::{rand::Rng, test_rng};
131
132 use crate::{
133 alloc::AllocVar, convert::ToBitsGadget, fields::fp::FpVar, poly::domain::Radix2DomainVar,
134 R1CSVar,
135 };
136
137 fn test_query_coset_template<F: PrimeField>() {
138 const COSET_DIM: u64 = 7;
139 const COSET_SIZE: u64 = 1 << COSET_DIM;
140 const LOCALIZATION: u64 = 3;
141 let cs = ConstraintSystem::new_ref();
142 let mut rng = test_rng();
143 let gen = F::get_root_of_unity(COSET_SIZE).unwrap();
144 let offset = F::rand(&mut rng);
145 let offset_var = FpVar::new_witness(cs.clone(), || Ok(offset)).unwrap();
146 let domain = Radix2DomainVar::new(gen, COSET_DIM, offset_var).unwrap();
147
148 let num_cosets = 1 << (COSET_DIM - LOCALIZATION);
149
150 let coset_index = rng.gen_range(0..num_cosets);
151 println!("{:0b}", coset_index);
152 let coset_index_var = UInt32::new_witness(cs.clone(), || Ok(coset_index))
153 .unwrap()
154 .to_bits_le()
155 .unwrap()
156 .into_iter()
157 .take(COSET_DIM as usize)
158 .collect::<Vec<_>>();
159
160 let elements_actual = domain
161 .query_position_to_coset(&coset_index_var, LOCALIZATION)
162 .unwrap()
163 .elements();
164
165 let elements_expected = domain
166 .elements()
167 .into_iter()
168 .skip(coset_index as usize)
169 .step_by(1 << (COSET_DIM - LOCALIZATION))
170 .collect::<Vec<_>>();
171
172 assert_eq!(elements_expected.len(), elements_actual.len());
173
174 elements_expected
175 .into_iter()
176 .zip(elements_actual.into_iter())
177 .for_each(|(left, right)| {
178 assert_eq!(left.value().unwrap(), right.value().unwrap());
179 });
180 }
181
182 #[test]
183 fn test_on_bls12_381() {
184 test_query_coset_template::<ark_bls12_381::Fr>();
185 }
186
187 #[test]
188 fn test_on_bls12_377() {
189 test_query_coset_template::<ark_bls12_377::Fr>();
190 }
191}