use crate::{characters::*, ChineseNumeralBase, MyriadScaleInt, Sign, Signed};
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)]
pub struct MidScaleInt {
pub(super) sign: Sign,
pub(super) data: u128,
}
impl MidScaleInt {
pub fn new_non_pos(abs: u128) -> Self {
if abs == 0 {
Self::default()
} else {
Self {
sign: Sign::Neg,
data: abs,
}
}
}
}
impl ChineseNumeralBase for MidScaleInt {
fn to_chars(&self) -> Vec<NumChar> {
let mut chars = Vec::new();
let mut num = *self.data();
let mut prev_rem = 1000_0000;
for exp in 13..=17 {
let rem = num % 1_0000_0000;
num /= 1_0000_0000;
if rem > 0 {
if !chars.is_empty() && prev_rem < 1000_0000 {
chars.push(NUM_CHARS[0]);
}
if exp > 13 {
chars.push(NUM_CHARS[exp]);
}
let myriad = MyriadScaleInt::from(rem);
let mut node = myriad.to_chars();
chars.append(&mut node);
}
prev_rem = rem;
}
chars
}
fn to_chars_trimmed(&self) -> Vec<NumChar> {
let mut chars = self.to_chars();
let mut data = *self.data();
while data >= 1_0000 {
data /= 1_0000;
}
if data >= 10 && data <= 19 {
let one = chars.pop();
debug_assert_eq!(one, Some(NumChar::One));
}
chars
}
}
#[cfg(feature = "bigint")]
use num_bigint::BigUint;
#[cfg(feature = "bigint")]
use num_integer::Integer;
#[cfg(feature = "bigint")]
use num_traits::{ToPrimitive, Zero};
#[cfg(feature = "bigint")]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Default)]
pub struct MidScaleBigInt {
pub(super) sign: Sign,
pub(super) data: BigUint,
}
#[cfg(feature = "bigint")]
impl MidScaleBigInt {
pub(super) const MAX_ABS_ARR: &'static [u32] = &[
4294967295, 4294967295, 2701131775, 807615852, 3882706566, 3057181734, 745289159,
4056365773, 462339630, 20,
];
pub fn max_value() -> Self {
Self {
sign: Sign::Pos,
data: BigUint::from_slice(Self::MAX_ABS_ARR),
}
}
pub fn min_value() -> Self {
Self {
sign: Sign::Neg,
data: BigUint::from_slice(Self::MAX_ABS_ARR),
}
}
}
#[cfg(feature = "bigint")]
impl ChineseNumeralBase for MidScaleBigInt {
fn to_chars(&self) -> Vec<NumChar> {
let mut chars = Vec::new();
let mut num = self.data().to_owned();
let mut prev_rem = BigUint::new(vec![1000_0000]);
let lim = BigUint::new(vec![1000_0000]);
let div = BigUint::new(vec![1_0000_0000]);
for exp in 13..=23 {
let (_, rem) = num.div_rem(&div);
num /= ÷
if rem > BigUint::zero() {
if !chars.is_empty() && prev_rem < lim {
chars.push(NUM_CHARS[0]);
}
if exp > 13 {
chars.push(NUM_CHARS[exp]);
}
let rem = rem.to_u32().unwrap();
let myriad = MyriadScaleInt::from(rem);
let mut node = myriad.to_chars();
chars.append(&mut node);
}
prev_rem = rem;
}
chars
}
fn to_chars_trimmed(&self) -> Vec<NumChar> {
let mut chars = self.to_chars();
let mut data = self.data().to_owned();
let div = BigUint::new(vec![1_0000]);
let ten = BigUint::new(vec![10]);
let nineteen = BigUint::new(vec![19]);
while data >= div {
data /= ÷
}
if data >= ten && data <= nineteen {
let one = chars.pop();
debug_assert_eq!(one, Some(NumChar::One));
}
chars
}
}