1#![cfg(not(feature = "compact"))]
14#![doc(hidden)]
15
16use lexical_util::num::UnsignedInteger;
17
18use crate::digit_count::fast_log2;
19use crate::jeaiii;
20
21#[inline(always)]
30pub fn fast_log10<T: UnsignedInteger>(x: T) -> usize {
31 let log2 = fast_log2(x);
32 (log2 * 1233) >> 12
33}
34
35#[inline(always)]
50pub fn fast_digit_count(x: u32) -> usize {
51 const TABLE: [u64; 32] = [
52 4294967296,
53 8589934582,
54 8589934582,
55 8589934582,
56 12884901788,
57 12884901788,
58 12884901788,
59 17179868184,
60 17179868184,
61 17179868184,
62 21474826480,
63 21474826480,
64 21474826480,
65 21474826480,
66 25769703776,
67 25769703776,
68 25769703776,
69 30063771072,
70 30063771072,
71 30063771072,
72 34349738368,
73 34349738368,
74 34349738368,
75 34349738368,
76 38554705664,
77 38554705664,
78 38554705664,
79 41949672960,
80 41949672960,
81 41949672960,
82 42949672960,
83 42949672960,
84 ];
85 let shift = TABLE[fast_log2(x)];
89 let count = (x as u64 + shift) >> 32;
90 count as usize
91}
92
93#[inline(always)]
102pub fn fallback_digit_count<T: UnsignedInteger>(x: T, table: &[T]) -> usize {
103 let log10 = fast_log10(x);
106 let shift_up = table.get(log10).map_or(false, |&y| x >= y);
107
108 log10 + shift_up as usize + 1
109}
110
111pub unsafe trait DecimalCount: UnsignedInteger {
120 fn decimal_count(self) -> usize;
122}
123
124unsafe impl DecimalCount for u8 {
126 #[inline(always)]
127 fn decimal_count(self) -> usize {
128 fast_digit_count(self as u32)
129 }
130}
131
132unsafe impl DecimalCount for u16 {
134 #[inline(always)]
135 fn decimal_count(self) -> usize {
136 fast_digit_count(self as u32)
137 }
138}
139
140unsafe impl DecimalCount for u32 {
142 #[inline(always)]
143 fn decimal_count(self) -> usize {
144 fast_digit_count(self)
145 }
146}
147
148unsafe impl DecimalCount for u64 {
151 #[inline(always)]
152 fn decimal_count(self) -> usize {
153 const TABLE: [u64; 19] = [
154 10,
155 100,
156 1000,
157 10000,
158 100000,
159 1000000,
160 10000000,
161 100000000,
162 1000000000,
163 10000000000,
164 100000000000,
165 1000000000000,
166 10000000000000,
167 100000000000000,
168 1000000000000000,
169 10000000000000000,
170 100000000000000000,
171 1000000000000000000,
172 10000000000000000000,
173 ];
174 fallback_digit_count(self, &TABLE)
175 }
176}
177
178unsafe impl DecimalCount for u128 {
181 #[inline(always)]
182 fn decimal_count(self) -> usize {
183 const TABLE: [u128; 38] = [
184 10,
185 100,
186 1000,
187 10000,
188 100000,
189 1000000,
190 10000000,
191 100000000,
192 1000000000,
193 10000000000,
194 100000000000,
195 1000000000000,
196 10000000000000,
197 100000000000000,
198 1000000000000000,
199 10000000000000000,
200 100000000000000000,
201 1000000000000000000,
202 10000000000000000000,
203 100000000000000000000,
204 1000000000000000000000,
205 10000000000000000000000,
206 100000000000000000000000,
207 1000000000000000000000000,
208 10000000000000000000000000,
209 100000000000000000000000000,
210 1000000000000000000000000000,
211 10000000000000000000000000000,
212 100000000000000000000000000000,
213 1000000000000000000000000000000,
214 10000000000000000000000000000000,
215 100000000000000000000000000000000,
216 1000000000000000000000000000000000,
217 10000000000000000000000000000000000,
218 100000000000000000000000000000000000,
219 1000000000000000000000000000000000000,
220 10000000000000000000000000000000000000,
221 100000000000000000000000000000000000000,
222 ];
223 fallback_digit_count(self, &TABLE)
224 }
225}
226
227unsafe impl DecimalCount for usize {
229 #[inline(always)]
230 fn decimal_count(self) -> usize {
231 match Self::BITS {
232 8 | 16 | 32 => (self as u32).decimal_count(),
233 64 => (self as u64).decimal_count(),
234 128 => (self as u128).decimal_count(),
235 _ => unimplemented!(),
236 }
237 }
238}
239
240pub trait Decimal: DecimalCount {
242 fn decimal(self, buffer: &mut [u8]) -> usize;
243
244 #[inline(always)]
252 fn decimal_signed(self, buffer: &mut [u8]) -> usize {
253 self.decimal(buffer)
254 }
255}
256
257macro_rules! decimal_impl {
259 ($($t:ty; $f:ident)*) => ($(
260 impl Decimal for $t {
261 #[inline(always)]
262 fn decimal(self, buffer: &mut [u8]) -> usize {
263 jeaiii::$f(self, buffer)
264 }
265 }
266 )*);
267}
268
269decimal_impl! {
270 u8; from_u8
271 u16; from_u16
272 u32; from_u32
273 u128; from_u128
274}
275
276impl Decimal for u64 {
277 #[inline(always)]
278 fn decimal(self, buffer: &mut [u8]) -> usize {
279 jeaiii::from_u64(self, buffer)
280 }
281
282 #[inline(always)]
283 fn decimal_signed(self, buffer: &mut [u8]) -> usize {
284 jeaiii::from_i64(self, buffer)
285 }
286}
287
288impl Decimal for usize {
289 #[inline(always)]
290 fn decimal(self, buffer: &mut [u8]) -> usize {
291 match usize::BITS {
292 8 => (self as u8).decimal(buffer),
293 16 => (self as u16).decimal(buffer),
294 32 => (self as u32).decimal(buffer),
295 64 => (self as u64).decimal(buffer),
296 128 => (self as u128).decimal(buffer),
297 _ => unimplemented!(),
298 }
299 }
300
301 #[inline(always)]
302 fn decimal_signed(self, buffer: &mut [u8]) -> usize {
303 match usize::BITS {
304 8 => (self as u8).decimal_signed(buffer),
305 16 => (self as u16).decimal_signed(buffer),
306 32 => (self as u32).decimal_signed(buffer),
307 64 => (self as u64).decimal_signed(buffer),
308 128 => (self as u128).decimal_signed(buffer),
309 _ => unimplemented!(),
310 }
311 }
312}