Statalist


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

Re: st: basic quesion about using structures in mata


From   wgould@stata.com (William Gould, StataCorp LP)
To   statalist@hsphsun2.harvard.edu
Subject   Re: st: basic quesion about using structures in mata
Date   Tue, 18 Sep 2007 10:34:22 -0500

Matthew Weinberg <mweinber@gmail.com> writes, 

> I'm trying to use structures for the first time and am having a little 
> trouble.  I want the function markups to take three arguments (s,p,b) 
> and return three arguments (margins, marks, and costs).  I'm getting 
> back one
> 
> My code is:
>
>       struct mups {                      /*define the structure*/
>           real matrix margins
>           real matrix marks
>           real matrix costs
>       }
>
>       struct mups function markups(s,p,b)  /*define the function*/
>       {
>           struct mups scalar ms  /*declare structure variable*/
>           n=rows(s)
>           S=J(n,n,0)
>           for(i=1;i<=n;i++){
>                   for(j=1;j<=n;j++){
>                           S[i,j]=-b*s[i]*s[j]
>                   }
>           }
>           for(i=1;i<=n;i++){
>                   S[i,i]=-b*s[i]*s[i]+b*s[i]
>           }
>           Omega=I(n)*S
>           ms.margins=invsym(Omega)*s
>           ms.costs=p-ms.margins
>           ms.marks=(p-ms.costs):/p
>           return(ms)
>        }
>
> When I evaluate my function, I get back what something like 0x27c65c 
> instead of the three vectors margins, costs, and marks.  

Everything is working as it should.  The result 0x27c65c is the address 
of the structure.  That's what you see when you use a structure interactively, 
such as

	: markups(..., ..., ...)
          0x27c65c                    /* you might see a different address */

However, in a programming context, they work as you might expect.  Try the 
following program with the above, 

        void listresult(struct mups scalar ms)
        {

            "margins is"
            ms.margins

            "marks is"
            ms.marks

            "costs is"
            ms.cost
        }

With that extra program, you could interactively type 

        : listresult(markups(..., ..., ...)) 
        margins is 
          <matrix listed here>
        marks is 
          <matrix listed here>
        costs is
          <matrix listed here>

More usefully, you might have another program that reads 

        void mainroutine(...)
        {
            struct mups scalar m

            ...
            m = markups(..., ..., ...)
            ...
            a = <calculation made with m.margins, m.marks, and m.costs>
            ...
            printf("The final result is %9.2f\n", a)
       }

or

        void anotherroutine(...)
        {
            struct mups scalar m1, m2

            ...
            m1 = markups(..., ..., ...)
            m2 = markups(..., ..., ...)
            ...
            a = <calculation made with m1.margins, m1.marks, and m2.costs
                 and m2.margins, m2.marks, and m2.costs>
            ...
            printf("The final result is %9.2f\n", a)
         }

or

        void lastexample(...)
        {
            struct mups scalar m1, m2

            ...
            m1 = markups(..., ..., ...)
            m2 = markups(..., ..., ...)
            ...
            a = perform_basic_calc(m1)
            b = perform_basic_calc(m2)
            ...
            printf("The final result is %9.2f\n", a+b)
         }

         real scalar perform_basic_calc(struct mps scalar m)
         {
            result = <calculation made with m.margins, m.marks, and m.costs>
            return(result)
         }


So what is 0x27c65c?  In the above examples, markups() returned a structure,
not some hexadecimal number, and we just used what markups() returned as the
structure it is.

This is difficult to explain, so bear with me.

    1.  A structure is, internally, a "pointer" to a memory address.
        That memory address contains the values of the elements of the 
        structure.

    2.  You are not required to know (1) or even understand what (1) 
        means; it is a detail of the implementation of Mata.

    3.  In the programs above, I used variables such as ms, m, m1, and m2 
        to hold the structures returned by markup().  Note that, in each 
        case, I explicitly declared ms, m, m1, and m2 to be struct mups.

    4.  Because I did that, Mata knew ms, m, m1, and m2 were struct mups, 
        and because it knew that, given the structure definition, Mata 
        knew (for instance) m.margins referred to the first element of the
        structure, m.marks referred to the second, and m.costs referred to 
        the third.  Mata also knew that, had I coded m.bill, that would be 
        a mistake because there is no element of the structure mups called
        bill.

    5.  Now consider a line such as 

                 : x = markups(..., ..., ...)

        Note, I typed the line interactively.  Well, you say to yourself, 
        then I suspect is can similarliy refer to x.margins, x.marks, 
        and m.costs.  But you cannot because you did not previously declare 
        x to be a struct mups.  x is just a transmorphic and, as such, 
        it can hold a structure such as a struct mups, but Mata doesn't
        understand that it really is a structure.  Said differently, Mata 
        understands that x is a structure of some sort, but it doesn't know
        that it is in particular a struct mups, and so Mata does not know 
        how to translate things like x.margins, x.marks, and x.costs into 
        1st element, 2nd element, and 3rd element.  For all Mata knows, 
        the translation might be 2nd element, 1st element, and 3rd element, 
        or x.marks might simply be an error and correspond to no element.

    6.  So what happens if you look at x interacctively?  Mata just gives 
        up and shows you the memory address of the structure.

    7.  If the above makes no sense, I apologize.  The short answer is 
        (1) structures work as you would expect INSIDE Mata programs and 
        (2) structures were never intended to work interactively, so 
        don't use them that way.

One more aside.  Concerning notes 5 and 6, while structures cannot be 
interpreted interactively, transmorphics can be used to hold the contents 
of a structure.  For instance, I might interactively type

        : x = markup(.., ..., ...)

        : listresult(x)

and that will work!  x contains the structure, it is just that Mata
can't work out the details of the INTERPRETATION based on what is stored 
in x.  I've mentioned this before:  Mata is a compiler, and being a 
compiler is what makes Mata fast.  


-- 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