*! NJC 1.0.0 4 July 2002
* ipolate 1.3.1  14jun2000
program define cipolate, byable(onecall) sort
	version 7
	syntax varlist(min=2 max=2) [if] [in], Generate(string) [ BY(varlist) ]

	if _by() {
		if "`by'" != "" {
			di as err /*
			*/ "option by() may not be combined with by prefix"
			exit 190
		}
		local by "`_byvars'"
	}

	confirm new var `generate'
	tokenize `varlist'
	args usery x
	tempvar touse negx negy ok ok2 x1 x2 x3 x4 y1 y2 y3 y4
	tempvar m m1 m2 m3 m4 z y

	quietly {
		mark `touse' `if' `in'
		replace `touse' = 0 if `x' == .
		sort `touse' `by' `x'

		by `touse' `by' `x': /*
		*/ gen `y' = sum(`usery') / sum(`usery' != .) if `touse'
		by `touse' `by' `x': replace `y' = `y'[_N]

		* following values
		gen `negx' = -`x'
		gen `negy' = -`y'
		bysort `touse' `by' (`negx' `negy') : /*
		*/ gen `ok' = _n * (`y' < .)
		by `touse' `by' : /*
		*/ replace `ok' = `ok'[_n-1] if !`ok'
		by `touse' `by' : gen `ok2' = `ok'[_n-1] * (`ok' > `ok'[_n-1])
		by `touse' `by' : replace `ok2' = `ok2'[_n-1] if !`ok2'
		by `touse' `by' : gen `x4' = `x'[`ok2']
		by `touse' `by' : gen `y4' = `y'[`ok2']
		by `touse' `by' : gen `x3' = `x'[`ok']
		by `touse' `by' : gen `y3' = `y'[`ok']

		* preceding values
		bysort `touse' `by' (`x' `y'): /*
		*/ replace `ok' = _n * (`y' < .)
		by `touse' `by' : /*
		*/ replace `ok' = `ok'[_n-1] if !`ok'
		by `touse' `by' : replace `ok2' = /*
		*/ `ok'[_n-1] * (`ok' > `ok'[_n-1])
		by `touse' `by' : replace `ok2' = /*
		*/ `ok2'[_n-1] if !`ok2'
		by `touse' `by' : gen `x1' = `x'[`ok2']
		by `touse' `by' : gen `y1' = `y'[`ok2']
		by `touse' `by' : gen `x2' = `x'[`ok']
		by `touse' `by' : gen `y2' = `y'[`ok']

		gen double `m1' = (`x' - `x2') * (`x' - `x3') * (`x' - `x4') /*
		*/ / ((`x1' - `x2') * (`x1' - `x3') * (`x1' - `x4'))
		gen double `m2' = (`x' - `x1') * (`x' - `x3') * (`x' - `x4') /*
		*/ / ((`x2' - `x1') * (`x2' - `x3') * (`x2' - `x4'))
		gen double `m3' = (`x' - `x1') * (`x' - `x2') * (`x' - `x4') /*
		*/ / ((`x3' - `x1') * (`x3' - `x2') * (`x3' - `x4'))
		gen double `m4' = (`x' - `x1') * (`x' - `x2') * (`x' - `x3') /*
		*/ / ((`x4' - `x1') * (`x4' - `x2') * (`x4' - `x3'))
		gen double `m' = /*
		*/ `m1' * `y1' + `m2' * `y2' + `m3' * `y3' + `m4' * `y4'

		gen `z' = `y' if `touse'
		replace `z' = `m' if `touse' & `z' == .
		rename `z' `generate'
		count if `generate' == .
	}

	if r(N) > 0 {
		if r(N) != 1 { local pl "s" }
		di as txt "(" r(N) `" missing value`pl' generated)"'
	}
end