*
* @StructResids(options) u start end v
* converts standard VAR residuals into structural innovations.
*
* Parameters:
*   u = VECT[SERIES] of VAR residuals (input)
*   start end = range to convert
*   v = VECT[SERIES] of structural innovations (output)
*
* Options:
*  FACTOR=factor of covariance matrix, or (if n x p), the loadings
*  from a subset of structural residuals onto the residuals.
*
*  If p<n, the output will be a p-vector of series. You also need to
*  input the SIGMA matrix (or allow use of %SIGMA) to provide enough
*  information to back out the structural residuals.
*
*  SIGMA=covariance matrix of the VAR residuals. Required if FACTOR isn't
*  full size.  By default, the standard matrix %SIGMA.
*
*  WEIGHTS=p x n matrix of weights on the VAR residuals. Alternative to
*  use of FACTOR and SIGMA for a less than full size set of structural
*  residuals.

* Revision Schedule:
*  06/2007 Written by Tom Doan, Estima
*  03/2011 Revised to add the SIGMA and WEIGHTS options.
*  06/2017 Do override of <<start>> and <<end>>
*
procedure StructResids u start end v
type vect[series] u *v
type integer start end
*
option rect 	 factor
option rect 	 weights
option symm 	 sigma		%sigma
*
local integer i n p startl endl
local rect    finv
*
if .not.%defined(v) {
   disp "##Syntax: @StructResids(other options) u start end >>V<<"
   return
}
if .not.%defined(factor).and..not.%defined(weights) {
   disp "##Syntax: @StructResids(FACTOR=factor matrix or WEIGHT=matrix of weights) u start end v"
   return
}
compute n=%rows(u)
if %defined(factor) {
   if %rows(factor)<>n {
      disp "##@StructResids. FACTOR matrix must have "+n+" rows to match size of u"
      return
   }
   if %cols(factor)<>n.and.%rows(%sigma)<>n {
      disp "##@StructResids. With FACTOR matrix with of size "+n+$
"x"+%cols(factor)+" need "+n+"x"+n+"SIGMA option as well"
      return
   }
   if %cols(factor)<>n
      compute finv=tr(factor)*inv(sigma)
   else
      compute finv=inv(factor)
}
else {
   if %cols(weights)<>n {
      disp "##@StructResids. WEIGHTS matrix must have "+n+" columns to match size of u"
      return
   }
   compute finv=weights
}
compute p=%rows(finv)
*
inquire(reglist) startl<<start endl<<end
# u
*
dim v(p)
do i=1,p
   set v(i) startl endl = %dot(%xrow(finv,i),%xt(u,t))
end do i
end

