File tree Expand file tree Collapse file tree 3 files changed +47
-1
lines changed Expand file tree Collapse file tree 3 files changed +47
-1
lines changed Original file line number Diff line number Diff line change @@ -20,3 +20,4 @@ features = ["blas"]
20
20
[dev-dependencies ]
21
21
rand = " 0.3.14"
22
22
ndarray-rand = " 0.3"
23
+ float-cmp = " 0.2.3"
Original file line number Diff line number Diff line change 3
3
use ndarray:: { Ix2 , Array , LinalgScalar } ;
4
4
use std:: fmt:: Debug ;
5
5
use num_traits:: float:: Float ;
6
+ use num_traits:: One ;
6
7
use lapack:: c:: Layout ;
7
8
8
9
use matrix:: Matrix ;
@@ -23,10 +24,12 @@ pub trait HermiteMatrix: SquareMatrix + Matrix {
23
24
fn ssqrt ( self ) -> Result < Self , LinalgError > ;
24
25
/// Cholesky factorization
25
26
fn cholesky ( self ) -> Result < Self , LinalgError > ;
27
+ /// calc determinant using Cholesky factorization
28
+ fn deth ( self ) -> Result < Self :: Scalar , LinalgError > ;
26
29
}
27
30
28
31
impl < A > HermiteMatrix for Array < A , Ix2 >
29
- where A : ImplQR + ImplSVD + ImplNorm + ImplSolve + ImplEigh + ImplCholesky + LinalgScalar + Float + Debug
32
+ where A : ImplQR + ImplSVD + ImplNorm + ImplSolve + ImplEigh + ImplCholesky + LinalgScalar + Float + Debug + One
30
33
{
31
34
fn eigh ( self ) -> Result < ( Self :: Vector , Self ) , LinalgError > {
32
35
self . check_square ( ) ?;
@@ -67,4 +70,10 @@ impl<A> HermiteMatrix for Array<A, Ix2>
67
70
}
68
71
Ok ( c)
69
72
}
73
+ fn deth ( self ) -> Result < Self :: Scalar , LinalgError > {
74
+ let ( n, _) = self . size ( ) ;
75
+ let c = self . cholesky ( ) ?;
76
+ let rt = ( 0 ..n) . map ( |i| c[ ( i, i) ] ) . fold ( A :: one ( ) , |det, c| det * c) ;
77
+ Ok ( rt * rt)
78
+ }
70
79
}
Original file line number Diff line number Diff line change
1
+
2
+ extern crate ndarray;
3
+ extern crate ndarray_linalg;
4
+ extern crate ndarray_rand;
5
+ extern crate rand;
6
+ extern crate float_cmp;
7
+
8
+ use ndarray:: prelude:: * ;
9
+ use ndarray_linalg:: prelude:: * ;
10
+ use rand:: distributions:: * ;
11
+ use ndarray_rand:: RandomExt ;
12
+ use float_cmp:: ApproxEqRatio ;
13
+
14
+ fn approx_eq ( val : f64 , truth : f64 , ratio : f64 ) {
15
+ if !val. approx_eq_ratio ( & truth, ratio) {
16
+ panic ! ( "Not almost equal! val={:?}, truth={:?}, ratio={:?}" ,
17
+ val,
18
+ truth,
19
+ ratio) ;
20
+ }
21
+ }
22
+
23
+ fn random_hermite ( n : usize ) -> Array < f64 , Ix2 > {
24
+ let r_dist = Range :: new ( 0. , 1. ) ;
25
+ let a = Array :: < f64 , _ > :: random ( ( n, n) , r_dist) ;
26
+ a. dot ( & a. t ( ) )
27
+ }
28
+
29
+ #[ test]
30
+ fn deth ( ) {
31
+ let a = random_hermite ( 3 ) ;
32
+ let ( e, _) = a. clone ( ) . eigh ( ) . unwrap ( ) ;
33
+ let deth = a. clone ( ) . deth ( ) . unwrap ( ) ;
34
+ let det_eig = e. iter ( ) . fold ( 1.0 , |x, y| x * y) ;
35
+ approx_eq ( deth, det_eig, 1.0e-7 ) ;
36
+ }
You can’t perform that action at this time.
0 commit comments