Statalist The Stata Listserver


[Date Prev][Date Next][Thread Prev][Thread Next][Date index][Thread index]

Re: st: Mata Structures


From   Ulrich Kohler <kohler@wz-berlin.de>
To   statalist@hsphsun2.harvard.edu
Subject   Re: st: Mata Structures
Date   Wed, 10 May 2006 12:14:11 +0200

Thank you Bill for explanation. Your revised code made our "real" code much 
nicer. From our side there is no need to fix the bug in a hurry ...

Uli

William Gould, Stata wrote:
> Uli and Magdalena Luniak <luniak@wz-berlin.de> asked about structures
> in Mata.
>
> They ran into a bug.  Had they coded a little more efficiently, they never
> would have run into it, but that does not excuse the bug.
>
> Where's what they did:  They had a vector of structures:  v[1] was the
> first struct, v[2] was the second.  The filled in a third structure,
> mypoint, and then stored mypoint in v[1]:
>
>         v[1] = mypoint.
>
> All went well.  The then filled in mypoint with a different set of values,
> and coded
>
>         v[2] = mypoint.
>
> That worked well, too, except that v[1] also changed, and it changed to be
> the same as v[2], namely, mypoint!
>
> Uli and Magdalena made no errors; Mata did.  Rather than storing a copy of
> mypoint in v[1], and then later, a copy of mypoint in v[2], Mata mistakenly
> stored mypoint itself in v[1] and v[2].  v[1], v[2], and mypoint all became
> the same object.
>
> I have just examined this bug in detail.  It occurs when the RHS is a
> structure and the LHS is an element of a structure vector or matrix, i.e.,
> statements of the form,
>
>         v[i] = mypoint
>
>         v[i,j] = mypoint
>
> It does *NOT* occur when the LHS is a scalar,
>
>         v = mypoint
>
> Until the bug is fixed, the workaround is to make the copy that Mata forgot
> to make:
>
>     Rather than code
>                 v[i] = mypoint
>     code
>                 v[i] = copyof(mypoint)
>
>     and rather than code
>                 v[i,j] = mypoint
>     code
>                 v[i,j] = copyof(mypoint)
>
>
> where function copyof() is coded
>
>         transmorphic copyof(transmorphic original)
>         {
>                 transmorphic         copy
>
>                 copy = original
>                 return(copy)
>         }
>
> In Uli's and Magdalena's case, they have a second alternative.  They can
> make their code more efficient and not provoke the bug.  Their original
> code reads,
>
>         struct point vector function help(real vector seq)
>         {
>                  real scalar length
>                  length = length(seq)
>                  struct point vector v
>                  v = point(length)
>                  real scalar i
>                  struct point scalar mypoint
>                  for (i=1; i<=length; i++) {
>                          mypoint.a=seq[i]
>                          mypoint.b=seq[i]
>                          v[i] = mypoint
>                  }
>                  return(v)
>         }
>
> I prefer all the declarations up top.  It is just a matter of style, and
> not even good style vs. bad style, but indulge me, and let me change their
> code to my preferred style before getting to my point:
>
>         struct point vector function help(real vector seq)
>         {
>                  real scalar          i
>                  real scalar          length
>                  struct point vector  v
>                  struct point scalar  mypoint
>
>                  length = length(seq)
>                  v      = point(length)
>                  for (i=1; i<=length; i++) {
>                          mypoint.a=seq[i]
>                          mypoint.b=seq[i]
>                          v[i] = mypoint
>                  }
>                  return(v)
>         }
>
> Style aside, a more efficient version of thier code reads,
>
>         struct point vector function help(real vector seq)
>         {
>                  real scalar          i
>                  real scalar          length
>                  struct point vector  v
>
>                  length = length(seq)
>                  v      = point(length)
>                  for (i=1; i<=length; i++) {
>                         v[i].a = seq[i]
>                         v[i].b = seq[i]
>                  }
>                  return(v)
>         }
>
> Did you know you could do that?  Refer to v[i].a and v[i].b?  On the
> left or on the right?
>
> Pretend v[i] had a third element, a vector c.  Then you could refer to
> v[i].c[j] and v[j].c[i] (which would be different things).
>
> I know, I'm changing the subject.  We will fix the bug, but it will not be
> in the next executable update.  It will be in the one after that.
>
> -- Bill
> wgould@stata.com
> *
> *   For searches and help try:
> *   http://www.stata.com/support/faqs/res/findit.html
> *   http://www.stata.com/support/statalist/faq
> *   http://www.ats.ucla.edu/stat/stata/

-- 
kohler@wz-berlin.de
+49 (030) 25491-361
*
*   For searches and help try:
*   http://www.stata.com/support/faqs/res/findit.html
*   http://www.stata.com/support/statalist/faq
*   http://www.ats.ucla.edu/stat/stata/



© Copyright 1996–2014 StataCorp LP   |   Terms of use   |   Privacy   |   Contact us   |   What's new   |   Site index