Auto merge of #128204 - GuillaumeGomez:integers-opti, r=workingjubilee · qinheping/verify-rust-std@7c896fc (original) (raw)
`@@ -208,75 +208,119 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
`
208
208
` 8081828384858687888990919293949596979899";
`
209
209
``
210
210
`macro_rules! impl_Display {
`
211
``
`-
($($t:ident),* as u:identviau:ident via u:identviaconv_fn:ident named $name:ident) => {
`
212
``
`-
#[cfg(not(feature = "optimize_for_size"))]
`
213
``
`-
fn name(mutn:name(mut n: name(mutn:u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
`
214
``
`-
// 2^128 is about 3*10^38, so 39 gives an extra byte of space
`
215
``
`-
let mut buf = [MaybeUninit::::uninit(); 39];
`
216
``
`-
let mut curr = buf.len();
`
217
``
`-
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
`
218
``
`-
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
`
``
211
`+
($($t:ident (as(as (aspositive:ident)? named name:ident,)∗;asname:ident,)* ; as name:ident,)∗;asu:ident via convfn:identnamedconv_fn:ident named convfn:identnamedgen_name:ident) => {
`
219
212
``
220
``
`` -
// SAFETY: Since d1 and d2 are always less than or equal to 198, we
``
221
``
`` -
// can copy from lut_ptr[d1..d1 + 1] and lut_ptr[d2..d2 + 1]. To show
``
222
``
`` -
// that it's OK to copy into buf_ptr, notice that at the beginning
``
223
``
`` -
// curr == buf.len() == 39 > log(n) since n < 2^128 < 10^39, and at
``
224
``
`` -
// each step this is kept the same as n is divided. Since n is always
``
225
``
`` -
// non-negative, this means that curr > 0 so buf_ptr[curr..curr + 1]
``
226
``
`-
// is safe to access.
`
227
``
`-
unsafe {
`
228
``
`-
// need at least 16 bits for the 4-characters-at-a-time to work.
`
229
``
`-
assert!(crate::mem::size_of::<$u>() >= 2);
`
``
213
`+
$(
`
``
214
`+
#[stable(feature = "rust1", since = "1.0.0")]
`
``
215
`+
impl fmt::Display for $t {
`
``
216
`+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
`
``
217
`+
// If it's a signed integer.
`
``
218
`+
$(
`
``
219
`+
let is_nonnegative = *self >= 0;
`
230
220
``
231
``
`-
// eagerly decode 4 characters at a time
`
232
``
`-
while n >= 10000 {
`
233
``
`-
let rem = (n % 10000) as usize;
`
234
``
`-
n /= 10000;
`
``
221
`+
#[cfg(not(feature = "optimize_for_size"))]
`
``
222
`+
{
`
``
223
`+
if !is_nonnegative {
`
``
224
`+
// convert the negative num to positive by summing 1 to its 2s complement
`
``
225
`+
return (!self as $positive).wrapping_add(1)._fmt(false, f);
`
``
226
`+
}
`
``
227
`+
}
`
``
228
`+
#[cfg(feature = "optimize_for_size")]
`
``
229
`+
{
`
``
230
`+
if !is_nonnegative {
`
``
231
`+
// convert the negative num to positive by summing 1 to its 2s complement
`
``
232
`+
return genname((!self.gen_name((!self.genname((!self.conv_fn()).wrapping_add(1), false, f);
`
``
233
`+
}
`
``
234
`+
}
`
``
235
`+
)?
`
``
236
`+
// If it's a positive integer.
`
``
237
`+
#[cfg(not(feature = "optimize_for_size"))]
`
``
238
`+
{
`
``
239
`+
self._fmt(true, f)
`
``
240
`+
}
`
``
241
`+
#[cfg(feature = "optimize_for_size")]
`
``
242
`+
{
`
``
243
`+
genname(self.gen_name(self.genname(self.conv_fn(), true, f)
`
``
244
`+
}
`
``
245
`+
}
`
``
246
`+
}
`
235
247
``
236
``
`-
let d1 = (rem / 100) << 1;
`
237
``
`-
let d2 = (rem % 100) << 1;
`
238
``
`-
curr -= 4;
`
``
248
`+
#[cfg(not(feature = "optimize_for_size"))]
`
``
249
`+
impl $t {
`
``
250
`+
fn _fmt(mut self: $t, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
`
``
251
`+
const SIZE: usize = $t::MAX.ilog(10) as usize + 1;
`
``
252
`+
let mut buf = [MaybeUninit::::uninit(); SIZE];
`
``
253
`+
let mut curr = SIZE;
`
``
254
`+
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
`
``
255
`+
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
`
``
256
+
``
257
`` +
// SAFETY: Since d1 and d2 are always less than or equal to 198, we
``
``
258
`` +
// can copy from lut_ptr[d1..d1 + 1] and lut_ptr[d2..d2 + 1]. To show
``
``
259
`` +
// that it's OK to copy into buf_ptr, notice that at the beginning
``
``
260
`` +
// curr == buf.len() == 39 > log(n) since n < 2^128 < 10^39, and at
``
``
261
`` +
// each step this is kept the same as n is divided. Since n is always
``
``
262
`` +
// non-negative, this means that curr > 0 so buf_ptr[curr..curr + 1]
``
``
263
`+
// is safe to access.
`
``
264
`+
unsafe {
`
``
265
`+
// need at least 16 bits for the 4-characters-at-a-time to work.
`
``
266
`+
#[allow(overflowing_literals)]
`
``
267
`+
#[allow(unused_comparisons)]
`
``
268
`+
// This block will be removed for smaller types at compile time and in the worst
`
``
269
`` +
// case, it will prevent to have the 10000 literal to overflow for i8 and u8.
``
``
270
`+
if core::mem::size_of::<$t>() >= 2 {
`
``
271
`+
// eagerly decode 4 characters at a time
`
``
272
`+
while self >= 10000 {
`
``
273
`+
let rem = (self % 10000) as usize;
`
``
274
`+
self /= 10000;
`
``
275
+
``
276
`+
let d1 = (rem / 100) << 1;
`
``
277
`+
let d2 = (rem % 100) << 1;
`
``
278
`+
curr -= 4;
`
``
279
+
``
280
`` +
// We are allowed to copy to buf_ptr[curr..curr + 3] here since
``
``
281
`` +
// otherwise curr < 0. But then n was originally at least 10000^10
``
``
282
`` +
// which is 10^40 > 2^128 > n.
``
``
283
`+
ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(curr), 2);
`
``
284
`+
ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(curr + 2), 2);
`
``
285
`+
}
`
``
286
`+
}
`
239
287
``
240
``
`` -
// We are allowed to copy to buf_ptr[curr..curr + 3] here since
``
241
``
`` -
// otherwise curr < 0. But then n was originally at least 10000^10
``
242
``
`` -
// which is 10^40 > 2^128 > n.
``
243
``
`-
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
`
244
``
`-
ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(curr + 2), 2);
`
245
``
`-
}
`
``
288
`+
// if we reach here numbers are <= 9999, so at most 4 chars long
`
``
289
`+
let mut n = self as usize; // possibly reduce 64bit math
`
246
290
``
247
``
`-
// if we reach here numbers are <= 9999, so at most 4 chars long
`
248
``
`-
let mut n = n as usize; // possibly reduce 64bit math
`
``
291
`+
// decode 2 more chars, if > 2 chars
`
``
292
`+
if n >= 100 {
`
``
293
`+
let d1 = (n % 100) << 1;
`
``
294
`+
n /= 100;
`
``
295
`+
curr -= 2;
`
``
296
`+
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
`
``
297
`+
}
`
249
298
``
250
``
`-
// decode 2 more chars, if > 2 chars
`
251
``
`-
if n >= 100 {
`
252
``
`-
let d1 = (n % 100) << 1;
`
253
``
`-
n /= 100;
`
254
``
`-
curr -= 2;
`
255
``
`-
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
`
``
299
`+
// if we reach here numbers are <= 100, so at most 2 chars long
`
``
300
`` +
// The biggest it can be is 99, and 99 << 1 == 198, so a u8 is enough.
``
``
301
`+
// decode last 1 or 2 chars
`
``
302
`+
if n < 10 {
`
``
303
`+
curr -= 1;
`
``
304
`+
*buf_ptr.add(curr) = (n as u8) + b'0';
`
``
305
`+
} else {
`
``
306
`+
let d1 = n << 1;
`
``
307
`+
curr -= 2;
`
``
308
`+
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
`
``
309
`+
}
`
256
310
`}
`
257
311
``
258
``
`-
// decode last 1 or 2 chars
`
259
``
`-
if n < 10 {
`
260
``
`-
curr -= 1;
`
261
``
`-
*buf_ptr.add(curr) = (n as u8) + b'0';
`
262
``
`-
} else {
`
263
``
`-
let d1 = n << 1;
`
264
``
`-
curr -= 2;
`
265
``
`-
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
`
266
``
`-
}
`
``
312
`` +
// SAFETY: curr > 0 (since we made buf large enough), and all the chars are valid
``
``
313
`` +
// UTF-8 since DEC_DIGITS_LUT is
``
``
314
`+
let buf_slice = unsafe {
`
``
315
`+
str::from_utf8_unchecked(
`
``
316
`+
slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr))
`
``
317
`+
};
`
``
318
`+
f.pad_integral(is_nonnegative, "", buf_slice)
`
267
319
`}
`
268
``
-
269
``
`` -
// SAFETY: curr > 0 (since we made buf large enough), and all the chars are valid
``
270
``
`` -
// UTF-8 since DEC_DIGITS_LUT is
``
271
``
`-
let buf_slice = unsafe {
`
272
``
`-
str::from_utf8_unchecked(
`
273
``
`-
slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr))
`
274
``
`-
};
`
275
``
`-
f.pad_integral(is_nonnegative, "", buf_slice)
`
276
``
`-
}
`
``
320
`+
})*
`
277
321
``
278
322
` #[cfg(feature = "optimize_for_size")]
`
279
``
`-
fn name(mutn:name(mut n: name(mutn:u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
`
``
323
`+
fn genname(mutn:gen_name(mut n: genname(mutn:u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
`
280
324
`// 2^128 is about 3*10^38, so 39 gives an extra byte of space
`
281
325
`let mut buf = [MaybeUninit::::uninit(); 39];
`
282
326
`let mut curr = buf.len();
`
`@@ -306,21 +350,6 @@ macro_rules! impl_Display {
`
306
350
`};
`
307
351
` f.pad_integral(is_nonnegative, "", buf_slice)
`
308
352
`}
`
309
``
-
310
``
`-
$(#[stable(feature = "rust1", since = "1.0.0")]
`
311
``
`-
impl fmt::Display for $t {
`
312
``
`-
#[allow(unused_comparisons)]
`
313
``
`-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
`
314
``
`-
let is_nonnegative = *self >= 0;
`
315
``
`-
let n = if is_nonnegative {
`
316
``
`-
self.$conv_fn()
`
317
``
`-
} else {
`
318
``
`-
// convert the negative num to positive by summing 1 to it's 2 complement
`
319
``
`-
(!self.$conv_fn()).wrapping_add(1)
`
320
``
`-
};
`
321
``
`-
$name(n, is_nonnegative, f)
`
322
``
`-
}
`
323
``
`-
})*
`
324
353
`};
`
325
354
`}
`
326
355
``
`@@ -374,7 +403,6 @@ macro_rules! impl_Exp {
`
374
403
`(n, exponent, exponent, added_precision)
`
375
404
`};
`
376
405
``
377
``
`-
// 39 digits (worst case u128) + . = 40
`
378
406
`` // Since curr always decreases by the number of digits copied, this means
``
379
407
`` // that curr >= 0.
``
380
408
`let mut buf = [MaybeUninit::::uninit(); 40];
`
`@@ -469,7 +497,7 @@ macro_rules! impl_Exp {
`
469
497
`let n = if is_nonnegative {
`
470
498
`self.$conv_fn()
`
471
499
`} else {
`
472
``
`-
// convert the negative num to positive by summing 1 to it's 2 complement
`
``
500
`+
// convert the negative num to positive by summing 1 to its 2s complement
`
473
501
`(!self.$conv_fn()).wrapping_add(1)
`
474
502
`};
`
475
503
` $name(n, is_nonnegative, false, f)
`
`@@ -484,7 +512,7 @@ macro_rules! impl_Exp {
`
484
512
`let n = if is_nonnegative {
`
485
513
`self.$conv_fn()
`
486
514
`} else {
`
487
``
`-
// convert the negative num to positive by summing 1 to it's 2 complement
`
``
515
`+
// convert the negative num to positive by summing 1 to its 2s complement
`
488
516
`(!self.$conv_fn()).wrapping_add(1)
`
489
517
`};
`
490
518
` $name(n, is_nonnegative, true, f)
`
`@@ -499,8 +527,17 @@ macro_rules! impl_Exp {
`
499
527
`mod imp {
`
500
528
`use super::*;
`
501
529
`impl_Display!(
`
502
``
`-
i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
`
503
``
`-
as u64 via to_u64 named fmt_u64
`
``
530
`+
i8 as u8 named fmt_i8,
`
``
531
`+
u8 named fmt_u8,
`
``
532
`+
i16 as u16 named fmt_i16,
`
``
533
`+
u16 named fmt_u16,
`
``
534
`+
i32 as u32 named fmt_i32,
`
``
535
`+
u32 named fmt_u32,
`
``
536
`+
i64 as u64 named fmt_i64,
`
``
537
`+
u64 named fmt_u64,
`
``
538
`+
isize as usize named fmt_isize,
`
``
539
`+
usize named fmt_usize,
`
``
540
`+
; as u64 via to_u64 named fmt_u64
`
504
541
`);
`
505
542
`impl_Exp!(
`
506
543
`i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
`
`@@ -511,8 +548,21 @@ mod imp {
`
511
548
`#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
`
512
549
`mod imp {
`
513
550
`use super::*;
`
514
``
`-
impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32);
`
515
``
`-
impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64);
`
``
551
`+
impl_Display!(
`
``
552
`+
i8 as u8 named fmt_i8,
`
``
553
`+
u8 named fmt_u8,
`
``
554
`+
i16 as u16 named fmt_i16,
`
``
555
`+
u16 named fmt_u16,
`
``
556
`+
i32 as u32 named fmt_i32,
`
``
557
`+
u32 named fmt_u32,
`
``
558
`+
isize as usize named fmt_isize,
`
``
559
`+
usize named fmt_usize,
`
``
560
`+
; as u32 via to_u32 named fmt_u32);
`
``
561
`+
impl_Display!(
`
``
562
`+
i64 as u64 named fmt_i64,
`
``
563
`+
u64 named fmt_u64,
`
``
564
`+
; as u64 via to_u64 named fmt_u64);
`
``
565
+
516
566
`impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);
`
517
567
`impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);
`
518
568
`}
`
`@@ -619,7 +669,7 @@ impl fmt::Display for i128 {
`
619
669
`let n = if is_nonnegative {
`
620
670
`self.to_u128()
`
621
671
`} else {
`
622
``
`-
// convert the negative num to positive by summing 1 to it's 2 complement
`
``
672
`+
// convert the negative num to positive by summing 1 to its 2s complement
`
623
673
`(!self.to_u128()).wrapping_add(1)
`
624
674
`};
`
625
675
`fmt_u128(n, is_nonnegative, f)
`