/ console / types / integers / src / bitwise.rs
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  }