-
Notifications
You must be signed in to change notification settings - Fork 2
/
logdet.m
93 lines (86 loc) · 3.06 KB
/
logdet.m
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
function v = logdet(A, op)
%LOGDET Computation of logarithm of determinant of a matrix
%
% v = logdet(A);
% computes the logarithm of determinant of A.
%
% Here, A should be a square matrix of double or single class.
% If A is singular, it will returns -inf.
%
% Theoretically, this function should be functionally
% equivalent to log(det(A)). However, it avoids the
% overflow/underflow problems that are likely to
% happen when applying det to large matrices.
%
% The key idea is based on the mathematical fact that
% the determinant of a triangular matrix equals the
% product of its diagonal elements. Hence, the matrix's
% log-determinant is equal to the sum of their logarithm
% values. By keeping all computations in log-scale, the
% problem of underflow/overflow caused by product of
% many numbers can be effectively circumvented.
%
% The implementation is based on LU factorization.
%
% v = logdet(A, 'chol');
% If A is positive definite, you can tell the function
% to use Cholesky factorization to accomplish the task
% using this syntax, which is substantially more efficient
% for positive definite matrix.
%
% Remarks
% -------
% logarithm of determinant of a matrix widely occurs in the
% context of multivariate statistics. The log-pdf, entropy,
% and divergence of Gaussian distribution typically comprises
% a term in form of log-determinant. This function might be
% useful there, especially in a high-dimensional space.
%
% Theoretially, LU, QR can both do the job. However, LU
% factorization is substantially faster. So, for generic
% matrix, LU factorization is adopted.
%
% For positive definite matrices, such as covariance matrices,
% Cholesky factorization is typically more efficient. And it
% is STRONGLY RECOMMENDED that you use the chol (2nd syntax above)
% when you are sure that you are dealing with a positive definite
% matrix.
%
% Examples
% --------
% % compute the log-determinant of a generic matrix
% A = rand(1000);
% v = logdet(A);
%
% % compute the log-determinant of a positive-definite matrix
% A = rand(1000);
% C = A * A'; % this makes C positive definite
% v = logdet(C, 'chol');
%
% Copyright 2008, Dahua Lin, MIT
% Email: dhlin@mit.edu
%
% This file can be freely modified or distributed for any kind of
% purposes.
%
%% argument checking
assert(isfloat(A) && ndims(A) == 2 && size(A,1) == size(A,2), ...
'logdet:invalidarg', ...
'A should be a square matrix of double or single class.');
if nargin < 2
use_chol = 0;
else
assert(strcmpi(op, 'chol'), ...
'logdet:invalidarg', ...
'The second argument can only be a string ''chol'' if it is specified.');
use_chol = 1;
end
%% computation
if use_chol
v = 2 * sum(log(diag(chol(A))));
else
[L, U, P] = lu(A);
du = diag(U);
c = det(P) * prod(sign(du));
v = log(c) + sum(log(abs(du)));
end