variable.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the deltavm library. 3 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 8 // http://www.apache.org/licenses/LICENSE-2.0 9 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 use crate::{LinearCombination, Mode}; 17 use deltavm_fields::traits::*; 18 19 use core::{ 20 cmp::Ordering, 21 fmt, 22 ops::{Add, Sub}, 23 }; 24 use std::sync::Arc; 25 26 pub type Index = u64; 27 28 #[derive(Clone, PartialEq, Eq, Hash)] 29 pub enum Variable<F: PrimeField> { 30 Constant(Arc<F>), 31 Public(Arc<(Index, F)>), 32 Private(Arc<(Index, F)>), 33 } 34 35 impl<F: PrimeField> Variable<F> { 36 /// 37 /// Returns `true` if the variable is a constant. 38 /// 39 pub fn is_constant(&self) -> bool { 40 matches!(self, Self::Constant(..)) 41 } 42 43 /// 44 /// Returns `true` if the variable is public. 45 /// 46 pub fn is_public(&self) -> bool { 47 matches!(self, Self::Public(..)) 48 } 49 50 /// 51 /// Returns `true` if the variable is private. 52 /// 53 pub fn is_private(&self) -> bool { 54 matches!(self, Self::Private(..)) 55 } 56 57 /// 58 /// Returns the mode of the variable. 59 /// 60 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 /// 69 /// Returns the relative index of the variable. 70 /// 71 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 /// 82 /// Returns the value of the variable. 83 /// 84 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 /// 95 /// Returns the relative index and value of the variable. 96 /// 97 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 108 impl<F: PrimeField> PartialOrd for Variable<F> { 109 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 110 Some(self.cmp(other)) 111 } 112 } 113 114 impl<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)] 131 impl<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)] 140 impl<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)] 149 impl<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 157 impl<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)] 169 impl<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)] 178 impl<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)] 187 impl<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 195 impl<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)] 204 impl<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)] 213 impl<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)] 222 impl<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 230 impl<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)] 242 impl<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)] 251 impl<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)] 260 impl<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 268 impl<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 276 impl<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 292 impl<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)] 299 mod 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 }