dashu-int 0.4.2

A big integer library with good performance
Documentation
use dashu_int::fast_div::ConstDivisor;
use num_modular::Reducer;

mod helper_macros;

#[test]
fn test_reducer_add() {
    let reducer = ConstDivisor::new(ubig!(1234));
    let small_cases = [
        (ubig!(0), ubig!(0), ubig!(0)),
        (ubig!(0), ubig!(1), ubig!(1)),
        (ubig!(1), ubig!(2), ubig!(3)),
        (ubig!(1000), ubig!(2000), ubig!(3000)),
    ];

    for (a, b, c) in small_cases {
        assert_eq!(reducer.add(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c));
    }

    let reducer = ConstDivisor::new(ubig!(0x1234567890123456789012345678901234567890));
    let large_cases = [
        (ubig!(0), ubig!(0), ubig!(0)),
        (ubig!(0), ubig!(1), ubig!(1)),
        (ubig!(1), ubig!(2), ubig!(3)),
        (ubig!(0x1000), ubig!(0x2000), ubig!(0x3000)),
        (
            ubig!(0x100000000000000000000000),
            ubig!(0x200000000000000000000000),
            ubig!(0x300000000000000000000000),
        ),
    ];

    for (a, b, c) in large_cases {
        assert_eq!(reducer.add(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c));
    }
}

#[test]
fn test_reducer_dbl() {
    let reducer = ConstDivisor::new(ubig!(1234));
    let small_cases = [
        (ubig!(0), ubig!(0)),
        (ubig!(1), ubig!(2)),
        (ubig!(2), ubig!(4)),
        (ubig!(1000), ubig!(2000)),
    ];

    for (a, b) in small_cases {
        assert_eq!(reducer.dbl(reducer.transform(a)), reducer.transform(b));
    }

    let reducer = ConstDivisor::new(ubig!(0x1234567890123456789012345678901234567890));
    let large_cases = [
        (ubig!(0), ubig!(0)),
        (ubig!(1), ubig!(2)),
        (ubig!(2), ubig!(4)),
        (ubig!(0x1000), ubig!(0x2000)),
        (ubig!(0x100000000000000000000000), ubig!(0x200000000000000000000000)),
    ];

    for (a, b) in large_cases {
        assert_eq!(reducer.dbl(reducer.transform(a)), reducer.transform(b));
    }
}

#[test]
fn test_reducer_sub() {
    let reducer = ConstDivisor::new(ubig!(1234));
    let small_cases = [
        (ubig!(0), ubig!(0), ubig!(0)),
        (ubig!(0), ubig!(1), ubig!(1233)),
        (ubig!(1), ubig!(0), ubig!(1)),
        (ubig!(1000), ubig!(2000), ubig!(234)),
        (ubig!(2000), ubig!(1000), ubig!(1000)),
    ];

    for (a, b, c) in small_cases {
        assert_eq!(reducer.sub(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c));
    }

    let m = ubig!(0x1234567890123456789012345678901234567890);
    let reducer = ConstDivisor::new(m.clone());
    let large_cases = [
        (ubig!(0), ubig!(0), ubig!(0)),
        (ubig!(0), ubig!(1), &m - ubig!(1)),
        (ubig!(1), ubig!(0), ubig!(1)),
        (ubig!(0x1000), ubig!(0x2000), &m - ubig!(0x1000)),
        (ubig!(0x2000), ubig!(0x1000), ubig!(0x1000)),
        (
            ubig!(0x100000000000000000000000),
            ubig!(0x200000000000000000000000),
            &m - ubig!(0x100000000000000000000000),
        ),
        (
            ubig!(0x200000000000000000000000),
            ubig!(0x100000000000000000000000),
            ubig!(0x100000000000000000000000),
        ),
    ];

    for (a, b, c) in large_cases {
        assert_eq!(reducer.sub(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c));
    }
}

#[test]
fn test_reducer_neg() {
    let reducer = ConstDivisor::new(ubig!(1234));
    let small_cases = [
        (ubig!(0), ubig!(0)),
        (ubig!(1), ubig!(1233)),
        (ubig!(2), ubig!(1232)),
        (ubig!(1000), ubig!(234)),
    ];

    for (a, b) in small_cases {
        assert_eq!(reducer.neg(reducer.transform(a)), reducer.transform(b));
    }

    let m = ubig!(0x1234567890123456789012345678901234567890);
    let reducer = ConstDivisor::new(m.clone());
    let large_cases = [
        (ubig!(0), ubig!(0)),
        (ubig!(1), &m - ubig!(1)),
        (ubig!(2), &m - ubig!(2)),
        (ubig!(0x1000), &m - ubig!(0x1000)),
        (ubig!(0x100000000000000000000000), &m - ubig!(0x100000000000000000000000)),
    ];

    for (a, b) in large_cases {
        assert_eq!(reducer.neg(reducer.transform(a)), reducer.transform(b));
    }
}

#[test]
fn test_reducer_mul() {
    let reducer = ConstDivisor::new(ubig!(1234));
    let small_cases = [
        (ubig!(0), ubig!(0), ubig!(0)),
        (ubig!(0), ubig!(1), ubig!(0)),
        (ubig!(1), ubig!(1), ubig!(1)),
        (ubig!(1000), ubig!(2000), ubig!(920)),
        (ubig!(2000), ubig!(1000), ubig!(920)),
    ];

    for (a, b, c) in small_cases {
        assert_eq!(reducer.mul(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c));
    }

    let m = ubig!(0x1234567890123456789012345678901234567890);
    let reducer = ConstDivisor::new(m.clone());
    let large_cases = [
        (ubig!(0), ubig!(0), ubig!(0)),
        (ubig!(0), ubig!(1), ubig!(0)),
        (ubig!(1), ubig!(1), ubig!(1)),
        (ubig!(0x1000), ubig!(0x2000), ubig!(0x2000000)),
        (ubig!(0x2000), ubig!(0x1000), ubig!(0x2000000)),
        (
            ubig!(0x100000000000000000000000),
            ubig!(0x200000000000000000000000),
            ubig!(0x12c000000012c000000012c000000012e000000),
        ),
        (
            ubig!(0x200000000000000000000000),
            ubig!(0x100000000000000000000000),
            ubig!(0x12c000000012c000000012c000000012e000000),
        ),
    ];

    for (a, b, c) in large_cases {
        assert_eq!(reducer.mul(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c));
    }
}

#[test]
fn test_reducer_sqr() {
    let reducer = ConstDivisor::new(ubig!(1234));
    let small_cases = [
        (ubig!(0), ubig!(0)),
        (ubig!(1), ubig!(1)),
        (ubig!(2), ubig!(4)),
        (ubig!(1000), ubig!(460)),
    ];

    for (a, b) in small_cases {
        assert_eq!(reducer.sqr(reducer.transform(a)), reducer.transform(b));
    }

    let m = ubig!(0x1234567890123456789012345678901234567890);
    let reducer = ConstDivisor::new(m.clone());
    let large_cases = [
        (ubig!(0), ubig!(0)),
        (ubig!(1), ubig!(1)),
        (ubig!(2), ubig!(4)),
        (ubig!(0x1000), ubig!(0x1000000)),
        (
            ubig!(0x100000000000000000000000),
            ubig!(0x96000000009600000000960000000097000000),
        ),
    ];

    for (a, b) in large_cases {
        assert_eq!(reducer.sqr(reducer.transform(a)), reducer.transform(b));
    }
}

#[test]
fn test_reducer_inv() {
    let reducer = ConstDivisor::new(ubig!(1234));
    let small_cases = [
        (ubig!(0), None),
        (ubig!(1), Some(ubig!(1))),
        (ubig!(2), None),
        (ubig!(1001), Some(ubig!(1091))),
    ];

    for (a, b) in small_cases {
        assert_eq!(reducer.inv(reducer.transform(a)), b.map(|v| reducer.transform(v)));
    }

    let m = ubig!(0x1234567890123456789012345678901234567890);
    let reducer = ConstDivisor::new(m.clone());
    let large_cases = [
        (ubig!(0), None),
        (ubig!(1), Some(ubig!(1))),
        (ubig!(2), None),
        (ubig!(0x1001), Some(ubig!(94593912811883961533498385659457234825064814993))),
        (
            ubig!(0x100000000000000000000001),
            Some(ubig!(49597318474237639809488304913303841829624579953)),
        ),
    ];

    for (a, b) in large_cases {
        assert_eq!(reducer.inv(reducer.transform(a)), b.map(|v| reducer.transform(v)));
    }
}

#[test]
fn test_reducer_pow() {
    let reducer = ConstDivisor::new(ubig!(1234));
    let small_cases = [
        (ubig!(0), ubig!(0), ubig!(1)),
        (ubig!(0), ubig!(1), ubig!(0)),
        (ubig!(1), ubig!(1), ubig!(1)),
        (ubig!(1000), ubig!(2000), ubig!(968)),
        (ubig!(2000), ubig!(1000), ubig!(446)),
    ];

    for (a, b, c) in small_cases {
        assert_eq!(reducer.pow(reducer.transform(a), &b), reducer.transform(c));
    }

    let m = ubig!(0x1234567890123456789012345678901234567890);
    let reducer = ConstDivisor::new(m.clone());
    let large_cases = [
        (ubig!(0), ubig!(0), ubig!(1)),
        (ubig!(0), ubig!(1), ubig!(0)),
        (ubig!(1), ubig!(1), ubig!(1)),
        (
            ubig!(0x1000),
            ubig!(0x2000),
            ubig!(6836336448053429355926867185433977698732821296),
        ),
        (
            ubig!(0x2000),
            ubig!(0x1000),
            ubig!(40493613063087797729807140685333106341989572736),
        ),
        (
            ubig!(0x100000000000000000000000),
            ubig!(0x200000000000000000000000),
            ubig!(3353173600746198511020157785071195910194367376),
        ),
        (
            ubig!(0x100000000000000000000001),
            ubig!(0x200000000000000000000001),
            ubig!(5183365446386658625038933891731846219325326897),
        ),
    ];

    for (a, b, c) in large_cases {
        assert_eq!(reducer.pow(reducer.transform(a), &b), reducer.transform(c));
    }
}