// 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::Itertools;
use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
use malachite_base::num::conversion::digits::general_digits::unsigned_to_digits_asc_naive;
use malachite_base::num::conversion::traits::{Digits, ExactFrom, SaturatingFrom, WrappingFrom};
use malachite_base::test_util::generators::{
unsigned_gen, unsigned_gen_var_4, unsigned_pair_gen_var_6,
};
use std::panic::catch_unwind;
#[test]
pub fn test_to_digits_asc() {
fn test + PrimitiveUnsigned, U: PrimitiveUnsigned>(x: T, base: U, out: &[U]) {
assert_eq!(x.to_digits_asc(&base), out);
}
test::(0, 64, &[]);
test::(2, 64, &[2]);
test::(123, 8, &[3, 7, 1]);
test::(1000000, 256, &[64, 66, 15]);
test::(1000000, 256, &[64, 66, 15]);
test::(1000, 2, &[0, 0, 0, 1, 0, 1, 1, 1, 1, 1]);
test::(0, 3, &[]);
test::(2, 3, &[2]);
test::(123456, 3, &[0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 2]);
test::(123456, 10, &[6, 5, 4, 3, 2, 1]);
test::(123456, 100, &[56, 34, 12]);
test::(123456, 123, &[87, 19, 8]);
}
fn to_digits_asc_fail_helper + PrimitiveUnsigned, U: PrimitiveUnsigned>() {
assert_panic!(T::exact_from(100).to_digits_asc(&U::ZERO));
assert_panic!(T::exact_from(100).to_digits_asc(&U::ONE));
if T::WIDTH < U::WIDTH {
assert_panic!(T::exact_from(100).to_digits_asc(&U::power_of_2(T::WIDTH)));
}
}
#[test]
fn to_digits_asc_fail() {
apply_fn_to_unsigneds_and_unsigneds!(to_digits_asc_fail_helper);
}
#[test]
pub fn test_to_digits_desc() {
fn test + PrimitiveUnsigned, U: PrimitiveUnsigned>(x: T, base: U, out: &[U]) {
assert_eq!(x.to_digits_desc(&base), out);
}
test::(0, 64, &[]);
test::(2, 64, &[2]);
test::(123, 8, &[1, 7, 3]);
test::(1000000, 256, &[15, 66, 64]);
test::(1000000, 256, &[15, 66, 64]);
test::(1000, 2, &[1, 1, 1, 1, 1, 0, 1, 0, 0, 0]);
test::(0, 3, &[]);
test::(2, 3, &[2]);
test::(123456, 3, &[2, 0, 0, 2, 1, 1, 0, 0, 1, 1, 0]);
test::(123456, 10, &[1, 2, 3, 4, 5, 6]);
test::(123456, 100, &[12, 34, 56]);
test::(123456, 123, &[8, 19, 87]);
}
fn to_digits_desc_fail_helper + PrimitiveUnsigned, U: PrimitiveUnsigned>() {
assert_panic!(T::exact_from(100).to_digits_desc(&U::ZERO));
assert_panic!(T::exact_from(100).to_digits_desc(&U::ONE));
if T::WIDTH < U::WIDTH {
assert_panic!(T::exact_from(100).to_digits_desc(&U::power_of_2(T::WIDTH)));
}
}
#[test]
fn to_digits_desc_fail() {
apply_fn_to_unsigneds_and_unsigneds!(to_digits_desc_fail_helper);
}
fn to_digits_asc_helper<
T: Digits + ExactFrom + PrimitiveUnsigned,
U: PrimitiveUnsigned + SaturatingFrom + WrappingFrom,
>() {
unsigned_pair_gen_var_6::().test_properties(|(u, base)| {
let digits = u.to_digits_asc(&base);
assert_eq!(unsigned_to_digits_asc_naive(&u, base), digits);
assert_eq!(
T::from_digits_asc(&base, digits.iter().copied()).unwrap(),
u
);
if u != T::ZERO {
assert_ne!(*digits.last().unwrap(), U::ZERO);
}
assert_eq!(
digits.iter().copied().rev().collect_vec(),
u.to_digits_desc(&base)
);
if u != T::ZERO {
assert_eq!(
u64::exact_from(digits.len()),
u.floor_log_base(T::exact_from(base)) + 1
);
}
assert!(digits.iter().all(|&digit| digit <= base));
});
unsigned_gen::().test_properties(|u| {
assert_eq!(
u.to_digits_asc(&U::TWO)
.into_iter()
.map(|digit| digit == U::ONE)
.collect_vec(),
u.to_bits_asc()
);
});
unsigned_gen_var_4::().test_properties(|base| {
assert!(T::ZERO.to_digits_asc(&base).is_empty());
});
}
#[test]
fn to_digits_asc_properties() {
apply_fn_to_unsigneds_and_unsigneds!(to_digits_asc_helper);
}
fn to_digits_desc_helper<
T: Digits + ExactFrom + PrimitiveUnsigned,
U: PrimitiveUnsigned + SaturatingFrom,
>() {
unsigned_pair_gen_var_6::().test_properties(|(u, base)| {
let digits = u.to_digits_desc(&base);
assert_eq!(
T::from_digits_desc(&base, digits.iter().copied()).unwrap(),
u
);
if u != T::ZERO {
assert_ne!(digits[0], U::ZERO);
}
assert_eq!(
digits.iter().copied().rev().collect_vec(),
u.to_digits_asc(&base)
);
if u != T::ZERO {
assert_eq!(
u64::exact_from(digits.len()),
u.floor_log_base(T::exact_from(base)) + 1
);
}
assert!(digits.iter().all(|&digit| digit <= base));
});
unsigned_gen::().test_properties(|u| {
assert_eq!(
u.to_digits_desc(&U::TWO)
.into_iter()
.map(|digit| digit == U::ONE)
.collect_vec(),
u.to_bits_desc()
);
});
unsigned_gen_var_4::().test_properties(|base| {
assert!(T::ZERO.to_digits_desc(&base).is_empty());
});
}
#[test]
fn to_digits_desc_properties() {
apply_fn_to_unsigneds_and_unsigneds!(to_digits_desc_helper);
}