Skip to content

Commit 7ec3cb4

Browse files
author
pd
committed
chol: zero trailing with pivot=TRUE + update help page
git-svn-id: https://svn.r-project.org/R/trunk@89125 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent 35391ce commit 7ec3cb4

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

doc/NEWS.Rd

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,11 @@
306306
307307
\subsection{BUG FIXES}{
308308
\itemize{
309+
\item \code{chol(x, pivot=TRUE)} now zeroes the trailing submatrix when
310+
the algorithm stops early. Following the help page instructions on
311+
how to reconstruct the matrix in postive semidefinite cases gave
312+
incorrect results if the rank was 2 or more less than the dimension.
313+
309314
\item Profiling \code{"mle"} objects (\pkg{stats4} package) could fail
310315
because profile MLE used starting value from full MLE. Now starts from profile MLE
311316
from previous step.

src/library/base/man/chol.Rd

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,22 @@ chol(x, \dots)
4242
error occurs. If \code{x} is positive semi-definite (i.e., some zero
4343
eigenvalues) an error will also occur as a numerical tolerance is used.
4444

45-
If \code{pivot = TRUE}, then the Cholesky decomposition of a positive
45+
If \code{pivot = TRUE}, then the Cholesky decomposition of a (rearranged)
46+
positive
4647
semi-definite \code{x} can be computed. The rank of \code{x} is
4748
returned as \code{attr(Q, "rank")}, subject to numerical errors.
4849
The pivot is returned as \code{attr(Q, "pivot")}. It is no longer
4950
the case that \code{t(Q) \%*\% Q} equals \code{x}. However, setting
5051
\code{pivot <- attr(Q, "pivot")} and \code{oo <- order(pivot)}, it
5152
is true that \code{t(Q[, oo]) \%*\% Q[, oo]} equals \code{x},
5253
or, alternatively, \code{t(Q) \%*\% Q} equals \code{x[pivot,
53-
pivot]}. See the examples.
54+
pivot]}. Notice also, that \code{Q[,oo]} is typically not triangular.
55+
See the examples.
56+
57+
NOTE: For versions of R up to 4.5.2, the above wasn't quite true.
58+
You also needed \code{rank <- attr(Q, "rank")} and
59+
\code{t(Q[1:rank, oo, drop=FALSE]) \%*\% Q[1:rank, oo, drop=FALSE]}
60+
and similar for the alternative version.
5461
5562
The value of \code{tol} is passed to LAPACK, with negative values
5663
selecting the default tolerance of (usually) \code{nrow(x) *
@@ -99,8 +106,8 @@ crossprod(cm) #-- = 'm'
99106
100107
# now for something positive semi-definite
101108
x <- matrix(c(1:5, (1:5)^2), 5, 2)
102-
x <- cbind(x, x[, 1] + 3*x[, 2])
103-
colnames(x) <- letters[20:22]
109+
x <- cbind(x, x[, 1] + 3*x[, 2], 2*x[, 1] + x[, 2])
110+
colnames(x) <- letters[20:23]
104111
m <- crossprod(x)
105112
qr(m)$rank # is 2, as it should be
106113
@@ -118,6 +125,13 @@ crossprod(Q[, order(pivot)]) # recover m
118125
try(chol(m)) # fails
119126
(Q <- chol(m, pivot = TRUE)) # warning
120127
crossprod(Q) # not equal to m
128+
129+
## another example, this time with positive, negative, and zero eigenvalues
130+
## notice that this (and the previous example) gets the rank wrong
131+
(m <- matrix(c(1,1,2, 1,1,2, 2,2,1), 3, 3))
132+
chol(m, pivot=TRUE)
133+
eigen(m)$values
121134
}
135+
122136
\keyword{algebra}
123137
\keyword{array}

src/modules/lapack/Lapack.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,10 @@ static SEXP La_chol(SEXP A, SEXP pivot, SEXP stol)
11181118
error(_("argument %d of Lapack routine %s had invalid value"),
11191119
-info, "dpstrf");
11201120
}
1121+
/* zero remaining upper triangle if rank < m */
1122+
for (int j = rank ; j < m ; j++)
1123+
for (int i = rank ; i <= j ; i++)
1124+
REAL(ans) [i + N * j] = 0. ;
11211125
setAttrib(ans, install("pivot"), piv);
11221126
SEXP s_rank = install("rank");
11231127
setAttrib(ans, s_rank, ScalarInteger(rank));

0 commit comments

Comments
 (0)