a/math/numbers/radix.rs
1//! Numbers as text in a radix from 2 to 36: [`Number::to_str_radix`], [`Number::from_str_radix`],
2//! and the formatting traits `Display` (decimal), `LowerHex`, `UpperHex`, `Octal` and `Binary`.
3//!
4//! The text is the sign and the digits of the magnitude, the most significant first, with `-` for
5//! a negative number and nothing for the others: `-255` is `-ff` in hexadecimal, not the two's
6//! complement that the formatting of a primitive integer gives. Digits above 9 are the letters,
7//! lower-case when written, either case when read.
8//!
9//! In a radix that is a power of two, each digit is a group of bits of the magnitude, and the
10//! text is written or read in one pass over the bytes, where they are: hexadecimal two digits a
11//! byte from a table, binary eight a byte spread by a multiplication, the others in groups of
12//! bytes. In another radix, the magnitude goes through the largest power `b` of the radix that
13//! fits in a limb, `10^19` for decimal, whose remainders are blocks of digits.
14//!
15//! Written, a short magnitude is divided by `b` again and again, limb by limb, with the
16//! reciprocal of `b` (see [`Divisor`]). Each limb of a division waits for the remainder of the
17//! limb above it, about ten cycles, and a division waits for the quotient of the one before it;
18//! but the next division can start on the top limb of that quotient as soon as it is known, so
19//! the divisions run in groups of up to [`PASSES`], each a limb behind the one before it, and the
20//! core overlaps their chains. The blocks of decimal digits are made eight digits at a time in the
21//! lanes of a `u64`, by multiplications, with no division. A long magnitude is split by divide
22//! and conquer, divided by `b^(2^i)` for the largest `i` that halves it, and the quotient and the
23//! remainder written the same way, the remainder with as many digits as `b^(2^i)` has places,
24//! zeros at the front. Up to two limbs of decimal take a path of their own, in registers.
25//!
26//! Read, decimal digits are checked and turned into values eight at a time in the lanes of a
27//! `u64`, other radices a digit at a time; up to 38 decimal digits are read into a `u128`, and the
28//! blocks of longer text multiplied in, `x b + v`, a pass over the limbs each, in place. The
29//! passes run in waves as the divisions do, [`READ_PASSES`] at a time. Long text is split in
30//! halves, the upper one multiplied by the power of `b` of the lower one's places and the lower
31//! one added. The powers of divide and conquer, both ways, drop their zero bytes at the bottom
32//! (`10^19` is `5^19 2^19`, so a third of the bytes of its powers are zeros), and the part of a
33//! number below them is set aside instead of divided or multiplied.
34
35use super::add::{read, read_small, write};
36use super::div::{divide_2by1, reciprocal};
37use super::mul::{Operand, Product, to_limbs};
38use super::{ByteOrder, Divisor, Number};
39use core::fmt;
40use core::mem::MaybeUninit;
41
42/// The digits of the radices up to 36.
43const DIGITS: &[u8; 36] = b"0123456789abcdefghijklmnopqrstuvwxyz";
44
45/// From this many limbs, a magnitude is written by divide and conquer. Measured on an Apple M4
46/// Max in decimal, 80 took at most 5.5% longer than the best of 40, 64, 80, 100 and 150 from 384
47/// bytes to 4 KiB, where 64 took up to 20% longer (at 512 bytes), 100 up to 10% (1.5 KiB), 40 36%
48/// (384 bytes) and 150 16% (2 KiB). It weighs the waves of divisions against the division of a
49/// long magnitude by a power: when the division gets faster, it falls.
50const WRITE_SPLIT: usize = 80;
51
52/// From this many blocks of text, it is read by divide and conquer. Measured on an Apple M4 Max in
53/// decimal, 220 took at most 7% longer than the best of 160, 220 and 300 from 1 to 64 KiB, the
54/// others up to 14% longer at some length; 100 took 33% longer for 1 KiB, and 600 15% to 35%
55/// longer from 3 to 12 KiB. It weighs the waves of passes against the products of halves, by
56/// Karatsuba's method from 24 limbs: when the multiplication gets faster, it falls.
57const READ_SPLIT: usize = 220;
58
59/// The most divisions by `b` that run at once when a magnitude is written: see [`divide_blocks`].
60/// Measured on an Apple M4 Max in decimal with one size of group for every length, 6 and 8 were
61/// within 4% of each other from 128 to 256 bytes, and up to 12% faster than 4, which was the best
62/// for 3 to 8 limbs, as smaller groups waste fewer divisions above the top; 2 was slower from 24
63/// bytes. So the groups shrink with the limbs left.
64const PASSES: usize = 8;
65
66/// The largest power of ten in a limb, `10^19`, whose remainders are the blocks of decimal digits.
67/// Its top bit is set, so it needs no shift to divide by.
68const TEN_19: u64 = 10_000_000_000_000_000_000;
69
70/// The reciprocal of [`TEN_19`], `floor((B^2 - 1) / 10^19) - B`, as [`reciprocal`] computes it.
71const TEN_19_INVERSE: u64 = (u128::MAX / TEN_19 as u128 - (1 << 64)) as u64;
72
73/// Text of up to this many digits is written in a buffer on the stack by the formatting traits.
74const STACK_TEXT: usize = 160;
75
76/// Text of up to this many blocks is read into limbs on the stack.
77const STACK_BLOCKS: usize = 64;
78
79/// The blocks multiplied in at once when text is read: see [`mul_add_group`]. Measured on an Apple
80/// M4 Max for 1 to 4 KiB of decimal text, 6 and 8 took 0.83 cycles a limb a block, 4 0.88 and 2
81/// 1.2, against 1.24 by a pass of the multiplication's kernel and an addition of the block.
82const READ_PASSES: usize = 6;
83
84/// From this many limbs, blocks are multiplied in [`READ_PASSES`] at a time: below, the waves
85/// that start and end a group outweigh the passes.
86const READ_WAVES: usize = 2;
87
88/// The largest power of `radix` that fits in a limb, `b = radix^k`, and its exponent `k`: the
89/// places of the blocks of digits.
90fn block(radix: u32) -> (u64, usize) {
91 let (mut b, mut k) = (u64::from(radix), 1);
92 while let Some(next) = b.checked_mul(u64::from(radix)) {
93 b = next;
94 k += 1;
95 }
96 (b, k)
97}
98
99/// Panics for a radix outside `2..=36`, as the primitive integers' `from_str_radix` does.
100#[track_caller]
101fn check_radix(radix: u32) {
102 assert!(
103 (2..=36).contains(&radix),
104 "from_str_radix_int: must lie in the range `[2, 36]` - found {radix}"
105 );
106}
107
108impl Number {
109 /// Returns the number as text in `radix`: `-` for a negative number, then the digits of the
110 /// magnitude, the most significant first, without zeros in front, letters lower-case; `0` for
111 /// zero.
112 ///
113 /// # Panics
114 ///
115 /// When `radix` is not from 2 to 36.
116 ///
117 /// # Examples
118 ///
119 /// ```
120 /// use a::math::numbers::{ByteOrder, Number};
121 ///
122 /// let n = Number::new_from_i32(-255, ByteOrder::BigEndian);
123 /// assert_eq!(n.to_str_radix(16), "-ff");
124 /// assert_eq!(n.to_str_radix(10), "-255");
125 /// assert_eq!(n.to_str_radix(2), "-11111111");
126 /// ```
127 #[track_caller]
128 pub fn to_str_radix(&self, radix: u32) -> String {
129 check_radix(radix);
130 let x = Operand::of(self);
131 let sign = usize::from(self.negative && x.significant != 0);
132 let mut out =
133 Vec::<u8>::with_capacity(digits_bound(x.significant, radix).saturating_add(sign));
134 // SAFETY: the vector has room for the sign and the digits, which are all written before
135 // the length is set; they are ASCII, so the string is UTF-8. `self` is borrowed while it
136 // is read.
137 unsafe {
138 let p = out.as_mut_ptr();
139 *p = b'-';
140 let n = write_magnitude(x, radix, p.add(sign));
141 out.set_len(sign + n);
142 String::from_utf8_unchecked(out)
143 }
144 }
145
146 /// Reads a number from text in `radix`: an optional sign, `+` or `-`, then at least one digit,
147 /// from `0` to the radix's last, letters in either case, with no other characters, as the
148 /// primitive integers' `from_str_radix` reads; zeros in front count for nothing. The number is
149 /// built in `byte_order`, in the shortest form; `-0` is zero, not negative.
150 ///
151 /// # Errors
152 ///
153 /// [`ParseNumberError`] of kind [`NumberErrorKind::Empty`] for empty text, and
154 /// [`NumberErrorKind::InvalidDigit`] for a character that is not a digit of the radix, or a
155 /// sign alone.
156 ///
157 /// # Panics
158 ///
159 /// When `radix` is not from 2 to 36.
160 ///
161 /// # Examples
162 ///
163 /// ```
164 /// use a::math::numbers::{ByteOrder, Number, NumberErrorKind};
165 ///
166 /// let n = Number::from_str_radix("-FF", 16, ByteOrder::BigEndian).unwrap();
167 /// assert_eq!(n.value, [0xFF]);
168 /// assert!(n.is_negative());
169 ///
170 /// // 10^21 = 0x36_35C9_ADC5_DEA0_0000.
171 /// let n = Number::from_str_radix("1000000000000000000000", 10, ByteOrder::LittleEndian);
172 /// assert_eq!(n.unwrap().value, [0, 0, 0xA0, 0xDE, 0xC5, 0xAD, 0xC9, 0x35, 0x36]);
173 ///
174 /// let error = Number::from_str_radix("12a", 10, ByteOrder::BigEndian).err().unwrap();
175 /// assert_eq!(*error.kind(), NumberErrorKind::InvalidDigit);
176 /// ```
177 #[track_caller]
178 pub fn from_str_radix(
179 src: &str,
180 radix: u32,
181 byte_order: ByteOrder,
182 ) -> Result<Number, ParseNumberError> {
183 check_radix(radix);
184 let bytes = src.as_bytes();
185 let (negative, digits) = match bytes.first() {
186 None => return Err(error(NumberErrorKind::Empty)),
187 Some(b'-') => (true, &bytes[1..]),
188 Some(b'+') => (false, &bytes[1..]),
189 Some(_) => (false, bytes),
190 };
191 if digits.is_empty() {
192 return Err(error(NumberErrorKind::InvalidDigit));
193 }
194 if radix == 10 {
195 read_decimal(digits, negative, byte_order)
196 } else if radix.is_power_of_two() {
197 read_bits(digits, radix.trailing_zeros(), negative, byte_order)
198 } else {
199 read_long(digits, radix, negative, byte_order)
200 }
201 .ok_or(error(NumberErrorKind::InvalidDigit))
202 }
203}
204
205/// The error of the kind `kind`.
206#[cold]
207fn error(kind: NumberErrorKind) -> ParseNumberError {
208 ParseNumberError { kind }
209}
210
211// Writing
212
213/// The most digits that a magnitude of `bytes` significant bytes has in `radix`, at least one:
214/// `log_radix(2)` digits a bit, rounded up, and one more. Computed in 64 bits, so that it does not
215/// wrap on 32-bit targets, and `usize::MAX` when it does not fit, which no vector can hold.
216fn digits_bound(bytes: usize, radix: u32) -> usize {
217 let bits = 8 * bytes as u64;
218 let digits = if radix == 10 {
219 // log10(2) < 1234 / 4096.
220 ((bits * 1234) >> 12) + 1
221 } else {
222 // At least `floor(log2(radix))` bits a digit.
223 bits / u64::from(31 - radix.leading_zeros()) + 1
224 };
225 usize::try_from(digits).unwrap_or(usize::MAX)
226}
227
228/// Writes the digits of the magnitude of the operand `x` in `radix` at `dst`, without zeros in
229/// front, `0` for zero, and returns how many.
230///
231/// # Safety
232///
233/// The operand's vector must be valid for reads, and `dst` for writing
234/// [`digits_bound`]`(x.significant, radix)` bytes.
235unsafe fn write_magnitude(x: Operand, radix: u32, dst: *mut u8) -> usize {
236 // SAFETY: as the caller guarantees.
237 unsafe {
238 if x.significant == 0 {
239 *dst = b'0';
240 return 1;
241 }
242 if radix.is_power_of_two() {
243 return write_bits(x, radix.trailing_zeros(), dst);
244 }
245 let n = x.significant.div_ceil(8);
246 if radix == 10 && n <= 2 {
247 let order = if x.big_endian {
248 ByteOrder::BigEndian
249 } else {
250 ByteOrder::LittleEndian
251 };
252 return write_u128(read_small(significant(x), order), dst);
253 }
254 if n < WRITE_SPLIT {
255 // The limbs, and the room above them that the divisions write quotients of zero into.
256 let mut u = [MaybeUninit::<u64>::uninit(); WRITE_SPLIT + PASSES];
257 let u = u.as_mut_ptr().cast::<u64>();
258 to_limbs(x, u);
259 return write_limbs(u, n, radix, None, dst);
260 }
261 let mut powers = Vec::new();
262 write_split(le_number(x), radix, None, dst, &mut powers, true)
263 }
264}
265
266/// The significant bytes of the operand `x`, in its byte order.
267///
268/// # Safety
269///
270/// The operand's vector must be valid for reads while the slice is alive.
271unsafe fn significant<'a>(x: Operand) -> &'a [u8] {
272 let start = if x.big_endian {
273 x.len - x.significant
274 } else {
275 0
276 };
277 // SAFETY: the significant bytes lie in the operand's vector.
278 unsafe { core::slice::from_raw_parts(x.ptr.add(start), x.significant) }
279}
280
281/// The magnitude of the operand `x` as a little-endian number in the shortest form.
282///
283/// # Safety
284///
285/// The operand's vector must be valid for reads.
286unsafe fn le_number(x: Operand) -> Number {
287 // SAFETY: as the caller guarantees.
288 let bytes = unsafe { significant(x) };
289 let le = if x.big_endian {
290 bytes.iter().rev().copied().collect()
291 } else {
292 bytes.to_vec()
293 };
294 Number {
295 value: le,
296 negative: false,
297 byte_order: ByteOrder::LittleEndian,
298 }
299}
300
301/// Writes the decimal digits of `x`, not zero, at `dst`, without zeros in front, and returns how
302/// many: from 1 to 20.
303///
304/// # Safety
305///
306/// `dst` must be valid for writing as many bytes as `x` has digits.
307#[inline]
308unsafe fn write_u64(x: u64, dst: *mut u8) -> usize {
309 // SAFETY: as the caller guarantees.
310 unsafe {
311 if x >= TEN_19 {
312 // 20 digits: `x < 2 10^19`.
313 *dst = b'1';
314 write_block(x - TEN_19, dst.add(1));
315 20
316 } else {
317 write_top(x, dst)
318 }
319 }
320}
321
322/// Writes the decimal digits of `x`, not zero, at `dst`, without zeros in front, and returns how
323/// many: from 1 to 39. Above a limb, one division by `10^19` gives the last block, and the quotient,
324/// below `2^65`, is written as a limb, or for 39 digits as its top digit and a block.
325///
326/// # Safety
327///
328/// `dst` must be valid for writing as many bytes as `x` has digits.
329#[inline]
330unsafe fn write_u128(x: u128, dst: *mut u8) -> usize {
331 let (hi, lo) = ((x >> 64) as u64, x as u64);
332 // SAFETY: as the caller guarantees.
333 unsafe {
334 if hi == 0 {
335 return write_u64(lo, dst);
336 }
337 // The quotient `top B + q` and the last block `r`.
338 let (top, hi) = if hi >= TEN_19 {
339 (1, hi - TEN_19)
340 } else {
341 (0, hi)
342 };
343 let (q, r) = divide_2by1(hi, lo, TEN_19, TEN_19_INVERSE);
344 let n = if top == 0 {
345 write_u64(q, dst)
346 } else {
347 // `B + q`, from `1.8 10^19` to `3.7 10^19`: its first digit is 1, 2 or 3.
348 let y = (1 << 64) + u128::from(q);
349 let t = 1 + u64::from(y >= 2 * TEN_19 as u128) + u64::from(y >= 3 * TEN_19 as u128);
350 *dst = b'0' + t as u8;
351 write_block((y - u128::from(t) * u128::from(TEN_19)) as u64, dst.add(1));
352 20
353 };
354 write_block(r, dst.add(n));
355 n + 19
356 }
357}
358
359/// Writes the digits of the magnitude in the `n` limbs at `u`, least significant first, which it
360/// clobbers, in `radix`, not a power of two, at `dst`: exactly `width` digits, zeros in front,
361/// when given (enough for the magnitude), and otherwise without zeros in front, `0` for zero.
362/// Returns how many it wrote.
363///
364/// # Safety
365///
366/// `n < WRITE_SPLIT`; the `n + PASSES` limbs at `u` must be valid for reads and writes, and `dst`
367/// for writing the digits.
368unsafe fn write_limbs(
369 u: *mut u64,
370 n: usize,
371 radix: u32,
372 width: Option<usize>,
373 dst: *mut u8,
374) -> usize {
375 // A block takes more than 58 bits, as `b > 2^64 / 36`: at most two blocks a limb, and the
376 // groups of divisions may give up to `PASSES` blocks of zero above the top.
377 let mut blocks = [MaybeUninit::<u64>::uninit(); 2 * WRITE_SPLIT + PASSES];
378 let blocks = blocks.as_mut_ptr().cast::<u64>();
379 // SAFETY: as the caller guarantees.
380 unsafe {
381 let count = if radix == 10 {
382 decimal_blocks(u, n, blocks)
383 } else {
384 let (b, _) = block(radix);
385 let s = b.leading_zeros();
386 let base = Base {
387 s,
388 d: b << s,
389 v: reciprocal(b << s),
390 };
391 if SELECTS.contains(&radix) {
392 select_blocks(u, n, base, blocks)
393 } else {
394 other_blocks(u, n, base, blocks)
395 }
396 };
397 // The blocks below `count` are written.
398 put_blocks(
399 core::slice::from_raw_parts(blocks, count),
400 radix,
401 width,
402 dst,
403 )
404 }
405}
406
407/// The block `b` of a radix as its divisions take it: `b = d / 2^s` for the normalized `d`, whose
408/// reciprocal is `v`.
409#[derive(Clone, Copy)]
410struct Base {
411 s: u32,
412 d: u64,
413 v: u64,
414}
415
416/// [`divide_blocks`] by `10^19`, with the constants in the code.
417///
418/// # Safety
419///
420/// As for [`divide_blocks`].
421unsafe fn decimal_blocks(u: *mut u64, n: usize, blocks: *mut u64) -> usize {
422 let base = Base {
423 s: 0,
424 d: TEN_19,
425 v: TEN_19_INVERSE,
426 };
427 // SAFETY: as the caller guarantees.
428 unsafe { divide_blocks::<false>(u, n, base, blocks) }
429}
430
431/// [`divide_blocks`] by the block of another radix, with the second correction of a quotient a
432/// branch.
433///
434/// # Safety
435///
436/// As for [`divide_blocks`].
437unsafe fn other_blocks(u: *mut u64, n: usize, base: Base, blocks: *mut u64) -> usize {
438 // SAFETY: as the caller guarantees.
439 unsafe { divide_blocks::<false>(u, n, base, blocks) }
440}
441
442/// [`divide_blocks`] by the block of a radix in [`SELECTS`], with both corrections of a quotient
443/// selects.
444///
445/// # Safety
446///
447/// As for [`divide_blocks`].
448unsafe fn select_blocks(u: *mut u64, n: usize, base: Base, blocks: *mut u64) -> usize {
449 // SAFETY: as the caller guarantees.
450 unsafe { divide_blocks::<true>(u, n, base, blocks) }
451}
452
453/// The radices whose blocks, normalized, often need the second correction of the quotient
454/// estimated by the reciprocal: in a simulation of random steps, 6.6% of them for 6 and 36, 3.6%
455/// for 29, 2.8% for 34 and 1.5% for 26; 0.44% for 3 and 9, 0.007% for 10, and fewer for the
456/// others. Measured on an Apple M4 Max, selects made 512 bytes in radix 36 12% faster, and radices
457/// 3 and 7 10% slower, as they lengthen the chain of a division.
458const SELECTS: [u32; 5] = [6, 26, 29, 34, 36];
459
460/// Divides the magnitude in the `n` limbs at `u`, least significant first, which it clobbers, by
461/// the block `b` again and again until nothing is left, and writes the remainders at `blocks`,
462/// the least significant first; returns how many, without those of zero above the top, at least
463/// one.
464///
465/// The limbs of one division wait for each other: the remainder of a limb is the high limb of
466/// the next one's dividend, and a step, [`div_2by1`](divide_2by1), takes about ten cycles. But
467/// the next division needs only the quotient's limbs, from the top: so the divisions run in
468/// groups, in waves, each a limb behind the one before it, which hands it its quotient limbs in
469/// registers (see [`group`]). Their chains are independent, and the core runs them side by side.
470/// A group of `K` divisions takes `n + K - 1` waves, and leaves a number about `K` limbs shorter:
471/// the groups take as many divisions as the limbs left but one, rounded down to 1, 2, 4 or
472/// [`PASSES`], so that few blocks of zero come out above the top, and the last limb is divided
473/// alone.
474///
475/// # Safety
476///
477/// The `n + PASSES` limbs at `u` must be valid for reads and writes, and `blocks` for writing
478/// `2 n + PASSES` limbs.
479#[inline(always)]
480unsafe fn divide_blocks<const SELECT: bool>(
481 u: *mut u64,
482 mut n: usize,
483 base: Base,
484 blocks: *mut u64,
485) -> usize {
486 let mut count = 0;
487 // SAFETY: as the caller guarantees: a group of `K` takes `K` blocks of a number of more than
488 // `K` limbs, each more than 58 bits, so there are fewer than `2 n` blocks before the last
489 // group, which may write `PASSES - 1` zeros above them.
490 unsafe {
491 while n > 1 {
492 let out = blocks.add(count);
493 let (taken, left) = match n - 1 {
494 1 => (1, group::<1, SELECT>(u, n, base, out)),
495 2 | 3 => (2, group::<2, SELECT>(u, n, base, out)),
496 4..=7 => (4, group::<4, SELECT>(u, n, base, out)),
497 _ => (PASSES, group::<PASSES, SELECT>(u, n, base, out)),
498 };
499 count += taken;
500 n = left;
501 }
502 if n == 1 {
503 let (x, b) = (*u, base.d >> base.s);
504 *blocks.add(count) = x % b;
505 *blocks.add(count + 1) = x / b;
506 count += 2;
507 }
508 if count == 0 {
509 *blocks = 0;
510 count = 1;
511 }
512 while count > 1 && *blocks.add(count - 1) == 0 {
513 count -= 1;
514 }
515 }
516 count
517}
518
519/// One step of a division by the block `b`: the dividend `r B + x` for the remainder `r < b`
520/// carried as `r 2^s`, shifted by `s` bits to be divided by the normalized `d`; returns the
521/// quotient and the remainder, again as `r 2^s`.
522///
523/// With `SELECT`, both corrections of the quotient are selects; otherwise the second is a branch,
524/// as in [`div_2by1`](divide_2by1), which costs nothing while it is rare, and is a mispredicted
525/// branch and a call when it is not (see [`SELECTS`]).
526#[inline(always)]
527fn step<const SELECT: bool>(r: u64, x: u64, base: Base) -> (u64, u64) {
528 // `x >> (64 - s)` in two steps, so that `s = 0` shifts everything out.
529 let (u1, u0) = (r | ((x >> 1) >> (63 - base.s)), x << base.s);
530 if !SELECT {
531 return divide_2by1(u1, u0, base.d, base.v);
532 }
533 // Algorithm 4 of Möller and Granlund, as `div_2by1` computes it, with the second correction
534 // a select.
535 let (d, v) = (base.d, base.v);
536 let p = (u128::from(v) * u128::from(u1))
537 .wrapping_add((u128::from(u1.wrapping_add(1)) << 64) | u128::from(u0));
538 let (q, q0) = ((p >> 64) as u64, p as u64);
539 let r = u0.wrapping_sub(q.wrapping_mul(d));
540 let mask = u64::from(r > q0).wrapping_neg();
541 let (q, r) = (q.wrapping_add(mask), r.wrapping_add(mask & d));
542 let more = r >= d;
543 (
544 q + u64::from(more),
545 r - (d & u64::from(more).wrapping_neg()),
546 )
547}
548
549/// `K` divisions of the `n >= 2` limbs at `u` by the block `b`, one after another, in waves (see
550/// [`divide_blocks`]): writes the `K` remainders at `out`, the least significant first, leaves the
551/// quotient by `b^K` in the limbs at `u`, and returns its length.
552///
553/// In wave `t`, division `p` takes the limb at `n - 1 - (t - p)`: the first one reads it from `u`,
554/// the others take it from the one before, in the last wave, and the last one writes its quotient
555/// limb back. Above the top, the limbs are zero; below the bottom, a division is done, and its
556/// remainder is kept when it is.
557///
558/// # Safety
559///
560/// The `n + K` limbs at `u` must be valid for reads and writes, and the `K` at `out` for writes.
561#[inline(always)]
562unsafe fn group<const K: usize, const SELECT: bool>(
563 u: *mut u64,
564 n: usize,
565 base: Base,
566 out: *mut u64,
567) -> usize {
568 // The remainders, as `r 2^s`, and the quotient limb that each division hands the next one.
569 let mut r = [0u64; K];
570 let mut c = [0u64; K];
571 // SAFETY: the first division reads limbs `n - 1` down to 0; the last one writes limb
572 // `n - 1 + K - 1 - t` in wave `t`, from `n + K - 2` down to 0, after the first one read it,
573 // as `t` grows.
574 unsafe {
575 for t in 0..n {
576 let mut p = K;
577 while p > 1 {
578 p -= 1;
579 let (q, rest) = step::<SELECT>(r[p], c[p - 1], base);
580 r[p] = rest;
581 if p == K - 1 {
582 *u.add(n + K - 2 - t) = q;
583 } else {
584 c[p] = q;
585 }
586 }
587 let (q, rest) = step::<SELECT>(r[0], *u.add(n - 1 - t), base);
588 r[0] = rest;
589 if K == 1 {
590 *u.add(n - 1 - t) = q;
591 } else {
592 c[0] = q;
593 }
594 }
595 *out = r[0] >> base.s;
596 // The waves after the first division is done: in wave `n + i`, divisions `i + 1` up.
597 for i in 0..K - 1 {
598 let mut p = K;
599 while p > i + 1 {
600 p -= 1;
601 let (q, rest) = step::<SELECT>(r[p], c[p - 1], base);
602 r[p] = rest;
603 if p == K - 1 {
604 *u.add(K - 2 - i) = q;
605 } else {
606 c[p] = q;
607 }
608 }
609 *out.add(i + 1) = r[i + 1] >> base.s;
610 }
611 }
612 let mut len = n;
613 // SAFETY: the limbs below `len` are the quotient's.
614 while len > 0 && unsafe { *u.add(len - 1) } == 0 {
615 len -= 1;
616 }
617 len
618}
619
620/// Writes the blocks, the least significant first, of `k` digits each in `radix`, as digits at
621/// `dst`: exactly `width` digits when given, zeros in front, and otherwise without zeros in front,
622/// `0` for zero. Returns how many.
623///
624/// # Safety
625///
626/// `blocks` must not be empty, and `dst` valid for writing the digits; `width`, when given, must
627/// have room for the digits of the blocks but their zeros in front.
628unsafe fn put_blocks(blocks: &[u64], radix: u32, width: Option<usize>, dst: *mut u8) -> usize {
629 let (_, k) = block(radix);
630 let count = blocks.len();
631 // SAFETY: as the caller guarantees.
632 unsafe {
633 // The digits in all, and the blocks written whole, from the least significant; the
634 // digits above them first.
635 let (total, whole) = match width {
636 None => {
637 let top = blocks[count - 1];
638 let head = if radix == 10 {
639 write_top(top, dst)
640 } else {
641 write_short_top(top, Radix::new(radix), dst)
642 };
643 (head + k * (count - 1), count - 1)
644 }
645 Some(w) => {
646 // The blocks that fit whole; above them the low digits of the next one, or zeros.
647 let whole = (w / k).min(count);
648 let head = w - k * whole;
649 if head > 0 {
650 let next = if whole < count { blocks[whole] } else { 0 };
651 write_partial(next, radix, k, head, dst);
652 }
653 (w, whole)
654 }
655 };
656 let mut at = dst.add(total);
657 if radix == 10 {
658 for &b in &blocks[..whole] {
659 at = at.sub(k);
660 write_block(b, at);
661 }
662 } else {
663 // Four blocks at once: the digits of a block wait for each other, a division each,
664 // and the four chains run side by side.
665 let radix = Radix::new(radix);
666 let (fours, rest) = blocks[..whole].as_chunks::<4>();
667 for four in fours {
668 at = at.sub(4 * k);
669 write_four(*four, radix, at, k);
670 }
671 for &b in rest {
672 at = at.sub(k);
673 write_digits(b, radix, at, k);
674 }
675 }
676 total
677 }
678}
679
680/// Writes the `n` low digits of `x` in `radix`, zeros in front, at `dst`: a block cut short, or
681/// zeros alone for `x` of zero.
682///
683/// # Safety
684///
685/// `dst` must be valid for writing `n` bytes; `x` must have at most `n` digits.
686unsafe fn write_partial(x: u64, radix: u32, k: usize, n: usize, dst: *mut u8) {
687 // SAFETY: as the caller guarantees.
688 unsafe {
689 if n <= k {
690 let mut buffer = [0u8; 64];
691 if radix == 10 {
692 write_block(x, buffer.as_mut_ptr());
693 } else {
694 write_digits(x, Radix::new(radix), buffer.as_mut_ptr(), k);
695 }
696 core::ptr::copy_nonoverlapping(buffer.as_ptr().add(k - n), dst, n);
697 } else {
698 core::ptr::write_bytes(dst, b'0', n - k);
699 write_partial(x, radix, k, k, dst.add(n - k));
700 }
701 }
702}
703
704/// Writes `x` in `radix` into the `n` bytes at `dst`, the most significant digit first, with zeros
705/// in front: `x` must have at most `n` digits.
706///
707/// # Safety
708///
709/// `dst` must be valid for writing `n` bytes.
710unsafe fn write_digits(mut x: u64, radix: Radix, dst: *mut u8, n: usize) {
711 // SAFETY: as the caller guarantees.
712 unsafe {
713 for i in (0..n).rev() {
714 let (q, digit) = radix.div_rem(x);
715 *dst.add(i) = DIGITS[digit as usize];
716 x = q;
717 }
718 }
719}
720
721/// Writes the blocks `x`, the least significant first, of `n` digits each in `radix`, into the
722/// `4 n` bytes at `dst`, the most significant digit first: the four chains of divisions in one
723/// loop.
724///
725/// # Safety
726///
727/// `dst` must be valid for writing `4 n` bytes; each block must have at most `n` digits.
728unsafe fn write_four(mut x: [u64; 4], radix: Radix, dst: *mut u8, n: usize) {
729 // SAFETY: block `j` goes to the `n` bytes at `dst + (3 - j) n`.
730 unsafe {
731 for i in (0..n).rev() {
732 for (j, x) in x.iter_mut().enumerate() {
733 let (q, digit) = radix.div_rem(*x);
734 *dst.add((3 - j) * n + i) = DIGITS[digit as usize];
735 *x = q;
736 }
737 }
738 }
739}
740
741/// Writes the digits of the top block `x` in `radix`, not 10, at `dst`, without zeros in front, `0`
742/// for zero; returns how many.
743///
744/// # Safety
745///
746/// `dst` must be valid for writing the digits.
747unsafe fn write_short_top(mut x: u64, radix: Radix, dst: *mut u8) -> usize {
748 let mut buffer = [0u8; 64];
749 let mut i = 64;
750 loop {
751 i -= 1;
752 let (q, digit) = radix.div_rem(x);
753 buffer[i] = DIGITS[digit as usize];
754 x = q;
755 if x == 0 {
756 break;
757 }
758 }
759 // SAFETY: as the caller guarantees.
760 unsafe { core::ptr::copy_nonoverlapping(buffer.as_ptr().add(i), dst, 64 - i) };
761 64 - i
762}
763
764/// A radix from 3 to 36 to divide by with a multiplication, as Granlund and Montgomery divide by
765/// an invariant integer: exact for every `u64`. The hardware's division takes about 10 cycles and
766/// does not overlap with the next one, which made the digits of radices other than 10 the larger
767/// part of writing them: on an Apple M4 Max, 512 bytes in radix 36 took 16,700 cycles with it.
768#[derive(Clone, Copy)]
769struct Radix {
770 /// The radix.
771 d: u64,
772 /// `floor(2^64 (2^l - d) / d) + 1`, below `2^64` as `2^l - d < d`.
773 m: u64,
774 /// `ceil(log2 d)`, at least 2.
775 l: u32,
776}
777
778impl Radix {
779 /// The radix `d`, from 3 to 36, prepared.
780 fn new(d: u32) -> Radix {
781 let d = u64::from(d);
782 let l = 64 - (d - 1).leading_zeros();
783 let m = (((1u128 << l) - u128::from(d)) << 64) / u128::from(d) + 1;
784 Radix { d, m: m as u64, l }
785 }
786
787 /// The quotient and the remainder of `n` by the radix.
788 #[inline(always)]
789 fn div_rem(self, n: u64) -> (u64, u64) {
790 // `t <= n`, as `m < 2^64`; the halved difference does not overflow.
791 let t = ((u128::from(self.m) * u128::from(n)) >> 64) as u64;
792 let q = (t + ((n - t) >> 1)) >> (self.l - 1);
793 (q, n - q * self.d)
794 }
795}
796
797// Decimal digits in lanes
798
799/// The eight decimal digits of `x < 10^8` as values from 0 to 9, the most significant in the
800/// lowest byte: split in halves of four digits in the 32-bit lanes, each in pairs in the 16-bit
801/// lanes, each in digits in the bytes, by multiplications that divide by 10^4, 100 and 10 in all
802/// lanes at once (`x · m >> k` with `m` the reciprocal rounded up: exact for these ranges).
803#[inline(always)]
804fn eight_digits(x: u64) -> u64 {
805 // x / 10^4 for x < 4.9 10^8.
806 let hi = (x * 109_951_163) >> 40;
807 let x = hi | ((x - hi * 10_000) << 32);
808 // Lanes / 100, for lanes below 43,690.
809 let q = ((x * 10_486) >> 20) & 0x0000_007F_0000_007F;
810 let x = q | ((x - q * 100) << 16);
811 // Lanes / 10, for lanes below 170.
812 let t = ((x * 103) >> 10) & 0x000F_000F_000F_000F;
813 t | ((x - t * 10) << 8)
814}
815
816/// Writes the 19 decimal digits of the block `x < 10^19` at `dst`, zeros in front.
817///
818/// # Safety
819///
820/// `dst` must be valid for writing 19 bytes.
821#[inline(always)]
822unsafe fn write_block(x: u64, dst: *mut u8) {
823 let (a, b, c) = split_block(x);
824 let zeros = 0x3030_3030_3030_3030;
825 // SAFETY: the writes lie in the 19 bytes: `[0, 4)`, then `[3, 11)` over its last byte, and
826 // `[11, 19)`.
827 unsafe {
828 write(dst, (three_digits(a) as u32 | 0x0030_3030).to_le_bytes());
829 write(dst.add(3), (eight_digits(b) | zeros).to_le_bytes());
830 write(dst.add(11), (eight_digits(c) | zeros).to_le_bytes());
831 }
832}
833
834/// The block `x < 10^19` as its top three digits, `x / 10^16`, and two groups of eight.
835#[inline(always)]
836fn split_block(x: u64) -> (u64, u64, u64) {
837 let a = x / 10_000_000_000_000_000;
838 let rest = x - a * 10_000_000_000_000_000;
839 let b = rest / 100_000_000;
840 (a, b, rest - b * 100_000_000)
841}
842
843/// The three decimal digits of `x < 1000` as values, the most significant in the lowest byte.
844#[inline(always)]
845fn three_digits(x: u64) -> u64 {
846 // x / 100 for x < 1024, then the two below.
847 let h = (x * 41) >> 12;
848 let rest = x - h * 100;
849 let t = (rest * 103) >> 10;
850 h | (t << 8) | ((rest - t * 10) << 16)
851}
852
853/// Writes the decimal digits of the block `x < 10^19` at `dst`, without zeros in front, `0` for
854/// zero; returns how many, from 1 to 19. The digits are made in a buffer, and only they are
855/// copied.
856///
857/// # Safety
858///
859/// `dst` must be valid for writing as many bytes as `x` has digits.
860#[inline(always)]
861unsafe fn write_top(x: u64, dst: *mut u8) -> usize {
862 let (a, b, c) = split_block(x);
863 let (a, b, c) = (three_digits(a), eight_digits(b), eight_digits(c));
864 // The zeros in front: the zero bytes at the bottom of the first group with a digit that is
865 // not zero, the most significant in the lowest byte.
866 let zeros = if a != 0 {
867 a.trailing_zeros() / 8
868 } else if b != 0 {
869 3 + b.trailing_zeros() / 8
870 } else {
871 11 + (c | 1 << 56).trailing_zeros() / 8
872 } as usize;
873 let mut buffer = [0u8; 24];
874 let ascii = 0x3030_3030_3030_3030;
875 let p = buffer.as_mut_ptr();
876 // SAFETY: the buffer holds the digits at `[5, 24)`, and `dst` has room for the `19 - zeros`
877 // copied.
878 unsafe {
879 write(p.add(4), ((a << 8) as u32 | 0x3030_3030).to_le_bytes());
880 write(p.add(8), (b | ascii).to_le_bytes());
881 write(p.add(16), (c | ascii).to_le_bytes());
882 copy_short(dst, p.add(5 + zeros), 19 - zeros);
883 }
884 19 - zeros
885}
886
887/// Copies the `n` bytes at `src`, from 1 to 24, to `dst`, apart from them: in up to three copies
888/// of eight, four or one, which overlap where `n` is not a multiple, and agree there.
889///
890/// # Safety
891///
892/// The bytes must be valid for reads at `src` and for writes at `dst`.
893#[inline(always)]
894unsafe fn copy_short(dst: *mut u8, src: *const u8, n: usize) {
895 // SAFETY: every access lies in the `n` bytes.
896 unsafe {
897 if n >= 8 {
898 write::<8>(dst, read(src));
899 if n > 16 {
900 write::<8>(dst.add(8), read(src.add(8)));
901 }
902 write::<8>(dst.add(n - 8), read(src.add(n - 8)));
903 } else if n >= 4 {
904 write::<4>(dst, read(src));
905 write::<4>(dst.add(n - 4), read(src.add(n - 4)));
906 } else {
907 *dst = *src;
908 *dst.add(n / 2) = *src.add(n / 2);
909 *dst.add(n - 1) = *src.add(n - 1);
910 }
911 }
912}
913
914// Divide and conquer
915
916/// A power `b^(2^i)` of the block for divide and conquer, without its zero bytes at the bottom.
917struct Power {
918 /// The power divided by `256^zeros`, little-endian, in the shortest form.
919 odd: Number,
920 /// The zero bytes at the bottom of the power.
921 zeros: usize,
922 /// Its places: `k 2^i` digits.
923 places: usize,
924 /// [`Power::odd`] prepared for dividing by it, when it first is.
925 divisor: Option<Divisor>,
926}
927
928impl Power {
929 /// The length of the power in bytes.
930 fn bytes(&self) -> usize {
931 self.odd.value.len() + self.zeros
932 }
933
934 /// The first power, `b`, of `k` places.
935 fn first(b: u64, k: usize) -> Power {
936 let zeros = (b.trailing_zeros() / 8) as usize;
937 Power {
938 odd: Number::new(
939 (b >> (8 * zeros)).to_le_bytes().to_vec(),
940 ByteOrder::LittleEndian,
941 ),
942 zeros,
943 places: k,
944 divisor: None,
945 }
946 }
947
948 /// The square of this power.
949 fn square(&self) -> Power {
950 let mut odd = &self.odd * &self.odd;
951 let more = odd.value.iter().take_while(|&&byte| byte == 0).count();
952 odd.value.drain(..more);
953 Power {
954 odd,
955 zeros: 2 * self.zeros + more,
956 places: 2 * self.places,
957 divisor: None,
958 }
959 }
960}
961
962/// The index of the largest power in `powers`, computed as they are first needed from `b` of `k`
963/// places, for which `fits(bytes, places)` holds, or 0. A square has at least twice the bytes of
964/// its root but one, and is computed only when that many may fit.
965fn largest(
966 powers: &mut Vec<Power>,
967 b: u64,
968 k: usize,
969 fits: impl Fn(usize, usize) -> bool,
970) -> usize {
971 if powers.is_empty() {
972 powers.push(Power::first(b, k));
973 }
974 let mut i = 0;
975 loop {
976 if i + 1 == powers.len() {
977 let p = &powers[i];
978 if !fits(2 * p.bytes() - 1, 2 * p.places) {
979 return i;
980 }
981 let next = p.square();
982 powers.push(next);
983 }
984 let p = &powers[i + 1];
985 if !fits(p.bytes(), p.places) {
986 return i;
987 }
988 i += 1;
989 }
990}
991
992/// Writes the digits of the magnitude `x`, little-endian in the shortest form, in `radix` at
993/// `dst`, as [`write_limbs`] writes them, and returns how many: by divide and conquer, divided by
994/// the largest power `b^(2^i)` that has at most half its limbs and one, the quotient written
995/// first, then the remainder in `k 2^i` places.
996///
997/// The power is `odd 256^zeros`; only the bytes of `x` from `zeros` up are divided by `odd`,
998/// and the remainder's are put above the bytes below them. `top` is set for the first split, whose
999/// power divides nothing else.
1000///
1001/// # Safety
1002///
1003/// `dst` must be valid for writing the digits.
1004unsafe fn write_split(
1005 x: Number,
1006 radix: u32,
1007 width: Option<usize>,
1008 dst: *mut u8,
1009 powers: &mut Vec<Power>,
1010 top: bool,
1011) -> usize {
1012 let limbs = x.value.len().div_ceil(8);
1013 // SAFETY: as the caller guarantees.
1014 unsafe {
1015 if limbs < WRITE_SPLIT {
1016 if limbs == 0 || x.value == [0] {
1017 return write_limbs([0; PASSES + 1].as_mut_ptr(), 0, radix, width, dst);
1018 }
1019 let mut u = [MaybeUninit::<u64>::uninit(); WRITE_SPLIT + PASSES];
1020 let u = u.as_mut_ptr().cast::<u64>();
1021 to_limbs(Operand::of(&x), u);
1022 return write_limbs(u, limbs, radix, width, dst);
1023 }
1024 let (b, k) = block(radix);
1025 let half = 8 * (limbs.div_ceil(2) + 1);
1026 let i = largest(powers, b, k, |bytes, _| bytes <= half);
1027 let power = &mut powers[i];
1028 let (zeros, places) = (power.zeros, power.places);
1029 let (q, r) = if x.value.len() > zeros {
1030 let high = Number {
1031 value: x.value[zeros..].to_vec(),
1032 negative: false,
1033 byte_order: ByteOrder::LittleEndian,
1034 };
1035 // The largest power divides once, at the top; the others divide the parts below it,
1036 // each at least twice, and are prepared as divisors, which keep the inverse of
1037 // Newton's method from one division to the next.
1038 let (q, r) = if top {
1039 high.div_rem(&power.odd)
1040 } else {
1041 power
1042 .divisor
1043 .get_or_insert_with(|| Divisor::new(&power.odd))
1044 .div_rem(&high)
1045 };
1046 let mut low = x.value;
1047 low.truncate(zeros);
1048 if r.value != [0] {
1049 low.extend_from_slice(&r.value);
1050 }
1051 (q, trimmed(low))
1052 } else {
1053 (Number::new(vec![0], ByteOrder::LittleEndian), x)
1054 };
1055 let n = match width {
1056 // Without a quotient, the remainder is the number, and has no zeros in front.
1057 None if q.value == [0] => return write_split(r, radix, None, dst, powers, top),
1058 None => write_split(q, radix, None, dst, powers, false),
1059 Some(w) => write_split(q, radix, Some(w - places), dst, powers, false),
1060 };
1061 n + write_split(r, radix, Some(places), dst.add(n), powers, false)
1062 }
1063}
1064
1065/// `value` as a little-endian number in the shortest form.
1066fn trimmed(mut value: Vec<u8>) -> Number {
1067 while value.len() > 1 && value.last() == Some(&0) {
1068 value.pop();
1069 }
1070 if value.is_empty() {
1071 value.push(0);
1072 }
1073 Number {
1074 value,
1075 negative: false,
1076 byte_order: ByteOrder::LittleEndian,
1077 }
1078}
1079
1080// Radices that are powers of two
1081
1082/// Writes the digits of the magnitude of the operand `x`, not zero, in the radix `2^bits` at
1083/// `dst`, without zeros in front, and returns how many: read where they are, from the most
1084/// significant byte. Hexadecimal is two digits a byte, from a table, binary eight, spread over the
1085/// bytes of a `u64` by one multiplication; other radices take groups of `bits` bits from the low
1086/// end, written from the back.
1087///
1088/// # Safety
1089///
1090/// The operand's vector must be valid for reads, and `dst` for writing the digits.
1091unsafe fn write_bits(x: Operand, bits: u32, dst: *mut u8) -> usize {
1092 // SAFETY: as the caller guarantees.
1093 let bytes = unsafe { significant(x) };
1094 let l = bytes.len();
1095 // Byte `i` of the magnitude from the most significant.
1096 // SAFETY: `i < l`.
1097 let from_top =
1098 |i: usize| unsafe { *bytes.get_unchecked(if x.big_endian { i } else { l - 1 - i }) };
1099 let top = from_top(0);
1100 // The digits, counted in 64 bits: their number fits, as the caller has room for them.
1101 let total = 8 * (l as u64 - 1) + u64::from(8 - top.leading_zeros());
1102 let n = total.div_ceil(u64::from(bits)) as usize;
1103 // SAFETY: as the caller guarantees, `dst` has room for the `n` digits; the top byte's digits
1104 // come first, then those of each byte below it.
1105 unsafe {
1106 match bits {
1107 4 => {
1108 let mut at = dst;
1109 if top < 16 {
1110 *at = DIGITS[usize::from(top)];
1111 at = at.add(1);
1112 } else {
1113 write(at, HEX[usize::from(top)]);
1114 at = at.add(2);
1115 }
1116 for i in 1..l {
1117 write(at, HEX[usize::from(from_top(i))]);
1118 at = at.add(2);
1119 }
1120 }
1121 1 => {
1122 let k = 8 - top.leading_zeros() as usize;
1123 for j in 0..k {
1124 *dst.add(j) = b'0' + ((top >> (k - 1 - j)) & 1);
1125 }
1126 for i in 1..l {
1127 write(dst.add(k + 8 * (i - 1)), binary_digits(from_top(i)));
1128 }
1129 }
1130 _ => {
1131 // Whole groups of bytes from the bottom, then the digits above them one by one.
1132 let (mut next, mut j) = match bits {
1133 2 => groups::<2, 1, 4>(from_top, l, n, dst),
1134 3 => groups::<3, 3, 8>(from_top, l, n, dst),
1135 _ => groups::<5, 5, 8>(from_top, l, n, dst),
1136 };
1137 let mask = (1u32 << bits) - 1;
1138 let (mut acc, mut have) = (0u32, 0u32);
1139 while j > 0 {
1140 j -= 1;
1141 if have < bits && next > 0 {
1142 next -= 1;
1143 acc |= u32::from(from_top(next)) << have;
1144 have += 8;
1145 }
1146 *dst.add(j) = DIGITS[(acc & mask) as usize];
1147 acc >>= bits;
1148 have = have.saturating_sub(bits);
1149 }
1150 }
1151 }
1152 }
1153 n
1154}
1155
1156/// Writes the digits of the magnitude of `l` bytes, `from_top(i)` its byte `i` from the most
1157/// significant, of `n` digits in the radix `2^B`, from the bottom in groups of `G` bytes, `D`
1158/// digits each, the last of the `n` digits at `dst` first; returns the bytes and the digits above
1159/// the groups, left to write.
1160///
1161/// # Safety
1162///
1163/// `dst` must be valid for writing `n` bytes.
1164#[inline(always)]
1165unsafe fn groups<const B: u32, const G: usize, const D: usize>(
1166 from_top: impl Fn(usize) -> u8,
1167 l: usize,
1168 n: usize,
1169 dst: *mut u8,
1170) -> (usize, usize) {
1171 let (mut bytes, mut digits) = (l, n);
1172 while bytes >= G && digits >= D {
1173 let mut v = 0u64;
1174 for t in 0..G {
1175 v |= u64::from(from_top(bytes - 1 - t)) << (8 * t);
1176 }
1177 for t in 0..D {
1178 // SAFETY: `digits - 1 - t < n`.
1179 unsafe {
1180 *dst.add(digits - 1 - t) =
1181 DIGITS[((v >> (B as usize * t)) & ((1 << B) - 1)) as usize]
1182 };
1183 }
1184 bytes -= G;
1185 digits -= D;
1186 }
1187 (bytes, digits)
1188}
1189
1190/// The eight binary digits of `byte` as ASCII, the most significant first: bit `7 - i` moved to
1191/// byte `i` by a multiplication that adds copies of `byte` nine bits apart, which cannot overlap.
1192#[inline(always)]
1193fn binary_digits(byte: u8) -> [u8; 8] {
1194 let spread = (u64::from(byte).wrapping_mul(0x8040_2010_0804_0201) >> 7) & 0x0101_0101_0101_0101;
1195 (spread | 0x3030_3030_3030_3030).to_le_bytes()
1196}
1197
1198/// The two hexadecimal digits of each byte.
1199const HEX: [[u8; 2]; 256] = {
1200 let mut t = [[0; 2]; 256];
1201 let mut i = 0;
1202 while i < 256 {
1203 t[i] = [DIGITS[i >> 4], DIGITS[i & 15]];
1204 i += 1;
1205 }
1206 t
1207};
1208
1209/// The value of each character as a digit, 36 or more when it is none.
1210const VALUES: [u8; 256] = {
1211 let mut t = [255; 256];
1212 let mut i = 0;
1213 while i < 36 {
1214 t[DIGITS[i] as usize] = i as u8;
1215 t[DIGITS[i].to_ascii_uppercase() as usize] = i as u8;
1216 i += 1;
1217 }
1218 t
1219};
1220
1221/// The number of the digits `text` in the radix `2^bits`, the most significant first, in
1222/// `order`, `negative` if not zero; `None` when a character is not a digit. One pass from the
1223/// last digit, each byte written in its place in `order`: two digits a byte for hexadecimal, and
1224/// otherwise the digits' bits gathered in a register; the digits' values are or-ed together, and
1225/// the radix checked once.
1226fn read_bits(text: &[u8], bits: u32, negative: bool, order: ByteOrder) -> Option<Number> {
1227 // Zeros in front count for nothing.
1228 let start = text.iter().position(|&c| c != b'0').unwrap_or(text.len());
1229 let digits = &text[start..];
1230 let Some(&first) = digits.first() else {
1231 return Some(zero(order));
1232 };
1233 let top = VALUES[usize::from(first)];
1234 if top >> bits != 0 {
1235 return None;
1236 }
1237 let n = digits.len();
1238 // Counted in 64 bits; the bytes are fewer than the digits, so their number fits.
1239 let len = (u64::from(bits) * (n as u64 - 1) + u64::from(8 - top.leading_zeros())).div_ceil(8)
1240 as usize;
1241 let mut value = Vec::<u8>::with_capacity(len);
1242 let be = order == ByteOrder::BigEndian;
1243 let out = value.as_mut_ptr();
1244 let mut seen = 0u8;
1245 // SAFETY: the bytes written are `len`, each at its own place below `len`: the significant
1246 // bits are `len` bytes, and no digit's bits go above them, as the top digit's are counted.
1247 unsafe {
1248 let put = |j: usize, byte: u8| *out.add(if be { len - 1 - j } else { j }) = byte;
1249 let digit = |i: usize| VALUES[usize::from(*digits.get_unchecked(i))];
1250 if bits == 4 {
1251 // Hexadecimal: a byte from two digits, `ceil(n / 2)` of them, as the top digit is not
1252 // zero.
1253 let mut j = 0;
1254 let mut i = n;
1255 while i >= 2 {
1256 let (high, low) = (digit(i - 2), digit(i - 1));
1257 seen |= high | low;
1258 put(j, high << 4 | low);
1259 j += 1;
1260 i -= 2;
1261 }
1262 if i == 1 {
1263 put(j, top);
1264 }
1265 } else {
1266 let (mut acc, mut have, mut j) = (0u32, 0u32, 0);
1267 for i in (0..n).rev() {
1268 let v = digit(i);
1269 seen |= v;
1270 acc |= u32::from(v) << have;
1271 have += bits;
1272 if have >= 8 {
1273 put(j, acc as u8);
1274 j += 1;
1275 acc >>= 8;
1276 have -= 8;
1277 }
1278 }
1279 if j < len {
1280 put(j, acc as u8);
1281 }
1282 }
1283 if seen >> bits != 0 {
1284 return None;
1285 }
1286 value.set_len(len);
1287 }
1288 Some(Number {
1289 value,
1290 negative,
1291 byte_order: order,
1292 })
1293}
1294
1295/// Zero, `[0]`, in `order`.
1296fn zero(order: ByteOrder) -> Number {
1297 Number {
1298 value: vec![0],
1299 negative: false,
1300 byte_order: order,
1301 }
1302}
1303
1304// Reading decimal text
1305
1306/// Eight ASCII zeros.
1307const ASCII_ZEROS: u64 = 0x3030_3030_3030_3030;
1308
1309/// Not zero when a byte of `w` is not an ASCII digit: the high half of each byte must be 3, and
1310/// stay 3 when 6 is added. A carry from adding 6 to one byte into the next comes only from a byte
1311/// of 0xFA or more, which fails anyway.
1312#[inline(always)]
1313fn not_digits(w: u64) -> u64 {
1314 let high = 0xF0F0_F0F0_F0F0_F0F0;
1315 ((w & high) | ((w.wrapping_add(0x0606_0606_0606_0606) & high) >> 4)) ^ 0x3333_3333_3333_3333
1316}
1317
1318/// The value of the eight ASCII digits of `w`, the most significant in the lowest byte: pairs in
1319/// the bytes, `10 x[i] + x[i + 1]`, then the pairs weighted by multiplications whose high halves
1320/// sum them. Wrapping on bytes that are not digits, whose value does not matter.
1321#[inline(always)]
1322fn eight_value(w: u64) -> u64 {
1323 let x = w.wrapping_sub(ASCII_ZEROS);
1324 let x = x.wrapping_mul(10).wrapping_add(x >> 8);
1325 let pairs = 0x0000_00FF_0000_00FF;
1326 (x & pairs)
1327 .wrapping_mul(100 + (1_000_000 << 32))
1328 .wrapping_add(((x >> 16) & pairs).wrapping_mul(1 + (10_000 << 32)))
1329 >> 32
1330}
1331
1332/// The value of the 19 ASCII digits at `p` and whether one is not a digit (not zero then).
1333///
1334/// # Safety
1335///
1336/// The 19 bytes must be valid for reads.
1337#[inline(always)]
1338unsafe fn block_value(p: *const u8) -> (u64, u64) {
1339 // SAFETY: as the caller guarantees: `[0, 8)`, `[8, 16)` and `[11, 19)`.
1340 let (a, b, c) = unsafe {
1341 (
1342 u64::from_le_bytes(read(p)),
1343 u64::from_le_bytes(read(p.add(8))),
1344 u64::from_le_bytes(read(p.add(11))),
1345 )
1346 };
1347 // The last three digits: those of `[11, 19)` with the five that `b` has made zeros.
1348 let low = (c & 0xFFFF_FF00_0000_0000) | 0x0000_0030_3030_3030;
1349 let value = eight_value(a)
1350 .wrapping_mul(100_000_000_000)
1351 .wrapping_add(eight_value(b).wrapping_mul(1000))
1352 .wrapping_add(eight_value(low));
1353 (value, not_digits(a) | not_digits(b) | not_digits(c))
1354}
1355
1356/// The value of the `n` ASCII digits at `p`, from 1 to 19, and whether one is not a digit: copied
1357/// behind zeros to make 19.
1358///
1359/// # Safety
1360///
1361/// The `n` bytes must be valid for reads.
1362#[inline(always)]
1363unsafe fn head_value(p: *const u8, n: usize) -> (u64, u64) {
1364 let mut buffer = [b'0'; 24];
1365 // SAFETY: the buffer holds the 19 digits from 5 up, the last `n` copied.
1366 unsafe {
1367 copy_short(buffer.as_mut_ptr().add(24 - n), p, n);
1368 block_value(buffer.as_ptr().add(5))
1369 }
1370}
1371
1372/// The number of the decimal digits `text`, `negative` if not zero, in `order`; `None` when a
1373/// character is not a digit. Up to 38 digits in registers, up to [`READ_SPLIT`] blocks in limbs.
1374fn read_decimal(text: &[u8], negative: bool, order: ByteOrder) -> Option<Number> {
1375 let n = text.len();
1376 if n <= 38 {
1377 let p = text.as_ptr();
1378 let head = n - 19 * ((n - 1) / 19);
1379 // SAFETY: the reads lie in the text: the head's `head` bytes, then 19 for 20 digits up.
1380 let (x, bad) = unsafe {
1381 let (first, bad) = head_value(p, head);
1382 if n <= 19 {
1383 (u128::from(first), bad)
1384 } else {
1385 let (low, more) = block_value(p.add(head));
1386 (
1387 u128::from(first) * u128::from(TEN_19) + u128::from(low),
1388 bad | more,
1389 )
1390 }
1391 };
1392 return (bad == 0).then(|| small_number(x, negative, order));
1393 }
1394 read_long(text, 10, negative, order)
1395}
1396
1397/// The number of the digits `text` in `radix`, not a power of two, `negative` if not zero, in
1398/// `order`; `None` when a character is not a digit. Up to [`READ_SPLIT`] blocks in limbs, on the
1399/// stack for up to [`STACK_BLOCKS`], and by divide and conquer beyond.
1400fn read_long(text: &[u8], radix: u32, negative: bool, order: ByteOrder) -> Option<Number> {
1401 let (b, k) = block(radix);
1402 let blocks = text.len().div_ceil(k);
1403 if blocks <= READ_SPLIT {
1404 let mut stack = [MaybeUninit::<u64>::uninit(); STACK_BLOCKS + 1];
1405 let mut heap = Vec::new();
1406 let x = if blocks <= STACK_BLOCKS {
1407 stack.as_mut_ptr().cast::<u64>()
1408 } else {
1409 heap.reserve_exact(blocks + 1);
1410 heap.as_mut_ptr()
1411 };
1412 // SAFETY: the limbs have room for one a block and one more.
1413 let len = unsafe { read_blocks(text, radix, b, k, x)? };
1414 return Some(limbs_number(x, len, negative, order));
1415 }
1416 let mut powers = Vec::new();
1417 let x = read_split(text, radix, &mut powers)?;
1418 Some(in_order(x, negative, order))
1419}
1420
1421/// Sets the `len` limbs at `x` to `x b + v`, and returns the limb that carries out of them.
1422///
1423/// # Safety
1424///
1425/// The limbs must be valid for reads and writes.
1426#[inline(always)]
1427unsafe fn mul_add(x: *mut u64, len: usize, b: u64, v: u64) -> u64 {
1428 let mut carry = v;
1429 // SAFETY: as the caller guarantees.
1430 unsafe {
1431 for i in 0..len {
1432 let t = u128::from(*x.add(i)) * u128::from(b) + u128::from(carry);
1433 *x.add(i) = t as u64;
1434 carry = (t >> 64) as u64;
1435 }
1436 }
1437 carry
1438}
1439
1440/// The magnitude `x` as a number with the sign `negative`, in `order`, in one new vector of
1441/// exactly its length.
1442fn small_number(x: u128, negative: bool, order: ByteOrder) -> Number {
1443 let limbs = [x as u64, (x >> 64) as u64];
1444 let len = usize::from(x != 0) + usize::from(x >> 64 != 0);
1445 // SAFETY: the limbs hold the `len` limbs.
1446 limbs_number(limbs.as_ptr().cast_mut(), len, negative, order)
1447}
1448
1449/// The `len` limbs at `x`, least significant first, as a number with the sign `negative`, in
1450/// `order`, in the shortest form, in one new vector of exactly its length.
1451fn limbs_number(x: *mut u64, len: usize, negative: bool, order: ByteOrder) -> Number {
1452 // SAFETY: the caller hands over `len` limbs; the top one is not zero.
1453 let bytes = if len == 0 {
1454 1
1455 } else {
1456 8 * len - unsafe { *x.add(len - 1) }.leading_zeros() as usize / 8
1457 };
1458 let p = Product {
1459 r: if len == 0 { core::ptr::null() } else { x },
1460 len: bytes,
1461 negative: negative && len != 0,
1462 };
1463 let mut value = Vec::with_capacity(bytes);
1464 // SAFETY: the vector has room for the bytes, all of which are written before the length is
1465 // set.
1466 unsafe {
1467 p.write(value.as_mut_ptr(), order);
1468 value.set_len(bytes);
1469 }
1470 Number {
1471 value,
1472 negative: p.negative,
1473 byte_order: order,
1474 }
1475}
1476
1477/// `x`, little-endian in the shortest form, as a number with the sign `negative` in `order`.
1478fn in_order(mut x: Number, negative: bool, order: ByteOrder) -> Number {
1479 if order == ByteOrder::BigEndian {
1480 x.value.reverse();
1481 }
1482 x.negative = negative && x.value != [0];
1483 x.byte_order = order;
1484 x
1485}
1486
1487// Blocks of digits
1488
1489/// Reads the digits `text` in `radix`, not a power of two, in blocks of `k` of `b = radix^k`,
1490/// the first one shorter when the digits do not fill it, into the limbs `x`, least significant
1491/// first; returns how many it holds, or `None` when a character is not a digit. Decimal blocks are
1492/// read eight digits at a time, other ones a digit at a time; they are multiplied in
1493/// [`READ_PASSES`] at a time, once the number has [`READ_WAVES`] limbs.
1494///
1495/// # Safety
1496///
1497/// `x` must be valid for writing one limb a block and one more; only the limbs written are read.
1498unsafe fn read_blocks(text: &[u8], radix: u32, b: u64, k: usize, x: *mut u64) -> Option<usize> {
1499 let n = text.len();
1500 let head = n - k * ((n - 1) / k);
1501 let count = (n - head) / k;
1502 let p = text.as_ptr();
1503 let mut bad = 0u64;
1504 // The value of the `k` digits at `at`, which turns `bad` not zero when one is not a digit.
1505 let mut value = |at: usize, len: usize| -> u64 {
1506 if radix == 10 {
1507 // SAFETY: the `len` bytes at `at` lie in the text, 19 of them for a whole block.
1508 let (v, more) = unsafe {
1509 if len == 19 {
1510 block_value(p.add(at))
1511 } else {
1512 head_value(p.add(at), len)
1513 }
1514 };
1515 bad |= more;
1516 v
1517 } else {
1518 text[at..at + len].iter().fold(0u64, |acc, &c| {
1519 let v = VALUES[usize::from(c)];
1520 bad |= u64::from(u32::from(v) >= radix);
1521 acc.wrapping_mul(u64::from(radix))
1522 .wrapping_add(u64::from(v))
1523 })
1524 }
1525 };
1526 let first = value(0, head);
1527 let mut len = usize::from(first != 0);
1528 let mut j = 0;
1529 let at = |j: usize| head + k * j;
1530 // SAFETY: as the caller guarantees: the number has at most as many limbs as the blocks taken,
1531 // and a group writes at most `READ_PASSES` more limbs than it has, as many as the blocks it
1532 // takes.
1533 unsafe {
1534 *x = first;
1535 while j < count {
1536 if len >= READ_WAVES && count - j >= READ_PASSES {
1537 let v: [u64; READ_PASSES] = core::array::from_fn(|i| value(at(j + i), k));
1538 len = mul_add_group(x, len, b, v);
1539 j += READ_PASSES;
1540 } else {
1541 let carry = mul_add(x, len, b, value(at(j), k));
1542 *x.add(len) = carry;
1543 len += usize::from(carry != 0);
1544 j += 1;
1545 }
1546 }
1547 }
1548 (bad == 0).then_some(len)
1549}
1550
1551/// Sets the `len` limbs at `x` to `(.. ((x b + v[0]) b + v[1]) ..) b + v[K - 1]`, the steps of
1552/// [`mul_add`] `K` times, and returns the new length. The steps of one pass wait for each other,
1553/// two additions on the carry; so the `K` passes run in waves, each a limb behind the one before
1554/// it, from which it takes its limbs in registers, and the core runs their chains side by side.
1555/// Every pass takes `len + K - 1` limbs, zeros above the number, so that their carries come out
1556/// as limbs; the last pass writes its limbs back, after the first one read them.
1557///
1558/// # Safety
1559///
1560/// The `len + K` limbs at `x` must be valid for writes, and the `len` first ones for reads.
1561#[inline(always)]
1562unsafe fn mul_add_group<const K: usize>(x: *mut u64, len: usize, b: u64, v: [u64; K]) -> usize {
1563 let n = len + K - 1;
1564 let mut carry = v;
1565 // The limb that each pass handed the next one in the last wave.
1566 let mut c = [0u64; K];
1567 // SAFETY: as the caller guarantees: in wave `t`, the first pass reads limb `t` below `len`,
1568 // the last one writes limb `t - K + 1`, below `n`, and the last carry goes to limb `n`.
1569 unsafe {
1570 // Pass `p` at limb `t - p` in wave `t`.
1571 let mut wave = |t: usize, from: usize, to: usize| {
1572 let mut p = to;
1573 while p > from {
1574 p -= 1;
1575 let input = if p > 0 {
1576 c[p - 1]
1577 } else if t < len {
1578 *x.add(t)
1579 } else {
1580 0
1581 };
1582 let s = u128::from(input) * u128::from(b) + u128::from(carry[p]);
1583 carry[p] = (s >> 64) as u64;
1584 if p == K - 1 {
1585 *x.add(t - p) = s as u64;
1586 } else {
1587 c[p] = s as u64;
1588 }
1589 }
1590 };
1591 for t in 0..K - 1 {
1592 wave(t, 0, t + 1);
1593 }
1594 for t in K - 1..n {
1595 wave(t, 0, K);
1596 }
1597 for i in 0..K - 1 {
1598 wave(n + i, i + 1, K);
1599 }
1600 *x.add(n) = carry[K - 1];
1601 let mut top = n + 1;
1602 while top > 0 && *x.add(top - 1) == 0 {
1603 top -= 1;
1604 }
1605 top
1606 }
1607}
1608
1609/// The value of the digits `text` in `radix`, not a power of two, as a little-endian number in the
1610/// shortest form, or `None` when a character is not a digit: halves by divide and conquer from
1611/// [`READ_SPLIT`] blocks, the upper one times `b^(2^i)` plus the lower one of `k 2^i` digits; below,
1612/// block by block. `powers` holds the powers `b^(2^i)`, computed as they are first needed.
1613///
1614/// With the power `odd 256^zeros`, the upper half is multiplied by `odd` alone, and the lower one
1615/// added in `zeros` bytes up, but for its bytes below them, which are put below.
1616fn read_split(text: &[u8], radix: u32, powers: &mut Vec<Power>) -> Option<Number> {
1617 let (b, k) = block(radix);
1618 let blocks = text.len().div_ceil(k);
1619 if blocks <= READ_SPLIT {
1620 let mut x = Vec::<u64>::with_capacity(blocks + 1);
1621 // SAFETY: the vector has room for one limb a block and one more.
1622 let len = unsafe { read_blocks(text, radix, b, k, x.as_mut_ptr())? };
1623 return Some(limbs_number(
1624 x.as_mut_ptr(),
1625 len,
1626 false,
1627 ByteOrder::LittleEndian,
1628 ));
1629 }
1630 // The largest `i` whose `k 2^i` places are at most half the digits.
1631 let half = text.len() / 2;
1632 let i = largest(powers, b, k, |_, places| places <= half);
1633 let (places, zeros) = (powers[i].places, powers[i].zeros);
1634 let (high, low) = text.split_at(text.len() - places);
1635 let high = read_split(high, radix, powers)?;
1636 let low = read_split(low, radix, powers)?;
1637 let product = &high * &powers[i].odd;
1638 let mut value = low.value;
1639 let sum = if value.len() > zeros {
1640 let above = Number {
1641 value: value[zeros..].to_vec(),
1642 negative: false,
1643 byte_order: ByteOrder::LittleEndian,
1644 };
1645 &product + &above
1646 } else {
1647 product
1648 };
1649 value.resize(zeros, 0);
1650 value.extend_from_slice(&sum.value);
1651 Some(trimmed(value))
1652}
1653
1654impl core::str::FromStr for Number {
1655 type Err = ParseNumberError;
1656
1657 /// Reads a number from decimal text, as [`Number::from_str_radix`] does with radix 10, and
1658 /// builds it little-endian, the byte order of [`Number::default`].
1659 ///
1660 /// # Examples
1661 ///
1662 /// ```
1663 /// use a::math::numbers::Number;
1664 ///
1665 /// let n: Number = "-123456789012345678901234567890".parse().unwrap();
1666 /// assert!(n.is_negative());
1667 /// assert_eq!(n.to_string(), "-123456789012345678901234567890");
1668 /// assert!("12a".parse::<Number>().is_err());
1669 /// ```
1670 #[inline]
1671 fn from_str(src: &str) -> Result<Number, ParseNumberError> {
1672 Number::from_str_radix(src, 10, ByteOrder::LittleEndian)
1673 }
1674}
1675
1676/// An error from [`Number::from_str_radix`]: what was wrong with the text, from
1677/// [`kind`](Self::kind).
1678#[derive(Debug, Clone, PartialEq, Eq)]
1679pub struct ParseNumberError {
1680 kind: NumberErrorKind,
1681}
1682
1683/// What [`ParseNumberError`] found wrong with the text.
1684#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1685#[non_exhaustive]
1686pub enum NumberErrorKind {
1687 /// The text is empty.
1688 Empty,
1689 /// A character is not a digit of the radix, or the sign has no digits after it.
1690 InvalidDigit,
1691}
1692
1693impl ParseNumberError {
1694 /// What was wrong with the text.
1695 pub fn kind(&self) -> &NumberErrorKind {
1696 &self.kind
1697 }
1698}
1699
1700impl fmt::Display for ParseNumberError {
1701 /// Writes what was wrong, in the words of the primitive integers' `ParseIntError`.
1702 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1703 match self.kind {
1704 NumberErrorKind::Empty => "cannot parse integer from empty string",
1705 NumberErrorKind::InvalidDigit => "invalid digit found in string",
1706 }
1707 .fmt(f)
1708 }
1709}
1710
1711impl std::error::Error for ParseNumberError {}
1712
1713/// Writes the magnitude of `n` in `radix` through `f.pad_integral`, which adds the sign, the
1714/// `prefix` with the `#` flag, and the width, fill and alignment asked for. Up to
1715/// [`STACK_TEXT`] digits are written in a buffer on the stack, longer text in a vector.
1716fn format(
1717 n: &Number,
1718 radix: u32,
1719 prefix: &str,
1720 upper: bool,
1721 f: &mut fmt::Formatter<'_>,
1722) -> fmt::Result {
1723 let x = Operand::of(n);
1724 let bound = digits_bound(x.significant, radix);
1725 let non_negative = !n.negative || x.significant == 0;
1726 let mut stack = [MaybeUninit::<u8>::uninit(); STACK_TEXT];
1727 let mut heap = Vec::new();
1728 let dst = if bound <= STACK_TEXT {
1729 stack.as_mut_ptr().cast::<u8>()
1730 } else {
1731 heap.reserve_exact(bound);
1732 heap.as_mut_ptr()
1733 };
1734 // SAFETY: the buffer has room for the digits, which are written before they are read; they
1735 // are ASCII. `n` is borrowed while it is read.
1736 let digits = unsafe {
1737 let len = write_magnitude(x, radix, dst);
1738 let digits = core::slice::from_raw_parts_mut(dst, len);
1739 if upper {
1740 digits.make_ascii_uppercase();
1741 }
1742 core::str::from_utf8_unchecked(digits)
1743 };
1744 f.pad_integral(non_negative, prefix, digits)
1745}
1746
1747impl fmt::Display for Number {
1748 /// Writes the number in decimal: `-` for a negative number, then the digits; the formatter's
1749 /// flags, width and fill apply as they do to the primitive integers.
1750 ///
1751 /// # Examples
1752 ///
1753 /// ```
1754 /// use a::math::numbers::{ByteOrder, Number};
1755 ///
1756 /// let n = Number::new_from_i64(-1_234_567_890_123, ByteOrder::LittleEndian);
1757 /// assert_eq!(n.to_string(), "-1234567890123");
1758 /// assert_eq!(format!("{:>16}", n), " -1234567890123");
1759 /// assert_eq!(format!("{:+}", Number::new_from_u8(7, ByteOrder::BigEndian)), "+7");
1760 /// ```
1761 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1762 format(self, 10, "", false, f)
1763 }
1764}
1765
1766impl fmt::LowerHex for Number {
1767 /// Writes the number in hexadecimal, lower-case: the sign and the digits of the magnitude, not
1768 /// a two's complement; `0x` in front with the `#` flag.
1769 ///
1770 /// # Examples
1771 ///
1772 /// ```
1773 /// use a::math::numbers::{ByteOrder, Number};
1774 ///
1775 /// let n = Number::new_from_i32(-0xBEEF, ByteOrder::BigEndian);
1776 /// assert_eq!(format!("{n:x}"), "-beef");
1777 /// assert_eq!(format!("{n:#x}"), "-0xbeef");
1778 /// ```
1779 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1780 format(self, 16, "0x", false, f)
1781 }
1782}
1783
1784impl fmt::UpperHex for Number {
1785 /// Writes the number in hexadecimal, upper-case, as [`LowerHex`](fmt::LowerHex) does.
1786 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1787 format(self, 16, "0x", true, f)
1788 }
1789}
1790
1791impl fmt::Octal for Number {
1792 /// Writes the number in octal: the sign and the digits; `0o` in front with the `#` flag.
1793 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1794 format(self, 8, "0o", false, f)
1795 }
1796}
1797
1798impl fmt::Binary for Number {
1799 /// Writes the number in binary: the sign and the digits; `0b` in front with the `#` flag.
1800 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1801 format(self, 2, "0b", false, f)
1802 }
1803}