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

Edward Meewis ed at extraordinarymachine.nl
Sun Dec 11 03:18:41 PST 2011


On 10-12-11 19:20, Howard Hinnant wrote:
> 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
>
Ah, I think the penny dropped.

In which case: shouldn't the template for std::pow be specialized into 
double and long double functions, with one calling exp and the latter 
calling expl?

Anyway, thanks to all who replied,

-- Ed.



More information about the cfe-dev mailing list