/*
REQUIREMENT : STATA >= 9
AUTHOR: André GILLIBERT (August 2017)
LICENSE: Creative Commons CC0
SUMMARY: Compute Clopper-Pearson mid-P confidence intervals of a binomial proportion
The procedure is described in DOI: 10.2307/2348891

SYNTAX 1: cpmidpi #trials #successes [, level(95) ]
EXAMPLE 1: cpmidpi 100 3
EXAMPLE 2: cpmidpi 100 3 , level(90)

#trials is the number of trials. It must be an immediate integer.
#successes is the number of successes. It must be an immediate integer.
level is the two-sided confidence level

SYNTAX 2: cpmidp col [, level(95) ]
EXAMPLE 3: cpmidp complications

col is a column of the current dataset.
This column must contain only 0 and 1 integer values. It may contain missing values. Missing values are excluded.
level is the two-sided confidence level

These commands mimicks the Stata cii and ci commands.
They return scalar values:
	r(level) = confidence level
	r(ub) = upper bound of the confidence interval
	r(lb) = lower bound of the confidence interval
	r(se) = standard error of the proportion (pretty useless)
	r(mean)= estimated proportion = number of successes / number of trials
	r(N) = number of trials

The cicmidp(successes,trials,confidence_level) function can be used from MATA
*/

mata:


real scalar midpvalue(x,n,p)
{
	return(binomial(n,x,p) - (binomial(n,x,p)-binomial(n,x-1,p))/2)
}

real scalar unirootpvalue(x,n,q)
{
	if (x==0 & q>0.50) {
		return(0)
	}
	if (x==n & q<=0.50) {
		return(1)
	}
	prec=1e-8/n
	real scalar flower, fupper, pupper, plower
	plower=0;pupper=1
	flower = midpvalue(x,n,plower) - q
	fupper = midpvalue(x,n,pupper) - q
	
	if (sign(flower)*sign(fupper) > 0) {
		return(.)
	}
	while ((pupper-plower) > prec) {
		pmid = (plower+pupper)/2
		fmid = midpvalue(x,n,pmid) - q
		if (sign(flower)*sign(fmid) > 0) {
			plower=pmid
			flower=fmid
		} else {
			pupper=pmid
			fupper=fmid
		}
	}
	return((plower+pupper)/2)
}

real rowvector cpmidpi(real scalar x,real scalar n,real scalar conf_level)
{
	return (unirootpvalue(x,n,0.5+conf_level/2), unirootpvalue(x,n,0.5-conf_level/2))
}
end

capture program drop cpmidpi
program define cpmidpi, rclass
	version 9
	syntax anything(name=x id="Number of trials and successes") [, level(real 95) ]

	scalar n=`1'
	scalar x=`2'
	if (x > n) {
		display "{error}Number of successes must be equal or smaller to number of trials"
		error 498
	}
	mata: st_matrix("outmat", cpmidpi(st_numscalar("x"), st_numscalar("n"), (`level'/100)))
	return scalar N=n
	return scalar mean=x/n
	return scalar se=sqrt((x*(n-x))/n^3)
	return scalar lb=outmat[1,1]
	return scalar ub=outmat[1,2]
	return scalar level=`level'
	display "Clopper-Pearson mid-P two-sided confidence interval"
	display "Confidence level: " `level' "%"
	display "Lower confidence limit: " outmat[1,1]
	display "Upper confidence limit: " outmat[1,2]
end

capture program drop cpmidp
program define cpmidp
	version 9
	syntax varname [, level(real 95) ]
	quietly summarize `1'
	cpmidpi r(N) r(sum) , level(`level')
end
