/* _grtvand.ado  10-5-2000
By David Kantor, Institute for Policy Studies, Johns Hopkins University.
This is a user-added feature for Stata's egen command.
As such, it goes in c:\ado rather than c:\stata\ado\_.

This is a three-valued logic AND in an egen context.
It is based on the earlier tvland.ado, but this is now set in the context
of egen; consequently, it uses egen grammar.

This is part of a suite of three-valued logic egen utilities:
 tvnot, rtvor, rtvand, tvor, tvand.
(There are also tvlnot, tvlor, & tvland.  Those are earlier, less complete
versions, which stand as separate programs; they are not egen utilities.
These egen utilities are to be preferred.)

We allow any number of input variables.

For 1 var, you should get back the original, but with all "true" (nonzero,
nonmissing) converted to 1.

For 0 vars, you should get false (1) -- the identity element for AND.

Parts of this are borrowed from stata\ado\_\_grmiss.ado.

1-31-2001:  I am adding the "liberal" option.  This allows a different
version of the operation; it takes the AND of all non-missing elements, and
only yields missing if all arguments are missing.

(That was originally done for _grtvor.  I do it here for completeness, but
I'm not sur what the utility of this is.)
*/

*! version 2.2.1  2-28-2001
program define _grtvand
version 5.0
local type "`1'"
if "`type'" == " " {local type "byte"}  /* default type */
mac shift
local g "`1'"
mac shift
mac shift                               /* discard = sign */
local varlist "opt ex none"
local in "opt"
local if "opt"
local options "LIBeral"
parse "`*'"

/* We need the row-sums of whether each variable in `varlist' is
0; 1; missing.  We will count each of these; the count of missings
is equivalent to egen ... rmiss(`varlist').
*/

tempvar numfals numtrue nummis

gen int `numfals' = 0
gen int `numtrue' = 0  /* Here, "true" does not include missing. */
gen int `nummis' = 0

parse "`varlist'", parse(" ")
while "`1'"!="" {
	quietly {
		replace `numfals' = `numfals' + (`1'==0)
		replace `numtrue' = `numtrue' + (`1'~=0 & `1'~=.)
		replace `nummis' = `nummis' + (`1'==.)
	}
	mac shift
}
/*
assert `numfals' >=0 & `numfals' ~=.
assert `numtrue' >=0 & `numtrue' ~=.
assert `nummis' >=0 & `nummis' ~=.
*/
#delimit ;
if "`liberal'" =="liberal" {;
	quietly gen `type' `g' =
	  cond(`numtrue'==0 & `numfals'== 0, ., `numfals' ==0)
	   `if' `in';
};
else {;
	quietly gen `type' `g' =
	  cond(`numfals' > 0, 0,
	   cond(`nummis' ==0, 1, .)
	  ) `if' `in';
};
end;