Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Returning pointer matrixes in functions

    This idea is probably well known to serious Mata programmers, but I've recently come across what appears to be a valuable (valuable to me, at least) use of pointer matrixes. Specifically, when defining a function one might wish to return a variety of results of different types and dimensions. Using a pointer matrix to store these results and then return them as a function's return seems generally workable. Here's a simple example
    Code:
    capture mata mata drop returnpointer()
    
    mata
    
    function returnpointer() {
     pointer matrix p
     string matrix ss,ls
     real matrix sr,lr
      p=J(4,1,NULL)
      ss="a","b"
      ls="a","b","c"
      sr=1,2
      lr=1,2,3,4
      p[1]=&ss
      p[2]=&ls
      p[3]=&sr
      p[4]=&lr
     return(p)
    }
    
    for (j=1;j<=4;j++) {
     *returnpointer()[j]
    }
    
    end
    which gives this output
    Code:
    :
    : for (j=1;j<=4;j++) {
    >  *returnpointer()[j]
    > }
           1   2
        +---------+
      1 |  a   b  |
        +---------+
           1   2   3
        +-------------+
      1 |  a   b   c  |
        +-------------+
           1   2
        +---------+
      1 |  1   2  |
        +---------+
           1   2   3   4
        +-----------------+
      1 |  1   2   3   4  |
        +-----------------+
    
    :
    What I'm wondering is whether the pointer experts among you see any obvious concerns with using such an approach OR whether there are more-straightforward strategies that would accomplish the same objective. Thanks in advance for any wisdom you might pass along.

  • #2
    Nice, I think it will come in handy for me as well
    Kind regards

    nhb

    Comment


    • #3
      I often want to do this kind of thing when the function is part of a larger system of functions. In those cases I use two alternative solutions. Sometimes I work with structures (help [M-2] struct). I think of a structure as a big box, with all kinds of labelled partitions that I can hand from one function to the other. An example can be found in the source files of smclpres. Other times I make all the functions part of a class (help [M-2] class). In a class you can have all kinds of variables that are local to the class, that all functions inside the class have access to. Various examples are given in this presentation on implementing Agent Based Models in Mata I gave at the last German Stata Users' meeting: http://maartenbuis.nl/presentations/munich19.html .

      The main advantage of both over the matrix of pointers is that the elements are named. This leads to more readable code. This is not a huge deal, as you can overcome that by first declaring locals to contain the row /column number and use those locals to refer to the row and/or column inside the matrix of pointers.
      ---------------------------------
      Maarten L. Buis
      University of Konstanz
      Department of history and sociology
      box 40
      78457 Konstanz
      Germany
      http://www.maartenbuis.nl
      ---------------------------------

      Comment


      • #4
        Thanks Maarten. I will take a look at these alternatives.

        Comment


        • #5
          You could also use a dictionary. It's one type of built-in class in Mata and probably the approach I'd go to first, I guess, because it's such a conventional programming construct that just about anyone else (including yourself, six months later) can figure out what you're doing / have done.
          Code:
          help mf_asarray

          Comment


          • #6
            Thanks Joseph.

            Comment


            • #7
              Just to illustrate with the four vectors:
              Code:
              version 16.0
              
              mata:
              mata clear
              
              // Instantiate dictionary object
              Dictionary = asarray_create()
              
              // Populate dictionary
              asarray(Dictionary, "ss", ("a","b"))
              asarray(Dictionary, "ls", ("a","b","c"))
              asarray(Dictionary, "sr", (1, 2))
              asarray(Dictionary, "lr", (1, 2, 3, 4))
              
              // Illustrative use case
              for (loc=asarray_first(Dictionary); loc!=NULL; loc=asarray_next(Dictionary, loc)) {
                  key = asarray_key(Dictionary, loc)
                  printf("\n%2s\n", key)
                  asarray(Dictionary, key)
              }
              
              end
              
              exit

              Comment


              • #8
                Hi, an additional point to consider is the copying of objects. When you return struct and class instances or associative arrays, the matrices of interest get copied, but not when you return a pointer vector, so the pointer strategy can be seen as being more efficient. Whether this is at all practically relevant obviously depends on the context of what you are doing.

                To get the best of both worlds, you can fill up a struct inside the function and then return a pointer to it, which gives you both readable code and efficiency.

                As a side note, I would think that accessing an element of an associative array is less efficient that directly accessing a member of a struct or class instance since it (a) needs to be looked up and (b) is returned by a function and hence requires an additional copy operation. So it may be the most convenient but also the least efficient option.

                Comment

                Working...
                X