[cfe-dev] [libcxx/test] Puzzling floating point behaviour

Howard Hinnant hhinnant at apple.com
Sat Dec 10 10:20:32 PST 2011


On Dec 10, 2011, at 2:04 AM, Edward Meewis wrote:

> On 10-12-11 5:34, Eli Friedman wrote:
>> On Fri, Dec 9, 2011 at 8:23 PM, Edward Meewis
>> <ed at extraordinarymachine.nl>  wrote:
>>> On 10-12-11 1:34, Eli Friedman wrote:
>>>> 
>>>> On Fri, Dec 9, 2011 at 7:58 AM, Edward Meewis
>>>> <ed at extraordinarymachine.nl>    wrote:
>>>>> 
>>>>> <snip>
>>>>> 
>>>>> 
>>>>> I'm guessing long doubles get demoted somewhere. Does anyone have an
>>>>> idea what the problem may be?
>>>> 
>>>> I'm not getting quite the same results as you, but your testcase isn't
>>>> really testing what you want to test: std::exp is not the same as
>>>> ::exp.
>>>> 
>>>> -Eli
>>> 
>>> Thanks, Eli, that's probably a big clue, but I don't get it. This is
>>> probably a stupid question, but can you explain? I would expect all exp's to
>>> be in std::. What's the difference?
>> 
>> std::exp is the properly overloaded exp defined by the C++ standard.
>> ::exp isn't overloaded, so it loses precision.
>> 
>> -Eli
> I am certainly not convinced that things are working properly. The attached program and test script tests 8 cases, all compiled with fresh clang++ and fresh libc++:
> 
> library    WITH_NS_STD    WITH_EXP_OVERLOADED  Result
> -------------------------------------------------------
> libc++     no             no                   d incorrect, dx1 correct
> libc++     no             yes                  d, dx1 correct
> libc++     yes            no                   d, dx1 incorrect
> libc++     yes            yes                  d, dx1 incorrect
> libstdc++  no             no                   d, dx1 correct
> libstdc++  no             yes                  doesn't compile
> libstdc++  yes            no                   d, dx1 correct
> libstdc++  yes            yes                  d, dx1 correct
> 
> I'm going to give it a rest for a while, any ideas are highly appriciated!
> 
> Regards, Ed.
> <pow_complex_test.cpp><test_pow.sh>_______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

Eli alluded to the difference.  In 7 places of pow_complex_test.cpp you're picking up the wrong math function when WITH_NS_STD is not defined.

In <math.h> you have:

double exp(double);
double sin(double);
double cos(double);

In <cmath> you *additionally* have:

namespace std
{
float exp(float);
double exp(double);
long double exp(long double);

float sin(float);
double sin(double);
long double sin(long double);

float cos(float);
double cos(double);
long double cos(long double);
}

In your WITH_EXP_OVERLOAD you silently convert long double to double and call ::exp, ::cos and ::sin unless WITH_NS_STD is defined.

Ditto in main() when computing dx1.  You should qualify all of these calls with std:: to prevent this, e.g.g:

    long double __e = std::exp(__x.real());
    return std::complex<long double>(__e * std::cos(__i), __e * std::sin(__i));

Howard




More information about the cfe-dev mailing list