snarkvm_synthesizer_program/logic/instruction/operation/
mod.rs

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