Skip to content

Commit

Permalink
feat: add num::traits::ops::OverflowingAdd trait (#4988)
Browse files Browse the repository at this point in the history
  • Loading branch information
enitrat authored Feb 19, 2024
1 parent f0caf04 commit 711d97b
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 0 deletions.
102 changes: 102 additions & 0 deletions corelib/src/integer.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2754,3 +2754,105 @@ impl I128One of core::num::traits::One<i128> {
!self.is_one()
}
}

// OverflowingAdd implementations
impl U8OverflowingAdd of core::num::traits::OverflowingAdd<u8> {
fn overflowing_add(self: u8, v: u8) -> (u8, bool) {
match u8_overflowing_add(self, v) {
Result::Ok(x) => (x, false),
Result::Err(x) => (x, true)
}
}
}

impl U16OverflowingAdd of core::num::traits::OverflowingAdd<u16> {
fn overflowing_add(self: u16, v: u16) -> (u16, bool) {
match u16_overflowing_add(self, v) {
Result::Ok(x) => (x, false),
Result::Err(x) => (x, true)
}
}
}

impl U32OverflowingAdd of core::num::traits::OverflowingAdd<u32> {
fn overflowing_add(self: u32, v: u32) -> (u32, bool) {
match u32_overflowing_add(self, v) {
Result::Ok(x) => (x, false),
Result::Err(x) => (x, true)
}
}
}

impl U64OverflowingAdd of core::num::traits::OverflowingAdd<u64> {
fn overflowing_add(self: u64, v: u64) -> (u64, bool) {
match u64_overflowing_add(self, v) {
Result::Ok(x) => (x, false),
Result::Err(x) => (x, true)
}
}
}

impl U128OverflowingAdd of core::num::traits::OverflowingAdd<u128> {
fn overflowing_add(self: u128, v: u128) -> (u128, bool) {
match u128_overflowing_add(self, v) {
Result::Ok(x) => (x, false),
Result::Err(x) => (x, true)
}
}
}

impl U256OverflowingAdd of core::num::traits::OverflowingAdd<u256> {
fn overflowing_add(self: u256, v: u256) -> (u256, bool) {
u256_overflowing_add(self, v)
}
}

impl I8OverflowingAdd of core::num::traits::OverflowingAdd<i8> {
fn overflowing_add(self: i8, v: i8) -> (i8, bool) {
match i8_overflowing_add_impl(self, v) {
SignedIntegerResult::InRange(x) => (x, false),
SignedIntegerResult::Underflow(x) => (x, true),
SignedIntegerResult::Overflow(x) => (x, true),
}
}
}

impl I16OverflowingAdd of core::num::traits::OverflowingAdd<i16> {
fn overflowing_add(self: i16, v: i16) -> (i16, bool) {
match i16_overflowing_add_impl(self, v) {
SignedIntegerResult::InRange(x) => (x, false),
SignedIntegerResult::Underflow(x) => (x, true),
SignedIntegerResult::Overflow(x) => (x, true),
}
}
}

impl I32OverflowingAdd of core::num::traits::OverflowingAdd<i32> {
fn overflowing_add(self: i32, v: i32) -> (i32, bool) {
match i32_overflowing_add_impl(self, v) {
SignedIntegerResult::InRange(x) => (x, false),
SignedIntegerResult::Underflow(x) => (x, true),
SignedIntegerResult::Overflow(x) => (x, true),
}
}
}

impl I64OverflowingAdd of core::num::traits::OverflowingAdd<i64> {
fn overflowing_add(self: i64, v: i64) -> (i64, bool) {
match i64_overflowing_add_impl(self, v) {
SignedIntegerResult::InRange(x) => (x, false),
SignedIntegerResult::Underflow(x) => (x, true),
SignedIntegerResult::Overflow(x) => (x, true),
}
}
}

impl I128OverflowingAdd of core::num::traits::OverflowingAdd<i128> {
fn overflowing_add(self: i128, v: i128) -> (i128, bool) {
match i128_overflowing_add_impl(self, v) {
SignedIntegerResult::InRange(x) => (x, false),
SignedIntegerResult::Underflow(x) => (x, true),
SignedIntegerResult::Overflow(x) => (x, true),
}
}
}
3 changes: 3 additions & 0 deletions corelib/src/num/traits.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ pub use one::One;

pub mod bit_size;
pub use bit_size::BitSize;

pub mod ops;
pub use ops::{OverflowingAdd};
2 changes: 2 additions & 0 deletions corelib/src/num/traits/ops.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod overflowing;
pub use overflowing::{OverflowingAdd};
7 changes: 7 additions & 0 deletions corelib/src/num/traits/ops/overflowing.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// Performs addition with a flag for overflow.
pub trait OverflowingAdd<T> {
/// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow
/// would occur.
/// If an overflow would have occurred then the wrapped value is returned.
fn overflowing_add(self: T, v: T) -> (T, bool);
}
51 changes: 51 additions & 0 deletions corelib/src/test/num_test.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use core::num::traits::BitSize;
use core::num::traits::OverflowingAdd;
use core::integer::BoundedInt;


#[test]
fn test_bit_size() {
Expand All @@ -15,3 +18,51 @@ fn test_bit_size() {
assert!(BitSize::<i128>::bits() == 128);
assert!(BitSize::<bytes31>::bits() == 248);
}

#[test]
fn tests_overflowing_add_unsigned_integers() {
assert_eq!(1_u8.overflowing_add(2), (3, false));
assert_eq!(BoundedInt::<u8>::max().overflowing_add(1), (0, true));
assert_eq!(1_u16.overflowing_add(2), (3, false));
assert_eq!(BoundedInt::<u16>::max().overflowing_add(1), (0, true));
assert_eq!(1_u32.overflowing_add(2), (3, false));
assert_eq!(BoundedInt::<u32>::max().overflowing_add(1), (0, true));
assert_eq!(1_u64.overflowing_add(2), (3, false));
assert_eq!(BoundedInt::<u64>::max().overflowing_add(1), (0, true));
assert_eq!(1_u128.overflowing_add(2), (3, false));
assert_eq!(BoundedInt::<u128>::max().overflowing_add(1), (0, true));
assert_eq!(1_u256.overflowing_add(2), (3, false));
assert_eq!(BoundedInt::<u256>::max().overflowing_add(1), (0, true));
}

#[test]
fn test_overflowing_add_positive_signed_integers() {
assert!(1_i8.overflowing_add(2) == (3, false));
assert!(BoundedInt::<i8>::max().overflowing_add(1) == (-0x80, true));
assert!(1_i16.overflowing_add(2) == (3, false));
assert!(BoundedInt::<i16>::max().overflowing_add(1) == (-0x8000, true));
assert!(1_i32.overflowing_add(2) == (3, false));
assert!(BoundedInt::<i32>::max().overflowing_add(1) == (-0x80000000, true));
assert!(1_i64.overflowing_add(2) == (3, false));
assert!(BoundedInt::<i64>::max().overflowing_add(1) == (-0x8000000000000000, true));
assert!(1_i128.overflowing_add(2) == (3, false));
assert!(
BoundedInt::<i128>::max().overflowing_add(1) == (-0x80000000000000000000000000000000, true)
);
}

#[test]
fn test_overflowing_add_negative_signed_integers() {
assert!((-1_i8).overflowing_add(-2) == (-3, false));
assert!(BoundedInt::<i8>::min().overflowing_add(-1) == (0x7f, true));
assert!((-1_i16).overflowing_add(-2) == (-3, false));
assert!(BoundedInt::<i16>::min().overflowing_add(-1) == (0x7fff, true));
assert!((-1_i32).overflowing_add(-2) == (-3, false));
assert!(BoundedInt::<i32>::min().overflowing_add(-1) == (0x7fffffff, true));
assert!((-1_i64).overflowing_add(-2) == (-3, false));
assert!(BoundedInt::<i64>::min().overflowing_add(-1) == (0x7fffffffffffffff, true));
assert!((-1_i128).overflowing_add(-2) == (-3, false));
assert!(
BoundedInt::<i128>::min().overflowing_add(-1) == (0x7fffffffffffffffffffffffffffffff, true)
);
}

0 comments on commit 711d97b

Please sign in to comment.