"discrim.fun"<-
function(z, gr)
{
#  z is a data matrix and gr is a T/F matrix of class membership
#  we find the linear discriminant and certain of its properties: on exit
#	ldisc	is the vector of linear discriminant weights
#	dcrit	is the critical value of the linear discriminant
#	xdisc	is the vector of values of the linear discriminant for the data in the sample
#	alloc	is the vector of allocations of the data in the sample
#------------------------------------------------------------------
#  find individual group means and pooled covariance matrix; add a very small constant to the
#	diagonal to ensure numerical stability
#
	m1 <- apply(z[gr,  ], 2, mean)
	m0 <- apply(z[!gr,  ], 2, mean)
	z1c <- sweep(z[gr,  ], 2, m1)
	z0c <- sweep(z[!gr,  ], 2, m0)
	vmat <- (t(z1c) %*% z1c + t(z0c) %*% z0c)/(dim(z)[1] - 2)
	diag(vmat) <- diag(vmat) + 0.0001 * mean(diag(vmat))	#
#  find linear discriminant, normalized to be of norm 1, and classify the data in the sample
#
	ldisc <- solve(vmat, m1 - m0)
	ldisc <- ldisc/vecnorm(ldisc)
	xdisc <- z %*% ldisc
	dcrit <- 0.5 * sum((m1 + m0) * ldisc)
	alloc <- (xdisc > dcrit)
	return(ldisc, dcrit, xdisc, alloc)
}
"discrimcv.fun"<-
function(z, gr)
{
	z <- as.matrix(z)
	nobs <- length(gr)
	cvalloc <- vector(length = nobs)
	for(j in (1:nobs)) {
		ldj <- discrim.fun(z[ - j,  ], gr[ - j])
		zdisc <- sum(z[j,  ] * ldj$ldisc)
		cvalloc[j] <- (zdisc > ldj$dcrit)
	}
	falsepos <- sum(cvalloc & !gr)
	falseneg <- sum(gr & !cvalloc)
	return(c(falsepos, falseneg))
}
"notchproc1.fun"<-
function(z)
{
	y <- c(rev(z$Y), z$Y)
	x <- c(rev(z$Xlat), z$Xmed)
	xscale <- diff(range(x))
	x <- (x - min(x))/xscale
	y <- (max(y) - y)/xscale
	return(cbind(x, y))
}
"notchproc2.fun"<-
function(z)
{
#
#   first of all replace all except the first and last rows
#     of z by the averages of neighboring rows
#
	nt <- dim(z)[1]
	z <- rbind(z[1,  ], (z[ - nt,  ] + z[-1,  ])/2, z[nt,  ])	#
#    now define the vector tl to be the cumulative arc length
#      along the curve defined by z by finding the distance 
#      successive points and then cumulating and dividing by
#      the total length
#
	zd <- sqrt(diff(z[, 1])^2 + diff(z[, 2])^2)
	tl <- c(0, cumsum(zd))/sum(zd)	#
#   finally, linearly interpolate the x and y coordinates
#      to yield the coordinates at points with evenly spaced
#      values of tl, and return a matrix with these coordinates
#
	x <- approx(tl, z[, 1], n = 50)$y
	y <- approx(tl, z[, 2], n = 50)$y
	return(cbind(x, y))
}
