*
* @EBA( options )  ueq   req  start  end
* Performs the calculations from Granger and Uhlig(1990), "Reasonable Extreme
* Bounds Analysis", J. of Econometrics, vol 44, pp 159-170.
*
* Parameters:
*   ueq        RATS EQUATION giving the unrestricted model
*   req        RATS EQUATION giving the most restricted model
*   start end  estimation range. By default, the range over which
*              the unrestricted equation can be estimated.
*
* Options:
*   TITLE=description of the coefficient/linear combination being examined
*   DELTA=specific value of delta. If not, used, a set of fixed values ranging
*         in [0,1] is used.
*   UCOEFF=position of a single coefficient being examined in the unrestricted
*          model.
*   RCOEFF=position of a single coefficient being examined in the restricted
*          model.
*   UVECTOR=VECTOR giving linear combination of coefficients to examine in the
*           unrestricted model.
*   RVECTOR=VECTOR giving linear combination of coefficients to examine in the
*           restricted model.
*
* You need one of each of the pairs of UCOEFF & UVECTOR and RCOEFF and RVECTOR.
* For example:
*
*  equation restricted fygn3
*  # constant ip gm2 gpw{1}
*  equation unrestricted fygn3
*  # constant ip gm2{0 1 2 3} gpw{1 2 3 4}
*  @eba(uvector=||0,0,1,1,1,1,0,0,0,0||,rcoeff=3,title="Sum of Money Growth") unrestricted restricted
*
* will analyze the range of the sum of money growth coefficients. In the
* restricted model, there is only the one coefficient, while in the second, there
* are four lags.
*
*  Revision Schedule:
*   04/1988 - written by Harald Uhlig
*   01/2005 - updated and syntax changed by Tom Doan, Estima
*
* This function is used to build up a descriptor string for the linear combination
* used in the analysis.
*
function %eqnlcstring eqn v
type string %eqnlcstring
type equation eqn
type vector v
*
local integer i start
*
compute %eqnlcstring=""
compute start=1
do i=1,%eqnsize(eqn)
   if v(i)<>0.0 {
      if .not.start
         compute %eqnlcstring=%eqnlcstring+"+"
      if v(i)<>1.0
         compute %eqnlcstring=%eqnlcstring+%strval(v(i),"*.*")+%eqnreglabels(eqn)(i)
      else
         compute %eqnlcstring=%eqnlcstring+%eqnreglabels(eqn)(i)
      compute start=0
   }
end do i
end

procedure EBA ueq req start end
type integer start end
type equation ueq req
*
option string  title
option real    delta
option integer ucoeff 1
option integer rcoeff 1
option vector  uvector
option vector  rvector
*
* These are global variables shared by the subprograms
*
local real zzzru zzzrr zzzyvar
local symm zzzxxu zzzxxr
local vect zzzbetau zzzbetar
local integer zzznobs
local real zzzbu zzzvaru zzzbr zzzvarr zzzvlen zzzulen zzzuv zzzco_uv zzzg
local real dwork upper lower
*
local vector  uv  rv
local vector deltalist
*
fixed vector deltagrid(18)
 0.0 .0001 .001 .01 .02 .05 .10 .15 .20 .25 .30 .40 .50 .60 .70 .80 .90 1.00
*
linreg(equation=ueq) * start end
compute zzzru=%rsquared,zzzxxu=%xx,zzzbetau=%beta
linreg(equation=req) * %regstart() %regend()
compute zzzrr=%rsquared,zzzxxr=%xx,zzzbetar=%beta
compute zzznobs=%nobs,zzzyvar=%variance
*
if %defined(uvector)
   compute uv=uvector
else
   compute uv=%unitv(%eqnsize(ueq),ucoeff)

if %defined(rvector)
   compute rv=rvector
else
   compute rv=%unitv(%eqnsize(req),rcoeff)

compute zzzbu=%dot(zzzbetau,uv)
compute zzzvaru=%qform(zzzxxu,uv)
compute zzzbr=%dot(zzzbetar,rv)
compute zzzvarr=%qform(zzzxxr,rv)

compute zzzvlen=sqrt((zzznobs-1.0)*zzzyvar*(zzzru-zzzrr))
compute zzzulen=sqrt(zzzvaru-zzzvarr)
compute zzzuv  =zzzbu-zzzbr
compute zzzco_uv=zzzuv/(zzzulen*zzzvlen)



report(action=define)
report(atrow=1,atcol=1,span) "Restricted Extreme Bounds"
if %defined(title)
   report(atrow=2,atcol=1,span) title
else
   report(atrow=2,atcol=1,span) "For "+%eqnlcstring(ueq,uv)

report(atrow=3,atcol=1,span) "Length of u-vector"
report(atrow=3,atcol=3) zzzulen
report(atrow=4,atcol=1,span) "Length of v-vector"
report(atrow=4,atcol=3) zzzvlen
report(atrow=5,atcol=1,span) "Inner Product     "
report(atrow=5,atcol=3) zzzuv
report(atrow=6,atcol=1,span) "cos(u,v)          "
report(atrow=6,atcol=3) zzzco_uv
*
if .not.%defined(delta)
   compute deltalist=deltagrid
else
   compute deltalist=||delta||

report(atrow=8,atcol=1) "Delta" "Lower" "Upper"
dofor [real] dwork = deltalist
   compute zzzg=sqrt(dwork)
   if dwork<=(1.0-zzzco_uv)/2.0
      compute upper=zzzbu-zzzg*(zzzco_uv*zzzg-sqrt(1-zzzco_uv**2)*sqrt(1-dwork))*zzzulen*zzzvlen
   else
      compute upper=zzzbu-((zzzco_uv-1.0)/2.0)*zzzulen*zzzvlen

   if dwork<=(1.0+zzzco_uv)/2.0
      compute lower=zzzbu-zzzg*(zzzco_uv*zzzg+sqrt(1-zzzco_uv**2)*sqrt(1-dwork))*zzzulen*zzzvlen
   else
      compute lower=zzzbu-((zzzco_uv+1.0)/2.0)*zzzulen*zzzvlen
   report(row=new,atcol=1) dwork lower upper
end dofor
report(action=format,atrow=9,atcol=2,tocol=3,width=8)
report(action=format,atrow=9,atcol=1,tocol=1,picture="#.#####")
report(action=format,atrow=3,atcol=3,torow=6,width=10)
report(action=show)
end

