*! Fields' decomposition of inequality by sources. v.1.0. Stas Kolenikov
program define gfields, rclass
   version 6
   if "`e(cmd)'"!="regress" { error 301 }
   tempname coeff covar
   matrix `coeff'=e(b)

   * retrieve the names from the coefficient matrix
   local regr : colnames(`coeff')
   local nreg : word count `regr'
   * the constant is the last element
   matrix `covar'=J(1,`nreg',0)
   * I would fill in this matrix

   tokenize `regr'
   local i=1
   local sum=0
   while `i'<=`nreg'-1 {
     ESSENSE ``i''
     mat `covar'[1,`i']=r(contrib)
     local sum=`sum'+`covar'[1,`i']
     local coln `coln' ``i''
     * accumulating column names
     local i=`i'+1
   }
   mat `covar'[1,`i']=1-`sum'
   mat colname `covar' = `coln' residual
   mat rowname `covar' = `e(depvar)'

   gettoken lpar rest : 0, parse("(")

   if "`lpar'"=="" {
      * gfields without arguments
      di in gre _n "  Fields' decomposition of factor contributions"
      di in gre _n "  Factor |  Share of SS"
      di in gre    "---------+---------------

      tokenize "`coln' residual"
      local k=1
      while `k'<=`nreg' {
         di in gre %8s "``k''" _col(10) "|     " in yel %6.4f `covar'[1,`k']
         local k=`k'+1
      }

      return matrix contrib `covar'
      exit
   }

   local l=1

   while "`rest'"~="" & "`rest'"~=")" {
     gettoken l`l' rest : rest, parse(")")
     gettoken rpar rest : rest, parse(")")
     cap gettoken lpar rest : rest, parse("(")
     local l=`l'+1
   }
   * cycle over groups

   tempname group it
   mat `group'=J(1,`l'+1,0)

   local l=`l'-1
   * the number of groups; one column in the `group' matrix is for residual,
   * and another one, for unlisted stuff


   di in gre _n "  Fields' decomposition of factor contributions"
   di in gre _n "  Factor |  Share of SS  |  Group share  "
   di in gre    "---------+---------------+---------------"

   local k=1
   local sum=0
   local coln
   while `k'<=`l' {
     unab this : `l`k''
     tokenize `this'
     return local group`k' `this'
     while "`1'"~="" {
        mat `it'=`covar'[1,"`1'"]
        di in gre %8s "`1'" _col(10) "|     " in yel %6.4f `it'[1,1] in gre _col(26) "|"
        mat `group'[1,`k'] = `group'[1,`k'] + `it'[1,1]
        mac shift
     }
     di in gre "Total    |               |    " in yel %6.4f `group'[1,`k']
     di in gre "---------+---------------+---------------"
     local sum=`sum'+`group'[1,`k']
     local coln `coln' Group`k'
     local k=`k'+1
   }
   matrix `group'[1,`k']=`covar'[1,"residual"]
   di in gre "Residual |    " in yel `group'[1,`k'] in gre _col(26) "|     " in yel `group'[1,`k']
   di in gre "---------+---------------+---------------"
   matrix `group'[1,`k'+1]=1-`sum'-`group'[1,`k']
   di in gre "Unlisted |    " in yel `group'[1,`k'+1] in gre _col(26) "|     " in yel `group'[1,`k'+1]
   di in gre "-----------------------------------------"

   mat colname `group' =  `coln' residual unlisted
   mat rowname `group' = `e(depvar)'
   * cycle over the groups
   return matrix contrib `covar'
   return matrix gcontrib `group'
end


pro def ESSENSE, rclass
        args var
        tempname x
        qui g double `x'=_b[`var']*`var'
        qui corr `x' `e(depvar)', cov
        return scalar contrib=r(cov_12)/r(Var_2)
end