Statalist The Stata Listserver


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

Re: st: Mata Structures


From   wgould@stata.com (William Gould, Stata)
To   statalist@hsphsun2.harvard.edu
Subject   Re: st: Mata Structures
Date   Mon, 08 May 2006 13:11:59 -0500

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/



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