"eigen" <-
function (x, symmetric, only.values=FALSE) 
{
	x <- as.matrix(x)
        if (nrow(x) != ncol(x)) 
                stop("non-square matrix in eigen")
        n <- nrow(x)

	if(is.complex(x)) {
		complex.vals <- TRUE
		if(missing(symmetric))
			symmetric <- all(x == Conj(t(x)))
	}
	else if(is.numeric(x)) {
		storage.mode(x) <- "double"
		if(missing(symmetric))
			symmetric <- all(x == t(x))
		complex.vals <- FALSE
	}
	else stop("numeric or complex values required in eigen")

	if(symmetric) {
		if(complex.vals) {
			xr <- Re(x)
			xi <- Im(x)
			vals <- double(n)
			z <- .Fortran(
				"ch",
				n,
				n,
				xr,
				xi,
				values = vals,
				only.values == FALSE,
				vectors = xr,
				ivectors = xi,
				vals,
				vals,
				double(2*n),
				ierr = integer(1))
			if (z$ierr) 
				stop(paste("ch returned code ", z$ierr, " in eigen"))
			if(!only.values)
				z$vectors <- matrix(complex(re=z$vectors,
						im=z$ivectors), nc=n)
		}
		else {
			vals <- double(n)
			z <- .Fortran(
				"rs",
				n,
				n,
				x,
				values = vals,
				only.values == FALSE,
				vectors = x,
				vals,
				vals,
				ierr = integer(1))
			if (z$ierr) 
				stop(paste("rs returned code ", z$ierr, " in eigen"))
		}
		ord <- rev(order(z$values))
	}
	else {
		if(complex.vals) {
			xr <- Re(x)
			xi <- Im(x)
			vals <- double(n)
			z <- .Fortran(
				"cg",
				n,
				n,
				xr,
				xi,
				values = vals,
				ivalues = vals,
				only.values == FALSE,
				vectors = xr,
				ivectors = xi,
				vals,
				vals,
				vals,
				ierr = integer(1))
			if (z$ierr) 
				stop(paste("cg returned code ", z$ierr, " in eigen"))
			z$values <- complex(re=z$values,im=z$ivalues)
			if(!only.values)
				z$vectors <- matrix(complex(re=z$vectors,
						im=z$ivectors), nc=n)
		}
		else {
			z <- .Fortran(
				"rg",
				n,
				n,
				x,
				values = double(n),
				ivalues = double(n),
				only.values == FALSE,
				vectors = x,
				integer(n),
				double(n),
				ierr = integer(1))
			if (z$ierr) 
				stop(paste("rg returned code ", z$ierr, " in eigen"))
			ind <- seq(n)[z$ivalues > 0]
			if(length(ind) > 0) {
				z$values <- complex(re=z$values,im=z$ivalues)
				if(!only.values) {
					z$vectors[, ind] <- complex(re=z$vectors[,ind],
								im=z$vectors[,ind+1])
					z$vectors[, ind+1] <- Conj(z$vectors[,ind])
				}
			}
		}
		ord <- rev(order(Mod(z$values)))
	}
	z$values <- z$values[ord]
	if(only.values == FALSE) {
		z$vectors <- z$vectors[,ord]
		z[c("values", "vectors")]
	}
	else z["values"]
}
