Skip to main content

time/
num_fmt.rs

1//! Formatting utilities for numbers.
2//!
3//! These functions are low-level, but are designed to be _extremely_ fast for their designed use
4//! cases. They have strict requirements, and may not return the most ergonomic types to avoid
5//! unnecessary allocations and copying.
6
7use core::mem::MaybeUninit;
8use core::ops::Deref;
9use core::{ptr, slice};
10
11#[cfg(feature = "formatting")]
12use deranged::ru64;
13use deranged::{ru8, ru16, ru32};
14
15static SINGLE_DIGITS: [u8; 10] = *b"0123456789";
16
17static ZERO_PADDED_PAIRS: [u8; 200] = *b"0001020304050607080910111213141516171819\
18                                         2021222324252627282930313233343536373839\
19                                         4041424344454647484950515253545556575859\
20                                         6061626364656667686970717273747576777879\
21                                         8081828384858687888990919293949596979899";
22
23#[cfg(feature = "formatting")]
24static SPACE_PADDED_PAIRS: [u8; 200] = *b" 0 1 2 3 4 5 6 7 8 910111213141516171819\
25                                          2021222324252627282930313233343536373839\
26                                          4041424344454647484950515253545556575859\
27                                          6061626364656667686970717273747576777879\
28                                          8081828384858687888990919293949596979899";
29
30/// A string type with a maximum length known at compile time, stored on the stack.
31///
32/// Note that while the _maximum_ length is known at compile time, the string may be shorter. This
33/// information is stored inline.
34#[derive(Clone, Copy)]
35pub(crate) struct StackStr<const MAX_LEN: usize> {
36    buf: [MaybeUninit<u8>; MAX_LEN],
37    len: usize,
38}
39
40impl<const MAX_LEN: usize> StackStr<MAX_LEN> {
41    /// # Safety:
42    ///
43    /// - `buf` must be initialized for at least `len` bytes.
44    /// - The first `len` bytes of `buf` must be valid UTF-8.
45    #[inline]
46    pub(crate) const unsafe fn new(buf: [MaybeUninit<u8>; MAX_LEN], len: usize) -> Self {
47        debug_assert!(len <= MAX_LEN);
48        Self { buf, len }
49    }
50}
51
52impl<const MAX_LEN: usize> Deref for StackStr<MAX_LEN> {
53    type Target = str;
54
55    #[inline]
56    fn deref(&self) -> &Self::Target {
57        // Safety: This type can only be constructed when the caller asserts that the buffer is
58        // valid UTF-8 for the first `len` bytes.
59        unsafe { str_from_raw_parts(self.buf.as_ptr().cast(), self.len) }
60    }
61}
62
63/// A string type with a maximum length known at compile time, stored on the stack.
64///
65/// Note that while the _maximum_ length is known at compile time, the string may be shorter. This
66/// information is stored inline.
67#[derive(Clone, Copy)]
68pub(crate) struct StackTrailingStr<const MAX_LEN: usize> {
69    buf: [MaybeUninit<u8>; MAX_LEN],
70    start_index: usize,
71}
72
73impl<const MAX_LEN: usize> StackTrailingStr<MAX_LEN> {
74    /// # Safety:
75    ///
76    /// - The last `MAX_LEN - start_index` bytes of `buf` must be initialized and valid UTF-8.
77    #[inline]
78    pub(crate) const unsafe fn new(buf: [MaybeUninit<u8>; MAX_LEN], start_index: usize) -> Self {
79        debug_assert!(start_index <= MAX_LEN);
80        Self { buf, start_index }
81    }
82
83    /// Return the length of `self` in bytes.
84    #[inline]
85    pub(crate) const fn len(&self) -> usize {
86        let len = MAX_LEN - self.start_index;
87        // Safety: `self.start_index` is an unsigned integer, so `len` cannot be larger than
88        // `MAX_LEN` with the arithmetic above.
89        unsafe { core::hint::assert_unchecked(len <= MAX_LEN) };
90        len
91    }
92}
93
94impl<const MAX_LEN: usize> Deref for StackTrailingStr<MAX_LEN> {
95    type Target = str;
96
97    #[inline]
98    fn deref(&self) -> &Self::Target {
99        // Safety: This type can only be constructed when the caller asserts that the buffer is
100        // valid UTF-8 for the last `len` bytes.
101        unsafe {
102            str_from_raw_parts(
103                self.buf.as_ptr().add(self.start_index).cast(),
104                MAX_LEN - self.start_index,
105            )
106        }
107    }
108}
109
110/// Write a two digit integer to `buf` at `offset` and `offset + 1`.
111///
112/// # Safety
113///
114/// `buf` must be at least `offset + 2` bytes long.
115#[inline]
116const unsafe fn write_two_digits(buf: &mut [MaybeUninit<u8>], offset: usize, value: ru8<0, 99>) {
117    // Safety: `buf` is at least `offset + 2` bytes long.
118    unsafe {
119        ptr::copy_nonoverlapping(
120            two_digits_zero_padded(value).as_ptr().cast(),
121            buf.as_mut_ptr().add(offset),
122            2,
123        );
124    }
125}
126
127/// Write a single digit integer to `buf` at `offset`.
128///
129/// # Safety
130///
131/// `buf` must be at least `offset` bytes long.
132#[inline]
133const unsafe fn write_one_digit(buf: &mut [MaybeUninit<u8>], offset: usize, value: ru8<0, 9>) {
134    // Safety: `buf` is at least `offset` bytes long.
135    unsafe {
136        ptr::copy_nonoverlapping(
137            single_digit(value).as_ptr().cast(),
138            buf.as_mut_ptr().add(offset),
139            1,
140        );
141    }
142}
143
144/// # Safety
145///
146/// - `ptr` must be non-null and point to `len` initialized bytes of UTF-8 data.
147/// - `ptr` is valid for (and not mutated during) lifetime `'a`.
148#[inline]
149pub(crate) const unsafe fn str_from_raw_parts<'a>(ptr: *const u8, len: usize) -> &'a str {
150    // Safety: The caller must ensure that `ptr` is valid for `len` bytes and that the bytes are
151    // valid UTF-8. The caller must also ensure that the lifetime `'a` is valid for the returned
152    // string.
153    unsafe { str::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) }
154}
155
156#[inline]
157const fn div_100(n: ru16<0, 9_999>) -> [ru8<0, 99>; 2] {
158    const EXP: u32 = 19; // 19 is faster or equal to 12 even for 3 digits.
159    const SIG: u32 = (1 << EXP) / 100 + 1;
160
161    let n = n.get();
162
163    let high = (n as u32 * SIG) >> EXP; // value / 100
164    let low = n as u32 - high * 100;
165
166    // Safety: `high` is guaranteed to be less than 100 and `low` is guaranteed to be less than 100
167    // due to the arithmetic above.
168    unsafe {
169        [
170            ru8::new_unchecked(high as u8),
171            ru8::new_unchecked(low as u8),
172        ]
173    }
174}
175
176/// Obtain a string containing a single ASCII digit representing `n`.
177#[inline]
178pub(crate) const fn single_digit(n: ru8<0, 9>) -> &'static str {
179    // Safety: We're staying within the bounds of the array. The array contains only ASCII
180    // characters, so it's valid UTF-8.
181    unsafe { str_from_raw_parts(SINGLE_DIGITS.as_ptr().add(n.get() as usize), 1) }
182}
183
184/// Obtain a string of one or two ASCII digits representing `n`. No leading zeros or spaces are
185/// included.
186#[inline]
187pub(crate) const fn one_to_two_digits_no_padding(n: ru8<0, 99>) -> &'static str {
188    let n = n.get();
189    let is_single_digit = n < 10;
190    // Safety: We're staying within the bounds of the array. The array contains only ASCII
191    // characters, so it's valid UTF-8.
192    unsafe {
193        str_from_raw_parts(
194            ZERO_PADDED_PAIRS
195                .as_ptr()
196                .add((n as usize) * 2 + is_single_digit as usize),
197            2 - is_single_digit as usize,
198        )
199    }
200}
201
202/// Obtain a string of two ASCII digits representing `n`. This includes a leading zero if `n` is
203/// less than 10.
204#[inline]
205pub(crate) const fn two_digits_zero_padded(n: ru8<0, 99>) -> &'static str {
206    // Safety: We're staying within the bounds of the array. The array contains only ASCII
207    // characters, so it's valid UTF-8.
208    unsafe { str_from_raw_parts(ZERO_PADDED_PAIRS.as_ptr().add((n.get() as usize) * 2), 2) }
209}
210
211/// Obtain a string of two ASCII digits representing `n`. This includes a leading space if `n` is
212/// less than 10.
213#[inline]
214#[cfg(feature = "formatting")]
215pub(crate) const fn two_digits_space_padded(n: ru8<0, 99>) -> &'static str {
216    // Safety: We're staying within the bounds of the array. The array contains only ASCII
217    // characters, so it's valid UTF-8.
218    unsafe { str_from_raw_parts(SPACE_PADDED_PAIRS.as_ptr().add((n.get() as usize) * 2), 2) }
219}
220
221/// Obtain two strings of ASCII digits representing `n`. The first string is most significant. No
222/// leading zeros or spaces are included.
223#[inline]
224#[cfg(feature = "formatting")]
225pub(crate) fn one_to_three_digits_no_padding(n: ru16<0, 999>) -> [&'static str; 2] {
226    if let Some(n) = n.narrow::<0, 99>() {
227        crate::hint::cold_path();
228        ["", one_to_two_digits_no_padding(n.into())]
229    } else {
230        three_digits_zero_padded(n)
231    }
232}
233
234/// Obtain two strings of ASCII digits representing `n`. The first string is the most significant.
235/// Leading zeros are included if the number has fewer than 3 digits.
236#[inline]
237#[cfg(feature = "formatting")]
238pub(crate) const fn three_digits_zero_padded(n: ru16<0, 999>) -> [&'static str; 2] {
239    let [high, low] = div_100(n.expand());
240    [
241        // Safety: `high` is guaranteed to be less than 10 due to the range of the input.
242        single_digit(unsafe { high.narrow_unchecked() }),
243        two_digits_zero_padded(low),
244    ]
245}
246
247/// Obtain two strings of ASCII digits representing `n`. The first string is the most significant.
248/// Leading spaces are included if the number has fewer than 3 digits.
249#[inline]
250#[cfg(feature = "formatting")]
251pub(crate) const fn three_digits_space_padded(n: ru16<0, 999>) -> [&'static str; 2] {
252    let [high, low] = div_100(n.expand());
253
254    if let Some(high) = high.narrow::<1, 9>() {
255        [single_digit(high.expand()), two_digits_zero_padded(low)]
256    } else {
257        [" ", two_digits_space_padded(low)]
258    }
259}
260
261/// Obtain two strings of ASCII digits representing `n`. The first string is the most significant.
262/// No leading zeros or spaces are included.
263#[inline]
264#[cfg(feature = "formatting")]
265pub(crate) fn one_to_four_digits_no_padding(n: ru16<0, 9_999>) -> [&'static str; 2] {
266    if let Some(n) = n.narrow::<0, 999>() {
267        crate::hint::cold_path();
268        one_to_three_digits_no_padding(n)
269    } else {
270        four_digits_zero_padded(n)
271    }
272}
273
274/// Obtain two strings of two ASCII digits each representing `n`. The first string is the most
275/// significant. Leading zeros are included if the number has fewer than 4 digits.
276#[inline]
277pub(crate) const fn four_digits_zero_padded(n: ru16<0, 9_999>) -> [&'static str; 2] {
278    let [high, low] = div_100(n);
279    [two_digits_zero_padded(high), two_digits_zero_padded(low)]
280}
281
282/// Obtain two strings of two ASCII digits each representing `n`. The first string is the most
283/// significant. Leading spaces are included if the number has fewer than 4 digits.
284#[inline]
285#[cfg(feature = "formatting")]
286pub(crate) const fn four_digits_space_padded(n: ru16<0, 9_999>) -> [&'static str; 2] {
287    let [high, low] = div_100(n);
288
289    if high.get() == 0 {
290        ["  ", two_digits_space_padded(low)]
291    } else {
292        [two_digits_space_padded(high), two_digits_zero_padded(low)]
293    }
294}
295
296/// Obtain three strings which together represent `n`. The first string is the most significant.
297/// Leading zeros are included if the number has fewer than 4 digits. The first string will be empty
298/// if `n` is less than 10,000.
299#[inline]
300pub(crate) const fn four_to_six_digits(n: ru32<0, 999_999>) -> [&'static str; 3] {
301    let n = n.get();
302
303    let (first_two, remaining) = (n / 10_000, n % 10_000);
304
305    let size = 2 - (first_two < 10) as usize - (first_two == 0) as usize;
306    let offset = first_two as usize * 2 + 2 - size;
307
308    // Safety: `offset` is within the bounds of the array. The array contains only ASCII characters,
309    // so it's valid UTF-8.
310    let first_two = unsafe { str_from_raw_parts(ZERO_PADDED_PAIRS.as_ptr().add(offset), size) };
311    // Safety: `remaining` is guaranteed to be less than 10,000 due to the modulus above.
312    let [second_two, last_two] =
313        four_digits_zero_padded(unsafe { ru16::new_unchecked(remaining as u16) });
314    [first_two, second_two, last_two]
315}
316
317/// Obtain three strings which together represent `n`. The first string is the most significant.
318/// Leading zeros are included if the number has fewer than 5 digits. The first string will be empty
319/// if `n` is less than 10,000.
320#[inline]
321#[cfg(feature = "formatting")]
322pub(crate) const fn five_digits_zero_padded(n: ru32<0, 99_999>) -> [&'static str; 3] {
323    let n = n.get();
324
325    let (first_one, remaining) = (n / 10_000, n % 10_000);
326
327    // Safety: `first_one` is guaranteed to be less than 10 due to the division above.
328    let first_one = single_digit(unsafe { ru8::new_unchecked(first_one as u8) });
329    // Safety: `remaining` is guaranteed to be less than 10,000 due to the modulus above.
330    let [second_two, last_two] =
331        four_digits_zero_padded(unsafe { ru16::new_unchecked(remaining as u16) });
332    [first_one, second_two, last_two]
333}
334
335/// Obtain three strings which together represent `n`. The first string is the most significant.
336/// Leading zeroes are included if the number has fewer than 6 digits.
337#[inline]
338#[cfg(feature = "formatting")]
339pub(crate) const fn six_digits_zero_padded(n: ru32<0, 999_999>) -> [&'static str; 3] {
340    let n = n.get();
341
342    let (first_two, remaining) = (n / 10_000, n % 10_000);
343
344    // Safety: `first_two` is guaranteed to be less than 100 due to the division above.
345    let first_two = two_digits_zero_padded(unsafe { ru8::new_unchecked(first_two as u8) });
346    // Safety: `remaining` is guaranteed to be less than 10,000 due to the modulus above.
347    let [second_two, last_two] =
348        four_digits_zero_padded(unsafe { ru16::new_unchecked(remaining as u16) });
349    [first_two, second_two, last_two]
350}
351
352/// Obtain five strings which together represent `n`, which is a number of nanoseconds.
353///
354/// This value is intended to be used after a decimal point to represent a fractional second. The
355/// first string will always contain exactly one digit; the remaining four will contain two digits
356/// each.
357#[inline]
358pub(crate) const fn subsecond_from_nanos(n: ru32<0, 999_999_999>) -> [&'static str; 5] {
359    let n = n.get();
360    let (digits_1_thru_5, digits_6_thru_9) = (n / 10_000, n % 10_000);
361    let (digit_1, digits_2_thru_5) = (digits_1_thru_5 / 10_000, digits_1_thru_5 % 10_000);
362
363    // Safety: The type of `n` ensures that `n` is less than 1,000,000,000. Combined with the
364    // arithmetic above, this guarantees that all values are in the required ranges.
365    unsafe {
366        let digit_1 = single_digit(ru8::new_unchecked(digit_1 as u8));
367        let [digits_2_and_3, digits_4_and_5] =
368            four_digits_zero_padded(ru16::new_unchecked(digits_2_thru_5 as u16));
369        let [digits_6_and_7, digits_8_and_9] =
370            four_digits_zero_padded(ru16::new_unchecked(digits_6_thru_9 as u16));
371
372        [
373            digit_1,
374            digits_2_and_3,
375            digits_4_and_5,
376            digits_6_and_7,
377            digits_8_and_9,
378        ]
379    }
380}
381
382/// Obtain a string of 1 to 9 ASCII digits representing `n`, which is a number of nanoseconds.
383///
384/// This value is intended to be used after a decimal point to represent a fractional second.
385/// Trailing zeros are truncated, but at least one digit is always present.
386#[inline]
387pub(crate) const fn truncated_subsecond_from_nanos(n: ru32<0, 999_999_999>) -> StackStr<9> {
388    #[repr(C, align(8))]
389    #[derive(Clone, Copy)]
390    struct Digits {
391        _padding: MaybeUninit<[u8; 7]>,
392        digit_1: u8,
393        digits_2_thru_9: [u8; 8],
394    }
395
396    let [
397        digit_1,
398        digits_2_and_3,
399        digits_4_and_5,
400        digits_6_and_7,
401        digits_8_and_9,
402    ] = subsecond_from_nanos(n);
403
404    // Ensure that digits 2 thru 9 are stored as a single array that is 8-aligned. This allows the
405    // conversion to a `u64` to be zero cost, resulting in a nontrivial performance improvement.
406    let buf = Digits {
407        _padding: MaybeUninit::uninit(),
408        digit_1: digit_1.as_bytes()[0],
409        digits_2_thru_9: [
410            digits_2_and_3.as_bytes()[0],
411            digits_2_and_3.as_bytes()[1],
412            digits_4_and_5.as_bytes()[0],
413            digits_4_and_5.as_bytes()[1],
414            digits_6_and_7.as_bytes()[0],
415            digits_6_and_7.as_bytes()[1],
416            digits_8_and_9.as_bytes()[0],
417            digits_8_and_9.as_bytes()[1],
418        ],
419    };
420
421    // By converting the bytes into a single integer, we can effectively perform an equality check
422    // against b'0' for all bytes at once. This is actually faster than using portable SIMD (even
423    // with `-Ctarget-cpu=native`).
424    let bitmask = u64::from_le_bytes(buf.digits_2_thru_9) ^ u64::from_le_bytes([b'0'; 8]);
425    let digits_to_truncate = bitmask.leading_zeros() / 8;
426    let len = 9 - digits_to_truncate as usize;
427
428    // Safety: All bytes are initialized and valid UTF-8, and `len` represents the number of bytes
429    // we wish to display (that is between 1 and 9 inclusive). `Digits` is `#[repr(C)]`, so the
430    // layout is guaranteed.
431    unsafe {
432        StackStr::new(
433            *(&raw const buf)
434                .byte_add(core::mem::offset_of!(Digits, digit_1))
435                .cast(),
436            len,
437        )
438    }
439}
440
441/// Format a `u64` into a string with no padding.
442#[inline]
443pub(crate) const fn u64_pad_none(value: u64) -> StackTrailingStr<20> {
444    let mut bytes = [MaybeUninit::uninit(); 20];
445
446    let mut offset = 20;
447    let mut remain = value;
448
449    while remain > 999 {
450        offset -= 4;
451        let quad = remain % 1_00_00;
452        remain /= 1_00_00;
453        // Safety: `quad` is guaranteed to be less than 10,000 due to the modulus above.
454        let [pair1, pair2] = div_100(unsafe { ru16::new_unchecked(quad as u16) });
455        // Safety: `buf` is at least `offset + 4` bytes long.
456        unsafe {
457            write_two_digits(&mut bytes, offset, pair1);
458            write_two_digits(&mut bytes, offset + 2, pair2);
459        }
460    }
461
462    if remain > 9 {
463        offset -= 2;
464
465        // Safety: `remain` is guaranteed to be less than 10,000 due to the loop above.
466        let [last, pair] = div_100(unsafe { ru16::new_unchecked(remain as u16) });
467        remain = last.get() as u64;
468        // Safety: `buf` is at least `offset + 2` bytes long.
469        unsafe { write_two_digits(&mut bytes, offset, pair) };
470    }
471
472    if remain != 0 || value == 0 {
473        offset -= 1;
474
475        let last = remain as u8 & 15;
476        // Safety: `offset` is known to be in bounds, and the value is known to be less than 10 due
477        // to the conditionals and bitwise AND above.
478        unsafe { write_one_digit(&mut bytes, offset, ru8::new_unchecked(last)) };
479    }
480
481    // Safety: All bytes starting at `offset` are initialized and valid UTF-8.
482    unsafe { StackTrailingStr::new(bytes, offset) }
483}
484
485/// Format a `u128` into a string with no padding.
486#[inline]
487#[cfg(feature = "formatting")]
488pub(crate) const fn u128_pad_none(value: u128) -> StackTrailingStr<39> {
489    let mut bytes = [MaybeUninit::uninit(); 39];
490
491    // Take the 16 least-significant decimals.
492    let (quot_1e16, mod_1e16) = div_rem_1e16(value);
493    let (mut remain, mut offset) = if quot_1e16 == 0 {
494        (mod_1e16.get(), 39)
495    } else {
496        // Write digits at buf[23..39].
497        // Safety: `bytes` is 39 bytes long, so writing at offset 23 for 16 bytes is sound.
498        unsafe { enc_16lsd::<23>(&mut bytes, mod_1e16) };
499
500        // Take another 16 decimals.
501        let (quot2, mod2) = div_rem_1e16(quot_1e16);
502        if quot2 == 0 {
503            (mod2.get(), 23)
504        } else {
505            // Write digits at buf[7..23].
506            // Safety: `bytes` is 39 bytes long, so writing at offset 7 for 16 bytes is sound.
507            unsafe { enc_16lsd::<7>(&mut bytes, mod2) };
508            // Safety: `quot2`` has at most 7 decimals remaining after two 1e16 divisions.
509            (quot2 as u64, 7)
510        }
511    };
512
513    // Format per four digits from the lookup table.
514    while remain > 999 {
515        offset -= 4;
516
517        // pull two pairs
518        let quad = remain % 1_00_00;
519        remain /= 1_00_00;
520        // Safety: `quad` is guaranteed to be less than 10,000 due to the modulus above.
521        let [pair1, pair2] = div_100(unsafe { ru16::new_unchecked(quad as u16) });
522        // Safety: `buf` is at least `offset + 4` bytes long.
523        unsafe {
524            write_two_digits(&mut bytes, offset, pair1);
525            write_two_digits(&mut bytes, offset + 2, pair2);
526        }
527    }
528
529    // Format per two digits from the lookup table.
530    if remain > 9 {
531        offset -= 2;
532
533        // Safety: `remain` is guaranteed to be less than 10,000 due to the loop above.
534        let [last, pair] = div_100(unsafe { ru16::new_unchecked(remain as u16) });
535        remain = last.get() as u64;
536        // Safety: `buf` is at least `offset + 2` bytes long.
537        unsafe { write_two_digits(&mut bytes, offset, pair) };
538    }
539
540    // Format the last remaining digit, if any.
541    if remain != 0 || value == 0 {
542        offset -= 1;
543
544        // Either the compiler sees that remain < 10, or it prevents a boundary check up next.
545        let last = remain as u8 & 15;
546        // Safety: `offset` is known to be in bounds, and the value is known to be less than 10 due
547        // to the conditionals and bitwise AND above.
548        unsafe { write_one_digit(&mut bytes, offset, ru8::new_unchecked(last)) };
549    }
550
551    // Safety: All bytes starting at `offset` are initialized and valid UTF-8.
552    unsafe { StackTrailingStr::new(bytes, offset) }
553}
554
555/// Encodes the 16 least-significant decimals of n into `buf[OFFSET..OFFSET + 16]`.
556///
557/// # Safety
558///
559/// - `buf` must be at least `OFFSET + 16` bytes long.
560#[cfg(feature = "formatting")]
561const unsafe fn enc_16lsd<const OFFSET: usize>(
562    buf: &mut [MaybeUninit<u8>],
563    n: ru64<0, 9999_9999_9999_9999>,
564) {
565    // Consume the least-significant decimals from a working copy.
566    let mut remain = n.get();
567
568    let mut quad_index = 3;
569    while quad_index >= 1 {
570        let quad = remain % 1_00_00;
571        remain /= 1_00_00;
572        // Safety: `quad` is guaranteed to be less than 10,000 due to the modulus above.
573        let [pair1, pair2] = div_100(unsafe { ru16::new_unchecked(quad as u16) });
574        // Safety: `buf` is at least `quad_index * 4 + OFFSET + 4` bytes long.
575        unsafe {
576            write_two_digits(buf, quad_index * 4 + OFFSET, pair1);
577            write_two_digits(buf, quad_index * 4 + OFFSET + 2, pair2);
578        }
579        quad_index -= 1;
580    }
581
582    // Safety: `remain` is guaranteed to be less than 10,000 due the range of `n` and the arithmetic
583    // in the loop above.
584    let [pair1, pair2] = div_100(unsafe { ru16::new_unchecked(remain as u16) });
585    // Safety: `buf` is at least `OFFSET + 4` bytes long.
586    unsafe {
587        write_two_digits(buf, OFFSET, pair1);
588        write_two_digits(buf, OFFSET + 2, pair2);
589    }
590}
591
592// Euclidean division plus remainder with constant 1e16 basically consumes 16
593// decimals from n.
594#[cfg(feature = "formatting")]
595const fn div_rem_1e16(n: u128) -> (u128, ru64<0, 9999_9999_9999_9999>) {
596    const D: u128 = 1_0000_0000_0000_0000;
597    if n < D {
598        // Safety: We just checked that `n` is in range.
599        return (0, unsafe { ru64::new_unchecked(n as u64) });
600    }
601
602    const M_HIGH: u128 = 76_624_777_043_294_442_917_917_351_357_515_459_181;
603    const SH_POST: u8 = 51;
604
605    // n.widening_mul(M_HIGH).1 >> SH_POST
606    let quot = mulhi(n, M_HIGH) >> SH_POST;
607    let rem = n - quot * D;
608    // Safety: The arithmetic above ensures that `rem` is in range.
609    (quot, unsafe { ru64::new_unchecked(rem as u64) })
610}
611
612/// Multiply unsigned 128 bit integers, return upper 128 bits of the result
613#[inline]
614#[cfg(feature = "formatting")]
615const fn mulhi(x: u128, y: u128) -> u128 {
616    let x_lo = x as u64;
617    let x_hi = (x >> 64) as u64;
618    let y_lo = y as u64;
619    let y_hi = (y >> 64) as u64;
620
621    // handle possibility of overflow
622    let carry = (x_lo as u128 * y_lo as u128) >> 64;
623    let m = x_lo as u128 * y_hi as u128 + carry;
624    let high1 = m >> 64;
625
626    let m_lo = m as u64;
627    let high2 = (x_hi as u128 * y_lo as u128 + m_lo as u128) >> 64;
628
629    x_hi as u128 * y_hi as u128 + high1 + high2
630}