diff --git a/stl/inc/complex b/stl/inc/complex index c5de49d13..55670acc6 100644 --- a/stl/inc/complex +++ b/stl/inc/complex @@ -990,9 +990,9 @@ protected: this->_Val[_IM] = (this->_Val[_IM] - this->_Val[_RE] * _Wr) / _Wd; this->_Val[_RE] = _Tmp; } - } else if (_Rightimag == 0) { // set NaN result - this->_Val[_RE] = _Myctraits::_Nanv(); - this->_Val[_IM] = this->_Val[_RE]; + } else if (_Rightimag == 0) { // _Right.real() == 0 && _Right.imag() == 0 + this->_Val[_RE] /= _Rightreal; + this->_Val[_IM] /= _Rightreal; } else { // 0 < |_Right.real()| <= |_Right.imag()| _Ty _Wr = _Rightreal / _Rightimag; _Ty _Wd = _Rightimag + _Wr * _Rightreal; diff --git a/tests/std/tests/Dev10_555491_complex_linker_errors/test.cpp b/tests/std/tests/Dev10_555491_complex_linker_errors/test.cpp index 77e1fdbd7..569adafec 100644 --- a/tests/std/tests/Dev10_555491_complex_linker_errors/test.cpp +++ b/tests/std/tests/Dev10_555491_complex_linker_errors/test.cpp @@ -47,6 +47,148 @@ bool nearly_equal_partwise(const complex actual, const complex expected) { return nearly_equal(actual.real(), expected.real()) && nearly_equal(actual.imag(), expected.imag()); } +// Also test GH-2728 : Implementation divergence for division by zero +void test_gh_2728() { + const complex zero{0, 0}; + const complex minus_zero{-0.0, 0.0}; + constexpr double inf = numeric_limits::infinity(); + constexpr double nan = numeric_limits::quiet_NaN(); + { + const complex test_one_one = complex{1, 1} / zero; + assert(isinf(test_one_one.real())); + assert(test_one_one.real() > 0); + assert(isinf(test_one_one.imag())); + assert(test_one_one.imag() > 0); + } + { + const complex test_one_one = complex{1, 1} / minus_zero; + assert(isinf(test_one_one.real())); + assert(test_one_one.real() < 0); + assert(isinf(test_one_one.imag())); + assert(test_one_one.imag() < 0); + } + { + const complex test_one_zero = complex{1, 0} / zero; + assert(isinf(test_one_zero.real())); + assert(test_one_zero.real() > 0); + assert(isnan(test_one_zero.imag())); + } + { + const complex test_one_minus_one = complex{1, -1} / zero; + assert(isinf(test_one_minus_one.real())); + assert(test_one_minus_one.real() > 0); + assert(isinf(test_one_minus_one.imag())); + assert(test_one_minus_one.imag() < 0); + } + { + const complex test_zero_one = complex{0, 1} / zero; + assert(isnan(test_zero_one.real())); + assert(isinf(test_zero_one.imag())); + assert(test_zero_one.imag() > 0); + } + { + const complex test_zero_zero = complex{0, 0} / zero; + assert(isnan(test_zero_zero.real())); + assert(isnan(test_zero_zero.imag())); + } + { + const complex test_zero_zero = complex{0, 0} / minus_zero; + assert(isnan(test_zero_zero.real())); + assert(isnan(test_zero_zero.imag())); + } + { + const complex test_zero_minus_one = complex{0, -1} / zero; + assert(isnan(test_zero_minus_one.real())); + assert(isinf(test_zero_minus_one.imag())); + assert(test_zero_minus_one.imag() < 0); + } + { + const complex test_minus_one_one = complex{-1, 1} / zero; + assert(isinf(test_minus_one_one.real())); + assert(test_minus_one_one.real() < 0); + assert(isinf(test_minus_one_one.imag())); + assert(test_minus_one_one.imag() > 0); + } + { + const complex test_minus_one_zero = complex{-1, 0} / zero; + assert(isinf(test_minus_one_zero.real())); + assert(test_minus_one_zero.real() < 0); + assert(isnan(test_minus_one_zero.imag())); + } + { + const complex test_minus_one_minus_one = complex{-1, -1} / zero; + assert(isinf(test_minus_one_minus_one.real())); + assert(test_minus_one_minus_one.real() < 0); + assert(isinf(test_minus_one_minus_one.imag())); + assert(test_minus_one_minus_one.imag() < 0); + } + { + const complex test_minus_one_minus_one = complex{-1, -1} / minus_zero; + assert(isinf(test_minus_one_minus_one.real())); + assert(test_minus_one_minus_one.real() > 0); + assert(isinf(test_minus_one_minus_one.imag())); + assert(test_minus_one_minus_one.imag() > 0); + } + { + const complex test_inf_inf = complex{inf, inf} / zero; + assert(isinf(test_inf_inf.real())); + assert(test_inf_inf.real() > 0); + assert(isinf(test_inf_inf.imag())); + assert(test_inf_inf.imag() > 0); + } + { + const complex test_inf_inf = complex{inf, inf} / minus_zero; + assert(isinf(test_inf_inf.real())); + assert(test_inf_inf.real() < 0); + assert(isinf(test_inf_inf.imag())); + assert(test_inf_inf.imag() < 0); + } + { + const complex test_inf_minus_inf = complex{inf, -inf} / zero; + assert(isinf(test_inf_minus_inf.real())); + assert(test_inf_minus_inf.real() > 0); + assert(isinf(test_inf_minus_inf.imag())); + assert(test_inf_minus_inf.imag() < 0); + } + { + const complex test_minus_inf_minus_inf = complex{-inf, -inf} / zero; + assert(isinf(test_minus_inf_minus_inf.real())); + assert(test_minus_inf_minus_inf.real() < 0); + assert(isinf(test_minus_inf_minus_inf.imag())); + assert(test_minus_inf_minus_inf.imag() < 0); + } + { + const complex test_minus_inf_minus_inf = complex{-inf, -inf} / minus_zero; + assert(isinf(test_minus_inf_minus_inf.real())); + assert(test_minus_inf_minus_inf.real() > 0); + assert(isinf(test_minus_inf_minus_inf.imag())); + assert(test_minus_inf_minus_inf.imag() > 0); + } + { + const complex test_one_nan = complex{1, nan} / zero; + assert(isinf(test_one_nan.real())); + assert(test_one_nan.real() > 0); + assert(isnan(test_one_nan.imag())); + } + { + const complex test_nan_one = complex{nan, 1} / zero; + assert(isnan(test_nan_one.real())); + assert(isinf(test_nan_one.imag())); + assert(test_nan_one.imag() > 0); + } + { + const complex test_nan_nan = complex{nan, nan} / zero; + assert(isnan(test_nan_nan.real())); + assert(isnan(test_nan_nan.imag())); + } + { + const complex test_nan_nan = complex{nan, nan} / minus_zero; + assert(isnan(test_nan_nan.real())); + assert(isnan(test_nan_nan.imag())); + } +} + + int main() { complex f(1, 2); @@ -148,4 +290,6 @@ int main() { constexpr double inf = numeric_limits::infinity(); assert((proj(inf) == complex{inf, 0.0})); assert((proj(-inf) == complex{inf, 0.0})); + + test_gh_2728(); }