Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<complex>: pow, incorrect type conversion #1260

Closed
fsb4000 opened this issue Sep 3, 2020 · 1 comment · Fixed by #1299
Closed

<complex>: pow, incorrect type conversion #1260

fsb4000 opened this issue Sep 3, 2020 · 1 comment · Fixed by #1299
Labels
bug Something isn't working fixed Something works now, yay!

Comments

@fsb4000
Copy link
Contributor

fsb4000 commented Sep 3, 2020

Describe the bug
wrong results with pow

Command-line test case

C:\Temp>type repro.cpp
#include <complex>
#include <type_traits>
#include <cassert>

template <typename T>
double promote(T, typename std::enable_if<std::is_integral<T>::value>::type* = 0);

float promote(float);
double promote(double);
long double promote(long double);

#pragma warning(disable:4244)
template <typename T,  typename U>
void test(const std::complex<T>& x, U y)
{
    typedef decltype(promote(std::real(x))+promote(y)) V;
    static_assert((std::is_same<decltype(std::pow(x, y)), std::complex<V> >::value), "");
    
    assert(std::pow(x, y) == std::pow(std::complex<V>(x), std::complex<V>(y, 0)));
    // (std::pow(x, y) - std::pow(std::complex<V>(x), std::complex<V>(y, 0)) == (1.7053e-12,-4.54747e-13)
    // if we cast y to V then it works:
    //assert(std::pow(x, static_cast<V>(y)) == std::pow(std::complex<V>(x), std::complex<V>(y, 0)));
}

int main()
{
    const auto cf = std::complex(3.0f, 4.0f);
    const auto cd = std::complex(3.0, 4.0);
    const auto cld = std::complex(3.0L, 4.0L);

    test(cf, 5);
    test(cd, 5);
    test(cld, 5);

    test(cf, 5u);
    test(cd, 5u);
    test(cld, 5u);

    test(cf, 5LL);
    test(cd, 5LL);
    test(cld, 5LL);
}

C:\Temp>cl /W4 /WX  /EHsc /std:c++latest repro.cpp
Оптимизирующий компилятор Microsoft (R) C/C++ версии 19.28.29213 для x64
(C) Корпорация Майкрософт (Microsoft Corporation).  Все права защищены.

/std:c++latest предоставляется как предварительная версия языковых функций из последнего
рабочего черновика C++. Мы приветствуем сообщения об ошибках и предложения к улучшению.
Однако обратите внимание, что эти функции предоставляются как есть, без поддержки и могут
измениться или быть удалены по мере развития рабочего черновика. Дополнительные сведения:
https://go.microsoft.com/fwlink/?linkid=2045807.

repro.cpp
Microsoft (R) Incremental Linker Version 14.28.29213.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:repro.exe
repro.obj

C:\Temp>repro
Assertion failed: std::pow(x, y) == std::pow(std::complex<V>(x), std::complex<V>(y, 0)), file repro.cpp, line 19

Expected behavior
Tests should pass

STL version
Microsoft Visual Studio Community 2019 Preview Version 16.8.0 Preview 2.0

Additional context
Skipped libcxx test

# STL bug: Incorrect return types.
std/numerics/complex.number/cmplx.over/pow.pass.cpp FAIL

@StephanTLavavej StephanTLavavej added bug Something isn't working libcxx_skip labels Sep 4, 2020
@fsb4000
Copy link
Contributor Author

fsb4000 commented Sep 4, 2020

if we change current implementation
https://github.com/microsoft/STL/blob/master/stl/inc/complex#L1879-L1899
to

template <class _Ty1, class _Ty2, enable_if_t<!is_integral_v<_Ty1> && is_integral_v<_Ty2>, int> = 0>
_NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const complex<_Ty1>& _Left, const _Ty2 _Right) {
    using type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
    return _STD pow(type(_Left), type(_Right));
}

then the libc++ test will pass.
But should we?
Current implementation looks fine for me, and difference is really small:

(std::pow(x, y) - std::pow(std::complex<V>(x), std::complex<V>(y, 0)) == (1.7053e-12,-4.54747e-13)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixed Something works now, yay!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants