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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
#### Sparse Matrices in Compressed column-oriented format
### contains = "dsparseMatrix", "CsparseMatrix"
## Specific conversions, should they be necessary. Better to convert as
## as(x, "TsparseMatrix") or as(x, "denseMatrix")
## Moved to ./Csparse.R :
## setAs("dgCMatrix", "dgTMatrix", ....
## setAs("dgCMatrix", "dgeMatrix", ....
## setAs("dgeMatrix", "dgCMatrix", ....
setAs("dgCMatrix", "ngCMatrix", function(from) .C2nC(from, FALSE))
## rather use Csparse* to lsparse* in ./lsparseMatrix.R ,
## but this is for "back-compatibility" (have had tests for it..):
setAs("dgCMatrix", "lgCMatrix",
function(from) { ## FIXME use .Call() too!
r <- new("lgCMatrix")
r@x <- as.logical(from@x)
## and copy the other slots
for(nm in c("i", "p", "Dim", "Dimnames"))
slot(r, nm) <- slot(from, nm)
r
})
setMethod("image", "dgCMatrix", function(x, ...) image(as(x, "dgTMatrix"), ...))
## Group Methods, see ?Arith (e.g.)
## -----
##
## "Arith" is now in ./Ops.R
##
## "Math" and "Math2" in ./Math.R
## "[<-" methods { setReplaceMethod()s } are now in ./Csparse.R
## setMethod("writeHB", signature(obj = "dgCMatrix"),
## function(obj, file, ...) {
## .Deprecated("writeMM")
## .Call(Matrix_writeHarwellBoeing, obj,
## as.character(file), "DGC")
## })
##-> ./colSums.R for colSums,... rowMeans
setMethod("t", signature(x = "dgCMatrix"),
function(x) .Call(Csparse_transpose, x, FALSE),
valueClass = "dgCMatrix")
setMethod("determinant", signature(x = "dgCMatrix", logarithm = "logical"),
detSparseLU) # using mkDet() --> ./Auxiliaries.R
setMethod("qr", signature(x = "dgCMatrix"),
function(x, tol = 1e-07, LAPACK = FALSE, keep.dimnames = TRUE,
verbose = !is.null(v <- getOption("Matrix.verbose")) && v >= 1)
.Call(dgCMatrix_QR, # -> cs_sqr() and cs_qr() >> ../src/dgCMatrix.c
x, ## order =
if(verbose) -1L else TRUE, keep.dimnames))
setMethod("qr", signature(x = "sparseMatrix"),
function(x, ...)
qr(as(as(as(x, "CsparseMatrix"), "dsparseMatrix"), "dgCMatrix"), ...))
LU.dgC <- function(x, errSing = TRUE, order = TRUE, tol = 1.0, keep.dimnames = TRUE, ...) {
chk.s(..., which.call=-2)
.Call(dgCMatrix_LU, x, order, tol, errSing, keep.dimnames) ## ../src/dgCMatrix.c
}
setMethod("lu", signature(x = "dgCMatrix"), LU.dgC)
setMethod("lu", signature(x = "sparseMatrix"),
function(x, ...)
.set.factors(x, "lu",
lu(as(as(as(x, "CsparseMatrix"), "dsparseMatrix"), "dgCMatrix"),
...)))
.solve.dgC.lu <- function(a, b, tol = .Machine$double.eps) {
## @MM: see also solveSparse() in ~/R/MM/Pkg-ex/Matrix/Doran-A.R
lu.a <- LU.dgC(a)
if(tol > 0) {
rU <- range(abs(diag(lu.a@U)))
if(rU[1] / rU[2] < tol)
stop(gettextf("LU computationally singular: ratio of extreme entries in |diag(U)| = %9.4g",
rU[1] / rU[2]),
domain=NA)
}
n <- dim(a)[1L] ## == dim(a)[2], as a[.,.] is square matrix
b.isMat <-
if(missing(b)) {
## default b = Identity = Diagonal(nrow(a)), however more efficiently
b <- .sparseDiagonal(n)
TRUE
} else {
isM <- !is.null(dim(b))
if(isM && nrow(b) != n)
stop("RHS 'b' has wrong number of rows:", nrow(b))
if(!isM && length(b) != n)
stop("RHS 'b' has wrong length", length(b))
isM
}
## bp := P %*% b
bp <- if(b.isMat) b[lu.a@p+1L, ] else b[lu.a@p+1L]
## R:= U^{-1} L^{-1} P b
R <- solve(lu.a@U, solve(lu.a@L, bp))
## result = Q'R = Q' U^{-1} L^{-1} P b = A^{-1} b, as A = P'LUQ
R[invPerm(lu.a@q, zero.p=TRUE), ]
}
## FIXME: workaround, till .Call(dgCMatrix_matrix_solve, a, b, sparse=TRUE) works:
.solve.dgC <- function(a, b, sparse, tol = .Machine$double.eps)
if(sparse) .solve.dgC.lu(a, b, tol=tol) else .Call(dgCMatrix_matrix_solve, a, b, FALSE)
.solve.dgC.mat <- function(a, b, sparse=FALSE, tol = .Machine$double.eps, ...) {
chk.s(..., which.call=-2)
if(sparse) .solve.dgC.lu(a, b, tol=tol) else .Call(dgCMatrix_matrix_solve, a, b, FALSE)
}
## Provide also for pkg MatrixModels
.solve.dgC.chol <- function(x, y)
.Call(dgCMatrix_cholsol, as(x, "CsparseMatrix"), y)
.solve.dgC.qr <- function(x, y, order = 1L) {
cld <- getClass(class(x))
.Call(dgCMatrix_qrsol, # has AS_CSP(): must be dgC or dtC:
if(extends1of(cld, c("dgCMatrix", "dtCMatrix"))) x
else as(x, "dgCMatrix"),
y, order)
}
setMethod("solve", signature(a = "dgCMatrix", b = "matrix"), .solve.dgC.mat)
setMethod("solve", signature(a = "dgCMatrix", b = "ddenseMatrix"), .solve.dgC.mat)
setMethod("solve", signature(a = "dgCMatrix", b = "dsparseMatrix"),
function(a, b, sparse=NA, tol = .Machine$double.eps, ...) {
chk.s(..., which.call=-2)
if(is.na(sparse)) {
if(isSymmetric(a))
## TODO: fast cholmod_symmetric() for Cholesky
return(solve(forceCspSymmetric(a, isTri=FALSE), b, tol=tol))
#-> sparse result
## else
sparse <- FALSE # (old default)
}
## FIXME: be better when sparse=TRUE (?)
.solve.dgC(a, as(b, "denseMatrix"), tol=tol, sparse=sparse)
})
## This is a really dumb method but some people apparently want it
## (MM: a bit less dumb now with possibility of staying sparse)
setMethod("solve", signature(a = "dgCMatrix", b = "missing"),
function(a, b, sparse=NA, tol = .Machine$double.eps, ...) {
chk.s(..., which.call=-2)
if(is.na(sparse)) {
if(isSymmetric(a))
## TODO: fast cholmod_symmetric() for Cholesky
return(solve(forceCspSymmetric(a, isTri=FALSE),
b = Diagonal(nrow(a)))) #-> sparse result
## else
sparse <- FALSE # (old default)
}
if(sparse)
.solve.dgC.lu(a, tol=tol) # -> "smart" diagonal b
else .Call(dgCMatrix_matrix_solve, a, b=diag(nrow(a)), FALSE)
})
|