https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115117
Bug ID: 115117
Summary: std::exp(Inf) result invalid with --disable-c99
Product: gcc
Version: 13.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: tomas.kalibera at gmail dot com
Target Milestone: ---
Created attachment 58218
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58218&action=edit
Example program ("im(e^inf):" should be 0, but is not with --disable-c99)
When the C++ library is built without C99 support (e.g. via passing
--disable-c99 to configure of gcc), the result of complex std::exp(Inf) is
incorrect, the imaginary part is NaN, but it should be zero.
It seems this is caused by this code in "complex", which doesn't handle special
cases:
// 26.2.8/3 exp(__z): Returns the complex base e exponential of x
template<typename _Tp>
inline complex<_Tp>
__complex_exp(const complex<_Tp>& __z)
{ return std::polar<_Tp>(exp(__z.real()), __z.imag()); }
that calls into:
template<typename _Tp>
inline complex<_Tp>
polar(const _Tp& __rho, const _Tp& __theta)
{
__glibcxx_assert( __rho >= 0 );
return complex<_Tp>(__rho * cos(__theta), __rho * sin(__theta));
}
where __rho is Inf, so the imaginary part becomes Inf * 0.
For example, the glibc implementation handles this special case explicitly as
follows (./math/s_cexp_template.c):
else if (__glibc_likely (rcls == FP_INFINITE))
{
/* Real part is infinite. */
if (__glibc_likely (icls >= FP_ZERO))
{
/* Imaginary part is finite. */
FLOAT value = signbit (__real__ x) ? 0 : M_HUGE_VAL;
if (icls == FP_ZERO)
{
/* Imaginary part is 0.0. */
__real__ retval = value;
__imag__ retval = __imag__ x;
}
I've this problem happen via _GLIBCXX11_USE_C99_COMPLEX being disabled by
accident, which still has to be investigated, but --disable-c99 reproduces it.
Example program from Andrew Johnson is attached.
I can reproduce the problem on Windows and Linux (on Windows I get nan, on
Linux I get -nan).