snarkvm_circuit_environment/helpers/
variable.rs1use crate::{LinearCombination, Mode};
17use snarkvm_fields::traits::*;
18
19use core::{
20 cmp::Ordering,
21 fmt,
22 ops::{Add, Sub},
23};
24use std::rc::Rc;
25
26pub type Index = u64;
27
28#[derive(Clone, PartialEq, Eq, Hash)]
29pub enum Variable<F: PrimeField> {
30 Constant(Rc<F>),
31 Public(Rc<(Index, F)>),
32 Private(Rc<(Index, F)>),
33}
34
35impl<F: PrimeField> Variable<F> {
36 pub fn is_constant(&self) -> bool {
40 matches!(self, Self::Constant(..))
41 }
42
43 pub fn is_public(&self) -> bool {
47 matches!(self, Self::Public(..))
48 }
49
50 pub fn is_private(&self) -> bool {
54 matches!(self, Self::Private(..))
55 }
56
57 pub fn mode(&self) -> Mode {
61 match self {
62 Self::Constant(..) => Mode::Constant,
63 Self::Public(..) => Mode::Public,
64 Self::Private(..) => Mode::Private,
65 }
66 }
67
68 pub fn index(&self) -> Index {
72 match self {
73 Self::Constant(..) => 0,
74 Self::Public(index_value) | Self::Private(index_value) => {
75 let (index, _value) = index_value.as_ref();
76 *index
77 }
78 }
79 }
80
81 pub fn value(&self) -> F {
85 match self {
86 Self::Constant(value) => **value,
87 Self::Public(index_value) | Self::Private(index_value) => {
88 let (_index, value) = index_value.as_ref();
89 *value
90 }
91 }
92 }
93}
94
95impl<F: PrimeField> PartialOrd for Variable<F> {
96 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
97 Some(self.cmp(other))
98 }
99}
100
101impl<F: PrimeField> Ord for Variable<F> {
102 fn cmp(&self, other: &Self) -> Ordering {
103 match (self, other) {
104 (Self::Constant(v1), Self::Constant(v2)) => v1.cmp(v2),
105 (Self::Constant(..), Self::Public(..)) => Ordering::Less,
106 (Self::Constant(..), Self::Private(..)) => Ordering::Less,
107 (Self::Public(..), Self::Constant(..)) => Ordering::Greater,
108 (Self::Private(..), Self::Constant(..)) => Ordering::Greater,
109 (Self::Public(i1, ..), Self::Public(i2, ..)) => i1.cmp(i2),
110 (Self::Private(i1, ..), Self::Private(i2, ..)) => i1.cmp(i2),
111 (Self::Public(..), Self::Private(..)) => Ordering::Less,
112 (Self::Private(..), Self::Public(..)) => Ordering::Greater,
113 }
114 }
115}
116
117#[allow(clippy::op_ref)]
118impl<F: PrimeField> Add<Variable<F>> for Variable<F> {
119 type Output = LinearCombination<F>;
120
121 fn add(self, other: Variable<F>) -> Self::Output {
122 self + &other
123 }
124}
125
126#[allow(clippy::op_ref)]
127impl<F: PrimeField> Add<Variable<F>> for &Variable<F> {
128 type Output = LinearCombination<F>;
129
130 fn add(self, other: Variable<F>) -> Self::Output {
131 self + &other
132 }
133}
134
135#[allow(clippy::op_ref)]
136impl<F: PrimeField> Add<&Variable<F>> for Variable<F> {
137 type Output = LinearCombination<F>;
138
139 fn add(self, other: &Variable<F>) -> Self::Output {
140 &self + other
141 }
142}
143
144impl<F: PrimeField> Add<&Variable<F>> for &Variable<F> {
145 type Output = LinearCombination<F>;
146
147 fn add(self, other: &Variable<F>) -> Self::Output {
148 match (self, other) {
149 (Variable::Constant(a), Variable::Constant(b)) => Variable::Constant(Rc::new(**a + **b)).into(),
150 (first, second) => LinearCombination::from([first.clone(), second.clone()]),
151 }
152 }
153}
154
155#[allow(clippy::op_ref)]
156impl<F: PrimeField> Add<LinearCombination<F>> for Variable<F> {
157 type Output = LinearCombination<F>;
158
159 fn add(self, other: LinearCombination<F>) -> Self::Output {
160 self + &other
161 }
162}
163
164#[allow(clippy::op_ref)]
165impl<F: PrimeField> Add<LinearCombination<F>> for &Variable<F> {
166 type Output = LinearCombination<F>;
167
168 fn add(self, other: LinearCombination<F>) -> Self::Output {
169 self + &other
170 }
171}
172
173#[allow(clippy::op_ref)]
174impl<F: PrimeField> Add<&LinearCombination<F>> for Variable<F> {
175 type Output = LinearCombination<F>;
176
177 fn add(self, other: &LinearCombination<F>) -> Self::Output {
178 &self + other
179 }
180}
181
182impl<F: PrimeField> Add<&LinearCombination<F>> for &Variable<F> {
183 type Output = LinearCombination<F>;
184
185 fn add(self, other: &LinearCombination<F>) -> Self::Output {
186 LinearCombination::from(self) + other
187 }
188}
189
190#[allow(clippy::op_ref)]
191impl<F: PrimeField> Sub<Variable<F>> for Variable<F> {
192 type Output = LinearCombination<F>;
193
194 fn sub(self, other: Variable<F>) -> Self::Output {
195 self - &other
196 }
197}
198
199#[allow(clippy::op_ref)]
200impl<F: PrimeField> Sub<Variable<F>> for &Variable<F> {
201 type Output = LinearCombination<F>;
202
203 fn sub(self, other: Variable<F>) -> Self::Output {
204 self - &other
205 }
206}
207
208#[allow(clippy::op_ref)]
209impl<F: PrimeField> Sub<&Variable<F>> for Variable<F> {
210 type Output = LinearCombination<F>;
211
212 fn sub(self, other: &Variable<F>) -> Self::Output {
213 &self - other
214 }
215}
216
217impl<F: PrimeField> Sub<&Variable<F>> for &Variable<F> {
218 type Output = LinearCombination<F>;
219
220 fn sub(self, other: &Variable<F>) -> Self::Output {
221 match (self, other) {
222 (Variable::Constant(a), Variable::Constant(b)) => Variable::Constant(Rc::new(**a - **b)).into(),
223 (first, second) => LinearCombination::from(first) - second,
224 }
225 }
226}
227
228#[allow(clippy::op_ref)]
229impl<F: PrimeField> Sub<LinearCombination<F>> for Variable<F> {
230 type Output = LinearCombination<F>;
231
232 fn sub(self, other: LinearCombination<F>) -> Self::Output {
233 self - &other
234 }
235}
236
237#[allow(clippy::op_ref)]
238impl<F: PrimeField> Sub<LinearCombination<F>> for &Variable<F> {
239 type Output = LinearCombination<F>;
240
241 fn sub(self, other: LinearCombination<F>) -> Self::Output {
242 self - &other
243 }
244}
245
246#[allow(clippy::op_ref)]
247impl<F: PrimeField> Sub<&LinearCombination<F>> for Variable<F> {
248 type Output = LinearCombination<F>;
249
250 fn sub(self, other: &LinearCombination<F>) -> Self::Output {
251 &self - other
252 }
253}
254
255impl<F: PrimeField> Sub<&LinearCombination<F>> for &Variable<F> {
256 type Output = LinearCombination<F>;
257
258 fn sub(self, other: &LinearCombination<F>) -> Self::Output {
259 LinearCombination::from(self) - other
260 }
261}
262
263impl<F: PrimeField> fmt::Debug for Variable<F> {
264 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
265 write!(f, "{}", match self {
266 Self::Constant(value) => format!("Constant({value})"),
267 Self::Public(index_value) => {
268 let (index, value) = index_value.as_ref();
269 format!("Public({index}, {value})")
270 }
271 Self::Private(index_value) => {
272 let (index, value) = index_value.as_ref();
273 format!("Private({index}, {value})")
274 }
275 })
276 }
277}
278
279impl<F: PrimeField> fmt::Display for Variable<F> {
280 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
281 write!(f, "{}", self.value())
282 }
283}
284
285#[cfg(test)]
286mod tests {
287 use crate::*;
288
289 #[test]
290 fn test_size() {
291 assert_eq!(16, std::mem::size_of::<Variable<<Circuit as Environment>::BaseField>>());
292 }
293}