digitalmars.D - Union copy
- =?UTF-8?B?Ikx1w61z?= Marques" (27/27) Oct 21 2013 Consider the following on a 32-bit system:
- =?UTF-8?B?Ikx1w61z?= Marques" (3/3) Oct 21 2013 BTW, I know I can copy the structs directly using the assignment
- Dicebot (3/4) Oct 22 2013 No idea how this is passing on your PC. Are you missing align
- Dicebot (1/1) Oct 22 2013 Ah, nvm, have not noticed the 32-bit part.
- =?UTF-8?B?Ikx1w61z?= Marques" (47/47) Oct 23 2013 Given the lack of feedback, I'm sending a sample scenario and
- Dicebot (3/3) Oct 23 2013 Can you check the value of `double` field in the copy origin
- =?UTF-8?B?Ikx1w61z?= Marques" (31/34) Oct 23 2013 // updated (b.v and writeln)
- Dicebot (4/4) Oct 23 2013 I am afraid you will need to investigate IEEE spec on NaN
- =?UTF-8?B?Ikx1w61z?= Marques" (2/6) Oct 23 2013 OK, thanks for the attempt anyway :-)
- =?UTF-8?B?Ikx1w61z?= Marques" (2/6) Oct 23 2013 I checked, it is not the payload of the NaN that is being changed.
- Dicebot (3/10) Oct 23 2013 I have reproduces the case and it is payload for sure (did you
- =?UTF-8?B?Ikx1w61z?= Marques" (30/32) Oct 23 2013 Hmmm, how are you concluding that?
- Dicebot (5/6) Oct 23 2013 By simply printing all bytes of a union as %b (binary) and
- Dicebot (2/2) Oct 23 2013 P.S. getNaNPayload takes `real`, not `double` and any floating
- =?UTF-8?B?Ikx1w61z?= Marques" (19/23) Oct 23 2013 I'm not sure I follow. The values I have are:
- Dicebot (4/6) Oct 23 2013 Because I am terrible at arithmetic, nevermind :) If it is
- =?UTF-8?B?Ikx1w61z?= Marques" (2/5) Oct 23 2013 Well, thanks for trying to help :-)
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/32) Oct 23 2013 If D's unions are like C's and C++'s, then it is not defined what
- =?UTF-8?B?Ikx1w61z?= Marques" (14/19) Oct 23 2013 Is it not valid to initialize a double with a bit pattern that
- =?UTF-8?B?Ikx1w61z?= Marques" (4/14) Oct 23 2013 (changed during the dst = *srcD assignment, I suppose):
Consider the following on a 32-bit system: union Foo { struct { void* v; int i; } double d; } static assert(Foo.sizeof == 8); void copy(Foo* a, Foo* b) { version(one) { a.v = b.v; a.i = b.i; } version(two) { a.d = b.d; } } Is there a difference between version one and version two? I was getting erroneous copies with version two on Linux and Windows, while it worked fine on OS X. Does it make a difference if the double is a NaN?
Oct 21 2013
BTW, I know I can copy the structs directly using the assignment operator, but I was trying to avoid mixing (translating C -> D) with refactoring / improving.
Oct 21 2013
On Tuesday, 22 October 2013 at 02:47:39 UTC, Luís Marques wrote:static assert(Foo.sizeof == 8);No idea how this is passing on your PC. Are you missing align directive in the snippet?
Oct 22 2013
Given the lack of feedback, I'm sending a sample scenario and results: union Foo { struct { void* v; int i; } double d; } static assert(Foo.sizeof == 8); void copy(Foo* a, Foo* b) { version(one) { a.v = b.v; a.i = b.i; } version(two) { a.d = b.d; } } void main() { Foo a; Foo b; b.i = 0x7ff7a502; copy(&a, &b); writef("%x\n", a.i); writeln(a.d); } Linux (32-bits): $ dmd -version=one test.d && ./test 7ff7a502 nan $ dmd -version=two test.d && ./test 7fffa502 <-- different nan OS X (64-bits, binary forced to 32-bits): $ dmd -m32 -version=one test.d && ./test 7ff7a502 nan $ dmd -m32 -version=two test.d && ./test 7ff7a502 <-- equal nan
Oct 23 2013
Can you check the value of `double` field in the copy origin (immediately after initialization). It may have something to do with floating arithmetic.
Oct 23 2013
On Wednesday, 23 October 2013 at 14:43:07 UTC, Dicebot wrote:Can you check the value of `double` field in the copy origin (immediately after initialization). It may have something to do with floating arithmetic.// updated (b.v and writeln) void main() { Foo a; Foo b; b.v = null; b.i = 0x7ff7a502; writeln("b.d: ", b.d); copy(&a, &b); writef("a.i: %x\n", a.i); writeln("a.d: ", a.d); } Linux: $ dmd -version=one test.d && ./test b.d: nan a.i: 7ff7a502 a.d: nan $ dmd -version=two test.d && ./test b.d: nan a.i: 7fffa502 a.d: nan OS X: $ dmd -m32 -version=one test.d && ./test b.d: nan a.i: 7ff7a502 a.d: nan $ dmd -m32 -version=two test.d && ./test b.d: nan a.i: 7ff7a502 a.d: nan
Oct 23 2013
I am afraid you will need to investigate IEEE spec on NaN assignment here to tell if this is a bug or valid behavior. I have made a quick check but it does not say anything about preserving NaN payload.
Oct 23 2013
On Wednesday, 23 October 2013 at 15:21:20 UTC, Dicebot wrote:I am afraid you will need to investigate IEEE spec on NaN assignment here to tell if this is a bug or valid behavior. I have made a quick check but it does not say anything about preserving NaN payload.OK, thanks for the attempt anyway :-)
Oct 23 2013
On Wednesday, 23 October 2013 at 15:21:20 UTC, Dicebot wrote:I am afraid you will need to investigate IEEE spec on NaN assignment here to tell if this is a bug or valid behavior. I have made a quick check but it does not say anything about preserving NaN payload.I checked, it is not the payload of the NaN that is being changed.
Oct 23 2013
On Wednesday, 23 October 2013 at 15:55:59 UTC, Luís Marques wrote:On Wednesday, 23 October 2013 at 15:21:20 UTC, Dicebot wrote:I have reproduces the case and it is payload for sure (did you took endianness into account?)I am afraid you will need to investigate IEEE spec on NaN assignment here to tell if this is a bug or valid behavior. I have made a quick check but it does not say anything about preserving NaN payload.I checked, it is not the payload of the NaN that is being changed.
Oct 23 2013
On Wednesday, 23 October 2013 at 16:27:56 UTC, Dicebot wrote:I have reproduces the case and it is payload for sure (did you took endianness into account?)Hmmm, how are you concluding that? My assertion that the NaN payload was being correctly preserved was based on the following: union Foo { double d; long l; } void main() { Foo src; Foo dst1; Foo dst2; src.l = 0x7ff7a50200000000; dst1.l = src.l; dst2.d = src.d; writef("src.l:\t%x\n", src.l); writef("dst1.l:\t%x\n", dst1.l); writef("dst2.l:\t%x\n", dst2.l); writef("dst1.payload:\t%x\n", getNaNPayload(dst1.d)); writef("dst2.payload:\t%x\n", getNaNPayload(dst2.d)); } Linux, 32-bit: $ dmd test.d && ./test src.l: 7ff7a50200000000 dst1.l: 7ff7a50200000000 <- the binary representation dst2.l: 7fffa50200000000 <- is different dst1.payload: 3d2810 <- but the decoded payloads dst2.payload: 3d2810 <- seem to be equal
Oct 23 2013
On Wednesday, 23 October 2013 at 16:48:22 UTC, Luís Marques wrote:Hmmm, how are you concluding that?By simply printing all bytes of a union as %b (binary) and checking bit pattern as per http://en.wikipedia.org/wiki/NaN :) I am not really proficient in IEEE stuff so checking bits is only thing I am capable of :P
Oct 23 2013
P.S. getNaNPayload takes `real`, not `double` and any floating numbers conversions may be destructive.
Oct 23 2013
On Wednesday, 23 October 2013 at 16:58:21 UTC, Dicebot wrote:By simply printing all bytes of a union as %b (binary) and checking bit pattern as per http://en.wikipedia.org/wiki/NaN :) I am not really proficient in IEEE stuff so checking bits is only thing I am capable of :PI'm not sure I follow. The values I have are: src.l: 7ff7a50200000000 dst1.l: 7ff7a50200000000 (0111111111110111101001010000001000000000000000000000000000000000) dst2.l: 7fffa50200000000 (0111111111111111101001010000001000000000000000000000000000000000) dst1.d: nan dst2.d: nan dst1.payload: 3d2810 dst2.payload: 3d2810 Making the bit pattern more explicit: S E F P 0 11111111111 0 111101001010000001000000000000000000000000000000000 0 11111111111 1 111101001010000001000000000000000000000000000000000 Is the only different bit not the quiet/signaling NaN flag? Why do you say that the payload is different?
Oct 23 2013
On Wednesday, 23 October 2013 at 17:47:54 UTC, Luís Marques wrote:Is the only different bit not the quiet/signaling NaN flag? Why do you say that the payload is different?Because I am terrible at arithmetic, nevermind :) If it is exactly q/s flag, IEEE spec yummies are even more likely. Not like bit copying via floating assignment is a good idea anyway.
Oct 23 2013
On Wednesday, 23 October 2013 at 21:22:30 UTC, Dicebot wrote:Because I am terrible at arithmetic, nevermind :) If it is exactly q/s flag, IEEE spec yummies are even more likely. Not like bit copying via floating assignment is a good idea anyway.Well, thanks for trying to help :-)
Oct 23 2013
On 10/21/2013 07:47 PM, "Luís Marques" <luis luismarques.eu>" wrote:Consider the following on a 32-bit system: union Foo { struct { void* v; int i; } double d; } static assert(Foo.sizeof == 8); void copy(Foo* a, Foo* b) { version(one) { a.v = b.v; a.i = b.i; } version(two) { a.d = b.d; } } Is there a difference between version one and version two? I was getting erroneous copies with version two on Linux and Windows, while it worked fine on OS X. Does it make a difference if the double is a NaN?If D's unions are like C's and C++'s, then it is not defined what happens when accessing members of the union that are not active. Either the anonymous struct or 'd' above is active, so only that member can be accessed. Ali
Oct 23 2013
On Wednesday, 23 October 2013 at 18:07:37 UTC, Ali Çehreli wrote:If D's unions are like C's and C++'s, then it is not defined what happens when accessing members of the union that are not active. Either the anonymous struct or 'd' above is active, so only that member can be accessed.Is it not valid to initialize a double with a bit pattern that you read from somewhere (e.g. disk)? (reinterpret cast, I guess?). Something like this(?): void main() { long srcL = 0x7ff7a50200000000; double* srcD = cast(double*) &srcL; double dst = *srcD; writef("src: %x\n", srcL); writef("dst: %x\n", *cast(long*) cast(void*) &dst); } If this is valid, the question seems to be why the quiet/signaling flag is changed.
Oct 23 2013
On Wednesday, 23 October 2013 at 18:19:14 UTC, Luís Marques wrote:void main() { long srcL = 0x7ff7a50200000000; double* srcD = cast(double*) &srcL; double dst = *srcD; writef("src: %x\n", srcL); writef("dst: %x\n", *cast(long*) cast(void*) &dst); } If this is valid, the question seems to be why the quiet/signaling flag is changed.(changed during the dst = *srcD assignment, I suppose): src: 7ff7a50200000000 dst: 7fffa50200000000
Oct 23 2013