Skip to content

Commit

Permalink
Implement From< U128 > for u256, b256 (#5887)
Browse files Browse the repository at this point in the history
## Description
Implements  From< U128 > for u256, b256

Partially addresses #5797 

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [ ] If my change requires substantial documentation changes, I have
[requested support from the DevRel
team](https://github.com/FuelLabs/devrel-requests/issues/new/choose)
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.
  • Loading branch information
SwayStar123 committed Apr 29, 2024
1 parent 08428b2 commit 850a2c4
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 20 deletions.
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
40 changes: 40 additions & 0 deletions 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 Down Expand Up @@ -103,6 +133,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

0 comments on commit 850a2c4

Please sign in to comment.