1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
#'
#' matrixpower.R
#'
#' Copyright (c) Adrian Baddeley, Ege Rubak and Rolf Turner 2016-2022
#' GNU Public Licence >= 2.0
#'
#' $Revision: 1.9 $ $Date: 2024/06/09 00:01:09 $
#'
matrixsqrt <- function(x, complexOK=TRUE) {
## matrix square root
if(length(dim(x)) != 2)
stop("x must be a matrix")
if(!is.matrix(x))
x <- as.matrix(x)
check.nmatrix(x, mname="x") ## requires square matrix
if(missing(complexOK) && is.complex(x)) complexOK <- TRUE
if(!complexOK) stopifnot(is.numeric(x)) else
stopifnot(is.numeric(x) || is.complex(x))
## eigen decomposition
e <- eigen(x)
values <- e$values
vectors <- e$vectors
## real or complex?
realresult <- is.numeric(vectors) && is.numeric(values) && all(values >= 0)
if(realresult) {
## result is a real matrix
y <- vectors %*% diag(sqrt(values)) %*% t(vectors)
} else {
## result is a complex matrix
if(!complexOK)
stop("square root is complex, but complexOK=FALSE was specified", call.=FALSE)
values <- as.complex(values)
y <- vectors %*% diag(sqrt(values)) %*% solve(vectors)
}
## add dimnames
if(!is.null(dn <- dimnames(x)))
dimnames(y) <- rev(dn)
return(y)
}
matrixinvsqrt <- function(x, complexOK=TRUE) {
## matrix inverse square root
if(length(dim(x)) != 2)
stop("x must be a matrix")
if(!is.matrix(x))
x <- as.matrix(x)
check.nmatrix(x, mname="x") ## requires square matrix
if(missing(complexOK) && is.complex(x)) complexOK <- TRUE
if(!complexOK) stopifnot(is.numeric(x)) else
stopifnot(is.numeric(x) || is.complex(x))
## eigen decomposition
e <- eigen(x)
values <- e$values
vectors <- e$vectors
if(any(values == 0))
stop("matrix is singular; cannot compute inverse square root", call.=FALSE)
## real or complex?
realresult <- is.numeric(vectors) && is.numeric(values) && all(values >= 0)
if(realresult) {
## result is a real matrix
y <- vectors %*% diag(1/sqrt(values)) %*% t(vectors)
} else {
## result is a complex matrix
if(!complexOK)
stop("inverse square root is complex, but complexOK=FALSE was specified", call.=FALSE)
values <- as.complex(values)
y <- vectors %*% diag(1/sqrt(values)) %*% solve(vectors)
}
## add dimnames
if(!is.null(dn <- dimnames(x)))
dimnames(y) <- rev(dn)
return(y)
}
matrixpower <- function(x, power, complexOK=TRUE) {
check.1.real(power)
if(length(dim(x)) != 2)
stop("x must be a matrix")
if(!is.matrix(x))
x <- as.matrix(x)
check.nmatrix(x, mname="x") ## requires square matrix
if(power == 0) {
## power = 0 yields identity matrix even if x is singular
y <- diag(nrow(x))
} else {
## nonzero power
if(missing(complexOK) && is.complex(x)) complexOK <- TRUE
if(!complexOK) stopifnot(is.numeric(x)) else
stopifnot(is.numeric(x) || is.complex(x))
## eigen decomposition
e <- eigen(x)
values <- e$values
vectors <- e$vectors
if(any(values == 0) && power < 0)
stop("matrix is singular; cannot compute negative power", call.=FALSE)
## real or complex?
realresult <- is.numeric(vectors) && is.numeric(values) && all(values >= 0)
if(realresult) {
## result is a real matrix
y <- vectors %*% diag(values^power) %*% t(vectors)
} else {
## result is a complex matrix
if(!complexOK)
stop("result is complex, but complexOK=FALSE was specified", call.=FALSE)
values <- as.complex(values)
y <- vectors %*% diag(values^power) %*% solve(vectors)
}
}
## add dimnames
if(!is.null(dn <- dimnames(x)))
dimnames(y) <- rev(dn)
return(y)
}
|