snarkvm_synthesizer_program/logic/instruction/operation/
mod.rs

1// Copyright 2024-2025 Aleo Network Foundation
2// This file is part of the snarkVM 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
16mod assert;
17pub use assert::*;
18
19mod async_;
20pub use async_::*;
21
22mod call;
23pub use call::*;
24
25mod cast;
26pub use cast::*;
27
28mod commit;
29pub use commit::*;
30
31mod hash;
32pub use hash::*;
33
34mod is;
35pub use is::*;
36
37mod literals;
38pub use literals::*;
39
40mod macros;
41
42mod sign_verify;
43pub use sign_verify::*;
44
45use crate::Opcode;
46use console::network::prelude::*;
47
48#[allow(unused)]
49use console::account::Signature;
50
51pub trait Operation<N: Network, Value: Parser + ToBits, ValueType: Parser, const NUM_OPERANDS: usize> {
52    /// The opcode of the operation.
53    const OPCODE: Opcode;
54
55    /// Returns the result of evaluating the operation on the given inputs.
56    fn evaluate(inputs: &[Value; NUM_OPERANDS]) -> Result<Value>;
57
58    /// Returns the result of executing the operation on the given circuit inputs.
59    fn execute<A: circuit::Aleo<Network = N>>(
60        inputs: &[circuit::Literal<A>; NUM_OPERANDS],
61    ) -> Result<circuit::Literal<A>>;
62
63    /// Returns the output type from the given input types.
64    fn output_type(inputs: &[ValueType; NUM_OPERANDS]) -> Result<ValueType>;
65}
66
67/// Compute the absolute value of `first`, checking for overflow/underflow, and storing the outcome in `destination`.
68pub type Abs<N> = UnaryLiteral<N, AbsOperation<N>>;
69
70crate::operation!(
71    pub struct AbsOperation<console::prelude::AbsChecked, circuit::traits::AbsChecked, abs_checked, "abs"> {
72        I8 => I8 ("ensure overflows halt"),
73        I16 => I16 ("ensure overflows halt"),
74        I32 => I32 ("ensure overflows halt"),
75        I64 => I64 ("ensure overflows halt"),
76        I128 => I128 ("ensure overflows halt"),
77    }
78);
79
80/// Compute the absolute value of `first`, wrapping around at the boundary of the type, and storing the outcome in `destination`.
81pub type AbsWrapped<N> = UnaryLiteral<N, AbsWrappedOperation<N>>;
82
83crate::operation!(
84    pub struct AbsWrappedOperation<console::prelude::AbsWrapped, circuit::traits::AbsWrapped, abs_wrapped, "abs.w"> {
85        I8 => I8,
86        I16 => I16,
87        I32 => I32,
88        I64 => I64,
89        I128 => I128,
90    }
91);
92
93/// Adds `first` with `second`, storing the outcome in `destination`.
94pub type Add<N> = BinaryLiteral<N, AddOperation<N>>;
95
96crate::operation!(
97    pub struct AddOperation<core::ops::Add, core::ops::Add, add, "add"> {
98        (Field, Field) => Field,
99        (Group, Group) => Group,
100        (I8, I8) => I8 ("ensure overflows halt"),
101        (I16, I16) => I16 ("ensure overflows halt"),
102        (I32, I32) => I32 ("ensure overflows halt"),
103        (I64, I64) => I64 ("ensure overflows halt"),
104        (I128, I128) => I128 ("ensure overflows halt"),
105        (U8, U8) => U8 ("ensure overflows halt"),
106        (U16, U16) => U16 ("ensure overflows halt"),
107        (U32, U32) => U32 ("ensure overflows halt"),
108        (U64, U64) => U64 ("ensure overflows halt"),
109        (U128, U128) => U128 ("ensure overflows halt"),
110        (Scalar, Scalar) => Scalar,
111    }
112);
113
114/// Adds `first` with `second`, wrapping around at the boundary of the type, and storing the outcome in `destination`.
115pub type AddWrapped<N> = BinaryLiteral<N, AddWrappedOperation<N>>;
116
117crate::operation!(
118    pub struct AddWrappedOperation<console::prelude::AddWrapped, circuit::traits::AddWrapped, add_wrapped, "add.w"> {
119        (I8, I8) => I8,
120        (I16, I16) => I16,
121        (I32, I32) => I32,
122        (I64, I64) => I64,
123        (I128, I128) => I128,
124        (U8, U8) => U8,
125        (U16, U16) => U16,
126        (U32, U32) => U32,
127        (U64, U64) => U64,
128        (U128, U128) => U128,
129    }
130);
131
132/// Performs a bitwise `and` on `first` and `second`, storing the outcome in `destination`.
133pub type And<N> = BinaryLiteral<N, AndOperation<N>>;
134
135crate::operation!(
136    pub struct AndOperation<core::ops::BitAnd, core::ops::BitAnd, bitand, "and"> {
137        (Boolean, Boolean) => Boolean,
138        (I8, I8) => I8,
139        (I16, I16) => I16,
140        (I32, I32) => I32,
141        (I64, I64) => I64,
142        (I128, I128) => I128,
143        (U8, U8) => U8,
144        (U16, U16) => U16,
145        (U32, U32) => U32,
146        (U64, U64) => U64,
147        (U128, U128) => U128,
148    }
149);
150
151/// Divides `first` by `second`, storing the outcome in `destination`.
152pub type Div<N> = BinaryLiteral<N, DivOperation<N>>;
153
154crate::operation!(
155    pub struct DivOperation<core::ops::Div, core::ops::Div, div, "div"> {
156        (Field, Field) => Field ("ensure divide by zero halts"),
157        (I8, I8) => I8 ("ensure overflows halt", "ensure divide by zero halts"),
158        (I16, I16) => I16 ("ensure overflows halt", "ensure divide by zero halts"),
159        (I32, I32) => I32 ("ensure overflows halt", "ensure divide by zero halts"),
160        (I64, I64) => I64 ("ensure overflows halt", "ensure divide by zero halts"),
161        (I128, I128) => I128 ("ensure overflows halt", "ensure divide by zero halts"),
162        (U8, U8) => U8 ("ensure divide by zero halts"),
163        (U16, U16) => U16 ("ensure divide by zero halts"),
164        (U32, U32) => U32 ("ensure divide by zero halts"),
165        (U64, U64) => U64 ("ensure divide by zero halts"),
166        (U128, U128) => U128 ("ensure divide by zero halts"),
167        // (Scalar, Scalar) => Scalar,
168    }
169);
170
171/// Divides `first` by `second`, wrapping around at the boundary of the type, storing the outcome in `destination`.
172pub type DivWrapped<N> = BinaryLiteral<N, DivWrappedOperation<N>>;
173
174crate::operation!(
175    pub struct DivWrappedOperation<console::prelude::DivWrapped, circuit::traits::DivWrapped, div_wrapped, "div.w"> {
176        (I8, I8) => I8 ("ensure divide by zero halts"),
177        (I16, I16) => I16 ("ensure divide by zero halts"),
178        (I32, I32) => I32 ("ensure divide by zero halts"),
179        (I64, I64) => I64 ("ensure divide by zero halts"),
180        (I128, I128) => I128 ("ensure divide by zero halts"),
181        (U8, U8) => U8 ("ensure divide by zero halts"),
182        (U16, U16) => U16 ("ensure divide by zero halts"),
183        (U32, U32) => U32 ("ensure divide by zero halts"),
184        (U64, U64) => U64 ("ensure divide by zero halts"),
185        (U128, U128) => U128 ("ensure divide by zero halts"),
186    }
187);
188
189/// Doubles `first`, storing the outcome in `destination`.
190pub type Double<N> = UnaryLiteral<N, DoubleOperation<N>>;
191
192crate::operation!(
193    pub struct DoubleOperation<console::prelude::Double, circuit::traits::Double, double, "double"> {
194        Field => Field,
195        Group => Group,
196    }
197);
198
199/// Computes whether `first` is greater than `second` as a boolean, storing the outcome in `destination`.
200pub type GreaterThan<N> = BinaryLiteral<N, GreaterThanOperation<N>>;
201
202crate::operation!(
203    pub struct GreaterThanOperation<console::prelude::Compare, circuit::traits::Compare, is_greater_than, "gt"> {
204        // (Address, Address) => Boolean,
205        (Field, Field) => Boolean,
206        (I8, I8) => Boolean,
207        (I16, I16) => Boolean,
208        (I32, I32) => Boolean,
209        (I64, I64) => Boolean,
210        (I128, I128) => Boolean,
211        (U8, U8) => Boolean,
212        (U16, U16) => Boolean,
213        (U32, U32) => Boolean,
214        (U64, U64) => Boolean,
215        (U128, U128) => Boolean,
216        (Scalar, Scalar) => Boolean,
217    }
218);
219
220/// Computes whether `first` is greater than or equal to `second` as a boolean, storing the outcome in `destination`.
221pub type GreaterThanOrEqual<N> = BinaryLiteral<N, GreaterThanOrEqualOperation<N>>;
222
223crate::operation!(
224    pub struct GreaterThanOrEqualOperation<console::prelude::Compare, circuit::traits::Compare, is_greater_than_or_equal, "gte"> {
225        // (Address, Address) => Boolean,
226        (Field, Field) => Boolean,
227        (I8, I8) => Boolean,
228        (I16, I16) => Boolean,
229        (I32, I32) => Boolean,
230        (I64, I64) => Boolean,
231        (I128, I128) => Boolean,
232        (U8, U8) => Boolean,
233        (U16, U16) => Boolean,
234        (U32, U32) => Boolean,
235        (U64, U64) => Boolean,
236        (U128, U128) => Boolean,
237        (Scalar, Scalar) => Boolean,
238    }
239);
240
241/// Computes the multiplicative inverse of `first`, storing the outcome in `destination`.
242pub type Inv<N> = UnaryLiteral<N, InvOperation<N>>;
243
244crate::operation!(
245    pub struct InvOperation<console::prelude::Inverse, circuit::traits::Inverse, inverse?, "inv"> {
246        Field => Field ("ensure inverse of zero halts"),
247    }
248);
249
250/// Computes whether `first` is less than `second` as a boolean, storing the outcome in `destination`.
251pub type LessThan<N> = BinaryLiteral<N, LessThanOperation<N>>;
252
253crate::operation!(
254    pub struct LessThanOperation<console::prelude::Compare, circuit::traits::Compare, is_less_than, "lt"> {
255        // (Address, Address) => Boolean,
256        (Field, Field) => Boolean,
257        (I8, I8) => Boolean,
258        (I16, I16) => Boolean,
259        (I32, I32) => Boolean,
260        (I64, I64) => Boolean,
261        (I128, I128) => Boolean,
262        (U8, U8) => Boolean,
263        (U16, U16) => Boolean,
264        (U32, U32) => Boolean,
265        (U64, U64) => Boolean,
266        (U128, U128) => Boolean,
267        (Scalar, Scalar) => Boolean,
268    }
269);
270
271/// Computes whether `first` is less than or equal to `second` as a boolean, storing the outcome in `destination`.
272pub type LessThanOrEqual<N> = BinaryLiteral<N, LessThanOrEqualOperation<N>>;
273
274crate::operation!(
275    pub struct LessThanOrEqualOperation<console::prelude::Compare, circuit::traits::Compare, is_less_than_or_equal, "lte"> {
276        // (Address, Address) => Boolean,
277        (Field, Field) => Boolean,
278        (I8, I8) => Boolean,
279        (I16, I16) => Boolean,
280        (I32, I32) => Boolean,
281        (I64, I64) => Boolean,
282        (I128, I128) => Boolean,
283        (U8, U8) => Boolean,
284        (U16, U16) => Boolean,
285        (U32, U32) => Boolean,
286        (U64, U64) => Boolean,
287        (U128, U128) => Boolean,
288        (Scalar, Scalar) => Boolean,
289    }
290);
291
292/// Computes the result of `first` mod `second`, storing the outcome in the destination.
293pub type Modulo<N> = BinaryLiteral<N, ModuloOperation<N>>;
294
295crate::operation!(
296    pub struct ModuloOperation<console::prelude::Modulo, circuit::traits::Modulo, modulo, "mod"> {
297        (U8, U8) => U8("ensure divide by zero halts"),
298        (U16, U16) => U16("ensure divide by zero halts"),
299        (U32, U32) => U32("ensure divide by zero halts"),
300        (U64, U64) => U64("ensure divide by zero halts"),
301        (U128, U128) => U128("ensure divide by zero halts"),
302    }
303);
304
305/// Multiplies `first` and `second`, storing the outcome in `destination`.
306pub type Mul<N> = BinaryLiteral<N, MulOperation<N>>;
307
308crate::operation!(
309    pub struct MulOperation<core::ops::Mul, core::ops::Mul, mul, "mul"> {
310        (Field, Field) => Field,
311        (Group, Scalar) => Group,
312        (Scalar, Group) => Group,
313        (I8, I8) => I8 ("ensure overflows halt"),
314        (I16, I16) => I16 ("ensure overflows halt"),
315        (I32, I32) => I32 ("ensure overflows halt"),
316        (I64, I64) => I64 ("ensure overflows halt"),
317        (I128, I128) => I128 ("ensure overflows halt"),
318        (U8, U8) => U8 ("ensure overflows halt"),
319        (U16, U16) => U16 ("ensure overflows halt"),
320        (U32, U32) => U32 ("ensure overflows halt"),
321        (U64, U64) => U64 ("ensure overflows halt"),
322        (U128, U128) => U128 ("ensure overflows halt"),
323        // (Scalar, Scalar) => Scalar,
324    }
325);
326
327/// Multiplies `first` and `second`, wrapping around at the boundary of the type, storing the outcome in `destination`.
328pub type MulWrapped<N> = BinaryLiteral<N, MulWrappedOperation<N>>;
329
330crate::operation!(
331    pub struct MulWrappedOperation<console::prelude::MulWrapped, circuit::traits::MulWrapped, mul_wrapped, "mul.w"> {
332        (I8, I8) => I8,
333        (I16, I16) => I16,
334        (I32, I32) => I32,
335        (I64, I64) => I64,
336        (I128, I128) => I128,
337        (U8, U8) => U8,
338        (U16, U16) => U16,
339        (U32, U32) => U32,
340        (U64, U64) => U64,
341        (U128, U128) => U128,
342    }
343);
344
345/// Returns `false` if `first` and `second` are `true`, storing the outcome in `destination`.
346pub type Nand<N> = BinaryLiteral<N, NandOperation<N>>;
347
348crate::operation!(
349    pub struct NandOperation<console::prelude::Nand, circuit::traits::Nand, nand, "nand"> {
350        (Boolean, Boolean) => Boolean,
351    }
352);
353
354/// Negates `first`, storing the outcome in `destination`.
355pub type Neg<N> = UnaryLiteral<N, NegOperation<N>>;
356
357crate::operation!(
358    pub struct NegOperation<core::ops::Neg, core::ops::Neg, neg, "neg"> {
359        Field => Field,
360        Group => Group,
361        I8 => I8 ("ensure overflows halt"),
362        I16 => I16 ("ensure overflows halt"),
363        I32 => I32 ("ensure overflows halt"),
364        I64 => I64 ("ensure overflows halt"),
365        I128 => I128 ("ensure overflows halt"),
366    }
367);
368
369/// Returns `true` if neither `first` nor `second` is `true`, storing the outcome in `destination`.
370pub type Nor<N> = BinaryLiteral<N, NorOperation<N>>;
371
372crate::operation!(
373    pub struct NorOperation<console::prelude::Nor, circuit::traits::Nor, nor, "nor"> {
374        (Boolean, Boolean) => Boolean,
375    }
376);
377
378/// Flips each bit in the representation of `first`, storing the outcome in `destination`.
379pub type Not<N> = UnaryLiteral<N, NotOperation<N>>;
380
381crate::operation!(
382    pub struct NotOperation<core::ops::Not, core::ops::Not, not, "not"> {
383        Boolean => Boolean,
384        I8 => I8,
385        I16 => I16,
386        I32 => I32,
387        I64 => I64,
388        I128 => I128,
389        U8 => U8,
390        U16 => U16,
391        U32 => U32,
392        U64 => U64,
393        U128 => U128,
394    }
395);
396
397/// Performs a bitwise `or` on `first` and `second`, storing the outcome in `destination`.
398pub type Or<N> = BinaryLiteral<N, OrOperation<N>>;
399
400crate::operation!(
401    pub struct OrOperation<core::ops::BitOr, core::ops::BitOr, bitor, "or"> {
402        (Boolean, Boolean) => Boolean,
403        (I8, I8) => I8,
404        (I16, I16) => I16,
405        (I32, I32) => I32,
406        (I64, I64) => I64,
407        (I128, I128) => I128,
408        (U8, U8) => U8,
409        (U16, U16) => U16,
410        (U32, U32) => U32,
411        (U64, U64) => U64,
412        (U128, U128) => U128,
413    }
414);
415
416/// Raises `first` to the power of `second`, storing the outcome in `destination`.
417pub type Pow<N> = BinaryLiteral<N, PowOperation<N>>;
418
419crate::operation!(
420    pub struct PowOperation<console::prelude::Pow, circuit::traits::Pow, pow, "pow"> {
421        (Field, Field) => Field,
422        (I8, U8) => I8 ("ensure exponentiation overflows halt"),
423        (I8, U16) => I8 ("ensure exponentiation overflows halt"),
424        (I8, U32) => I8 ("ensure exponentiation overflows halt"),
425        (I16, U8) => I16 ("ensure exponentiation overflows halt"),
426        (I16, U16) => I16 ("ensure exponentiation overflows halt"),
427        (I16, U32) => I16 ("ensure exponentiation overflows halt"),
428        (I32, U8) => I32 ("ensure exponentiation overflows halt"),
429        (I32, U16) => I32 ("ensure exponentiation overflows halt"),
430        (I32, U32) => I32 ("ensure exponentiation overflows halt"),
431        (I64, U8) => I64 ("ensure exponentiation overflows halt"),
432        (I64, U16) => I64 ("ensure exponentiation overflows halt"),
433        (I64, U32) => I64 ("ensure exponentiation overflows halt"),
434        (I128, U8) => I128 ("ensure exponentiation overflows halt"),
435        (I128, U16) => I128 ("ensure exponentiation overflows halt"),
436        (I128, U32) => I128 ("ensure exponentiation overflows halt"),
437        (U8, U8) => U8 ("ensure exponentiation overflows halt"),
438        (U8, U16) => U8 ("ensure exponentiation overflows halt"),
439        (U8, U32) => U8 ("ensure exponentiation overflows halt"),
440        (U16, U8) => U16 ("ensure exponentiation overflows halt"),
441        (U16, U16) => U16 ("ensure exponentiation overflows halt"),
442        (U16, U32) => U16 ("ensure exponentiation overflows halt"),
443        (U32, U8) => U32 ("ensure exponentiation overflows halt"),
444        (U32, U16) => U32 ("ensure exponentiation overflows halt"),
445        (U32, U32) => U32 ("ensure exponentiation overflows halt"),
446        (U64, U8) => U64 ("ensure exponentiation overflows halt"),
447        (U64, U16) => U64 ("ensure exponentiation overflows halt"),
448        (U64, U32) => U64 ("ensure exponentiation overflows halt"),
449        (U128, U8) => U128 ("ensure exponentiation overflows halt"),
450        (U128, U16) => U128 ("ensure exponentiation overflows halt"),
451        (U128, U32) => U128 ("ensure exponentiation overflows halt"),
452    }
453);
454
455/// Raises `first` to the power of `second`, wrapping around at the boundary of the type, storing the outcome in `destination`.
456pub type PowWrapped<N> = BinaryLiteral<N, PowWrappedOperation<N>>;
457
458crate::operation!(
459    pub struct PowWrappedOperation<console::prelude::PowWrapped, circuit::traits::PowWrapped, pow_wrapped, "pow.w"> {
460        (I8, U8) => I8,
461        (I8, U16) => I8,
462        (I8, U32) => I8,
463        (I16, U8) => I16,
464        (I16, U16) => I16,
465        (I16, U32) => I16,
466        (I32, U8) => I32,
467        (I32, U16) => I32,
468        (I32, U32) => I32,
469        (I64, U8) => I64,
470        (I64, U16) => I64,
471        (I64, U32) => I64,
472        (I128, U8) => I128,
473        (I128, U16) => I128,
474        (I128, U32) => I128,
475        (U8, U8) => U8,
476        (U8, U16) => U8,
477        (U8, U32) => U8,
478        (U16, U8) => U16,
479        (U16, U16) => U16,
480        (U16, U32) => U16,
481        (U32, U8) => U32,
482        (U32, U16) => U32,
483        (U32, U32) => U32,
484        (U64, U8) => U64,
485        (U64, U16) => U64,
486        (U64, U32) => U64,
487        (U128, U8) => U128,
488        (U128, U16) => U128,
489        (U128, U32) => U128,
490    }
491);
492
493/// Divides `first` by `second`, storing the remainder in `destination`.
494pub type Rem<N> = BinaryLiteral<N, RemOperation<N>>;
495
496crate::operation!(
497    pub struct RemOperation<core::ops::Rem, core::ops::Rem, rem, "rem"> {
498        (I8, I8) => I8 ("ensure overflows halt", "ensure divide by zero halts"),
499        (I16, I16) => I16 ("ensure overflows halt", "ensure divide by zero halts"),
500        (I32, I32) => I32 ("ensure overflows halt", "ensure divide by zero halts"),
501        (I64, I64) => I64 ("ensure overflows halt", "ensure divide by zero halts"),
502        (I128, I128) => I128 ("ensure overflows halt", "ensure divide by zero halts"),
503        (U8, U8) => U8 ("ensure divide by zero halts"),
504        (U16, U16) => U16 ("ensure divide by zero halts"),
505        (U32, U32) => U32 ("ensure divide by zero halts"),
506        (U64, U64) => U64 ("ensure divide by zero halts"),
507        (U128, U128) => U128 ("ensure divide by zero halts"),
508    }
509);
510
511/// Divides `first` by `second`, wrapping around at the boundary of the type, storing the remainder in `destination`.
512pub type RemWrapped<N> = BinaryLiteral<N, RemWrappedOperation<N>>;
513
514crate::operation!(
515    pub struct RemWrappedOperation<console::prelude::RemWrapped, circuit::traits::RemWrapped, rem_wrapped, "rem.w"> {
516        (I8, I8) => I8 ("ensure divide by zero halts"),
517        (I16, I16) => I16 ("ensure divide by zero halts"),
518        (I32, I32) => I32 ("ensure divide by zero halts"),
519        (I64, I64) => I64 ("ensure divide by zero halts"),
520        (I128, I128) => I128 ("ensure divide by zero halts"),
521        (U8, U8) => U8 ("ensure divide by zero halts"),
522        (U16, U16) => U16 ("ensure divide by zero halts"),
523        (U32, U32) => U32 ("ensure divide by zero halts"),
524        (U64, U64) => U64 ("ensure divide by zero halts"),
525        (U128, U128) => U128 ("ensure divide by zero halts"),
526    }
527);
528
529/// Shifts `first` left by `second` bits, storing the outcome in `destination`.
530pub type Shl<N> = BinaryLiteral<N, ShlOperation<N>>;
531
532crate::operation!(
533    pub struct ShlOperation<console::prelude::ShlChecked, circuit::traits::ShlChecked, shl_checked, "shl"> {
534        (I8, U8) => I8 ("ensure shifting past boundary halts"),
535        (I8, U16) => I8 ("ensure shifting past boundary halts"),
536        (I8, U32) => I8 ("ensure shifting past boundary halts"),
537        (I16, U8) => I16 ("ensure shifting past boundary halts"),
538        (I16, U16) => I16 ("ensure shifting past boundary halts"),
539        (I16, U32) => I16 ("ensure shifting past boundary halts"),
540        (I32, U8) => I32 ("ensure shifting past boundary halts"),
541        (I32, U16) => I32 ("ensure shifting past boundary halts"),
542        (I32, U32) => I32 ("ensure shifting past boundary halts"),
543        (I64, U8) => I64 ("ensure shifting past boundary halts"),
544        (I64, U16) => I64 ("ensure shifting past boundary halts"),
545        (I64, U32) => I64 ("ensure shifting past boundary halts"),
546        (I128, U8) => I128 ("ensure shifting past boundary halts"),
547        (I128, U16) => I128 ("ensure shifting past boundary halts"),
548        (I128, U32) => I128 ("ensure shifting past boundary halts"),
549        (U8, U8) => U8 ("ensure shifting past boundary halts"),
550        (U8, U16) => U8 ("ensure shifting past boundary halts"),
551        (U8, U32) => U8 ("ensure shifting past boundary halts"),
552        (U16, U8) => U16 ("ensure shifting past boundary halts"),
553        (U16, U16) => U16 ("ensure shifting past boundary halts"),
554        (U16, U32) => U16 ("ensure shifting past boundary halts"),
555        (U32, U8) => U32 ("ensure shifting past boundary halts"),
556        (U32, U16) => U32 ("ensure shifting past boundary halts"),
557        (U32, U32) => U32 ("ensure shifting past boundary halts"),
558        (U64, U8) => U64 ("ensure shifting past boundary halts"),
559        (U64, U16) => U64 ("ensure shifting past boundary halts"),
560        (U64, U32) => U64 ("ensure shifting past boundary halts"),
561        (U128, U8) => U128 ("ensure shifting past boundary halts"),
562        (U128, U16) => U128 ("ensure shifting past boundary halts"),
563        (U128, U32) => U128 ("ensure shifting past boundary halts"),
564    }
565);
566
567/// Shifts `first` left by `second` bits, continuing past the boundary of the type, storing the outcome in `destination`.
568pub type ShlWrapped<N> = BinaryLiteral<N, ShlWrappedOperation<N>>;
569
570crate::operation!(
571    pub struct ShlWrappedOperation<console::prelude::ShlWrapped, circuit::traits::ShlWrapped, shl_wrapped, "shl.w"> {
572        (I8, U8) => I8,
573        (I8, U16) => I8,
574        (I8, U32) => I8,
575        (I16, U8) => I16,
576        (I16, U16) => I16,
577        (I16, U32) => I16,
578        (I32, U8) => I32,
579        (I32, U16) => I32,
580        (I32, U32) => I32,
581        (I64, U8) => I64,
582        (I64, U16) => I64,
583        (I64, U32) => I64,
584        (I128, U8) => I128,
585        (I128, U16) => I128,
586        (I128, U32) => I128,
587        (U8, U8) => U8,
588        (U8, U16) => U8,
589        (U8, U32) => U8,
590        (U16, U8) => U16,
591        (U16, U16) => U16,
592        (U16, U32) => U16,
593        (U32, U8) => U32,
594        (U32, U16) => U32,
595        (U32, U32) => U32,
596        (U64, U8) => U64,
597        (U64, U16) => U64,
598        (U64, U32) => U64,
599        (U128, U8) => U128,
600        (U128, U16) => U128,
601        (U128, U32) => U128,
602    }
603);
604
605/// Shifts `first` right by `second` bits, storing the outcome in `destination`.
606pub type Shr<N> = BinaryLiteral<N, ShrOperation<N>>;
607
608crate::operation!(
609    pub struct ShrOperation<console::prelude::ShrChecked, circuit::traits::ShrChecked, shr_checked, "shr"> {
610        (I8, U8) => I8 ("ensure shifting past boundary halts"),
611        (I8, U16) => I8 ("ensure shifting past boundary halts"),
612        (I8, U32) => I8 ("ensure shifting past boundary halts"),
613        (I16, U8) => I16 ("ensure shifting past boundary halts"),
614        (I16, U16) => I16 ("ensure shifting past boundary halts"),
615        (I16, U32) => I16 ("ensure shifting past boundary halts"),
616        (I32, U8) => I32 ("ensure shifting past boundary halts"),
617        (I32, U16) => I32 ("ensure shifting past boundary halts"),
618        (I32, U32) => I32 ("ensure shifting past boundary halts"),
619        (I64, U8) => I64 ("ensure shifting past boundary halts"),
620        (I64, U16) => I64 ("ensure shifting past boundary halts"),
621        (I64, U32) => I64 ("ensure shifting past boundary halts"),
622        (I128, U8) => I128 ("ensure shifting past boundary halts"),
623        (I128, U16) => I128 ("ensure shifting past boundary halts"),
624        (I128, U32) => I128 ("ensure shifting past boundary halts"),
625        (U8, U8) => U8 ("ensure shifting past boundary halts"),
626        (U8, U16) => U8 ("ensure shifting past boundary halts"),
627        (U8, U32) => U8 ("ensure shifting past boundary halts"),
628        (U16, U8) => U16 ("ensure shifting past boundary halts"),
629        (U16, U16) => U16 ("ensure shifting past boundary halts"),
630        (U16, U32) => U16 ("ensure shifting past boundary halts"),
631        (U32, U8) => U32 ("ensure shifting past boundary halts"),
632        (U32, U16) => U32 ("ensure shifting past boundary halts"),
633        (U32, U32) => U32 ("ensure shifting past boundary halts"),
634        (U64, U8) => U64 ("ensure shifting past boundary halts"),
635        (U64, U16) => U64 ("ensure shifting past boundary halts"),
636        (U64, U32) => U64 ("ensure shifting past boundary halts"),
637        (U128, U8) => U128 ("ensure shifting past boundary halts"),
638        (U128, U16) => U128 ("ensure shifting past boundary halts"),
639        (U128, U32) => U128 ("ensure shifting past boundary halts"),
640    }
641);
642
643/// Shifts `first` right by `second` bits, continuing past the boundary of the type, storing the outcome in `destination`.
644pub type ShrWrapped<N> = BinaryLiteral<N, ShrWrappedOperation<N>>;
645
646crate::operation!(
647    pub struct ShrWrappedOperation<console::prelude::ShrWrapped, circuit::traits::ShrWrapped, shr_wrapped, "shr.w"> {
648        (I8, U8) => I8,
649        (I8, U16) => I8,
650        (I8, U32) => I8,
651        (I16, U8) => I16,
652        (I16, U16) => I16,
653        (I16, U32) => I16,
654        (I32, U8) => I32,
655        (I32, U16) => I32,
656        (I32, U32) => I32,
657        (I64, U8) => I64,
658        (I64, U16) => I64,
659        (I64, U32) => I64,
660        (I128, U8) => I128,
661        (I128, U16) => I128,
662        (I128, U32) => I128,
663        (U8, U8) => U8,
664        (U8, U16) => U8,
665        (U8, U32) => U8,
666        (U16, U8) => U16,
667        (U16, U16) => U16,
668        (U16, U32) => U16,
669        (U32, U8) => U32,
670        (U32, U16) => U32,
671        (U32, U32) => U32,
672        (U64, U8) => U64,
673        (U64, U16) => U64,
674        (U64, U32) => U64,
675        (U128, U8) => U128,
676        (U128, U16) => U128,
677        (U128, U32) => U128,
678    }
679);
680
681/// Squares `first`, storing the outcome in `destination`.
682pub type Square<N> = UnaryLiteral<N, SquareOperation<N>>;
683
684crate::operation!(
685    pub struct SquareOperation<console::prelude::Square, circuit::traits::Square, square, "square"> {
686        Field => Field,
687    }
688);
689
690/// Computes the square root of `first`, storing the outcome in `destination`.
691pub type SquareRoot<N> = UnaryLiteral<N, SquareRootOperation<N>>;
692
693crate::operation!(
694    pub struct SquareRootOperation<console::prelude::SquareRoot, circuit::traits::SquareRoot, square_root?, "sqrt"> {
695        Field => Field ("ensure quadratic nonresidues halt"),
696    }
697);
698
699/// Computes `first - second`, storing the outcome in `destination`.
700pub type Sub<N> = BinaryLiteral<N, SubOperation<N>>;
701
702crate::operation!(
703    pub struct SubOperation<core::ops::Sub, core::ops::Sub, sub, "sub"> {
704        (Field, Field) => Field,
705        (Group, Group) => Group,
706        (I8, I8) => I8 ("ensure overflows halt"),
707        (I16, I16) => I16 ("ensure overflows halt"),
708        (I32, I32) => I32 ("ensure overflows halt"),
709        (I64, I64) => I64 ("ensure overflows halt"),
710        (I128, I128) => I128 ("ensure overflows halt"),
711        (U8, U8) => U8 ("ensure overflows halt"),
712        (U16, U16) => U16 ("ensure overflows halt"),
713        (U32, U32) => U32 ("ensure overflows halt"),
714        (U64, U64) => U64 ("ensure overflows halt"),
715        (U128, U128) => U128 ("ensure overflows halt"),
716        // (Scalar, Scalar) => Scalar,
717    }
718);
719
720/// Computes `first - second`, wrapping around at the boundary of the type, and storing the outcome in `destination`.
721pub type SubWrapped<N> = BinaryLiteral<N, SubWrappedOperation<N>>;
722
723crate::operation!(
724    pub struct SubWrappedOperation<console::prelude::SubWrapped, circuit::traits::SubWrapped, sub_wrapped, "sub.w"> {
725        (I8, I8) => I8,
726        (I16, I16) => I16,
727        (I32, I32) => I32,
728        (I64, I64) => I64,
729        (I128, I128) => I128,
730        (U8, U8) => U8,
731        (U16, U16) => U16,
732        (U32, U32) => U32,
733        (U64, U64) => U64,
734        (U128, U128) => U128,
735    }
736);
737
738/// Selects `first`, if `condition` is true, otherwise selects `second`, storing the result in `destination`.
739pub type Ternary<N> = TernaryLiteral<N, TernaryOperation<N>>;
740
741crate::operation!(
742    pub struct TernaryOperation<console::prelude::Ternary, circuit::traits::Ternary, ternary, "ternary"> {
743        (Boolean, Address, Address) => Address,
744        (Boolean, Boolean, Boolean) => Boolean,
745        (Boolean, Field, Field) => Field,
746        (Boolean, Group, Group) => Group,
747        (Boolean, I8, I8) => I8,
748        (Boolean, I16, I16) => I16,
749        (Boolean, I32, I32) => I32,
750        (Boolean, I64, I64) => I64,
751        (Boolean, I128, I128) => I128,
752        (Boolean, U8, U8) => U8,
753        (Boolean, U16, U16) => U16,
754        (Boolean, U32, U32) => U32,
755        (Boolean, U64, U64) => U64,
756        (Boolean, U128, U128) => U128,
757        (Boolean, Scalar, Scalar) => Scalar,
758        (Boolean, Signature, Signature) => Signature,
759        // (Boolean, StringType, StringType) => StringType,
760    }
761);
762
763/// Performs a bitwise `xor` on `first` and `second`, storing the outcome in `destination`.
764pub type Xor<N> = BinaryLiteral<N, XorOperation<N>>;
765
766crate::operation!(
767    pub struct XorOperation<core::ops::BitXor, core::ops::BitXor, bitxor, "xor"> {
768        (Boolean, Boolean) => Boolean,
769        (I8, I8) => I8,
770        (I16, I16) => I16,
771        (I32, I32) => I32,
772        (I64, I64) => I64,
773        (I128, I128) => I128,
774        (U8, U8) => U8,
775        (U16, U16) => U16,
776        (U32, U32) => U32,
777        (U64, U64) => U64,
778        (U128, U128) => U128,
779    }
780);