// 2021.02.02 \\
cap program drop ultimatch
program define ultimatch, rclass
	version 9.0
	syntax [varlist(default=none)] [if] [in], [EXAct(varlist)] [CAliper(real -1.0)] [Draw(integer -1)] [EXP(string)] [Limit(string)] Treated(varname) [REport(varlist))] [UNIt(varlist)] [Between] [Greedy] [SIngle] [SUpport] [UNMatched] [COpy] [Full] [RANk] [EUclid] [Mahalanobis] [RADius]
	tempvar axis tr mark cell nouse base cluster claim lock cnt trcnt ctcnt miss order
	tempname table cell matrix row
	matrix `matrix' = (.)
	return matrix match = `matrix'
	if `caliper' <= 0 {
		local caliper = .
	}
	if `draw' <= 0 {
		local draw = .
	}
	tokenize `"`varlist'"'
	local copy = "`copy'"' != ""
	local unmatched = "`unmatched'" != ""
	local between = "`between'" != ""
	local greedy = "`greedy'" != ""
	local single = "`single'" != ""
	local support = "`support'" != ""
	local rank = "`rank'" != ""
	local euclid = "`euclid'" != ""
	local mahalanobis = "`mahalanobis'" != ""
	local full = "`full'" != ""
	local radius = "`radius'" != ""
	local clustered = 0
	local method = ""
	if `greedy' & `copy' {
		di as error "options greedy and copy are mutually exclusive"
		error 999
	}
	if `euclid' & `mahalanobis' {
		di as error "options euclid and mahalanobis are mutually exclusive"
		error 999
	}
	if `full' & `copy' == 0 {
		di as error "full is a sub-option of copy"
		error 999
	}
	if `unmatched' & "`report'" == "" {
		di as error "unmatched is a sub-option of report"
		error 999
	}
	if `"`1'"' != "" {
		if `"`2'"' != "" {
			local method = "Distance"
		}
		else {
			local method = "Score"
		}
	}
	if "`method'" == "" {
		if `"`exact'"' != "" {
			if  `draw' != . | `caliper' != . | `between' | `greedy' | `support' | `copy' | `rank' | `euclid' | `mahalanobis' | `radius' | `"`limit'"' != "" | `"`exp'"' != "" {
				di as error "coarsened exact mode does not support following options: draw, caliper, between, greedy, support, copy, rank, single, euclid, mahalanobis, radius, limit, exp"
				error 999
			}
			local draw = .
			local caliper = 1
		}
		else {
			di as error "if varlist is empty, exact option has to be specified"
			error 999
		}
	}
	if "`method'" == "Distance" & `between' {
		di as error "distance based matching does not support following options: between"
		error 999
	}
	if "`method'" == "Score" & (`euclid' | `mahalanobis') {
		di as error "score based matching does not support following options: euclid, mahalanobis"
		error 999
	}
	if `radius' & (`between' | `greedy' | `single' | `draw' != .) {
		di as error "radius matching does not support following options: between, greedy, single, draw"
		error 999
	}
	if `radius' & `caliper' == . {
		di as error "radius matching requires the specification of option: caliper"
		error 999
	}
	if "`method'" == "Distance" {
		if `rank' {
			if `mahalanobis' == 0 {
				local euclid = 1
			}
		}
		else {
			if `euclid' == 0 {
				local mahalanobis = 1
			}
		}
	}
	if `full' {
		local copy = 2
	}
	local matching = cond(`copy',"Copying ","")
	local matching = "`matching'" + cond(`support',"Supported ","")
	local matching = "`matching'" + cond(`single',"Single ","")
	local matching = "`matching'" + cond(`greedy',"Greedy ","")
	local matching = "`matching'" + cond(`between',"Sandwiched ","")
	local matching = "`matching'" + cond(`euclid',"Euclidean ","")
	local matching = "`matching'" + cond(`mahalanobis',"Mahalanobis ","")
	local matching = "`matching'" + cond("`method'" != "","`method'-based ", "")
	local matching = "`matching'" + cond(`rank',"Percentile Rank ", "")
	local matching = "`matching'" + cond(`radius',"Radius ", "")
	local matching = "`matching'" + cond("`method'" != "" & `radius' == 0,"Neighborhood ", "")
	local matching = "`matching'" + cond("`method'" == "","Coarsened Exact ", "")
	local matching = "`matching'" + "Matching"
	cap confirm var _match
	if _rc == 0 {
		di as error "_match is already defined"
		error 999
	}
	cap confirm var _weight
	if _rc == 0 {
		di as error "_weight is already defined"
		error 999
	}
	if "`Method'" != "" {
		cap confirm var _distance
		if _rc == 0 {
			di as error "_distance is already defined"
			error 999
		}
		if `greedy' == 0 {
			cap confirm var _copy
			if _rc == 0 {
				di as error "_copy is already defined"
				error 999
			}
		}
	}
	if `support' {
		cap confirm var _support
		if _rc == 0 {
			di as error "_support is already defined"
			error 999
		}
	}
	di as text "`matching'"
	return local matching = "`matching'"
	if "`exp'" != "" {
		local exp = "`exp' "
		local cmd = ""
		local var = ""
		local prev = ""
		local len = length("`exp'")
		forvalue i = 1/`len' {
			local chr = substr("`exp'",`i',1)
			if "`var'" == "" {
				if regexm("`chr'","[a-zA-Z._]") {
					local var = "`chr'"
				}
				else {
					local cmd = "`cmd'`chr'"
				}
			}
			else {
				if regexm("`chr'","[a-zA-Z._0-9]") {
					local var = "`var'`chr'"
				}
				else if "`chr'" == "(" {
					local cmd = "`cmd'`var'`chr'"
					local var = ""
				}
				else {
					if regexm("`var'","t\..+") {
						local var = substr("`var'",3,.)
						cap confirm var `var'
						if _rc == 0 {
							local var = "`var'[t]"
						}
					}
					else {
						cap confirm var `var'
						if _rc == 0 {
							local var = "`var'[c]"
						}
					}
					local cmd = "`cmd'`var'`chr'"
					local var = ""
				}
			}
		}
		local test = subinstr(subinstr(`"`cmd'"',"[c]","[2]",.),"[t]","[1]",.)
		cap local test = `test'
		if _rc != 0 {
			di as error `"invalid expression: `exp'"'
			error 999
		}
	}
	else {
		local cmd = ""
	}
	qui des, varlist
	local names = r(varlist)
	qui gen byte `nouse' = 9
	qui replace `nouse' = 0 `if' `in'
	qui replace `nouse' = 9 if `treated' == .
	if "`exact'" != "" {
		qui egen long `miss' = rmiss(`exact') if `nouse' == 0
		qui replace `nouse' = 9 if `miss' > 0 & `miss' != .
		qui drop `miss'
	}
	if "`method'" != "" {
		qui egen long `miss' = rmiss(`*') if `nouse' == 0
		qui replace `nouse' = 9 if `miss' > 0 & `miss' != .
		qui drop `miss'
		local score = `"`1'"'
	}
	qui gen byte `tr' = (`treated' == 1) if `nouse' == 0
	qui gen long `order' = _n
	if `support' {
		qui sum `score' if `nouse' == 0 & `tr' == 1
		local Ns = r(N)
		local max = r(max)
		local min = r(min)
		qui sum `score' if `nouse' == 0 & `tr' == 0
		local Ns = `Ns'+r(N)
		local max = min(r(max), `max')
		local min = max(r(min), `min')
		qui gen byte _support = `score' <= `max' & `score' >= `min' if `nouse' == 0
		label var _support "common support"
		qui replace `nouse' = 7 if `nouse' == 0 & _support == 0 // non-supported nouse < general nouse
	}
	if "`limit'" != "" | `rank' {
		local vars = ""
		local range = ""
		local i = 1
		local var = word("`limit'", `i')
		while "`var'" != "" {
			cap confirm var `var'
			if _rc != 0 {
				di as error `"invalid limitation variable `var'"'
				error 999
			}
			local j = `j'+1
			local vars = "`vars' `var'"
			local i = `i'+1
			local var = word("`limit'", `i')
			cap confirm number `var'
			if _rc == 0 {
				local ranges = "`ranges' `var'"
				local i = `i'+1
				local var = word("`limit'", `i')
			}
			else {
				local ranges = "`ranges' 5"
			}
		}
		if "`vars'" != "" {
			local vars = trim("`vars'")
			local ranges = trim("`ranges'")
			qui egen long `miss' = rmiss(`vars') if `nouse' == 0
			qui replace `nouse' = 9 if `miss' > 0 & `miss' != .
			qui drop `miss'
		}
		if `rank' {
			local vars = "`vars' `*'"
			local vars = trim("`vars'")
		}
		qui count if `nouse' == 0
		local N = r(N)
		local limit = ""
		local ranks = ""
		local i = 1
		local var = word("`vars'", `i')
		local range = word("`ranges'", `i')
		while `"`var'"' != "" {
			tempvar r`i'
			sort `nouse' `var' `order'
			qui egen double `cnt' = count(1) in 1/`N', by(`nouse' `var')
			qui gen double `r`i'' = (_n - 1 + 0.5 * `cnt')/`N' * 100 in 1/`N' if `var' != `var'[_n-1]
			qui replace `r`i'' = `r`i''[_n-1] in 1/`N' if `r`i'' == .
			qui drop `cnt'
			if "`range'" != "" {
				local limit = `"`limit' & abs(`r`i''[t]-`r`i''[c]) <= `range'"'
			}
			else {
				local ranks = "`ranks' `r`i''"
			}
			local i = `i'+1
			local var = word("`vars'", `i')
			local range = word("`ranges'", `i')
		}
		local limit = substr(trim(`"`limit'"'),3,.)
		local ranks = trim("`ranks'")
	}
	else {
		qui count if `nouse' == 0
		local N = r(N)
		sort `nouse' `order'
	}
	local obs1 = _N
	if "`unit'" != "" {
		if word("`unit'",2) == "" {
			local cluster = "`unit'"
		}
		else {
			qui egen long `cluster' = group(`unit') in 1/`N'
		}
		local clustered = 1
	}
	else {
		qui gen long `cluster' = _n in 1/`N'
	}
	if `"`report'"' != "" & `unmatched' {
		qui gen byte `base' = (`nouse' == 0)
	}
	if `"`exact'"' != "" {
		qui egen long `cell' = group(`exact') in 1/`N'
	}
	else {
		qui gen byte `cell' = 1 in 1/`N'
	}
	if "`method'" == "Distance" {
		if `radius' {
			qui gen long _match = .
			qui gen double _weight = .
			qui gen double _distance = .
			label var _match "match id"
			label var _weight "pweight"
			if `rank' {
				if `mahalanobis' {
					label var _distance "closest mahalanobis rank radius distance"
				}
				else {
					label var _distance "closest euclidean rank radius distance"
				}
				local distvars = "`ranks'"
			}
			else {
				if `mahalanobis' {
					label var _distance "closest mahalanobis radius distance"
				}
				else {
					label var _distance "closest euclidean radius distance"
				}
				local distvars = "`*'"
			}
			qui gen double `axis' = .
			order `nouse' `axis' `cell' `tr' _match _distance _weight `distvars'
			local varcnt = wordcount("`distvars'")
			if `mahalanobis' {
				qui corr `distvars' in 1/`N', covar noformat
				matrix `matrix' = invsym(r(C))
			}
			else {
				matrix `matrix' = diag(J(1,`varcnt',1)) // identity matrix replaces inverted covariance matrix for eucledian distance
			}
			mata: _ultimatchdistanceaxis(`N', 2, 8, "`matrix'")
			sort `nouse' `cell' `axis' `tr' `order'
			mata: _ultimatchradius(`varcnt', "`matrix'", `caliper', `copy')
			local M = r(obs)
			if r(match) == 0 {
				di as error "unable to match"
				drop _match _weight _distance
				error 999
			}
			return scalar comp = r(comp)
			order _match _weight _distance
		}
		else {
			qui gen long `claim' = .
			qui gen byte `lock' = .
			qui gen long _match = .
			qui gen double _weight = .
			qui gen double _distance = .
			label var _match "match id"
			label var _weight "pweight"
			if `rank' {
				if `mahalanobis' {
					label var _distance "nearest mahalanobis rank distance"
				}
				else {
					label var _distance "nearest euclidean rank distance"
				}
				local distvars = "`ranks'"
			}
			else {
				if `mahalanobis' {
					label var _distance "nearest mahalanobis distance"
				}
				else {
					label var _distance "nearest euclidean distance"
				}
				local distvars = "`*'"
			}
			if `draw' == . {
				local draw = 1
			}
			qui gen double `axis' = .
			order `nouse' `axis' `cell' `tr' _match _distance _weight `claim' `lock' `distvars'
			local varcnt = wordcount("`distvars'")
			if `mahalanobis' {
				qui corr `distvars' in 1/`N', covar noformat
				matrix `matrix' = syminv(r(C))
			}
			else {
				matrix `matrix' = diag(J(1,`varcnt',1)) // identity matrix replaces inverted covariance matrix for eucledian distance
			}
			mata: _ultimatchdistanceaxis(`N', 2, 10, "`matrix'")
			sort `nouse' `cell' `axis' `tr' `order'
			mata: _ultimatchdistance(`varcnt', "`matrix'", `caliper', `single', `draw', `greedy', `copy')
			qui drop `claim'
			local M = r(obs)
			if r(match) == 0 {
				di as error "unable to match"
				drop _match _weight _distance
				error 999
			}
			return scalar comp = r(comp)
			order _match _weight _distance
		}
	}
	else if "`method'" == "Score" {
		if `radius' {
			qui gen long _match = .
			qui gen double _weight = .
			qui gen double _distance = .
			label var _match "match id"
			label var _weight "pweight"
			if `rank' {
				label var _distance "closest rank radius distance"
				local distvars = "`ranks'"
			}
			else {
				label var _distance "closest radius distance"
				local distvars = "`score'"
			}
			sort `nouse' `cell' `distvars' `tr'	`order'
			order `nouse' `distvars' `cell' `tr' _match _distance _weight
			mata: _ultimatchradius(1, "", `caliper', `copy')
			local M = r(obs)
			if r(match) == 0 {
				di as error "unable to match"
				drop _match _weight _distance
				error 999
			}
			return scalar comp = r(comp)
			order _match _weight _distance
		}
		else {
			qui gen long `claim' = .
			qui gen long _match = .
			qui gen double _weight = .
			qui gen double _distance = .
			label var _match "match id"
			label var _weight "pweight"
			if `rank' {
				label var _distance "nearest rank distance"
				local distvars = "`ranks'"
			}
			else {
				label var _distance "nearest distance"
				local distvars = "`score'"
			}
			if `draw' == . {
				local draw = 1
			}
			sort `nouse' `cell' `distvars' `tr'	`order'
			order `nouse' `distvars' `cell' `tr' _match _distance _weight `claim'
			mata: _ultimatchneighbor(`caliper', `single', `draw', `between', `greedy', `copy')
			qui drop `claim'
			local M = r(obs)
			if r(match) == 0 {
				di as error "unable to match"
				drop _match _weight _distance
				error 999
			}
			return scalar comp = r(comp)
			order _match _weight _distance
		}
	}
	else {
		sort `nouse' `cell' `order'
		qui egen double `trcnt' = sum(`tr') in 1/`N', by(`cell')
		qui egen double `ctcnt' = sum(1-`tr') in 1/`N', by(`cell')
		qui gen double _weight = `trcnt'/`ctcnt' in 1/`N' if `trcnt' > 0 & `ctcnt' > 0
		label var _weight "pweight"
		qui drop `trcnt' `ctcnt'
		qui replace _weight = 1 in 1/`N' if `tr' == 1 & _weight != .
		qui egen long _match = group(`cell') in 1/`N' if _weight != .
		label var _match "match id"
		local M = `N'
		qui count in 1/`N' if _match != .
		if r(N) == 0 {
			di as error "unable to match"
			drop _match _weight
			error 999
		}
		order _match _weight
	}
	if `copy' {
		qui gen byte _copy = .
		label var _copy "copied observation"
		local obs1 = `obs1'+1
		local obs2 = _N
		if `obs1' <= `obs2' {
			qui replace _copy = 1 in `obs1'/`obs2'
			local clustered = 1
		}
	}
	order `names'
	di as text "{hline 17}{c TT}{hline 32}"
	di as text "{ralign 16:Support} {c |}        Treated         Control"
	di as text "{hline 17}{c +}{hline 32}"
	if `support' {
		qui tab _support `tr' in 1/`Ns', matcell(`cell') matrow(`row')
		if `row'[2,1] == . {
			if `row'[1,1] == 1 {
				matrix `cell' = J(1,2,0) \ `cell'
			}
			else {
				matrix `cell' = `cell' \ J(1,2,0)
			}
		}
		di as text "{ralign 16:Total} {c |} " as result %14.9g `cell'[1,2]+`cell'[2,2] "  "  %14.9g `cell'[1,1]+`cell'[2,1]
		di as text "{ralign 16:Without} {c |} " as result %14.9g `cell'[1,2] "  "  %14.9g `cell'[1,1]
		di as text "{ralign 16:With} {c |} " as result %14.9g `cell'[2,2] "  "  %14.9g `cell'[2,1]
		matrix `matrix' = (`cell'[1,2]+`cell'[2,2],`cell'[1,1]+`cell'[2,1],.,.,.,.)
		matrix `matrix' = `matrix' \ (`cell'[1,2],`cell'[1,1],.,.,.,.)
		matrix `matrix' = `matrix' \ (`cell'[2,2],`cell'[2,1],.,.,.,.)
	}
	else {
		qui count in 1/`M' if `tr' == 1
		di as text "{ralign 16:Total} {c |} " as result %14.9g r(N) "  "  %14.9g `M'-r(N)
		di as text "{ralign 16:Without} {c |} " as result %14.9g 0 "  "  %14.9g 0
		di as text "{ralign 16:With} {c |} " as result %14.9g r(N) "  "  %14.9g `M'-r(N)
		matrix `matrix' = (r(N), `M'-r(N),.,.,.,.)
		matrix `matrix' = `matrix' \ (0,0,.,.,.,.)
		matrix `matrix' = `matrix' \ (r(N), `M'-r(N),.,.,.,.)
	}
	local rownames = "total without with "
	qui replace `nouse' = 1 if _match == 0 | _match == .
	sort `nouse' `tr' `cluster'
	qui count if `nouse' == 0
	local N = r(N)
	if `N' == 0 {
		di as text "{hline 17}{c BT}{hline 32}
		di as error "no observations"
		error 999
	}
	qui count in 1/`N' if `tr' == 0
	local ntr = r(N)
	local tre = `ntr'+1
	if `ntr' == 0 {
		di as text "{hline 17}{c BT}{hline 32}
		di as error "no control observations"
		error 999
	}
	if `tre' > `N' {
		di as text "{hline 17}{c BT}{hline 32}
		di as error "no treated observations"
		error 999
	}
	di as text "{hline 17}{c +}{hline 32}
	matrix `cell' = (`N'-`ntr',`ntr')
	di as text "{ralign 16:Matched} {c |} " as result %14.9g `cell'[1,1] "  "  %14.9g `cell'[1,2]
	matrix `matrix' = `matrix' \ (`cell'[1,1],`cell'[1,2],.,.,.,.)
	local rownames = "`rownames' matched"
	qui gen byte `mark' = 1 in 1/`ntr' if `cluster' == `cluster'[_n-1] | `cluster' == `cluster'[_n+1]
	qui replace `mark' = `cluster' == `cluster'[`ntr'-1] in `ntr'
	qui count in 1/`ntr' if `mark' == 1
	local cluc = r(N)
	qui drop `mark'
	qui gen byte `mark' = 1 in `tre'/`N' if `cluster' == `cluster'[_n-1] | `cluster' == `cluster'[_n+1]
	qui replace `mark' = `cluster' == `cluster'[`N'-1] in `N'
	qui count in `tre'/`N' if `mark' == 1
	local clutr = r(N)
	qui drop `mark'
	di as text "{ralign 16:Clustered} {c |} " as result %14.9g `clutr' "  "  %14.9g `cluc'
	matrix `matrix' = `matrix' \ (`clutr',`cluc',.,.,.,.)
	local rownames = "`rownames' clustered"
	qui count in 1/`ntr' if `cluster' != `cluster'[_n-1]
	local cluc = r(N)
	qui count in `tre'/`N' if `cluster' != `cluster'[_n-1]
	local clutr = r(N)
	if `cluster'[`tre'] == `cluster'[`tre'-1] {
		local clutr = `clutr'+1
	}
	di as text "{ralign 16: Clusters} {c |} " as result %14.9g `clutr' "  "  %14.9g `cluc'
	matrix `matrix' = `matrix' \ (`clutr',`cluc',.,.,.,.)
	local rownames = "`rownames' clusters"
	if "`report'" == "" {
		di as text "{hline 17}{c BT}{hline 32}"
	}
	if "`report'" != "" {
		di as text "{hline 17}{c +}{hline 32}{c TT}{hline 36}"
		if `unmatched' {
			if "`unit'" != "" & `clustered' {
				di as text "{dup 7: }Unmatched {c |}        Treated         Control {c |} CluStdErr        t  p>|t|       SDM"
			}
			else {
				di as text "{dup 7: }Unmatched {c |}        Treated         Control {c |}    StdErr        t  p>|t|       SDM"
			}
			di as text "{hline 17}{c +}{hline 32}{c +}{hline 36}"
			foreach v of varlist `report' {
				if "`unit'" == "" & `clustered' {
					qui reg `v' `tr' if `base' == 1, vce(cluster `cluster')
				}
				else {
					qui reg `v' `tr' if `base' == 1, robust
				}
				matrix `table' = r(table)
				qui sum `v' if `tr' == 1 & `base' == 1
				local m1 = r(mean)
				local s1 = r(sd)
				local n1 = r(N)
				qui sum `v' if `tr' == 0 & `base' == 1
				local m0 = r(mean)
				local s0 = r(sd)
				local n0 = r(N)
				local nx = (`n1'+`n0'-2)
				local sdm = (`m1'-`m0')/ sqrt(((`n1'-1)*`s1'^2 + (`n0'-1)*`s0'^2)/(`nx'))
				if `n1'+`n0' <= 40 { // Hedges'g bias correction
					local sdm = `sdm'*exp(lngamma(`nx'/2))/(sqrt(`nx'/2)*exp(lngamma((`nx'-1)/2)))
				}
				else {
					local sdm = `sdm'*(1-3/(4*(`n1'+`n0')-9))
				}
				local tmean = `table'[1,1]+`table'[1,2]
				local cmean = `table'[1,2]
				local r = `table'[2,1]
				local t = `table'[3,1]
				local p = `table'[4,1]
				local var = substr("`v'",1,16)
				if abs(`sdm') < 10 {
					local sdmf = `""  " %8.5f `sdm'"'
				}
				else {
					local sdmf = `""  " %8.5g `sdm'"'
				}
				di as text "{ralign 16:`var'} {c |} " as result %14.9g round(`tmean',0.000000001) "  "  %14.9g round(`cmean',0.000000001) as text " {c |} " as result %9.6g `r' "  " %7.2f `t' "  " %5.3f `p' `sdmf'
				matrix `matrix' = `matrix' \ (`tmean',`cmean',`r',`t',`p',`sdm')
				local rownames = "`rownames' u_`v'"
			}
			di as text "{hline 17}{c +}{hline 32}{c +}{hline 36}"
		}
		if `clustered' {
			di as text "{dup 9: }Matched {c |}        Treated         Control {c |} CluStdErr        t  p>|t|       SDM"
		}
		else {
			di as text "{dup 9: }Matched {c |}        Treated         Control {c |}    StdErr        t  p>|t|       SDM"
		}
		di as text "{hline 17}{c +}{hline 32}{c +}{hline 36}"
		foreach v of varlist `report' {
			if `clustered' {
				qui reg `v' `tr' [pweight=_weight] in 1/`N', vce(cluster `cluster')
			}
			else {
				qui reg `v' `tr' [pweight=_weight] in 1/`N', robust
			}
			matrix `table' = r(table)
			qui sum `v' [aweight=_weight] in `tre'/`N'
			local m1 = r(mean)
			local s1 = r(sd)
			local n1 = r(sum_w)
			qui sum `v' [aweight=_weight] in 1/`ntr'
			local m0 = r(mean)
			local s0 = r(sd)
			local n0 = r(sum_w)
			local nx = (`n1'+`n0'-2)
			local sdm = (`m1'-`m0')/ sqrt(((`n1'-1)*`s1'^2 + (`n0'-1)*`s0'^2)/(`nx'))
			if `n1'+`n0' <= 40 {  // Hedges'g bias correction
				local sdm = `sdm'*exp(lngamma(`nx'/2))/(sqrt(`nx'/2)*exp(lngamma((`nx'-1)/2)))
			}
			else {
				local sdm = `sdm'*(1-3/(4*(`n1'+`n0')-9))
			}
			local tmean = `table'[1,1]+`table'[1,2]
			local cmean = `table'[1,2]
			local r = `table'[2,1]
			local t = `table'[3,1]
			local p = `table'[4,1]
			local var = substr("`v'",1,16)
			if abs(`sdm') < 10 {
				local sdmf = `""  " %8.5f `sdm'"'
			}
			else {
				local sdmf = `""  " %8.5g `sdm'"'
			}
			di as text "{ralign 16:`var'} {c |} " as result %14.9g round(`tmean',0.000000001) "  "  %14.9g round(`cmean',0.000000001) as text " {c |} " as result %9.6g `r' "  " %7.2f `t' "  " %5.3f `p' `sdmf'
			matrix `matrix' = `matrix' \ (`tmean',`cmean',`r',`t',`p',`sdm')
			local rownames = "`rownames' m_`v'"
		}
		di as text "{hline 17}{c BT}{hline 32}{c BT}{hline 36}"
	}
	matrix rownames `matrix' = `rownames'
	if "`report'" == "" {
		matrix `matrix' = `matrix'[.,1..2]
		matrix colnames `matrix' = treated control
	}
	else {
		matrix colnames `matrix' = treated control stderr t p sdm
	}
	return matrix match = `matrix'
end

mata:
void _ultimatchneighbor(real scalar caliper, real scalar single, real scalar draw, real scalar between, real scalar greedy, real scalar copy)
{	real matrix D, neighbor, nb, miss
	real scalar hood, top, bot, tgo, bgo, tdif, bdif, tprev, bprev, tcnt, bcnt, cnt, rows
	real scalar i, j, w, reset, claim
	real scalar match, obs, uselimit, usecmd
	string scalar limit, cmd, explimit, expcmd, exp, str
	real scalar comp

	obs = st_nobs()
	for (i=1; i <= obs; i++)
	{	if (_st_data(i,1) != 0) // nouse
		{	break
		}
	}
	obs = i-1
	if (obs <= 0)
	{	st_numscalar("r(obs)", 0)
		st_numscalar("r(match)", 0)
		return
	}
	st_view(D=.,(1,obs),(2..8)) // score:1, cell:2, treated:3, match:4, distance:5, weight:6, claim:7
	limit = st_local("limit")
	cmd = st_local("cmd")
	uselimit = 0
	usecmd = 0
	if (limit != "")
	{	limit = "local limitok = "+limit
		uselimit = 1
	}
	if (cmd != "")
	{	cmd = "local cmdok = "+cmd
		usecmd = 1
	}
	if (greedy)
	{	copy = 0
	}
	comp = 0
	miss = J(1,4,.)
	neighbor = J(obs,3,0)
	match = 0
	i = 0
	while (1)
	{	i++
		if (i > obs)
		{	break
		}
		if (D[i,3] == 0)
		{	continue
		}
		if (D[i,4] != .)
		{	match = D[i,4]
			if (D[i,6] != .)
			{	continue
			}
		}
		else
		{	match++
		}
		if (uselimit)
		{	explimit = subinstr(limit,"[t]","["+strofreal(i)+"]")
		}
		if (usecmd)
		{	expcmd = subinstr(cmd,"[t]","["+strofreal(i)+"]")
		}
		top = i
		bot = i
		tgo = 1
		bgo = 1
		tcnt = 0
		bcnt = 0
		tprev = .
		bprev = .
		hood = 0
		while (1)
		{	while (tgo & top != .)
			{	top--
				if (top < 1)
				{	top = .
					break
				}
				if (D[i,2] != D[top,2])
				{	top = .
					break
				}
				if (D[top,3] == 1)
				{	continue
				}
				if (greedy & D[top,4] == match)
				{	tdif = D[top,5]
					D[top,4..7] = miss
					comp++
					break
				}
				tdif = D[i,1]-D[top,1]
				if (tdif > caliper)
				{	top = .
					break
				}
				comp++
				if (greedy & tdif >= D[top,5])
				{	continue
				}
				if (uselimit | usecmd)
				{	str = strofreal(top)
					if (uselimit)
					{	exp = subinstr(explimit,"[c]","["+str+"]")
						stata(exp,1,1)
						if (st_local("limitok") != "1")
						{	continue
						}
					}
					if (usecmd)
					{	exp = subinstr(expcmd,"[c]","["+str+"]")
						stata(exp,1,1)
						if (st_local("cmdok") != "1")
						{	continue
						}
					}
				}
				break
			}
			while (bgo & bot != .)
			{	bot++
				if (bot > obs)
				{	bot = .
					break
				}
				if (D[i,2] != D[bot,2])
				{	bot = .
					break
				}
				if (D[bot,3] == 1)
				{	continue
				}
				if (greedy & D[bot,4] == match)
				{	bdif = D[bot,5]
					D[bot,4..7] = miss
					comp++
					break
				}
				bdif = D[bot,1]-D[i,1]
				if (bdif > caliper)
				{	bot = .
					break
				}
				comp++
				if (greedy & bdif >= D[bot,5])
				{	continue
				}
				if (uselimit | usecmd)
				{	str = strofreal(bot)
					if (uselimit)
					{	exp = subinstr(explimit,"[c]","["+str+"]")
						stata(exp,1,1)
						if (st_local("limitok") != "1")
						{	continue
						}
					}
					if (usecmd)
					{	exp = subinstr(expcmd,"[c]","["+str+"]")
						stata(exp,1,1)
						if (st_local("cmdok") != "1")
						{	continue
						}
					}
				}
				break
			}
			bgo = 0
			tgo = 0
			if (top != . & (between | bot == . | tdif <= bdif))
			{	tgo = 1
				if (tprev != tdif)
				{	tcnt++
					if (between)
					{	if (tcnt > draw)
						{	top = .
						}
					}
					else
					{	if (tcnt+bcnt > draw)
						{	top = .
							bot = .
						}
					}
				}
				if (top != .)
				{	tprev = tdif
					hood++
					neighbor[hood,1] = top
					neighbor[hood,2] = tdif
					neighbor[hood,3] = 0
				}
			}
			if (bot != . & (between | top == . | bdif < tdif))
			{	bgo = 1
				if (bprev != bdif)
				{	bcnt++
					if (between)
					{	if (bcnt > draw)
						{	bot = .
						}
					}
					else
					{	if (tcnt+bcnt > draw)
						{	top = .
							bot = .
						}
					}
				}
				if (bot != .)
				{	bprev = bdif
					hood++
					neighbor[hood,1] = bot
					neighbor[hood,2] = bdif
					neighbor[hood,3] = 1
				}
			}
			if (bot == . & top == .)
			{	break
			}
		}
		if (hood == 0)
		{	D[i,4..7] = miss
			match--
			continue
		}
		if (single)
		{	nb = _ultimatchsingle(neighbor[1..hood,.],between,draw)
			hood = rows(nb)
		}
		else
		{	nb = neighbor[1..hood,.]
		}
		w = 1/hood
		D[i,4] = match
		D[i,5] = 0
		D[i,6] = 1
		if (copy == 1)
		{	for (j = 1; j <= hood; j++)
			{	pos = nb[j,1]
				dif = nb[j,2]
				if (D[pos,4] == .)
				{	D[pos,4] = match
					D[pos,5] = dif
					D[pos,6] = w
				}
				else
				{	_ultimatchcopy(pos)
					_st_store(st_nobs(), 5, match)
					_st_store(st_nobs(), 6, dif)
					_st_store(st_nobs(), 7, w)
				}
			}
		}
		else if (copy == 2)
		{	D[i,6] = w
			for (j = 1; j <= hood; j++)
			{	pos = nb[j,1]
				dif = nb[j,2]
				if (j > 1)
				{	match++
					_ultimatchcopy(i)
					_st_store(st_nobs(), 5, match)
				}
				if (D[pos,4] == .)
				{	D[pos,4] = match
					D[pos,5] = dif
					D[pos,6] = w
				}
				else
				{	_ultimatchcopy(pos)
					_st_store(st_nobs(), 5, match)
					_st_store(st_nobs(), 6, dif)
					_st_store(st_nobs(), 7, w)
				}
			}
		}
		else if (greedy)
		{	reset = i
			for (j = 1; j <= hood; j++)
			{	pos = nb[j,1]
				dif = nb[j,2]
				claim = D[pos,7]
				if (claim != .)
				{	if (claim < reset)
					{	reset = claim
					}
					D[claim,6] = .
				}
				D[pos,4] = match
				D[pos,5] = dif
				D[pos,6] = w
				D[pos,7] = i
			}
			if (reset < i)
			{	i = reset-1
			}
		}
		else
		{	for (j = 1; j <= hood; j++)
			{	pos = nb[j,1]
				dif = nb[j,2]
				if (dif < D[pos,5])
				{	D[pos,4] = match
					D[pos,5] = dif
				}
				if (D[pos,6] == .)
				{	D[pos,6] = w
				}
				else
				{	D[pos,6] = D[pos,6] + w
				}
			}
		}
	}
	st_numscalar("r(obs)", obs)
	st_numscalar("r(match)", match)
	st_numscalar("r(comp)", comp)
	return
}

void _ultimatchradius(real scalar varcnt, string scalar covmat, real scalar caliper, real scalar copy)
{	real matrix D, M, C, neighbor, difvec
	real scalar hood, top, bot, dif, dist, distance
	real scalar i, j, w
	real scalar match, obs, uselimit, usecmd
	string scalar limit, cmd, explimit, expcmd, exp, str
	real scalar comp

	obs = st_nobs()
	for (i=1; i <= obs; i++)
	{	if (_st_data(i,1) != 0) // nouse
		{	break
		}
	}
	obs = i-1
	if (obs <= 0)
	{	st_numscalar("r(obs)", 0)
		st_numscalar("r(match)", 0)
		return
	}
	st_view(D=.,(1,obs),(2..7)) // score:1, cell:2, treated:3, match:4, distance:5, weight:6
	if (varcnt > 1)
	{	st_view(M=.,(1,obs),(8..8+varcnt-1)) // distance variables
		C = st_matrix(covmat)
		distance = 1
	}
	else
	{	distance = 0
	}
	limit = st_local("limit")
	cmd = st_local("cmd")
	uselimit = 0
	usecmd = 0
	if (limit != "")
	{	limit = "local limitok = "+limit
		uselimit = 1
	}
	if (cmd != "")
	{	cmd = "local cmdok = "+cmd
		usecmd = 1
	}
	comp = 0
	neighbor = J(obs,2,.)
	match = 0
	i = 0
	while (1)
	{	i++
		if (i > obs)
		{	break
		}
		if (D[i,3] == 0)
		{	continue
		}
		if (uselimit)
		{	explimit = subinstr(limit,"[t]","["+strofreal(i)+"]")
		}
		if (usecmd)
		{	expcmd = subinstr(cmd,"[t]","["+strofreal(i)+"]")
		}
		match++
		top = i
		bot = i
		hood = 0
		while (1)
		{	top--
			if (top < 1)
			{	break
			}
			if (D[i,2] != D[top,2])
			{	break
			}
			dif = D[i,1]-D[top,1]
			if (dif > caliper)
			{	break
			}
			if (D[top,3] == 1)
			{	continue
			}
			comp++
			if (uselimit | usecmd)
			{	str = strofreal(top)
				if (uselimit)
				{	exp = subinstr(explimit,"[c]","["+str+"]")
					stata(exp,1,1)
					if (st_local("limitok") != "1")
					{	continue
					}
				}
				if (usecmd)
				{	exp = subinstr(expcmd,"[c]","["+str+"]")
					stata(exp,1,1)
					if (st_local("cmdok") != "1")
					{	continue
					}
				}
			}
			if (distance)
			{	difvec = M[i,.] :- M[top,.]
				difvec = difvec * C * difvec'
				dist = sqrt(difvec[1,1])
				if (dist <= caliper)
				{	hood++
					neighbor[hood,1] = top
					neighbor[hood,2] = dist
				}
			}
			else
			{	hood++
				neighbor[hood,1] = top
				neighbor[hood,2] = dif
			}
		}
		while (1)
		{	bot++
			if (bot > obs)
			{	break
			}
			if (D[i,2] != D[bot,2])
			{	break
			}
			dif = D[bot,1]-D[i,1]
			if (dif > caliper)
			{	break
			}
			if (D[bot,3] == 1)
			{	continue
			}
			comp++
			if (uselimit | usecmd)
			{	str = strofreal(bot)
				if (uselimit)
				{	exp = subinstr(explimit,"[c]","["+str+"]")
					stata(exp,1,1)
					if (st_local("limitok") != "1")
					{	continue
					}
				}
				if (usecmd)
				{	exp = subinstr(expcmd,"[c]","["+str+"]")
					stata(exp,1,1)
					if (st_local("cmdok") != "1")
					{	continue
					}
				}
			}
			if (distance)
			{	difvec = M[i,.] :- M[bot,.]
				difvec = difvec * C * difvec'
				dist = sqrt(difvec[1,1])
				if (dist <= caliper)
				{	hood++
					neighbor[hood,1] = bot
					neighbor[hood,2] = dist
				}
			}
			else
			{	hood++
				neighbor[hood,1] = bot
				neighbor[hood,2] = dif
			}
		}
		if (hood == 0)
		{	match--
			continue
		}
		w = 1/hood
		D[i,4] = match
		D[i,5] = 0
		D[i,6] = 1
		if (copy == 1)
		{	for (j = 1; j <= hood; j++)
			{	pos = neighbor[j,1]
				dif = neighbor[j,2]
				if (D[pos,4] == .)
				{	D[pos,4] = match
					D[pos,5] = dif
					D[pos,6] = w
				}
				else
				{	_ultimatchcopy(pos)
					_st_store(st_nobs(), 5, match)
					_st_store(st_nobs(), 6, dif)
					_st_store(st_nobs(), 7, w)
				}
			}
		}
		else if (copy == 2)
		{	D[i,6] = w
			for (j = 1; j <= hood; j++)
			{	pos = neighbor[j,1]
				dif = neighbor[j,2]
				if (j > 1)
				{	match++
					_ultimatchcopy(i)
					_st_store(st_nobs(), 5, match)
				}
				if (D[pos,4] == .)
				{	D[pos,4] = match
					D[pos,5] = dif
					D[pos,6] = w
				}
				else
				{	_ultimatchcopy(pos)
					_st_store(st_nobs(), 5, match)
					_st_store(st_nobs(), 6, dif)
					_st_store(st_nobs(), 7, w)
				}
			}
		}
		else
		{	for (j = 1; j <= hood; j++)
			{	pos = neighbor[j,1]
				dif = neighbor[j,2]
				if (dif < D[pos,5])
				{	D[pos,4] = match
					D[pos,5] = dif
				}
				if (D[pos,6] == .)
				{	D[pos,6] = w
				}
				else
				{	D[pos,6] = D[pos,6] + w
				}
			}
		}
	}
	st_numscalar("r(obs)", obs)
	st_numscalar("r(match)", match)
	st_numscalar("r(comp)", comp)
	return
}

void _ultimatchdistance(real scalar varcnt, string scalar covmat, real scalar caliper, real scalar single, real scalar draw, real scalar greedy, real scalar copy)
{	real matrix D, M, C, difvec, miss, neighbor, nb
	real scalar hood, top, bot, dist, nearest, pos, dif, w, reset
	real scalar i, j, match, obs, uselimit, usecmd
	real scalar free, count
	string scalar limit, cmd, explimit, expcmd, exp, str
	real scalar comp

	obs = st_nobs()
	for (i=1; i <= obs; i++)
	{	if (_st_data(i,1) != 0) // nouse
		{	break
		}
	}
	obs = i-1
	if (obs <= 0)
	{	st_numscalar("r(obs)", 0)
		st_numscalar("r(match)", 0)
		return
	}
	st_view(D=.,(1,obs),(2..9)) // score:1, cell:2, treated:3, match:4, distance:5, weight:6, claim:7, lock:8
	st_view(M=.,(1,obs),(10..10+varcnt-1)) // distance variables
	C = st_matrix(covmat)
	limit = st_local("limit")
	cmd = st_local("cmd")
	uselimit = 0
	usecmd = 0
	if (limit != "")
	{	limit = "local limitok = "+limit
		uselimit = 1
	}
	if (cmd != "")
	{	cmd = "local cmdok = "+cmd
		usecmd = 1
	}
	if (greedy)
	{	copy = 0
	}
	comp = 0
	miss = J(1,4,.)
	neighbor = J(obs,2,0)
	match = 0
	i = 0
	while (1)
	{	i++
		if (i > obs)
		{	break
		}
		if (D[i,3] == 0)
		{	continue
		}
		if (D[i,4] != .)
		{	match = D[i,4]
			if (D[i,6] != .)
			{	continue
			}
		}
		else
		{	match++
		}
		if (uselimit)
		{	explimit = subinstr(limit,"[t]","["+strofreal(i)+"]")
		}
		if (usecmd)
		{	expcmd = subinstr(cmd,"[t]","["+strofreal(i)+"]")
		}
		top = i
		bot = i
		nearest = .
		hood = 0
		free = 1
		count = 0
		while (1)
		{	while (top != .)
			{	top--
				if (top < 1)
				{	top = .
					break
				}
				if (D[i,2] != D[top,2])
				{	top = .
					break
				}
				if (D[i,1]-D[top,1] > nearest)
				{	top = .
					break
				}
				if (D[top,8] == 1)
				{	break
				}
				if (D[top,3] == 1)
				{	break
				}
				comp++
				if (uselimit | usecmd)
				{	str = strofreal(top)
					if (uselimit)
					{	exp = subinstr(explimit,"[c]","["+str+"]")
						stata(exp,1,1)
						if (st_local("limitok") != "1")
						{	break
						}
					}
					if (usecmd)
					{	exp = subinstr(expcmd,"[c]","["+str+"]")
						stata(exp,1,1)
						if (st_local("cmdok") != "1")
						{	break
						}
					}
				}
				if (greedy & D[top,4] == match)
				{	dist = D[top,5]
					D[top,4..7] = miss
				}
				else
				{	difvec = M[i,.] :- M[top,.]
					difvec = difvec * C * difvec'
					dist = sqrt(difvec[1,1])
					if (greedy & dist >= D[top,5])
					{	break
					}
				}
				if (dist < nearest)
				{	hood = free
					neighbor[hood,1] = top
					neighbor[hood,2] = dist
					nearest = dist
				}
				else if (dist == nearest)
				{	hood++
					neighbor[hood,1] = top
					neighbor[hood,2] = dist
				}
				break
			}
			while (bot != .)
			{	bot++
				if (bot > obs)
				{	bot = .
					break
				}
				if (D[i,2] != D[bot,2])
				{	bot = .
					break
				}
				if (D[bot,1]-D[i,1] > nearest)
				{	bot = .
					break
				}
				if (D[bot,8] == 1)
				{	break
				}
				if (D[bot,3] == 1)
				{	break
				}
				comp++
				if (uselimit | usecmd)
				{	str = strofreal(bot)
					if (uselimit)
					{	exp = subinstr(explimit,"[c]","["+str+"]")
						stata(exp,1,1)
						if (st_local("limitok") != "1")
						{	break
						}
					}
					if (usecmd)
					{	exp = subinstr(expcmd,"[c]","["+str+"]")
						stata(exp,1,1)
						if (st_local("cmdok") != "1")
						{	break
						}
					}
				}
				if (greedy & D[bot,4] == match)
				{	dist = D[bot,5]
					D[bot,4..7] = miss
				}
				else
				{	difvec = M[i,.] :- M[bot,.]
					difvec = difvec * C * difvec'
					dist = sqrt(difvec[1,1])
					if (greedy & dist >= D[bot,5])
					{	break
					}
				}
				if (dist < nearest)
				{	hood = free
					neighbor[hood,1] = bot
					neighbor[hood,2] = dist
					nearest = dist
				}
				else if (dist == nearest)
				{	hood++
					neighbor[hood,1] = bot
					neighbor[hood,2] = dist
				}
				break
			}
			if (top != . | bot != .)
			{	continue
			}
			if (nearest > caliper)
			{	hood = free-1
			}
			if (hood >= free)
			{	count++
				if (count < draw)
				{	for (j = free; j <= hood; j++)
					{	D[neighbor[j,1],8] = 1
					}
					free = hood+1
					top = i
					bot = i
					nearest = .
					continue
				}
			}
			for (j = 1; j < free; j++)
			{	D[neighbor[j,1],8] = 0
			}
			if (hood == 0)
			{	D[i,4..7] = miss
				match--
				break
			}
			if (single)
			{	nb = sort((neighbor[1..hood,.],runiform(hood,1)),(2,3))
				if (hood > draw)
				{	hood = draw
				}
			}
			else
			{	nb = neighbor[1..hood,1..2]
			}
			w = 1/hood
			D[i,4] = match
			D[i,5] = 0
			D[i,6] = 1
			if (copy == 1)
			{	for (j = 1; j <= hood; j++)
				{	pos = nb[j,1]
					dif = nb[j,2]
					if (D[pos,4] == .)
					{	D[pos,4] = match
						D[pos,5] = dif
						D[pos,6] = w
					}
					else
					{	_ultimatchcopy(pos)
						_st_store(st_nobs(), 5, match)
						_st_store(st_nobs(), 6, dif)
						_st_store(st_nobs(), 7, w)
					}
				}
			}
			else if (copy == 2)
			{	D[i,6] = w
				for (j = 1; j <= hood; j++)
				{	pos = nb[j,1]
					dif = nb[j,2]
					if (j > 1)
					{	match++
						_ultimatchcopy(i)
						_st_store(st_nobs(), 5, match)
					}
					if (D[pos,4] == .)
					{	D[pos,4] = match
						D[pos,5] = dif
						D[pos,6] = w
					}
					else
					{	_ultimatchcopy(pos)
						_st_store(st_nobs(), 5, match)
						_st_store(st_nobs(), 6, dif)
						_st_store(st_nobs(), 7, w)
					}
				}
			}
			else if (greedy)
			{	reset = i
				for (j = 1; j <= hood; j++)
				{	pos = nb[j,1]
					dif = nb[j,2]
					claim = D[pos,7]
					if (claim != .)
					{	if (claim < reset)
						{	reset = claim
						}
						D[claim,6] = .
					}
					D[pos,4] = match
					D[pos,5] = dif
					D[pos,6] = w
					D[pos,7] = i
				}
				if (reset < i)
				{	i = reset-1
				}
			}
			else
			{	for (j = 1; j <= hood; j++)
				{	pos = nb[j,1]
					dif = nb[j,2]
					if (dif < D[pos,5])
					{	D[pos,4] = match
						D[pos,5] = dif
					}
					if (D[pos,6] == .)
					{	D[pos,6] = w
					}
					else
					{	D[pos,6] = D[pos,6] + w
					}
				}
			}
			break
		}
	}
	st_numscalar("r(obs)", obs)
	st_numscalar("r(match)", match)
	st_numscalar("r(comp)", comp)
	return
}

void _ultimatchcopy(real scalar from)
{	real scalar i, to
	st_addobs(1)
	to = st_nobs()
	for (i = 1; i <= st_nvar(); i++)
	{	if (st_isstrvar(i))
		{	_st_sstore(to, i, _st_sdata(from, i))
		}
		else
		{	_st_store(to, i, _st_data(from, i))
		}
	}
}

void _ultimatchdistanceaxis(real scalar obs, real scalar axispos,  real scalar varpos, string scalar covmat)
{	real matrix S, M, dif
	real matrix p75, p50, p25, s
	real scalar i, varcnt

	cov = st_matrix(covmat)
	st_view(S=.,(1,obs),(axispos))
	st_view(M=.,(1,obs),(varpos..varpos+cols(cov)-1)) // distance variables

	p75 = J(1,cols(M),.)
	p50 = J(1,cols(M),.)
	p25 = J(1,cols(M),.)
	for (i = 1; i <= cols(M); i++)
	{	s = sort(M[.,i],1)
		p75[1,i] = s[ceil(rows(s)*0.75),1]
		p50[1,i] = s[ceil(rows(s)*0.50),1]
		p25[1,i] = s[ceil(rows(s)*0.25),1]
	}
	base = p50+(p25-p75)
	for (i = 1; i <= obs; i++)
	{	dif = base :- M[i, .]
		dif = dif * cov * dif'
		S[i,1] = sqrt(dif[1,1])
	}
}


real matrix _ultimatchsingle(real matrix neighbor, real scalar between, real scalar draw)
{	real matrix top, bot
	real scalar i
	if (between)
	{	neighbor = sort((neighbor,runiform(rows(neighbor),1)),(3,2,4))
		top = select(neighbor,neighbor[.,3]:<1)
		if (rows(top) == 0 | rows(top) == rows(neighbor))
		{	return(neighbor[1..min((rows(neighbor),draw)),.])
		}
		bot = neighbor[(rows(top)+1)..rows(neighbor),.]
		top = top[1..min((rows(top),draw)),.]
		bot = bot[1..min((rows(bot),draw)),.]
		return(top\bot)
	}
	neighbor = sort((neighbor,runiform(rows(neighbor),1)),(2,4))
	return(neighbor[1..min((rows(neighbor),draw)),.])
}

end