ramp 0.7.0

A high-performance multiple-precision arithmetic library
Documentation
extern crate quickcheck;
extern crate ramp;
extern crate num_bigint;

use quickcheck::TestResult;
use ramp::ll::limb;
use ramp::ll::limb::Limb;
use num_bigint::BigUint;

#[cfg(feature = "full-quickcheck")]
const QUICKCHECK_THOROUGNESS: u64 = 100;
#[cfg(not(feature = "full-quickcheck"))]
const QUICKCHECK_THOROUGNESS: u64 = 1;

// Copy of quickcheck macro, but with custom tests and max_tests values
macro_rules! quickcheck {
    (@as_items $($i:item)*) => ($($i)*);
    {
        $(
            fn $fn_name:ident($($arg_name:ident : $arg_ty:ty),*) -> $ret:ty {
                $($code:tt)*
            }
        )*
    } => (
        quickcheck! {
            @as_items
            $(
                #[test]
                fn $fn_name() {
                    fn prop($($arg_name: $arg_ty),*) -> $ret {
                        $($code)*
                    }
                    quickcheck::QuickCheck::new()
                        .tests(QUICKCHECK_THOROUGNESS*10_000)
                        .max_tests(QUICKCHECK_THOROUGNESS*100_000)
                        .quickcheck(prop as fn($($arg_ty),*) -> $ret);
                }
            )*
        }
    )
}

macro_rules! B { () => { BigUint::from(usize::max_value()) + BigUint::from(1usize) } }
macro_rules! l { ($e:expr) => { Limb($e as limb::BaseInt) } }
macro_rules! b  {   ($e:expr) => { BigUint::from($e as usize) };
                    ($h:expr,$l:expr) => { b!($h) * B!() + b!($l) }
                }

quickcheck!{
    fn check_add(ha:usize, la:usize, hb:usize, lb:usize) -> TestResult {
        let a = b!(ha,la);
        let b = b!(hb,lb);
        let num_sum = (a+b)%(B!()*B!());

        let (hw,lw) = limb::add_2(l!(ha), l!(la), l!(hb), l!(lb));
        let ramp_sum = b!(hw.0, lw.0);

        TestResult::from_bool(num_sum == ramp_sum)
    }

    fn check_sub(ha: usize, la: usize, hb: usize, lb: usize) -> TestResult {
        let a = b!(ha,la);
        let b = b!(hb,lb);
        if a < b {
            return TestResult::discard();
        }
        let num_diff = (a - b) % (B!()*B!());

        let (hw, lw) = limb::sub_2(l!(ha), l!(la), l!(hb), l!(lb));
        let ramp_diff = b!(hw.0, lw.0);

        TestResult::from_bool(num_diff == ramp_diff)
    }

    fn check_mul(a: usize, b: usize) -> TestResult {
        let num_prod = b!(a) * b!(b);

        let (hw, lw) = limb::mul(l!(a), l!(b));
        let ramp_prod = b!(hw.0, lw.0);

        TestResult::from_bool(ramp_prod == num_prod)
    }

    fn check_div(hn: usize, ln: usize, d: usize) -> TestResult {
        let d = (1 + usize::max_value() / 2).saturating_add(d / 2);
        if hn >= d {
            return TestResult::discard();
        }

        let num_n = b!(hn,ln);
        let num_q = &num_n / b!(d);
        let num_r = &num_n % b!(d);

        let (ramp_q, ramp_r) = limb::div(l!(hn), l!(ln), l!(d));

        TestResult::from_bool(num_q == b!(ramp_q.0) && num_r == b!(ramp_r.0))
    }
}