diff --git a/compiler/rustc_apfloat/src/ieee.rs b/compiler/rustc_apfloat/src/ieee.rs index 2286712f02565..ae938c6a6b982 100644 --- a/compiler/rustc_apfloat/src/ieee.rs +++ b/compiler/rustc_apfloat/src/ieee.rs @@ -1001,6 +1001,7 @@ impl Float for IeeeFloat { (Category::Infinity, _) | (_, Category::Zero) => Status::INVALID_OP.and(Self::NAN), (Category::Normal, Category::Normal) => { + let sign = self.sign; while self.is_finite_non_zero() && rhs.is_finite_non_zero() && self.cmp_abs_normal(rhs) != Ordering::Less @@ -1015,6 +1016,10 @@ impl Float for IeeeFloat { self = unpack!(status=, self - v); assert_eq!(status, Status::OK); } + // IEEE754 requires this + if self.is_zero() { + self.sign = sign; + } Status::OK.and(self) } } diff --git a/tests/ui/numbers-arithmetic/issue-109567.rs b/tests/ui/numbers-arithmetic/issue-109567.rs new file mode 100644 index 0000000000000..81a73595edee6 --- /dev/null +++ b/tests/ui/numbers-arithmetic/issue-109567.rs @@ -0,0 +1,16 @@ +// run-pass +// check-run-results + +pub fn f() -> f64 { + std::hint::black_box(-1.0) % std::hint::black_box(-1.0) +} + +pub fn g() -> f64 { + -1.0 % -1.0 +} + +pub fn main() { + assert_eq!(-1, g().signum() as i32); + assert_eq!((-0.0_f64).to_bits(), f().to_bits()); + assert_eq!(f().signum(), g().signum()); +}