Description
In line 745 of file libcxx/include/cmath the following function template is defined:
template <class _Tp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp __x, int __exp)
This function can be called with a value of type long double
as the first argument (e.g., line 710 of file libcxx/include/complex). However, its return statement is:
return __builtin_scalbn(__x, __exp);
This other built-in function takes a double
as the first argument (instead of a long double
) and also returns a double
(instead of a long double
). This accuracy loss yields undesired results, as it can be seen in the following example (Compiler Explorer):
#include <complex>
int main( ){
bool res = true;
const std::complex<long double> &a = {0.L, 0.5L};
const std::complex<long double> &b = {0.L, 0.549306144334054845697622618461262852323745278911374725867L};
std::complex<long double> x = std::atan<>( a );
res &= ( std::real<long double>(x) == std::real<long double>(b) );
res &= ( std::imag<long double>(x) == std::imag<long double>(b) );
return !res;
}
This bug was found in clang 16.0.0
using the SuperTest suite, clang 15.0.0
still works fine.
Compilation flags: -m64 -std=c++20 -stdlib=libc++ -O0 -funsigned-char
Replacing the call to __builtin_scalbn()
with a call to __builtin_scalbnl()
for this case should fix it (or creating a specialization).