// Copyright © 2024 Mikhail Hogrefe
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See .
use itertools::repeat_n;
use malachite_base::num::basic::signeds::PrimitiveSigned;
use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
use malachite_base::test_util::generators::{
bool_vec_gen_var_1, bool_vec_gen_var_2, bool_vec_gen_var_3, bool_vec_gen_var_4,
unsigned_gen_var_5,
};
use malachite_base::test_util::num::logic::bit_convertible::{
from_bits_asc_alt, from_bits_asc_signed_naive, from_bits_asc_unsigned_naive, from_bits_desc_alt,
};
use std::iter::once;
use std::panic::catch_unwind;
#[test]
pub fn test_from_bits_asc() {
fn test_unsigned(bits: &[bool], out: T) {
assert_eq!(T::from_bits_asc(bits.iter().copied()), out);
assert_eq!(
from_bits_asc_unsigned_naive::(bits.iter().copied()),
out
);
assert_eq!(from_bits_asc_alt::(bits.iter().copied()), out);
}
test_unsigned(&[], 0u8);
test_unsigned(&[false], 0u8);
test_unsigned(&[false, false, false], 0u8);
test_unsigned(&[false; 100], 0u8);
test_unsigned(&[true], 1u16);
test_unsigned(&[false, true], 2u32);
test_unsigned(&[true, true], 3u64);
test_unsigned(&[true, true, false, true, true, true, true], 123u16);
test_unsigned(
&[true, true, false, true, true, true, true, false, false, false],
123u16,
);
test_unsigned(&[true; 8], u8::MAX);
fn test_signed(bits: &[bool], out: T) {
assert_eq!(T::from_bits_asc(bits.iter().copied()), out);
assert_eq!(
from_bits_asc_signed_naive::(bits.iter().copied()),
out
);
assert_eq!(from_bits_asc_alt::(bits.iter().copied()), out);
}
test_signed(&[], 0i8);
test_signed(&[false], 0i8);
test_signed(&[false, false, false], 0i8);
test_signed(&[false; 100], 0i8);
test_signed(&[true, false], 1i16);
test_signed(&[false, true, false], 2i32);
test_signed(&[true, true, false], 3i64);
test_signed(&[true], -1i16);
test_signed(&[true, true, true], -1i16);
test_signed(&[true; 100], -1i16);
test_signed(&[false, true], -2i32);
test_signed(&[true, false, true], -3i64);
test_signed(&[true, true, false, true, true, true, true, false], 123i16);
test_signed(
&[true, true, false, true, true, true, true, false, false, false, false],
123i16,
);
test_signed(
&[true, false, true, false, false, false, false, true],
-123i16,
);
test_signed(
&[true, false, true, false, false, false, false, true, true, true, true],
-123i16,
);
test_signed(&[true, true, true, true, true, true, true, false], i8::MAX);
test_signed(
&[false, false, false, false, false, false, false, true],
i8::MIN,
);
}
fn from_bits_asc_fail_helper_unsigned() {
assert_panic!(T::from_bits_asc(repeat_n(true, 200)));
}
fn from_bits_asc_fail_helper_signed() {
assert_panic!(T::from_bits_asc(
repeat_n(false, 200).chain([true, false].iter().copied())
));
assert_panic!(T::from_bits_asc(repeat_n(false, 200).chain(once(true))));
}
#[test]
fn from_bits_asc_fail() {
apply_fn_to_unsigneds!(from_bits_asc_fail_helper_unsigned);
apply_fn_to_signeds!(from_bits_asc_fail_helper_signed);
}
#[test]
pub fn test_from_bits_desc() {
fn test_unsigned(bits: &[bool], out: T) {
assert_eq!(T::from_bits_desc(bits.iter().copied()), out);
assert_eq!(from_bits_desc_alt::(bits.iter().copied()), out);
}
test_unsigned(&[], 0u8);
test_unsigned(&[false], 0u8);
test_unsigned(&[false, false, false], 0u8);
test_unsigned(&[false; 100], 0u8);
test_unsigned(&[true], 1u16);
test_unsigned(&[true, false], 2u32);
test_unsigned(&[true, true], 3u64);
test_unsigned(&[true, true, true, true, false, true, true], 123u16);
test_unsigned(
&[false, false, false, true, true, true, true, false, true, true],
123u16,
);
test_unsigned(&[true; 8], u8::MAX);
fn test_signed(bits: &[bool], out: T) {
assert_eq!(T::from_bits_desc(bits.iter().copied()), out);
assert_eq!(from_bits_desc_alt::(bits.iter().copied()), out);
}
test_signed(&[], 0i8);
test_signed(&[false], 0i8);
test_signed(&[false, false, false], 0i8);
test_signed(&[false; 100], 0i8);
test_signed(&[false, true], 1i16);
test_signed(&[false, true, false], 2i32);
test_signed(&[false, true, true], 3i64);
test_signed(&[true], -1i16);
test_signed(&[true, true, true], -1i16);
test_signed(&[true; 100], -1i16);
test_signed(&[true, false], -2i32);
test_signed(&[true, false, true], -3i64);
test_signed(&[false, true, true, true, true, false, true, true], 123i16);
test_signed(
&[false, false, false, false, true, true, true, true, false, true, true],
123i16,
);
test_signed(
&[true, false, false, false, false, true, false, true],
-123i16,
);
test_signed(
&[true, true, true, true, false, false, false, false, true, false, true],
-123i16,
);
test_signed(&[false, true, true, true, true, true, true, true], i8::MAX);
test_signed(
&[true, false, false, false, false, false, false, false],
i8::MIN,
);
}
fn from_bits_desc_fail_helper_unsigned() {
assert_panic!(T::from_bits_desc(repeat_n(true, 200)));
}
fn from_bits_desc_fail_helper_signed() {
assert_panic!(T::from_bits_desc(
[false, true].iter().copied().chain(repeat_n(false, 200))
));
assert_panic!(T::from_bits_desc(once(true).chain(repeat_n(false, 200))));
}
#[test]
fn from_bits_desc_fail() {
apply_fn_to_unsigneds!(from_bits_desc_fail_helper_unsigned);
apply_fn_to_signeds!(from_bits_desc_fail_helper_signed);
}
fn from_bits_asc_properties_helper_unsigned() {
bool_vec_gen_var_1::().test_properties(|bs| {
let n = T::from_bits_asc(bs.iter().copied());
assert_eq!(from_bits_asc_unsigned_naive::(bs.iter().copied()), n);
assert_eq!(from_bits_asc_alt::(bs.iter().copied()), n);
let trailing_falses = bs.iter().rev().take_while(|&&bit| !bit).count();
let trimmed_bits = bs[..bs.len() - trailing_falses].to_vec();
assert_eq!(n.to_bits_asc(), trimmed_bits);
});
unsigned_gen_var_5().test_properties(|u| {
assert_eq!(T::from_bits_desc(repeat_n(false, u)), T::ZERO);
});
}
fn from_bits_asc_properties_helper_signed() {
bool_vec_gen_var_2::().test_properties(|bs| {
let n = T::from_bits_asc(bs.iter().copied());
assert_eq!(from_bits_asc_signed_naive::(bs.iter().copied()), n);
assert_eq!(from_bits_asc_alt::(bs.iter().copied()), n);
let trimmed_bits = if bs.iter().all(|&bit| !bit) {
Vec::new()
} else {
let sign_bits = if *bs.last().unwrap() {
bs.iter().rev().take_while(|&&bit| bit).count()
} else {
bs.iter().rev().take_while(|&&bit| !bit).count()
};
bs[..=bs.len() - sign_bits].to_vec()
};
assert_eq!(n.to_bits_asc(), trimmed_bits);
});
unsigned_gen_var_5().test_properties(|u| {
assert_eq!(T::from_bits_asc(repeat_n(false, u)), T::ZERO);
assert_eq!(T::from_bits_asc(repeat_n(true, u + 1)), T::NEGATIVE_ONE);
});
}
#[test]
fn from_bits_asc_properties() {
apply_fn_to_unsigneds!(from_bits_asc_properties_helper_unsigned);
apply_fn_to_signeds!(from_bits_asc_properties_helper_signed);
}
fn from_bits_desc_properties_helper_unsigned() {
bool_vec_gen_var_3::().test_properties(|bs| {
let n = T::from_bits_desc(bs.iter().copied());
assert_eq!(from_bits_desc_alt::(bs.iter().copied()), n);
let leading_falses = bs.iter().take_while(|&&bit| !bit).count();
let trimmed_bits = bs[leading_falses..].to_vec();
assert_eq!(n.to_bits_desc(), trimmed_bits);
});
unsigned_gen_var_5().test_properties(|u| {
assert_eq!(T::from_bits_desc(repeat_n(false, u)), T::ZERO);
});
}
fn from_bits_desc_properties_helper_signed() {
bool_vec_gen_var_4::().test_properties(|bs| {
let n = T::from_bits_desc(bs.iter().copied());
assert_eq!(from_bits_desc_alt::(bs.iter().copied()), n);
let trimmed_bits = if bs.iter().all(|&bit| !bit) {
Vec::new()
} else {
let sign_bits = if bs[0] {
bs.iter().take_while(|&&bit| bit).count()
} else {
bs.iter().take_while(|&&bit| !bit).count()
};
bs[sign_bits - 1..].to_vec()
};
assert_eq!(n.to_bits_desc(), trimmed_bits);
});
unsigned_gen_var_5().test_properties(|u| {
assert_eq!(T::from_bits_desc(repeat_n(false, u)), T::ZERO);
assert_eq!(T::from_bits_desc(repeat_n(true, u + 1)), T::NEGATIVE_ONE);
});
}
#[test]
fn from_bits_desc_properties() {
apply_fn_to_unsigneds!(from_bits_desc_properties_helper_unsigned);
apply_fn_to_signeds!(from_bits_desc_properties_helper_signed);
}