*! version 0.3.8 2011-12-12 rename to statsto1; jd's v1.6 made live

* version 0.3.7 2011-06-03 rename to statsto
* version 0.3.6 2011-05-31 rename to x_statsto
* version 0.3.5 2011-05-26 bug with regress p-values
*      TODO: search USEt and generalize how t-dist is determined
*      TODO: search 0.3.5 and update xstatsto.ado
* version 0.3.4 2011-04-04 add version control for factor variables
* version 0.3.4      and rename _clct_ListMatrix
* version 0.3.3 2011-03-25 fix matrixrow1() where 1st row dropped

*  - scott long and jd wolfe: collecting statistics
* 2. if rows(11) and row 1 is _N_u_l_l_ it drops that row later. Don't!
* 3. is z and t correct for all types of models?
* 4. allow _ci and _all for what to retrieve?
* 5. Add something like rows(1-4)?
* 6. at() expand to allow at(XX=age X2=female 4)
* 7. input matrix
* 8. test further with factor variables
* 9. local MATrownum = 1 why used with listing; listnew if multiple rows added.

capture clear programs
program define statsto1

    version 10.1

//  #1 syntax

    syntax [anything] ,[    /// analysis matrix name in local MATname
                            /// Default name: StatSto<moutcome>
///
        ROWs(string)        /// was rownames (_all for all b's)
rowstub(string) ///
        MOUTcome(string)    /// outcome# added to matrix name; local mstubout
        OUTcome(string)     /// outcome# added to column name; local stubout
/// collector types
        ATreturns(string)    /// at(_all) for all
            ATStub(string)  /// stub to column names for at()
        blank               /// add a blank row
        Ereturns(string)    /// collect e() returns
            EStub(string)   /// stub to column names for e() collections
        EBreturns(string)   /// collect e(b) returns
            EBStub(string)  /// stub to column names for e(b) collections
        MATrix(string)      /// collect matrix
MATROWStub(string)   /// stub to column names for m() collections
MATCOLStub(string)   /// stub to column names for m() collections
MATROW1(string)   /// 1st row
MATCOL1(string)   /// 1st column
        Rreturns(string)    /// collect r() returns
            RStub(string)   /// stub to column names for r() collections
        RBreturns(string)   /// collect r(b) returns
            RBStub(string)  /// stub to column names for r(b) collections
        Uservalues(string)  /// collect user created scalars
            UStub(string)   /// stub to column names for u() collections
/// matrix utilities - subset of statout
        clear               /// reset matrix to null
        DECimals(numlist >-1 integer) /// digits when list matrix
        Format(string)      /// format for matrix
        list                /// list matrix
        LISTNew             /// list new ropws
        mv(string)          /// default missing value
        preview             /// preview changes but don't change matrix
        save(string)        /// save matrix to new matrix
        title(string)       /// title added when listing
        TRANspose           /// list/save transposed matrix
        WIDth(numlist >0 integer) /// width when listing matrix
///
        debug debug2 debug3 ///
     ]

    * clear matrices in case program crashed last time
    capture drop ATmatrix
    capture drop Bmatrix
    capture drop Ematrix
    capture drop MATmatrix
    capture drop Rmatrix
    capture drop Umatrix
    capture drop MATRIXmatrix

//  #2 decode sytnax

     local rownames "`rows'"
     local matrixin "`matrix'"

    * transpose implies list; listnew implies no list
    if ("`transpose'"=="transpose") local list "list"
    if ("`listnew'"=="listnew") local list ""

    * decode outcome() as number added to column names
    if ("`outcome'"=="") local stubout ""
    else {
        capture confirm integer number `outcome'
        if _rc>0 {
            di as error "outcome() must be an integer."
            exit
        }
        local stubout = `outcome'
    }

    * decode moutcome() to add moutcome to matrix name
    if ("`moutcome'"=="") local mstubout ""
    else {
        capture confirm integer number `moutcome'
        if _rc>0 {
            di as error "moutcome() must be an integer."
            exit
        }
        if (`moutcome'>=0) local mstubout "`moutcome'"
        if `moutcome'<0 {
            local mstubout = abs(`moutcome')
            local mstubout "_`mstubout'"
        }
    }

    * determine missing value to use as default
    local mvis "."
    if "`mv'"!="" & "`mv'"!="." {
        if length("`mv'")>1 {
            di as error "mv() must be a period or a single letter."
            exit
        }
        local mv = lower("`mv'")
        local mvis ".`mv'"
    }
    local mv "`mvis'"

    * format for listing matrix
    if ("`decimals'"!="" | "`width'"!="") & "`format'"=="" {
        if ("`decimals'"=="")   local decimals "0"
        if ("`width'"=="")      local width "10"
        if (`decimals'>`width') local width = `decimals' + 1
        local format "%`width'.`decimals'f"
    }

//  #3 indicators of what needs to be done

    * collector types
    if "`atreturns'"!=""           local ATis = 1
    else                    local ATis = 0
    if "`ereturns'"!=""     local Eis = 1
    else                    local Eis = 0
    if "`ebreturns'"!=""    local EBis = 1
    else                    local EBis = 0
    if "`matrixin'"!=""     local MATRIXis = 1
    else                    local MATRIXis = 0
    if "`rreturns'"!=""     local Ris = 1
    else                    local Ris = 0
    if "`rbreturns'"!=""    local RBis = 1
    else                    local RBis = 0
    if "`uservalues'"!=""   local Uis = 1
    else                    local Uis = 0
    if "`list'"=="list" | "`listnew'"=="listnew" | "`preview'"=="preview" {
                            local LISTis = 1
    }
    else                    local LISTis = 0
    if ("`moutcome'"!="" | "`outcome'"!="") local OUTis = 1
    else                    local OUTis = 0

    local SINGLEROWis = 0
    if (`Uis' | `Ris' | `Eis') local SINGLEROWis = 1

    * is anything being collected - excluding matrix()
    local ANYis = 0
    foreach ctype in AT E EB R RB U {
        if (``ctype'is'==1) local ANYis = 1
    }

if "`debug2'"=="debug2" {
    di in red _new ">> statsto #3" _new
    foreach v in AT E EB MATRIX R RB U LIST OUT ANY {
        di "`v'is: ``v'is'"
    }
    di
}

//  #4 determine if quantities exist in memory

    * is margins active? Will this always catch it?
    local MARGexistsE = 0
    qui capture confirm scalar e(k_margins)
    if !_rc local MARGexistsE = 1
    qui capture confirm scalar e(k_by)
    if !_rc local MARGexistsE = 1
    local MARGexistsR = 0
    qui capture confirm matrix r(b)
    if !_rc local MARGexistsR = 1
    qui capture confirm scalar r(k_by)
    if !_rc local MARGexistsR = 1
    qui capture confirm scalar r(k_margins)
    if !_rc local MARGexistsR = 1

    * does at() matrix exist?
    capture confirm matrix e(at)
    if _rc>0 local ATexistsE = 0
        else local ATexistsE = 1
    capture confirm matrix r(at)
    if _rc>0 local ATexistsR = 0
       else  local ATexistsR = 1

    * does matrix exist
    capture confirm matrix `matrixin'
    if _rc>0 local MATRIXexists = 0
       else  local MATRIXexists = 1

if "`debug2'"=="debug2" {
    di in red _new ">> statsto #4" _new
    di in red "ATexistsE:   `ATexistsE'"
    di in red "ATexistsR:   `ATexistsR'"
    di in red "MARGexistsE: `MARGexistsE'"
    di in red "MARGexistsR: `MARGexistsR'"
    di
}

//  #5 trap inconsistent syntax requests

    local isERROR = 0

    if `MATRIXis' & `MATRIXexists'==0 {
        di as error ///
"matrix(`matrixin') is not in memory."
        local isERROR = 1
    }

    if `ANYis' & `MATRIXis' {
        di as error ///
"matrix() cannot be used in the same command with other collection options."
        local isERROR = 1
}

    if `EBis' & `ATis' & `ATexistsE'==0 {
        di as error ///
"ebreturn() & at() are used, but e(at) does not exist."
        local isERROR = 1
    }
    if `RBis' & `ATis' & `ATexistsR'==0 {
        di as error ///
"rbreturn() & at() are used, but r(at) does not exist."
        local isERROR = 1
    }

    if `ANYis'==0 & `LISTis'==0 & "`clear'"=="" & `MATRIXis'==0 {
        di as error ///
"No information is being collected or printed. -statout- can be used to"
        di as error ///
"modify or list the collection matrix."
        local isERROR = 1
    }

    if "`moutcome'"!="" & "`outcome'"!="" {
        di as error ///
"Options moutcome() and outcome() cannot be used in the same command."
        local isERROR = 1
    }

    if `ATis'==1 & `ATexistsE'==0 & `ATexistsR'==0 {
        di as error ///
"at() collection option used but neither e(at) or r(at) are in memory."
        di as error ///
"Verify that -margins- was run using the -at()- option."
        local isERROR = 1
    }

    if (`isERROR'==1) exit

//  #6 set up matrices

    tempname CMAT nullmat
    matrix `nullmat' = J(1,1,`mv')
    matrix colnames `nullmat' = _N_u_l_l_
    matrix rownames `nullmat' = _N_u_l_l_
    * name of matrix for results
    if ("`anything'"=="") local MATname "StatSto`mstubout'"
    else                  local MATname "`anything'`mstubout'"

    * does collection matrix exist?
    capture matrix list `MATname'
    if _rc ~= 0 { // no matrix in memory
        matrix `CMAT' = `nullmat'
        matrix `MATname' = `nullmat' // in case clear is used
    }
    else matrix `CMAT' = `MATname'

    if ("`clear'"=="clear") matrix `CMAT' = `nullmat'

    if `ANYis'==0 & `MATRIXis'==0 & `LISTis' {

*! #6.1: why is MATrownum needed?
        local MATrownum = 1
        _clct_ListMatrix, matprint(`CMAT') matname(`MATname') ///
            matrownum(`MATrownum') `list' `transpose' `listnew' ///
            `preview' format(`format') title(`title')
        if "`clear'"=="clear" capture matrix drop `MATname'
        exit
    }

//  #7 decode rows()

if "`debug'"=="debug" {
    di in red  _new ">> statsto #8before - before ParseRows" _new
    di "rowstring:   `rownames'"
    di "ebis:        `EBis'"
    di "rbis:        `RBis'"
    di "atis:        `ATis'"
    di "singlerowis: `singlerowis'"
    di
    di "Working CMAT matrix"
    mat list `CMAT'
}

    if `MATRIXis'!=1 { // rownames not allowed with matrix()

        ParseRows, matnm(`CMAT') rowstub(`rowstub') rowstring(`rownames') ///
            mv("`mv'") ebis(`EBis') rbis(`RBis') atis(`ATis') ///
            singlerowis(`SINGLEROWis') `debug' `debug2' `debug3'

        local error = s(error)
        if `error'==1 exit

        * CMAT...: #s and names in collect matrix based on rows()
        local CINrowNUMS `s(CINrowNUMS)'
        local CINrowNMS `s(CINrowNMS)'
        * BMAT...: indices and names in e(b)|r(b) matrix corresponded to rows()
        local BINrowNUMS `s(BINrowNUMS)'
        local BINrowNMS `s(BINrowNMS)'
    }

if "`debug'"=="debug" {
    di in red  _new ">> statsto #8after - after ParseRows" _new
    di "Collect matrix row names and #s for changes" _new
    di "CINrowNUMS: `CINrowNUMS'"
    di "CINrowNMS:  `CINrowNMS'" // used to label collect matrix
    di
    di "b matrix names and #s for new stats" _new
    di "BINrowNUMS: `BINrowNUMS'"
    di "BINrowNMS:  `BINrowNMS'"
    di
    di "Working CMAT matrix"
    mat list `CMAT'
}

    * only one row allowed for these collection types
    if `Eis' | `Ris' | `Uis' {
        local nrows : word count `CINrowNMS'
        if `nrows'>1 {
            di as error ///
"With e(), r() and u() only one row name is allowed."
            exit
        }
    }

    * error if BINrowNUMS is 0; all names must be in e(b) or r(b)
    local error = 0
    foreach i in `BINrowNUMS' {
        if `i'==0 local error = 1
    }
    if `error'==1 {
        di as error ///
"rows() includes names not found in e(b) or r(b)."
        exit
    }

//  #8 Add rows in collect matrix based on rownames()

if "`debug2'"=="debug2" {
    di in red  _new ">> statsto #8: CMAT before adding rows" _new
    mat list `CMAT'
    di
}
    local i = 0
    foreach irow in `CINrowNUMS' {
        local ++i
        * if 0, row does not exist so add
        if `irow'==0 {
            local rowname : word `i' of `CINrowNMS'
            AddRow, matnm(`CMAT') mv("`mv'") newrowname("`rowname'")
*di "A1"
*mat list `CMAT'
        }
        * if # and rows does not exist
        local CMATrowN = rowsof(`CMAT')
        if `irow'>`CMATrowN' {
            * if first row is null rename it so it dosn't get dropped later
            local rowNMS : colnames `CMAT'
            local row1nm : word 1 of `rowNMS'
            if "`row1nm'"=="_N_u_l_l_" {
                local rowNMS : subinstr local rowNMS "_N_u_l_l_" "Row1", all
                matrix rownames `CMAT' = `rowNMS'
            }
            local inextrow = `CMATrowN' + 1
            * add rows till # rows matches number of row being added
            local irowm1 = `irow' - 1
            while `CMATrowN'<`irowm1' {
                AddRow, matnm(`CMAT') mv("`mv'") newrowname(`inextrow')
*di "A2"
*mat list `CMAT'
                local ++CMATrowN
                local ++inextrow
            }
            local rowname : word `i' of `CINrowNMS'
            AddRow, matnm(`CMAT') mv("`mv'") newrowname("`rowname'")
*di "A3"
*mat list `CMAT'

        }
    }

if "`debug2'"=="debug2" {
    di in red  _new ">> statsto #8: CMAT after adding rows" _new
    mat list `CMAT'
    di
}

//  #9 Matrix()

if `MATRIXis' {

    tempname inmatrix
    matrix MATRIXmatrix = `matrixin'
*matrix list MATRIXmatrix
    local  MATRIXrowNMS : rownames MATRIXmatrix
    local  MATRIXcolNMS : colnames MATRIXmatrix

    * add row stubs to input matrix
    if "`matrowstub'"!="" {
        local nms ""
        local isnum = regexm("`matrowstub'", "#")>0
        local matrowstub : subinstr local matrowstub "#" "", all
        local i = 0
        foreach nm in `MATRIXrowNMS' {
            local ++i
            if `isnum' local nms "`nms' `matrowstub'`i'"
            else       local nms "`nms' `matrowstub'`nm'"
        }
        matrix rownames MATRIXmatrix = `nms'
    }
    * add column stubs to input matrix
    if "`matcolstub'"!="" {
        local nms ""
        local isnum = regexm("`matcolstub'", "#")>0
        local matcolstub : subinstr local matcolstub "#" "", all
        local i = 0
        foreach nm in `MATRIXcolNMS' {
            local ++i
            if `isnum' local nms "`nms' `matcolstub'`i'"
            else       local nms "`nms' `matcolstub'`nm'"
        }
        matrix colnames MATRIXmatrix = `nms'
    }

    PopulateMatrix, matnm(`CMAT') mv("`mv'")  ///
        row1(`matrow1') col1(`matcol1') ///
        `debug' `debug2'

}

//  #11 Parse Uservalues

    local UstatsN = 0
    local UstatsNMS ""
    matrix Umatrix = J(1,1,`mv')
    if `Uis' {
        ParseUservalues, input(`uservalues') stub("`ustub'") ///
            stubout("`stubout'")
        local UstatsN = colsof(Umatrix)
        local UstatsNMS : colnames Umatrix

if "`debug2'"=="debug2" {
    di in red _new ">> statsto #11" _new
    di "UstatsN:   `UstatsN'"
    di "UstatsNMS: `UstatsNMS'"
    matrix list Umatrix
    di
}
        local error = s(error)
        if (`error'==1) exit
    }

//  #12 Parse Ereturns that are scalars

    local EstatsN = 0
    matrix Ematrix = J(1,1,.)
    local EstatsNMS ""
    if `Eis' {
        ParseEreturns, items(`ereturns') stub(`estub') ///
            stubout(`stubout') matnm(`CMAT') `debug' `debug2'
        local error = s(error)
        if (`error'==1) exit
        local EstatsN = colsof(Ematrix)
        local EstatsNMS : colnames Ematrix

if "`debug2'"=="debug2" {
    di in red _new ">> statsto #12" _new
    di "EstatsN:    `EstatsN'"
    di "EstatsNMS:  `EstatsNMS'"
    matrix list Ematrix
    di
}
    }

//  #13 Parse Rreturns - r() scalars including values derived from test
//  can combination commands.

    local RstatsN = 0
    matrix Rmatrix = J(1,1,.)
    local RstatsNMS ""
    if `Ris' {
        ParseRreturns, items(`rreturns') stub(`rstub') ///
            stubout(`stubout') matnm(`CMAT') `debug' `debug2' `debug3'
        local error = s(error)
        if (`error'==1) exit
        local RstatsN = colsof(Rmatrix)
        local RstatsNMS : colnames Rmatrix

if "`debug2'"=="debug2" {
    di in red _new ">> statsto #13" _new
    di "RstatsN:    `RstatsN'"
    di "RstatsNMS:  `RstatsNMS'"
    matrix list Rmatrix
    di
}
    }

//  #14 Parse ebreturns & rbreturns

    local BstatsN = 0
*BUG    matrix Bmatrix = J(1,1,.)
    local BstatsNMS ""
    if `EBis' | `RBis' {
        local breturns "`ebreturns'`rbreturns'"
        local bstub   "`ebstub'`rbstub'"

if "`debug'"=="debug" {
    di in red _new ">> statsto #14" _new
    di "breturns: |`breturns'|"
    di "bstub:   |`bstub'|" _new
}
        ParseBreturns, matnm(`CMAT') items(`breturns') ///
          ebis(`EBis') rbis(`RBis') ///
          binrownums(`BINrowNUMS') binrownms(`BINrowNMS') ///
          stubout(`stubout') stub(`bstub') mv("`mv'") `debug' `debug2'
        local error = s(error)
        if (`error'==1) exit
        local BstatsN = colsof(Bmatrix)
        local BstatsNMS : colnames Bmatrix

if "`debug'"=="debug" {
    di in red _new ">> statsto #14" _new
    di "BstatsN: `BstatsN'"
    di "BstatsNMS:  `BstatsNMS'"
    matrix list Bmatrix
    di
}
    } // EBis or RBis

//  #15 Parse at

*! #15.1 allow _all and _allmiss
    local  ATstatsN = 0
    local  ATstatsNMS ""
    if `ATis' {
*! #15.2 what if neither of these returns exist
        local ATtype "r" // r(at) should always work...
        if `EBis' local ATtype "e"
        if `RBis' local ATtype "r"

if "`debug2'"=="debug2" {
    di in red _new ">> statsto #15" _new
    di "atreturns: |`atreturns'|"
    di "ATtype:    |`ATtype'|" _new
}
*di in red "atstub: `atstub'"
        * note use BINrowNUMS and BINrowNMS with at()
        ParseATreturns, matnm(`CMAT') items(`atreturns') ///
          attype(`ATtype') binrownums(`BINrowNUMS') binrownms(`BINrowNMS') ///
          stubout(`stubout') stub(`atstub') mv("`mv'") `debug' `debug2'
        local error = s(error)
        if (`error'==1) exit
        local ATstatsN = colsof(ATmatrix)
        local ATstatsNMS : colnames ATmatrix

if "`debug'"=="debug" {
    di in red _new ">> statsto #15" _new
    di "ATstatsN:   `ATstatsN'"
    di "ATstatsNMS: `ATstatsNMS'"
    *matrix list ATmatrix
    di
}
    } // ATis

//  #50: add e(), r() and u() information to collect matrix

    * which row to modify?
    if `Uis' | `Eis' | `Ris' {
        GetRowNum, name("`CINrowNMS'") matnm(`CMAT')
        local CINrowNUM = s(rownum)
    }
    foreach ctype in E R U {
        if ``ctype'is' {
          PopulateERU, matnm(`CMAT') collecttype("`ctype'") ///
            newrownum(`CINrowNUM') mv("`mv'")
*mat list `CMAT'
        }
    }

//  #51: add eb() and rb() and at() results to collect matrix

    if `EBis' | `RBis' | `ATis' {

if "`debug'"=="debug" {
    di in red _new ">> #51" _new
    di "EBis: `EBis'   RBis: `RBis'   ATis: `ATis'"
    di "CINrowNUMS: `CINrowNUMS'"
    di "CINrowNMS:  `CINrowNMS'"
    di "BINrowNUMS: `BINrowNUMS'"
    di "BINrowNMS:  `BINrowNMS'"
    if (`EBis' | `RBis') matrix list Bmatrix
    if `ATis' matrix list ATmatrix
    di "CMAT"
    matrix list `CMAT'
    di
}
        PopulateBAT, matnm(`CMAT') mv("`mv'") rownames(`CINrowNMS') ///
            ebis(`EBis') rbis(`RBis') atis(`ATis') `debug' `debug2'
    }

//  #90 get rid of null column or row

    local MATcolNMS : colnames `CMAT'
    local MATcolN = colsof(`CMAT')
    local colnm : word 1 of `MATcolNMS'
    if "`colnm'"=="_N_u_l_l_" & `MATcolN'>1 {
        matrix `CMAT' = `CMAT'[1...,2...]
        local MATcolNMS : colnames `CMAT'
    }

    local MATrowNMS : rownames `CMAT'
    local MATrowN = rowsof(`CMAT')
    local rowname : word 1 of `MATrowNMS'
    if "`rowname'"=="_N_u_l_l_" & `MATrowN'>1 {
        matrix `CMAT' = `CMAT'[2...,1...]
        local MATrowNMS : rownames `CMAT'
    }

//  #91 add a blank row to bottom of matrix

    if "`blank'"!="" {
        * use rowstub in blank row name
        if "`rowstub'"!="" local newnm "`rowstub'- - - - -"
        else local newnm "- - - - -"
        AddRow, matnm(`CMAT') mv("`mv'") newrowname("`newnm'")
    }

//  92 save matrix

    if "`save'"!="" {
        capture matrix list `save'
        if _rc==0 {
            di as error ///
"Matrix `save' already exists. Choose another name. Use -matrix drop- to"
            di as error ///
"delete existing matrix."
        }
        else {
            if ("`transpose'"=="transpose") matrix `save' = `CMAT''
            else matrix `save' = `CMAT'
            di as result "Matrix `save' was created."
        }
    }

//  93 list matrix - TO DO CHECK THIS

*! #93: why is matrownum needed?
local MATrownum = 1
    if `LISTis' {
        _clct_ListMatrix, matprint(`CMAT') matname(`MATname') ///
            matrownum(`MATrownum') ///
            `list' `transpose' `listnew' `preview' ///
            format(`format') title(`title')
    }

//  #94 change the matrix in memory

    if ("`preview'"=="") matrix `MATname' = `CMAT'

//  #95 cleanup

    capture drop ATmatrix
    capture drop Bmatrix
    capture drop Ematrix
    capture drop MATmatrix
    capture drop Rmatrix
    capture drop Umatrix

end

//  ParseUservalues: parse uservalues(nm1=val1 nm2=val2 ...) \ 2011-02-08
//  Input:  input(string)
//          stub(string)
//          stubout(string)
//  Output: s(error)

program ParseUservalues, sclass

    syntax , input(string) [ stub(string) stubout(string) ]
    sreturn clear

    * remove ='s and count words
    local input = subinstr("`input'","="," ",.)
    local inputN : word count `input'

    * even number?
    local inputN = `inputN'/2
    capture confirm integer number `inputN'
    if _rc>0 {
        di as error ///
"Incorrect uservalues() syntax: name=value ... must be paired."
        sreturn local error = 1
        exit
    }

    * record names, values
    matrix Umatrix = J(1,1,.)
    matrix rownames Umatrix = Values
    local colnm "NULL"
    local iname = -1
    forvalues i = 1(1)`inputN' {
        local iname = `iname' + 2
        local ivalue = `iname' + 1
        local name : word `iname' of `input'
        local colnm "`colnm' `stub'`name'`stubout'" // with stubs
        local value : word `ivalue' of `input'
        matrix Umatrix = Umatrix , `value'
    }
    matrix colnames Umatrix = `colnm'
    matrix Umatrix = Umatrix[1...,2...] // delete null columns
    sreturn local error = 0

end // ParseUservalues

//  GetColNum: get column # column given name \ 2011-02-08
//  Input:  matnm(string)
//          name(string)
//  Output: colnum(string)

program GetColNum, sclass

    syntax, name(string) matnm(string)
    sreturn clear
    local colnms : colnames `matnm'
    local colnum : list posof "`name'" in colnms
    sreturn local colnum "`colnum'"

end // GetColNum

//  GetRowNum: get row # give row name \ 2011-02-05
//  Input:  matnm(string)
//          name(string)
//  Output: rownum(string)

program GetRowNum, sclass

    syntax, name(string) matnm(string)
    sreturn clear
    local rownms : rownames `matnm'
    local rownum : list posof "`name'" in rownms
    sreturn local rownum "`rownum'"

end // GetRowNum

//  GetColName: get name of column given index # \ 2011-02-08
//  Input:  matnm(string)
//          index(string)
//  Output: colname(string)

program GetColName, sclass

    syntax, index(string) matnm(string)
    sreturn clear
    local colnms : colnames `matnm'
    local colname : word `index' of `colnms'
    sreturn local colname "`colname'"

end // GetColName

//  ParseEreturns: parse ereturns() \ 2011-02-08
//  Input:  items(string)
//          stub(string)
//          stubout(string)
//  Output: s(error)

program ParseEreturns, sclass

    syntax , items(string) matnm(string) ///
        [ stub(string) stubout(string) debug debug2 ]
    sreturn clear

    DecodeERstring, items(`items')
    local EreturnNMS `s(ERretNMS)'
    local tempcolNMS `s(ERcolNMS)'

    * add stubs to column names
    local EcolNMS ""
    foreach colnm in `tempcolNMS' {

        capture confirm integer number `colnm'
        if _rc>0 { // not integer
            * hold for now
        }
        else { // integer
            GetColName, matnm(`matnm') index(`colnm')
            local colnm `s(colname)'
            if "`colnm'"=="" local colnm "_new_"
        }
        local EcolNMS "`EcolNMS' `stub'`colnm'`stubout'"
    }

    * retrieve stats
    matrix Ematrix = J(1,1,.)
    matrix rownames Ematrix = Values
    foreach retname in `EreturnNMS' {
        local returnvalue = e(`retname')
*! test if valid return?
        matrix Ematrix = Ematrix , `returnvalue'
    }
    matrix Ematrix = Ematrix[1...,2...]
    matrix colnames Ematrix = `EcolNMS'
    sreturn local error = 0

if "`debug2'"=="debug2" {
    di in red _new ">> xx # _new"
    di "EcolNMS: `EcolNMS'"
    di "EreturnNMS: `EreturnNMS'"
    mat list Ematrix
    di
}

end // ParseEreturns

//  DecodeERstring: decode col & ret names for e() & r() \ 2011-02-05
//  input:   items(string)    : e() or r() returns
//  output:  s(ERcolNMS)    : column names to use for each return
//           s(ERretNMS)    : return names for each return
//           s(error)         : 0 or 1

program DecodeERstring, sclass

    syntax , items(string)
    local error = 0
    local ERcolNMS    // name to assign column in results matrix
    local ERretNMS    // names of the returns

    * make = a seperate word
    local items : subinstr local items "  " " ", all
    local items : subinstr local items "=" " = ", all
    local items : subinstr local items "  " " ", all
    local itemsN : word count `items'

//  loop through words in the returns

    local i_item = 1
    local i_itemnext = 1
    while `i_item' <= `itemsN' {

        * note: L=R corresonds to L.. EQ.. R..
        local Litem : word `i_item' of `items'
        local Lnum = `i_item'

        * next item will be = if entery is of form a=b
        if `i_item' < `itemsN' {
            local ++i_item
            local EQitem : word `i_item' of `items'
        }
        else local EQitem "VOID"

        * if =, get item on right
        if "`EQitem'"=="=" {
            local i_itemnext = `i_item' + 2 // +2 since EQitem and Ritem used
            * when =, item on left is column name
            local ERcolNMS "`ERcolNMS' `Litem'"
            local ++i_item
            if (`i_item' <= `itemsN') local Ritem : word `i_item' of `items'
            else {
                di as error "A return name must follow = in e() and r()."
                local error = 1
                continue, break
            }
            * with equal name of return is listed on right of =
            local ERretNMS "`ERretNMS' `Ritem'"
        } // equal sign

        * EQitem not = use return name for col name
        else {
            local i_itemnext = `Lnum' + 1 // 1 word to specify e(b) value
            local ERcolNMS "`ERcolNMS' `Litem'"
            local ERretNMS "`ERretNMS' `Litem'"
        }
        local i_item = `i_itemnext'
    } // loop through option words

    if `error'==1 {
        sreturn local error = 1
        exit
    }
    sreturn local ERcolNMS `"`ERcolNMS'"'
    sreturn local ERretNMS `"`ERretNMS'"'

end // DecodeERstring

//  ParseRreturns: parse rreturns() \ 2011-02-08
//  Input:  items(string)
//          stub(string)
//          stubout(string)
//  Output: s(error)

program ParseRreturns, sclass

* parse any scalar r() but also parse test and combinations where
* derivative quantities are computed
*
*   b|est|estimate:
*           	estimate in r(estimate) from lincom; r(b) for nlcom.
*    lb & ub:  	lower/upper bound computed from r(estimate) and r(se) for
*               lincom; r(b) & r(V) for nlcom
*	level: 	    level used for bounds
*	se: 	    standard error from r(se) or r(V)
*	chi2:	    chi-square statistics from r(chi2)
*	F: 		    F statistic from r(F)
*	z: 		    z statistic computed from r(estimate) & r(se) or r(b) & r(V)
*	t: 		    t statistic computed from r(estimate) & r(se) or r(b) & r(V)
*	df: 	    degrees of freedom from r(df)
*	df_r:	    residual degrees of freedom from r(df_r)
*	p: 		    two-tailed p-value computed  or from r(p)

    syntax , items(string) matnm(string) ///
        [ stub(string) stubout(string) debug debug2 debug3 ]
    sreturn clear

//  #1 set up information for parsing

    DecodeERstring, items(`items')
    local tmpNMS `s(ERretNMS)'

    * lower case for derivative quantities above
    local RreturnNMS ""
    foreach nm in `tmpNMS' {
        foreach optnm in LB UB LEVEL SE CHI2 Z T DF DF_R P {
            if "`nm'"=="`optnm'" local nm = lower("`nm'")
        }
        local RreturnNMS "`RreturnNMS' `nm'"
    }
    local tempcolNMS `s(ERcolNMS)'
    matrix Rmatrix = J(1,1,.)
    matrix rownames Rmatrix = Values

*! ParseRreturns: is this sufficient to determine combine or test command
*! If other commands use these returns, then what?

* returns from lincom and nlcomb
*    local COMBlist df se estimate b est df_r level ub lb t z // N
* returns from tests
*    local TESTlist chi2 df df_r drop F  p

    * hold results of tests and combination
    tempname estval estimateval bval seval // est and se
    tempname dfval df_rval // df
    tempname Fval tval chi2val zval pval // tests
    tempname lbval ubval levelval levelpval cifactorval ci // ci
    tempname returnvalue

//  #2 are any returns from test or combinations?

*! COMBis TESTis == these tests are insufficient!

* try to determine which is active
local isT = 99
local isZ = 99

local TESTis = 0
local TESTNLis = 0
local LRTESTis = 0
local LINCOMis = 0
local NLCOMis = 0

* test
if r(df_r)!=. & r(F)!=. & r(df)!=. & r(p)!=. {
    capture confirm matrix r(G)
* di _rc
    if _rc>0 {
        local TESTis = 1
    }
}
if r(chi2)!=. & r(df)!=. & r(p)!=. & r(drop)!=. {
    local TESTis = 1
}

* testnl
if r(p)!=. & r(F)!=. & r(df_r)!=. & r(df)!=. {
    capture confirm matrix r(G)
    if _rc==0 {
        local TESTNLis = 1
    }
}
if r(p)!=. & r(chi2)!=. & r(df)!=. {
    capture confirm matrix r(G)
    if _rc==0 local TESTNLis = 1
}

* lrtest
if r(p)!=. & r(chi2)!=. & r(df)!=. & r(drop)==. {
    capture confirm matrix r(G)
    if _rc>0 {
        local LRTESTis = 1
    }
}

* lincom
if r(df)!=. & r(se)!=. & r(estimate)!=. {
    local LINCOMis = 1
    local isT = 1
    local isZ = 0
}
else if r(se)!=. & r(estimate)!=. {
    local isT = 0
    local isZ = 1
    local LINCOMis = 1
}

* nlcom
if r(df_r)!=. & r(N)!=. {
    capture confirm matrix r(b)
    if _rc==0 {
        local NLCOMis = 1
        local isT = 1
        local isZ = 0
    }
}
else {
    capture confirm matrix r(b)
    if _rc==0 {
        capture confirm matrix r(V)
        if _rc==0 {
            local isT = 0
            local isZ = 1
            local NLCOMis = 1
        }
    }
}
local COMBANYis = 0
local TESTANYis = 0
if `TESTis'==1 local TESTANYis = 1
if `TESTNLis'==1 local TESTANYis = 1
if `LRTESTis'==1 local TESTANYis = 1
if `NLCOMis'==1 local COMBANYis = 1
if `LINCOMis'==1 local COMBANYis = 1

if "`debug3'"=="debug3" {
    di in red _new ">> statsto #2 - type of test/comb" _new
    foreach is in TEST TESTNL LRTEST NLCOM LINCOM COMBANY TESTANY {
        di "`is'is: " _col(12) "``is'is'"
    }
    di "idT: " _col(12) "`isT'"
    di "isZ: " _col(12) "`isZ'"
    di
}

//  #3 if test or comb get all possible information

    if `COMBANYis' | `TESTANYis' {

        * retrieve all possible returns, even if they are not in memory
        * Note: no error generated if, say, r(se) does not exist
        scalar `estval' = r(estimate)
        scalar `seval' = r(se)
        scalar `dfval' = r(df)
        scalar `df_rval' = r(df_r)
        scalar `Fval' = r(F)
        scalar `tval' = r(t)
        scalar `chi2val' = r(chi2)
        scalar `zval' = r(z)
        scalar `pval' = r(p)

        * get from r(b) and r(V) if needed
        local getmatrix = 0
        if `estval'==. {
            capture scalar `estval' = el(r(b),1,1)
            local getmatrix = 1
        }
        if `getmatrix' {
            capture scalar `seval' = sqrt( el(r(V),1,1) )
        }
        * these are synonyms
        scalar `bval' = `estval'
        scalar `estimateval' = `estval'
        * cu levels
        scalar `levelval' = $S_level // level for CI
        scalar `levelpval' = ( 1 - (`levelval'/100) )/2

        * decide if use t or z distribution
* 2011-02-11 use isT and isZ
/*        local USEt = 0
        local ISdf = .
        * lincom
        if r(df)<. & r(se)<. & r(estimate)<. {
            local USEt = 1
            local ISdf = r(df)
        }
        * nlcom
        else if r(df_r)<. & r(N)<. {
            local USEt = 1
            local ISdf = r(df_r)
        }
*/
        * if df, use t
*        if `USEt' {
if `isT' {
local ISdf = r(df)
if `NLCOMis' local ISdf = r(df_r)
            scalar `cifactorval' =  abs(invttail(`ISdf',`levelpval'))
        }
if `isZ' {
local ISdf = r(df_r)
            scalar `cifactorval' =  abs(invnormal(`levelpval'))
        }

        * test estimate is 0
if `isZ' scalar `zval' = `estval'/`seval'
if `isT' scalar `tval' = `estval'/`seval'
if `isT' & `pval'==. {
        *if `USEt' & `pval'==. {
            scalar `pval' = 2*ttail(`ISdf',abs(`tval'))
        }
        *else if `pval'==.  {
if `isZ' & `pval'==. {
            scalar `pval' = 2*(1-normal(abs(`zval')))
        }

        * bounds
        scalar `lbval' = `estval' - (`cifactorval'*`seval')
        scalar `ubval' = `estval' + (`cifactorval'*`seval')
    }

if "`debug2'"=="debug2" & (`COMBANYis' | `TESTANYis') {
    di in red _new ">> ParseReturns #3" _new
    di "bval       :" `bval'
    di "chi2val    :" `chi2val'
    di "cifactorval:" `cifactorval'
    di "df_rval    :" `df_rval'
    di "dfval      :" `dfval'
    di "estimateval:" `estimateval'
    di "estval     :" `estval'
    di "Fval       :" `Fval'
    di "lbval      :" `lbval'
    di "levelpval  :" `levelpval'
    di "levelval   :" `levelval'
    di "pval       :" `pval'
    di "seval      :" `seval'
    di "tval       :" `tval'
    di "tval       :" `tval'
    di "ubval      :" `ubval'
    di "zval       :" `zval'
    di
    di "RreturnNMS: `RreturnNMS'"
*    di "COMBlist:  `COMBlist'"
*    di "TESTlist:  `TESTlist'" _new
}

//  #4 Populate matrix

    foreach returnname in `RreturnNMS' {

*        local COMBANYis = regexm("`COMBlist'", "`returnname'")
*        local TESTANYis = regexm("`TESTlist'", "`returnname'")
        if `COMBANYis' | `TESTANYis' {
            scalar `returnvalue' = ``returnname'val'
        }
        else {
            scalar `returnvalue' = r(`returnname')
        }
        matrix Rmatrix = Rmatrix , `returnvalue'

    }

//  #5 decode column names

    local RcolNMS ""
    foreach colnm in `tempcolNMS' {

        capture confirm integer number `colnm'
        if _rc>0 { // not integer
            *! add error message
        }
        else { // integer
            GetColName, matnm(`matnm') index(`colnm')
            local colnm `s(colname)'
            if "`colnm'"=="" local colnm "_new_"
        }
        local RcolNMS "`RcolNMS' `stub'`colnm'`stubout'"

    }

//  #6 cleanup

    matrix Rmatrix = Rmatrix[1...,2...]
    matrix colnames Rmatrix = `RcolNMS'
    sreturn local error = 0

if "`debug2'"=="debug2" {
    di in red _new ">> ParseRreturns #6" _new
    di "RcolNMS:    `RcolNMS'"
    di "RreturnNMS: `RreturnNMS'"
    mat list Rmatrix
    di
}

end // ParseRreturns

//  ParseRows: decode rownames \ 2011-02-08
//  input:  rowstring(string)
//          rowstub(string) * added 2011-02-14
//          matnm(string)
//          ebis(string)
//          rbis(string)
//          atis(string)
//          singlerowis(string)
//  output: CINrowNUMS  row index in collect for new stats
//          CINrowNMS   row name in collect for new stats
//          BINrowNUMS  column index in b matrix for new stats
//          BINrowNMS   column name in b matrix for new stats
//          s(error)    0 or 1

program ParseRows, sclass
*if "`debug3'"=="debug3" set trace on

    syntax , matnm(string) ///
        [ rowstub(string ) rowstring(string) mv(string) ebis(string) ///
            rbis(string) atis(string) singlerowis(string) ///
            debug debug2 debug3 ]
    * allows rows() to be blank if collect matrix is null
    if "`rowstring'"=="" {
        IsMatNull, matnm(`matnm')
        local isnull = s(isnull)
        * if null add Row1 as first row
        if `isnull' {
            local rowstring "Row1"
        }
        else {
            * if only single row needed, add row 2011-02-14
            if `singlerowis' {
                local nextN = rowsof(`matnm') + 1
                local rowstring "Row`nextN'"
                local tmprownm "`rowstub'Row`nextN'" // rowstub
                AddRow, matnm(`matnm') mv("`mv'") newrowname("`tmprownm'")
            }
            else {
                di as error "rows() must be specified."
                sreturn local error = 1
                exit
            }
        }
    }

    local CMATrowNMS : rownames `matnm'

//  names from b matrix

    tempname BMAT
    local BMATcolNMS ""
    local BMATcolN = 0
    local BMATis = 0
    if `ebis'==1 {
        local BMATis = 1
        matrix `BMAT' = e(b)
    }
    else if `rbis'==1 {
        local BMATis = 1
        matrix `BMAT' = r(b)
    }
* ATBUG
else if `atis' {
    * ebis and rbis are 0
    * get r(b) matrix
        local BMATis = 1
        matrix `BMAT' = r(b)
}
    ** strip out o. type variables if factors are used
    if `BMATis' {

        if c(stata_version)>=11 { // requires stata 11 or later
            tempname noomit mret
            _return hold `mret'
            _ms_omit_info `BMAT' // find omitted variables
*mat list `BMAT'
*mat list r(omit)
            local BMATcolN = colsof(`BMAT')
            matrix `noomit' = J(1,`BMATcolN',1) - r(omit)
            * get new column names
            local origcolnms : colnames `BMAT'
            local newcolnms ""
            local i = 0
            foreach nm in `origcolnms' {
                local ++i
                if `noomit'[1,`i']==1 local newcolnms "`newcolnms' `nm'"
            }
            * reduce matrix b
            mata: newB = ///
             select(st_matrix(st_local("BMAT")),(st_matrix(st_local("noomit"))))
            mata: st_matrix(st_local("BMAT"),newB)
            _return restore `mret'
            * add new names
* 0.3.4 - factor fixes
local stataVrunning = c(stata_version)
version `stataVrunning' : matrix colnames `BMAT' = `newcolnms'
        } // stata 11 or later
        local BMATcolNMS : colnames `BMAT'
        local BMATcolN : word count `BMATcolNMS'
    } // BMATis

if "`debug'"=="debug" {
    di in red _new ">> ParseRows #1" _new
    di
    di "BMATcolNMS: `BMATcolNMS'"
    di "BMATcolN:   `BMATcolN'"
}

//  is e(b) margins?c

    local MARGis = 0
    if `atis' local MARGis = 1
    if `rbis' local MARGis = 1
    if `ebis' {
        qui capture confirm scalar e(k_margins)
        if !_rc local MARGis = 1
        qui capture confirm scalar e(k_by)
        if !_rc local MARGis = 1
    }

//  decode _all options

    local isall = regexm("`rowstring'", "_all")
    local allprefix ""
    if `isall'>0 local isall = 1
    if `isall' {
        local iseq = regexm("`rowstring'", "=")
        if `iseq'>1 local iseq = 1
        if `iseq' {
            local rowstring : subinstr local rowstring "=" " ", all
            local allprefix : word 1 of `rowstring'
            local rowstr : word 2 of `rowstring'
            if "`rowstr'"!="_all" {
                print "_all decoding didn't work..."
                exit
            }
            else {
                local rowstring "_all"
                local allprefixN = rowsof(`matnm') + 1
                local tmpnms : rownames `matnm'
                local tmpnull : word 1 of `tmpnms'
                if "`tmpnull'"=="_N_u_l_l_" local allprefixN = `allprefixN' - 1
            }
        }
    } // isall

//  _all when MARGis = 0

    local tmpstring : subinstr local rowstring " " "", all

    if "`tmpstring'"=="_all" & `MARGis'==0 {
        local rowstring ""
        foreach nm in `BMATcolNMS' {
            local rowstring "`rowstring' `nm'"
        }
    }

//  _all with MARGis = 1

    if "`tmpstring'"=="_all" & `MARGis'==1 {
        local rowstring ""
        foreach nm in `BMATcolNMS' {
            local rowstring "`rowstring' `nm'"
        }
*! parse out pecular margins names
    }

/*
//  _all
    local rowstringnoat "`rowstring'"
    local tmpstring : subinstr local rowstring " " "", all
    if "`tmpstring'"=="_all" {
        local rownm_noat ""
        local rownm_at ""
        foreach nm_at in `BMATcolNMS' {
            * get rid of 1bn
            *local nm_at : subinstr local nm_at "1bn._at" "1._at", all
            local nm_noat : subinstr local nm_at "._at" "", all
            if "`rowstub'"=="" {
                local rownm_noat "`rownm_noat' `nm_noat'"
                local rownm_at "`rownm_at' `nm_at'"
            }
            else {
                local rownm_noat "`rownm_noat' `rowstub'`nm_noat'=`nm_noat'"
                local rownm_at   "`rownm_at' `rowstub'`nm_at'=`nm_at'"
            }
        }
        local rowstringat   "`rownm_at'"
        local rowstringnoat "`rownm_noat'"
        local rowstring "`rowstringat'"
    }
*/

//  decode rowstring

    local error = 0
    local BINinput      // input for b matrix columns (name or number)
    local BINrowNMS     // b names decoded from rows()
    local BINrowNUMS    // b index decoded from rows()
    local CINinput      // input for collection matrix (name or number)
    local CINrowNMS    // collect matrix names decoded from rows()
    local CINrowNUMS    // collect matrix index decoded from rows()

    * make = a seperate item
    local rowstring : subinstr local rowstring "  " " ", all
    local rowstring : subinstr local rowstring "=" " = ", all
    local rowstring : subinstr local rowstring "  " " ", all
    local itemsN : word count `rowstring'
    * loop through words from rowstring
    local i_item = 1
    local i_itemnext = 1
    while `i_item' <= `itemsN' {

        * note: L=R corresonds to L.. EQ.. R..
        local Litem : word `i_item' of `rowstring'
* rowstub
        local LitemNoStub "`Litem'" // item without stub added; used for b mat
* rowstub
        local Litem "`rowstub'`Litem'"
        local Lindex = `i_item'

        * get word that will be = if entery is of form a=b
        if `i_item' < `itemsN' {
            local ++i_item
            local EQitem : word `i_item' of `rowstring'
        }
        else local EQitem "VOID"

        * if =, get word on right
        if "`EQitem'"=="=" {
            local i_itemnext = `i_item' + 2 // +2 since EQitem & Ritem used
            * when = word on left is column name
            local CINinput "`CINinput' `Litem'"
            local ++i_item
            if (`i_item' <= `itemsN') local Ritem : word `i_item' of `rowstring'
            else {
                di as error ///
"A name or number must follow = in rownames() and rows()."
                local error = 1
                continue, break
            }
            * with equal name of return is listed on right of =
            local BINinput "`BINinput' `Ritem'"
        } // equal sign

        * EQitem not = use return name for col name
        else {
            local i_itemnext = `Lindex' + 1 // 1 item for e(b) value
            local CINinput "`CINinput' `Litem'"
*rowstub: local BINinput "`BINinput' `Litem'"
            local BINinput "`BINinput' `LitemNoStub'" // no stub in b names
        }
        local i_item = `i_itemnext'

    } // loop through option items

    if `error'==1 {
        sreturn local error = 1
        exit
    }

if "`debug'"=="debug" {
    di in red _new ">> ParseRows #2" _new
    di in green "NB! CINinput: `CINinput'"
    di in green "NB! BINinput: `BINinput'"
    di "CMATrowNMS: `CMATrowNMS'"
    di
}

//  Get names and row numbers for collect matrix

    foreach input in `CINinput' {
        capture confirm integer number `input'
        if _rc>0 { // is string
            local iname "`input'"
            local inum : list posof "`input'" in CMATrowNMS
            if "`allprefix'"!="" {
                local iname "`allprefix'`allprefixN'"
                local ++allprefixN
            }
        }
        else { // is number
            local inum = `input'
            local iname : word `inum' of `CMATrowNMS'
            if "`iname'"=="" {
                local iname "Row`inum'"
                local inum = 0 // since this name doesn't exist
                * 2011-02-15 04.37 pm local inum = `input' // since this name doesn't exist
            }
            else if "`iname'"=="_N_u_l_l_" {
                local iname "Row`inum'"
                local inum = 0 // since this name doesn't exist
            }
        }
        local CINrowNUMS "`CINrowNUMS' `inum'"
        local CINrowNMS "`CINrowNMS' `iname'"
    }

if "`debug'"=="debug" {
    di in red _new ">> ParseRows #3" _new
    di "CINrowNMS:  `CINrowNMS'"
    di "CINrowNUMS: `CINrowNUMS'"
}

//  Get names and index for b matrix

    if `BMATis' {
        foreach input in `BINinput' {
            capture confirm integer number `input'
            if _rc>0 { // is string
                local iname "`input'"
                local inum : list posof "`input'" in BMATcolNMS
            }
            else { // is number
                local inum = `input'
                local iname : word `inum' of `BMATcolNMS'
                if `inum'>`BMATcolN' local inum = 0
            }
            local BINrowNUMS "`BINrowNUMS' `inum'"
            local BINrowNMS "`BINrowNMS' `iname'"
        }
    }

//  Replace Row# with b name if e(b) or r(b) exist

    if `BMATis' & "`allprefix'"=="" {
        if "`BMATcolNMS'"!="" {
            local newnames ""
            local i = 0
            foreach rowname in `CINrowNMS' {
                local ++i
                local checkrow = substr("`rowname'",1,3)
                if "`checkrow'"=="Row" {
                    local rowname : word `i' of `BINrowNMS'
                }
                local newnames "`newnames' `rowname'"
            }
            local CINrowNMS "`newnames'"
        }
    }

//  add rowstub to names in C

    local cnms "`CINrowNMS'"
    local CINrowNMS ""
    foreach nm in `cnms' {
        local CINrowNMS "`cnms'"
    }

//  cleanup ._at
/*
    local i = 0
    local tempNMS ""
    foreach nm in `CINrowNMS' {
        local nm : subinstr local nm "._at" "", all
local nm : subinstr local nm "1bn" "1", all
        local tempNMS "`tempNMS' `nm'"
    }
    local CINrowNMS "`tempNMS'"

    local i = 0
    local tempNMS ""
    foreach nm in `BINrowNMS' {
        local nm : subinstr local nm "._at" "", all
local nm : subinstr local nm "1bn" "1", all
        local tempNMS "`tempNMS' `nm'"
    }
    local BINrowNMS "`tempNMS'"
*/
// cleanup: note NUMS are 0 if item does not exist

    sreturn local CINrowNUMS `"`CINrowNUMS'"'
    sreturn local CINrowNMS  `"`CINrowNMS'"'
    sreturn local BINrowNMS  `"`BINrowNMS'"'
    sreturn local BINrowNUMS `"`BINrowNUMS'"'
*if "`debug3'"=="debug3" set trace off
end // ParseRows

//  AddRow: add new row \ 2011-02-08
//  input:  newrowname(string)
//          matnm(string)
//          mv(string)
//  output: s(error)      : 0 or 1

program AddRow, sclass

    syntax , matnm(string) ///
        [ newrowname(string) mv(string) ]

    local rowN   = rowsof(`matnm')
    local rowNMS : rownames `matnm'
    local colN   = colsof(`matnm')
    local colNMS : colnames `matnm'
    if "`mv'"=="" local mv "."
    * name for new row
    if "`newrowname'"=="" {
        local rownum = `rowN' + 1
        local newrowname "Row`rownum'"
    }
    capture confirm integer number `newrowname'
    if _rc==0 {
        local newrowname "Row`newrowname'"
    }
    else {
        local newrowname "`newrowname'"
    }
    * add row
    tempname rownull
    matrix `rownull' = J(1,`colN',`mv')
* 0.3.4 factors
local stataVrunning = c(stata_version)
version `stataVrunning' : matrix rownames `rownull' = `newrowname'
    matrix `matnm' = (`matnm') \ (`rownull')

    sreturn local error = 0

end // AddRow

//  AddCol: add new column \ 2011-02-08
//  input:  newcolname(string)
//          matnm(string)
//          mv(string)
//  output: s(error)

program AddCol, sclass

    syntax , matnm(string) ///
        [ newcolname(string) mv(string) ]

    local rowN   = rowsof(`matnm')
    local rowNMS : rownames `matnm'
    local colN   = colsof(`matnm')
    local colNMS : colnames `matnm'
    if "`mv'"=="" local mv "."

    * name for new col
    if "`newcolname'"=="" {
        local colnum = `colN' + 1
        local newcolname "Col`colnum'"
    }
    capture confirm integer number `newcolname'
    if _rc==0 {
        local rownm "Col`newcolname'"
    }

    * add column
    tempname colnull
    matrix `colnull' = J(`rowN',1,`mv')
    matrix colnames `colnull' = `newcolname'
    matrix `matnm' = (`matnm') , (`colnull')

    sreturn local error = 0

end // AddCol

//  PopulateERU: add e() r() u() data to collect matrix \ 2011-02-06
//  input:  matnm(name of matrix)
//          newrownum(new row of collect matrix)
//          collecttype(U R E)
//          mv(missing value)

program PopulateERU, sclass

    syntax , matnm(string) newrownum(string) collecttype(string) mv(string)
    tempname value
    local ADDmatrix "`collecttype'matrix"
    local ADDnames : colnames `ADDmatrix'
    local ADDcol = 0
    foreach statnm in `ADDnames' {
        local ++ADDcol
        GetColNum, name("`statnm'") matnm(`matnm')
        local CMATcol = s(colnum)
        if `CMATcol'==0 {
           AddCol, matnm(`matnm') newcolname("`statnm'") mv("`mv'")
           local CMATcol = colsof(`matnm')
        }
        scalar `value' = `ADDmatrix'[1,`ADDcol']
        matrix `matnm'[`newrownum',`CMATcol'] = `value'
    }

end // PopulateERU

//  ParseBreturns: get e|r(b), e|r(V) and derivatives \ 2011-02-08
//  input:  matnm(name of matrix)
//          ebis() rbis()
//          items(`breturns' `rreturns')
//          binrownums()                    aka BINrowNUMS
//          binrownms()                     aka BINrowNMS
//          mv(missing value)
//          stub(`ebstub' | `rbstub')
//  output: error

program ParseBreturns, sclass

    syntax , matnm(string) ebis(string) rbis(string) ///
                items(string) binrownums(string) binrownms(string) ///
                mv(string) [ stub(string) stubout(string) ///
                debug debug2 ]

    sreturn clear
    tempname BTEMP bin bout vin // matrices
    tempname b ci cifactorval lbval levelpval levelval or pct pval
    tempname sd tempname tval ubval v value zval

    if `ebis'==`rbis' {
        sreturn local error = 1
        di in red ///
"You cannot have ebreturns() and rbreturns() in the same command."
        exit
    }
    if `ebis'==1 local ER "e"
    else         local ER "r"

    local binrowN : word count `binrownums' // # of b elements to keep
    DecodeERstring, items(`items')
    local ERretNMS `s(ERretNMS)'
    local ERretN : word count `ERretNMS'
    local ERcolNMS `s(ERcolNMS)'

if "`debug'"=="debug" {
    di in red _new ">> ParseBreturns #1" _new
    di "items:      `items'"
    di "ERretNMS:   `ERretNMS'"
    di "ERcolNMS:   `ERcolNMS'"
    di "binrownums: `binrownums'"
    di "binrownms:  `binrownms'" _new
}

    * get b and V
    capture matrix `bin' = `ER'(b)
    if _rc>0 {
        di as error "`ER'(b) is not in memory."
        sreturn local error = 1
        exit
    }
    matrix `vin' = `ER'(V)

*! ParseBreturns: check code for use with margins r(b)?
    local ismargins = 0
    qui capture confirm scalar r(k_margins)
    if !_rc local ismargins = 1
    qui capture confirm scalar r(k_by)
    if !_rc local ismargins = 1

if c(stata_version)>=11 {
    ** strip out o. type variables if factors are used
    tempname noomit mret
    _return hold `mret'
    _ms_omit_info `bin' // find omitted variables
    local bincolN = colsof(`bin')
    matrix `noomit' = J(1,`bincolN',1) - r(omit)
    * get new column names
    local origcolnms : colnames `bin'
    local newcolnms ""
    local i = 0
    foreach nm in `origcolnms' {
        local ++i
        if `noomit'[1,`i']==1 local newcolnms "`newcolnms' `nm'"
    }
    * reduce matrix v and b
    mata: newV = ///
        select(st_matrix(st_local("vin")),(st_matrix(st_local("noomit"))))
    mata: newV = select(newV, (st_matrix(st_local("noomit")))')
    mata: st_matrix(st_local("vin"),newV)
    mata: newB = ///
        select(st_matrix(st_local("bin")),(st_matrix(st_local("noomit"))))
    mata: st_matrix(st_local("bin"),newB)
    _return restore `mret'
    * add new names
* 0.3.4 factors
local stataVrunning = c(stata_version)
version `stataVrunning' : matrix colnames `bin' = `newcolnms'
version `stataVrunning' : matrix colnames `vin' = `newcolnms'
version `stataVrunning' : matrix rownames `vin' = `newcolnms'
*mat list `bin'

/*
We created a matrix named noomit which will mark columns that
should be kept with the number one and zero otherwise. Now we can use the
-select()- function in Mata to return the reduced matrix.

	/* reduce matrix V */
	mata: newV = select(st_matrix(st_local("V")),(st_matrix(st_local("noomit"))))
        mata: newV = select(newV, (st_matrix(st_local("noomit")))')
        mata: st_matrix(st_local("V"),newV)

	/* reduce matrix b */
	mata: newB = select(st_matrix(st_local("b")),(st_matrix(st_local("noomit"))))
        mata: st_matrix(st_local("b"),newB)


The function -st_matrix()- was used to overwrite the temporary matrices b and
V with the reduced matrices obtained in Mata. If you want the column names to
still be in place on the reduced matrix, you will need to reassign the names.
Now that we have the reduced matrices, we can perform computations that
require the reduced form.
*/

} // version
    local BINcolNMS : colnames `bin'

if "`debug'"=="debug" {
    di in red _new ">> ParseBreturns #2" _new
    di "BINcolNMS: `BINcolNMS'" _new
}

*! ParseBreturns: decide on how to determine if t or z!

    local USEt = 0
    local ISdf = .

* 0.3.5 2011-05-26
if e(cmd)=="regress" {
    local USEt = 1
    local ISdf = e(df_r)
}

*   b:		from e(b)
*	expb|or: exp(b)
*	pctb:	100*(exp(b)-1)
*	se:		standard error
*	z:		z-test of Ho: b=0
*	t:		t-test of Ho: b=0
*	p:		two-tailed p-value
*	lb:		lower bound of CI
*	ub:		upper bound of CI

    * BTEMP holds computed values from b and V before they are selected
    matrix `BTEMP' = J(`binrowN',13,`mv')
    local BTEMPcolNMS "b est estimate exp or pctb se z t p lb ub level"
    *                  1 2   3        4   5  6    7  8 9 0 11 12 13
    matrix colnames `BTEMP' = `BTEMPcolNMS'
    scalar `levelval' = $S_level // level for CI
    scalar `levelpval' = ( 1 - (`levelval'/100) )/2

    local btemprow = 0
    foreach bincol in `binrownums' {

        local ++btemprow
        scalar `b' = `bin'[1,`bincol']
        matrix `BTEMP'[`btemprow',1] = `b'
        matrix `BTEMP'[`btemprow',2] = `b'
        matrix `BTEMP'[`btemprow',3] = `b'

        scalar `or' = exp(`b')
        matrix `BTEMP'[`btemprow',4] = `or'
        matrix `BTEMP'[`btemprow',5] = `or'
        scalar `pct' = 100*(`or'-1)
        matrix `BTEMP'[`btemprow',6] = `pct'

        scalar `sd' = sqrt(`vin'[`bincol',`bincol'])
        matrix `BTEMP'[`btemprow',7] = `sd'
        scalar `zval' = `b'/`sd'
        matrix `BTEMP'[`btemprow',8] = `zval'
        scalar `tval' = `zval'
        matrix `BTEMP'[`btemprow',9] = `tval'

        if `USEt' {
            scalar `cifactorval' = abs(invttail(`ISdf',`levelpval'))
        }
        else {
            scalar `cifactorval' = abs(invnormal(`levelpval'))
        }
        if `USEt' {
            scalar `pval' = 2*ttail(`ISdf',abs(`tval'))
        }
        else {
            scalar `pval' = 2*(1-normal(abs(`zval')))
        }
        matrix `BTEMP'[`btemprow',10] = `pval'
        scalar `lbval' = `b' - (`cifactorval'*`sd')
        scalar `ubval' = `b' + (`cifactorval'*`sd')
        matrix `BTEMP'[`btemprow',11] = `lbval'
        matrix `BTEMP'[`btemprow',12] = `ubval'
        matrix `BTEMP'[`btemprow',13] = `levelval'
    }

if "`debug'"=="debug" {
    di in red _new ">> ParseBreturns #3" _new
    di "BTEMP"
    matrix list `BTEMP'
    di
}

//  populate Bmatrix

    matrix Bmatrix = J(`binrowN',`ERretN',`mv')
* 0.3.4 factors
local stataVrunning = c(stata_version)
version `stataVrunning' : matrix rownames Bmatrix = `binrownms'
    * add stubs to Bmatrix names
    local bincolnms ""

    foreach nm in `ERcolNMS' { // use assigned names not return names
        local bincolnms "`bincolnms' `stub'`nm'`stubout'"
    }
    matrix colnames Bmatrix = `bincolnms'
    local icol = 0
    foreach retname in `ERretNMS' {
        local retcol : list posof "`retname'" in BTEMPcolNMS
        local ++icol
        local irow = 0
        foreach var in `binrownms' {
            local ++irow
            scalar `value' = `BTEMP'[`irow',`retcol']
            matrix Bmatrix[`irow',`icol'] = `value'
        }
    }

if "`debug'"=="debug" {
    di in red _new ">> ParseBreturns #4" _new
    mat list Bmatrix
    di
}
    sreturn local error = 0

end // ParseBreturns

//  ParseATreturns: get e(at) or r(at) \ 2011-02-15
//  input:  matnm(name of matrix)
//          items(`atreturns')         column names to keep
//          attype(e|r)                get e(at) or r(at)
//          binrownums()               BINrowNUMS - row match at matrix
//          binrownms()                BINrowNMS - row match at matrix
//          mv(missing value)
//          stub(`atstub')
//          stubout()                  stub from outcome()
//  output: error

*! ParseATreturns: add stubs to names

program ParseATreturns, sclass

    syntax , matnm(string) attype(string) ///
                items(string) binrownums(string) binrownms(string) ///
                mv(string) [ stub(string) stubout(string) debug debug2 ]

    sreturn clear
    tempname ATIN ATTMP
    local binrowN : word count `binrownums' // # rows of at to keep

    * get at() matrix
    capture matrix `ATIN' = `attype'(at)
    if _rc>0 {
        di as error "No `attype'(at) matrix is in memory."
        sreturn local error = 1
        exit
    }
    local ATINcolNMS : colnames `ATIN'
    local ATINrowNMS : rownames `ATIN'

if "`debug2'"=="debug2" {
    di in red _new ">> ParseAT #1 - before parsing" _new
    di "items:      `items'"
    di "ATINcolNMS: `ATINcolNMS'"
    di "ATINrowNMS: `ATINrowNMS'"
    di "binrownums  `binrownums'"
    di "binrownms:  `binrownms'"
    di
    di "ATIN"
    matrix list `ATIN'
    di
}

//  decode atreturns()

*! ParseATreturns: drop columns that are all missing

    if "`items'"=="_all" {
        local TMPATcolNMS "`ATINcolNMS'"
    }
*! add _allmiss option to ParseATreturns
    else if "`items'"=="_allmiss" {
        local TMPATcolNMS "`ATINcolNMS'"
    }
*    else local TMPATcolNMS "`items'"
    else {
        local TMPATcolNMS ""
        foreach i in `items' {
            capture confirm integer number `i'
            if _rc==0 {
                local i : word `i' of `ATINcolNMS'
            }
            local TMPATcolNMS "`TMPATcolNMS' `i'"
        }
    }

    local ATcolNMS ""
    local ATcolNUMS ""
    local error = 0
    foreach atnm in `TMPATcolNMS' {
        local atnum : list posof "`atnm'" in ATINcolNMS
        if `atnum'==0 {
            local error = 1
            di in red "Column `atnm' is not in `attype'(at)"
        }
        else {
            local ATcolNMS "`ATcolNMS' `atnm'"
            local ATcolNUMS "`ATcolNUMS' `atnum'"
        }
    }
    if `error'==1 {
        sreturn local error = 1
        exit
    }

//  keep selected columns and rows

    * select columns
    foreach icol in `ATcolNUMS' {
        matrix `ATTMP' = (nullmat(`ATTMP'), `ATIN'[1...,`icol'])
    }
    * select rows
    capture matrix drop ATmatrix
    foreach irow in `binrownums' {
        matrix ATmatrix = (nullmat(ATmatrix) \ `ATTMP'[`irow',1...])
    }

if "`debug'"=="debug" {
    di "In ParseATreturns #1"
    mat list ATmatrix
}

    * add stubs
    local tmpcolnm "`ATcolNMS'"
    local ATcolNMS ""
    foreach nm in `tmpcolnm' {
        local ATcolNMS "`ATcolNMS' `stub'`nm'`stubout'"
    }

*di "ATcolNMS: `ATcolNMS'"
* 0.3.4 - factor fixes
local stataVrunning = c(stata_version)
    matrix colnames ATmatrix = `ATcolNMS'
    version `stataVrunning' : matrix rownames ATmatrix = `binrownms'

if "`debug'"=="debug" {
    di in red _new ">> ParseATreturns #2" _new
    di "items:      `items'"
    di "ATcolNMS:   `ERretNMS'"
    di "binrownums: `binrownums'"
    di "binrownms:  `binrownms'" _new
    matrix list ATmatrix
    di
}
    sreturn local error = 0

end // ParseATreturns

//  PopulateBAT: add eb() rb() at() data to collect matrix \ 2011-02-08
//  input:  matnm(name of matrix)
//          newrownum(new row of collect matrix)
//          collecttype(U R E)
//          mv(missing value)

program PopulateBAT, sclass

    syntax , matnm(string) mv(string) rownames(string) ///
        ebis(string) rbis(string) atis(string) [ debug debug2 ]

    tempname MATBAT

if "`debug'"=="debug" {
    di in red _new ">> PopulateBAT #0" _new
    di
    di "rownames: `rownames'"
    di "matnm"
    matrix list `matnm'
}

    if `ebis' | `rbis' {
        matrix `MATBAT' = Bmatrix
if "`debug'"=="debug" {
    di "IS B!"
    di in red _new ">> PopulateBAT #1" _new
    matrix list `MATBAT'
}
    }
    if `atis' {
        matrix `MATBAT' = (nullmat(`MATBAT'), ATmatrix)
if "`debug'"=="debug" {
    di "IS AT!"
    di in red _new ">> PopulateBAT #2" _new
    matrix list `MATBAT'
}
    }

* 0.3.4 factors
local stataVrunning = c(stata_version)
version `stataVrunning' : matrix rownames `MATBAT' = `rownames'
    local rowN = rowsof(`MATBAT')
    local rowNMS : rownames `MATBAT'
    local colN = colsof(`MATBAT')
    local colNMS : colnames `MATBAT'

if "`debug'"=="debug" {
    di in red _new ">> PopulateBAT #3 - MATBAT" _new
    matrix list `MATBAT'
}


    * loop through rows and columns of combined Bmatrix + ATmatrix
    forvalues icol = 1(1)`colN' {
        local colnm : word `icol' of `colNMS'
        forvalues irow = 1(1)`rowN' {
            local rownm : word `irow' of `rowNMS'
            * get matrix locations in collect matrix
            GetColNum, matnm(`matnm') name(`colnm')
            local ioutcol = s(colnum)
            GetRowNum, matnm(`matnm') name(`rownm')
            local ioutrow = s(rownum)

if "`debug2'"=="debug2" {
    di in red _new ">> PopulateBAT" _new
    di "irow,jcol: (`irow', `icol') --> CMAT(`ioutrow', `ioutcol')"
    di
}
        * if column doesn't exist, add it
        if `ioutcol'==0 {
           AddCol, matnm(`matnm') newcolname("`colnm'") mv("`mv'")
           local CMATcolN = colsof(`matnm')
           local ioutcol = `CMATcolN'
        }
        * populate the matrix
        matrix `matnm'[`ioutrow',`ioutcol'] = `MATBAT'[`irow',`icol']
        }
    }

if "`debug'"=="debug" {
    di in red _new ">> PopulateBAT" _new
    di in red "MATBAT - combined B and AT"
    mat list `MATBAT'
    di _new in red "Collect matrix"
    mat list `matnm'
    di
}

end // PopulateBAT

//  IsMatNull: get name of column given index # \ 2011-02-08
//  Input:  matnm(string)
//  Output: isnull(string)

program IsMatNull, sclass

    syntax, matnm(string)
    sreturn clear
    local isnull = 0
    local colNMS : colnames `matnm'
    local rowNMS : colnames `matnm'
    local colN = colsof(`matnm')
    local rowN = rowsof(`matnm')
    tempname value
    forvalues r = 1(1)`rowN' {
        local rnm : word `r' of `rowNMS'
        if "`rnm'"!="_N_u_l_l_" {
            sreturn local isnull = 0
            exit
        }
        forvalues c = 1(1)`colN' {
            local cnm : word `r' of `colNMS'
            if "`cnm'"!="_N_u_l_l_" {
                sreturn local isnull = 0
                exit
            }
            scalar `value' = `matnm'[`r',`c']
            if `value'<. {
               sreturn local isnull = 0
               exit
            }
        }
    }
    sreturn local isnull = 1

end // IsNullMat

/*
//  PopulateMatrix: add matrix to collect matrix
//  input:  matnm(name of matrix)
//          mv(missing value)

program PopulateMatrix, sclass

    syntax , matnm(string) mv(string) ///
        [ row1(string) col1(string)  debug debug2 ]

    * names of collect matrix
    local CMATrowNMS : rownames `matnm'
    local CMATcolNMS : rownames `matnm'
    local CMATrowN : word count `CMATrowNMS'
    local CMATcolN : word count `CMATcolNMS'

    * matrow1 specified?
    local isrow1 = 0
    if "`row1'"!="" {
        local isrow1 = 1
        capture confirm integer number `row1'
        * is number
        if _rc==0 local CMATrow1 = `row1'
        * is name
        else {
            local CMATrow1 : list posof "`row1'" in CMATrowNMS
            if `CMATrow1'==0 {
                local CMATrow1 = `CMATrowN' + 1
                * new name so add row
di "#2"
                AddRow, matnm(`matnm') mv("`mv'") newrowname("`row1'")
            }
        }
    }

    * matcol1?
    local iscol1 = 0
    if "`col1'"!="" {
        local iscol1 = 1
        capture confirm integer number `col1'
        if _rc==0 local CMATcol1 = `col1'
        else {
            local CMATcol1 : list posof "`col1'" in CMATcolNMS
            if `CMATcol1'==0 {
di "#1"
                local CMATcol1 = `CMATcolN' + 1
                AddCol, matnm(`matnm') mv("`mv'") newcolname("`col1'")
            }
        }
    }

if "`debug'"=="debug" {
    di in red _new ">> PopulateMatrix" _new
    di
    di "isrow1:   `isrow1'"
    di "CMATrow1: `CMATrow1'"
    di "iscol1:   `iscol1'"
    di "CMATcol1: `CMATcol1'"
}

    * names of input matrix
    local  MATRIXrowNMS : rownames MATRIXmatrix
    local  MATRIXcolNMS : colnames MATRIXmatrix
    local  MATRIXrowN   = rowsof(MATRIXmatrix)
    local  MATRIXcolN   = colsof(MATRIXmatrix)

    * populate collect matrix
    tempname value
    local CMATrownum = `CMATrow1' - 1
    local CMATcolnum = `CMATcol1' - 1

    forvalues MATRIXrownum = 1(1)`MATRIXrowN' {

        local rownm : word `MATRIXrownum' of `MATRIXrowNMS'

        if `isrow1' {
            local CMATrownum = `CMATrownum' + 1
        }
        else { // matrch by row name of input matrix
            GetRowNum, name("`rownm'") matnm(`matnm')
            local CMATrownum = s(rownum)
        }

        forvalues MATRIXcolnum = 1(1)`MATRIXcolN' {

            local colnm : word `MATRIXcolnum' of `MATRIXcolNMS'

            if `iscol1' {
                local CMATcolnum = `CMATcolnum' + 1
            }
            else {
                GetColNum, name("`colnm'") matnm(`matnm')
                local CMATcolnum = s(colnum)
            }

            scalar `value' = MATRIXmatrix[`MATRIXrownum',`MATRIXcolnum']
            if `value'==. scalar `value' = `mv'

            local rowN = rowsof(`matnm')
            if `CMATrownum'==0 | `CMATrownum'>`rowN' {
                AddRow, matnm(`matnm') mv("`mv'") newrowname("`rownm'")
                local CMATrownum = rowsof(`matnm')
            }
            local colN = colsof(`matnm')
            if `CMATcolnum'==0 | `CMATcolnum'>`colN' {
                AddCol, matnm(`matnm') newcolname("`colnm'") mv("`mv'")
                local CMATcolnum = colsof(`matnm')
            }
            matrix `matnm'[`CMATrownum',`CMATcolnum'] = `value'
        }
    }

end // PopulateMatrix
*/
//  PopulateMatrix: add matrix to collect matrix
//  input:  matnm(name of matrix)
//          mv(missing value)

program PopulateMatrix, sclass

    syntax , matnm(string) mv(string) ///
        [ row1(string) col1(string)  debug debug2 ]

    local  MATRIXrowNMS : rownames MATRIXmatrix
    local  MATRIXcolNMS : colnames MATRIXmatrix
    local  MATRIXrowN   = rowsof(MATRIXmatrix)
    local  MATRIXcolN   = colsof(MATRIXmatrix)
    local  CMATrowNMS : rownames `matnm'
    local  CMATcolNMS : colnames `matnm'
    local  CMATrowN   = rowsof(`matnm')
    local  CMATcolN   = colsof(`matnm')
    tempname value

* assign by matching row and column names of input to
* row and column names of collect matrix
if "`row1'"=="" & "`col1'"=="" {

    forvalues irow = 1(1)`MATRIXrowN' {
        local rownm : word `irow' of `MATRIXrowNMS'
        forvalues icol = 1(1)`MATRIXcolN' {
            local colnm : word `icol' of `MATRIXcolNMS'
            * get value
            scalar `value' = MATRIXmatrix[`irow',`icol']
            if `value'==. scalar `value' = `mv'
            * find location in matnm
            GetRowNum, name("`rownm'") matnm(`matnm')
            local crow = s(rownum)
            GetColNum, name("`colnm'") matnm(`matnm')
            local ccol = s(colnum)
            * add row if needed
            if `crow'==0 {
*di "R old crow: `crow'   rownm: `rownm'"
                AddRow, matnm(`matnm') mv("`mv'") newrowname("`rownm'")
                GetRowNum, name("`rownm'") matnm(`matnm')
                local crow = s(rownum)
*di "R new crow: `crow'   rownm: `rownm'"

            }
            * add column if needed
            if `ccol'==0 {
*di "C old ccol: `ccol'   colnm: `colnm'"
                AddCol, matnm(`matnm') newcolname("`colnm'") mv("`mv'")
                GetColNum, name("`colnm'") matnm(`matnm')
                local ccol = s(colnum)
*di "C new: ccol: `ccol'   colnm: `colnm'"
            }
            * add value
            matrix `matnm'[`crow',`ccol'] = `value'
        }
    }

} // assign by row and column names

* place in collect based on row1 and or col1
else {

    * find row1
    if "`row1'"=="" {
        *local CMATrow1 = `CMATrowN' + 1
        local CMATrow1 = 1
    }
    else {
        capture confirm integer number `row1'
        if _rc==0 { // is number
            local CMATrow1 = `row1'
        }
        else { // is name
            local CMATrow1 : list posof "`row1'" in CMATrowNMS
            if `CMATrow1'==0 { // not found
                local CMATrow1 = `CMATrowN' + 1
            }
        }
    }
    * find col1
    if "`col1'"=="" {
        *local CMATcol1 = `CMATcolN' + 1
*0.3.2        local CMATcol1 = n1
        local CMATcol1 = 1 // 0.3.3
    }
    else {
        capture confirm integer number `col1'
        if _rc==0 { // is number
            local CMATcol1 = `col1'
        }
        else { // is name
            local CMATcol1 : list posof "`col1'" in CMATcolNMS
            if `CMATcol1'==0 { // not found
                local CMATcol1 = `CMATcolN' + 1
            }
        }
    }

if "`debug2'"=="debug2" {
    di in red _new ">> xx #" _new
    di
    di  "CMATcol1: `CMATcol1'"
    di  "CMATrow1: `CMATrow1'"
}
*set trace on
    * populate
    local crow = `CMATrow1' - 1
    forvalues irow = 1(1)`MATRIXrowN' {
        local rownm : word `irow' of `MATRIXrowNMS'
        * location in matnm
        local ++crow
        local ccol = `CMATcol1' - 1
        forvalues icol = 1(1)`MATRIXcolN' {
            local colnm : word `icol' of `MATRIXcolNMS'
            * get value
            scalar `value' = MATRIXmatrix[`irow',`icol']
if "`debug2'"=="debug2" {
    di in red _new ">> xy #" _new
    di
    di  "irow:  `irow'"
    di  "icol:  `icol'"
    di  "value: " `value'
}
            if `value'==. scalar `value' = `mv'
            * location in matnm
            local ++ccol
            local iadd = 0
            while `ccol'>`CMATcolN' {
                local ++iadd
                local ccol1 = `ccol' - 1
                * in case fill in columns, add _# to column name
                if `CMATcolN'<`ccol1' {
                    local newcolnm "`colnm'_`iadd'"
                }
                else {
                    local newcolnm "`colnm'"
                }
                AddCol, matnm(`matnm') newcolname("`newcolnm'") mv("`mv'")
                local  CMATcolN   = colsof(`matnm')
            }
            local iadd = 0
            while `crow'>`CMATrowN' {
                local ++iadd
                local crow1 = `crow' - 1
                if `CMATrowN'<`crow1' {
                    local newrownm "`rownm'_`iadd'"
                }
                else {
                    local newrownm "`rownm'"
                }
                AddRow, matnm(`matnm') mv("`mv'") newrowname("`newrownm'")
                local  CMATrowN   = rowsof(`matnm')
            }
            * add value
            matrix `matnm'[`crow',`ccol'] = `value'
* version 0.3.3 2011-03-25 fix matrixrow1() where 1st row dropped
if `crow'==1 & `ccol'==1 {
    local crnm : word 1 of `CMATrowNMS'
    local ccnm : word 1 of `CMATcolNMS'
    if "`crnm'"=="_N_u_l_l_" {
        local CMATrowNMS = subinstr("`CMATrowNMS'","_N_u_l_l_","`rownm'",1)
        matrix rownames `matnm' = `CMATrowNMS'
    }
    if "`ccnm'"=="_N_u_l_l_" {
        local CMATcolNMS = subinstr("`CMATcolNMS'","_N_u_l_l_","`colnm'",1)
        matrix colnames `matnm' = `CMATcolNMS'
    }
}



*mat list `matnm'
        }
    }
*set trace off
} // row1 and col1

end // PopulateMatrix

exit
* version 0.0.6c 2011-02-07 get b - need to populate collect yet...
* version 0.0.5c 2011-02-06 start populating
* version 0.0.4b 2011-02-05 clean code
* version 0.0.3 2011-02-05
* version 0.0.2 2011-02-03
* version 0.0.1 2011-02-02 - i/o and basic syntax
* version 0.0.8 2011-02-08 pre major cleanup
* version 0.0.7a 2011-02-07 ParseAT
* version 0.1.0 2011-02-08 rationalize names
* version 0.1.6 rows(_all)
* version 0.1.5 clear alone didn't change matrix in memory
* version 0.1.4 b doesn't add new names adds extra column
* version 0.1.3 allow no row
* version 0.1.2 2011-02-09 only rows()
* version 0.1.1 2011-02-08 populate b and at
* version 0.2.6 rowstub() added; needs more debugging
* version 0.2.5 auto add row if no row(); don't drop _N_u_l_l_ if other rows are added
* version 0.2.4 mout and outcome
* version 0.2.3 fix z vs t in testnl and test
* version 0.2.2 fix when r(t) is not a test...
* version 0.2.1 matrix
* version 0.2.0 version 10 compatable
* version 0.1.8 rows(xx=_all)
* version 0.1.7 all margins and most factor seems functional
* version 0.3.0 2011-02-19 mrowstub to matrowstub; mcolstub matcolstub
* version 0.2.9 2011-02-18
* version 0.2.8 problem with i.wc in dydx() for margins; c(stata_version) not c(version)!
* version 0.2.7 debug at() options; allow at(3)
* version 0.3.1 matrowstub matcolstub matrow1 matcol1 again
* version 0.3.2 2011-03-01 allow upper case for derivative r() returns