Bookmark and Share

Notice: On March 31, it was announced that Statalist is moving from an email list to a forum. The old list will shut down at the end of May, and its replacement, statalist.org is already up and running.


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: st: Copying structures


From   "William Gould, StataCorp LP" <wgould@stata.com>
To   statalist@hsphsun2.harvard.edu
Subject   Re: st: Copying structures
Date   Mon, 15 Apr 2013 10:53:01 -0500

Matthew White <mwhite@poverty-action.org> has found a bug in Mata and
Matthew Baker <matthew.baker@hunter.cuny.edu> has verified it.

We have verified it, too, and found the cause.  We will fix it, but
that will not happen immediately and so let me explain how the problem
arose and show you how to avoid it.

Here is the simpliest example of the bug I can concoct:

        mata:
        struct mys {
                real scalar x
        }

        void myfunc()
        {
                struct mys scalar me
                me.x = 1
                mysub(me)
                me.x
        }

        void mysub(struct mys scalar me)
        {
                struct mys scalar test

                test = me[1]        // <- (1) 
                // test = me        // <- (2)
                test.x = 3
        }

        myfunc()
        end

Choose line (1) and you will observe the bug. Choose line (2), and you
will avoid the bug.  Because all the structures in this example are
scalars, there is no reason to code line (1) but, by the same token, it
is pefectly acceptable to subscript a scalar, and this example allowed  
us to trace the bug to lines like, 

            test = me[1]          /* me a structure or class */

This problem has to do with opimization, but not with -set mataoptimize-
on or off.  From the compiler's point of view, it is not necessary that 
test be a real variable and, to make code run faster, the compiler 
performed a trick.  In copying me[1] to test, it performed a "shallow
copy".  A shallow copy is a new copy of me[1] itself, but all the members 
are linked back to the original.  The compiler incorrectly thought this
shallow copy would be sufficieint.  In most circumstances, a shallow copy 
would have been sufficieint.  Think of the expression, 

            x = me[1].x + 2

In this case, however, me[1] is the entire point of the expression and 
a "deep copy" of me needs to be made.  Mata is not doing that. 

We will fix this.

In the meantime, either 

    1.  Never code 

            <something> = name[i]    

        where name is a struct or class if you are planning on changing 
        any of the members of <something>, or 

    2.  Code

          <something> = cp(name[i])

        where function cp() is defined as 

            transmorphic cp(transmorphic x)
            {
                  transmoprhic   y
                    y = x 
                        return(y) 
            }

Solution (2) forces the compiler to make the correct decision of making 
a deep copy of name[i]. 

We checked and this bug since structures were first added to Mata and
this is the first report we have had of it.

-- Bill
wgould@stata.com
*
*   For searches and help try:
*   http://www.stata.com/help.cgi?search
*   http://www.stata.com/support/faqs/resources/statalist-faq/
*   http://www.ats.ucla.edu/stat/stata/


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