www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Is this a operator overloading bug?

reply "Tim Fang" <no spam.com> writes:
    I am very new to D and I am trying to implement a Vector3 struct, please 
take a look at the code below, why the output is "nananan"? I use dmd 1.00.

--code---------------------
import std.stdio;

void main()
{
 Vector3 a;
 a.set(1,1,1);
 a = a*2;
 writefln(a.x, a.y, a.z);
}


struct Vector3
{
 float x,y,z;

 // constructor
 void set(float _x, float _y, float _z)
 {
  x = _x;
  y = _y;
  z = _z;
 }

 Vector3 opMul(float s)
 {
  Vector3 ret;
  ret.x = x*s;
  ret.y = y*s;
  ret.z = z*s;
  return ret;
 }
} 
Jan 10 2007
next sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Yikes. That looks to me like it might be a bug introduced by the Named 
Return Value Optimization implemented in DMD 0.178.
   http://www.digitalmars.com/d/glossary.html#nrvo


--bb

Tim Fang wrote:
     I am very new to D and I am trying to implement a Vector3 struct, please 
 take a look at the code below, why the output is "nananan"? I use dmd 1.00.
 
 --code---------------------
 import std.stdio;
 
 void main()
 {
  Vector3 a;
  a.set(1,1,1);
  a = a*2;
  writefln(a.x, a.y, a.z);
 }
 
 
 struct Vector3
 {
  float x,y,z;
 
  // constructor
  void set(float _x, float _y, float _z)
  {
   x = _x;
   y = _y;
   z = _z;
  }
 
  Vector3 opMul(float s)
  {
   Vector3 ret;
   ret.x = x*s;
   ret.y = y*s;
   ret.z = z*s;
   return ret;
  }
 } 
 
 
Jan 10 2007
prev sibling next sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Btw, you might also want to check out Helix before you spend a bunch of 
time writing your own Vector3 type classes.
    http://www.dsource.org/projects/helix

--bb

Tim Fang wrote:
     I am very new to D and I am trying to implement a Vector3 struct, please 
 take a look at the code below, why the output is "nananan"? I use dmd 1.00.
 
 --code---------------------
 import std.stdio;
 
 void main()
 {
  Vector3 a;
  a.set(1,1,1);
  a = a*2;
  writefln(a.x, a.y, a.z);
 }
 
 
 struct Vector3
 {
  float x,y,z;
 
  // constructor
  void set(float _x, float _y, float _z)
  {
   x = _x;
   y = _y;
   z = _z;
  }
 
  Vector3 opMul(float s)
  {
   Vector3 ret;
   ret.x = x*s;
   ret.y = y*s;
   ret.z = z*s;
   return ret;
  }
 } 
 
 
Jan 10 2007
prev sibling next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
I have confirmed that the code below works properly in DMD 0.177 but 
fails in DMD 0.178 (in the same way it does in 1.00), so it does look 
very much like the NRVO is indeed the culprit.

Can you file a bug about it with bugzilla?
   http://d.puremagic.com/issues/

You can get around it for now by making a constructor function (using 
static opCall is popular), and writing your opMul as
    return the_constructor_func(x*s, y*s, z*s);

That seems to work, although I suspect that just means that it's 
disabling the NRVO, which I guess isn't smart enough to do the 
optimization when the return value is passed through several functions.

--bb

Tim Fang wrote:
     I am very new to D and I am trying to implement a Vector3 struct, please 
 take a look at the code below, why the output is "nananan"? I use dmd 1.00.
 
 --code---------------------
 import std.stdio;
 
 void main()
 {
  Vector3 a;
  a.set(1,1,1);
  a = a*2;
  writefln(a.x, a.y, a.z);
 }
 
 
 struct Vector3
 {
  float x,y,z;
 
  // constructor
  void set(float _x, float _y, float _z)
  {
   x = _x;
   y = _y;
   z = _z;
  }
 
  Vector3 opMul(float s)
  {
   Vector3 ret;
   ret.x = x*s;
   ret.y = y*s;
   ret.z = z*s;
   return ret;
  }
 } 
 
 
Jan 11 2007
parent "Tim Fang" <no spam.com> writes:
    Thank you for you reply.


    static opCall() works well. I have downloaded helix lib, it looks pretty 
good!

"Bill Baxter" <dnewsgroup billbaxter.com> 
wrote:eo4r0c$25tg$1 digitaldaemon.com...
I have confirmed that the code below works properly in DMD 0.177 but fails 
in DMD 0.178 (in the same way it does in 1.00), so it does look very much 
like the NRVO is indeed the culprit.

 Can you file a bug about it with bugzilla?
   http://d.puremagic.com/issues/

 You can get around it for now by making a constructor function (using 
 static opCall is popular), and writing your opMul as
    return the_constructor_func(x*s, y*s, z*s);

 That seems to work, although I suspect that just means that it's disabling 
 the NRVO, which I guess isn't smart enough to do the optimization when the 
 return value is passed through several functions.

 --bb

 Tim Fang wrote:
     I am very new to D and I am trying to implement a Vector3 struct, 
 please take a look at the code below, why the output is "nananan"? I use 
 dmd 1.00.

 --code---------------------
 import std.stdio;

 void main()
 {
  Vector3 a;
  a.set(1,1,1);
  a = a*2;
  writefln(a.x, a.y, a.z);
 }


 struct Vector3
 {
  float x,y,z;

  // constructor
  void set(float _x, float _y, float _z)
  {
   x = _x;
   y = _y;
   z = _z;
  }

  Vector3 opMul(float s)
  {
   Vector3 ret;
   ret.x = x*s;
   ret.y = y*s;
   ret.z = z*s;
   return ret;
  }
 }
Jan 11 2007
prev sibling parent reply David Medlock <noone nowhere.com> writes:
Tim Fang wrote:
     I am very new to D and I am trying to implement a Vector3 struct, please 
 take a look at the code below, why the output is "nananan"? I use dmd 1.00.
 
 --code---------------------
 import std.stdio;
 
 void main()
 {
  Vector3 a;
  a.set(1,1,1);
  a = a*2;
  writefln(a.x, a.y, a.z);
 }
 
 
 struct Vector3
 {
  float x,y,z;
 
  // constructor
  void set(float _x, float _y, float _z)
  {
   x = _x;
   y = _y;
   z = _z;
  }
 
  Vector3 opMul(float s)
  {
   Vector3 ret;
   ret.x = x*s;
   ret.y = y*s;
   ret.z = z*s;
   return ret;
  }
 } 
 
 
Its not a bug, you didn't initialize the x,y and z members of Vector3. try: struct Vector3 { float x =0, y =0, z =0; ... } -DavidM
Jan 11 2007
next sibling parent reply "Tim Fang" <no spam.com> writes:
I have called "a.set(1,1,1)" to init the members in main().

"David Medlock" <noone nowhere.com> Wrote
:eo5bif$2sr4$1 digitaldaemon.com...
 Tim Fang wrote:
     I am very new to D and I am trying to implement a Vector3 struct,
 please take a look at the code below, why the output is "nananan"? I use
 dmd 1.00.

 --code---------------------
 import std.stdio;

 void main()
 {
  Vector3 a;
  a.set(1,1,1);
  a = a*2;
  writefln(a.x, a.y, a.z);
 }


 struct Vector3
 {
  float x,y,z;

  // constructor
  void set(float _x, float _y, float _z)
  {
   x = _x;
   y = _y;
   z = _z;
  }

  Vector3 opMul(float s)
  {
   Vector3 ret;
   ret.x = x*s;
   ret.y = y*s;
   ret.z = z*s;
   return ret;
  }
 }
Its not a bug, you didn't initialize the x,y and z members of Vector3. try: struct Vector3 { float x =0, y =0, z =0; ... } -DavidM
Jan 11 2007
parent reply mike <vertex gmx.at> writes:
Am 11.01.2007, 15:07 Uhr, schrieb Tim Fang <no spam.com>:

 I have called "a.set(1,1,1)" to init the members in main().
Yeah, but
  Vector3 opMul(float s)
  {
   Vector3 ret;
   ret.x =3D x*s;
   ret.y =3D y*s;
   ret.z =3D z*s;
   return ret;
  }
creates a new, uninitialized Vector3 and returns it. This should work: ' Vector3 ret; ' ret.set(0., 0., 0.); ' // ... -mike -- = Erstellt mit Operas revolution=E4rem E-Mail-Modul: http://www.opera.com/= mail/
Jan 11 2007
next sibling parent mike <vertex gmx.at> writes:
Am 11.01.2007, 15:24 Uhr, schrieb mike <vertex gmx.at>:

 ' Vector3 ret;
 ' ret.set(0., 0., 0.);
 ' // ...
Ah ... of course you need to initialize with 1, not 0. :) -mike -- = Erstellt mit Operas revolution=E4rem E-Mail-Modul: http://www.opera.com/= mail/
Jan 11 2007
prev sibling next sibling parent reply "Frank Benoit (keinfarbton)" <benoit tionex.removethispart.de> writes:
 creates a new, uninitialized Vector3 and returns it. This should work:
according to the spec, structs should be default initialized. Is this a bug?
Jan 11 2007
next sibling parent David Medlock <noone nowhere.com> writes:
Frank Benoit (keinfarbton) wrote:
creates a new, uninitialized Vector3 and returns it. This should work:
according to the spec, structs should be default initialized. Is this a bug?
The default initialization for float/double/real is nan. Look under 'types'. -DavidM
Jan 11 2007
prev sibling parent mike <vertex gmx.at> writes:
Am 11.01.2007, 15:23 Uhr, schrieb Frank Benoit (keinfarbton)  =

<benoit tionex.removethispart.de>:

 creates a new, uninitialized Vector3 and returns it. This should work=
:
 according to the spec, structs should be default initialized. Is this =
a =
 bug?
No, since floats are initialized to NaN, at least AFAIR. -mike -- = Erstellt mit Operas revolution=E4rem E-Mail-Modul: http://www.opera.com/= mail/
Jan 11 2007
prev sibling next sibling parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
mike wrote:
 Am 11.01.2007, 15:07 Uhr, schrieb Tim Fang <no spam.com>:
 
 I have called "a.set(1,1,1)" to init the members in main().
Yeah, but
  Vector3 opMul(float s)
  {
   Vector3 ret;
   ret.x = x*s;
   ret.y = y*s;
   ret.z = z*s;
   return ret;
  }
creates a new, uninitialized Vector3 and returns it. This should work:
It creates a new default-initialized Vector3, *initializes* it and returns it. I don't see anything wrong with the code. The result of the original code should be "222", not "nannannan". As Bill Baxter said, this is a bug introduced in DMD 0.178. /Oskar
Jan 11 2007
parent reply mike <vertex gmx.at> writes:
Am 11.01.2007, 15:31 Uhr, schrieb Oskar Linde  =

<oskar.lindeREM OVEgmail.com>:

 It creates a new default-initialized Vector3, *initializes* it and  =
 returns it. I don't see anything wrong with the code. The result of th=
e =
 original code should be "222", not "nannannan".
Yes, but the default initializer for float is NaN, so: ' Vector3 opMul(float s) ' { ' Vector3 ret; // <-- creates new, and ' ret.x =3D x*s; // <-- oh, wait a sec ... this x should be initialized= ' ret.y =3D y*s; ' ret.z =3D z*s; ' return ret; ' } '} Now I'm confused ... :) Maybe it's really a bug. -mike -- = Erstellt mit Operas revolution=E4rem E-Mail-Modul: http://www.opera.com/= mail/
Jan 11 2007
parent "Tim Fang" <no spam.com> writes:
' Vector3 opMul(float s)
' {
'  Vector3 ret; // <-- creates new, and
'  ret.x = x*s; // <-- oh, wait a sec ... this x should be initialized

-- x is the member of "Vector3 a", which is declared and initialized in 
"main()".



'  ret.y = y*s;
'  ret.z = z*s;
'  return ret;
' }
'}

"mike" <vertex gmx.at> wrote :op.tlzu9adrnxkcto zimmermoos...
Am 11.01.2007, 15:31 Uhr, schrieb Oskar Linde
<oskar.lindeREM OVEgmail.com>:

 It creates a new default-initialized Vector3, *initializes* it and 
 returns it. I don't see anything wrong with the code. The result of the 
 original code should be "222", not "nannannan".
Yes, but the default initializer for float is NaN, so: ' Vector3 opMul(float s) ' { ' Vector3 ret; // <-- creates new, and ' ret.x = x*s; // <-- oh, wait a sec ... this x should be initialized ' ret.y = y*s; ' ret.z = z*s; ' return ret; ' } '} Now I'm confused ... :) Maybe it's really a bug. -mike -- Erstellt mit Operas revolutionärem E-Mail-Modul: http://www.opera.com/mail/
Jan 11 2007
prev sibling parent "Tim Fang" <no spam.com> writes:
Every member of "Vector3 ret" assigned a new value in the opMul(), It seams 
need not to init "Vector3 ret". However if call ret.set(1,1,1), it works 
well; if call ret.set(0,0,0), it return (0,0,0).  I think this should be a 
bug.


"mike" <vertex gmx.at> wrote:op.tlzubjapnxkcto zimmermoos...
Am 11.01.2007, 15:07 Uhr, schrieb Tim Fang <no spam.com>:

 I have called "a.set(1,1,1)" to init the members in main().
Yeah, but
  Vector3 opMul(float s)
  {
   Vector3 ret;
   ret.x = x*s;
   ret.y = y*s;
   ret.z = z*s;
   return ret;
  }
creates a new, uninitialized Vector3 and returns it. This should work: ' Vector3 ret; ' ret.set(0., 0., 0.); ' // ... -mike -- Erstellt mit Operas revolutionärem E-Mail-Modul: http://www.opera.com/mail/
Jan 11 2007
prev sibling parent reply Leandro Lucarella <llucarella integratech.com.ar> writes:
David Medlock escribió:
 Its not a bug, you didn't initialize the x,y and z members of Vector3.
 
 try:
 
 struct Vector3
 {
   float x =0, y =0, z =0;
 ....
 }
Is there a logical explanation about why floats are initialized to NAN and not zero? -- Leandro Lucarella Integratech S.A. 4571-5252
Jan 11 2007
parent reply "Tomas Lindquist Olsen" <tomas famolsen.dk> writes:
Leandro Lucarella wrote:

 David Medlock escribió:
 Its not a bug, you didn't initialize the x,y and z members of
 Vector3.
 
 try:
 
 struct Vector3
 {
  float x =0, y =0, z =0;
 ....
 }
Is there a logical explanation about why floats are initialized to NAN and not zero?
http://www.digitalmars.com/d/faq.html#nan --
Jan 11 2007
parent Leandro Lucarella <llucarella integratech.com.ar> writes:
Tomas Lindquist Olsen escribió:
 Leandro Lucarella wrote:
 
 David Medlock escribió:
 Its not a bug, you didn't initialize the x,y and z members of
 Vector3.

 try:

 struct Vector3
 {
  float x =0, y =0, z =0;
 ....
 }
Is there a logical explanation about why floats are initialized to NAN and not zero?
http://www.digitalmars.com/d/faq.html#nan
My fault for not looking at the FAQ =) Even so, I think I read this before and I forgot it =P -- Leandro Lucarella Integratech S.A. 4571-5252
Jan 11 2007