better implementation of signed div_floor/ceil · qinheping/verify-rust-std@b947f0a
@@ -3023,8 +3023,16 @@ macro_rules! int_impl {
30233023pub const fn div_floor(self, rhs: Self) -> Self {
30243024let d = self / rhs;
30253025let 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 {
30593067pub const fn div_ceil(self, rhs: Self) -> Self {
30603068let d = self / rhs;
30613069let 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}