dashu-int 0.3.1

A big integer library with good performance
Documentation
use core::{
    fmt::Debug,
    ops::{Add, AddAssign, Sub, SubAssign},
};

mod helper_macros;

/// Test a + b = c in various ways.
fn test_add_sub<'a, T>(a: &'a T, b: &'a T, c: &'a T)
where
    T: Add<T, Output = T>,
    T: Add<&'a T, Output = T>,
    &'a T: Add<T, Output = T>,
    &'a T: Add<&'a T, Output = T>,
    T: AddAssign<T>,
    T: AddAssign<&'a T>,
    T: Sub<T, Output = T>,
    T: Sub<&'a T, Output = T>,
    &'a T: Sub<T, Output = T>,
    &'a T: Sub<&'a T, Output = T>,
    T: SubAssign<T>,
    T: SubAssign<&'a T>,
    T: Clone,
    T: Debug,
    T: Eq,
{
    assert_eq!(a + b, *c);
    assert_eq!(a.clone() + b, *c);
    assert_eq!(a + b.clone(), *c);
    assert_eq!(a.clone() + b.clone(), *c);

    let mut x = a.clone();
    x += b;
    assert_eq!(x, *c);

    let mut x = a.clone();
    x += b.clone();
    assert_eq!(x, *c);

    assert_eq!(c - a, *b);
    assert_eq!(c.clone() - a, *b);
    assert_eq!(c - a.clone(), *b);
    assert_eq!(c.clone() - a.clone(), *b);

    let mut x = c.clone();
    x -= a;
    assert_eq!(x, *b);

    let mut x = c.clone();
    x -= a.clone();
    assert_eq!(x, *b);
}

#[test]
fn test_add_sub_ubig() {
    let test_cases = [
        (ubig!(3), ubig!(4), ubig!(7)),
        (ubig!(0xffffffffffffffff), ubig!(1), ubig!(0x10000000000000000)),
        (ubig!(0x10000000000000003), ubig!(4), ubig!(0x10000000000000007)),
        (
            ubig!(0xeeeeeeeeeeeeeeeeffffffffffffffff),
            ubig!(1),
            ubig!(0xeeeeeeeeeeeeeeef0000000000000000),
        ),
        (
            ubig!(0xeeeeeeeeeeeeeeeeffffffffffffffff),
            ubig!(1),
            ubig!(0xeeeeeeeeeeeeeeef0000000000000000),
        ),
        (
            ubig!(0xffffffffffffffffffffffffffffffff),
            ubig!(2),
            ubig!(0x100000000000000000000000000000001),
        ),
        (
            ubig!(0x88888888888888888888888888888888),
            ubig!(0x88888888888888888888888888888888),
            ubig!(0x111111111111111111111111111111110),
        ),
        (
            ubig!(0x888888888888888888888888888888888888888888888888),
            ubig!(0x88888888888888888888888888888888),
            ubig!(0x888888888888888911111111111111111111111111111110),
        ),
        (
            ubig!(0x888888888888888888888888888888888888888888888888),
            ubig!(0),
            ubig!(0x888888888888888888888888888888888888888888888888),
        ),
    ];

    for (a, b, c) in &test_cases {
        test_add_sub(a, b, c);
        test_add_sub(b, a, c);
    }
}

#[test]
#[should_panic]
fn test_sub_ubig_overflow() {
    let _ = ubig!(3) - ubig!(4);
}

#[test]
fn test_add_sub_ibig() {
    let test_cases = [
        (ibig!(3), ibig!(4), ibig!(7)),
        (ibig!(3), ibig!(-4), ibig!(-1)),
        (ibig!(-3), ibig!(4), ibig!(1)),
        (ibig!(-3), ibig!(-4), ibig!(-7)),
        (ibig!(0x10000000000000000), ibig!(-4), ibig!(0xfffffffffffffffc)),
        (
            ibig!(0x10000000000000000),
            ibig!(0x200000000000000000000000000000000),
            ibig!(0x200000000000000010000000000000000),
        ),
        (
            ibig!(-0x200000000000000010000000000000000),
            ibig!(0x200000000000000000000000000000000),
            ibig!(-0x10000000000000000),
        ),
        (
            ibig!(0x200000000000000010000000000000000),
            ibig!(-0x200000000000000000000000000000000),
            ibig!(0x10000000000000000),
        ),
    ];

    for (a, b, c) in &test_cases {
        test_add_sub(a, b, c);
        test_add_sub(b, a, c);
    }
}

#[test]
#[allow(clippy::op_ref)]
fn test_add_sub_ubig_primitive() {
    assert_eq!(ubig!(3) + 7u16, ubig!(10));
    assert_eq!(ubig!(3) + &7u16, ubig!(10));
    assert_eq!(&ubig!(3) + 7u16, ubig!(10));
    assert_eq!(&ubig!(3) + &7u16, ubig!(10));
    assert_eq!(7u16 + ubig!(3), ubig!(10));
    assert_eq!(7u16 + &ubig!(3), ubig!(10));
    assert_eq!(&7u16 + ubig!(3), ubig!(10));
    assert_eq!(&7u16 + &ubig!(3), ubig!(10));
    let mut x = ubig!(3);
    x += 3u8;
    x += &3u8;
    assert_eq!(x, ubig!(9));

    assert_eq!(ubig!(7) - 5u16, ubig!(2));
    assert_eq!(ubig!(7) - &5u16, ubig!(2));
    assert_eq!(&ubig!(7) - 5u16, ubig!(2));
    assert_eq!(&ubig!(7) - &5u16, ubig!(2));
    let mut x = ubig!(10);
    x -= 1u8;
    x -= &2u8;
    assert_eq!(x, ubig!(7));
}

#[test]
#[should_panic]
fn test_sub_ubig_primitive_overflow() {
    let _ = ubig!(3) - 5u16;
}

#[test]
#[allow(clippy::op_ref)]
fn test_add_sub_ibig_primitive() {
    assert_eq!(ibig!(-3) + 7, ibig!(4));
    assert_eq!(ibig!(-3) + &7, ibig!(4));
    assert_eq!(&ibig!(-3) + 7, ibig!(4));
    assert_eq!(&ibig!(-3) + &7, ibig!(4));
    assert_eq!(7 + ibig!(-3), ibig!(4));
    assert_eq!(7 + &ibig!(-3), ibig!(4));
    assert_eq!(&7 + ibig!(-3), ibig!(4));
    assert_eq!(&7 + &ibig!(-3), ibig!(4));
    let mut x = ibig!(-3);
    x += 3;
    x += &3;
    assert_eq!(x, ibig!(3));

    assert_eq!(ibig!(7) - 5, ibig!(2));
    assert_eq!(ibig!(7) - &5, ibig!(2));
    assert_eq!(&ibig!(7) - 5, ibig!(2));
    assert_eq!(&ibig!(7) - &5, ibig!(2));
    assert_eq!(5 - ibig!(7), ibig!(-2));
    assert_eq!(5 - &ibig!(7), ibig!(-2));
    assert_eq!(&5 - ibig!(7), ibig!(-2));
    assert_eq!(&5 - &ibig!(7), ibig!(-2));

    let mut x = ibig!(10);
    x -= 7;
    x -= &7;
    assert_eq!(x, ibig!(-4));

    assert_eq!(ibig!(3) + (-1), ibig!(2));
    assert_eq!(ibig!(3) + &(-1), ibig!(2));
    assert_eq!(&ibig!(3) + (-1), ibig!(2));
    assert_eq!(&ibig!(3) + &(-1), ibig!(2));
    assert_eq!(-1 + ibig!(3), ibig!(2));
    assert_eq!(-1 + &ibig!(3), ibig!(2));
    assert_eq!(&-1 + ibig!(3), ibig!(2));
    assert_eq!(&-1 + &ibig!(3), ibig!(2));
    let mut x = ibig!(3);
    x += -10;
    x += &20;
    assert_eq!(x, ibig!(13));

    assert_eq!(ibig!(3) - -1, ibig!(4));
    assert_eq!(ibig!(3) - &-1, ibig!(4));
    assert_eq!(&ibig!(3) - -1, ibig!(4));
    assert_eq!(&ibig!(3) - &-1, ibig!(4));
    assert_eq!(3 - ibig!(4), ibig!(-1));
    assert_eq!(3 - &ibig!(4), ibig!(-1));
    assert_eq!(&3 - ibig!(4), ibig!(-1));
    assert_eq!(&3 - &ibig!(4), ibig!(-1));
    let mut x = ibig!(3);
    x -= -1;
    x -= &10;
    assert_eq!(x, ibig!(-6));
}

#[test]
fn test_add_sub_ubig_ibig() {
    let test_cases = [
        (ubig!(3), ibig!(4), ibig!(7)),
        (ubig!(3), ibig!(-4), ibig!(-1)),
        (ubig!(0x10000000000000000), ibig!(-4), ibig!(0xfffffffffffffffc)),
        (
            ubig!(0x10000000000000000),
            ibig!(0x200000000000000000000000000000000),
            ibig!(0x200000000000000010000000000000000),
        ),
        (
            ubig!(0x200000000000000010000000000000000),
            ibig!(-0x200000000000000000000000000000000),
            ibig!(0x10000000000000000),
        ),
    ];

    for (a, b, c) in &test_cases {
        assert_eq!(a + b, *c);
        assert_eq!(a.clone() + b, *c);
        assert_eq!(a + b.clone(), *c);
        assert_eq!(a.clone() + b.clone(), *c);

        assert_eq!(c - a, *b);
        assert_eq!(c.clone() - a, *b);
        assert_eq!(c - a.clone(), *b);
        assert_eq!(c.clone() - a.clone(), *b);

        let mut x = c.clone();
        x -= a;
        assert_eq!(x, *b);

        let mut x = c.clone();
        x -= a.clone();
        assert_eq!(x, *b);
    }
}