From f7921fc8bbbd1ce9d91f9d1c1583fe3939a1a8aa Mon Sep 17 00:00:00 2001 From: xunilrj Date: Mon, 14 Aug 2023 12:23:45 +0100 Subject: [PATCH 1/6] u256 bitwise and comparison operators --- .../asm_generation/fuel/fuel_asm_builder.rs | 31 +- sway-core/src/asm_lang/virtual_immediate.rs | 5 + sway-ir/src/optimize/misc_demotion.rs | 7 +- sway-ir/tests/serialize/wide_ops.ir | 18 + sway-lib-core/src/ops.sw | 1680 +++++++++++------ .../should_pass/language/u256/src/main.sw | 47 +- .../should_pass/language/u256/test.toml | 2 +- 7 files changed, 1179 insertions(+), 611 deletions(-) diff --git a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs index 48e8f790885..eaf834c5d81 100644 --- a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs +++ b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs @@ -588,6 +588,24 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { val2_reg, VirtualImmediate06::wide_op(WideOperations::Sub, true), ), + BinaryOpKind::And => VirtualOp::WQOP( + result_reg, + val1_reg, + val2_reg, + VirtualImmediate06::wide_op(WideOperations::And, true), + ), + BinaryOpKind::Or => VirtualOp::WQOP( + result_reg, + val1_reg, + val2_reg, + VirtualImmediate06::wide_op(WideOperations::Or, true), + ), + BinaryOpKind::Xor => VirtualOp::WQOP( + result_reg, + val1_reg, + val2_reg, + VirtualImmediate06::wide_op(WideOperations::Xor, true), + ), BinaryOpKind::Lsh => VirtualOp::WQOP( result_reg, val1_reg, @@ -670,7 +688,18 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> { val2_reg, VirtualImmediate06::wide_cmp(WideCmp::Equality, true), ), - _ => todo!(), + Predicate::LessThan => VirtualOp::WQCM( + res_reg.clone(), + val1_reg, + val2_reg, + VirtualImmediate06::wide_cmp(WideCmp::LessThan, true), + ), + Predicate::GreaterThan => VirtualOp::WQCM( + res_reg.clone(), + val1_reg, + val2_reg, + VirtualImmediate06::wide_cmp(WideCmp::GreaterThan, true), + ), }; self.cur_bytecode.push(Op { diff --git a/sway-core/src/asm_lang/virtual_immediate.rs b/sway-core/src/asm_lang/virtual_immediate.rs index 0c21c22ae61..0bead6b4892 100644 --- a/sway-core/src/asm_lang/virtual_immediate.rs +++ b/sway-core/src/asm_lang/virtual_immediate.rs @@ -11,6 +11,9 @@ pub enum WideOperations { Add = 0, Sub = 1, Not = 2, + Or = 3, + Xor = 4, + And = 5, Lsh = 6, Rsh = 7, } @@ -18,6 +21,8 @@ pub enum WideOperations { #[repr(u8)] pub enum WideCmp { Equality = 0, + LessThan = 2, + GreaterThan = 3, } /// 6-bit immediate value type diff --git a/sway-ir/src/optimize/misc_demotion.rs b/sway-ir/src/optimize/misc_demotion.rs index 354c6319007..67496f815a9 100644 --- a/sway-ir/src/optimize/misc_demotion.rs +++ b/sway-ir/src/optimize/misc_demotion.rs @@ -354,7 +354,9 @@ fn wide_binary_op_demotion(context: &mut Context, function: Function) -> Result< (Some(256), Some(256)) => { use BinaryOpKind::*; match op { - Add | Sub | Mul | Div | Mod => Some((block, instr_val)), + Add | Sub | Mul | Div | Mod | And | Or | Xor => { + Some((block, instr_val)) + } _ => todo!(), } } @@ -585,8 +587,7 @@ fn wide_cmp_demotion(context: &mut Context, function: Function) -> Result { use Predicate::*; match op { - Equal => Some((block, instr_val)), - _ => todo!(), + Equal | LessThan | GreaterThan => Some((block, instr_val)), } } _ => None, diff --git a/sway-ir/tests/serialize/wide_ops.ir b/sway-ir/tests/serialize/wide_ops.ir index 4097ed92843..e185d586b2a 100644 --- a/sway-ir/tests/serialize/wide_ops.ir +++ b/sway-ir/tests/serialize/wide_ops.ir @@ -29,6 +29,24 @@ script { wide not v0 to v0 // check: wide not v0 to v0 + wide and v0, v0 to v0 +// check: wide and v0, v0 to v0 + + wide or v0, v0 to v0 +// check: wide or v0, v0 to v0 + + wide xor v0, v0 to v0 +// check: wide xor v0, v0 to v0 + + v2 = wide cmp eq v0 v0 +// check: v2 = wide cmp eq v0 v0 + + v3 = wide cmp lt v0 v0 +// check: v3 = wide cmp lt v0 v0 + + v4 = wide cmp gt v0 v0 +// check: v4 = wide cmp gt v0 v0 + v5 = const unit () ret () v5 } diff --git a/sway-lib-core/src/ops.sw b/sway-lib-core/src/ops.sw index d624e2e2d05..ff733a363c1 100644 --- a/sway-lib-core/src/ops.sw +++ b/sway-lib-core/src/ops.sw @@ -4,54 +4,90 @@ use ::primitives::*; /// Trait for the addition of two values. pub trait Add { - /// Add two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value to add to self. - /// - /// # Returns - /// - /// * [Self] - The result of the two values added. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Add for MyStruct { - /// fn add(self, other: Self) -> Self { - /// let val = self.val + other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 1 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 + struct2; - /// assert(result_struct.val == 3); - /// } - /// ``` - fn add(self, other: Self) -> Self; + /// Add two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value to add to self. + /// + /// # Returns + /// + /// * [Self] - The result of the two values added. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Add for MyStruct { + /// fn add(self, other: Self) -> Self { + /// let val = self.val + other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 1 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 + struct2; + /// assert(result_struct.val == 3); + /// } + /// ``` +/// Add two values of the same type. + /// + + /// # Arguments + /// + /// * `other`: [Self] - The value to add to self. + /// + + /// # Returns + /// + /// +* [Self] - The result of the two values added. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + + /// + /// impl Add for MyStruct { + /// fn add(self, other: Self) -> Self { + /// let val = self.val + other.val; + /// Self { + /// val + + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 1 }; + / +// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 + struct2; + /// assert(result_struct.val == 3); + /// } + /// ``` + fn add(self, other: Self) -> Self; } - impl Add for u256 { fn add(self, other: Self) -> Self { __add(self, other) } } - impl Add for u64 { fn add(self, other: Self) -> Self { __add(self, other) } } - // Emulate overflowing arithmetic for non-64-bit integer types impl Add for u32 { fn add(self, other: Self) -> Self { @@ -67,7 +103,6 @@ impl Add for u32 { } } } - impl Add for u16 { fn add(self, other: Self) -> Self { let res = __add(self, other); @@ -78,7 +113,6 @@ impl Add for u16 { } } } - impl Add for u8 { fn add(self, other: Self) -> Self { let res = __add(self, other); @@ -89,127 +123,201 @@ impl Add for u8 { } } } - /// Trait for the subtraction of two values. pub trait Subtract { - /// Subtract two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value to subtract from self. - /// - /// # Returns - /// - /// * [Self] - The result of the two values subtracted. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Subtract for MyStruct { - /// fn subtract(self, other: Self) -> Self { - /// let val = self.val - other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 3 }; - /// let struct2 = MyStruct { val: 1 }; - /// let result_struct = struct1 - struct2; - /// assert(result_struct.val == 2); - /// } - /// ``` - fn subtract(self, other: Self) -> Self; + /// Subtract two values of the same type. + /// + + /// # Arguments + /// + /// * `other`: [Self] - The value to subtract from self. + /// + + /// # Returns + /// + /// +* [Self] - The result of the two values subtracted. + /// + /// # Examples + /// + + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + + /// + /// impl Subtract for MyStruct { + /// fn subtract(self, other: Self) -> Self { + + /// let val = self.val - other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 3 }; + /// let struct2 = MyStruct { val: 1 }; + /// let result_struct = struct1 - struct2; + /// assert(result_struct.val == 2); + /// } + /// ``` +/// Subtract two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value to subtract from self. + /// + /// # Returns + /// + /// * [Self] - The result of the two values subtracted. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Subtract for MyStruct { + /// fn subtract(self, other: Self) -> Self { + /// let val = self.val - other.val; + /// Self { + /// val + /// } + + /// } + /// } + /// + + /// fn foo() { + /// let struct1 = MyStruct { val: 3 }; + /// let struct2 = MyStruct { val: 1 }; + + /// let result_struct = struct1 - struct2; + /// assert(result_struct.val == 2); + /// } + /// ``` + fn subtract(self, other: Self) -> Self; } - impl Subtract for u256 { - fn subtract(self, other: Self) -> Self { + fn + subtract(self, other: Self) -> Self { __sub(self, other) } } - impl Subtract for u64 { fn subtract(self, other: Self) -> Self { __sub(self, other) } } - // unlike addition, underflowing subtraction does not need special treatment // because VM handles underflow -impl Subtract for u32 { +impl Subtract for u32 + { fn subtract(self, other: Self) -> Self { __sub(self, other) } } - impl Subtract for u16 { fn subtract(self, other: Self) -> Self { __sub(self, other) } } - -impl Subtract for u8 { +impl Subtract + for u8 { fn subtract(self, other: Self) -> Self { __sub(self, other) } } - /// Trait for the multiplication of two values. pub trait Multiply { - /// Multiply two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value to multiply with self. - /// - /// # Returns - /// - /// * [Self] - The result of the two values multiplied. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Multiply for MyStruct { - /// fn multiply(self, other: Self) -> Self { - /// let val = self.val * other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 3 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 * struct2; - /// assert(result_struct.val == 6); - /// } - /// ``` - fn multiply(self, other: Self) -> Self; + /// Multiply two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value to multiply with self. + /// + /// # Returns + /// + /// * [Self] - The result of the two values multiplied. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Multiply for MyStruct { + /// fn multiply(self, other: Self) -> Self { + /// let val = self.val * other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 3 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 * struct2; + /// assert(result_struct.val == 6); + /// +} + /// ``` +/// Multiply two values of the same type. + /// + + /// # Arguments + /// + /// * `other`: [Self] - The value to multiply with self. + /// + + /// # Returns + /// + /// * [Self] - The result of the two values multiplied. + + /// + /// # Examples + /// + / +// ```sway + /// struct MyStruct { + /// val: u64, + /// } + + /// + /// impl Multiply for MyStruct { + /// fn multiply(self, other: Self) -> Self { + /// let val = self.val * other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 3 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 * struct2; + /// assert(result_struct.val == 6); + /// } + /// ``` + fn multiply(self, other: Self) -> Self; } - impl Multiply for u256 { fn multiply(self, other: Self) -> Self { __mul(self, other) } } - impl Multiply for u64 { fn multiply(self, other: Self) -> Self { __mul(self, other) } } - // Emulate overflowing arithmetic for non-64-bit integer types impl Multiply for u32 { fn multiply(self, other: Self) -> Self { @@ -225,79 +333,119 @@ impl Multiply for u32 { } } } - impl Multiply for u16 { fn multiply(self, other: Self) -> Self { let res = __mul(self, other); - if __gt(res, Self::max()) { + if + __gt(res, Self::max()) { __revert(0) } else { res } } } - impl Multiply for u8 { + fn multiply(self, other: Self) -> Self { let res = __mul(self, other); - if __gt(res, Self::max()) { + if __gt( +res, Self::max()) { __revert(0) } else { res } } } - /// Trait for the division of two values. + pub trait Divide { - /// Divide two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value to divide with self. - /// - /// # Returns - /// - /// * [Self] - The result of the two values divided. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Divide for MyStruct { - /// fn divide(self, other: Self) -> Self { - /// let val = self.val / other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 / struct2; - /// assert(result_struct.val == 5); - /// } - /// ``` - fn divide(self, other: Self) -> Self; + /// Divide two values of the same type. + /// + /// # Arguments + + /// + /// * `other`: [Self] - The value to divide with self. + /// + / +// # Returns + /// + /// * [Self] - The result of the two values divided. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Divide for MyStruct { + /// fn divide(self, other: Self) -> Self { + /// let val = self.val / other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 / struct2; + /// assert(result_struct.val == 5); + /// } + /// ``` +/// Divide two values of the same type. + /// + /// # Arguments + + /// + /// * `other`: [Self] - The value to divide with self. + /// + + /// # Returns + /// + /// +* [Self] - The result of the two values divided. + /// + /// # Examples + / +// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// +} + /// + /// impl Divide for MyStruct { + /// fn divide(self, other: Self) -> Self { + /// let val = self.val / other.val; + + /// Self { + /// val + /// } + /// } + /// } + + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 / struct2; + /// assert(result_struct.val == 5); + /// } + /// ``` + fn divide(self, other: Self) -> Self; } - impl Divide for u256 { fn divide(self, other: Self) -> Self { __div(self, other) } } - impl Divide for u64 { fn divide(self, other: Self) -> Self { __div(self, other) } } - // division for unsigned integers cannot overflow, // but if signed integers are ever introduced, // overflow needs to be handled, since @@ -307,164 +455,285 @@ impl Divide for u32 { __div(self, other) } } - impl Divide for u16 { fn divide(self, other: Self) -> Self { __div(self, other) } } - impl Divide for u8 { fn divide(self, other: Self) -> Self { __div(self, other) } } - /// Trait for the modulo of two values. pub trait Mod { - /// Modulo two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value to mod with self. - /// - /// # Returns - /// - /// * [Self] - The modulo of the two values. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Mod for MyStruct { - /// fn modulo(self, other: Self) -> Self { - /// let val = self.val % other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 % struct2; - /// assert(result_struct.val == 0); - /// } - /// ``` - fn modulo(self, other: Self) -> Self; -} - -impl Mod for u256 { + /// Modulo two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value to mod with self. + /// + /// # Returns + /// + /// * [Self] - The modulo of the two values. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Mod for MyStruct { + /// fn modulo(self, other: Self) -> Self { + /// let val = self.val % other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 % struct2; + /// assert(result_struct.val == 0); + /// } + /// ``` +/// Modulo two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value to mod with self. + /// + /// # Returns + /// + /// * [Self] - The modulo of the two values. + + /// + /// # Examples + /// + / +// ```sway + /// struct MyStruct { + /// val: u64, + /// } + + /// + /// impl Mod for MyStruct { + /// fn modulo(self, other: Self) -> Self { + /// let val = self.val % other.val; + + /// Self { + /// val + /// + } + /// } + /// } + /// + + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 % struct2; + + /// assert(result_struct.val == 0); + /// } + /// ``` + fn modulo(self, other: Self) -> Self; +} +impl Mod + for u256 { fn modulo(self, other: Self) -> Self { __mod(self, other) } } - -impl Mod for u64 { +impl Mod + for u64 { fn modulo(self, other: Self) -> Self { __mod(self, other) } } - impl Mod for u32 { fn modulo(self, other: Self) -> Self { __mod(self, other) } } - impl Mod for u16 { fn modulo(self, other: Self) -> Self { __mod(self, other) } } - impl Mod for u8 { fn modulo(self, other: Self) -> Self { __mod(self, other) } } - /// Trait to invert a type. pub trait Not { - /// Inverts the value of the type. - /// - /// # Returns - /// - /// * [Self] - The result of the inverse. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: bool, - /// } - /// - /// impl Not for MyStruct { - /// fn not(self) -> Self { - /// Self { - /// val: !self.val, - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct = MyStruct { val: true }; - /// let result_struct = !struct; - /// assert(!result_struct.val); - /// } - /// ``` - fn not(self) -> Self; + /// Inverts the value of the type. + /// + /// # Returns + /// + /// * [Self] - The result of the inverse. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: bool, + /// } + /// + /// impl Not for MyStruct { + /// fn not(self) -> Self { + /// Self { + /// val: !self.val, + /// } + /// } + + /// } + /// + /// fn foo() { + /// let struct = MyStruct { val: true }; + /// let result_struct = !struct; + /// assert(!result_struct.val); + /// } + /// ``` +/// Inverts the value of the type. + /// + /// # Returns + /// + /// * [Self] - The result of the inverse. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: bool, + /// } + /// + /// impl Not for MyStruct { + /// fn not(self) -> Self { + /// Self { + /// val: !self.val, + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct = MyStruct { val: true }; + + /// let result_struct = !struct; + /// assert(!result_struct.val); + /// } + /// ``` + fn not(self) -> Self; } - impl Not for bool { + fn not(self) -> Self { __eq(self, false) } } - impl Not for u256 { fn not(self) -> Self { __not(self) } } +impl Not for u64 { + fn not( +self) -> Self { + __not(self) + } +} +impl Not for u32 { + fn not(self) -> Self { + let v = __not(self); + __and(v, u32::max()) + } +} +impl + Not for u16 { + fn not(self) -> Self { + let v = __not(self); + __and(v, u16::max()) + } +} +impl Not for u8 { + fn not(self) -> Self { + let v = __not(self); + __and(v, u8::max()) + } +} /// Trait to evaluate if two types are equal. pub trait Eq { - /// Evaluates if two values of the same type are equal. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [bool] - `true` if the values are equal, otherwise `false`. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Eq for MyStruct { - /// fn eq(self, other: Self) -> bool { - /// self.val == other.val - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 2 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result = struct1 == struct2; - /// assert(result); - /// } - /// ``` - fn eq(self, other: Self) -> bool; + /// Evaluates if two values of the same type are equal. + /// + + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [bool] - `true` if the values are equal, otherwise `false`. + + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Eq for MyStruct { + + /// fn eq(self, other: Self) -> bool { + /// self.val == other.val + /// } + /// } + /// + / +// fn foo() { + /// let struct1 = MyStruct { val: 2 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result = struct1 == struct2; + /// assert(result); + /// } + /// ``` +/// Evaluates if two values of the same type are equal. + /// + /// # Arguments + /// + + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [bool] - `true` if the values are equal, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Eq for MyStruct { + /// fn eq(self, other: Self) -> bool { + /// self.val == other.val + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 2 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result = struct1 == struct2; + /// assert(result); + /// } + /// ``` + fn eq(self, other: Self) -> bool; } { /// Evaluates if two values of the same type are not equal. /// @@ -474,157 +743,235 @@ pub trait Eq { /// /// # Arguments /// + /// * `other`: [Self] - The value of the same type. /// /// # Returns + /// /// * [bool] - `true` if the two values are not equal, otherwise `false`. /// /// # Examples + /// /// ```sway /// struct MyStruct { + /// val: u64, /// } /// - /// impl Eq for MyStruct { + / +// impl Eq for MyStruct { /// fn eq(self, other: Self) -> bool { /// self.val == other.val /// } + /// } /// /// fn foo() { /// let struct1 = MyStruct { val: 10 }; /// let struct2 = MyStruct { val: 2 }; /// let result = struct1 != struct2; - /// assert(result); + /// assert(result); /// } /// ``` fn neq(self, other: Self) -> bool { (self.eq(other)).not() } } - impl Eq for bool { fn eq(self, other: Self) -> bool { __eq(self, other) } } - impl Eq for u256 { fn eq(self, other: Self) -> bool { __eq(self, other) } } - impl Eq for u64 { fn eq(self, other: Self) -> bool { __eq(self, other) } } - impl Eq for u32 { fn eq(self, other: Self) -> bool { __eq(self, other) } } - impl Eq for u16 { fn eq(self, other: Self) -> bool { __eq(self, other) } } - impl Eq for u8 { fn eq(self, other: Self) -> bool { __eq(self, other) } } - impl Eq for b256 { fn eq(self, other: Self) -> bool { // Both self and other are addresses of the values, so we can use MEQ. - asm(r1: self, r2: other, r3, r4) { + asm( +r1: self, r2: other, r3, r4) { addi r3 zero i32; - meq r4 r1 r2 r3; + meq r4 r1 r2 r3; r4: bool } } } - -impl Eq for raw_ptr { +impl Eq for raw_ptr + { fn eq(self, other: Self) -> bool { __eq(self, other) } } - -/// Trait to evaluate if one value is greater or less than another of the same type. +/// +Trait to evaluate if one value is greater or less than another of the same type. pub trait Ord { - /// Evaluates if one value of the same type is greater than another. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [bool] - `true` if `self` is greater than `other`, otherwise `false`. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Ord for MyStruct { - /// fn gt(self, other: Self) -> bool { - /// self.val > other.val - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result = struct1 > struct2; - /// assert(result); - /// } - /// ``` - fn gt(self, other: Self) -> bool; - - /// Evaluates if one value of the same type is less than another. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [bool] - `true` if `self` is less than `other`, otherwise `false`. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Ord for MyStruct { - /// fn lt(self, other: Self) -> bool { - /// self.val < other.val - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result = struct1 < struct2; - /// assert(!result); - /// } - /// ``` - fn lt(self, other: Self) -> bool; + /// Evaluates if one value of the same type is greater than another. + /// + /// # Arguments + + /// + /// * `other`: [Self] - The value of the same type. + /// + + /// # Returns + /// + /// * [bool] - `true` if `self` is greater than `other`, otherwise `false`. + / +// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Ord for MyStruct { + /// fn gt(self, other: Self) -> bool { + /// self.val > other.val + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result = struct1 > struct2; + /// assert(result); + /// } + /// ``` +/// Evaluates if one value of the same type is greater than another. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [bool] - `true` if `self` is greater than `other`, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// +} + /// + /// impl Ord for MyStruct { + /// fn gt(self, other: Self) -> bool { + + /// self.val > other.val + /// } + /// } + /// + + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + + /// let result = struct1 > struct2; + /// assert(result); + /// } + / +// ``` + fn gt(self, other: Self) -> bool; + /// Evaluates if one value of the same type is less than another. + /// + + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [bool] - `true` if `self` is less than `other`, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// +} + /// + /// impl Ord for MyStruct { + /// fn lt(self, other: Self) -> bool { + /// self.val < other.val + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result = struct1 < struct2; + /// assert(!result); + /// } + /// ``` + +/// Evaluates if one value of the same type is less than another. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [bool] - `true` if `self` is less than `other`, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + + /// } + /// + /// impl Ord for MyStruct { + /// fn lt(self, other: Self) -> bool { + /// self.val < other.val + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result = struct1 < struct2; + /// assert(!result); + /// } + /// ``` + fn lt(self, other: Self) -> bool; +} +impl Ord for u256 { + fn gt(self, other: Self) -> bool { + __gt(self, other) + } + fn lt(self, other: Self) -> bool { + __lt(self, other) + } } - impl Ord for u64 { fn gt(self, other: Self) -> bool { __gt(self, other) @@ -633,7 +980,6 @@ impl Ord for u64 { __lt(self, other) } } - impl Ord for u32 { fn gt(self, other: Self) -> bool { __gt(self, other) @@ -642,7 +988,6 @@ impl Ord for u32 { __lt(self, other) } } - impl Ord for u16 { fn gt(self, other: Self) -> bool { __gt(self, other) @@ -651,7 +996,6 @@ impl Ord for u16 { __lt(self, other) } } - impl Ord for u8 { fn gt(self, other: Self) -> bool { __gt(self, other) @@ -660,12 +1004,11 @@ impl Ord for u8 { __lt(self, other) } } - impl Ord for b256 { + fn gt(self, other: Self) -> bool { let (self_word_1, self_word_2, self_word_3, self_word_4) = decompose(self); let (other_word_1, other_word_2, other_word_3, other_word_4) = decompose(other); - if self.eq(other) { false } else if self_word_1.neq(other_word_1) { @@ -678,11 +1021,9 @@ impl Ord for b256 { self_word_4.gt(other_word_4) } } - fn lt(self, other: Self) -> bool { let (self_word_1, self_word_2, self_word_3, self_word_4) = decompose(self); let (other_word_1, other_word_2, other_word_3, other_word_4) = decompose(other); - if self.eq(other) { false } else if self_word_1.neq(other_word_1) { @@ -696,220 +1037,311 @@ impl Ord for b256 { } } } - /// Trait to bitwise AND two values of the same type. pub trait BitwiseAnd { - /// Bitwise AND two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [Self] - The result of the bitwise AND of the two values. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl BitwiseAnd for MyStruct { - /// fn binary_and(self, other: Self) -> Self { - /// let val = self.val & other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 11 }; - /// let result_struct = struct1 & struct2; - /// assert(result_struct.val == 10); - /// } - /// ``` - fn binary_and(self, other: Self) -> Self; + /// Bitwise AND two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [Self] - The result of the bitwise AND of the two values. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + + /// val: u64, + /// } + /// + /// impl BitwiseAnd for MyStruct { + /// fn binary_and(self, other: Self) -> Self { + + /// let val = self.val & other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 11 }; + /// let result_struct = struct1 & struct2; + /// assert(result_struct.val == 10); + /// } + /// ``` +/// Bitwise AND two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [Self] - The result of the bitwise AND of the two values. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl BitwiseAnd for MyStruct { + /// fn binary_and(self, other: Self) -> Self { + /// let val = self.val & other.val; + /// Self { + /// val + + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 11 }; + /// let result_struct = struct1 & struct2; + /// assert(result_struct.val == 10); + /// } + /// ``` + fn binary_and(self, other: Self) -> Self; +} +impl BitwiseAnd for u256 { + fn binary_and(self, other: Self) -> Self { + __and(self, other) + } } - impl BitwiseAnd for u64 { fn binary_and(self, other: Self) -> Self { __and(self, other) } } - impl BitwiseAnd for u32 { fn binary_and(self, other: Self) -> Self { __and(self, other) } } - impl BitwiseAnd for u16 { fn binary_and(self, other: Self) -> Self { __and(self, other) } } - impl BitwiseAnd for u8 { fn binary_and(self, other: Self) -> Self { __and(self, other) } } - /// Trait to bitwise OR two values of the same type. pub trait BitwiseOr { - /// Bitwise OR two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [Self] - The result of the bitwise OR of the two values. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl BitwiseOr for MyStruct { - /// fn binary_or(self, other: Self) -> Self { - /// let val = self.val | other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 11 }; - /// let result_struct = struct1 | struct2; - /// assert(result_struct.val == 11); - /// } - /// ``` - fn binary_or(self, other: Self) -> Self; + /// Bitwise OR two values of the same type. + /// + + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + + /// * [Self] - The result of the bitwise OR of the two values. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + + /// val: u64, + /// } + /// + /// impl BitwiseOr for MyStruct { + /// fn binary_or(self, other: Self) -> Self { + /// let val = self.val | other.val; + / +// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + + /// let struct2 = MyStruct { val: 11 }; + /// let result_struct = struct1 | struct2; + /// assert(result_struct.val == 11); + /// } + /// ``` +/// Bitwise OR two values of the same type. + + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [Self] - The result of the bitwise OR of the two values. + + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl BitwiseOr for MyStruct { + /// fn binary_or(self, other: Self) -> Self { + /// let val = self.val | other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 11 }; + /// let result_struct = struct1 | struct2; + /// assert(result_struct.val == 11); + /// } + /// ``` + fn binary_or(self, other: Self) -> Self; +} +impl BitwiseOr for u256 { + fn binary_or(self, other: Self) -> Self { + __or(self, other) + } } - impl BitwiseOr for u64 { fn binary_or(self, other: Self) -> Self { __or(self, other) + } } - impl BitwiseOr for u32 { - fn binary_or(self, other: Self) -> Self { + fn binary_or(self +, other: Self) -> Self { __or(self, other) } } - impl BitwiseOr for u16 { fn binary_or(self, other: Self) -> Self { __or(self, other) } } - impl BitwiseOr for u8 { - fn binary_or(self, other: Self) -> Self { + fn binary_or(self, + other: Self) -> Self { __or(self, other) } } - /// Trait to bitwise XOR two values of the same type. pub trait BitwiseXor { - /// Bitwise XOR two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [Self] - The result of the bitwise XOR of the two values. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl BitwiseXOr for MyStruct { - /// fn binary_xor(self, other: Self) -> Self { - /// let val = self.val ^ other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 11 }; - /// let result_struct = struct1 ^ struct2; - /// assert(result_struct.val == 1); - /// } - /// ``` - fn binary_xor(self, other: Self) -> Self; + /// Bitwise XOR two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [Self] - The result of the bitwise XOR of the two values. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl BitwiseXOr for MyStruct { + /// fn binary_xor(self, other: Self) -> Self { + /// let val = self.val ^ other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 11 }; + + /// let result_struct = struct1 ^ struct2; + /// assert(result_struct.val == 1); + + /// } + /// ``` +/// Bitwise XOR two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + / +// # Returns + /// + /// * [Self] - The result of the bitwise XOR of the two values. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + + /// } + /// + /// impl BitwiseXOr for MyStruct { + /// fn binary_xor(self, other: Self) -> Self { + + /// let val = self.val ^ other.val; + /// Self { + /// val + /// } + /// } + /// } + + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 11 }; + /// let result_struct = struct1 ^ struct2; + /// assert(result_struct.val == 1); + /// } + + /// ``` + fn binary_xor(self, other: Self) -> Self; +} +impl BitwiseXor for u256 { + fn binary_xor(self, other: Self) -> Self { + __xor(self, other) + } } - impl BitwiseXor for u64 { fn binary_xor(self, other: Self) -> Self { __xor(self, other) } } - impl BitwiseXor for u32 { fn binary_xor(self, other: Self) -> Self { __xor(self, other) } } - impl BitwiseXor for u16 { fn binary_xor(self, other: Self) -> Self { __xor(self, other) } } - impl BitwiseXor for u8 { fn binary_xor(self, other: Self) -> Self { __xor(self, other) } } - -impl Not for u64 { - fn not(self) -> Self { - __not(self) - } -} - -impl Not for u32 { - fn not(self) -> Self { - let v = __not(self); - __and(v, u32::max()) - } -} - -impl Not for u16 { - fn not(self) -> Self { - let v = __not(self); - __and(v, u16::max()) - } -} - -impl Not for u8 { - fn not(self) -> Self { - let v = __not(self); - __and(v, u8::max()) - } -} - impl BitwiseAnd for b256 { fn binary_and(val: self, other: Self) -> Self { let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val); @@ -922,7 +1354,6 @@ impl BitwiseAnd for b256 { rebuilt } } - impl BitwiseOr for b256 { fn binary_or(val: self, other: Self) -> Self { let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val); @@ -935,7 +1366,6 @@ impl BitwiseOr for b256 { rebuilt } } - impl BitwiseXor for b256 { fn binary_xor(val: self, other: Self) -> Self { let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val); @@ -948,7 +1378,6 @@ impl BitwiseXor for b256 { rebuilt } } - /// Trait to evaluate if one value is greater than or equal, or less than or equal to another of the same type. trait OrdEq: Ord + Eq { } { @@ -991,14 +1420,12 @@ trait OrdEq: Ord + Eq { /// let struct1 = MyStruct { val: 10 }; /// let struct2 = MyStruct { val: 10 }; /// let result = struct1 >= struct2; - /// assert(result); + /// assert(result); /// } /// ``` fn ge(self, other: Self) -> bool { self.gt(other) || self.eq(other) - } - - /// Evaluates if one value of the same type is less or equal to than another. + } /// Evaluates if one value of the same type is less or equal to than another. /// /// # Additional Information /// @@ -1037,91 +1464,158 @@ trait OrdEq: Ord + Eq { /// let struct1 = MyStruct { val: 10 }; /// let struct2 = MyStruct { val: 10 }; /// let result = struct1 <= struct2; - /// assert(result); + /// assert(result); /// } /// ``` fn le(self, other: Self) -> bool { self.lt(other) || self.eq(other) } } - -impl OrdEq for u64 {} -impl OrdEq for u32 {} -impl OrdEq for u16 {} -impl OrdEq for u8 {} -impl OrdEq for b256 {} - +impl OrdEq for u256 { +} +impl OrdEq for u64 { +} +impl OrdEq for u32 { +} +impl OrdEq for u16 { +} +impl OrdEq for u8 { +} +impl OrdEq for b256 { +} /// Trait to bit shift a value. pub trait Shift { - /// Bit shift left by an amount. - /// - /// # Arguments - /// - /// * `other`: [u64] - The amount to bit shift by. - /// - /// # Returns - /// - /// * [Self] - The result of the value bit shifted to the left. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Shift for MyStruct { - /// fn lsh(self, other: u64) -> Self { - /// let val = self.val << other; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let result_struct = struct1 << 3; - /// assert(result_struct.val == 80); - /// } - /// ``` - fn lsh(self, other: u64) -> Self; - - /// Bit shift right by an amount. - /// - /// # Arguments - /// - /// * `other`: [u64] - The amount to bit shift by. - /// - /// # Returns - /// - /// * [Self] - The result of the value bit shifted to the right. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Shift for MyStruct { - /// fn rsh(self, other: u64) -> Self { - /// let val = self.val >> other; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let result_struct = struct1 >> 1; - /// assert(result_struct.val == 5); - /// } - /// ``` - fn rsh(self, other: u64) -> Self; + /// Bit shift left by an amount. + /// + /// # Arguments + /// + /// * `other`: [u64] - The amount to bit shift by. + /// + /// # Returns + /// + /// * [Self] - The result of the value bit shifted to the left. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Shift for MyStruct { + /// fn lsh(self, other: u64) -> Self { + /// let val = self.val << other; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let result_struct = struct1 << 3; + /// assert(result_struct.val == 80); + /// } + /// ``` +/// Bit shift left by an amount. + /// + /// # Arguments + /// + /// * `other`: [u64] - The amount to bit shift by. + /// + /// # Returns + /// + /// * [Self] - The result of the value bit shifted to the left. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Shift for MyStruct { + /// fn lsh(self, other: u64) -> Self { + /// let val = self.val << other; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let result_struct = struct1 << 3; + /// assert(result_struct.val == 80); + /// } + /// ``` + fn lsh(self, other: u64) -> Self; + /// Bit shift right by an amount. + /// + /// # Arguments + /// + /// * `other`: [u64] - The amount to bit shift by. + /// + /// # Returns + /// + /// * [Self] - The result of the value bit shifted to the right. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Shift for MyStruct { + /// fn rsh(self, other: u64) -> Self { + /// let val = self.val >> other; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let result_struct = struct1 >> 1; + /// assert(result_struct.val == 5); + /// } + /// ``` +/// Bit shift right by an amount. + /// + /// # Arguments + /// + /// * `other`: [u64] - The amount to bit shift by. + /// + /// # Returns + /// + /// * [Self] - The result of the value bit shifted to the right. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Shift for MyStruct { + /// fn rsh(self, other: u64) -> Self { + /// let val = self.val >> other; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let result_struct = struct1 >> 1; + /// assert(result_struct.val == 5); + /// } + /// ``` + fn rsh(self, other: u64) -> Self; } - impl Shift for u256 { fn lsh(self, other: u64) -> Self { __lsh(self, other) @@ -1130,7 +1624,6 @@ impl Shift for u256 { __rsh(self, other) } } - impl Shift for u64 { fn lsh(self, other: u64) -> Self { __lsh(self, other) @@ -1139,7 +1632,6 @@ impl Shift for u64 { __rsh(self, other) } } - impl Shift for u32 { fn lsh(self, other: u64) -> Self { // any non-64-bit value is compiled to a u64 value under-the-hood @@ -1150,7 +1642,6 @@ impl Shift for u32 { __rsh(self, other) } } - impl Shift for u16 { fn lsh(self, other: u64) -> Self { __and(__lsh(self, other), Self::max()) @@ -1159,7 +1650,6 @@ impl Shift for u16 { __rsh(self, other) } } - impl Shift for u8 { fn lsh(self, other: u64) -> Self { __and(__lsh(self, other), Self::max()) @@ -1168,7 +1658,6 @@ impl Shift for u8 { __rsh(self, other) } } - impl Shift for b256 { fn lsh(self, shift_amount: u64) -> Self { let (word_1, word_2, word_3, word_4) = decompose(self); @@ -1176,7 +1665,6 @@ impl Shift for b256 { let mut w2 = 0; let mut w3 = 0; let mut w4 = 0; - let w = shift_amount.divide(64); // num of whole words to shift in addition to b let b = shift_amount.modulo(64); // num of bits to shift within each word // TODO: Use generalized looping version when vec lands ! @@ -1199,17 +1687,14 @@ impl Shift for b256 { w1 = word_3.lsh(b).add(carry_4); w2 = shifted_4; } else if w.eq(3) { w1 = word_4.lsh(b); } else { (); }; - compose((w1, w2, w3, w4)) } - fn rsh(self, shift_amount: u64) -> Self { let (word_1, word_2, word_3, word_4) = decompose(self); let mut w1 = 0; let mut w2 = 0; let mut w3 = 0; let mut w4 = 0; - let w = shift_amount.divide(64); // num of whole words to shift in addition to b let b = shift_amount.modulo(64); // num of bits to shift within each word // TODO: Use generalized looping version when vec lands ! @@ -1232,11 +1717,9 @@ impl Shift for b256 { w4 = word_2.rsh(b).add(carry_1); w3 = shifted_1; } else if w.eq(3) { w4 = word_1.rsh(b); } else { (); }; - compose((w1, w2, w3, w4)) } } - ///////////////////////////////////////////////// // Internal Helpers ///////////////////////////////////////////////// @@ -1247,7 +1730,6 @@ fn lsh_with_carry(word: u64, shift_amount: u64) -> (u64, u64) { let shifted = word.lsh(shift_amount); (shifted, carry) } - /// Right shift a u64 and preserve the overflow amount if any fn rsh_with_carry(word: u64, shift_amount: u64) -> (u64, u64) { let left_shift_amount = 64.subtract(shift_amount); @@ -1255,17 +1737,14 @@ fn rsh_with_carry(word: u64, shift_amount: u64) -> (u64, u64) { let shifted = word.rsh(shift_amount); (shifted, carry) } - /// Build a single b256 value from a tuple of 4 u64 values. fn compose(words: (u64, u64, u64, u64)) -> b256 { asm(r1: words) { r1: b256 } } - /// Get a tuple of 4 u64 values from a single b256 value. fn decompose(val: b256) -> (u64, u64, u64, u64) { asm(r1: val) { r1: (u64, u64, u64, u64) } } - #[test] fn test_compose() { let expected: b256 = 0x0000000000000001_0000000000000002_0000000000000003_0000000000000004; @@ -1274,7 +1753,6 @@ fn test_compose() { __revert(0) } } - #[test] fn test_decompose() { let initial: b256 = 0x0000000000000001_0000000000000002_0000000000000003_0000000000000004; diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw index 34a0c7a0108..609e3aad157 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw @@ -19,11 +19,14 @@ fn locals() -> u256 { result } -// returns 2 -fn not_operator() -> u256 { +// returns 9 +fn bitwise_operators() -> u256 { let a = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFu256; - let b = 0x0000000000000000000000000000000000000000000000000000000000000002u256; - !(a - b) + let b = 0x0000000000000000000000000000000000000000000000000000000000000003u256; + let c = 0x0000000000000000000000000000000000000000000000000000000000000002u256; + let d = 0x0000000000000000000000000000000000000000000000000000000000000004u256; + let e = 0x000000000000000000000000000000000000000000000000000000000000000Fu256; + !(a - b) & c | d ^ e } // returns 8 @@ -66,6 +69,40 @@ fn shift_operators() -> u256 { (a << 4) >> 2 } + +// returns 0 +fn comparison_operators() -> u256 { + let a = 0x0000000000000000000000000000000000000000000000000000000000000001u256; + let b = 0x0000000000000000000000000000000000000000000000000000000000000002u256; + let c = 0x0000000000000000000000000000000000000000000000000000000000000003u256; + let d = 0x0000000000000000000000000000000000000000000000000000000000000003u256; + + assert(c == c); + assert(c <= c); + assert(c >= c); + + assert(c == d); + assert(d == c); + assert(c <= d); + assert(c >= d); + assert(d <= c); + assert(d >= c); + + assert(a < b); + assert(b < c); + assert(a < c); + + assert(a <= b); + assert(b <= c); + assert(a <= c); + + assert(b > a); + assert(c > b); + assert(c > a); + + return 0x0000000000000000000000000000000000000000000000000000000000000000u256; +} + fn main() -> u256 { - constants() + locals() + not_operator() + shift_operators() + constants() + locals() + bitwise_operators() + shift_operators() + comparison_operators() } \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/test.toml index d3b2918a072..e0beb8b65ab 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/test.toml @@ -1,3 +1,3 @@ category = "run" -expected_result = { action = "return_data", value = "000000000000000000000000000000000000000000000000000000000000000E" } +expected_result = { action = "return_data", value = "0000000000000000000000000000000000000000000000000000000000000017" } validate_abi = true From 5416a5e72dc4721bba1601313a5d4046a6a951c2 Mon Sep 17 00:00:00 2001 From: xunilrj Date: Mon, 14 Aug 2023 15:30:10 +0100 Subject: [PATCH 2/6] fix returned value --- .../should_pass/language/u256/src/main.sw | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw index 609e3aad157..7a58a8ab4b9 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw @@ -19,8 +19,17 @@ fn locals() -> u256 { result } -// returns 9 +// returns 11 fn bitwise_operators() -> u256 { + let a = 18446744073709551615u64; + let b = 3u64; + let c = 2u64; + let d = 4u64; + let e = 15u64; + + let r = !(a - b) & c | d ^ e; + assert(r == 11); + let a = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFu256; let b = 0x0000000000000000000000000000000000000000000000000000000000000003u256; let c = 0x0000000000000000000000000000000000000000000000000000000000000002u256; From aa069654a267d7fbc00b6c7c68336fc78c5c6e73 Mon Sep 17 00:00:00 2001 From: xunilrj Date: Mon, 14 Aug 2023 15:30:47 +0100 Subject: [PATCH 3/6] fix returned value comment --- .../test_programs/should_pass/language/u256/src/main.sw | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw index 7a58a8ab4b9..532f11755b1 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/src/main.sw @@ -35,7 +35,11 @@ fn bitwise_operators() -> u256 { let c = 0x0000000000000000000000000000000000000000000000000000000000000002u256; let d = 0x0000000000000000000000000000000000000000000000000000000000000004u256; let e = 0x000000000000000000000000000000000000000000000000000000000000000Fu256; - !(a - b) & c | d ^ e + let r = !(a - b) & c | d ^ e; + + assert(r == 0x000000000000000000000000000000000000000000000000000000000000000Bu256); + + r } // returns 8 From a53a4897f70afc5310bd9e334259925564c02bf5 Mon Sep 17 00:00:00 2001 From: xunilrj Date: Tue, 22 Aug 2023 09:29:31 +0100 Subject: [PATCH 4/6] fix rebase --- sway-lib-core/src/ops.sw | 1623 ++++++++++++++------------------------ 1 file changed, 587 insertions(+), 1036 deletions(-) diff --git a/sway-lib-core/src/ops.sw b/sway-lib-core/src/ops.sw index ff733a363c1..c32e1f3b8a9 100644 --- a/sway-lib-core/src/ops.sw +++ b/sway-lib-core/src/ops.sw @@ -4,90 +4,54 @@ use ::primitives::*; /// Trait for the addition of two values. pub trait Add { - /// Add two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value to add to self. - /// - /// # Returns - /// - /// * [Self] - The result of the two values added. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Add for MyStruct { - /// fn add(self, other: Self) -> Self { - /// let val = self.val + other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 1 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 + struct2; - /// assert(result_struct.val == 3); - /// } - /// ``` -/// Add two values of the same type. - /// - - /// # Arguments - /// - /// * `other`: [Self] - The value to add to self. - /// - - /// # Returns - /// - /// -* [Self] - The result of the two values added. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - - /// - /// impl Add for MyStruct { - /// fn add(self, other: Self) -> Self { - /// let val = self.val + other.val; - /// Self { - /// val - - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 1 }; - / -// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 + struct2; - /// assert(result_struct.val == 3); - /// } - /// ``` - fn add(self, other: Self) -> Self; + /// Add two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value to add to self. + /// + /// # Returns + /// + /// * [Self] - The result of the two values added. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Add for MyStruct { + /// fn add(self, other: Self) -> Self { + /// let val = self.val + other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 1 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 + struct2; + /// assert(result_struct.val == 3); + /// } + /// ``` + fn add(self, other: Self) -> Self; } + impl Add for u256 { fn add(self, other: Self) -> Self { __add(self, other) } } + impl Add for u64 { fn add(self, other: Self) -> Self { __add(self, other) } } + // Emulate overflowing arithmetic for non-64-bit integer types impl Add for u32 { fn add(self, other: Self) -> Self { @@ -103,6 +67,7 @@ impl Add for u32 { } } } + impl Add for u16 { fn add(self, other: Self) -> Self { let res = __add(self, other); @@ -113,6 +78,7 @@ impl Add for u16 { } } } + impl Add for u8 { fn add(self, other: Self) -> Self { let res = __add(self, other); @@ -123,201 +89,127 @@ impl Add for u8 { } } } + /// Trait for the subtraction of two values. pub trait Subtract { - /// Subtract two values of the same type. - /// - - /// # Arguments - /// - /// * `other`: [Self] - The value to subtract from self. - /// - - /// # Returns - /// - /// -* [Self] - The result of the two values subtracted. - /// - /// # Examples - /// - - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - - /// - /// impl Subtract for MyStruct { - /// fn subtract(self, other: Self) -> Self { - - /// let val = self.val - other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 3 }; - /// let struct2 = MyStruct { val: 1 }; - /// let result_struct = struct1 - struct2; - /// assert(result_struct.val == 2); - /// } - /// ``` -/// Subtract two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value to subtract from self. - /// - /// # Returns - /// - /// * [Self] - The result of the two values subtracted. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Subtract for MyStruct { - /// fn subtract(self, other: Self) -> Self { - /// let val = self.val - other.val; - /// Self { - /// val - /// } - - /// } - /// } - /// - - /// fn foo() { - /// let struct1 = MyStruct { val: 3 }; - /// let struct2 = MyStruct { val: 1 }; - - /// let result_struct = struct1 - struct2; - /// assert(result_struct.val == 2); - /// } - /// ``` - fn subtract(self, other: Self) -> Self; + /// Subtract two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value to subtract from self. + /// + /// # Returns + /// + /// * [Self] - The result of the two values subtracted. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Subtract for MyStruct { + /// fn subtract(self, other: Self) -> Self { + /// let val = self.val - other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 3 }; + /// let struct2 = MyStruct { val: 1 }; + /// let result_struct = struct1 - struct2; + /// assert(result_struct.val == 2); + /// } + /// ``` + fn subtract(self, other: Self) -> Self; } + impl Subtract for u256 { - fn - subtract(self, other: Self) -> Self { + fn subtract(self, other: Self) -> Self { __sub(self, other) } } + impl Subtract for u64 { fn subtract(self, other: Self) -> Self { __sub(self, other) } } + // unlike addition, underflowing subtraction does not need special treatment // because VM handles underflow -impl Subtract for u32 - { +impl Subtract for u32 { fn subtract(self, other: Self) -> Self { __sub(self, other) } } + impl Subtract for u16 { fn subtract(self, other: Self) -> Self { __sub(self, other) } } -impl Subtract - for u8 { + +impl Subtract for u8 { fn subtract(self, other: Self) -> Self { __sub(self, other) } } + /// Trait for the multiplication of two values. pub trait Multiply { - /// Multiply two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value to multiply with self. - /// - /// # Returns - /// - /// * [Self] - The result of the two values multiplied. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Multiply for MyStruct { - /// fn multiply(self, other: Self) -> Self { - /// let val = self.val * other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 3 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 * struct2; - /// assert(result_struct.val == 6); - /// -} - /// ``` -/// Multiply two values of the same type. - /// - - /// # Arguments - /// - /// * `other`: [Self] - The value to multiply with self. - /// - - /// # Returns - /// - /// * [Self] - The result of the two values multiplied. - - /// - /// # Examples - /// - / -// ```sway - /// struct MyStruct { - /// val: u64, - /// } - - /// - /// impl Multiply for MyStruct { - /// fn multiply(self, other: Self) -> Self { - /// let val = self.val * other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 3 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 * struct2; - /// assert(result_struct.val == 6); - /// } - /// ``` - fn multiply(self, other: Self) -> Self; + /// Multiply two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value to multiply with self. + /// + /// # Returns + /// + /// * [Self] - The result of the two values multiplied. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Multiply for MyStruct { + /// fn multiply(self, other: Self) -> Self { + /// let val = self.val * other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 3 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 * struct2; + /// assert(result_struct.val == 6); + /// } + /// ``` + fn multiply(self, other: Self) -> Self; } + impl Multiply for u256 { fn multiply(self, other: Self) -> Self { __mul(self, other) } } + impl Multiply for u64 { fn multiply(self, other: Self) -> Self { __mul(self, other) } } + // Emulate overflowing arithmetic for non-64-bit integer types impl Multiply for u32 { fn multiply(self, other: Self) -> Self { @@ -333,119 +225,79 @@ impl Multiply for u32 { } } } + impl Multiply for u16 { fn multiply(self, other: Self) -> Self { let res = __mul(self, other); - if - __gt(res, Self::max()) { + if __gt(res, Self::max()) { __revert(0) } else { res } } } -impl Multiply for u8 { +impl Multiply for u8 { fn multiply(self, other: Self) -> Self { let res = __mul(self, other); - if __gt( -res, Self::max()) { + if __gt(res, Self::max()) { __revert(0) } else { res } } } -/// Trait for the division of two values. +/// Trait for the division of two values. pub trait Divide { - /// Divide two values of the same type. - /// - /// # Arguments - - /// - /// * `other`: [Self] - The value to divide with self. - /// - / -// # Returns - /// - /// * [Self] - The result of the two values divided. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Divide for MyStruct { - /// fn divide(self, other: Self) -> Self { - /// let val = self.val / other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 / struct2; - /// assert(result_struct.val == 5); - /// } - /// ``` -/// Divide two values of the same type. - /// - /// # Arguments - - /// - /// * `other`: [Self] - The value to divide with self. - /// - - /// # Returns - /// - /// -* [Self] - The result of the two values divided. - /// - /// # Examples - / -// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// -} - /// - /// impl Divide for MyStruct { - /// fn divide(self, other: Self) -> Self { - /// let val = self.val / other.val; - - /// Self { - /// val - /// } - /// } - /// } - - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 / struct2; - /// assert(result_struct.val == 5); - /// } - /// ``` - fn divide(self, other: Self) -> Self; + /// Divide two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value to divide with self. + /// + /// # Returns + /// + /// * [Self] - The result of the two values divided. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Divide for MyStruct { + /// fn divide(self, other: Self) -> Self { + /// let val = self.val / other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 / struct2; + /// assert(result_struct.val == 5); + /// } + /// ``` + fn divide(self, other: Self) -> Self; } + impl Divide for u256 { fn divide(self, other: Self) -> Self { __div(self, other) } } + impl Divide for u64 { fn divide(self, other: Self) -> Self { __div(self, other) } } + // division for unsigned integers cannot overflow, // but if signed integers are ever introduced, // overflow needs to be handled, since @@ -455,285 +307,192 @@ impl Divide for u32 { __div(self, other) } } + impl Divide for u16 { fn divide(self, other: Self) -> Self { __div(self, other) } } + impl Divide for u8 { fn divide(self, other: Self) -> Self { __div(self, other) } } + /// Trait for the modulo of two values. pub trait Mod { - /// Modulo two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value to mod with self. - /// - /// # Returns - /// - /// * [Self] - The modulo of the two values. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Mod for MyStruct { - /// fn modulo(self, other: Self) -> Self { - /// let val = self.val % other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 % struct2; - /// assert(result_struct.val == 0); - /// } - /// ``` -/// Modulo two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value to mod with self. - /// - /// # Returns - /// - /// * [Self] - The modulo of the two values. - - /// - /// # Examples - /// - / -// ```sway - /// struct MyStruct { - /// val: u64, - /// } - - /// - /// impl Mod for MyStruct { - /// fn modulo(self, other: Self) -> Self { - /// let val = self.val % other.val; - - /// Self { - /// val - /// - } - /// } - /// } - /// - - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result_struct = struct1 % struct2; - - /// assert(result_struct.val == 0); - /// } - /// ``` - fn modulo(self, other: Self) -> Self; -} -impl Mod - for u256 { + /// Modulo two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value to mod with self. + /// + /// # Returns + /// + /// * [Self] - The modulo of the two values. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Mod for MyStruct { + /// fn modulo(self, other: Self) -> Self { + /// let val = self.val % other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result_struct = struct1 % struct2; + /// assert(result_struct.val == 0); + /// } + /// ``` + fn modulo(self, other: Self) -> Self; +} + +impl Mod for u256 { fn modulo(self, other: Self) -> Self { __mod(self, other) } } -impl Mod - for u64 { + +impl Mod for u64 { fn modulo(self, other: Self) -> Self { __mod(self, other) } } + impl Mod for u32 { fn modulo(self, other: Self) -> Self { __mod(self, other) } } + impl Mod for u16 { fn modulo(self, other: Self) -> Self { __mod(self, other) } } + impl Mod for u8 { fn modulo(self, other: Self) -> Self { __mod(self, other) } } + /// Trait to invert a type. pub trait Not { - /// Inverts the value of the type. - /// - /// # Returns - /// - /// * [Self] - The result of the inverse. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: bool, - /// } - /// - /// impl Not for MyStruct { - /// fn not(self) -> Self { - /// Self { - /// val: !self.val, - /// } - /// } - - /// } - /// - /// fn foo() { - /// let struct = MyStruct { val: true }; - /// let result_struct = !struct; - /// assert(!result_struct.val); - /// } - /// ``` -/// Inverts the value of the type. - /// - /// # Returns - /// - /// * [Self] - The result of the inverse. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: bool, - /// } - /// - /// impl Not for MyStruct { - /// fn not(self) -> Self { - /// Self { - /// val: !self.val, - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct = MyStruct { val: true }; - - /// let result_struct = !struct; - /// assert(!result_struct.val); - /// } - /// ``` - fn not(self) -> Self; + /// Inverts the value of the type. + /// + /// # Returns + /// + /// * [Self] - The result of the inverse. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: bool, + /// } + /// + /// impl Not for MyStruct { + /// fn not(self) -> Self { + /// Self { + /// val: !self.val, + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct = MyStruct { val: true }; + /// let result_struct = !struct; + /// assert(!result_struct.val); + /// } + /// ``` + fn not(self) -> Self; } -impl Not for bool { +impl Not for bool { fn not(self) -> Self { __eq(self, false) } } + impl Not for u256 { fn not(self) -> Self { __not(self) } } + + impl Not for u64 { - fn not( -self) -> Self { + fn not(self) -> Self { __not(self) } } + impl Not for u32 { fn not(self) -> Self { let v = __not(self); __and(v, u32::max()) } } -impl - Not for u16 { + +impl Not for u16 { fn not(self) -> Self { let v = __not(self); __and(v, u16::max()) } } + impl Not for u8 { fn not(self) -> Self { - let v = __not(self); __and(v, u8::max()) } } + /// Trait to evaluate if two types are equal. pub trait Eq { - /// Evaluates if two values of the same type are equal. - /// - - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [bool] - `true` if the values are equal, otherwise `false`. - - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Eq for MyStruct { - - /// fn eq(self, other: Self) -> bool { - /// self.val == other.val - /// } - /// } - /// - / -// fn foo() { - /// let struct1 = MyStruct { val: 2 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result = struct1 == struct2; - /// assert(result); - /// } - /// ``` -/// Evaluates if two values of the same type are equal. - /// - /// # Arguments - /// - - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [bool] - `true` if the values are equal, otherwise `false`. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Eq for MyStruct { - /// fn eq(self, other: Self) -> bool { - /// self.val == other.val - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 2 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result = struct1 == struct2; - /// assert(result); - /// } - /// ``` - fn eq(self, other: Self) -> bool; + /// Evaluates if two values of the same type are equal. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [bool] - `true` if the values are equal, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Eq for MyStruct { + /// fn eq(self, other: Self) -> bool { + /// self.val == other.val + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 2 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result = struct1 == struct2; + /// assert(result); + /// } + /// ``` + fn eq(self, other: Self) -> bool; } { /// Evaluates if two values of the same type are not equal. /// @@ -743,227 +502,157 @@ pub trait Eq { /// /// # Arguments /// - /// * `other`: [Self] - The value of the same type. /// /// # Returns - /// /// * [bool] - `true` if the two values are not equal, otherwise `false`. /// /// # Examples - /// /// ```sway /// struct MyStruct { - /// val: u64, /// } /// - / -// impl Eq for MyStruct { + /// impl Eq for MyStruct { /// fn eq(self, other: Self) -> bool { /// self.val == other.val /// } - /// } /// /// fn foo() { /// let struct1 = MyStruct { val: 10 }; /// let struct2 = MyStruct { val: 2 }; /// let result = struct1 != struct2; - /// assert(result); + /// assert(result); /// } /// ``` fn neq(self, other: Self) -> bool { (self.eq(other)).not() } } + impl Eq for bool { fn eq(self, other: Self) -> bool { __eq(self, other) } } + impl Eq for u256 { fn eq(self, other: Self) -> bool { __eq(self, other) } } + impl Eq for u64 { fn eq(self, other: Self) -> bool { __eq(self, other) } } + impl Eq for u32 { fn eq(self, other: Self) -> bool { __eq(self, other) } } + impl Eq for u16 { fn eq(self, other: Self) -> bool { __eq(self, other) } } + impl Eq for u8 { fn eq(self, other: Self) -> bool { __eq(self, other) } } + impl Eq for b256 { fn eq(self, other: Self) -> bool { // Both self and other are addresses of the values, so we can use MEQ. - asm( -r1: self, r2: other, r3, r4) { + asm(r1: self, r2: other, r3, r4) { addi r3 zero i32; - meq r4 r1 r2 r3; + meq r4 r1 r2 r3; r4: bool } } } -impl Eq for raw_ptr - { + +impl Eq for raw_ptr { fn eq(self, other: Self) -> bool { __eq(self, other) } } -/// -Trait to evaluate if one value is greater or less than another of the same type. + +/// Trait to evaluate if one value is greater or less than another of the same type. pub trait Ord { - /// Evaluates if one value of the same type is greater than another. - /// - /// # Arguments - - /// - /// * `other`: [Self] - The value of the same type. - /// - - /// # Returns - /// - /// * [bool] - `true` if `self` is greater than `other`, otherwise `false`. - / -// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Ord for MyStruct { - /// fn gt(self, other: Self) -> bool { - /// self.val > other.val - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result = struct1 > struct2; - /// assert(result); - /// } - /// ``` -/// Evaluates if one value of the same type is greater than another. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [bool] - `true` if `self` is greater than `other`, otherwise `false`. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// -} - /// - /// impl Ord for MyStruct { - /// fn gt(self, other: Self) -> bool { - - /// self.val > other.val - /// } - /// } - /// - - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - - /// let result = struct1 > struct2; - /// assert(result); - /// } - / -// ``` - fn gt(self, other: Self) -> bool; - /// Evaluates if one value of the same type is less than another. - /// - - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [bool] - `true` if `self` is less than `other`, otherwise `false`. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// -} - /// - /// impl Ord for MyStruct { - /// fn lt(self, other: Self) -> bool { - /// self.val < other.val - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result = struct1 < struct2; - /// assert(!result); - /// } - /// ``` - -/// Evaluates if one value of the same type is less than another. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [bool] - `true` if `self` is less than `other`, otherwise `false`. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - - /// } - /// - /// impl Ord for MyStruct { - /// fn lt(self, other: Self) -> bool { - /// self.val < other.val - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 2 }; - /// let result = struct1 < struct2; - /// assert(!result); - /// } - /// ``` - fn lt(self, other: Self) -> bool; + /// Evaluates if one value of the same type is greater than another. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [bool] - `true` if `self` is greater than `other`, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Ord for MyStruct { + /// fn gt(self, other: Self) -> bool { + /// self.val > other.val + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result = struct1 > struct2; + /// assert(result); + /// } + /// ``` + fn gt(self, other: Self) -> bool; + + /// Evaluates if one value of the same type is less than another. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [bool] - `true` if `self` is less than `other`, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Ord for MyStruct { + /// fn lt(self, other: Self) -> bool { + /// self.val < other.val + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 2 }; + /// let result = struct1 < struct2; + /// assert(!result); + /// } + /// ``` + fn lt(self, other: Self) -> bool; } + impl Ord for u256 { fn gt(self, other: Self) -> bool { __gt(self, other) @@ -972,6 +661,7 @@ impl Ord for u256 { __lt(self, other) } } + impl Ord for u64 { fn gt(self, other: Self) -> bool { __gt(self, other) @@ -980,6 +670,7 @@ impl Ord for u64 { __lt(self, other) } } + impl Ord for u32 { fn gt(self, other: Self) -> bool { __gt(self, other) @@ -988,6 +679,7 @@ impl Ord for u32 { __lt(self, other) } } + impl Ord for u16 { fn gt(self, other: Self) -> bool { __gt(self, other) @@ -996,6 +688,7 @@ impl Ord for u16 { __lt(self, other) } } + impl Ord for u8 { fn gt(self, other: Self) -> bool { __gt(self, other) @@ -1004,11 +697,12 @@ impl Ord for u8 { __lt(self, other) } } -impl Ord for b256 { +impl Ord for b256 { fn gt(self, other: Self) -> bool { let (self_word_1, self_word_2, self_word_3, self_word_4) = decompose(self); let (other_word_1, other_word_2, other_word_3, other_word_4) = decompose(other); + if self.eq(other) { false } else if self_word_1.neq(other_word_1) { @@ -1021,9 +715,11 @@ impl Ord for b256 { self_word_4.gt(other_word_4) } } + fn lt(self, other: Self) -> bool { let (self_word_1, self_word_2, self_word_3, self_word_4) = decompose(self); let (other_word_1, other_word_2, other_word_3, other_word_4) = decompose(other); + if self.eq(other) { false } else if self_word_1.neq(other_word_1) { @@ -1037,311 +733,211 @@ impl Ord for b256 { } } } + /// Trait to bitwise AND two values of the same type. pub trait BitwiseAnd { - /// Bitwise AND two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [Self] - The result of the bitwise AND of the two values. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - - /// val: u64, - /// } - /// - /// impl BitwiseAnd for MyStruct { - /// fn binary_and(self, other: Self) -> Self { - - /// let val = self.val & other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 11 }; - /// let result_struct = struct1 & struct2; - /// assert(result_struct.val == 10); - /// } - /// ``` -/// Bitwise AND two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [Self] - The result of the bitwise AND of the two values. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl BitwiseAnd for MyStruct { - /// fn binary_and(self, other: Self) -> Self { - /// let val = self.val & other.val; - /// Self { - /// val - - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 11 }; - /// let result_struct = struct1 & struct2; - /// assert(result_struct.val == 10); - /// } - /// ``` - fn binary_and(self, other: Self) -> Self; + /// Bitwise AND two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [Self] - The result of the bitwise AND of the two values. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl BitwiseAnd for MyStruct { + /// fn binary_and(self, other: Self) -> Self { + /// let val = self.val & other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 11 }; + /// let result_struct = struct1 & struct2; + /// assert(result_struct.val == 10); + /// } + /// ``` + fn binary_and(self, other: Self) -> Self; } + impl BitwiseAnd for u256 { fn binary_and(self, other: Self) -> Self { __and(self, other) } } + impl BitwiseAnd for u64 { fn binary_and(self, other: Self) -> Self { __and(self, other) } } + impl BitwiseAnd for u32 { fn binary_and(self, other: Self) -> Self { __and(self, other) } } + impl BitwiseAnd for u16 { fn binary_and(self, other: Self) -> Self { __and(self, other) } } + impl BitwiseAnd for u8 { fn binary_and(self, other: Self) -> Self { __and(self, other) } } + /// Trait to bitwise OR two values of the same type. pub trait BitwiseOr { - /// Bitwise OR two values of the same type. - /// - - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - - /// * [Self] - The result of the bitwise OR of the two values. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - - /// val: u64, - /// } - /// - /// impl BitwiseOr for MyStruct { - /// fn binary_or(self, other: Self) -> Self { - /// let val = self.val | other.val; - / -// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - - /// let struct2 = MyStruct { val: 11 }; - /// let result_struct = struct1 | struct2; - /// assert(result_struct.val == 11); - /// } - /// ``` -/// Bitwise OR two values of the same type. - - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [Self] - The result of the bitwise OR of the two values. - - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl BitwiseOr for MyStruct { - /// fn binary_or(self, other: Self) -> Self { - /// let val = self.val | other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 11 }; - /// let result_struct = struct1 | struct2; - /// assert(result_struct.val == 11); - /// } - /// ``` - fn binary_or(self, other: Self) -> Self; + /// Bitwise OR two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [Self] - The result of the bitwise OR of the two values. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl BitwiseOr for MyStruct { + /// fn binary_or(self, other: Self) -> Self { + /// let val = self.val | other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 11 }; + /// let result_struct = struct1 | struct2; + /// assert(result_struct.val == 11); + /// } + /// ``` + fn binary_or(self, other: Self) -> Self; } + impl BitwiseOr for u256 { fn binary_or(self, other: Self) -> Self { __or(self, other) } } + impl BitwiseOr for u64 { fn binary_or(self, other: Self) -> Self { __or(self, other) - } } + impl BitwiseOr for u32 { - fn binary_or(self -, other: Self) -> Self { + fn binary_or(self, other: Self) -> Self { __or(self, other) } } + impl BitwiseOr for u16 { fn binary_or(self, other: Self) -> Self { __or(self, other) } } + impl BitwiseOr for u8 { - fn binary_or(self, - other: Self) -> Self { + fn binary_or(self, other: Self) -> Self { __or(self, other) } } + /// Trait to bitwise XOR two values of the same type. pub trait BitwiseXor { - /// Bitwise XOR two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - /// # Returns - /// - /// * [Self] - The result of the bitwise XOR of the two values. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl BitwiseXOr for MyStruct { - /// fn binary_xor(self, other: Self) -> Self { - /// let val = self.val ^ other.val; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 11 }; - - /// let result_struct = struct1 ^ struct2; - /// assert(result_struct.val == 1); - - /// } - /// ``` -/// Bitwise XOR two values of the same type. - /// - /// # Arguments - /// - /// * `other`: [Self] - The value of the same type. - /// - / -// # Returns - /// - /// * [Self] - The result of the bitwise XOR of the two values. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - - /// } - /// - /// impl BitwiseXOr for MyStruct { - /// fn binary_xor(self, other: Self) -> Self { - - /// let val = self.val ^ other.val; - /// Self { - /// val - /// } - /// } - /// } - - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let struct2 = MyStruct { val: 11 }; - /// let result_struct = struct1 ^ struct2; - /// assert(result_struct.val == 1); - /// } - - /// ``` - fn binary_xor(self, other: Self) -> Self; + /// Bitwise XOR two values of the same type. + /// + /// # Arguments + /// + /// * `other`: [Self] - The value of the same type. + /// + /// # Returns + /// + /// * [Self] - The result of the bitwise XOR of the two values. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl BitwiseXOr for MyStruct { + /// fn binary_xor(self, other: Self) -> Self { + /// let val = self.val ^ other.val; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let struct2 = MyStruct { val: 11 }; + /// let result_struct = struct1 ^ struct2; + /// assert(result_struct.val == 1); + /// } + /// ``` + fn binary_xor(self, other: Self) -> Self; } + impl BitwiseXor for u256 { fn binary_xor(self, other: Self) -> Self { __xor(self, other) } } + impl BitwiseXor for u64 { fn binary_xor(self, other: Self) -> Self { __xor(self, other) } } + impl BitwiseXor for u32 { fn binary_xor(self, other: Self) -> Self { __xor(self, other) } } + impl BitwiseXor for u16 { fn binary_xor(self, other: Self) -> Self { __xor(self, other) } } + impl BitwiseXor for u8 { fn binary_xor(self, other: Self) -> Self { __xor(self, other) } } + impl BitwiseAnd for b256 { fn binary_and(val: self, other: Self) -> Self { let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val); @@ -1354,6 +950,7 @@ impl BitwiseAnd for b256 { rebuilt } } + impl BitwiseOr for b256 { fn binary_or(val: self, other: Self) -> Self { let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val); @@ -1366,6 +963,7 @@ impl BitwiseOr for b256 { rebuilt } } + impl BitwiseXor for b256 { fn binary_xor(val: self, other: Self) -> Self { let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val); @@ -1378,6 +976,7 @@ impl BitwiseXor for b256 { rebuilt } } + /// Trait to evaluate if one value is greater than or equal, or less than or equal to another of the same type. trait OrdEq: Ord + Eq { } { @@ -1420,12 +1019,14 @@ trait OrdEq: Ord + Eq { /// let struct1 = MyStruct { val: 10 }; /// let struct2 = MyStruct { val: 10 }; /// let result = struct1 >= struct2; - /// assert(result); + /// assert(result); /// } /// ``` fn ge(self, other: Self) -> bool { self.gt(other) || self.eq(other) - } /// Evaluates if one value of the same type is less or equal to than another. + } + + /// Evaluates if one value of the same type is less or equal to than another. /// /// # Additional Information /// @@ -1464,158 +1065,92 @@ trait OrdEq: Ord + Eq { /// let struct1 = MyStruct { val: 10 }; /// let struct2 = MyStruct { val: 10 }; /// let result = struct1 <= struct2; - /// assert(result); + /// assert(result); /// } /// ``` fn le(self, other: Self) -> bool { self.lt(other) || self.eq(other) } } -impl OrdEq for u256 { -} -impl OrdEq for u64 { -} -impl OrdEq for u32 { -} -impl OrdEq for u16 { -} -impl OrdEq for u8 { -} -impl OrdEq for b256 { -} + +impl OrdEq for u256 {} +impl OrdEq for u64 {} +impl OrdEq for u32 {} +impl OrdEq for u16 {} +impl OrdEq for u8 {} +impl OrdEq for b256 {} + /// Trait to bit shift a value. pub trait Shift { - /// Bit shift left by an amount. - /// - /// # Arguments - /// - /// * `other`: [u64] - The amount to bit shift by. - /// - /// # Returns - /// - /// * [Self] - The result of the value bit shifted to the left. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Shift for MyStruct { - /// fn lsh(self, other: u64) -> Self { - /// let val = self.val << other; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let result_struct = struct1 << 3; - /// assert(result_struct.val == 80); - /// } - /// ``` -/// Bit shift left by an amount. - /// - /// # Arguments - /// - /// * `other`: [u64] - The amount to bit shift by. - /// - /// # Returns - /// - /// * [Self] - The result of the value bit shifted to the left. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Shift for MyStruct { - /// fn lsh(self, other: u64) -> Self { - /// let val = self.val << other; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let result_struct = struct1 << 3; - /// assert(result_struct.val == 80); - /// } - /// ``` - fn lsh(self, other: u64) -> Self; - /// Bit shift right by an amount. - /// - /// # Arguments - /// - /// * `other`: [u64] - The amount to bit shift by. - /// - /// # Returns - /// - /// * [Self] - The result of the value bit shifted to the right. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Shift for MyStruct { - /// fn rsh(self, other: u64) -> Self { - /// let val = self.val >> other; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let result_struct = struct1 >> 1; - /// assert(result_struct.val == 5); - /// } - /// ``` -/// Bit shift right by an amount. - /// - /// # Arguments - /// - /// * `other`: [u64] - The amount to bit shift by. - /// - /// # Returns - /// - /// * [Self] - The result of the value bit shifted to the right. - /// - /// # Examples - /// - /// ```sway - /// struct MyStruct { - /// val: u64, - /// } - /// - /// impl Shift for MyStruct { - /// fn rsh(self, other: u64) -> Self { - /// let val = self.val >> other; - /// Self { - /// val - /// } - /// } - /// } - /// - /// fn foo() { - /// let struct1 = MyStruct { val: 10 }; - /// let result_struct = struct1 >> 1; - /// assert(result_struct.val == 5); - /// } - /// ``` - fn rsh(self, other: u64) -> Self; + /// Bit shift left by an amount. + /// + /// # Arguments + /// + /// * `other`: [u64] - The amount to bit shift by. + /// + /// # Returns + /// + /// * [Self] - The result of the value bit shifted to the left. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Shift for MyStruct { + /// fn lsh(self, other: u64) -> Self { + /// let val = self.val << other; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let result_struct = struct1 << 3; + /// assert(result_struct.val == 80); + /// } + /// ``` + fn lsh(self, other: u64) -> Self; + + /// Bit shift right by an amount. + /// + /// # Arguments + /// + /// * `other`: [u64] - The amount to bit shift by. + /// + /// # Returns + /// + /// * [Self] - The result of the value bit shifted to the right. + /// + /// # Examples + /// + /// ```sway + /// struct MyStruct { + /// val: u64, + /// } + /// + /// impl Shift for MyStruct { + /// fn rsh(self, other: u64) -> Self { + /// let val = self.val >> other; + /// Self { + /// val + /// } + /// } + /// } + /// + /// fn foo() { + /// let struct1 = MyStruct { val: 10 }; + /// let result_struct = struct1 >> 1; + /// assert(result_struct.val == 5); + /// } + /// ``` + fn rsh(self, other: u64) -> Self; } + impl Shift for u256 { fn lsh(self, other: u64) -> Self { __lsh(self, other) @@ -1624,6 +1159,7 @@ impl Shift for u256 { __rsh(self, other) } } + impl Shift for u64 { fn lsh(self, other: u64) -> Self { __lsh(self, other) @@ -1632,6 +1168,7 @@ impl Shift for u64 { __rsh(self, other) } } + impl Shift for u32 { fn lsh(self, other: u64) -> Self { // any non-64-bit value is compiled to a u64 value under-the-hood @@ -1642,6 +1179,7 @@ impl Shift for u32 { __rsh(self, other) } } + impl Shift for u16 { fn lsh(self, other: u64) -> Self { __and(__lsh(self, other), Self::max()) @@ -1650,6 +1188,7 @@ impl Shift for u16 { __rsh(self, other) } } + impl Shift for u8 { fn lsh(self, other: u64) -> Self { __and(__lsh(self, other), Self::max()) @@ -1658,6 +1197,7 @@ impl Shift for u8 { __rsh(self, other) } } + impl Shift for b256 { fn lsh(self, shift_amount: u64) -> Self { let (word_1, word_2, word_3, word_4) = decompose(self); @@ -1665,6 +1205,7 @@ impl Shift for b256 { let mut w2 = 0; let mut w3 = 0; let mut w4 = 0; + let w = shift_amount.divide(64); // num of whole words to shift in addition to b let b = shift_amount.modulo(64); // num of bits to shift within each word // TODO: Use generalized looping version when vec lands ! @@ -1687,14 +1228,17 @@ impl Shift for b256 { w1 = word_3.lsh(b).add(carry_4); w2 = shifted_4; } else if w.eq(3) { w1 = word_4.lsh(b); } else { (); }; + compose((w1, w2, w3, w4)) } + fn rsh(self, shift_amount: u64) -> Self { let (word_1, word_2, word_3, word_4) = decompose(self); let mut w1 = 0; let mut w2 = 0; let mut w3 = 0; let mut w4 = 0; + let w = shift_amount.divide(64); // num of whole words to shift in addition to b let b = shift_amount.modulo(64); // num of bits to shift within each word // TODO: Use generalized looping version when vec lands ! @@ -1717,9 +1261,11 @@ impl Shift for b256 { w4 = word_2.rsh(b).add(carry_1); w3 = shifted_1; } else if w.eq(3) { w4 = word_1.rsh(b); } else { (); }; + compose((w1, w2, w3, w4)) } } + ///////////////////////////////////////////////// // Internal Helpers ///////////////////////////////////////////////// @@ -1730,6 +1276,7 @@ fn lsh_with_carry(word: u64, shift_amount: u64) -> (u64, u64) { let shifted = word.lsh(shift_amount); (shifted, carry) } + /// Right shift a u64 and preserve the overflow amount if any fn rsh_with_carry(word: u64, shift_amount: u64) -> (u64, u64) { let left_shift_amount = 64.subtract(shift_amount); @@ -1737,14 +1284,17 @@ fn rsh_with_carry(word: u64, shift_amount: u64) -> (u64, u64) { let shifted = word.rsh(shift_amount); (shifted, carry) } + /// Build a single b256 value from a tuple of 4 u64 values. fn compose(words: (u64, u64, u64, u64)) -> b256 { asm(r1: words) { r1: b256 } } + /// Get a tuple of 4 u64 values from a single b256 value. fn decompose(val: b256) -> (u64, u64, u64, u64) { asm(r1: val) { r1: (u64, u64, u64, u64) } } + #[test] fn test_compose() { let expected: b256 = 0x0000000000000001_0000000000000002_0000000000000003_0000000000000004; @@ -1753,6 +1303,7 @@ fn test_compose() { __revert(0) } } + #[test] fn test_decompose() { let initial: b256 = 0x0000000000000001_0000000000000002_0000000000000003_0000000000000004; From 65bc629af5269ca3358ba1644f71bffb0e627198 Mon Sep 17 00:00:00 2001 From: Daniel Frederico Lins Leite Date: Mon, 28 Aug 2023 11:33:12 +0100 Subject: [PATCH 5/6] udeps dont need nightly anymore --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67150db0229..e40456dfdc0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -397,9 +397,6 @@ jobs: - uses: actions/checkout@v3 - name: Install toolchain uses: dtolnay/rust-toolchain@master - with: - # `cargo-udeps` requires nightly to run - toolchain: ${{ env.NIGHTLY_RUST_VERSION }} - uses: Swatinem/rust-cache@v2 - name: Install cargo-udeps run: cargo install --locked cargo-udeps From fd56e35e37590fa557f4e29283daaa6f59745af5 Mon Sep 17 00:00:00 2001 From: Daniel Frederico Lins Leite Date: Mon, 28 Aug 2023 13:08:20 +0100 Subject: [PATCH 6/6] rollback udeps rustc version change --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e40456dfdc0..67150db0229 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -397,6 +397,9 @@ jobs: - uses: actions/checkout@v3 - name: Install toolchain uses: dtolnay/rust-toolchain@master + with: + # `cargo-udeps` requires nightly to run + toolchain: ${{ env.NIGHTLY_RUST_VERSION }} - uses: Swatinem/rust-cache@v2 - name: Install cargo-udeps run: cargo install --locked cargo-udeps