1use super::common::{is_8digits, ByteSlice};
13
14#[derive(Clone)]
15pub(crate) struct Decimal {
16 pub(crate) num_digits: usize,
18 pub(crate) decimal_point: i32,
20 pub(crate) truncated: bool,
22 pub(crate) digits: [u8; Self::MAX_DIGITS],
24}
25
26impl Decimal {
27 const fn default() -> Self {
28 Self {
29 num_digits: 0,
30 decimal_point: 0,
31 truncated: false,
32 digits: [0; Self::MAX_DIGITS],
33 }
34 }
35}
36
37impl Decimal {
38 pub(crate) const MAX_DIGITS: usize = 768;
64 pub(crate) const MAX_DIGITS_WITHOUT_OVERFLOW: usize = 19;
66 pub(crate) const DECIMAL_POINT_RANGE: i32 = 2047;
67
68 pub(crate) fn try_add_digit(&mut self, digit: u8) {
70 if self.num_digits < Self::MAX_DIGITS {
71 self.digits[self.num_digits] = digit;
72 }
73 self.num_digits += 1;
74 }
75
76 pub(crate) fn trim(&mut self) {
78 debug_assert!(self.num_digits <= Self::MAX_DIGITS);
86 while self.num_digits != 0 && self.digits[self.num_digits - 1] == 0 {
87 self.num_digits -= 1;
88 }
89 }
90
91 pub(crate) fn round(&self) -> u64 {
92 if self.num_digits == 0 || self.decimal_point < 0 {
93 return 0;
94 } else if self.decimal_point > 18 {
95 return 0xFFFF_FFFF_FFFF_FFFF_u64;
96 }
97 let dp = self.decimal_point as usize;
98 let mut n = 0_u64;
99 for i in 0..dp {
100 n *= 10;
101 if i < self.num_digits {
102 n += self.digits[i] as u64;
103 }
104 }
105 let mut round_up = false;
106 if dp < self.num_digits {
107 round_up = self.digits[dp] >= 5;
108 if self.digits[dp] == 5 && dp + 1 == self.num_digits {
109 round_up = self.truncated || ((dp != 0) && (1 & self.digits[dp - 1] != 0));
110 }
111 }
112 if round_up {
113 n += 1;
114 }
115 n
116 }
117
118 pub(crate) fn left_shift(&mut self, shift: usize) {
120 if self.num_digits == 0 {
121 return;
122 }
123 let num_new_digits = number_of_digits_decimal_left_shift(self, shift);
124 let mut read_index = self.num_digits;
125 let mut write_index = self.num_digits + num_new_digits;
126 let mut n = 0_u64;
127 while read_index != 0 {
128 read_index -= 1;
129 write_index -= 1;
130 n += (self.digits[read_index] as u64) << shift;
131 let quotient = n / 10;
132 let remainder = n - (10 * quotient);
133 if write_index < Self::MAX_DIGITS {
134 self.digits[write_index] = remainder as u8;
135 } else if remainder > 0 {
136 self.truncated = true;
137 }
138 n = quotient;
139 }
140 while n > 0 {
141 write_index -= 1;
142 let quotient = n / 10;
143 let remainder = n - (10 * quotient);
144 if write_index < Self::MAX_DIGITS {
145 self.digits[write_index] = remainder as u8;
146 } else if remainder > 0 {
147 self.truncated = true;
148 }
149 n = quotient;
150 }
151 self.num_digits += num_new_digits;
152 if self.num_digits > Self::MAX_DIGITS {
153 self.num_digits = Self::MAX_DIGITS;
154 }
155 self.decimal_point += num_new_digits as i32;
156 self.trim();
157 }
158
159 pub(crate) fn right_shift(&mut self, shift: usize) {
161 let mut read_index = 0;
162 let mut write_index = 0;
163 let mut n = 0_u64;
164 while (n >> shift) == 0 {
165 if read_index < self.num_digits {
166 n = (10 * n) + self.digits[read_index] as u64;
167 read_index += 1;
168 } else if n == 0 {
169 return;
170 } else {
171 while (n >> shift) == 0 {
172 n *= 10;
173 read_index += 1;
174 }
175 break;
176 }
177 }
178 self.decimal_point -= read_index as i32 - 1;
179 if self.decimal_point < -Self::DECIMAL_POINT_RANGE {
180 self.num_digits = 0;
182 self.decimal_point = 0;
183 self.truncated = false;
184 return;
185 }
186 let mask = (1_u64 << shift) - 1;
187 while read_index < self.num_digits {
188 let new_digit = (n >> shift) as u8;
189 n = (10 * (n & mask)) + self.digits[read_index] as u64;
190 read_index += 1;
191 self.digits[write_index] = new_digit;
192 write_index += 1;
193 }
194 while n > 0 {
195 let new_digit = (n >> shift) as u8;
196 n = 10 * (n & mask);
197 if write_index < Self::MAX_DIGITS {
198 self.digits[write_index] = new_digit;
199 write_index += 1;
200 } else if new_digit > 0 {
201 self.truncated = true;
202 }
203 }
204 self.num_digits = write_index;
205 self.trim();
206 }
207}
208
209pub(crate) fn parse_decimal(mut s: &[u8]) -> Decimal {
211 let mut d = Decimal::default();
212 let start = s;
213
214 while let Some((&b'0', s_next)) = s.split_first() {
215 s = s_next;
216 }
217
218 s = s.parse_digits(|digit| d.try_add_digit(digit));
219
220 if let Some((b'.', s_next)) = s.split_first() {
221 s = s_next;
222 let first = s;
223 if d.num_digits == 0 {
225 while let Some((&b'0', s_next)) = s.split_first() {
226 s = s_next;
227 }
228 }
229 while s.len() >= 8 && d.num_digits + 8 < Decimal::MAX_DIGITS {
230 let v = s.read_u64le();
231 if !is_8digits(v) {
232 break;
233 }
234 d.digits[d.num_digits..].write_u64le(v - 0x3030_3030_3030_3030);
235 d.num_digits += 8;
236 s = &s[8..];
237 }
238 s = s.parse_digits(|digit| d.try_add_digit(digit));
239 d.decimal_point = s.len() as i32 - first.len() as i32;
240 }
241 if d.num_digits != 0 {
242 let mut n_trailing_zeros = 0;
244 for &c in start[..(start.len() - s.len())].iter().rev() {
245 if c == b'0' {
246 n_trailing_zeros += 1;
247 } else if c != b'.' {
248 break;
249 }
250 }
251 d.decimal_point += n_trailing_zeros as i32;
252 d.num_digits -= n_trailing_zeros;
253 d.decimal_point += d.num_digits as i32;
254 if d.num_digits > Decimal::MAX_DIGITS {
255 d.truncated = true;
256 d.num_digits = Decimal::MAX_DIGITS;
257 }
258 }
259 if let Some((&ch, s_next)) = s.split_first() {
260 if ch == b'e' || ch == b'E' {
261 s = s_next;
262 let mut neg_exp = false;
263 if let Some((&ch, s_next)) = s.split_first() {
264 neg_exp = ch == b'-';
265 if ch == b'-' || ch == b'+' {
266 s = s_next;
267 }
268 }
269 let mut exp_num = 0_i32;
270
271 s.parse_digits(|digit| {
272 if exp_num < 0x10000 {
273 exp_num = 10 * exp_num + digit as i32;
274 }
275 });
276
277 d.decimal_point += if neg_exp { -exp_num } else { exp_num };
278 }
279 }
280 for i in d.num_digits..Decimal::MAX_DIGITS_WITHOUT_OVERFLOW {
281 d.digits[i] = 0;
282 }
283 d
284}
285
286fn number_of_digits_decimal_left_shift(d: &Decimal, mut shift: usize) -> usize {
287 #[rustfmt::skip]
288 static TABLE: [u16; 65] = [
289 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, 0x181D, 0x2024,
290 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067, 0x3073, 0x3080, 0x388E, 0x389C,
291 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF, 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169,
292 0x5180, 0x5998, 0x59B0, 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B,
293 0x72AA, 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC, 0x8C02,
294 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C, 0x051C, 0x051C,
295 ];
296 #[rustfmt::skip]
297 static TABLE_POW5: [u8; 0x051C] = [
298 5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, 9, 0, 6, 2, 5, 1,
299 9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, 1, 2, 5, 2, 4, 4, 1, 4, 0, 6, 2, 5,
300 1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, 0, 3, 5, 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2,
301 5, 1, 5, 2, 5, 8, 7, 8, 9, 0, 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6,
302 9, 7, 2, 6, 5, 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1,
303 6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, 1, 8, 5, 7, 9,
304 1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, 8, 1, 2, 5, 5, 9, 6, 0, 4, 6,
305 4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1,
306 4, 9, 0, 1, 1, 6, 1, 1, 9, 3, 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2,
307 3, 8, 2, 8, 1, 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6,
308 2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5, 7, 4, 6, 1, 5,
309 4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0, 7, 7, 3, 9, 2, 5, 7, 8, 1, 2,
310 5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6, 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5,
311 3, 2, 1, 8, 2, 6, 9, 3, 4, 8, 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4,
312 6, 7, 4, 0, 7, 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6,
313 1, 3, 2, 8, 1, 2, 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, 0, 6, 6, 4, 0,
314 6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, 0, 3, 3, 2, 0, 3, 1, 2, 5, 3,
315 6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, 9, 5, 1, 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8,
316 9, 8, 9, 4, 0, 3, 5, 4, 5, 8, 5, 6, 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4,
317 7, 0, 1, 7, 7, 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5,
318 0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, 3, 7, 3, 6, 7, 5,
319 4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, 6, 2, 5, 1, 1, 3, 6, 8, 6, 8, 3, 7,
320 7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, 3, 7, 9, 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8,
321 8, 6, 0, 8, 0, 8, 0, 1, 4, 8, 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0,
322 9, 4, 3, 0, 4, 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0,
323 8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, 6, 2, 5, 7, 1,
324 0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, 2, 4, 2, 6, 7, 5, 7, 8, 1, 2,
325 5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8,
326 9, 0, 6, 2, 5, 1, 7, 7, 6, 3, 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0,
327 6, 6, 8, 9, 4, 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3,
328 8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8, 5, 0, 0, 6, 2,
329 6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2, 5, 2, 2, 2, 0, 4, 4, 6, 0, 4,
330 9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6, 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1, 1,
331 1, 0, 2, 2, 3, 0, 2, 4, 6, 2, 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8,
332 2, 0, 3, 1, 2, 5, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5,
333 8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, 6, 2, 8, 9, 1,
334 3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, 1, 2, 5, 1, 3, 8, 7, 7, 7, 8,
335 7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, 5, 3, 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0,
336 6, 2, 5, 6, 9, 3, 8, 8, 9, 3, 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2,
337 5, 5, 6, 7, 6, 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1,
338 8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, 1, 7, 3, 4, 7, 2,
339 3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, 4, 4, 8, 1, 3, 9, 1, 9, 0, 6, 7, 3,
340 8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, 7, 3, 7, 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2,
341 2, 4, 0, 6, 9, 5, 9, 5, 3, 3, 6, 9, 1, 4, 0, 6, 2, 5,
342 ];
343
344 shift &= 63;
345 let x_a = TABLE[shift];
346 let x_b = TABLE[shift + 1];
347 let num_new_digits = (x_a >> 11) as usize;
348 let pow5_a = (0x7FF & x_a) as usize;
349 let pow5_b = (0x7FF & x_b) as usize;
350 let pow5 = &TABLE_POW5[pow5_a..];
351 for (i, &p5) in pow5.iter().enumerate().take(pow5_b - pow5_a) {
352 if i >= d.num_digits {
353 return num_new_digits - 1;
354 } else if d.digits[i] == p5 {
355 continue;
356 } else if d.digits[i] < p5 {
357 return num_new_digits - 1;
358 } else {
359 return num_new_digits;
360 }
361 }
362 num_new_digits
363}