*! version 1.1.0  20jun1995     sg41: STB-26
program define rfprobit
	version 4.0
	local options "Level(integer $S_level)"
	if substr("`1'",1,1)=="," | "`*'"=="" {
		if "$S_E_cmd"~="rfprobit" {
			error 301
		}
		parse "`*'"
	}
	else {
		local varlist "req ex"
		local if "opt"
		local in "opt"
		local options /*
		*/ "`options' I(string) Quadrat(integer 6) noCHIsq noLOg *"
		parse "`*'"
		parse "`varlist'", parse(" ")
		local y "`1'"
		macro shift
		xt_iis `i'
		local i "$S_1"
		tempvar doit x w
		mark `doit' `if' `in'
		markout `doit' `y' `*' `i'

	/* Check to see if outcome varies. */

		quietly count if `doit'
		local n = _result(1)
		quietly count if `y'==0 & `doit'
		local n0 = _result(1)
		if `n0'==0 | `n0'==`n' {
			di _n in blu "outcome does not vary"
			exit
		}

	/* Sort data. */

		sort `doit' `i'

	/* Get points and weights for Gaussian-Hermite quadrature. */

		ghquad double(`x' `w'), n(`quadrat')

	/* Set up macros for ml function. */

		global S_sample "`doit'"
		global S_ivar   "`i'"
		global S_x      "`x'"
		global S_w      "`w'"
		global S_quad   "`quadrat'"

	/* Fit constant-only model. */

		if "`chisq'"=="" & "`*'"~="" {
			rfpr_ml `y', title("Constant-only model") /*
			*/	     `log' `options'
			local lf0 "lf0($S_1)"
			local rho "rho($S_2)"
		}

	/* Fit full model. */

		rfpr_ml `y' `*', title("Full model") post `lf0' `rho' /*
		*/	         `log' `options'
	}

/* Display results. */

	ml mlout rfprobit, level(`level')

/* Compute LR test for rho = 0. */

	local chi = 2*($S_E_ll - $S_E_rho0)

	#delimit ;
	di in gr "LR test of rho = 0:   chi2(" in ye "1" in gr ")     = "
	   in ye %7.2f `chi' _n
	   in gr "                      Prob > chi2 = " in ye %7.4f
	   chiprob(1,`chi') ;
	#delimit cr
end


program define rfpr_ml /* y x, title(string) POST noLOg ml_options */
	version 4.0
	local varlist "req ex"
	local options "TITLE(string) POST LF0(string) RHO(string) noLOg *"
	parse "`*'"
	parse "`varlist'", parse(" ")
	local y "`1'"
	macro shift
	local doit "$S_sample"
	if "`lf0'"~="" { local lf0 "lf0(`lf0')" }

	tempname llrho0 b0 b1 lllast b ll V
	tempvar  mldoit

/* Get initial values. */

	quietly probit `y' `*' if `doit'
	scalar `llrho0' = _result(2)
	if "`log'"=="" {
		di _n in gr "`title'"
		di in gr "rho =" in ye %4.1f 0 /*
		*/ in gr "     Log Likelihood = " in ye `llrho0'
	}
	matrix `b0' = get(_b)
	matrix coleq `b0' = `y'
	matrix `b1' = (0)
	matrix colnames `b1' = rho:_cons
	matrix `b0' = `b0' , `b1'
	local rcol = colnumb(`b0',"rho:_cons")

/* Search for good starting value for rho if not supplied. */

	if "`rho'"=="" {
		global S_mldepn "`y'"
		scalar `lllast' = `llrho0'
		local rho    0.05
		local rhotry 0.1
		while `rhotry' < 0.91 {
			matrix `b0'[1,`rcol'] = `rhotry'
			rfpr_ll1 `b0' `ll' `b' , fast(0)
			if "`log'"=="" {
				di in gr "rho =" in ye %4.1f `rhotry' /*
				*/ in gr "     Log Likelihood ~ " in ye `ll'
			}
			if `ll' < `lllast' { /* exit loop */
				local rhotry 1
			}
			else {
				scalar `lllast' = `ll'
				local rho `rhotry'
				local rhotry = `rhotry' + 0.1
			}
		}
	}

	matrix `b0'[1,`rcol'] = `rho'

/* Set up ml commands. */

	ml begin
	ml function rfpr_ll1
	ml method deriv1
	eq `y': `y' `*'
	eq rho:
	ml model `b' = `y' rho, depv(10) from(`b0')
	ml sample `mldoit' if `doit', noauto

	if "`log'"=="" { noisily ml max `ll' `V', `options' }
	else		 quietly ml max `ll' `V', `options'

	global S_1 = `ll'
	global S_2 = `b'[1,`rcol']

	if "`post'"~="" {
		ml post rfprobit, `lf0' pr2 title("Random-Effects Probit")
	}

	global S_E_rho0 = `llrho0'
end

/*
	Routines that compute weights and points for Gaussian-Hermite
	quadrature follow:
*/

* version 1.0.1  29jun1995
program define ghquad
	version 4.0
	local varlist "req new min(2) max(2)"
	local options "N(integer 10)"
	parse "`*'"
	parse "`varlist'", parse(" ")
	local x "`1'"
	local w "`2'"
	if `n' + 2 > _N  {
		di in red  /*
		*/ "`n' + 2 observations needed to compute quadrature points"
		exit 2001
	}
	tempname xx ww
	local i 1
	local m = int((`n' + 1)/2)
	while `i' <= `m' {
		if `i' == 1 {
			scalar `xx' = sqrt(2*`n'+1)-1.85575*(2*`n'+1)^(-1/6)
		}
		else if `i' == 2 { scalar `xx' = `xx'-1.14*`n'^0.426/`xx' }
		else if `i' == 3 { scalar `xx' = 1.86*`xx'-0.86*`x'[1] }
		else if `i' == 4 { scalar `xx' = 1.91*`xx'-0.91*`x'[2] }
		else { scalar `xx' = 2*`xx'-`x'[`i'-2] }
		hermite `n' `xx' `ww'
		qui replace `x' = `xx' in `i'
		qui replace `w' = `ww' in `i'
		local i = `i' + 1
	}
	if mod(`n', 2) == 1 { qui replace `x' = 0 in `m' }
	qui replace `x' = -`x'[`n'+1-_n] in `i'/`n'
	qui replace `w' =  `w'[`n'+1-_n] in `i'/`n'
end


program define hermite  /* integer n, scalar x, scalar w */
	version 4.0
	local n "`1'"
	local x "`2'"
	local w "`3'"
	local last = `n' + 2
	tempvar p
	tempname i
	qui gen double `p' = .
	scalar `i' = 1
	while `i' <= 10 {
		qui replace `p' = 0 in 1
		qui replace `p' = _pi^(-0.25) in 2
		qui replace `p' = `x'*sqrt(2/(_n-2))*`p'[_n-1] /*
		*/	- sqrt((_n-3)/(_n-2))*`p'[_n-2] in 3/`last'
		scalar `w' = sqrt(2*`n')*`p'[`last'-1]
		scalar `x' = `x' - `p'[`last']/`w'
		if abs(`p'[`last']/`w') < 3e-14 {
			scalar `w' = 2/(`w'*`w')
			exit
		}
		scalar `i' = `i' + 1
	}
	di in red "hermite did not converge"
	exit 499
end