bitwise.rs
1 // Copyright (c) 2025-2026 ACDC Network 2 // This file is part of the alphavm library. 3 // 4 // Alpha Chain | Delta Chain Protocol 5 // International Monetary Graphite. 6 // 7 // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com). 8 // They built world-class ZK infrastructure. We installed the EASY button. 9 // Their cryptography: elegant. Our modifications: bureaucracy-compatible. 10 // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours. 11 // 12 // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0 13 // All modifications and new work: CC0 1.0 Universal Public Domain Dedication. 14 // No rights reserved. No permission required. No warranty. No refunds. 15 // 16 // https://creativecommons.org/publicdomain/zero/1.0/ 17 // SPDX-License-Identifier: CC0-1.0 18 19 use super::*; 20 21 impl<E: Environment, I: IntegerType> Equal for Integer<E, I> { 22 type Output = Boolean<E>; 23 24 /// Returns `true` if `self` and `other` are equal. 25 fn is_equal(&self, other: &Self) -> Self::Output { 26 Boolean::new(self == other) 27 } 28 29 /// Returns `true` if `self` and `other` are *not* equal. 30 fn is_not_equal(&self, other: &Self) -> Self::Output { 31 Boolean::new(self != other) 32 } 33 } 34 35 impl<E: Environment, I: IntegerType> Compare<Self> for Integer<E, I> { 36 type Output = Boolean<E>; 37 38 /// Returns `true` if `self` is less than `other`. 39 fn is_less_than(&self, other: &Self) -> Self::Output { 40 Boolean::new(self.integer < other.integer) 41 } 42 43 /// Returns `true` if `self` is greater than `other`. 44 fn is_greater_than(&self, other: &Self) -> Self::Output { 45 other.is_less_than(self) 46 } 47 48 /// Returns `true` if `self` is less than or equal to `other`. 49 fn is_less_than_or_equal(&self, other: &Self) -> Self::Output { 50 other.is_greater_than_or_equal(self) 51 } 52 53 /// Returns `true` if `self` is greater than or equal to `other`. 54 fn is_greater_than_or_equal(&self, other: &Self) -> Self::Output { 55 !self.is_less_than(other) 56 } 57 } 58 59 impl<E: Environment, I: IntegerType> Not for Integer<E, I> { 60 type Output = Self; 61 62 /// Returns the bitwise `NOT` of `self`. 63 #[inline] 64 fn not(self) -> Self::Output { 65 Integer::new(self.integer.not()) 66 } 67 } 68 69 impl<E: Environment, I: IntegerType> BitAnd for Integer<E, I> { 70 type Output = Self; 71 72 /// Returns the bitwise `AND` of `self` and `other`. 73 #[inline] 74 fn bitand(self, other: Self) -> Self::Output { 75 Integer::new(self.integer & other.integer) 76 } 77 } 78 79 impl<E: Environment, I: IntegerType> BitAnd<&Integer<E, I>> for Integer<E, I> { 80 type Output = Self; 81 82 /// Returns the bitwise `AND` of `self` and `other`. 83 #[inline] 84 fn bitand(self, other: &Integer<E, I>) -> Self::Output { 85 Integer::new(self.integer & other.integer) 86 } 87 } 88 89 impl<E: Environment, I: IntegerType> BitAndAssign for Integer<E, I> { 90 /// Performs the bitwise `AND` of `self` and `other` and assigns the result to `self`. 91 #[inline] 92 fn bitand_assign(&mut self, other: Self) { 93 self.integer = self.integer & other.integer; 94 } 95 } 96 97 impl<E: Environment, I: IntegerType> BitOr for Integer<E, I> { 98 type Output = Self; 99 100 /// Returns the bitwise `OR` of `self` and `other`. 101 #[inline] 102 fn bitor(self, other: Self) -> Self::Output { 103 Integer::new(self.integer | other.integer) 104 } 105 } 106 107 impl<E: Environment, I: IntegerType> BitOr<&Integer<E, I>> for Integer<E, I> { 108 type Output = Self; 109 110 /// Returns the bitwise `OR` of `self` and `other`. 111 #[inline] 112 fn bitor(self, other: &Integer<E, I>) -> Self::Output { 113 Integer::new(self.integer | other.integer) 114 } 115 } 116 117 impl<E: Environment, I: IntegerType> BitOrAssign for Integer<E, I> { 118 /// Performs the bitwise `OR` of `self` and `other` and assigns the result to `self`. 119 #[inline] 120 fn bitor_assign(&mut self, other: Self) { 121 self.integer = self.integer | other.integer; 122 } 123 } 124 125 impl<E: Environment, I: IntegerType> BitXor for Integer<E, I> { 126 type Output = Self; 127 128 /// Returns the bitwise `XOR` of `self` and `other`. 129 #[inline] 130 fn bitxor(self, other: Self) -> Self::Output { 131 Integer::new(self.integer ^ other.integer) 132 } 133 } 134 135 impl<E: Environment, I: IntegerType> BitXor<&Integer<E, I>> for Integer<E, I> { 136 type Output = Self; 137 138 /// Returns the bitwise `XOR` of `self` and `other`. 139 #[inline] 140 fn bitxor(self, other: &Integer<E, I>) -> Self::Output { 141 Integer::new(self.integer ^ other.integer) 142 } 143 } 144 145 impl<E: Environment, I: IntegerType> BitXorAssign for Integer<E, I> { 146 /// Performs the bitwise `XOR` of `self` and `other` and assigns the result to `self`. 147 #[inline] 148 fn bitxor_assign(&mut self, other: Self) { 149 self.integer = self.integer ^ other.integer; 150 } 151 } 152 153 impl<E: Environment, I: IntegerType, M: Magnitude> Shl<Integer<E, M>> for Integer<E, I> { 154 type Output = Self; 155 156 /// Shifts `self` to the left by `n` bits. 157 #[inline] 158 fn shl(self, n: Integer<E, M>) -> Self::Output { 159 // Unwrap is safe as we only cast up. 160 match self.integer.checked_shl(&n.integer.to_u32().unwrap()) { 161 Some(shifted) => Integer::new(shifted), 162 None => E::halt(format!("Failed to shift {self} left by {n} bits")), 163 } 164 } 165 } 166 167 impl<E: Environment, I: IntegerType, M: Magnitude> Shl<&Integer<E, M>> for Integer<E, I> { 168 type Output = Self; 169 170 /// Shifts `self` to the left by `n` bits. 171 #[inline] 172 fn shl(self, n: &Integer<E, M>) -> Self::Output { 173 // Unwrap is safe as we only cast up. 174 match self.integer.checked_shl(&n.integer.to_u32().unwrap()) { 175 Some(shifted) => Integer::new(shifted), 176 None => E::halt(format!("Failed to shift {self} left by {n} bits")), 177 } 178 } 179 } 180 181 impl<E: Environment, I: IntegerType, M: Magnitude> ShlChecked<Integer<E, M>> for Integer<E, I> { 182 type Output = Self; 183 184 /// Shifts `self` to the left by `n` bits. 185 #[inline] 186 fn shl_checked(&self, n: &Integer<E, M>) -> Self::Output { 187 // Unwrap is safe as we only cast up. 188 match self.integer.checked_shl(&n.integer.to_u32().unwrap()) { 189 Some(shifted) => Integer::new(shifted), 190 None => E::halt(format!("Failed to shift {self} left by {n} bits")), 191 } 192 } 193 } 194 195 impl<E: Environment, I: IntegerType, M: Magnitude> ShlWrapped<Integer<E, M>> for Integer<E, I> { 196 type Output = Self; 197 198 /// Shifts `self` to the left by `n` bits, continuing past the boundary. 199 #[inline] 200 fn shl_wrapped(&self, n: &Integer<E, M>) -> Self::Output { 201 Integer::new(self.integer.wrapping_shl(n.integer.to_u32().unwrap())) 202 } 203 } 204 205 impl<E: Environment, I: IntegerType, M: Magnitude> ShlAssign<Integer<E, M>> for Integer<E, I> { 206 /// Shifts `self` to the left by `n` bits and assigns the result to `self`. 207 #[inline] 208 fn shl_assign(&mut self, n: Integer<E, M>) { 209 match self.integer.checked_shl(&n.integer.to_u32().unwrap()) { 210 // Unwrap is safe as we only cast up. 211 Some(shifted) => { 212 self.integer = shifted; 213 } 214 None => E::halt(format!("Failed to shift {self} left by {n} bits")), 215 } 216 } 217 } 218 219 impl<E: Environment, I: IntegerType, M: Magnitude> Shr<Integer<E, M>> for Integer<E, I> { 220 type Output = Self; 221 222 /// Shifts `self` to the right by `n` bits. 223 #[inline] 224 fn shr(self, n: Integer<E, M>) -> Self::Output { 225 match self.integer.checked_shr(n.integer.to_u32().unwrap()) { 226 // Unwrap is safe as we only cast up. 227 Some(shifted) => Integer::new(shifted), 228 None => E::halt(format!("Failed to shift {self} right by {n} bits")), 229 } 230 } 231 } 232 233 impl<E: Environment, I: IntegerType, M: Magnitude> Shr<&Integer<E, M>> for Integer<E, I> { 234 type Output = Self; 235 236 /// Shifts `self` to the right by `n` bits. 237 #[inline] 238 fn shr(self, n: &Integer<E, M>) -> Self::Output { 239 match self.integer.checked_shr(n.integer.to_u32().unwrap()) { 240 // Unwrap is safe as we only cast up. 241 Some(shifted) => Integer::new(shifted), 242 None => E::halt(format!("Failed to shift {self} right by {n} bits")), 243 } 244 } 245 } 246 247 impl<E: Environment, I: IntegerType, M: Magnitude> ShrChecked<Integer<E, M>> for Integer<E, I> { 248 type Output = Self; 249 250 /// Shifts `self` to the right by `n` bits. 251 #[inline] 252 fn shr_checked(&self, n: &Integer<E, M>) -> Self::Output { 253 match self.integer.checked_shr(n.integer.to_u32().unwrap()) { 254 Some(shifted) => Integer::new(shifted), 255 None => E::halt(format!("Failed to shift {self} right by {n} bits")), 256 } 257 } 258 } 259 260 impl<E: Environment, I: IntegerType, M: Magnitude> ShrWrapped<Integer<E, M>> for Integer<E, I> { 261 type Output = Self; 262 263 /// Shifts `self` to the right by `n` bits, continuing past the boundary. 264 #[inline] 265 fn shr_wrapped(&self, n: &Integer<E, M>) -> Self::Output { 266 Integer::new(self.integer.wrapping_shr(n.integer.to_u32().unwrap())) 267 } 268 } 269 270 impl<E: Environment, I: IntegerType, M: Magnitude> ShrAssign<Integer<E, M>> for Integer<E, I> { 271 /// Shifts `self` to the right by `n` bits and assigns the result to `self`. 272 #[inline] 273 fn shr_assign(&mut self, n: Integer<E, M>) { 274 match self.integer.checked_shr(n.integer.to_u32().unwrap()) { 275 // Unwrap is safe as we only cast up. 276 Some(shifted) => { 277 self.integer = shifted; 278 } 279 None => E::halt(format!("Failed to shift {self} right by {n} bits")), 280 } 281 } 282 } 283 284 impl<E: Environment, I: IntegerType> Ternary for Integer<E, I> { 285 type Boolean = Boolean<E>; 286 type Output = Self; 287 288 /// Returns `first` if `condition` is `true`, otherwise returns `second`. 289 fn ternary(condition: &Self::Boolean, first: &Self, second: &Self) -> Self::Output { 290 match **condition { 291 true => *first, 292 false => *second, 293 } 294 } 295 }