Skip to content

Commit fe9bbe3

Browse files
authored
Add wrapping operations to standard library (#7329)
## Description Add implementation for `wrapping_add()`, `wrapping_sub()` and `wrapping_mul()` to standard operations. ## Checklist - [ ] I have linked to any relevant issues. - [ ] I have commented my code, particularly in hard-to-understand areas. - [ ] 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) - [ ] I have added tests that prove my fix is effective or that my feature works. - [ ] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [ ] 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). - [ ] I have requested a review from the relevant team or maintainers.
1 parent 6bdfa0c commit fe9bbe3

File tree

2 files changed

+133
-1
lines changed
  • sway-lib-std/src
  • test/src/in_language_tests/test_programs/ops_inline_tests/src

2 files changed

+133
-1
lines changed

sway-lib-std/src/ops.sw

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ library;
22

33
use ::primitives::*;
44
use ::registers::flags;
5-
use ::flags::panic_on_overflow_enabled;
5+
use ::flags::{disable_panic_on_overflow, panic_on_overflow_enabled, set_flags};
66

77
const MAX_U32_U64: u64 = __transmute::<u32, u64>(u32::max());
88
const MAX_U16_U64: u64 = __transmute::<u16, u64>(u16::max());
@@ -1570,6 +1570,28 @@ impl PartialEq for str {
15701570
impl Eq for str {}
15711571

15721572
impl u8 {
1573+
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of the type.
1574+
pub fn wrapping_add(self, other: Self) -> Self {
1575+
let f = disable_panic_on_overflow();
1576+
let res = self + other;
1577+
set_flags(f);
1578+
res
1579+
}
1580+
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of the type.
1581+
pub fn wrapping_sub(self, other: Self) -> Self {
1582+
let f = disable_panic_on_overflow();
1583+
let res = self - other;
1584+
set_flags(f);
1585+
res
1586+
}
1587+
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary of the type.
1588+
pub fn wrapping_mul(self, other: Self) -> Self {
1589+
let f = disable_panic_on_overflow();
1590+
let res = self * other;
1591+
set_flags(f);
1592+
res
1593+
}
1594+
15731595
/// Returns whether a `u8` is set to zero.
15741596
///
15751597
/// # Returns
@@ -1590,6 +1612,28 @@ impl u8 {
15901612
}
15911613

15921614
impl u16 {
1615+
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of the type.
1616+
pub fn wrapping_add(self, other: Self) -> Self {
1617+
let f = disable_panic_on_overflow();
1618+
let res = self + other;
1619+
set_flags(f);
1620+
res
1621+
}
1622+
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of the type.
1623+
pub fn wrapping_sub(self, other: Self) -> Self {
1624+
let f = disable_panic_on_overflow();
1625+
let res = self - other;
1626+
set_flags(f);
1627+
res
1628+
}
1629+
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary of the type.
1630+
pub fn wrapping_mul(self, other: Self) -> Self {
1631+
let f = disable_panic_on_overflow();
1632+
let res = self * other;
1633+
set_flags(f);
1634+
res
1635+
}
1636+
15931637
/// Returns whether a `u16` is set to zero.
15941638
///
15951639
/// # Returns
@@ -1610,6 +1654,28 @@ impl u16 {
16101654
}
16111655

16121656
impl u32 {
1657+
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of the type.
1658+
pub fn wrapping_add(self, other: Self) -> Self {
1659+
let f = disable_panic_on_overflow();
1660+
let res = self + other;
1661+
set_flags(f);
1662+
res
1663+
}
1664+
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of the type.
1665+
pub fn wrapping_sub(self, other: Self) -> Self {
1666+
let f = disable_panic_on_overflow();
1667+
let res = self - other;
1668+
set_flags(f);
1669+
res
1670+
}
1671+
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary of the type.
1672+
pub fn wrapping_mul(self, other: Self) -> Self {
1673+
let f = disable_panic_on_overflow();
1674+
let res = self * other;
1675+
set_flags(f);
1676+
res
1677+
}
1678+
16131679
/// Returns whether a `u32` is set to zero.
16141680
///
16151681
/// # Returns
@@ -1630,6 +1696,28 @@ impl u32 {
16301696
}
16311697

16321698
impl u64 {
1699+
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of the type.
1700+
pub fn wrapping_add(self, other: Self) -> Self {
1701+
let f = disable_panic_on_overflow();
1702+
let res = self + other;
1703+
set_flags(f);
1704+
res
1705+
}
1706+
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of the type.
1707+
pub fn wrapping_sub(self, other: Self) -> Self {
1708+
let f = disable_panic_on_overflow();
1709+
let res = self - other;
1710+
set_flags(f);
1711+
res
1712+
}
1713+
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary of the type.
1714+
pub fn wrapping_mul(self, other: Self) -> Self {
1715+
let f = disable_panic_on_overflow();
1716+
let res = self * other;
1717+
set_flags(f);
1718+
res
1719+
}
1720+
16331721
/// Returns whether a `u64` is set to zero.
16341722
///
16351723
/// # Returns
@@ -1650,6 +1738,28 @@ impl u64 {
16501738
}
16511739

16521740
impl u256 {
1741+
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of the type.
1742+
pub fn wrapping_add(self, other: Self) -> Self {
1743+
let f = disable_panic_on_overflow();
1744+
let res = self + other;
1745+
set_flags(f);
1746+
res
1747+
}
1748+
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of the type.
1749+
pub fn wrapping_sub(self, other: Self) -> Self {
1750+
let f = disable_panic_on_overflow();
1751+
let res = self - other;
1752+
set_flags(f);
1753+
res
1754+
}
1755+
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary of the type.
1756+
pub fn wrapping_mul(self, other: Self) -> Self {
1757+
let f = disable_panic_on_overflow();
1758+
let res = self * other;
1759+
set_flags(f);
1760+
res
1761+
}
1762+
16531763
/// Returns whether a `u256` is set to zero.
16541764
///
16551765
/// # Returns

test/src/in_language_tests/test_programs/ops_inline_tests/src/main.sw

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,25 @@ pub fn str_eq_test() {
99
assert("" != "a");
1010
assert("a" != "b");
1111
}
12+
13+
#[test]
14+
pub fn wrapping_tests() {
15+
assert_eq(0u8.wrapping_sub(1u8), u8::max());
16+
assert_eq(0u16.wrapping_sub(1u16), u16::max());
17+
assert_eq(0u32.wrapping_sub(1u32), u32::max());
18+
assert_eq(0u64.wrapping_sub(1u64), u64::max());
19+
assert_eq(u256::zero().wrapping_sub(u256::from(1u64)), u256::max());
20+
21+
assert_eq(u8::max().wrapping_add(1u8), 0);
22+
assert_eq(u16::max().wrapping_add(1u16), 0);
23+
assert_eq(u32::max().wrapping_add(1u32), 0);
24+
assert_eq(u64::max().wrapping_add(1u64), 0);
25+
assert_eq(u256::max().wrapping_add(u256::from(1u64)), u256::zero());
26+
27+
assert_eq(16u8.wrapping_mul(16u8), 0);
28+
assert_eq(256u16.wrapping_mul(256u16), 0);
29+
assert_eq(65_536u32.wrapping_mul(65_536u32), 0);
30+
assert_eq(4_294_967_296u64.wrapping_mul(4_294_967_296u64), 0);
31+
assert_eq(u256::from(0x0000000000000000000000000000000100000000000000000000000000000000).wrapping_mul(u256::from(0x0000000000000000000000000000000100000000000000000000000000000000)), 0);
32+
33+
}

0 commit comments

Comments
 (0)