program define bivariate, rclass byable(recall) sortpreserve
*!	bivariate.ado Version 3.9 14Feb2024 by Mead Over, CGD.
	version 11.1
	syntax varlist(min=2 numeric fv ts) [if] [in] [using]  ///
		[fweight  aweight  pweight  iweight] ,  ///
		[ DEPvar(varname) Matrix(name) ROWnames(string) noVIF UNCentered List  ///
		TABstat Format Format2(str) addstat(string) ///
		OBSGain GROUPSTats(string) group(varname) nowide ESAmple(string) RMColl  ///
		post noDUMmies  ///  New in ver. 2.7
		TABstat2(string) INSpect INSpect2(string)   ///  New in ver. 2.8
		DEMean fer2 Absorb(passthru) TIMEit Verbose(passthru) debug fe_r2j  ///  New in ver. 3.3, 3.4
		addtable replace tex CORrelate COVariance  addnote(string)  ///   New in ver. 3.5
		TBivariate(string) TTabstat(string) TInspect(string) TGrouptab(string) TCo(string)]

	local cmdline bivariate `0'

	if "`timeit'"~="" {
		timer clear 86
		timer on 86
	}

	if "`group'"~="" {
		local pos : list posof "`group'" in varlist
		if `pos'> 0 {
			di as err _n "The grouping variable -" as res "`group'" as err "- cannot also be one of the analysis variables,"  ///
				_n "and thus is omitted from the list of analyzed variables."
			local varlist : list varlist - group
		}
	}

	if "`verbose'"~="verbose" {
		local shhh quietly
	}

	marksample touse
		if "`group'"~="" {
			markout `touse' `group'
		}
		sum `touse', meanonly
		local dropped = _N - `r(sum)'
		local nobs = `r(sum)'
		local nobstxt : display %15.0fc `nobs'

	if "`depvar'"=="" {  // By default, the first variable is the dependent variable
		local depvar = word("`varlist'", 1)
		return local depvar `depvar'
	}
	local rhslist : list varlist - depvar
	qui summ `depvar'
	if `r(Var)' < 0.00000001 {
		di as err "Dependent variable may not be a constant."  ///
			_n "Here dependent variable is: -`depvar'-"  ///
			_n "with variance: `r(Var)'"
		exit 198
	}
	if "`rhslist'"=="" {
		di as err _n "Program requires a dependent variable and at least one independent variable."
		exit 198
	}

	if "`wide'" =="nowide" {
		local wide
	}
	else {
		local wide wide
	}

	//	Following line of code assures that each value of any discrete variable is
	//	separately correlated with the dependent variuable.  Requires Stata version >= 11.1
	local rhslist = subinstr("`rhslist'","i.","ibn.",.)

	//	Specifying the -list- option prevents the expansion of factor variables
	if "`obsgain'"~="" | "`demean'"~="" local list list
	myfvrevar `rhslist' , `list'
		local indepvars `r(displist)'
		return local indepvars `r(displist)'
	fvrevar `r(displist)'
		local rhslist `r(varlist)'
if "`debug'"~= "" {
	di as txt _n "AFTER -myfvrevar-: "
	di as txt _n "  indepvars is: " as res "`indepvars'"
	di as txt _n "  rhslist is: " as res "`rhslist'"
}

	// Build -expvarlist-
	foreach rhsvar of varlist `rhslist' {
		if strmatch("`rhsvar'","__??????") {
			local rhsname_fv : char `rhsvar'[fvrevar]
			local rhsname_ts : char `rhsvar'[tsrevar]
			local rhsname = cond("`rhsname_fv'"~="","`rhsname_fv'",cond("`rhsname_ts'"~="","`rhsname_ts'","error"))
				if "`rhsname'"== "error" exit 199
			if "`rhsname_fv'"~="" {
				//	Label the values of the dummies created from the factor variables
				local dotpos = strpos("`rhsname'",".")
				local beforedot = substr("`rhsname'",1,`dotpos'-1)
				local afterdot = substr("`rhsname'",`dotpos'+1,.)
				local bpos = strpos("`beforedot'","b")
				if `bpos' == 0 {
					local bpos = .
				}
				else {
					local bpos = `bpos' - 1
				}
				local rhsval = real(substr("`beforedot'",1,`bpos'))
				// Only categorical factor variables will have a numeric -rhsval-
				// -rhsval- is the value of the categorical variable corresponding
				// to this expanded dummy variable, -rhsvar-
				if `rhsval'<. {
					if strpos("`afterdot'","#")>0 {
						local afterdot = substr("`afterdot'",1,strpos("`afterdot'","#")-1)
					}
					local origlbl : label (`afterdot') `rhsval'
					tempname `rhsvar'lbl
					sum `rhsvar', meanonly
						local max = `r(max)'
					label define ``rhsvar'lbl' `max' `"`origlbl'"'
					label values `rhsvar' ``rhsvar'lbl'
				}
			}
		}
		else {
			local rhsname `rhsvar'
		}
		local expvarlist `expvarlist' `rhsname'
	}  // End of loop to build -expvarlist-

if "`debug'"~= "" {
	di as txt _n "AFTER building -expvarlist-: "
	di as txt _n "  indepvars is: " as res "`indepvars'"
	di as txt _n "  rhslist is: " as res "`rhslist'"
	di as txt _n "  expvarlist is: " as res "`expvarlist'"
}

	//  New in version 3.4
	if "`fer2'"~= ""  {
		if "`absorb'"=="" {
			di as err "The option -fer2- must be accompanied by the option -absorb({it:FE_vars})-"
			exit 198
	    }
		getfer2 `rhslist' if `touse', displist(`indepvars') `absorb' `verbose' `timeit' `fe_r2j'
		tempname fe_r2mat
		matrix define `fe_r2mat' = r(r2mat)
		local df_a = e(df_a)
		return scalar maxfer2val = `r(maxfer2val)'
		return local maxfer2var `r(maxfer2var)'
		if "`timeit'"~="" {
			return scalar time4fer2 = `r(time4fer2)'
			return scalar time4fer2byvar = `r(time4fer2byvar)'
		}
	}

	//  New in version 3.3
	if "`absorb'"~="" {
		if "`demean'"=="" & "`fer2'"=="" {
		    di as err "The option -absorb()- is ineffective unless either or both of the options -demean- or -fer2- is also specified."
			exit 198
		}
		local fe_vars = subinstr("`absorb'","absorb(", "", 1)
		local fe_vars = subinstr("`fe_vars'",")", "", 1 )
		return local fe_vars `fe_vars'
	}
	preserve
	return local data_is "raw"  // Overwritten if -demean- option selected
	if "`demean'"~="" {
		if "`absorb'"=="" {
			di as err "The option -demean- must be accompanied by the option -absorb({it:FE_vars})-"
			exit 198
	    }
		if "`obsgain'"~="" {
			di as err "The option -demean- is incompatible with the option -obsgain-"
			exit 198
	    }
		if "`rownames'"~="" {
			di as err "The option -demean- is incompatible with the option -rownames()-"  ///
				_n as err "The option is ignored and exectuion continues..."
			local rownames
	    }
		capt which hdfe
		if _rc > 0 {
		    di as err  _n "For the options -`demean'- and -`absorb'-, -bivariate- requires installation of the the user-written command {search hdfe}."
			exit 111
		}

	    if "`group'`depvar'`touse'"~="" local keepvars keepvars(`group' `depvar' `touse')

		if "`timeit'"~="" {
			timer clear 87
			timer on 87
		}
		myfvrevar `varlist' , list
		local dmnlist `r(displist)'
		`shhh' hdfe `dmnlist' [`weight'], `absorb' clear `keepvars' `verbose'
			local df_a = e(df_a)
			return local data_is "demeaned"
			local hdfelist `r(varlist)'
			local demeaned_txt " demeaned"
		if "`timeit'"~="" {
			timer off 87
			qui timer list 87
			local time4demean = `r(t87)'
			return scalar time4demean = `time4demean'
		}
		local rhslist : list hdfelist - depvar

		if "`verbose'"~="" {
			di as txt _n "{help hdfe} returns the following information in r() and e()"
			return list
			ereturn list
		}
	}
if "`debug'"~= "" {
	di as txt _n "AFTER -hdfe- with -demean- equal to:  "  as res "`demean'"
	di as txt _n "  indepvars is: " as res "`indepvars'"
	di as txt _n "  rhslist is: " as res "`rhslist'"
	di as txt _n "  expvarlist is: " as res "`expvarlist'"
	di as txt _n "  hdfelist is: " as res "`hdfelist'"
}
	//	By default, this command keeps all dummies, so that
	//  the resulting expanded varlist does not have full rank.
	//	By leaving -list- blank and specifying -rmcoll-,
	//	the collinear variables are removed, restoring full-rank
	if "`rmcoll'"~="" {
		local whichdropop rmcoll
	}
	if "`group'"~="" {
	    local rmcoll rmcoll
		local whichdropop group
	}
	if "`list'"=="" & "`rmcoll'"~="" {
		qui _rmcoll `rhslist', forcedrop
		local rhslist_rmcoll `r(varlist)'
		local omittedrhs : list rhslist - rhslist_rmcoll
		local rhslist `rhslist_rmcoll'
		if "`omittedrhs'"~="" {
			foreach v of varlist `omittedrhs' {
				local subvnm : char `v'[fvrevar]
				if "`subvnm'"~="" {
					local omitted `omitted' `subvnm'
				}
				else {
					local omitted `omitted' `v'
				}
			}
		}
	}

	if "`vif'"~="novif" {
		qui _regress `depvar' `rhslist' if `touse' [`weight' `exp']
		qui estat vif , `uncentered'
		getvif
		tempname fv_vifmat
		mat def `fv_vifmat' = r(fv_vifmat)
		return scalar meanvif = `r(meanvif)'
		return scalar maxvifval = `r(maxvifval)'
		return local maxvifvar `r(maxvifvar)'
		if "`uncentered'"=="uncentered" {
			local viftype "Uncentered"
		}
		else {
			local viftype "Centered"
		}
	}
	else {
		if "`uncentered'"~="" {
			di as err "Option -uncentered- is incompatible with option -novif-"
			exit 198
		}
		local viftype "Suppressed"
	}

	if "`matrix'"=="" {
		local matrix bivariate
	}
	tempname eb eV  //  Define both as row vectors (ver. 2.7)
	tempname `matrix'

	//  Default column width is 11, the number of letters in the word "Correlation"
	if "`format'" == "" & `"`format2'"' == "" {
		local colwidth = 11
		local format2use format(%11.5f)
	}
	else {
		if "`format'" != "" & `"`format2'"' != "" {
			di as err "may not specify both format and format()"
			exit 198
		}
		if `"`format2'"' != "" {
			capt local tmp : display `format2' 1
			if _rc {
				di as err `"invalid %fmt in format(): `format2'"'
				exit 120
			}
			local colwidth = real(substr("`format2'",strpos("`format2'","%")+1,strpos("`format2'",".")-strpos("`format2'","%")))
			local format2use format(`format2')
		}
		if `"`format'"' != "" {
			local colwidth = 9
			local format2use format(%9.3f)
		}
	}

	di _n as txt "Results for the" as res "`demeaned_txt'" as txt " dependent variable: " as res "`depvar'" as txt " and each of the" as res "`demeaned_txt'" as txt " independent variables:"
		local maxwidth = min(c(linesize) , 74)
		local i = 1
		local thispiece : piece `i' `maxwidth' of "`expvarlist'"
		while `"`thispiece'"' ~="" {
			di as res `"    `thispiece'"'
			local i = `i' + 1
			local thispiece : piece `i' `maxwidth' of "`expvarlist'"
		}
	if "`demean'"~="" {
		di as txt _n "User has specified the options -" as res "demean" as txt "- and " as res "`absorb'" as txt "-,"  ///
			_n as txt "which invoke {help hdfe} to demean the data prior to computing -bivariate- results."
			if "`verbose'"~="" {
				di as txt "  The command issued is:"  ///
					_n as inp `". hdfe `varlist' [`weight'], `absorb' clear `keepvars' `timeit' `verbose'"'
			}
	}

	if `dropped' > 0 {
		di _n as txt "Casewise deletion drops: " as res "`dropped'" as txt " observations."
	}
	if "`omitted'" ~= "" {
		di as txt _n "Option -`whichdropop'- invokes Stata's {help _rmcoll} which drops the following variables because of collinearity:"  ///
			as res _n "  `omitted'"
	}
	di _n as txt "The analysis uses : " as res "`nobstxt'" as txt " observations."
	di    as txt "The variance inflation factor is: " as res "`viftype'"

	if "`rownames'"~="" {
		if ~("`rownames'"=="varname" | "`rownames'"=="eqname" | "`rownames'"=="none") {
			di _n as err "The rownames() option must contain one of the following three strings:"
			di    as res "    varname" as err " if the label of the larger value of each dummy variable is used as its row name"
			di    as res "    eqname" as err " if the label of the larger value of each dummy variable is used as its equation name"
			di    as res "    none" as err " if dummy variable value labels are ignored, equation names remain blank"
			di    as err "                      and the rownames are the variable names."
			exit 198
		}
	}

	//  Compute the bivariate statistics for each [by default, expanded] RHS variable

	//  Standardize the dependent variable
	tempvar std_dep  //  New in ver. 2.71
	qui egen `std_dep' = std(`depvar') if `touse'
	//	Add a column giving number of observations to be gained
	//	if the variable in that row were dropped from the analysis
	local maxobsgain = 0
	local everdummy = 0
	local nmsngvif = 0
	local i = 1
	foreach rhsvar of varlist `rhslist' {
		tempvar std_rhs  //  New in ver. 2.71, use standardized version of -rhsvar-
		qui egen `std_rhs' = std(`rhsvar') if `touse'

		if strmatch("`rhsvar'","__??????") {  //  For expanded factor variables
			local rhsname_fv : char `rhsvar'[fvrevar]
			local rhsname_ts : char `rhsvar'[tsrevar]
			local rhsname = cond("`rhsname_fv'"~="","`rhsname_fv'",cond("`rhsname_ts'"~="","`rhsname_ts'","error"))
				if "`rhsname'"== "error" exit 199
		}
		else {  //  For ordinary or time-series variables.
			local rhsname `rhsvar'
		}

		if "`weight'"=="" {
			qui sum `rhsvar'  if `touse'
				local mean = r(mean)
				local sd = r(sd)
					local min = r(min)
					local max = r(max)
		}
		else {
			qui sum `rhsvar'  if `touse' [aweight `exp']
				local mean = r(mean)
				local sd = r(sd)
					local min = r(min)
					local max = r(max)
		}
		//	Check whether each variable is a dummy
		//  Prior to version 16, the command -varclassify- did not exist
		capt tab `rhsvar' if `touse', mi
			if _rc == 0 {
				local ncat = `r(r)'
			}
			else {
				local ncat = .
			}

		// Remove variables with only one value.
		// These include the -fvrevar-created expanded version
		// of a categorical value with a specified base, e.g. ib3.race
		if `ncat' < 2  {
			local rhslist : list rhslist - rhsvar
		}
		// Display the bivariate statistics on all other variables.
		else {
			//  Special treatment for dummy variables, including dummies
			//  created as temporary variables by -fvrevar-
			if `ncat'==2  {  // Display a -mean- for -min- & for -max-
				if ~(`max' == 1 & `min' == 0) {
					di _n as err "Warning: The variable -`rhsvar'- has only the two values: -`min'- and -`max'-."  ///
						_n as err "Should it be {help recode:recoded} as a dummy variable with values 0 and 1"  ///
						_n as err "or prefixed with the {help fvvarlist##bases:factor variable operator} -i.-?"
						local maxnot1 maxnot1
				}
				local lbl0 : label (`rhsvar') `min'
				local lbl1 : label (`rhsvar') `max'   //  Assumes that the label of the larger value is the condition
					// Replaces characters that are unacceptable in a matrix row or column name
					local lbl1 = subinstr("`lbl1'", ">", "GT",1)
					local lbl1 = subinstr("`lbl1'", ">=", "GE",1)
					local lbl1 = subinstr("`lbl1'", "<", "LT",1)
					local lbl1 = subinstr("`lbl1'", "<=", "LE",1)
					local lbl1 = subinstr("`lbl1'", ".", "%",1)
					local lbl1 = subinstr("`lbl1'", ".", "%",1)
					local pcnt = substr("`lbl1'",strpos("`lbl1'","%")+1,2)
					local lbl1 = subinstr("`lbl1'","%`pcnt'","`pcnt'%",1)
					if trim("`max'")~=trim("`lbl1'") & "`maxnot1'"=="maxnot1"  {
						local lbl1 = trim("`max'=") + trim("`lbl1'")
					}
				qui ttest `depvar'  if `touse', by(`rhsvar')
					local mu_1 = `r(mu_1)'
					local mu_2 = `r(mu_2)'
					local t = -`r(t)'
					local p = `r(p)'
				qui _regress `std_dep' `std_rhs'  if `touse' [`weight' `exp']
					local rho = _b[`std_rhs']
					local V  = (_se[`std_rhs'])^2          //  New in ver. 2.7
				local everdummy = 1
			}  // End of special treatment for dummy variables
			else if `ncat' > 2  | `ncat' >= . {  // For variables with more than two values
				//  New in ver. 2.7
				qui _regress `std_dep' `std_rhs'  if `touse' [`weight' `exp']
					local rho = _b[`std_rhs']
					local se  = _se[`std_rhs']
					local t = _b[`std_rhs']/_se[`std_rhs']
					local p = 2*ttail(e(df_r), abs(`t'))
					local V  = (_se[`std_rhs'])^2          //  New in ver. 2.7
					local pcnt1 = .
				local mu_1 = .
				local mu_2 = .
				local lbl1 "Continuous"
			}

			//  -obsgain- requests -bivariate to add a column giving the number of observations
			//  that could be added to the analyis if this variable were dropped from the right-hand-side
			if "`obsgain'"~="" {
				if "`timeit'"~="" {
					timer clear 85
					timer on 85
				}
				local wothisone : list expvarlist - rhsname

				qui _regress `depvar' `wothisone' `if' `in'  // eschew if `touse'
					local obsplus = `e(N)' - `nobs'

					if `obsplus' > 0 {
						di as txt "Without the variable " as res "`rhsname'" as txt " N would be: " as res `e(N)'
					}
					local comma_og , `obsplus'
				if `obsplus' > `maxobsgain' {
					local maxobsgain = `obsplus'
					local maxobsgainvar `rhsname'
				}
				local obsgaincolname `""Obs Gained""'
				if "`timeit'"~="" {
					timer off 85
					qui timer list 85
					return scalar time4obsgain = `r(t85)'
				}
			}

			if "`fer2'"~= "" & "`absorb'"~="" {
				local rn = rownumb(`fe_r2mat',"`rhsname'")
				local fer2val = el(`fe_r2mat',`rn',2)
				local comma_fer2 , `fer2val'
				local fer2colname "FE_R^2"
			}

			if "`vif'"~="novif" {
				local rn = rownumb(`fv_vifmat',"`rhsname'")
				local vifval = el(`fv_vifmat',`rn',1)
				mat def ``matrix'' = (	nullmat(``matrix'') \   ///
									`rho', `mu_1', `mu_2', `t', `p', `vifval' `comma_og' `comma_fer2' )

				capt confirm number `vifval'  //  Added in version 3.0
				if _rc~=0 {  //  Enumerate the variables missing a VIF due to multicollinearity
					local nmsngvif = `nmsngvif' + 1
					local msngvif `msngvif' "`rhsname'"
				}
			}
			else {
				mat def ``matrix'' = (	nullmat(``matrix'') \   ///
									`rho', `mu_1', `mu_2', `t', `p' `comma_og' `comma_fer2' )
			}
			mat def `eb' = (	nullmat(`eb') ,  `rho')    //  New in ver. 2.7
			mat def `eV' = (	nullmat(`eV') ,  `V')      //  New in ver. 2.7

			if "`rownames'"=="" | "`rownames'"=="none" {
				local rownms`i' `rownms`i'' `rhsname'
			}
			else {
				local lbl1 = subinstr(`"`lbl1'"'," ","_",.)
				if "`rownames'"=="varname" {
					local rownms`i' `rownms`i'' `"`lbl1'"'
					local eqns `eqns' `rhsname'
				}
				if "`rownames'"=="eqname" {
					if `"`lbl1'"'=="Continuous" {
						local rownms`i' `rownms`i'' `rhsname'
						local eqns `eqns' `"`lbl1'"'
					}
					else {
						if strpos("`rhsname'",".") {
							local dotpos = strpos("`rhsname'",".")
							local afterdot = substr("`rhsname'",`dotpos'+1,.)
							local rhsname `afterdot'
						}
						local rownms`i' `rownms`i'' `"`lbl1'"'
						local eqns `eqns' `rhsname'
					}
				}
			}

			if length(`"`rownms`i''"')> 210 {
				local i = `i' + 1
				if `i' > /* 5 */ 50 {  //  With -list- option works with -20- instead of -5-
					di as err "Too many variables for program -bivariate-"
					exit 198
				}
			}
		}  //  End of loop for factor variables
	}  //  End of loop through the RHS variables

	mat roweq   ``matrix'' = `eqns'
	mat rownames ``matrix'' = `rownms1' `rownms2' `rownms3' `rownms4'  `rownms5'
	if "`vif'"~="novif" {
		mat colnames ``matrix'' =  "Correlation" "For D=0" "For D=1" "t-stat" "p-value" "VIF" `obsgaincolname' `fer2colname'
		return matrix vifmat = `fv_vifmat'
	}
	else {
		mat colnames ``matrix'' =  "Correlation" "For D=0" "For D=1" "t-stat" "p-value" `obsgaincolname' `fer2colname'
	}
	if `everdummy'==0 | "`dummies'"=="nodummies" {  // If there are no dummy variables, delete the columns 2 and 3.
		tempname col1 cols45
		mat def `col1'   = ``matrix''[1...,"Correlation"]
		mat def `cols45 '= ``matrix''[1...,"t-stat"...]
		mat def ``matrix'' = `col1' , `cols45'
	}

	di _n(2) as txt "Table of bivariate correlation coefficients for the" as res "`demeaned_txt'" as txt " dependent variable: " as res "`depvar'"
	local xtrapercol = 4
	local indent1 = 12 +  max(0,ceil(`xtrapercol'+`colwidth' - 9))  // "Coef. of" has 9 characters
	local indent2 = 12 + `xtrapercol' + `colwidth' + max(0,ceil((2*(`xtrapercol'+`colwidth') - 19)/2))  // "Means of variables:" has 19 characters
	if `everdummy'==0 | "`dummies'"=="nodummies"  {
		di _n _col(`indent1') as txt "Coef. of" _col(`indent2')
	}
	else {
		di _n _col(`indent1') as txt "Coef. of" _col(`indent2') as txt "Means of " as res "`depvar'" as txt ":"
	}
	matlist  ``matrix'', `format2use' noblank

	if `nmsngvif' > 0 {
	    di as txt "For the following " as res `nmsngvif' as txt " variable(s), which {help regress} would omit from a multiple regression"  ///
		_n as txt "due to multicollinearity, the VIF value is undefined because it would be infinitely large."  ///
			_n as res `"    `msngvif'"'
		return scalar nmsngvif = `nmsngvif'
		return local msngvif  `msngvif'
	}

	if "`obsgain'"~="" {
		return scalar maxobsgain = `maxobsgain'
		return local maxobsgainvar `maxobsgainvar'
	}

	if "`addtable'" =="" {
	    local ftbl `replace' landscape
	}
	else {
	    local ftbl addtable  pretext("\page")
	}

	if `"`using'"'~="" {
	    if "`tbivariate'"=="" {
			local tbivariate title("Bivariate correlations with -`depvar'- and other diagnostic statistics from program -bivariate-")
		}
		else {
			local tbivariate title(`"`tbivariate'"')
		}
		di as txt  ///
			_n "Writing -bivariate result table -r(`matrix')- to a file using -frmttable- with command:"
		di as inp `". frmttable `using', statmat(r(`matrix'))  `ftbl' `tbivariate' `tex' "'
	    frmttable `using' , statmat(``matrix'') `ftbl' `tbivariate' `tex' note("`nobstxt' observations used after casewise deletion" \ `"`addnote'"') nodisplay
	}
	else {
		di as txt  ///
			_n "If Gallup's -{help frmttable}- is installed, user can write the -bivariate- results table" _n  "to a MS Word or TeX file with a command like:"
		di as txt "    {stata frmttable , statmat(r(`matrix')) } "
	}

	return scalar N = `nobs'
	return matrix `matrix' = ``matrix''

	//	Produce the descriptive statistics output
	if "`tabstat'"~="" | "`tabstat2'"~="" {
		di _n as txt "Option -tabstat-:"  ///
			_n "Descriptive statistics on the" as res "`demeaned_txt'" as txt " dependent and the" as res "`demeaned_txt'" as txt " independent variables: "
		if "`tabstat2'"=="" {
		    local tablist mean median sd cv min max skewness `addstat'
		}
		else {
		    local tablist `tabstat2' `addstat'
		}
		qui tabstat `depvar' `rhslist' if `touse' [`weight' `exp'], s(`tablist') columns(stat) `format2use' save
		tempname StatTotal TransposedST
		matrix define `StatTotal' = r(StatTotal)
		mat colnames `StatTotal' = `depvar' `rownms1' `rownms2' `rownms3' `rownms4'  `rownms5'
		matrix define `TransposedST' = `StatTotal''
		return matrix StatTotal = `StatTotal'
		matlist `TransposedST' , noheader `format2use'

		if `"`using'"'~="" {
			if "`ttabstat'"=="" {
				local ttabstat title("Descriptive statistics from option -tabstat- of program -bivariate-")
			}
			else {
				local ttabstat title(`"`ttabstat'"')
			}
			di as txt  ///
				_n "Writing -bivariate-'s -tabstat- result table -r(TransposedST)- to a file using -frmttable- with command:"
			di as inp `". frmttable `using', statmat(r(TransposedST))  addtable  pretext("\page") `tex'   "'
			frmttable `using' , statmat(`TransposedST') addtable  pretext("\page") `ttabstat' `tex'  note("`nobstxt' observations used after casewise deletion" \ `"`addnote'"') nodisplay
		}
		else {
			di as txt  ///
			_n "If Gallup's -{help frmttable}- is installed, user can write -bivariate-'s -tabstat- table" _n  "to a MS Word or TeX file with a command like:"
			di as txt "    {stata frmttable , statmat(r(TransposedST)) } "
		}
		return matrix TransposedST = `TransposedST'
	}

	//	Produce the correlation coefficients or covariances output among the independent variables
	if "`correlate'"~="" | "`covariance'"~="" {
		di _n as txt "Option -correlate- or -covariance-:"  ///
			_n "Correlation or covariance statistics on the" as res "`demeaned_txt'" as txt " independent variables: "
		qui correlate `rhslist' if `touse' [`weight' `exp'], `covariance'

		local nvars = wordcount("`rhslist'")
		local nchars = strlen("`rhslist'")
		if `nvars' > 10 | `nchars' > 80 {
			foreach v of varlist `rhslist' {
				local abrv = substr("`v'",1,5)
				local ctitlesabrev `ctitlesabrev' `comma' `abrv'
				local comma ,
				local cwidths `cwidths' 5
			}
			local ctitles ctitles("`demeaned' Variables" , `ctitlesabrev')
			if "`tex'"=="" {
				local colwidth colwidth(`cwidths')
				local basefont basefont(fs8)
			}
		}

		tempname corr_or_cov
		matrix define `corr_or_cov' = r(C)
		if "`covariance'"=="" {
		    local cfrmt format(%9.4f)
			local ctype correlation
		}
		else {
		    local cfrmt format(%9.0g)
			local ctype covariance
		}
		matlist `corr_or_cov' , noheader `cfrmt'
		if `"`using'"'~="" {
			if "`tco'"=="" {
				local Ctype = subinstr("`ctype'","c","C",1)
				local tco title("`Ctype's among independent variables from option -`ctype'- of program -bivariate-")
			}
			else {
				local tco title(`"`tco'"')
			}
			di as txt  ///
				_n "Writing -bivariate-'s -`ctype'- result table -r(`ctype')- to a file using -frmttable- with command:"
			di as inp `". frmttable `using', statmat(r(`ctype'))  addtable  pretext("\page") `tex'   "'
			frmttable `using' , statmat(`corr_or_cov') addtable  pretext("\page") `tco' `tex' `ctitles' `colwidth' `basefont'  note("`nobstxt' observations used after casewise deletion" \ `"`addnote'"') nodisplay

		}
		else {
			di as txt  ///
			_n "If Gallup's -{help frmttable}- is installed, user can write -bivariate-'s -`ctype'- table" _n  "to a MS Word or TeX file with a command like:"
			di as txt "    {stata frmttable , statmat(r(`corr_or_cov')) } "
		}
		return matrix `ctype' = `corr_or_cov'
	}

	//  Produce the -inspect- statistics
	if "`inspect'"~="" | "`inspect2'"~="" {
		di _n as txt "Option -inspect-:"  ///
			_n "Results of Stata's -inspect- command for the" as res "`demeaned_txt'" as txt " dependent and the" as res "`demeaned_txt'" as txt " independent variables: "

		if "`inspect2'"~="" {
		    local inspect_list "`inspect2'"
		}
		else {
		    local inspect_list N N_neg N_0 N_pos N_negint N_posint N_unique N_undoc
		}
		tempname `inspect_list'
		foreach v of varlist `depvar' `rhslist' {
		    qui inspect `v' if `touse'
			foreach mname in `inspect_list' {
				mat def ``mname'' = (nullmat(``mname'') \ `r(`mname')' )
			}
		}
		tempname inspect
		foreach mname in `inspect_list' {
			mat def `inspect' = (nullmat(`inspect') , ``mname'')
		}
		mat rownames `inspect' = `depvar' `rownms1' `rownms2' `rownms3' `rownms4'  `rownms5'
		mat colnames `inspect' = `inspect_list'

		if "`format'"=="" & "`format2'"=="" {
		    local frmt4insp format(%8.0g)
		}
		else {
		    local frmt4insp `format2use'
		}
		matlist `inspect' , `frmt4insp'

		if `"`using'"'~="" {
			if "`tinspect'"=="" {
				local tinspect title("Observation counts from option -inspect- of program -bivariate-")
			}
			else {
				local tinspect title(`"`tinspect'"')
			}
			di as txt  ///
				_n "Writing -bivariate-'s -inspect- table -r(inspect)- to a file using -frmttable- with command:"
			di as inp `". frmttable `using', statmat(r(inspect)))  addtable  pretext("\page") `tex'   "'
			frmttable `using' , statmat(`inspect')  sdec(0) addtable  pretext("\page") `tinspect' `tex'  note("`nobstxt' observations used after casewise deletion" \ `"`addnote'"') nodisplay
		}
		else {
			di as txt  ///
			_n "If Gallup's -{help frmttable}- is installed, user can write -bivariate-'s -inspect- table" _n  "to a MS Word or TeX file with a command like:"
			di as txt "    {stata frmttable , statmat(r(inspect)) sdec(0) } "
		}

		return matrix inspect = `inspect'
	}

	//	Produce the statistics by group using the discriminant analysis command
	if "`groupstats'`group'"~="" {
		grouptab`wide' `depvar' `rhslist' if `touse' [`weight' `exp'], group(`group') groupstats(`groupstats') `format2use'
		tempname grouptab
		tempname frmttable
		mat define `grouptab' = r(grouptab)
		mat define `frmttable' = r(frmttable)
		if "`wide'" ~= "" {
			return local statlist `r(statlist)'
			return local N_stats  `r(N_stats)'
			return matrix frmttable = `frmttable'
		}
		return matrix grouptab = `grouptab'
	}
	restore
	if "`esample'"~="" {
		tokenize "`esample'", parse(" ,")
		local esmplvar `1'
		if "`3'"=="replace" {
			capture drop `esmplvar'
		}
		gen byte `esmplvar' = `touse'
		lab var `esmplvar' "Identifies observations in sample analyzed by -bivariate-"
		return local esamplevar "`esmplvar'"
	}

	ereturn clear
	if "`post'"~="" {

		matrix rownames `eb' = `depvar'
		matrix colnames `eb' = `rownms1' `rownms2' `rownms3' `rownms4'  `rownms5'
		tempname Vmat
		matrix define `Vmat' = diag(`eV'')
		matrix rownames `Vmat' = `rownms1' `rownms2' `rownms3' `rownms4'  `rownms5'
		matrix colnames `Vmat' = `rownms1' `rownms2' `rownms3' `rownms4'  `rownms5'

		if "`df_a'"~="" local opt_df_a df_a(`df_a')

		biv_corr if `touse', b(`eb') vmat(`Vmat') nobs(`nobs') cmdline(`"`cmdline'"') depvar(`depvar') varlist(`indepvars') `opt_df_a' `absorb'

	}

	if "`timeit'"~="" {
		timer off 86
		qui timer list 86
		local time4biv = `r(t86)'
		di as txt "Execution time for -bivariate-: " as res `time4biv'   as txt " seconds."
		return scalar time4biv = `time4biv'
	}
	if "`fe_r2mat'"~=""  return matrix fe_r2mat `fe_r2mat'
	if "`df_a'"~=""  return scalar df_a = `df_a'

end	//	End of program bivariate

************************Subroutines**************************************
program define biv_corr, eclass
*	Only function of this subroutine is to -post- the results to -ereturn- space
	syntax [if], b(name) vmat(name) nobs(real) cmdline(string) depvar(varname) varlist(varlist fv ts)  [df_a(real -1) absorb(varlist)]

	marksample touse

	local df_r = cond(`df_a' < 0, `nobs' - 2, `nobs' - 2 - `df_a')

	ereturn post `b' `vmat', properties(b V) esample(`touse') obs(`nobs') dof(`df_r')

	if `df_a' > -1 ereturn scalar df_a = `df_a'
	if `df_a' > -1 ereturn local data_is "demeaned"
	if `df_a' <  0 ereturn local data_is "raw"
	if "`absorb'"~="" ereturn local fe_vars `absorb'
	ereturn local marginsnotok _ALL
	ereturn local varlist `varlist'
	ereturn local depvar `depvar'
	ereturn local cmdline `"`cmdline'"'
	ereturn local cmd bivariate

end  // End of subroutine biv_corr

program define getvif, rclass
* Based on program maxvif   Version 1.0  by Mead Over, May 4, 2012
	if "`r(name_1)'`r(vif_1)'" == "" {
		di as err "This -getvif- subroutine must be executed immediately after the command -estat vif-"
		exit 198
	}
	tempname vifmat fv_vifmat
	tempname sumvif
	scalar `sumvif' = 0
	local i = 1
	local j = 1
	local maxvif = -99999999999999999999
	//	Make one VIF matrix, but for factor and ts variables keep track of both variable names
	while "`r(name_`i')'`r(vif_`i')'" ~= "" {

		scalar `sumvif' = `sumvif' + `r(vif_`i')'

		if strmatch("`r(name_`i')'","__??????") {
			local rhsname_fv : char `r(name_`i')'[fvrevar]
			local rhsname_ts : char `r(name_`i')'[tsrevar]
			local rhsname = cond("`rhsname_fv'"~="","`rhsname_fv'",cond("`rhsname_ts'"~="","`rhsname_ts'",""))
		}
		else {
			local rhsname `r(name_`i')'
		}

		if `r(vif_`i')'>`maxvif' & `r(vif_`i')'<. {
			local maxvif = `r(vif_`i')'
			local maxvifvar `rhsname'
		}

		mat `vifmat' = (nullmat(`vifmat') \ `r(vif_`i')' )

		local rownames`j' = "`rownames`j'' " + "`r(name_`i')'"
		//	Second set of variable/row names for expanded factor and ts variables
		local fv_rownames`j' = "`fv_rownames`j'' " + "`rhsname'"

		while length("`rownames`j''")> 220 {
			local j = `j' + 1
			if `j' > 5 {
				di as err "Too many variables for program -bivariate-"
				exit 198
			}
		}

		local i = `i' + 1
	}
	//	First version of VIF matrix, with temporary variable rownames for expanded factor variables
	matrix colnames `vifmat' = "VIF"
	matrix rownames `vifmat' = `rownames1' `rownames2' `rownames3' `rownames4' `rownames5'
	//	Second version of VIF matrix, with meaningful rownames of expanded factor variables
	mat define `fv_vifmat' = `vifmat'
	matrix colnames `fv_vifmat' = "VIF"
	matrix rownames `fv_vifmat' = `fv_rownames1' `fv_rownames2' `fv_rownames3' `fv_rownames4' `fv_rownames5'

	return matrix vifmat = `vifmat'
	return matrix fv_vifmat = `fv_vifmat'
	return scalar meanvif = `sumvif'/(`i'-1)
	return scalar maxvifval = `maxvif'
	return local maxvifvar `maxvifvar'
	return local viftype `viftype'
end  /* End of program getvif */

program define grouptab, rclass
	//	Produce the statistics by group using the discriminant analysis command
	//	Arrange the results matrix in long format
	syntax varlist [if] [in] [using] [fweight aweight pweight iweight][, groupstats(string) group(varname) format(string)]

	if "`format'"~="" {
		local format format(`format')
	}
	local i = 1
	if "`groupstats'`group'" ~= "" {
		if "`group'" == "" {
			di as err _n "Option -groupstats- selected, but no -group- variable designated."
			exit 198
		}
		if "`groupstats'" == "" {
			local groupstats n mean
		}
		qui discrim lda `varlist' `if' [`weight' `exp'], group(`group')
			local N_groups = e(N_groups)
			local N_vars = e(k)
		qui estat grsumma, `groupstats'
		local matlist
		local statlist
		local N_stats = 0
		foreach stat0 in `groupstats' {
			tempname `stat0'_mat
			if "`stat0'" == "n" {
				local stat count
				mat define `n_mat' = r(`stat')
			}
			else {
				local stat `stat0'
				mat define ``stat'_mat' = r(`stat')
				local matlist `matlist' ``stat'mat'
				local statlist `statlist' `stat'
				local N_stats = `N_stats' + 1
			}
		}
		tempname grouptab	//	Name of the new matrix of group statistics
		foreach var of varlist `varlist' {
			local rowno = `rowno' + 1
			if strmatch("`var'","__??????") {
				local rhsname : char `var'[fvrevar]
			}
			else {
				local rhsname `var'
			}
			foreach stat in `statlist' {
				local thisrow
				local comma
				foreach cat of numlist 1/`N_groups' {
					local thisel = el(matrix(``stat'_mat'),`rowno',`cat')
					local thisrow `thisrow' `comma' `thisel'
					local comma ,
				}
				mat def `grouptab' = (	nullmat(`grouptab') \   `thisrow' )
				local grownms`i' `grownms`i'' `stat'
				local geqnms`i' `geqnms`i'' `rhsname'
			}
			if length("`grownms`i''")> 220 | length("`geqnms`i''")> 220 {
				local i = `i' + 1
				if `i' > 5 {
					di as err "Too many variables for option -group()- of program -bivariate-"
					exit 198
				}
			}
		}
		mat rownames `grouptab' = `grownms1' `grownms2' `grownms3' `grownms4'  `grownms5'
		mat roweq    `grouptab' = `geqnms1' `geqnms2' `geqnms3' `geqnms4'  `geqnms5'
		local vlbl : value label `group'
		qui levelsof `group'
			local lvls `r(levels)'
		foreach grp of numlist 1/`N_groups' {
			if "`vlbl'"=="" {
				local gcolnms `gcolnms' Group`grp'
			}
			else {
				local thislvl : word `grp' of `lvls'
				local thislbl : label `vlbl' `thislvl'
				local gcolnms `gcolnms' `thislbl'
			}
		}
		mat colnames `grouptab' =  `gcolnms'
	}
	di _n as txt "Statistics by group available in the matrix r(grouptab)"
	matlist `grouptab', `format' noheader

	if `"`using'"'~="" {
		if "`tgrouptab'"=="" {
			local tgrouptab title("Descriptive statistics by group from option -grouptab- of program -bivariate-")
		}
		else {
			local tgrouptab title(`"`tgrouptab'"')
		}
		di as txt  ///
			_n "Writing -bivariate-'s -grouptab- table -r(grouptab)- to a file using -frmttable- with command:"
		di as inp `". frmttable `using', statmat(r(grouptab)))  addtable  pretext("\page") `tex'   "'
		frmttable `using' , statmat(`grouptab') addtable  pretext("\page") `tgrouptab' `tex'  note("`nobstxt' observations used after casewise deletion" \ `"`addnote'"') nodisplay
	}
	else {
		di as txt  ///
		_n "If Gallup's -{help frmttable}- is installed, user can write -bivariate-'s -grouptab- table" _n  "to a MS Word or TeX file with a command like:"
		di as txt "    {stata frmttable , statmat(r(grouptab)) } "
	}

	return matrix grouptab `grouptab'	//	Returns the long version of the grouptab matrix

	return local statlist `statlist'
	return local N_stats = `N_stats'

end	//	End of program grouptab

program define grouptabwide, rclass
	//	Produce the statistics by group using the discriminant analysis command
	//	Arrange the results matrix in wide format
	syntax varlist [if] [in] [using] [fweight aweight pweight iweight][, groupstats(string) group(varname) format(string)]

	if "`format'"~="" {
		local format format(`format')
	}
	local i = 1
	if "`groupstats'`group'" ~= "" {
		if "`group'" == "" {
			di as err _n "Option -groupstats- selected, but no -group- variable designated."
			exit 198
		}
		if "`groupstats'" == "" {
			local groupstats n mean
		}

		qui discrim lda `varlist' `if' [`weight' `exp'], group(`group')
			local N_groups = e(N_groups)
			local N_vars = e(k)

		qui estat grsumma, `groupstats'  // This output provides group sizes
		local matlist
		local statlist
		local N_stats = 0

		foreach stat0 in `groupstats' {
			tempname `stat0'_mat
			if "`stat0'" == "n" {
				local stat count
				mat define `n_mat' = r(`stat')
			}
			else {
				local stat `stat0'
				mat define ``stat'_mat' = r(`stat')
				local matlist `matlist' ``stat'mat'
				local statlist `statlist' `stat'
				local N_stats = `N_stats' + 1
			}
		}

		tempname grouptab	//	Name of the new matrix of group statistics
		local rowno = 0
		foreach var of varlist `varlist' {
			local rowno = `rowno' + 1
			if strmatch("`var'","__??????") {
				local rhsname : char `var'[fvrevar]
			}
			else {
				local rhsname `var'
			}
			local thisrow
			local comma
			foreach cat of numlist 1/`N_groups' {
				foreach stat in `statlist' {
					local colno = `colno' + 1
					local thisel = el(matrix(``stat'_mat'),`rowno',`cat')
					local thisrow `thisrow' `comma' `thisel'
					local comma ,
					local gcolnms`i' `gcolnms`i'' `stat'
				}
			}
			mat def `grouptab' = (	nullmat(`grouptab') \   `thisrow' )
			local grownms`i' `grownms`i'' `rhsname'
			if length("`grownms`i''")> 220 ///
				| length("`gcolnms`i''")> 220 ///
				| length("`geqnms`i''")> 220 {
				local i = `i' + 1
				if `i' > 5 {
					di as err "Too many variables for option -group()- of program -bivariate-"
					exit 198
				}
			}
		}

		local vlbl : value label `group'
		qui levelsof `group'
			local lvls `r(levels)'
		foreach grp of numlist 1/`N_groups' {
			foreach stat in `statlist' {
				local gcolnms `gcolnms' `stat'
				if "`vlbl'"=="" {
					local geqnms `geqnms' Group`grp'
				}
				else {
					local thislvl : word `grp' of `lvls'
					local thislbl : label `vlbl' `thislvl'
					local geqnms `geqnms' `thislbl'
				}
			}
		}

		mat rownames `grouptab' = `grownms1' `grownms2' `grownms3' `grownms4'  `grownms5'
		mat colnames `grouptab' = `gcolnms'
		mat coleq    `grouptab' = `geqnms'
	}
	tempname frmttable
	mat define `frmttable' = `grouptab'
	mat coleq    `frmttable' = _:  			//	Blanks out the equation names to create
	mat colnames `frmttable' = `geqnms'		//	a matrix for the frmttable command

	di _n as txt "Statistics by group available in the matrix r(grouptab)"
	matlist `grouptab', `format' noheader

	if `"`using'"'~="" {
		if "`tgrouptab'"=="" {
			local tgrouptab title("Descriptive statistics by group from option -grouptab- of program -bivariate-")
		}
		else {
			local tgrouptab title(`"`tgrouptab'"')
		}
		di as txt  ///
			_n "Writing -bivariate-'s -grouptab- table -r(grouptab)- to a file using -frmttable- with command:"
		di as inp `". frmttable `using', statmat(r(grouptab)))  addtable  pretext("\page") `tex'   "'
		frmttable `using' , statmat(`grouptab') addtable  pretext("\page") `tgrouptab' `tex'  note("`nobstxt' observations used after casewise deletion" \ `"`addnote'"') nodisplay
	}
	else {
		di as txt  ///
			_n "If Gallup's -{help frmttable}- is installed, click on one of the following links:"
		di as txt "    {stata frmttable , statmat(r(grouptab))} "
		di as txt "    {stata frmttable , statmat(r(frmttable)) note(Statistics are -- `statlist') substat(`N_substats')} "
	}

	return matrix grouptab `grouptab'	//	Returns the wide version of the grouptab matrix
	return matrix frmttable `frmttable'
	local N_substats = `N_stats' - 1
	return local statlist `statlist'
	return local N_stats = `N_stats'
end	//	End of program grouptabwide

prog define myfvrevar, rclass
*	Execute fvrevar as if it had a -fvonly- option
	syntax varlist(numeric ts fv) , [list]

	foreach v in `varlist' {
	    fvrevar `v'
			local expvlist `r(varlist)'
			local firstev : word 1 of `expvlist'
			local rhsname_ts : char `firstev'[tsrevar]
			local rhsname_fv : char `firstev'[fvrevar]
			local type = cond("`rhsname_fv'"~="","fv",cond("`rhsname_ts'"~="","ts","not_fv_or_ts"))
		if "`type'"== "not_fv_or_ts" {
			local reallist `reallist' `v'          // List of actual variable names, permanent & temporary
			local displist `displist' `v'          // List of displayed -subvarnames- names
		}
		else if "`type'"=="ts"  {
			local reallist `reallist' `firstev'
			local displist `displist' `rhsname_ts'
		}
		else if "`type'"=="fv"  {
			if "`list'"=="" {
				foreach ev of varlist `expvlist' {
					local rhsname_fv : char `ev'[fvrevar]
					local reallist `reallist' `ev'
					local displist `displist' `rhsname_fv'
				}
			}
			else {  // -list- option only affects factor variables
				fvrevar `v', list
				local reallist `reallist' `r(varlist)'
				local displist `displist' `r(varlist)'
			}
		}
		else {
			di as err "This error should never occur"
			exit 198
		}

	}
	local reallist : list uniq reallist
	local displist : list uniq displist

	return local reallist `reallist'	// List of actual variable names, permanent & temporary
	return local displist `displist'	// List of displayed -subvarnames- names

end  //  End of program myfvrevar

prog define getfer2, rclass
	syntax varlist (numeric fv ts) [if], displist(string) absorb(passthru) [verbose(passthru) timeit fe_r2j]

if "`debug'"~= "" {
	di as txt _n "INSIDE -getfer2-: "
	di as txt _n "  displist is: " as res "`displist'"
	di as txt _n "  varlist is: " as res "`varlist'"
}

	capt which reghdfe
	if _rc > 0 {
		di as err  _n "With the options -`fer2'- and -`absorb'- invoked, this program requires installation of the the user-written command {search reghdfe}."
		exit 111
	}
	tempname fe_r2mat
	local rnms
	local cnms
	//  The -cache- option does not seem to work even on -old- version
*	local cache cache(save,keep(sampleaafb1 aafb1 Ucluster)) old
	if "`timeit'"~="" timer clear 88
	local maxfer2 = -99999999999999999999
	foreach v of local varlist {
		if "`timeit'"~=""  timer on 88
		if strmatch("`v'","__??????") {
			local rhsname_fv : char `v'[fvrevar]
			local rhsname_ts : char `v'[tsrevar]
			local rhsname = cond("`rhsname_fv'"~="","`rhsname_fv'",cond("`rhsname_ts'"~="","`rhsname_ts'",""))
		}
		else {
			local rhsname `v'
		}

		local restofvars : list varlist - v
		if "`fe_r2j'" ~= "" {
			qui reghdfe `v' `restofvars' `if', `absorb' `verbose'
				local r2_rest =`e(r2)'
				local comma_r2_rest  , `r2_rest'
				local vif = 1/(1 - `e(r2)')
				local comma_vif , `vif'
				local extracnms  R^2j  VIF_w_FE
		}
		qui reghdfe `v' `if', `absorb'
			local nobs = `e(N)'
			local r2_fe  =`e(r2)'
		local rnms `rnms' `rhsname'
		mat def `fe_r2mat' = nullmat(`fe_r2mat') \ ( `nobs' ,  `r2_fe' `comma_r2_rest' `comma_vif' )

		if `r2_fe'>`maxfer2' & `r2_fe'<. {
			local maxfer2 = `r2_fe'
			local maxfer2var `rhsname'
		}

		if "`timeit'"~=""  timer off 88
	}
	if "`timeit'"~="" {
		qui timer list 88
		local time4fer2 = `r(t88)'
		local time4fer2byvar = `time4fer2'/`r(nt88)'
	}
	mat rownames `fe_r2mat' = `rnms'
	mat colnames `fe_r2mat' = N FE_R^2 `extracnms'

	if "`verbose'" ~="" {
		di as txt "The option -fer2- computes and records in the columns of the matrix r(fe_r2mat0):"  ///
			_n "  1. N: The sample size"  ///
			_n "  2. FE_R^2: the proportion of the variation in each of the independent variables"  ///
			_n "     which is explained by the fixed effects alone"  ///
			_n "if the undocumented option -fe_r2j- is specified:"
			_n "  3. R^2j: the proportion of the variation in each of the independent variables"  ///
			_n "     which is explained by all the other variables as well as the fixed effects"  ///
			_n "  4. VIF_w_FE: the Variance Inflation Factor defined as 1/(1 - R^2j), where -R^2j-"  ///
			_n "     is R^2 in column 3."
		matlist `fe_r2mat'
	}

	if "`timeit'"~=""  {
		return local time4fer2 = `time4fer2'
		return local time4fer2byvar = `time4fer2byvar'
	}
	return scalar maxfer2val = `maxfer2'
	return local maxfer2var `maxfer2var'
	return matrix r2mat `fe_r2mat'
	return local df_a = e(df_a)

end	//  End of program getfer2

*	Version 1.1 adds the estat vif column
*	Version 1.2 incorporates factor variables
*	Version 1.3 change the sign on the t-value reported by ttest to correspond with
*		a test that mean(1) - mean(0) == 0
*	Version 1.4 7/11/2012 Name the rows of the return matrices after the underlying factor variables
*	Version 1.5 5/24/2013 Modify to accept a list of variable names > 256 characters
*	Version 1.6 6/12/2013 Add the -addstat- and the -obsgain- options.
*	Version 1.7 6/21/2013 Fix bug in matrix rownames
*	Version 1.8 6/21/2013 Add the groupstats and group options
*	Version 1.9 12/10/2013 Add the line -local varlist = subinstr("`varlist'","i.","ibn.",.)-
*	Version 2.0 6/5/2014 Add the Stata version number
*	Version 2.1 10/8/2015 Require version 11.1 in line 3 to enable factor variables to work
*		but option -obsgain- does not work with i. factor variables.
*		It shows that dropping only one of a set of dummy variables coes not increase sample,
*		because other variables in the set have the same missing observations.
*		Also if `touse' appears in several places without the `in' macro.  Shouldn't they always appear together?
*	Version 2.2 2/10/2016 Tweaks include:
*		Wrap the -frmttable- messages and provide clickable links.
*		Restrict the message "Without the variable `rhsname' nobs is: `e(N)'"
*		to the variables with obsplus > 0.
*		For the -obsgain- option, save some cpu time by replacing -regress- with -_regress-
*		Add the _rmcoll command to strip out collinear variables, so that -group()-option
*		works with factor variables and obsgain works on dummy variables.
*		Add correct row names for expanded factor variables
*		Use matlist command, with noheader option to avoid printing name of temporary matrix
*		and to assure proper rownames on all output.
*		Replace blanks with _'s in line 239 to allow rowname(eqname) to work
*	Version 2.3 4/10/2017  Adds the esample(varname [,replace]) option which causes -bivariate-
*		to return a 0/1 byte variable identifying the onservations used
*		by -bivariate-.  Should equal e(sample) from the regression
*		of the dependent variable on all the rhs variables.
*		Also adds option -rmcoll- without which collinear variables are not removed.
*		Thus, by default, -bivariate- will display results for all values of categorical
*		and dummy variables.  Specifying the -group(groupvar) option automatically
*		invokes option rmcoll.
*	Version 2.4 28Aug2018 Accommodates factor variables with interactions as
*		represented by the character strings "#" or "##". (Lines 71-73,76,77.)
*		Also, in line 273, increase limit on number of characters of the names of the
*		rhs variables from 5*210 characters to 20*210 characters.
*	Version 2.5 30Aug2018 Error trap for a dependent variable with zero variance.
*	Version 2.6 13Apr2019 Change matrix names col1 and cols45 to temporary names
*	Version 2.71 6Mar2020 Add -post- option to post e(b) and e(V) matrices of bivariate correlations
*		Simplify computation of correlation coefficients by regressing standardized
*		versions of the -depvar- and -rhsvar-.  Include rho with and without dummies.
*		Add the -nodummies- option in order to suppress the estimation of the dummy coefficients.
*	Version 2.8 18Apr2020 Add the options:
*		tabstat2(string) Allows user to select which tabstat statistics to compute and display.
*		inspect and inspect2(string) add descriptive statistics from Stata's -inspect- command
*	Version 2.9 17Jun2020 Use "capt tab `rhsvar'" instead of "levelsof `rhsvar'" in line 198
*	Version 3.0 16Jul2020 Add note to appear if any VIF values are missing due to multicollinearity
*		Improve display of results when a factor variable appears on the RHS.
*		Suppress display of unformatted -estat grsumma- results
*	Version 3.1 30Jul2020 Require -varlist- to be numeric and contain at least 2 variables
*		Allow varlist to include -ts- as well as -fv- variables
*		Fix bug preventing the specification of a base value such as ib2.race
*	Version 3.2 2Aug2020 Fix bug in option -rmcoll-, list meaningful, not temporary, names of omitted variables
*	Version 3.3 13Aug2020 Trap and correct the error generated by -discrim lda-
*		when the grouping variable designated in the -group- option is also one
*		of the analysis variables.
*		Add the -absorb-, -adjust(fevars)-, -timeit- and -verbose(#)- options using Sergio Correia's -hdfe-.
*	Version 3.4 15Aug2020 Add the options -demean- and -fer2-.
*		These options require Sergio Correia's -hdfe- and -reghdfe-.
*		Use markout to add e(sample) to contents posted to -estimates return-
*	Version 3.5 20Aug2020 return the -depvar- in line 42.
*		Enable -timeit-option to display execution time in line 661
*		Add the using option to execute -frmttable- for the -bivariate- table
*		and, if they are selected, the -tabstat-, -inspect- or -grouptab- tables.
*	Version 3.6 27Aug2020 Fix bugs in the -using-/-frmttable- option.
*	Version 3.61 28Aug2020 Fix typo in title for correlation, line 647
*	Version 3.7 23Sep2020 Return the -maxfer2val- and -maxfer2var- macros
*		Prefix the listing of the -bivariate- matrix with a first row of title info.
*		Change default formats to %11.5f, to accommodate "Correlation" with 11 characters
*		Fix the option -format- and set its default to %9.3f
*		Fix the -obsgain- option by replacing -if `touse'- by -`if' `in'-.
*		(With -if `touse'-, -obsgain- cannot find additional obaservations.)
*		Fix the option -demean- to invoke -list- and -myfvrevar-
*	Version 3.8 10Nov2020  To fix bug preventing user from choosing -tabstat- stats,
*		replace -tablist- with -tabstat2 in lines 600 & 603 & 607
*	Version 3.9 14Feb2024 Heading of two columns for dummy variables changed
*		from misleading "Means of variables" to "Means of `depvar'"
*	NOTE: Stata 16's undocumented command -varclassify- offers a better way
*		to determine that a variable is categorical.