From cf0010b86fd6b7bad213d4361030e8e81812226e Mon Sep 17 00:00:00 2001 From: xunilrj Date: Tue, 22 Aug 2023 09:29:31 +0100 Subject: [PATCH] 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;