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)

`