October 23, 2014
On Thursday, 23 October 2014 at 21:17:25 UTC, deed wrote:
> Some testing can be found on http://dpaste.dzfl.pl/5f55f4152aa8
> for both Windows and Linux. This just illustrates the sin function.

I think the tests marked "[1]" are expected to fail. They involve
converting one operand of the comparison to double, but not the
other. The comparison is done using real precision. So, one
operand goes through a real->double->real conversion, which
changes the value.
October 23, 2014
On Thursday, 23 October 2014 at 21:42:46 UTC, anonymous wrote:
> On Thursday, 23 October 2014 at 21:17:25 UTC, deed wrote:
>> Some testing can be found on http://dpaste.dzfl.pl/5f55f4152aa8
>> for both Windows and Linux. This just illustrates the sin function.
>
> I think the tests marked "[1]" are expected to fail. They involve
> converting one operand of the comparison to double, but not the
> other. The comparison is done using real precision. So, one
> operand goes through a real->double->real conversion, which
> changes the value.

Then again, I guess they're not guaranteed to fail. I remember
that the compiler is free to use higher than specified precision,
and that Walter feels strongly that this is the right thing to
do. So, the compiler could skip the conversion to double, making
the operands equal again.

And this is presumably what happens in the other failing tests,
where both operands are nominally doubles. One operand is indeed
converted to double. But the other is not, because the compiler
is free to do either.
October 24, 2014
On Thursday, 23 October 2014 at 21:42:46 UTC, anonymous wrote:
> On Thursday, 23 October 2014 at 21:17:25 UTC, deed wrote:
>> Some testing can be found on http://dpaste.dzfl.pl/5f55f4152aa8
>> for both Windows and Linux. This just illustrates the sin function.
>
> I think the tests marked "[1]" are expected to fail. They involve
> converting one operand of the comparison to double, but not the
> other. The comparison is done using real precision. So, one
> operand goes through a real->double->real conversion, which
> changes the value.

You're right about those marked [1]; sin returns real and shouldn't be expected to equal the same value truncated to double or float and then extended back to real.

Converting the sin to double and compare is expected to work for those, and it does when compiled with -m64, but not with -m32, on Linux:

--
import std.math : sin;
import std.conv : to;
double fun (double a) { return sin(a); }

immutable double a = 3.
assert (fun(a) == sin(a).to!double);  // Works when compiled with -m64
--

The behaviour of those only marked [2] and [4] (the 32-bit versions) seems to be a bug.
October 24, 2014
On 10/23/14 2:46 PM, deed wrote:
> On Thursday, 23 October 2014 at 18:26:53 UTC, Steven Schveighoffer wrote:
>> On 10/23/14 2:18 PM, deed wrote:
>>>> Using equality is not a good idea with floating point.
>>>>
>>>> The compiler will on a whim, or depending on whether it can inline or
>>>> not, use higher precision floats, changing the outcome slightly.
>>>>
>>>> I cannot say for certain whether this explains all the issues you
>>>> have, the very last one seems troubling to me at least.
>>>>
>>>
>>> Sure, in many cases it's a bad idea. While I understand that sin(PI) !=
>>> 0.0, but approxEqual(sin(PI), 0.0) == true, I would expect the following
>>> to pass:
>>>
>>> assert (0.0 == 0.0);
>>> assert (1.2345 == 1.2345);
>>> F a = 1.2345, b = 9.8765;
>>>
>>> assert (a+b == b+a);
>>> assert (a*b == b*a);
>>
>> None of these fail on my system
>
> Same for me, that's the point; it's perfectly valid to compare floating
> points.

OK. I think to be frank, your explanation by example needs to be accompanied with what the result is (you do this below, thanks). From the above, it sounds like they did not pass, but you expected them to.

As to your assertion that it's perfectly valid to compare floating points, I think examples where they compare equal do not prove all equivalent floating point calculations should compare equal.

Is it valid? Yes. Is it wise? No.

>>> F fun (F a) pure;
>>>
>>> assert (fun(a) + fun(b) == fun(b) + fun(a));
>>> assert (fun(a) * fun(b) == fun(b) * fun(a));
>>>
>>> auto a = fun(100);
>>> auto b = fun(100);
>>>
>>> assert (a == b);
>>> assert (fun(100) == fun(100));
>>>
>>
>> Not sure what body of fun is, so I cannot test this.
>
> Could be anything taking a floating point and returning a floating point.
> You would expect to get the same back for the same input, especially when
> it's pure. If so, the asserts above are expected to hold.

OK, I get that. I agree, it should be equal.

>>> Now, if fun's body is { return sin(a); }, the behaviour changes to:
>>>
>>> auto c = fun(100);
>>> auto d = fun(100);
>>>
>>> assert (c == d);              // Ok
>>> assert (fun(100) != fun(100)) // I have a hard time understanding
>>>                               // this is correct behaviour
>>
>> Tried that out, it does not fail on my machine. Can you be more
>> specific on your testing? What compiler/platform? Stock compiler, or
>> did you build it yourself?
>
> Right. It doesn't fail, and that's the problem.

Sorry, I said this wrong. I tried out fun(100) == fun(100) and the assert passed.

>
> assert (fun(100) == fun(100));  // Should pass, and does with
>                                  // body { return a + 1; }
>                                  // but not with
>                                  // body { return sin(a); }

Does not fail for me for sin(a) case.

> Compiler: DMD32 D Compiler v2.066.0

OK, I tried with OSX 64-bit compiler. Perhaps 32 bit would not fare as well. What platform are you testing on?

-Steve
October 24, 2014
> OK, I tried with OSX 64-bit compiler. Perhaps 32 bit would not fare as well. What platform are you testing on?

Have tried Linux and Windows 64-bit and it seems to be an issue when compiled with -m32. Tests are provided here http://dpaste.dzfl.pl/5f55f4152aa8.

I agree that one cannot compare double and real and expect equality, so the ones marked with [1] are not incorrect behaviour, while [2] and [4] seem to be bugs.

1 2
Next ›   Last »