diff --git a/sway-lib-std/src/lib.sw b/sway-lib-std/src/lib.sw index 76aad2cd846..249ffc21ce5 100644 --- a/sway-lib-std/src/lib.sw +++ b/sway-lib-std/src/lib.sw @@ -13,10 +13,10 @@ pub mod registers; pub mod iterator; pub mod vec; pub mod bytes; -pub mod primitive_conversions; pub mod math; pub mod flags; pub mod u128; +pub mod primitive_conversions; pub mod alias; pub mod hash; pub mod asset_id; diff --git a/sway-lib-std/src/primitive_conversions/b256.sw b/sway-lib-std/src/primitive_conversions/b256.sw index 52d3157c500..9e267da1adc 100644 --- a/sway-lib-std/src/primitive_conversions/b256.sw +++ b/sway-lib-std/src/primitive_conversions/b256.sw @@ -3,6 +3,7 @@ library; use ::bytes::Bytes; use ::convert::{From, TryFrom}; use ::option::Option::{self, *}; +use ::u128::U128; impl TryFrom for b256 { fn try_from(b: Bytes) -> Option { @@ -37,6 +38,35 @@ impl From for b256 { } } +impl From for b256 { + /// Converts a `U128` to a `b256`. + /// + /// # Arguments + /// + /// * `num`: [U128] - The `U128` to be converted. + /// + /// # Returns + /// + /// * [b256] - The `b256` representation of the `U128` value. + /// + /// # Examples + /// + /// ```sway + /// use std::u128::U128; + /// + /// fn foo() { + /// let u128_value = U128::from((18446744073709551615_u64, 18446744073709551615_u64)); + /// let b256_value = b256::from(u128_value); + /// } + /// ``` + fn from(num: U128) -> Self { + let input = (0u64, 0u64, num.upper(), num.lower()); + asm(input: input) { + input: b256 + } + } +} + impl From<(u64, u64, u64, u64)> for b256 { /// Casts a tuple of 4 `u64` values to a `b256`. /// @@ -103,6 +133,16 @@ fn test_b256_from_u256() { assert(res == 0x0000000000000000000000000000000000000000000000000000000000000000); } +#[test] +fn test_b256_from_u128() { + use ::assert::assert; + + let b256_value = >::from(U128::from((18446744073709551615_u64, 18446744073709551615_u64))); + assert( + b256_value == 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff, + ); +} + #[test] fn test_b256_from_tuple() { use ::assert::assert; diff --git a/sway-lib-std/src/primitive_conversions/u256.sw b/sway-lib-std/src/primitive_conversions/u256.sw index 8e840404cd5..3acfcf97539 100644 --- a/sway-lib-std/src/primitive_conversions/u256.sw +++ b/sway-lib-std/src/primitive_conversions/u256.sw @@ -1,6 +1,7 @@ library; use ::convert::From; +use ::u128::U128; /// Functions for casting between `u256` and other types. impl From for u256 { @@ -124,6 +125,35 @@ impl From for u256 { } } +impl From for u256 { + /// Converts a `U128` to a `u256`. + /// + /// # Arguments + /// + /// * `num`: [U128] - The `U128` to be converted. + /// + /// # Returns + /// + /// * [u256] - The `u256` representation of the `U128` value. + /// + /// # Examples + /// + /// ```sway + /// use std::u128::U128; + /// + /// fn foo() { + /// let u128_value = U128::from((18446744073709551615_u64, 18446744073709551615_u64)); + /// let u256_value = u256::from(u128_value); + /// } + /// ``` + fn from(num: U128) -> Self { + let input = (0u64, 0u64, num.upper(), num.lower()); + asm(input: input) { + input: u256 + } + } +} + impl From<(u64, u64, u64, u64)> for u256 { /// Casts a tuple of 4 `u64` values to a `u256`. /// @@ -206,6 +236,16 @@ fn test_u256_from_b256() { ); } +#[test] +fn test_u256_from_u128() { + use ::assert::assert; + + let u256_value = >::from(U128::from((18446744073709551615_u64, 18446744073709551615_u64))); + assert( + u256_value == 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff_u256, + ); +} + #[test] fn test_u256_from_tuple() { use ::assert::assert; diff --git a/sway-lib-std/src/u128.sw b/sway-lib-std/src/u128.sw index d5c1cca2fc3..9c0f0aa28ac 100644 --- a/sway-lib-std/src/u128.sw +++ b/sway-lib-std/src/u128.sw @@ -3,7 +3,6 @@ library; use ::assert::assert; use ::convert::{From, Into}; -use ::primitive_conversions::u64::*; use ::flags::{disable_panic_on_overflow, set_flags}; use ::math::*; use ::result::Result::{self, *}; @@ -39,7 +38,7 @@ impl From for U128 { fn from(val: u8) -> Self { Self { upper: 0, - lower: val.into(), + lower: val.as_u64(), } } } @@ -63,7 +62,7 @@ impl From for U128 { fn from(val: u16) -> Self { Self { upper: 0, - lower: val.into(), + lower: val.as_u64(), } } } @@ -87,7 +86,7 @@ impl From for U128 { fn from(val: u32) -> Self { Self { upper: 0, - lower: val.into(), + lower: val.as_u64(), } } } diff --git a/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/reduced_lib.config b/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/reduced_lib.config index 87e01ae7cd0..eee66bc33f4 100644 --- a/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/reduced_lib.config +++ b/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/reduced_lib.config @@ -12,6 +12,10 @@ intrinsics.sw constants.sw bytes.sw clone.sw +registers.sw +flags.sw +math.sw +u128.sw bytes_conversions.sw bytes_conversions/b256.sw bytes_conversions/u16.sw diff --git a/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/src/lib.sw b/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/src/lib.sw index 4f8c777cad2..0cce699db10 100644 --- a/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/src/lib.sw +++ b/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/src/lib.sw @@ -12,6 +12,10 @@ pub mod alloc; pub mod iterator; pub mod vec; pub mod bytes; +pub mod registers; +pub mod flags; +pub mod math; +pub mod u128; pub mod primitive_conversions; pub mod array_conversions; pub mod bytes_conversions; diff --git a/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/src/prelude.sw b/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/src/prelude.sw index 910663a6e90..7cbdb460de4 100644 --- a/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/src/prelude.sw +++ b/test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-conversions/src/prelude.sw @@ -15,6 +15,9 @@ use ::revert::{require, revert}; // Convert use ::convert::From; +/// U128 +use ::u128::*; + // Primitive conversions use ::primitive_conversions::*; diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/src/main.sw index ea39bf95f0f..a76cb9e624a 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/issue_1512_repro/src/main.sw @@ -8,13 +8,13 @@ abi U128Contract { impl U128Contract for Contract { fn multiply_u64(a: u64, b: u64) -> (u64, u64) { - let result_u128: U128 = mul64(a, b); + let result_u128: U128Duplicate = mul64(a, b); (result_u128.upper, result_u128.lower) } } // U128 represented as two components of a base-(2**64) number : (upper, lower) , where value = (2**64)^upper + lower -pub struct U128 { +pub struct U128Duplicate { upper: u64, lower: u64, } @@ -24,16 +24,16 @@ pub trait AltFrom { } { } -impl core::ops::Eq for U128 { +impl core::ops::Eq for U128Duplicate { fn eq(self, other: Self) -> bool { self.lower == other.lower && self.upper == other.upper } } /// Function for creating U128 from its u64 components -impl AltFrom for U128 { - fn from(h: u64, l: u64) -> U128 { - U128 { +impl AltFrom for U128Duplicate { + fn from(h: u64, l: u64) -> U128Duplicate { + U128Duplicate { upper: h, lower: l, } @@ -41,16 +41,16 @@ impl AltFrom for U128 { } /// Methods on the U128 type -impl U128 { +impl U128Duplicate { /// Initializes a new, zeroed U128. - fn new() -> U128 { - U128 { + fn new() -> U128Duplicate { + U128Duplicate { upper: 0, lower: 0, } } - fn add(self, other: U128) -> U128 { + fn add(self, other: U128Duplicate) -> U128Duplicate { let lower = self.lower + other.lower; let mut upper = self.upper + other.upper; @@ -62,13 +62,13 @@ impl U128 { // If overflow has occurred in the upper component addition, panic // assert(upper >= self.upper); - U128 { + U128Duplicate { upper: upper, lower: lower, } } - fn sub(self, other: U128) -> U128 { + fn sub(self, other: U128Duplicate) -> U128Duplicate { let mut upper = self.upper - other.upper; let mut lower = 0; @@ -84,7 +84,7 @@ impl U128 { // If upper component has underflowed, panic // assert(upper < self.upper); - U128 { + U128Duplicate { upper: upper, lower: lower, } @@ -94,7 +94,7 @@ impl U128 { } // Multiply two u64 values, producing a U128 -pub fn mul64(a: u64, b: u64) -> U128 { +pub fn mul64(a: u64, b: u64) -> U128Duplicate { // Split a and b into 32-bit lo and hi components let a_lo = (a & 0x00000000ffffffff).try_as_u32().unwrap(); let a_hi = (a >> 32).try_as_u32().unwrap(); @@ -122,7 +122,7 @@ pub fn mul64(a: u64, b: u64) -> U128 { // High result let result_hi: u64 = ab_hi + (ab_mid >> 32) + (ba_mid >> 32) + carry_bit; - U128 { + U128Duplicate { upper: result_hi, lower: result_lo, }