Jump to page: 1 2
Thread overview
[dmd-beta] Struct Comparision WTF: Is the new or old behavior right?
Dec 10, 2011
David Simcha
Dec 10, 2011
Walter Bright
Dec 10, 2011
Jonathan M Davis
Dec 10, 2011
Walter Bright
Dec 10, 2011
Jonathan M Davis
Dec 10, 2011
Don Clugston
Dec 10, 2011
Jonathan M Davis
Dec 10, 2011
kenji hara
Dec 10, 2011
David Simcha
Dec 10, 2011
Jesse Phillips
Dec 10, 2011
David Simcha
Dec 11, 2011
Simen Kjærås
Dec 10, 2011
kenji hara
December 10, 2011
Using DMD 2.057 beta:

// test2.d:
import std.stdio;

struct S {
     double d;  // NaN
}

void main() {
     S s;
     writeln(s == S.init);
}

$ dmd test2.d -m32
$ ./test2
true
$ dmd test2.d -m64
$ ./test2
false

Somehow I think it's a bad idea to have the result of this comparison change depending on whether you're compiling in 32- or 64-bit mode.  I just spent a few hours debugging Plot2kill because this behavior changed between releases in 64-bit mode, and I was comparing font structs to their .init values to determine whether they had already been initialized.  Everything worked in 32-bit mode but failed in 64-bit mode.  In 64-bit mode it looked like the structs had already been initialized (e.g. titleFont == Font.init is false) so they never got initialized.  Needless to say, GTK does weird things when you pass in a NaN as a font size.
December 09, 2011

On 12/9/2011 10:36 PM, David Simcha wrote:
> Using DMD 2.057 beta:
>
> // test2.d:
> import std.stdio;
>
> struct S {
>     double d;  // NaN
> }
>
> void main() {
>     S s;
>     writeln(s == S.init);
> }
>
> $ dmd test2.d -m32
> $ ./test2
> true
> $ dmd test2.d -m64
> $ ./test2
> false
>
> Somehow I think it's a bad idea to have the result of this comparison change depending on whether you're compiling in 32- or 64-bit mode.  I just spent a few hours debugging Plot2kill because this behavior changed between releases in 64-bit mode, and I was comparing font structs to their .init values to determine whether they had already been initialized.  Everything worked in 32-bit mode but failed in 64-bit mode.  In 64-bit mode it looked like the structs had already been initialized (e.g. titleFont == Font.init is false) so they never got initialized.  Needless to say, GTK does weird things when you pass in a NaN as a font size.
>

The 32 bit code is wrong (please file a bug report). Comparisons should always yield false if one or both operands is a nan.
December 10, 2011
On Friday, December 09, 2011 23:56:30 Walter Bright wrote:
> On 12/9/2011 10:36 PM, David Simcha wrote:
> > Using DMD 2.057 beta:
> > 
> > // test2.d:
> > import std.stdio;
> > 
> > struct S {
> > 
> >     double d;  // NaN
> > 
> > }
> > 
> > void main() {
> > 
> >     S s;
> >     writeln(s == S.init);
> > 
> > }
> > 
> > $ dmd test2.d -m32
> > $ ./test2
> > true
> > $ dmd test2.d -m64
> > $ ./test2
> > false
> > 
> > Somehow I think it's a bad idea to have the result of this comparison change depending on whether you're compiling in 32- or 64-bit mode.  I just spent a few hours debugging Plot2kill because this behavior changed between releases in 64-bit mode, and I was comparing font structs to their .init values to determine whether they had already been initialized.  Everything worked in 32-bit mode but failed in 64-bit mode.  In 64-bit mode it looked like the structs had already been initialized (e.g. titleFont == Font.init is false) so they never got initialized.  Needless to say, GTK does weird things when you pass in a NaN as a font size.
> 
> The 32 bit code is wrong (please file a bug report). Comparisons should always yield false if one or both operands is a nan.

That makes it kind of ugly for init though, since it's often useful to check whether a value is equal to its type's init value. Treating NaN like this means that you can't do such equality checks if your type includes any floating point values - directly or indirectly. But it _would_ break the normal behavior of NaN to make init values act differently (and likely complicate the code generation a fair bit, since it would mean special casing init with regards to equality). So, I guess that it just means that you have to be careful when dealing with default-initialized floating point values.

Part of me thinks that NaN should be equal to NaN, but it's likely too late for that at this point, even if it were determined to be a good idea.

In any case, it's a bit funny to see a code generation error which is correct in 64-bit mode and incorrect in 32-bit mode. That's the reverse of what normally happens.

- Jonathan M Davis
December 10, 2011

On 12/10/2011 12:01 AM, Jonathan M Davis wrote:
> Part of me thinks that NaN should be equal to NaN, but it's likely too late for that at this point, even if it were determined to be a good idea.
>

That issue was decided at least 25 years ago.

December 10, 2011
You can use s is S.init for bitwise comparison.
2011/12/10 17:02 "Jonathan M Davis" <jmdavisProg at gmx.com>:

> On Friday, December 09, 2011 23:56:30 Walter Bright wrote:
> > On 12/9/2011 10:36 PM, David Simcha wrote:
> > > Using DMD 2.057 beta:
> > >
> > > // test2.d:
> > > import std.stdio;
> > >
> > > struct S {
> > >
> > >     double d;  // NaN
> > >
> > > }
> > >
> > > void main() {
> > >
> > >     S s;
> > >     writeln(s == S.init);
> > >
> > > }
> > >
> > > $ dmd test2.d -m32
> > > $ ./test2
> > > true
> > > $ dmd test2.d -m64
> > > $ ./test2
> > > false
> > >
> > > Somehow I think it's a bad idea to have the result of this comparison change depending on whether you're compiling in 32- or 64-bit mode.  I just spent a few hours debugging Plot2kill because this behavior changed between releases in 64-bit mode, and I was comparing font structs to their .init values to determine whether they had already been initialized.  Everything worked in 32-bit mode but failed in 64-bit mode.  In 64-bit mode it looked like the structs had already been initialized (e.g. titleFont == Font.init is false) so they never got initialized.  Needless to say, GTK does weird things when you pass in a NaN as a font size.
> >
> > The 32 bit code is wrong (please file a bug report). Comparisons should always yield false if one or both operands is a nan.
>
> That makes it kind of ugly for init though, since it's often useful to
> check
> whether a value is equal to its type's init value. Treating NaN like this
> means that you can't do such equality checks if your type includes any
> floating
> point values - directly or indirectly. But it _would_ break the normal
> behavior of NaN to make init values act differently (and likely complicate
> the
> code generation a fair bit, since it would mean special casing init with
> regards to equality). So, I guess that it just means that you have to be
> careful when dealing with default-initialized floating point values.
>
> Part of me thinks that NaN should be equal to NaN, but it's likely too late for that at this point, even if it were determined to be a good idea.
>
> In any case, it's a bit funny to see a code generation error which is
> correct
> in 64-bit mode and incorrect in 32-bit mode. That's the reverse of what
> normally happens.
>
> - Jonathan M Davis
> _______________________________________________
> dmd-beta mailing list
> dmd-beta at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-beta
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/dmd-beta/attachments/20111210/b414b40a/attachment-0001.html>
December 10, 2011
Current dmd front-end does not generate member-wise comparison code
for floating point members.
It is already filed as issue 3789 (and I've posted a pull request
dmd/#387 to fix it).

So 64bit mode result is *accidentally* correct.

Kenji Hara

2011/12/10 Walter Bright <walter at digitalmars.com>:
>
>
> On 12/9/2011 10:36 PM, David Simcha wrote:
>>
>> Using DMD 2.057 beta:
>>
>> // test2.d:
>> import std.stdio;
>>
>> struct S {
>> ? ?double d; ?// NaN
>> }
>>
>> void main() {
>> ? ?S s;
>> ? ?writeln(s == S.init);
>> }
>>
>> $ dmd test2.d -m32
>> $ ./test2
>> true
>> $ dmd test2.d -m64
>> $ ./test2
>> false
>>
>> Somehow I think it's a bad idea to have the result of this comparison change depending on whether you're compiling in 32- or 64-bit mode. ?I just spent a few hours debugging Plot2kill because this behavior changed between releases in 64-bit mode, and I was comparing font structs to their .init values to determine whether they had already been initialized. ?Everything worked in 32-bit mode but failed in 64-bit mode. ?In 64-bit mode it looked like the structs had already been initialized (e.g. titleFont == Font.init is false) so they never got initialized. ?Needless to say, GTK does weird things when you pass in a NaN as a font size.
>>
>
> The 32 bit code is wrong (please file a bug report). Comparisons should always yield false if one or both operands is a nan.
>
> _______________________________________________
> dmd-beta mailing list
> dmd-beta at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-beta
December 10, 2011
On 12/10/2011 3:25 AM, kenji hara wrote:
>
> You can use s is S.init for bitwise comparison.
>

That gives me the same results as using ==.  I ended up working around my immediate problem in Plot2kill by using memcmp, but in general this behavior needs to be better specified.

I was not even aware that `is` was defined for anything other than pointers/class references before this conversation.   As you implicitly suggested, I think `is` should be defined for all types and should mean "guaranteed to return true iff lhs is bitwise identical to rhs.  Will not dereference pointers, will not call opEquals, will not return false because of NaNs".

Also, the behavior of == _must_ be consistent on 32- and 64-bit.  Since I know this definitely is a bug, I'll file a report for it.
December 10, 2011
Don't NaN's have several bit patterns and thus this isn't always true, but good enough and possibly expected?

On Sat, Dec 10, 2011 at 9:24 AM, David Simcha <dsimcha at gmail.com> wrote:
> will not return false because of NaNs".
December 10, 2011
On 12/10/2011 1:30 PM, Jesse Phillips wrote:
> Don't NaN's have several bit patterns and thus this isn't always true, but good enough and possibly expected?
>
> On Sat, Dec 10, 2011 at 9:24 AM, David Simcha<dsimcha at gmail.com>  wrote:
>> will not return false because of NaNs".
> _______________________________________________
> dmd-beta mailing list
> dmd-beta at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-beta
>
Right.  I meant that NaNs with the same bit pattern are identical as evaluated by `is`.
December 10, 2011
On Saturday, December 10, 2011 00:11:55 Walter Bright wrote:
> On 12/10/2011 12:01 AM, Jonathan M Davis wrote:
> > Part of me thinks that NaN should be equal to NaN, but it's likely too late for that at this point, even if it were determined to be a good idea.
> That issue was decided at least 25 years ago.

So it pre-dates D by a fair chunk huh. Well, as I said, I figured that it was probably too late to change it. I guess that I'll just have to make sure that I unit test whether an init value equals itself for every struct type that I use so that I can catch this sort of situation. I'd say that this definitely falls in one of those "forced faults" that Andrei has talked about, where one language design forces a suboptimal design decision elsewhere. It's annoying but not hard to deal with if you know about it. Just one more thing to be careful about I guess.

- Jonathan M Davis
« First   ‹ Prev
1 2