Stl: LWG-2597 std::log misspecified for complex numbers

Created on 6 Sep 2019  ·  3Comments  ·  Source: microsoft/STL

LWG-2597 std::log misspecified for complex numbers

LWG fixed

Most helpful comment

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.

All 3 comments

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.

  • There are correctness bugs in 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.

    • And also std::norm and std::polar, although they are C++ specific and their wording is vague.

  • Some functions don't correctly signal floating point exceptions.
  • Some functions overflow or underflow spuriously.

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.
Was this page helpful?
0 / 5 - 0 ratings

Related issues

ned14 picture ned14  ·  41Comments

StephanTLavavej picture StephanTLavavej  ·  12Comments

AlexGuteniev picture AlexGuteniev  ·  18Comments

StephanTLavavej picture StephanTLavavej  ·  11Comments

malkia picture malkia  ·  10Comments