chinese_numerals/
midscale.rs1use crate::{characters::*, ChineseNumeralBase, MyriadScaleInt, Sign, Signed};
2
3#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)]
7pub struct MidScaleInt {
8 pub(super) sign: Sign,
9 pub(super) data: u128,
10}
11
12impl MidScaleInt {
13 pub fn new_non_pos(abs: u128) -> Self {
17 if abs == 0 {
18 Self::default()
19 } else {
20 Self {
21 sign: Sign::Neg,
22 data: abs,
23 }
24 }
25 }
26}
27
28impl ChineseNumeralBase for MidScaleInt {
29 fn to_chars(&self) -> Vec<NumChar> {
30 let mut chars = Vec::new();
31 let mut num = *self.data();
32 let mut prev_rem = 1000_0000;
33
34 for exp in 13..=17 {
36 let rem = num % 1_0000_0000;
37 num /= 1_0000_0000;
38
39 if rem > 0 {
40 if !chars.is_empty() && prev_rem < 1000_0000 {
41 chars.push(NUM_CHARS[0]);
42 }
43 if exp > 13 {
44 chars.push(NUM_CHARS[exp]);
45 }
46 let myriad = MyriadScaleInt::from(rem);
47 let mut node = myriad.to_chars();
48 chars.append(&mut node);
49 }
50 prev_rem = rem;
51 }
52 chars
53 }
54
55 fn to_chars_trimmed(&self) -> Vec<NumChar> {
56 let mut chars = self.to_chars();
57 let mut data = *self.data();
58 while data >= 1_0000 {
59 data /= 1_0000;
60 }
61 if data >= 10 && data <= 19 {
62 let one = chars.pop();
63 debug_assert_eq!(one, Some(NumChar::One));
64 }
65 chars
66 }
67}
68
69#[cfg(feature = "bigint")]
70use num_bigint::BigUint;
71#[cfg(feature = "bigint")]
72use num_integer::Integer;
73#[cfg(feature = "bigint")]
74use num_traits::{ToPrimitive, Zero};
75
76#[cfg(feature = "bigint")]
80#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Default)]
81pub struct MidScaleBigInt {
82 pub(super) sign: Sign,
83 pub(super) data: BigUint,
84}
85
86#[cfg(feature = "bigint")]
87impl MidScaleBigInt {
88 pub(super) const MAX_ABS_ARR: &'static [u32] = &[
89 4294967295, 4294967295, 2701131775, 807615852, 3882706566, 3057181734, 745289159,
90 4056365773, 462339630, 20,
91 ];
92
93 pub fn max_value() -> Self {
95 Self {
96 sign: Sign::Pos,
97 data: BigUint::from_slice(Self::MAX_ABS_ARR),
98 }
99 }
100
101 pub fn min_value() -> Self {
103 Self {
104 sign: Sign::Neg,
105 data: BigUint::from_slice(Self::MAX_ABS_ARR),
106 }
107 }
108}
109
110#[cfg(feature = "bigint")]
111impl ChineseNumeralBase for MidScaleBigInt {
112 fn to_chars(&self) -> Vec<NumChar> {
113 let mut chars = Vec::new();
114 let mut num = self.data().to_owned();
115 let mut prev_rem = BigUint::new(vec![1000_0000]);
116 let lim = BigUint::new(vec![1000_0000]);
117 let div = BigUint::new(vec![1_0000_0000]);
118
119 for exp in 13..=23 {
120 let (_, rem) = num.div_rem(&div);
121 num /= ÷
122
123 if rem > BigUint::zero() {
124 if !chars.is_empty() && prev_rem < lim {
125 chars.push(NUM_CHARS[0]);
126 }
127 if exp > 13 {
128 chars.push(NUM_CHARS[exp]);
129 }
130 let rem = rem.to_u32().unwrap();
131 let myriad = MyriadScaleInt::from(rem);
132 let mut node = myriad.to_chars();
133 chars.append(&mut node);
134 }
135 prev_rem = rem;
136 }
137 chars
138 }
139
140 fn to_chars_trimmed(&self) -> Vec<NumChar> {
141 let mut chars = self.to_chars();
142 let mut data = self.data().to_owned();
143 let div = BigUint::new(vec![1_0000]);
144 let ten = BigUint::new(vec![10]);
145 let nineteen = BigUint::new(vec![19]);
146 while data >= div {
147 data /= ÷
148 }
149 if data >= ten && data <= nineteen {
150 let one = chars.pop();
151 debug_assert_eq!(one, Some(NumChar::One));
152 }
153 chars
154 }
155}