Small optimization for integers Display implementation · qinheping/verify-rust-std@c4be3da (original) (raw)

`@@ -208,11 +208,46 @@ 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) => {

`

``

211

`+

($($t:ident => size:literalsize:literal size:literal(as positive:identinpositive:ident in positive:identinother:ident)? => named name:ident,)∗;asname:ident,)* ; as name:ident,);asu:ident via convfn:identnamedconv_fn:ident named convfn:identnamedgen_name:ident) => {

`

``

212

+

``

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;

`

``

220

+

``

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 other((!selfasother((!self as other((!selfaspositive).wrapping_add(1), 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 other((!self.other((!self.other((!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

`+

$name(*self, true, f)

`

``

240

`+

}

`

``

241

`+

#[cfg(feature = "optimize_for_size")]

`

``

242

`+

{

`

``

243

`+

$gen_name(*self, true, f)

`

``

244

`+

}

`

``

245

`+

}

`

``

246

`+

}

`

``

247

+

212

248

` #[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];

`

``

249

`+

fn name(mutn:name(mut n: name(mutn:t, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {

`

``

250

`+

let mut buf = [MaybeUninit::::uninit(); $size];

`

216

251

`let mut curr = buf.len();

`

217

252

`let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);

`

218

253

`let lut_ptr = DEC_DIGITS_LUT.as_ptr();

`

`@@ -226,22 +261,26 @@ macro_rules! impl_Display {

`

226

261

`// is safe to access.

`

227

262

`unsafe {

`

228

263

`// need at least 16 bits for the 4-characters-at-a-time to work.

`

229

``

`-

assert!(crate::mem::size_of::<$u>() >= 2);

`

230

``

-

231

``

`-

// eagerly decode 4 characters at a time

`

232

``

`-

while n >= 10000 {

`

233

``

`-

let rem = (n % 10000) as usize;

`

234

``

`-

n /= 10000;

`

235

``

-

236

``

`-

let d1 = (rem / 100) << 1;

`

237

``

`-

let d2 = (rem % 100) << 1;

`

238

``

`-

curr -= 4;

`

239

``

-

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);

`

``

264

`+

#[allow(overflowing_literals)]

`

``

265

`+

#[allow(unused_comparisons)]

`

``

266

`+

// This block will be removed for smaller types at compile time and in the worst

`

``

267

`` +

// case, it will prevent to have the 10000 literal to overflow for i8 and u8.

``

``

268

`+

if core::mem::size_of::<$t>() >= 2 {

`

``

269

`+

// eagerly decode 4 characters at a time

`

``

270

`+

while n >= 10000 {

`

``

271

`+

let rem = (n % 10000) as usize;

`

``

272

`+

n /= 10000;

`

``

273

+

``

274

`+

let d1 = (rem / 100) << 1;

`

``

275

`+

let d2 = (rem % 100) << 1;

`

``

276

`+

curr -= 4;

`

``

277

+

``

278

`` +

// We are allowed to copy to buf_ptr[curr..curr + 3] here since

``

``

279

`` +

// otherwise curr < 0. But then n was originally at least 10000^10

``

``

280

`` +

// which is 10^40 > 2^128 > n.

``

``

281

`+

ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(curr), 2);

`

``

282

`+

ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(curr + 2), 2);

`

``

283

`+

}

`

245

284

`}

`

246

285

``

247

286

`// if we reach here numbers are <= 9999, so at most 4 chars long

`

`@@ -255,6 +294,8 @@ macro_rules! impl_Display {

`

255

294

` ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);

`

256

295

`}

`

257

296

``

``

297

`+

// if we reach here numbers are <= 100, so at most 2 chars long

`

``

298

`` +

// The biggest it can be is 99, and 99 << 1 == 198, so a u8 is enough.

``

258

299

`// decode last 1 or 2 chars

`

259

300

`if n < 10 {

`

260

301

` curr -= 1;

`

`@@ -273,11 +314,10 @@ macro_rules! impl_Display {

`

273

314

` slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr))

`

274

315

`};

`

275

316

` f.pad_integral(is_nonnegative, "", buf_slice)

`

276

``

`-

}

`

``

317

`+

})*

`

277

318

``

278

319

` #[cfg(feature = "optimize_for_size")]

`

279

``

`-

fn name(mutn:name(mut n: name(mutn:u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {

`

280

``

`-

// 2^128 is about 3*10^38, so 39 gives an extra byte of space

`

``

320

`+

fn genname(mutn:gen_name(mut n: genname(mutn:u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {

`

281

321

`let mut buf = [MaybeUninit::::uninit(); 39];

`

282

322

`let mut curr = buf.len();

`

283

323

`let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);

`

`@@ -306,21 +346,6 @@ macro_rules! impl_Display {

`

306

346

`};

`

307

347

` f.pad_integral(is_nonnegative, "", buf_slice)

`

308

348

`}

`

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

349

`};

`

325

350

`}

`

326

351

``

`@@ -374,7 +399,6 @@ macro_rules! impl_Exp {

`

374

399

`(n, exponent, exponent, added_precision)

`

375

400

`};

`

376

401

``

377

``

`-

// 39 digits (worst case u128) + . = 40

`

378

402

`` // Since curr always decreases by the number of digits copied, this means

``

379

403

`` // that curr >= 0.

``

380

404

`let mut buf = [MaybeUninit::::uninit(); 40];

`

`@@ -469,7 +493,7 @@ macro_rules! impl_Exp {

`

469

493

`let n = if is_nonnegative {

`

470

494

`self.$conv_fn()

`

471

495

`} else {

`

472

``

`-

// convert the negative num to positive by summing 1 to it's 2 complement

`

``

496

`+

// convert the negative num to positive by summing 1 to its 2s complement

`

473

497

`(!self.$conv_fn()).wrapping_add(1)

`

474

498

`};

`

475

499

` $name(n, is_nonnegative, false, f)

`

`@@ -484,7 +508,7 @@ macro_rules! impl_Exp {

`

484

508

`let n = if is_nonnegative {

`

485

509

`self.$conv_fn()

`

486

510

`} else {

`

487

``

`-

// convert the negative num to positive by summing 1 to it's 2 complement

`

``

511

`+

// convert the negative num to positive by summing 1 to its 2s complement

`

488

512

`(!self.$conv_fn()).wrapping_add(1)

`

489

513

`};

`

490

514

` $name(n, is_nonnegative, true, f)

`

`@@ -499,8 +523,17 @@ macro_rules! impl_Exp {

`

499

523

`mod imp {

`

500

524

`use super::*;

`

501

525

`impl_Display!(

`

502

``

`-

i8, u8, i16, u16, i32, u32, i64, u64, usize, isize

`

503

``

`-

as u64 via to_u64 named fmt_u64

`

``

526

`+

i8 => 3 as u8 in fmt_u8 => named fmt_i8,

`

``

527

`+

u8 => 3 => named fmt_u8,

`

``

528

`+

i16 => 5 as u16 in fmt_u16 => named fmt_i16,

`

``

529

`+

u16 => 5 => named fmt_u16,

`

``

530

`+

i32 => 10 as u32 in fmt_u32 => named fmt_i32,

`

``

531

`+

u32 => 10 => named fmt_u32,

`

``

532

`+

i64 => 19 as u64 in fmt_u64 => named fmt_i64,

`

``

533

`+

u64 => 20 => named fmt_u64,

`

``

534

`+

isize => 19 as usize in fmt_usize => named fmt_isize,

`

``

535

`+

usize => 20 => named fmt_usize,

`

``

536

`+

; as u64 via to_u64 named fmt_u64

`

504

537

`);

`

505

538

`impl_Exp!(

`

506

539

`i8, u8, i16, u16, i32, u32, i64, u64, usize, isize

`

`@@ -511,8 +544,21 @@ mod imp {

`

511

544

`#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]

`

512

545

`mod imp {

`

513

546

`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);

`

``

547

`+

impl_Display!(

`

``

548

`+

i8 => 3 as u8 in fmt_u8 => named fmt_i8,

`

``

549

`+

u8 => 3 => named fmt_u8,

`

``

550

`+

i16 => 5 as u16 in fmt_u16 => named fmt_i16,

`

``

551

`+

u16 => 5 => named fmt_u16,

`

``

552

`+

i32 => 10 as u32 in fmt_u32 => named fmt_i32,

`

``

553

`+

u32 => 10 => named fmt_u32,

`

``

554

`+

isize => 10 as usize in fmt_usize => named fmt_isize,

`

``

555

`+

usize => 10 => named fmt_usize,

`

``

556

`+

; as u32 via to_u32 named fmt_u32);

`

``

557

`+

impl_Display!(

`

``

558

`+

i64 => 19 as u64 in fmt_u64 => named fmt_i64,

`

``

559

`+

u64 => 20 => named fmt_u64,

`

``

560

`+

; as u64 via to_u64 named fmt_u64);

`

``

561

+

516

562

`impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);

`

517

563

`impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);

`

518

564

`}

`

`@@ -619,7 +665,7 @@ impl fmt::Display for i128 {

`

619

665

`let n = if is_nonnegative {

`

620

666

`self.to_u128()

`

621

667

`} else {

`

622

``

`-

// convert the negative num to positive by summing 1 to it's 2 complement

`

``

668

`+

// convert the negative num to positive by summing 1 to its 2s complement

`

623

669

`(!self.to_u128()).wrapping_add(1)

`

624

670

`};

`

625

671

`fmt_u128(n, is_nonnegative, f)

`