use crate::natural::InnerNatural::{Large, Small};
use crate::platform::Limb;
#[cfg(feature = "doc-images")]
use embed_doc_image::embed_doc_image;
use malachite_base::comparison::traits::Min;
use malachite_base::named::Named;
#[cfg(feature = "float_helpers")]
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::traits::{One, Two, Zero};
use malachite_base::slices::slice_trailing_zeros;
#[cfg_attr(
feature = "doc-images",
embed_doc_image("natural-mem-layout", "images/natural-mem-layout.svg")
)]
#[derive(Clone, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(
feature = "serde",
serde(try_from = "SerdeNatural", into = "SerdeNatural")
)]
pub struct Natural(pub(crate) InnerNatural);
#[derive(Clone, Eq, Hash, PartialEq)]
pub(crate) enum InnerNatural {
Small(Limb),
Large(Vec<Limb>),
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub(crate) struct SerdeNatural(String);
impl Natural {
fn demote_if_small(&mut self) {
if let Natural(Large(ref limbs)) = self {
match limbs.len() {
0 => *self = Natural::ZERO,
1 => *self = Natural(Small(limbs[0])),
_ => {}
}
}
}
pub(crate) fn promote_in_place(&mut self) -> &mut Vec<Limb> {
if let Natural(Small(x)) = self {
*self = Natural(Large(vec![*x]));
}
if let Natural(Large(ref mut xs)) = self {
xs
} else {
unreachable!();
}
}
pub(crate) fn trim(&mut self) {
if let Natural(Large(ref mut limbs)) = *self {
let trailing_zero_count = slice_trailing_zeros(limbs);
if trailing_zero_count != 0 {
let len = limbs.len();
limbs.truncate(len - trailing_zero_count);
}
}
self.demote_if_small();
}
#[cfg(feature = "test_build")]
pub fn is_valid(&self) -> bool {
match *self {
Natural(Small(_)) => true,
Natural(Large(ref xs)) => xs.len() > 1 && *xs.last().unwrap() != 0,
}
}
}
impl Zero for Natural {
const ZERO: Natural = Natural(Small(0));
}
impl One for Natural {
const ONE: Natural = Natural(Small(1));
}
impl Two for Natural {
const TWO: Natural = Natural(Small(2));
}
impl Min for Natural {
const MIN: Natural = Natural::ZERO;
}
#[cfg(feature = "float_helpers")]
impl Natural {
pub const HIGH_BIT: Natural = Natural(Small(1 << (Limb::WIDTH - 1)));
}
impl Default for Natural {
fn default() -> Natural {
Natural::ZERO
}
}
impl_named!(Natural);
pub mod arithmetic;
pub mod comparison;
pub mod conversion;
pub mod exhaustive;
pub mod factorization;
pub mod logic;
#[cfg(feature = "random")]
pub mod random;