#![feature(bigint_helper_methods)]
macro_rules! test_operator {
($operator:expr, $expected:expr) => {
let res = $operator;
assert_eq!(res, $expected, "{} -> {:?}, expected {:?}", stringify!($operator), res, $expected);
}
}
#[test]
fn std_overflowing() {
test_operator!(255u8.overflowing_add(1), (0, true));
test_operator!(127u8.overflowing_add(1), (128, false));
test_operator!((255u8 as i8).overflowing_add(1), (0, false));
test_operator!(127i8.overflowing_add(1), (-128, true));
test_operator!(0u8.overflowing_add(255), (255, false));
test_operator!(128u8.overflowing_add(255), (127, true));
test_operator!(0i8.overflowing_add(-1), (-1, false));
test_operator!((-128i8).overflowing_add(-1), (127, true));
test_operator!(0u8.overflowing_sub(1), (255, true));
test_operator!(128u8.overflowing_sub(1), (127, false));
test_operator!(0i8.overflowing_sub(1), (-1, false));
test_operator!((-128i8).overflowing_sub(1), (127, true));
test_operator!(255u8.overflowing_sub(255), (0, false));
test_operator!(127u8.overflowing_sub(255), (128, true));
test_operator!((255u8 as i8).overflowing_sub(-1), (0, false));
test_operator!(127i8.overflowing_sub(-1), (-128, true));
}
#[test]
fn std_big_int() {
test_operator!(255u8.carrying_add(1, false), (0, true));
test_operator!(255u8.carrying_add(0, true), (0, true));
test_operator!(255u8.carrying_add(1, true), (1, true));
test_operator!(0u8.carrying_add(255, false), (255, false));
test_operator!(0u8.carrying_add(255, true), (0, true));
test_operator!(127i8.carrying_add(1, false), (-128, true));
test_operator!(127i8.carrying_add(0, true), (-128, true));
test_operator!(127i8.carrying_add(1, true), (-127, true));
test_operator!(127i8.carrying_add(-1, false), (126, false));
test_operator!(127i8.carrying_add(-1, true), (127, false)); test_operator!((-128i8).carrying_add(-1, false), (127, true));
test_operator!((-128i8).carrying_add(-1, true), (-128, false));
test_operator!(0u8.borrowing_sub(1, false), (255u8, true));
test_operator!(0u8.borrowing_sub(0, true), (255u8, true));
test_operator!(0u8.borrowing_sub(1, true), (254u8, true));
test_operator!(255u8.borrowing_sub(255, false), (0, false));
test_operator!(255u8.borrowing_sub(255, true), (255u8, true));
test_operator!((-128i8).borrowing_sub(1, false), (127, true));
test_operator!((-128i8).borrowing_sub(0, true), (127, true));
test_operator!((-128i8).borrowing_sub(1, true), (126, true));
test_operator!((-128i8).borrowing_sub(-1, false), (-127, false));
test_operator!((-128i8).borrowing_sub(-1, true), (-128, false)); test_operator!(127i8.borrowing_sub(-1, false), (-128, true));
test_operator!(127i8.borrowing_sub(-1, true), (127, false)); }
#[test]
fn custom_extended() {
test_operator!(255u8.extended_add(1, false), (0, true));
test_operator!(255u8.extended_add(0, true), (0, true));
test_operator!(255u8.extended_add(1, true), (1, true));
test_operator!(0u8.extended_add(255, false), (255, false));
test_operator!(0u8.extended_add(255, true), (0, true));
test_operator!(127i8.extended_add(1, false), (-128, true));
test_operator!(127i8.extended_add(0, true), (-128, true));
test_operator!(127i8.extended_add(1, true), (-127, true));
test_operator!(127i8.extended_add(-1, false), (126, false));
test_operator!(127i8.extended_add(-1, true), (127, false)); test_operator!((-128i8).extended_add(-1, false), (127, true));
test_operator!((-128i8).extended_add(-1, true), (-128, false)); test_operator!((0i8).extended_add(127, true), (-128, true));
test_operator!(0u8.extended_sub(1, false), (255u8, true));
test_operator!(0u8.extended_sub(0, true), (255u8, true));
test_operator!(0u8.extended_sub(1, true), (254u8, true));
test_operator!(255u8.extended_sub(255, false), (0, false));
test_operator!(255u8.extended_sub(255, true), (255u8, true));
test_operator!((-128i8).extended_sub(1, false), (127, true));
test_operator!((-128i8).extended_sub(0, true), (127, true));
test_operator!((-128i8).extended_sub(1, true), (126, true));
test_operator!((-128i8).extended_sub(-1, false), (-127, false));
test_operator!((-128i8).extended_sub(-1, true), (-128, false)); test_operator!(127i8.extended_sub(-1, false), (-128, true));
test_operator!(127i8.extended_sub(-1, true), (127, false)); test_operator!((0i8).extended_sub(-128, true), (127, false));
}
pub trait BigInt {
fn extended_add(self, rhs: Self, carry: bool) -> (Self, bool) where Self: Sized;
fn extended_sub(self, rhs: Self, carry: bool) -> (Self, bool) where Self: Sized;
}
macro_rules! impl_bigint {
($type:ty, $bigtype:ty) => {
impl BigInt for $type {
fn extended_add(self, rhs: Self, carry: bool) -> (Self, bool)
where Self: Sized {
let res = self as $bigtype + rhs as $bigtype + carry as $bigtype;
(res as Self, res < <$type>::MIN as $bigtype || res > <$type>::MAX as $bigtype)
}
fn extended_sub(self, rhs: Self, carry: bool) -> (Self, bool)
where Self: Sized {
let res = self as $bigtype - rhs as $bigtype - carry as $bigtype;
(res as Self, res < <$type>::MIN as $bigtype || res > <$type>::MAX as $bigtype)
}
}
};
}
impl_bigint!(u8, i16);
impl_bigint!(i8, i16);
impl_bigint!(u16, i32);
impl_bigint!(i16, i32);
impl_bigint!(u32, i64);
impl_bigint!(i32, i64);