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::sync::Arc;
25
26pub type Index = u64;
27
28#[derive(Clone, PartialEq, Eq, Hash)]
29pub enum Variable<F: PrimeField> {
30 Constant(Arc<F>),
31 Public(Arc<(Index, F)>),
32 Private(Arc<(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 pub fn index_value(&self) -> (Index, F) {
98 match self {
99 Self::Constant(value) => (0, **value),
100 Self::Public(index_value) | Self::Private(index_value) => {
101 let (index, value) = index_value.as_ref();
102 (*index, *value)
103 }
104 }
105 }
106}
107
108impl<F: PrimeField> PartialOrd for Variable<F> {
109 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
110 Some(self.cmp(other))
111 }
112}
113
114impl<F: PrimeField> Ord for Variable<F> {
115 fn cmp(&self, other: &Self) -> Ordering {
116 match (self, other) {
117 (Self::Constant(v1), Self::Constant(v2)) => v1.cmp(v2),
118 (Self::Constant(..), Self::Public(..)) => Ordering::Less,
119 (Self::Constant(..), Self::Private(..)) => Ordering::Less,
120 (Self::Public(..), Self::Constant(..)) => Ordering::Greater,
121 (Self::Private(..), Self::Constant(..)) => Ordering::Greater,
122 (Self::Public(i1, ..), Self::Public(i2, ..)) => i1.cmp(i2),
123 (Self::Private(i1, ..), Self::Private(i2, ..)) => i1.cmp(i2),
124 (Self::Public(..), Self::Private(..)) => Ordering::Less,
125 (Self::Private(..), Self::Public(..)) => Ordering::Greater,
126 }
127 }
128}
129
130#[allow(clippy::op_ref)]
131impl<F: PrimeField> Add<Variable<F>> for Variable<F> {
132 type Output = LinearCombination<F>;
133
134 fn add(self, other: Variable<F>) -> Self::Output {
135 self + &other
136 }
137}
138
139#[allow(clippy::op_ref)]
140impl<F: PrimeField> Add<Variable<F>> for &Variable<F> {
141 type Output = LinearCombination<F>;
142
143 fn add(self, other: Variable<F>) -> Self::Output {
144 self + &other
145 }
146}
147
148#[allow(clippy::op_ref)]
149impl<F: PrimeField> Add<&Variable<F>> for Variable<F> {
150 type Output = LinearCombination<F>;
151
152 fn add(self, other: &Variable<F>) -> Self::Output {
153 &self + other
154 }
155}
156
157impl<F: PrimeField> Add<&Variable<F>> for &Variable<F> {
158 type Output = LinearCombination<F>;
159
160 fn add(self, other: &Variable<F>) -> Self::Output {
161 match (self, other) {
162 (Variable::Constant(a), Variable::Constant(b)) => Variable::Constant(Arc::new(**a + **b)).into(),
163 (first, second) => LinearCombination::from([first.clone(), second.clone()]),
164 }
165 }
166}
167
168#[allow(clippy::op_ref)]
169impl<F: PrimeField> Add<LinearCombination<F>> for Variable<F> {
170 type Output = LinearCombination<F>;
171
172 fn add(self, other: LinearCombination<F>) -> Self::Output {
173 self + &other
174 }
175}
176
177#[allow(clippy::op_ref)]
178impl<F: PrimeField> Add<LinearCombination<F>> for &Variable<F> {
179 type Output = LinearCombination<F>;
180
181 fn add(self, other: LinearCombination<F>) -> Self::Output {
182 self + &other
183 }
184}
185
186#[allow(clippy::op_ref)]
187impl<F: PrimeField> Add<&LinearCombination<F>> for Variable<F> {
188 type Output = LinearCombination<F>;
189
190 fn add(self, other: &LinearCombination<F>) -> Self::Output {
191 &self + other
192 }
193}
194
195impl<F: PrimeField> Add<&LinearCombination<F>> for &Variable<F> {
196 type Output = LinearCombination<F>;
197
198 fn add(self, other: &LinearCombination<F>) -> Self::Output {
199 LinearCombination::from(self) + other
200 }
201}
202
203#[allow(clippy::op_ref)]
204impl<F: PrimeField> Sub<Variable<F>> for Variable<F> {
205 type Output = LinearCombination<F>;
206
207 fn sub(self, other: Variable<F>) -> Self::Output {
208 self - &other
209 }
210}
211
212#[allow(clippy::op_ref)]
213impl<F: PrimeField> Sub<Variable<F>> for &Variable<F> {
214 type Output = LinearCombination<F>;
215
216 fn sub(self, other: Variable<F>) -> Self::Output {
217 self - &other
218 }
219}
220
221#[allow(clippy::op_ref)]
222impl<F: PrimeField> Sub<&Variable<F>> for Variable<F> {
223 type Output = LinearCombination<F>;
224
225 fn sub(self, other: &Variable<F>) -> Self::Output {
226 &self - other
227 }
228}
229
230impl<F: PrimeField> Sub<&Variable<F>> for &Variable<F> {
231 type Output = LinearCombination<F>;
232
233 fn sub(self, other: &Variable<F>) -> Self::Output {
234 match (self, other) {
235 (Variable::Constant(a), Variable::Constant(b)) => Variable::Constant(Arc::new(**a - **b)).into(),
236 (first, second) => LinearCombination::from(first) - second,
237 }
238 }
239}
240
241#[allow(clippy::op_ref)]
242impl<F: PrimeField> Sub<LinearCombination<F>> for Variable<F> {
243 type Output = LinearCombination<F>;
244
245 fn sub(self, other: LinearCombination<F>) -> Self::Output {
246 self - &other
247 }
248}
249
250#[allow(clippy::op_ref)]
251impl<F: PrimeField> Sub<LinearCombination<F>> for &Variable<F> {
252 type Output = LinearCombination<F>;
253
254 fn sub(self, other: LinearCombination<F>) -> Self::Output {
255 self - &other
256 }
257}
258
259#[allow(clippy::op_ref)]
260impl<F: PrimeField> Sub<&LinearCombination<F>> for Variable<F> {
261 type Output = LinearCombination<F>;
262
263 fn sub(self, other: &LinearCombination<F>) -> Self::Output {
264 &self - other
265 }
266}
267
268impl<F: PrimeField> Sub<&LinearCombination<F>> for &Variable<F> {
269 type Output = LinearCombination<F>;
270
271 fn sub(self, other: &LinearCombination<F>) -> Self::Output {
272 LinearCombination::from(self) - other
273 }
274}
275
276impl<F: PrimeField> fmt::Debug for Variable<F> {
277 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
278 write!(f, "{}", match self {
279 Self::Constant(value) => format!("Constant({value})"),
280 Self::Public(index_value) => {
281 let (index, value) = index_value.as_ref();
282 format!("Public({index}, {value})")
283 }
284 Self::Private(index_value) => {
285 let (index, value) = index_value.as_ref();
286 format!("Private({index}, {value})")
287 }
288 })
289 }
290}
291
292impl<F: PrimeField> fmt::Display for Variable<F> {
293 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
294 write!(f, "{}", self.value())
295 }
296}
297
298#[cfg(test)]
299mod tests {
300 use crate::*;
301
302 #[test]
303 fn test_size() {
304 assert_eq!(16, std::mem::size_of::<Variable<<Circuit as Environment>::BaseField>>());
305 }
306}