Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement From< U128 > for u256, b256 #5887

Merged
merged 16 commits into from
Apr 29, 2024
Merged
2 changes: 1 addition & 1 deletion sway-lib-std/src/lib.sw
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
41 changes: 40 additions & 1 deletion sway-lib-std/src/primitive_conversions/b256.sw
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ library;
use ::bytes::Bytes;
use ::convert::{From, TryFrom};
use ::option::Option::{self, *};
use ::u128::U128;

impl TryFrom<Bytes> for b256 {
fn try_from(b: Bytes) -> Option<Self> {
Expand Down Expand Up @@ -37,6 +38,35 @@ impl From<u256> for b256 {
}
}

impl From<U128> 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`.
///
Expand All @@ -51,7 +81,6 @@ impl From<(u64, u64, u64, u64)> for b256 {
/// # Examples
///
/// ```sway
///
/// fn foo() {
/// let b256_value = b256::from((1, 2, 3, 4));
/// }
Expand Down Expand Up @@ -103,6 +132,16 @@ fn test_b256_from_u256() {
assert(res == 0x0000000000000000000000000000000000000000000000000000000000000000);
}

#[test]
fn test_b256_from_u128() {
use ::assert::assert;

let b256_value = <b256 as From<U128>>::from(U128::from((18446744073709551615_u64, 18446744073709551615_u64)));
assert(
b256_value == 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff,
);
}

#[test]
fn test_b256_from_tuple() {
use ::assert::assert;
Expand Down
40 changes: 40 additions & 0 deletions sway-lib-std/src/primitive_conversions/u256.sw
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
library;

use ::convert::From;
use ::u128::U128;

/// Functions for casting between `u256` and other types.
impl From<u8> for u256 {
Expand Down Expand Up @@ -124,6 +125,35 @@ impl From<b256> for u256 {
}
}

impl From<U128> 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`.
///
Expand Down Expand Up @@ -206,6 +236,16 @@ fn test_u256_from_b256() {
);
}

#[test]
fn test_u256_from_u128() {
use ::assert::assert;

let u256_value = <u256 as From<U128>>::from(U128::from((18446744073709551615_u64, 18446744073709551615_u64)));
assert(
u256_value == 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff_u256,
);
}

#[test]
fn test_u256_from_tuple() {
use ::assert::assert;
Expand Down
7 changes: 3 additions & 4 deletions sway-lib-std/src/u128.sw
Original file line number Diff line number Diff line change
Expand Up @@ -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, *};
Expand Down Expand Up @@ -39,7 +38,7 @@ impl From<u8> for U128 {
fn from(val: u8) -> Self {
Self {
upper: 0,
lower: val.into(),
lower: val.as_u64(),
}
}
}
Expand All @@ -63,7 +62,7 @@ impl From<u16> for U128 {
fn from(val: u16) -> Self {
Self {
upper: 0,
lower: val.into(),
lower: val.as_u64(),
}
}
}
Expand All @@ -87,7 +86,7 @@ impl From<u32> for U128 {
fn from(val: u32) -> Self {
Self {
upper: 0,
lower: val.into(),
lower: val.as_u64(),
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ use ::revert::{require, revert};
// Convert
use ::convert::From;

/// U128
use ::u128::*;

// Primitive conversions
use ::primitive_conversions::*;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand All @@ -24,33 +24,33 @@ 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,
}
}
}

/// 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;

Expand All @@ -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;

Expand All @@ -84,7 +84,7 @@ impl U128 {
// If upper component has underflowed, panic
// assert(upper < self.upper);

U128 {
U128Duplicate {
upper: upper,
lower: lower,
}
Expand All @@ -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();
Expand Down Expand Up @@ -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,
}
Expand Down
Loading