*! asignadip v1.0 JavierMarquez 22dic2009
program define asignadip, rclass byable(recall) sortpreserve
	version 10.0
	syntax varlist(numeric min=2) [if] [in]				///
		[, NULOynoreg(varlist numeric max=2)			///
		THReshold(real .02) MAXSeats(integer 300) 		///
		MAXOVERrep(real .08) NUMmay(numlist integer) 	///
		ESCrp(integer 200) MAXIter(integer 20) noMAY 	///
		noRP noPRInt]
	marksample touse
	checkinput `0'
	if ("`may'" == "nomay") {
		local maxseats NA
		local maxoverrep NA
		local j = 0
		foreach var of local varlist {
			tempname ssd_`++j'
			scalar `ssd_`j'' = 0
		}
	}
	else {
		if "`nummay'" == "" {
			_asignamay `varlist' `if' `in'
			local j = 0
			foreach var of local varlist {
				tempname ssd_`++j'
				scalar `ssd_`j'' = r(ssd_`j')
			}
		}
		else {
			local j = 0
			foreach var of local varlist {
				local tempo : word `++j' of `nummay'
				tempname ssd_`j'
				scalar `ssd_`j'' = `tempo'
			}
		}
	}
	tempname _sizemay
	scalar `_sizemay' = 0
	local j = 0
	foreach var of local varlist {
		scalar `_sizemay' = `_sizemay' + `ssd_`++j''
	}
 	local j = 0
 	foreach var of local varlist {
		tempname vte_`++j' list_`j'
	}
	local j = 0
	foreach var of local varlist {
		quietly sum `var' if `touse'
		scalar `vte_`++j'' = r(mean)
	}
	if ("`rp'" == "norp") {
		local maxseats NA
		local maxoverrep NA
		local threshold NA
		local j = 0
		foreach var of local varlist {
			scalar `list_`++j'' = 0
		}
	}
	else {
		tempname vne
		scalar `vne' = 0
		local j = 0
		foreach var of local varlist {
			if `vte_`++j'' >= `threshold' {
				scalar `vne' = `vne' + `vte_`j''
			}
		}
		foreach var of local varlist {
			local exc_list `exc_list' 0
		}
		_hiremainder `varlist' `if' `in', vne(`=`vne'')	///
			seats(`escrp') thr(`threshold')				///
			exc(`exc_list')
		local j = 0
		foreach var of local varlist {
			scalar `list_`++j'' = r(list_`j')
		}
	}
	local iter = 0
	if ("`rp'" != "norp") & ("`may'" != "nomay") {
		local j = 0
		foreach var of local varlist {
			local MaxSeats_`++j' NO
			local MaxOverr_`j' NO
		}
		local j = 0
		local mylist1
		local mylist2
		foreach var of local varlist {
			local mylist1 `mylist1' `=`ssd_`++j'''
			local mylist2 `mylist2' `=`list_`j'''
		}
		_checkclauses `varlist' `if' `in',				///
		_sizemay(`=`_sizemay'') escrp(`escrp')			///
			ssd(`mylist1') list(`mylist2') 				///
			vne(`=`vne'')								///
			maxseats(`maxseats') 						///
			maxoverrep(`maxoverrep')
		tempname vnefec newescrp
		while "`r(clauses)'" == "YES" {
			local iter = `iter' + 1
			if `iter' >= `maxiter' {
				di as error "asignadip did not achieve " _c
				di as error "convergence because of " _c
				di as error "maxseats() and/or maxoverrep()"
				di as error "Max. number of iterations: `maxiter'"
				error 430
			}
			local j = 0
			foreach var of local varlist {
				if `=`r(excMaxSeats_`++j')'' > 0 {
					local MaxSeats_`j' YES
				}
				if `=`r(excMaxOverr_`j')'' > 0 {
					local MaxOverr_`j' YES
				}
			}
			scalar `vnefec' = 0
			scalar `newescrp' = `escrp'
			local exc_list
			local j = 0
			foreach var of local varlist {
				scalar `list_`++j'' = 					///
					`list_`j'' - r(exc_`j')
				local exc_list  `exc_list' 				///
					`=`r(exc_`j')''
				if `vte_`j'' >= `threshold' & 			///
				`=`r(exc_`j')'' == 0 {
					scalar `vnefec' = `vnefec' + 		///
						`vte_`j''
				}
				if `=`r(exc_`j')'' > 0 {
					scalar `newescrp' =					///
						`newescrp' - `list_`j''
				}
			}
			_hiremainder `varlist' `if' `in' ,			///
				vne(`=`vnefec'') seats(`=`newescrp'') 	///
				thr(`threshold') exc(`exc_list')
			local j = 0
			foreach var of local varlist {
				if "`=r(list_`++j')'" != "." {
					scalar `list_`j'' = 				///
						r(list_`j')
				}
			}
			local j = 0
			local mylist1
			local mylist2
			foreach var of local varlist {
				local mylist1 `mylist1' `=`ssd_`++j'''
				local mylist2 `mylist2' `=`list_`j'''
			}
			_checkclauses `varlist' `if' `in',			///
				_sizemay(`=`_sizemay'') escrp(`escrp')	///
				ssd(`mylist1') list(`mylist2') 			///
				vne(`=`vne'')							///
				maxseats(`maxseats') 					///
				maxoverrep(`maxoverrep')
			local j = 0
			foreach var of local varlist {
				if `=`r(excMaxSeats_`++j')'' > 0 {
					local MaxSeats_`j' YES
				}
				if `=`r(excMaxOverr_`j')'' > 0 {
					local MaxOverr_`j' YES
				}
			}
		}
	}
	tempname _sizerp
	scalar `_sizerp' = 0
	local j = 0
	foreach var of local varlist {
		scalar `_sizerp' = `_sizerp' + `list_`++j''
	}
	local j = 0
	foreach var of local varlist {
		local ssd `ssd' `=`ssd_`++j'''
		return scalar ssd_`j' = `ssd_`j''
		return scalar list_`j' = `list_`j''
		return local MaxSeats_`j' `MaxSeats_`j''
		return local MaxOverr_`j' `MaxOverr_`j''
	}
	return local ssd `ssd'
	local j = 0
	foreach var of local varlist {
		tempname tot_`++j'
		scalar `tot_`j'' = `ssd_`j'' + `list_`j''
	}
	tempname chamber_size
	scalar `chamber_size' = `_sizemay' + `_sizerp'
	if ("`print'" != "noprint") {
		.tableasignadip = ._tab.new
		.tableasignadip.reset, columns(8) lmargin(0)
		.tableasignadip.width 		12| 	. 	. 	. 	. 		. 		. 	.
		.tableasignadip.titlefmt 	%12s 	. 	. 	. 	. 		. 		. 	.
		.tableasignadip.strfmt 		%12s 	. 	. 	. 	. 		. 		.	.
		.tableasignadip.numfmt		. 		. 	. 	. 	%10.2f	%10.2f	. 	.
		.tableasignadip.pad 		. 		. 	. 	. 	. 		. 		. 	.
		.tableasignadip.titlecolor 	. 		. 	. 	. 	. 		. 		. 	.
		.tableasignadip.strcolor 	.	 	. 	. 	. 	. 		. 		. 	.
		.tableasignadip.numcolor 	. 		. 	. 	. 	. 		. 		. 	.
		local w = `.tableasignadip.width_of_table'
		local lengthmaxoverrep : length local maxoverrep
		local w = `w'-32-`lengthmaxoverrep'
		di
		di as text "Single-Member Seats{col 26}=" 		as result %8.0g `_sizemay'
		di as text "List Seats{col 26}=" 			as result %8.0g `_sizerp'
		di as text "Chamber Size{col 26}=" 			as result %8.0g `chamber_size'
		di as text "Threshold{col 26}="				as result %8s "`threshold'"
		di as text "Max. number of seats{col 26}="		as result %8s "`maxseats'"
		di as text "Max. overrepresentation{col 26}="		as result %8s "`maxoverrep'" _c
		di as text "{ralign `w':Number of iterations = {result}`iter'}"
		di
		.tableasignadip.sep, top
		.tableasignadip.titles "Party " "SSD seats" "List seats" "Total" "%Votes" "%Seats" "MaxSeats" "MaxOverrep"
		.tableasignadip.sep, middle
		local j = 0
		foreach var of local varlist {
			local abname_`var' = abbrev("`var'",11)
			tempname percent_votes_`++j' percent_seats_`j'
			scalar `percent_votes_`j'' = `vte_`j''*100
			scalar `percent_seats_`j'' = (`tot_`j''/`chamber_size')*100
			.tableasignadip.row 				///
						"`abname_`var'' "		///1
						`ssd_`j'' 				///2
						`list_`j'' 				///3
						`tot_`j'' 				///4
						`percent_votes_`j'' 	///5
						`percent_seats_`j''		///6
						"`MaxSeats_`j''" 		///7
						"`MaxOverr_`j''"
		}
		.tableasignadip.sep, bottom
	}
end

*! checkinput v1.0 JavierMarquez 22dic2009
program define checkinput, byable(recall) sortpreserve
	version 10.0
	syntax varlist(numeric min=2) [if] [in]				///
		[, NULOynoreg(varlist numeric max=2)			///
		THReshold(real .02) MAXSeats(integer 300) 		///
		MAXOVERrep(real .08) NUMmay(numlist integer) 	///
		ESCrp(integer 200) MAXIter(integer 20) noMAY 	///
		noRP noPRInt]
	marksample touse
	tempvar validacion
	qui generate `validacion' = 0
	local tempo `varlist' `nuloynoreg'
	foreach t of local tempo {
		qui replace `validacion' = `validacion' + `t'
	}
	qui sum `validacion' if `touse', meanonly
	if r(min) < 0 | round(r(max),.001) > 1 {
		di as err "Values in varlist are invalid. " _c
		di as err "All values must be between 0 and 1"
		error 198
	}
	if round(r(mean),.001) != 1	{
		di as err "Variable list is invalid. " _c
		di as err "Values must sum to 1"
		error 198
	}
	local tempo threshold maxoverrep
	foreach t of local tempo {
		if ``t'' < 0 | ``t'' > 1 {
			di as err "Values in `t'() are invalid. " _c
			di as err "Values must be between 0 and 1"
			error 198
		}
	}
	local tempo maxseats escrp maxiter
	foreach t of local tempo {
		if ``t'' < 0 {
			di as err "Values in `t'() are invalid. " _c
			di as err "Values must be > 1"
			error 198
		}
	}
	if "`nummay'" != "" {
		local tempo1: word count `varlist'
		local tempo2: word count `nummay'
		if `tempo1' != `tempo2' {
			di as err "invalid numlist in option nummay()"
			error 121
		}
	}
end

*! _asignamay v1.0 JavierMarquez 22dic2009
program define _asignamay, rclass byable(recall) sortpreserve
	version 10.0
	syntax varlist(numeric min=2) [if] [in]
	marksample touse
	foreach var of local varlist {
		local varlistcomma "`varlistcomma', `var'"
	}
	local varlistcomma: subinstr local varlistcomma "," ""
	local j = 0
	foreach var of local varlist {
		tempvar gana_`var'
		qui generate `gana_`var'' = 0 if `touse'
		qui replace  `gana_`var'' = 1 if `touse' & 		///
			`var' == max(`varlistcomma')
		qui sum `gana_`var'' if `touse', meanonly
		tempname ssd_`++j'
		scalar `ssd_`j'' = r(sum)
	}
	local j = 0
	foreach var of local varlist {
		return scalar ssd_`++j' = `ssd_`j''
	}
end

*! _hiremainder v1.0 JavierMarquez 22dic2009
program define _hiremainder, rclass byable(recall) sortpreserve
	version 10.0
	syntax varlist(numeric min=2) [if] [in]	,			///
		vne(real) seats(integer) THReshold(real) 		///
		exc(numlist min=2)
	marksample touse
	local j = 0
	foreach var of local varlist {
		quietly sum `var' if `touse'
		tempname vte_`++j'
		scalar `vte_`j'' = r(mean)
	}
	tempname cociente
	scalar `cociente' = `vne'/`seats'

	local j = 0
	foreach var of local varlist {
		tempname entero_`++j' residuo_`j'
		scalar `entero_`j'' = 0
		scalar `residuo_`j'' = 0
		local tempo: word `j' of `exc'
		if `vte_`j'' >= `threshold' & `tempo' == 0 {
			scalar `entero_`j'' = 						///
				int(`vte_`j''/`cociente')
			scalar `residuo_`j'' = 						///
				mod(`vte_`j'',`cociente')
		}
	}
	local j = 0
	foreach var of local varlist {
		local listresiduos `listresiduos' `=`residuo_`++j'''
	}
	listsort "`listresiduos'", reverse
	local i = 0
	foreach var of local varlist {
		local orden_`++i' = s(i`i')
	}
	tempname sobrantes
	scalar `sobrantes' = `seats'
	local j = 0
	foreach var of local varlist {
		scalar `sobrantes' = `sobrantes' - `entero_`++j''
	}
	local j = 0
	foreach var of local varlist {
		tempname resto_`++j'
		scalar `resto_`j'' = 0
		if `sobrantes' > 0 {
			forvalues i = 1/`=`sobrantes'' {
				if `=`residuo_`j''' == `orden_`i'' {
					scalar `resto_`j'' = 1
				}
			}
		}
	}
	local j = 0
	foreach var of local varlist {
		local tempo: word `++j' of `exc'
		if `tempo' == 0 {
		return scalar list_`j' = 						///
			`entero_`j'' + `resto_`j''
		}
	}
end

*! listsort version 1.0.0 PR 16Feb2001.  (TSJ-1: dm0001)
program define listsort, sclass
	version 6
	gettoken p 0 : 0, parse(" ,")
	if `"`p'"'=="" {
	        exit
	}
	sret clear
	syntax , [ Reverse Lexicographic ]
	local lex="`lexicog'"!=""
	if "`reverse'"!="" { local comp < }
	else local comp >
	local np: word count `p'
	local i 1
	while `i'<=`np' {
	        local p`i': word `i' of `p'
	        if !`lex' { confirm number `p`i'' }
	        local i=`i'+1
	}
	* Apply shell sort (Kernighan & Ritchie p 58)
	local gap=int(`np'/2)
	while `gap'>0 {
	        local i `gap'
	        while `i'<`np' {
	                local j=`i'-`gap'
	                while `j'>=0 {
	                        local j1=`j'+1
	                        local j2=`j'+`gap'+1
	                        if `lex' { local swap=(`"`p`j1''"' `comp' `"`p`j2''"') }
	                        else local swap=(`p`j1'' `comp' `p`j2'')
	                        if `swap' {
	                                local temp `p`j1''
	                                local p`j1' `p`j2''
	                                local p`j2' `temp'
	                        }
	                        local j=`j'-`gap'
	                }
	                local i=`i'+1
	        }
	        local gap=int(`gap'/2)
	}
	local p
	local i 1
	while `i'<=`np' {
	        sret local i`i' `p`i''
	        local p `p' `p`i''
	        local i=`i'+1
	}
	sret local list `p'
end

*! _checkclauses v1.0 JavierMarquez 22dic2009
program define _checkclauses, rclass
	syntax varlist(numeric min=2) [if] [in],			///
		_sizemay(integer) escrp(integer)				///
		ssd(numlist) list(numlist) vne(real)			///
		maxseats(integer) maxoverrep(real)
	marksample touse
	local j = 0
	foreach var of local varlist {
		quietly sum `var' if `touse'
		tempname vte_`++j'
		scalar `vte_`j'' = r(mean)
	}
	tempname chamber_size
	scalar `chamber_size' = `_sizemay' + `escrp'
	local clauses = "NO"
	local j = 0
	foreach var of local varlist {
		tempname tot_`++j' excMaxSeats_`j' excMaxOverr_`j'
		local ssd_`j': word `j' of `ssd'
		local list_`j' : word `j' of `list'
		scalar `tot_`j'' = `ssd_`j'' + `list_`j''
		scalar `excMaxSeats_`j'' = 0
		scalar `excMaxOverr_`j'' = 0
		if `tot_`j'' > `maxseats' {
			local clauses = "YES"
			scalar `excMaxSeats_`j'' = 					///
				`tot_`j'' - `maxseats'
		}
		if ((`tot_`j''/`chamber_size') >				///
			((`vte_`j''/`vne') + `maxoverrep')			///
		&  ( `ssd_`j''/`chamber_size') <				///
			((`vte_`j''/`vne') + `maxoverrep')) {
				local clauses = "YES"
				scalar `excMaxOverr_`j'' = 				///
				`tot_`j'' - int(((`vte_`j''/`vne') +	///
				`maxoverrep')*`chamber_size')
		}
		return scalar excMaxSeats_`j' = 				///
			`excMaxSeats_`j''
		return scalar excMaxOverr_`j' = 				///
			`excMaxOverr_`j''
		return scalar exc_`j' = 						///
			max(`=`excMaxSeats_`j''', 					///
			`=`excMaxOverr_`j''')
	}
	return local clauses `clauses'
end