zinc_uair/
ideal_collector.rs1use crate::{
2 ConstraintBuilder, TraceRow, Uair,
3 dummy_semiring::{DUMMY_SEMIRING_CONFIG, DummySemiring, DummySemiringConfig},
4 ideal::{Ideal, IdealCheck, IdealCheckError},
5};
6use std::fmt::{Display, Formatter};
7use zinc_utils::{add, from_ref::FromRef};
8
9pub struct IdealCollector<I: Ideal, IFq: Ideal> {
20 pub ideals: Vec<IdealOrZero<I>>,
21 pub fq_ideals: Vec<Vec<IdealOrZero<IFq>>>,
25}
26
27impl<I: Ideal, IFq: Ideal> IdealCollector<I, IFq> {
28 pub fn new(num_constraints: usize) -> Self {
32 Self {
33 ideals: Vec::with_capacity(num_constraints),
34 fq_ideals: Vec::new(),
35 }
36 }
37}
38
39pub fn collect_ideals<U: Uair>(num_constraints: usize) -> IdealCollector<U::Ideal, U::FqIdeal> {
43 let mut ideal_collector = IdealCollector::new(num_constraints);
44
45 let sig = U::signature();
46 let (up_dummy, down_dummy) = sig.dummy_rows(DummySemiring);
47 let up_row = TraceRow::from_slice_with_layout(&up_dummy, sig.total_cols().as_column_layout());
48 let down_row =
49 TraceRow::from_slice_with_layout(&down_dummy, sig.down_cols().as_column_layout());
50 U::constrain_general(
51 &mut ideal_collector,
52 &DUMMY_SEMIRING_CONFIG,
53 up_row,
54 down_row,
55 |_| DummySemiring,
56 |_, _| Some(DummySemiring),
57 IdealOrZero::from_ref,
58 IdealOrZero::from_ref,
59 );
60
61 ideal_collector
62}
63
64impl<I, IFq> ConstraintBuilder for IdealCollector<I, IFq>
65where
66 I: Ideal,
67 IFq: Ideal,
68{
69 type Expr = DummySemiring;
70 type Ideal = IdealOrZero<I>;
71 type FqIdeal = IdealOrZero<IFq>;
72
73 fn assert_in_ideal(&mut self, _expr: Self::Expr, ideal: &Self::Ideal) {
74 self.ideals.push(ideal.clone());
75 }
76
77 fn assert_zero(&mut self, _expr: Self::Expr) {
78 self.ideals.push(IdealOrZero::zero());
79 }
80
81 fn assert_in_fq_ideal(&mut self, prime_idx: usize, _expr: Self::Expr, ideal: &Self::FqIdeal) {
82 if self.fq_ideals.len() <= prime_idx {
83 self.fq_ideals.resize(add!(prime_idx, 1), Vec::new());
84 }
85 self.fq_ideals[prime_idx].push(ideal.clone());
86 }
87}
88
89#[derive(Clone, Copy, Debug)]
92pub enum IdealOrZero<I: Ideal> {
93 NonZero(I),
94 Zero,
95}
96
97impl<I: Ideal> IdealOrZero<I> {
98 pub fn zero() -> Self {
99 IdealOrZero::Zero
100 }
101
102 pub fn is_zero_ideal(&self) -> bool {
105 matches!(self, IdealOrZero::Zero)
106 }
107
108 pub fn map<I2: Ideal>(&self, f: impl FnOnce(&I) -> I2) -> IdealOrZero<I2> {
109 match self {
110 IdealOrZero::NonZero(ideal) => IdealOrZero::NonZero(f(ideal)),
111 IdealOrZero::Zero => IdealOrZero::Zero,
112 }
113 }
114}
115
116impl<I: Ideal> Display for IdealOrZero<I> {
117 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
118 write!(f, "IdealOrZero<")?;
119 match self {
120 Self::Zero => write!(f, "Zero")?,
121 Self::NonZero(ideal) => write!(f, "{ideal}")?,
122 }
123 write!(f, ">")?;
124 Ok(())
125 }
126}
127
128impl<I: Ideal> Ideal for IdealOrZero<I> {}
129
130impl<I: Ideal> FromRef<IdealOrZero<I>> for IdealOrZero<I> {
131 fn from_ref(value: &IdealOrZero<I>) -> Self {
132 value.clone()
133 }
134}
135
136impl<I: Ideal> FromRef<I> for IdealOrZero<I> {
137 fn from_ref(value: &I) -> Self {
138 IdealOrZero::NonZero(value.clone())
139 }
140}
141
142impl<I: Ideal> IdealCheck<DummySemiringConfig> for IdealOrZero<I> {
143 fn contains(
144 &self,
145 _cfg: &DummySemiringConfig,
146 _value: &DummySemiring,
147 ) -> Result<bool, IdealCheckError> {
148 Ok(true)
150 }
151}