The R Project SVN R

Rev

Rev 49007 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

#  File src/library/base/R/eigen.R
#  Part of the R package, http://www.R-project.org
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  A copy of the GNU General Public License is available at
#  http://www.r-project.org/Licenses/


isSymmetric <- function(object, ...) UseMethod("isSymmetric")

isSymmetric.matrix <- function(object, tol = 100*.Machine$double.eps, ...)
{
    if(!is.matrix(object)) return(FALSE) ## we test for  symmetric *matrix*
    ## cheap pretest: is it square?
    d <- dim(object)
    if(d[1L] != d[2L]) return(FALSE)
    test <-
        if(is.complex(object))
            all.equal.numeric(object, Conj(t(object)), tolerance = tol, ...)
        else # numeric, character, ..
            all.equal(object, t(object), tolerance = tol, ...)
    isTRUE(test)
}

eigen <- function(x, symmetric, only.values = FALSE, EISPACK = FALSE)
{
    x <- as.matrix(x)
    if(!is.null(dimnames(x)))
        dimnames(x) <- list(NULL, NULL)  # or they appear on eigenvectors
    n <- nrow(x)
    if (!n) stop("0 x 0 matrix")
    if (n != ncol(x)) stop("non-square matrix in 'eigen'")

    complex.x <- is.complex(x)
    if(!complex.x && !is.double(x))
    storage.mode(x) <- "double"
    if (!all(is.finite(x))) stop("infinite or missing values in 'x'")

    if(missing(symmetric)) symmetric <- isSymmetric.matrix(x)

    if (!EISPACK) {
        if (symmetric) {
            z <- if(!complex.x)
                .Call("La_rs", x, only.values, PACKAGE = "base")
            else
                .Call("La_rs_cmplx", x, only.values, PACKAGE = "base")
            ord <- rev(seq_along(z$values))
        } else {
            z <- if(!complex.x)
                .Call("La_rg", x, only.values, PACKAGE = "base")
            else
                .Call("La_rg_cmplx", x, only.values, PACKAGE = "base")
            ord <- sort.list(Mod(z$values), decreasing = TRUE)
        }
        return(list(values = z$values[ord],
                    vectors = if (!only.values) z$vectors[, ord, drop = FALSE]))
    }

    dbl.n <- double(n)
    if(symmetric) {##--> real values
    if(complex.x) {
        xr <- Re(x)
        xi <- Im(x)
        z <- .Fortran("ch",
              n,
              n,
              xr,
              xi,
              values = dbl.n,
              !only.values,
              vectors = xr,
              ivectors = xi,
              dbl.n,
              dbl.n,
              double(2*n),
              ierr = integer(1L),
                          PACKAGE="base")
        if (z$ierr)
        stop(gettextf("'ch' returned code %d in 'eigen'", z$ierr),
                     domain = NA)
        if(!only.values)
        z$vectors <- matrix(complex(real=z$vectors,
                        imaginary=z$ivectors), ncol=n)
    }
    else {
        z <- .Fortran("rs",
              n,
              n,
              x,
              values = dbl.n,
              !only.values,
              vectors = x,
              dbl.n,
              dbl.n,
              ierr = integer(1L),
                          PACKAGE="base")
        if (z$ierr)
        stop(gettextf("'rs' returned code %d in 'eigen'", z$ierr),
                     domain = NA)
    }
    ord <- sort.list(z$values, decreasing = TRUE)
    }
    else {##- Asymmetric :
    if(complex.x) {
        xr <- Re(x)
        xi <- Im(x)
        z <- .Fortran("cg",
              n,
              n,
              xr,
              xi,
              values = dbl.n,
              ivalues = dbl.n,
              !only.values,
              vectors = xr,
              ivectors = xi,
              dbl.n,
              dbl.n,
              dbl.n,
              ierr = integer(1L),
                          PACKAGE="base")
        if (z$ierr)
        stop(gettextf("'cg' returned code %d in 'eigen'", z$ierr),
                     domain = NA)
        z$values <- complex(real=z$values,imaginary=z$ivalues)
        if(!only.values)
        z$vectors <- matrix(complex(real=z$vectors,
                        imaginary=z$ivectors), ncol=n)
    }
    else {
        z <- .Fortran("rg",
              n,
              n,
              x,
              values = dbl.n,
              ivalues = dbl.n,
              !only.values,
              vectors = x,
              integer(n),
              dbl.n,
              ierr = integer(1L),
                          PACKAGE="base")
        if (z$ierr)
        stop(gettextf("'rg' returned code %d in 'eigen'", z$ierr),
                     domain = NA)
        ind <- z$ivalues > 0L
        if(any(ind)) {#- have complex (conjugated) values
        ind <- seq.int(n)[ind]
        z$values <- complex(real=z$values,imaginary=z$ivalues)
        if(!only.values) {
            z$vectors[, ind] <- complex(real=z$vectors[,ind],
                        imaginary=z$vectors[,ind+1])
            z$vectors[, ind+1] <- Conj(z$vectors[,ind])
        }
        }
    }
    ord <- sort.list(Mod(z$values), decreasing = TRUE)
    }
    list(values = z$values[ord],
     vectors = if(!only.values) z$vectors[,ord, drop = FALSE])
}