Skip to content

Commit 70a1855

Browse files
committed
Add .ln_detc*() methods to DeterminantC*
1 parent 346d43c commit 70a1855

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

src/cholesky.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,15 @@ where
102102
type Output = <A as AssociatedReal>::Real;
103103

104104
fn detc(&self) -> Self::Output {
105+
self.ln_detc().exp()
106+
}
107+
108+
fn ln_detc(&self) -> Self::Output {
105109
self.factor
106110
.diag()
107111
.iter()
108112
.map(|elem| elem.abs_sqr().ln())
109113
.sum::<Self::Output>()
110-
.exp()
111114
}
112115
}
113116

@@ -121,6 +124,10 @@ where
121124
fn detc_into(self) -> Self::Output {
122125
self.detc()
123126
}
127+
128+
fn ln_detc_into(self) -> Self::Output {
129+
self.ln_detc()
130+
}
124131
}
125132

126133
impl<A, S> InverseC for CholeskyFactorized<S>
@@ -391,6 +398,14 @@ pub trait DeterminantC {
391398
/// Computes the determinant of the Hermitian (or real symmetric) positive
392399
/// definite matrix.
393400
fn detc(&self) -> Self::Output;
401+
402+
/// Computes the natural log of the determinant of the Hermitian (or real
403+
/// symmetric) positive definite matrix.
404+
///
405+
/// This method is more robust than `.detc()` to very small or very large
406+
/// determinants since it returns the natural logarithm of the determinant
407+
/// rather than the determinant itself.
408+
fn ln_detc(&self) -> Self::Output;
394409
}
395410

396411

@@ -401,6 +416,14 @@ pub trait DeterminantCInto {
401416
/// Computes the determinant of the Hermitian (or real symmetric) positive
402417
/// definite matrix.
403418
fn detc_into(self) -> Self::Output;
419+
420+
/// Computes the natural log of the determinant of the Hermitian (or real
421+
/// symmetric) positive definite matrix.
422+
///
423+
/// This method is more robust than `.detc_into()` to very small or very
424+
/// large determinants since it returns the natural logarithm of the
425+
/// determinant rather than the determinant itself.
426+
fn ln_detc_into(self) -> Self::Output;
404427
}
405428

406429
impl<A, S> DeterminantC for ArrayBase<S, Ix2>
@@ -411,7 +434,11 @@ where
411434
type Output = Result<<A as AssociatedReal>::Real>;
412435

413436
fn detc(&self) -> Self::Output {
414-
Ok(self.factorizec(UPLO::Upper)?.detc())
437+
Ok(self.ln_detc()?.exp())
438+
}
439+
440+
fn ln_detc(&self) -> Self::Output {
441+
Ok(self.factorizec(UPLO::Upper)?.ln_detc())
415442
}
416443
}
417444

@@ -423,6 +450,10 @@ where
423450
type Output = Result<<A as AssociatedReal>::Real>;
424451

425452
fn detc_into(self) -> Self::Output {
426-
Ok(self.factorizec_into(UPLO::Upper)?.detc_into())
453+
Ok(self.ln_detc_into()?.exp())
454+
}
455+
456+
fn ln_detc_into(self) -> Self::Output {
457+
Ok(self.factorizec_into(UPLO::Upper)?.ln_detc_into())
427458
}
428459
}

tests/cholesky.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,16 @@ fn cholesky_det() {
104104
($elem:ty, $atol:expr) => {
105105
let a: Array2<$elem> = random_hpd(3);
106106
println!("a = \n{:?}", a);
107-
let det = a.eigvalsh(UPLO::Upper).unwrap().mapv(|elem| elem.ln()).scalar_sum().exp();
108-
assert_aclose!(a.detc().unwrap(), det, $atol);
107+
let ln_det = a.eigvalsh(UPLO::Upper).unwrap().mapv(|elem| elem.ln()).scalar_sum();
108+
let det = ln_det.exp();
109109
assert_aclose!(a.factorizec(UPLO::Upper).unwrap().detc(), det, $atol);
110-
assert_aclose!(a.factorizec(UPLO::Lower).unwrap().detc(), det, $atol);
110+
assert_aclose!(a.factorizec(UPLO::Upper).unwrap().ln_detc(), ln_det, $atol);
111+
assert_aclose!(a.factorizec(UPLO::Lower).unwrap().detc_into(), det, $atol);
112+
assert_aclose!(a.factorizec(UPLO::Lower).unwrap().ln_detc_into(), ln_det, $atol);
113+
assert_aclose!(a.detc().unwrap(), det, $atol);
114+
assert_aclose!(a.ln_detc().unwrap(), ln_det, $atol);
115+
assert_aclose!(a.clone().detc_into().unwrap(), det, $atol);
116+
assert_aclose!(a.ln_detc_into().unwrap(), ln_det, $atol);
111117
}
112118
}
113119
cholesky_det!(f64, 1e-9);

0 commit comments

Comments
 (0)