twofloat 0.6.1

Double-double arithmetic functionality.
Documentation
use rand::Rng;

const TEST_ITERS: usize = 100000;

pub fn random_float() -> f64 {
    let mut engine = rand::thread_rng();
    let mantissa_dist = rand::distributions::Uniform::new(0, 1u64 << 52);
    let exponent_dist = rand::distributions::Uniform::new(0, 2047u64);
    let x = f64::from_bits(engine.sample(mantissa_dist) | (engine.sample(exponent_dist) << 52));
    if engine.gen() {
        x
    } else {
        -x
    }
}

pub fn repeated_test<F>(test: F)
where
    F: Fn(),
{
    for _ in 0..TEST_ITERS {
        test();
    }
}

pub fn get_valid_pair<F: Fn(f64, f64) -> bool>(pred: F) -> (f64, f64) {
    loop {
        let a = random_float();
        let b = random_float();
        if pred(a, b) {
            return (a, b);
        }
    }
}

macro_rules! assert_eq_ulp {
    ($left:expr, $right:expr, $ulp:expr) => ({
        let left_val = $left;
        let right_val = $right;
        let ulp_val = $ulp;

        let a_bits = left_val.to_bits();
        let b_bits = right_val.to_bits();
        let fix_sign = |x| {
            if x & (1 << 63) == 0 {
                x
            } else {
                x ^ ((1 << 63) - 1)
            }
        };
        let diff = (fix_sign(a_bits) as i64)
            .saturating_sub(fix_sign(b_bits) as i64)
            .abs();
        if !(diff <= *ulp_val) {
            panic!(r#"assertion failed: `(left == right) ({:?} ulp)`
  left: `{:?}`,
 right: `{:?}`,
  diff: `{}`"#, ulp_val, left_val, right_val, diff)
        }
    });
    ($left:expr, $right:expr, $ulp:expr, $($args:tt,)+) => ({
        let left_val = $left;
        let right_val = $right;
        let ulp_val = $ulp;

        let a_bits = left_val.to_bits();
        let b_bits = right_val.to_bits();
        let fix_sign = |x| {
            if x & (1 << 63) == 0 {
                x
            } else {
                x ^ ((1 << 63) - 1)
            }
        };
        let diff = (fix_sign(a_bits) as i64)
            .saturating_sub(fix_sign(b_bits) as i64)
            .abs();
        if !(diff <= ulp_val) {
            panic!(r#"assertion failed: `(left == right) ({:?} ulp)`
  left: `{:?}`,
 right: `{:?}`,
  diff: `{}`: {}"#, ulp_val, left_val, right_val, diff, format_args!($($args,)+))
        }
    });
    ($left:expr, $right:expr, $ulp:expr, $($args:tt),+) => {
        assert_eq_ulp!($left, $right, $ulp, $($args,)+)
    };
}