better implementation of signed div_floor/ceil · qinheping/verify-rust-std@b947f0a

@@ -3023,8 +3023,16 @@ macro_rules! int_impl {

30233023

pub const fn div_floor(self, rhs: Self) -> Self {

30243024

let d = self / rhs;

30253025

let r = self % rhs;

3026-

if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {

3027-

d - 1

3026+3027+

// If the remainder is non-zero, we need to subtract one if the

3028+

// signs of self and rhs differ, as this means we rounded upwards

3029+

// instead of downwards. We do this branchlessly by creating a mask

3030+

// which is all-ones iff the signs differ, and 0 otherwise. Then by

3031+

// adding this mask (which corresponds to the signed value -1), we

3032+

// get our correction.

3033+

let correction = (self ^ rhs) >> (Self::BITS - 1);

3034+

if r != 0 {

3035+

d + correction

30283036

} else {

30293037

d

30303038

}

@@ -3059,8 +3067,12 @@ macro_rules! int_impl {

30593067

pub const fn div_ceil(self, rhs: Self) -> Self {

30603068

let d = self / rhs;

30613069

let r = self % rhs;

3062-

if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) {

3063-

d + 1

3070+3071+

// When remainder is non-zero we have a.div_ceil(b) == 1 + a.div_floor(b),

3072+

// so we can re-use the algorithm from div_floor, just adding 1.

3073+

let correction = 1 + ((self ^ rhs) >> (Self::BITS - 1));

3074+

if r != 0 {

3075+

d + correction

30643076

} else {

30653077

d

30663078

}