use crate::{characters::*, ChineseNumeralBase, ShortScaleInt, Sign, Signed};
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)]
pub struct MyriadScaleInt {
pub(super) sign: Sign,
pub(super) data: u128,
}
impl MyriadScaleInt {
pub fn new_non_pos(abs: u128) -> Self {
if abs == 0 {
Self::default()
} else {
Self {
sign: Sign::Neg,
data: abs,
}
}
}
}
impl ChineseNumeralBase for MyriadScaleInt {
fn to_chars(&self) -> Vec<NumChar> {
let mut chars = Vec::new();
let mut num = *self.data();
let mut prev_rem = 1000;
for exp in 12..=21 {
let rem = (num % 1_0000) as u16;
num /= 1_0000;
if rem > 0 {
if !chars.is_empty() && prev_rem < 1000 {
chars.push(NUM_CHARS[0]);
}
if exp > 12 {
chars.push(NUM_CHARS[exp]);
}
let short = ShortScaleInt::from(rem);
let mut node = short.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 MyriadScaleBigInt {
pub(super) sign: Sign,
pub(super) data: BigUint,
}
#[cfg(feature = "bigint")]
impl MyriadScaleBigInt {
pub(super) const MAX_ABS_ARR: &'static [u32] =
&[4294967295, 2134966271, 2523967787, 239310294, 2938735877];
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 MyriadScaleBigInt {
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]);
let lim = BigUint::new(vec![1000]);
let div = BigUint::new(vec![1_0000]);
for exp in 12..=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 > 12 {
chars.push(NUM_CHARS[exp]);
}
let rem = rem.to_u16().unwrap();
let short = ShortScaleInt::from(rem);
let mut node = short.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
}
}