Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 143 additions & 6 deletions soroban-sdk/src/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,7 @@ impl U256 {
pub const BITS: u32 = 256;

fn is_zero(&self) -> bool {
const ZERO: U256Val = U256Val::from_u32(0);
self.val.as_val().get_payload() == ZERO.as_val().get_payload()
*self == U256::from_u32(&self.env, 0)
}

pub fn from_u32(env: &Env, u: u32) -> Self {
Expand Down Expand Up @@ -440,13 +439,11 @@ impl I256 {
pub const BITS: u32 = 256;

fn is_zero(&self) -> bool {
const ZERO: I256Val = I256Val::from_i32(0);
self.val.as_val().get_payload() == ZERO.as_val().get_payload()
*self == I256::from_i32(&self.env, 0)
}

fn is_neg_one(&self) -> bool {
const NEG_ONE: I256Val = I256Val::from_i32(-1);
self.val.as_val().get_payload() == NEG_ONE.as_val().get_payload()
*self == I256::from_i32(&self.env, -1)
}

/// Returns the minimum value of I256 (-2^255).
Expand Down Expand Up @@ -850,6 +847,61 @@ mod test {
assert_eq!(u3.rem_euclid(&u4), U256::from_u32(&env, 3));
}

#[test]
fn test_u256_checked_arith() {
let env = Env::default();

let u1 = U256::from_u32(&env, 6);
let u2 = U256::from_u32(&env, 3);
assert_eq!(u1.checked_add(&u2), Some(U256::from_u32(&env, 9)));
assert_eq!(u1.checked_sub(&u2), Some(U256::from_u32(&env, 3)));
assert_eq!(u1.checked_mul(&u2), Some(U256::from_u32(&env, 18)));
assert_eq!(u1.checked_div(&u2), Some(U256::from_u32(&env, 2)));
assert_eq!(u1.checked_pow(2), Some(U256::from_u32(&env, 36)));
assert_eq!(u1.checked_shl(2), Some(U256::from_u32(&env, 24)));
assert_eq!(u1.checked_shr(1), Some(U256::from_u32(&env, 3)));

let u3 = U256::from_u32(&env, 7);
let u4 = U256::from_u32(&env, 4);
assert_eq!(u3.checked_rem_euclid(&u4), Some(U256::from_u32(&env, 3)));
}

#[test]
fn test_u256_checked_arith_overflow() {
let env = Env::default();

let zero = U256::from_u32(&env, 0);
let one = U256::from_u32(&env, 1);
let two = U256::from_u32(&env, 2);
let max = U256::from_parts(&env, u64::MAX, u64::MAX, u64::MAX, u64::MAX);
assert_eq!(max.checked_add(&one), None);
assert_eq!(zero.checked_sub(&one), None);
assert_eq!(max.checked_mul(&two), None);
assert_eq!(one.checked_div(&zero), None);
assert_eq!(max.checked_pow(2), None);
assert_eq!(one.checked_shl(256), None);
assert_eq!(one.checked_shr(256), None);
assert_eq!(one.checked_rem_euclid(&zero), None);

let zero_from_parts = U256::from_parts(&env, 0, 0, 0, 0);
let one_from_parts = U256::from_parts(&env, 0, 0, 0, 1);
assert_eq!(one.checked_div(&zero_from_parts), None);
assert_eq!(zero.checked_sub(&one_from_parts), None);
}

#[test]
fn test_u256_is_zero() {
let env = Env::default();

let zero = U256::from_u32(&env, 0);
let zero_from_parts = U256::from_parts(&env, 0, 0, 0, 0);
let non_zero = U256::from_u32(&env, 1);

assert!(zero.is_zero());
assert!(zero_from_parts.is_zero());
assert!(!non_zero.is_zero());
}

#[test]
fn test_i256_arith() {
let env = Env::default();
Expand All @@ -868,4 +920,89 @@ mod test {
let u4 = I256::from_i32(&env, 4);
assert_eq!(u3.rem_euclid(&u4), I256::from_i32(&env, 1));
}

#[test]
fn test_i256_checked_arith() {
let env = Env::default();

let i1 = I256::from_i32(&env, -6);
let i2 = I256::from_i32(&env, 3);
assert_eq!(i1.checked_add(&i2), Some(I256::from_i32(&env, -3)));
assert_eq!(i1.checked_sub(&i2), Some(I256::from_i32(&env, -9)));
assert_eq!(i1.checked_mul(&i2), Some(I256::from_i32(&env, -18)));
assert_eq!(i1.checked_div(&i2), Some(I256::from_i32(&env, -2)));
assert_eq!(i1.checked_pow(2), Some(I256::from_i32(&env, 36)));
assert_eq!(i1.checked_shl(2), Some(I256::from_i32(&env, -24)));
assert_eq!(i1.checked_shr(1), Some(I256::from_i32(&env, -3)));

let u3 = I256::from_i32(&env, -7);
let u4 = I256::from_i32(&env, 4);
assert_eq!(u3.checked_rem_euclid(&u4), Some(I256::from_i32(&env, 1)));
}

#[test]
fn test_i256_checked_arith_overflow() {
let env = Env::default();

let zero = I256::from_i32(&env, 0);
let one = I256::from_i32(&env, 1);
let negative_one = I256::from_i32(&env, -1);
let two = I256::from_i32(&env, 2);
let max = I256::from_parts(&env, i64::MAX, u64::MAX, u64::MAX, u64::MAX);
let min = I256::from_parts(&env, i64::MIN, 0, 0, 0);
assert_eq!(max.checked_add(&one), None);
assert_eq!(min.checked_sub(&one), None);
assert_eq!(max.checked_mul(&two), None);
assert_eq!(one.checked_div(&zero), None);
assert_eq!(min.checked_div(&negative_one), None);
assert_eq!(max.checked_pow(2), None);
assert_eq!(one.checked_shl(256), None);
assert_eq!(one.checked_shr(256), None);
assert_eq!(one.checked_rem_euclid(&zero), None);

let zero_from_parts = I256::from_parts(&env, 0, 0, 0, 0);
let one_from_parts = I256::from_parts(&env, 0, 0, 0, 1);
assert_eq!(one.checked_div(&zero_from_parts), None);
assert_eq!(min.checked_sub(&one_from_parts), None);
}

#[test]
fn test_i256_is_zero() {
let env = Env::default();

let zero = I256::from_i32(&env, 0);
let zero_from_parts = I256::from_parts(&env, 0, 0, 0, 0);
let non_zero = I256::from_i32(&env, 1);

assert!(zero.is_zero());
assert!(zero_from_parts.is_zero());
assert!(!non_zero.is_zero());
}

#[test]
fn test_i256_is_neg_one() {
let env = Env::default();

let negative_one = I256::from_i32(&env, -1);
let negative_one_from_parts = I256::from_parts(&env, -1, u64::MAX, u64::MAX, u64::MAX);
let negative_two = I256::from_i32(&env, -2);

assert!(negative_one.is_neg_one());
assert!(negative_one_from_parts.is_neg_one());
assert!(!negative_two.is_neg_one());
}

#[test]
fn test_i256_is_div_overflow() {
let env = Env::default();

let zero = I256::from_i32(&env, 0);
let negative_one = I256::from_i32(&env, -1);
let min = I256::min_value(&env);

assert!(!zero.is_div_overflow(&negative_one));

assert!(negative_one.is_div_overflow(&zero));
assert!(min.is_div_overflow(&negative_one));
}
}
Loading