LWG-2597 std::log misspecified for complex numbers
When I looked into this briefly, the STL's behavior differed from the UCRT, indicating that we need to change our product code. Currently, I don't have an exhaustive list of the behavior that differs, or the code changes that are necessary.
I did some testing of <complex> behavior.
std::asin, std::asinh, std::acos and std::acosh. #379 std::pow, std::sqrt, std::asin, std::asinh, std::acos, std::acosh, std::atan and std::atanh handle some inputs on the branch cut incorrectly.std::exp, std::pow, std::sqrt, std::asin, std::asinh, std::acos, std::acosh, std::atan and std::atanh could return zero of the wrong sign in the real or imaginary part.operator*, operator/ and all non-_Ugly functions that take at least one std::complex argument and return std::complex, except std::conj, handle some infinity inputs incorrectly. Note that ±∞ + i qNaN and qNaN ± i ∞ are also infinities, not NaNs.std::norm and std::polar, although they are C++ specific and their wording is vague.There are 20+ occurrences of x < 0 in <complex> where x is of floating point type, and probably a few more in xmeow.cpp used by <complex>. x < 0 should not be used to tell the sign of a floating point value (-0.0 < 0 is false), and could be a major source of bugs related to ±0 and branch cuts. I suggest reviewing each of them, and replacing them with std::fabs, std::copysign or std::signbit if that's the intended behavior.
Test case
https://gist.github.com/statementreply/0991bf88d4b943c31d41c27db7592be7
G:\Temp>cl /EHsc /std:c++17 /W4 complex_branch.cpp
用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.24.28314 版
版权所有(C) Microsoft Corporation。保留所有权利。
complex_branch.cpp
Microsoft (R) Incremental Linker Version 14.24.28314.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:complex_branch.exe
complex_branch.obj
G:\Temp>.\complex_branch.exe
Testing arg...
Wrong result: arg(cmplx(+max_norm, +min_subn))
Expected = +0 signal underflow, inexact
Actual = +0 signal inexact
Wrong result: arg(cmplx(+max_norm, -min_subn))
Expected = -0 signal underflow, inexact
Actual = -0 signal inexact
Testing log...
Wrong result: log(cmplx(+0.0, +0.0))
Expected = (-inf,+0) signal div_by_zero
Actual = (-inf,+0)
Wrong result: log(cmplx(+0.0, -0.0))
Expected = (-inf,-0) signal div_by_zero
Actual = (-inf,-0)
Wrong result: log(cmplx(-0.0, +0.0))
Expected = (-inf,+3.1415926535897931) signal div_by_zero, inexact
Actual = (-inf,+3.1415926535897931) signal inexact
Wrong result: log(cmplx(-0.0, -0.0))
Expected = (-inf,-3.1415926535897931) signal div_by_zero, inexact
Actual = (-inf,-3.1415926535897931) signal inexact
Testing pow...
Wrong result: pow(cmplx(-2.0, -0.0), cmplx(+0.25, +0.0))
Expected = (+0.8408964152537145,-0.8408964152537145) signal inexact
Actual = (+0.84089641525371461,+0.84089641525371461) signal inexact
Wrong result: pow(cmplx(-2.0, -0.0), cmplx(-0.25, +0.0))
Expected = (+0.59460355750136051,+0.59460355750136051) signal inexact
Actual = (+0.59460355750136062,-0.59460355750136062) signal inexact
Wrong result: pow(cmplx(-2.0, -0.0), cmplx(+0.0, +1.0))
Expected = (+17.800720977640488,+14.786006499422168) signal inexact
Actual = (+0.03324182700885666,+0.027612020368333014) signal inexact
(...Omitted...)
96 test(s) failed.
Most helpful comment
Test case
https://gist.github.com/statementreply/0991bf88d4b943c31d41c27db7592be7