chinese_numerals/
longscale.rs

1use crate::{characters::*, ChineseNumeralBase, MidScaleInt, Sign, Signed};
2
3/// Long scale integers (上数).
4///
5/// 「上数者,数穷则变。若言万万曰亿,亿亿曰兆、兆兆曰京也。」
6#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)]
7pub struct LongScaleInt {
8    pub(super) sign: Sign,
9    pub(super) data: u128,
10}
11
12impl LongScaleInt {
13    /// Generates a new non-positive long scale integer from given absolute value.
14    ///
15    /// There is no way to generate Chinese numerals by `From` trait from negative primitive numbers less than [`i128::MIN`]. This associated function provides a way to generate them from the given absolute value less than or equal to [`u128::MAX`]. This crate also provides struct [`LongScaleBigInt`] for integers with absolute value larger than `u128::MAX`.
16    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 LongScaleInt {
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_0000_0000;
33
34        // u128 uses up to NUM_CHARS[16] = Jing (京) for long scale numerals
35        for exp in 14..=16 {
36            let rem = num % 1_0000_0000_0000_0000;
37            num /= 1_0000_0000_0000_0000;
38
39            if rem > 0 {
40                if !chars.is_empty() && prev_rem < 1000_0000_0000_0000 {
41                    chars.push(NUM_CHARS[0]);
42                }
43                if exp > 14 {
44                    chars.push(NUM_CHARS[exp]);
45                }
46                let mid = MidScaleInt::from(rem);
47                let mut node = mid.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/// Long scale big integers (上数).
77///
78/// Use it by turning on feature "bigint". It uses [`BigUint`](num_bigint::BigUint) to store the absolute value. Therefore, all integers that can be expressed in long scale are included.
79#[cfg(feature = "bigint")]
80#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Default)]
81pub struct LongScaleBigInt {
82    pub(super) sign: Sign,
83    pub(super) data: BigUint,
84}
85
86#[cfg(feature = "bigint")]
87impl LongScaleBigInt {
88    pub(super) const MAX_ABS_ARR: &'static [u32] = &[
89        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
90        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
91        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
92        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
93        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
94        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
95        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
96        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
97        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
98        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
99        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
100        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
101        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
102        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
103        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
104        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
105        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
106        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
107        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
108        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
109        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
110        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
111        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
112        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
113        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
114        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
115        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
116        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
117        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
118        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
119        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
120        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
121        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
122        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
123        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
124        4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295,
125        4294967295, 4294967295, 4294967295, 4294967295, 1691320320, 2671006246, 1682531301,
126        2072858707, 1240508969, 3108358191, 1125119096, 2470144952, 1610099978, 1690632660,
127        1941696884, 2663506355, 1006364675, 3909158537, 4147711374, 1072663936, 4078768933,
128        745751659, 4123687570, 471458681, 655028926, 4113407388, 3945524552, 985625313, 1254424514,
129        2127508744, 570530434, 945388122, 3194649404, 2589065070, 2731705399, 202030749,
130        2090780394, 3348662271, 1481754777, 1130635472, 4025144705, 1924486271, 2578567861,
131        125491448, 1558036315, 994248173, 3817216711, 763950077, 1030439870, 959586474, 3845661701,
132        483795093, 1637944470, 2275463649, 3398804829, 1758016486, 2665513698, 2004912571,
133        1094885097, 4223064276, 3307819021, 651121777, 1757003305, 3603542336, 129917786,
134        2215974994, 3042386306, 2205352757, 3944939700, 3710987569, 97967515, 1217242524,
135        930630949, 3660328512, 1787663098, 1784141600, 2500542892, 4034561586, 3444961378,
136        785043562, 3869499367, 885623728, 2625011087, 3053789617, 1965731793, 3900511934,
137        2648823592, 3851062028, 3321968688, 799195417, 1011847510, 1369129160, 1348009103,
138        2876796955, 2915408967, 3305284948, 263399535, 1715990604, 2645821294, 1587844552,
139        2624912049, 3035631499, 2306636348, 3499275462, 675152704, 854794152, 4004972748,
140        1739996642, 1333476491, 4012621867, 3658792931, 3297985728, 2864481726, 3066357406,
141        785287846, 1671499798, 433044045, 1919608025, 264833858, 3999983367, 1116778570,
142        1301982149, 4213901070, 4081649357, 536169226, 1389008649, 188923873, 373495152,
143        2551132278, 1800758715, 3951840330, 2632334454, 3118778225, 1034046547, 1862428410,
144        3037609062, 1994608505, 29051798, 2571685694, 264151332, 2260643090, 2717535964,
145        3508441116, 3283713017, 1903365635, 923575694, 1219598101, 2288281570, 3676533911,
146        1014136356, 555142354, 2389170030, 4185108175, 884862419, 836141292, 2957159173,
147        1997444768, 4233903127, 2876184692, 3089125070, 1480848293, 1097600237, 299700527,
148        2507669891, 2982628312, 2114881043, 2529576251, 2812279824, 2987750993, 4241938954,
149        2204775591, 1037094060, 829315638, 1231047149, 52608178, 3735136637, 3455232602, 962039123,
150        488286513, 50685385, 3516451821, 843975207, 1572355722, 675489076, 2428445672, 1555117248,
151        3708476086, 10375249, 4172112346, 2117510871, 2227658327, 3187664554, 3050656558,
152        328034318, 3179601324, 1247769761, 3439263953, 1431538938, 2962525068, 1213366289,
153        3813013550, 2651093719, 1860661503, 3933716208, 264320617, 789980519, 2257856172,
154        102000748, 977269860, 1113845122, 3008928583, 1461738106, 557786285, 2926560363,
155        1038106190, 3643478847, 828004507, 457818698, 1933056971, 373408056, 2076808229,
156        3160935130, 2781854874, 2519636100, 177606000, 4237103862, 3977834316, 1621936232,
157        2599050516, 319893558, 3343370366, 765044144, 976657331, 7026264, 294277429, 3829376742,
158        3029627280, 2705178718, 3614653880, 230519152, 3288033233, 293525479, 3805751881,
159        3227511198, 2520308544, 3648103003, 1111086184, 437622105, 2232033852, 3239146386,
160        584244184, 1450926016, 2462430443, 3226534010, 298582169, 4214576928, 1762099469,
161        964985185, 1585788148, 1641127666, 787006566, 2315956284, 3258232694, 2275058964,
162        2541003317, 1508235863, 2613339827, 4080647514, 1152057965, 3149266279, 731345410,
163        914737650, 65395712, 1884566942, 1379520432, 2611027720, 4163073378, 2619704967,
164        2746552541, 1388822415, 3005141199, 843440249, 4288674003, 3136174279, 4051522914,
165        4144149433, 3427566947, 3419023197, 3758479825, 3893877676, 96899594, 1657725776,
166        253618880, 434129337, 1499045748, 2996992534, 4036042074, 2110713869, 906222950, 928326225,
167        2541827893, 1604330202, 226792470, 4022228930, 815850898, 1466012310, 3377712199,
168        292769859, 2822055597, 3225701344, 3052947004, 385831222, 705324593, 4030158636,
169        3540280538, 2982120874, 2136414455, 255762046, 3852783591, 3262064164, 2358991588,
170        3756586117, 4143612643, 3326743817, 2897365738, 807711264, 3719310016, 3721264861,
171        3627337076, 944539331, 3640975513, 3712525681, 1162911839, 2008243316, 2179489649,
172        2867584109, 261861553, 3570253908, 2062868357, 2220328623, 3857004679, 3744109002,
173        4138041873, 1451860932, 2364975637, 2802161722, 2680106834, 753401584, 1223182946,
174        1245401957, 4163377735, 3565815922, 2216942838, 4036140094, 71979081, 3924559643,
175        400477238, 551750683, 1174153235, 859969898, 1185921017, 1711399735, 812991545, 4051735761,
176        3549118738, 1631653329, 3631835958, 3648867800, 1206500363, 2155893137, 361030362,
177        3454286017, 2505909489, 1083595169, 453595313, 1510564703, 1706163902, 1632924345,
178        1381875722, 1661526119, 1082778324, 3571910052, 1140625929, 851544870, 1145546234,
179        2938573139, 907528924, 1304752338, 1764668294, 1788942063, 1700368828, 104979467,
180        1413911959, 3327497828, 1956384744, 1272712474, 2815637534, 3307809377, 1320574940,
181        1111968962, 4073107827, 434096622, 169451929, 3201183459, 3331028877, 2852366972,
182        3369830128, 2924794558, 3106537952, 3739481231, 1612955817, 4138608722, 2721281595,
183        2755775390, 843505117, 982234295, 1157276611, 814674632, 4246504726, 3532006708, 992340967,
184        1647538031, 204696133, 193866982, 3899126129, 300851698, 1379496684, 1759463683,
185        1354782756, 1374637239, 3410883240, 1073406229, 3038431791, 1053909855, 3607043270,
186        173719711, 3733903830, 171820911, 1573050589, 932781534, 4183534770, 2158849555, 372245998,
187        3573073830, 841339264, 2759200520, 1610547277, 2603293319, 3890906486, 1557138278,
188        3964109906, 677238797, 537994297, 1124184993, 4287078344, 4207654540, 2943022776,
189        2977947524, 3255359985, 4098397558, 2274666217, 2915862060, 243524940, 2467726756,
190        2869020032, 507521339, 3403121914, 522051455, 1803903108, 3471254194, 473535371,
191        1948602036, 3352095732, 3116527002, 1795743673, 775867940, 2551469548, 3757442064,
192        3162525227, 3765412747, 3040105484, 1927625810, 48214767, 2997207130, 1342349989,
193        2536583992, 1501320191, 3592287317, 887432730, 967585477, 3334212779, 948663609,
194        1064513472, 15386372, 2465931737, 3230242590, 3036652803, 2063155087, 1927500726,
195        2821790499, 2187774383, 501520074, 3688568496, 3606711121, 2576459247, 3176542345,
196        378322447, 156541411, 1400607301, 1406179107, 677848877, 2253753529, 193196070, 4207435024,
197        4166396241, 509467541, 2906024136, 1221753746, 3375413222, 431327897, 2749265123,
198        2848827671, 3412997614, 2051920238, 1283516885, 1300498239, 1957256104, 2634010560,
199        3531900395, 360276850, 1461184973, 2012063967, 2873572430, 2914608609, 4289554777,
200        1539331673, 1859532928, 4213441063, 538215691, 3512720863, 4258743698, 3040408445,
201        982396546, 343095663, 4138069496, 1021581857, 214185242, 1968079460, 2864275059,
202        3347192726, 4096783459, 3259169450, 3707808869, 142485006, 399610869, 230556456,
203        2219467721, 4191227798, 2242548189, 3136366572, 179755707, 3464881829, 452317775,
204        3887426070, 3446430233, 1473370015, 1576807208, 3964523248, 419325089, 2373067114,
205        1596072055, 1928415752, 3635452689, 1005598891, 3335462724, 3290848636, 3669078247,
206        1178176812, 2110774376, 3068593619, 1253036518, 908857731, 3631223047, 4138506423,
207        2903592318, 3596915748, 3289036113, 3721512676, 2704409359, 3386016968, 3676268074,
208        2185259502, 1096257611, 3360076717, 3548676554, 170167319, 3360064287, 3899940843, 9640,
209    ];
210
211    /// The maximum integer can be expressed in long scale.
212    pub fn max_value() -> Self {
213        Self {
214            sign: Sign::Pos,
215            data: BigUint::from_slice(Self::MAX_ABS_ARR),
216        }
217    }
218
219    /// The minimum integer can be expressed in long scale.
220    pub fn min_value() -> Self {
221        Self {
222            sign: Sign::Neg,
223            data: BigUint::from_slice(Self::MAX_ABS_ARR),
224        }
225    }
226}
227
228#[cfg(feature = "bigint")]
229impl ChineseNumeralBase for LongScaleBigInt {
230    fn to_chars(&self) -> Vec<NumChar> {
231        let mut chars = Vec::new();
232        let mut num = self.data().to_owned();
233        // 1000_0000_0000_0000
234        let mut prev_rem = BigUint::new(vec![2764472320, 232830]);
235        let mut lim = BigUint::new(vec![2764472320, 232830]);
236        // 1_0000_0000_0000_0000
237        let mut div = BigUint::new(vec![1874919424, 2328306]);
238        let ten = BigUint::new(vec![10]);
239
240        for exp in 14..=23 {
241            let (_, rem) = num.div_rem(&div);
242            num /= &div;
243
244            if rem > BigUint::zero() {
245                if !chars.is_empty() && prev_rem < lim {
246                    chars.push(NUM_CHARS[0]);
247                }
248                if exp > 14 {
249                    chars.push(NUM_CHARS[exp]);
250                }
251                let mut node = if exp <= 15 {
252                    let rem = rem.to_u64().unwrap();
253                    let mid = MidScaleInt::from(rem);
254                    mid.to_chars()
255                } else {
256                    let long = Self::try_from(&rem).unwrap();
257                    long.to_chars()
258                };
259                chars.append(&mut node);
260            }
261            prev_rem = rem;
262            if exp > 14 {
263                prev_rem *= &div;
264                div = &div * &div;
265                lim = &div / &ten;
266            }
267        }
268        chars
269    }
270
271    fn to_chars_trimmed(&self) -> Vec<NumChar> {
272        let mut chars = self.to_chars();
273        let mut data = self.data().to_owned();
274        let div = BigUint::new(vec![1_0000]);
275        let ten = BigUint::new(vec![10]);
276        let nineteen = BigUint::new(vec![19]);
277        while data >= div {
278            data /= &div;
279        }
280        if data >= ten && data <= nineteen {
281            let one = chars.pop();
282            debug_assert_eq!(one, Some(NumChar::One));
283        }
284        chars
285    }
286}