bva 0.4.1

bva is a rust crate for manipulating and doing arithmetics on bit vectors of fixed but arbitrary size.
Documentation
use std::cmp::{Ordering, PartialEq, PartialOrd};
use std::ops::{Not, Sub};

use crate::auto::Bv;
use crate::bit::Bit;
use crate::dynamic::Bvd;
use crate::fixed::Bvf;
use crate::tests::{bvf_bvf_inner_unroll, bvf_inner_unroll, random_bv};
use crate::utils::{Integer, StaticCast};
use crate::BitVector;

fn eq_inner<B1, B2>(max_capacity: usize)
where
    B1: BitVector + PartialEq<B2> + Not<Output = B1>,
    B2: BitVector + PartialEq<B1> + for<'a> TryFrom<&'a B1, Error: std::fmt::Debug>,
{
    for length in 1..max_capacity {
        let mut bv1 = random_bv::<B1>(length);
        let mut bv2 = B2::try_from(&bv1).unwrap();
        bv1.resize(max_capacity, Bit::Zero);
        bv2.resize(bv2.significant_bits(), Bit::Zero);
        assert_eq!(bv1, bv2);
        assert_eq!(bv2, bv1);
        assert_ne!(!bv1, bv2);
    }
}

fn eq_inner_bvf_bvf<I1: Integer, I2: Integer, const N1: usize, const N2: usize>()
where
    I1: StaticCast<I2>,
    I2: StaticCast<I1>,
{
    eq_inner::<Bvf<I1, N1>, Bvf<I2, N2>>(usize::min(
        Bvf::<I1, N1>::capacity(),
        Bvf::<I2, N2>::capacity(),
    ));
}

fn eq_inner_bvf_bvd<I: Integer, const N: usize>()
where
    I: StaticCast<u64>,
    u64: StaticCast<I>,
{
    eq_inner::<Bvf<I, N>, Bvd>(Bvf::<I, N>::capacity());
    eq_inner::<Bvd, Bvf<I, N>>(Bvf::<I, N>::capacity());
}

fn eq_inner_bvf_bv<I: Integer, const N: usize>()
where
    I: StaticCast<u64>,
    u64: StaticCast<I>,
{
    eq_inner::<Bvf<I, N>, Bv>(Bvf::<I, N>::capacity());
    eq_inner::<Bv, Bvf<I, N>>(Bvf::<I, N>::capacity());
}

#[test]
fn eq_bvf_bvf() {
    bvf_bvf_inner_unroll!(eq_inner_bvf_bvf, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

#[test]
fn eq_bvf_bvd() {
    bvf_inner_unroll!(eq_inner_bvf_bvd, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

#[test]
fn eq_bvf_bv() {
    bvf_inner_unroll!(eq_inner_bvf_bv, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

#[test]
fn eq_bvd_bvd() {
    eq_inner::<Bvd, Bvd>(512);
}

#[test]
fn eq_bvd_bv() {
    eq_inner::<Bvd, Bv>(512);
    eq_inner::<Bv, Bvd>(512);
}

#[test]
fn eq_bv_bv() {
    eq_inner::<Bv, Bv>(512);
}

fn cmp_inner<B1, B2>(max_capacity: usize)
where
    B1: BitVector + PartialOrd<B2>,
    for<'a, 'b> &'a B1: Sub<&'b B2, Output = B1>,
    B2: BitVector + PartialOrd<B1> + for<'a> TryFrom<&'a B1, Error: std::fmt::Debug>,
    for<'a, 'b> &'a B2: Sub<&'b B1, Output = B2>,
{
    for length in 0..max_capacity {
        let mut bv1 = random_bv::<B1>(length);
        let mut bv2 = random_bv::<B2>(length);
        bv1.resize(max_capacity, Bit::Zero);
        bv2.resize(bv2.significant_bits(), Bit::Zero);
        match bv1.partial_cmp(&bv2).unwrap() {
            Ordering::Less => {
                assert_eq!(bv2.partial_cmp(&bv1).unwrap(), Ordering::Greater);
                let diff = &bv2 - &bv1;
                // If bv1 < bv2, then bv2 - bv1 > 0 and so it shouldn't overflow
                assert_ne!(diff.partial_cmp(&bv2).unwrap(), Ordering::Greater);
            }
            Ordering::Equal => {
                assert_eq!(bv2.partial_cmp(&bv1).unwrap(), Ordering::Equal);
                let diff = &bv2 - &bv1;
                assert!(diff.is_zero());
            }
            Ordering::Greater => {
                assert_eq!(bv2.partial_cmp(&bv1).unwrap(), Ordering::Less);
                let diff = &bv1 - &bv2;
                // If bv1 > bv2, then bv1 - bv2 > 0 and so it shouldn't overflow
                assert_ne!(diff.partial_cmp(&bv1).unwrap(), Ordering::Greater);
            }
        }
    }
}

fn cmp_inner_bvf_bvf<I1: Integer, I2: Integer, const N1: usize, const N2: usize>()
where
    I1: StaticCast<I2>,
    I2: StaticCast<I1>,
{
    cmp_inner::<Bvf<I1, N1>, Bvf<I2, N2>>(usize::min(
        Bvf::<I1, N1>::capacity(),
        Bvf::<I2, N2>::capacity(),
    ));
}

fn cmp_inner_bvf_bvd<I: Integer, const N: usize>()
where
    I: StaticCast<u64>,
    u64: StaticCast<I>,
{
    cmp_inner::<Bvf<I, N>, Bvd>(Bvf::<I, N>::capacity());
    cmp_inner::<Bvd, Bvf<I, N>>(Bvf::<I, N>::capacity());
}

fn cmp_inner_bvf_bv<I: Integer, const N: usize>()
where
    I: StaticCast<u64>,
    u64: StaticCast<I>,
{
    cmp_inner::<Bvf<I, N>, Bv>(Bvf::<I, N>::capacity());
    cmp_inner::<Bv, Bvf<I, N>>(Bvf::<I, N>::capacity());
}

#[test]
fn cmp_bvf_bvf() {
    bvf_bvf_inner_unroll!(cmp_inner_bvf_bvf, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

#[test]
fn cmp_bvf_bvd() {
    bvf_inner_unroll!(cmp_inner_bvf_bvd, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

#[test]
fn cmp_bvf_bv() {
    bvf_inner_unroll!(cmp_inner_bvf_bv, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

#[test]
fn cmp_bvd_bvd() {
    cmp_inner::<Bvd, Bvd>(512);
}

#[test]
fn cmp_bvd_bv() {
    cmp_inner::<Bvd, Bv>(512);
    cmp_inner::<Bv, Bvd>(512);
}

#[test]
fn cmp_bv_bv() {
    cmp_inner::<Bv, Bv>(512);
}