88#include < cstring>
99#include < iostream>
1010
11- static const double x_mat_test[] = {
12- 5.551063927745538 , 0.034194385271978 , -0.276508795460738 ,
13- 0.034194385271978 , 4.704686460853461 , 0.087572555571367 ,
14- -0.276508795460738 , 0.087572555571367 , 6.07658590927362 };
15-
16- static const double r_mat_test[] = {2.356069593145656 ,
17- 0 .,
18- 0 .,
19- 0.014513317166631 ,
20- 2.16898036516661 ,
21- 0 .,
22- -0.117360198639788 ,
23- 0.041160281019929 ,
24- 2.461933858639425 };
25-
26- static const int test_size = 3 ;
11+ static const int test_size = 5 ;
2712
2813Cholesky::Cholesky () {
2914 x_mat = r_mat = 0 ;
@@ -45,50 +30,86 @@ void Cholesky::make_args(int size) {
4530 for (int i = 0 ; i < n; i++) {
4631 r_mat[i * n + i] = 1 ;
4732 }
48- cblas_dgemm (CblasColMajor, CblasNoTrans, CblasTrans, n, n, n, 1.0 , x_mat, n,
49- x_mat, n, n, r_mat, n);
33+
34+ static const char uplo = ' U' ;
35+ static const char trans = ' T' ;
36+ static const double alpha = 1 .;
37+ static const double beta = n;
38+ dsyrk (&uplo, &trans, &n, &n, &alpha, x_mat, &n, &beta, r_mat, &n);
5039
5140 // we now have r_mat = x_mat * x_mat' + n * np.eye(n)
5241 // copy back into x_mat
5342 memcpy (x_mat, r_mat, mat_size * sizeof (*x_mat));
5443}
5544
5645void Cholesky::copy_args () {
57- memcpy (r_mat, x_mat, mat_size * sizeof (*x_mat));
46+ // copy moved to compute()
5847}
5948
6049void Cholesky::compute () {
50+ // perform copy here.
51+ static const int one = 1 ;
52+ dcopy (&mat_size, x_mat, &one, r_mat, &one);
53+
6154 // compute cholesky decomposition
6255 int info;
63- const char uplo = ' U' ;
56+ static const char uplo = ' U' ;
6457 dpotrf (&uplo, &n, r_mat, &lda, &info);
6558 assert (info == 0 );
6659
6760 // we only want an upper triangular matrix
68- for (int i = 0 ; i < n - 1 ; i++) {
69- memset (&r_mat[i * n + i + 1 ], 0 , (n - i - 1 ) * sizeof (*r_mat));
61+ // in scipy, this is done in *potrf wrapper.
62+ // https://github.com/scipy/scipy/blob/maintenance/1.3.x/scipy/linalg/flapack_pos_def.pyf.src#L85
63+ for (int i = 0 ; i < n; i++) {
64+ for (int j = i + 1 ; j < n; j++) {
65+ r_mat[i * n + j] = 0 .;
66+ }
7067 }
7168}
7269
73- bool Cholesky::test () {
70+ bool Cholesky::test (bool verbose ) {
7471 clean_args ();
7572 make_args (test_size);
76- memcpy (x_mat, x_mat_test, mat_size * sizeof (*x_mat));
7773 copy_args ();
7874 compute ();
7975
80- return mat_equal (r_mat, r_mat_test, mat_size);
76+ // verify that r_mat is upper triangular
77+ for (int i = 0 ; i < n; i++) {
78+ for (int j = i + 1 ; j < n; j++) {
79+ if (r_mat[i * n + j] != 0 .) {
80+ if (verbose) {
81+ std::cerr << " r_mat is not upper triangular!" << std::endl;
82+ }
83+ return false ;
84+ }
85+ }
86+ }
87+
88+ // try to reconstruct x_mat from its Cholesky decomposition
89+ static const double alpha = 1 ., beta = 0 .;
90+ static const char uplo = ' U' ;
91+ static const char trans = ' T' ;
92+ double *c = make_mat (mat_size);
93+ dsyrk (&uplo, &trans, &n, &n, &alpha, r_mat, &n, &beta, c, &n);
94+
95+ if (verbose) {
96+ std::cout << " U* * U = (should be equal to A)" << std::endl;
97+ print_mat (' c' , c, n, n);
98+ }
99+ bool equal = mat_equal (c, x_mat, mat_size);
100+ mkl_free (c);
101+ return equal;
81102}
82103
83104void Cholesky::print_args () {
84- std::cout << " Cholesky decomposition, A = LL* , of a "
105+ std::cout << " Cholesky decomposition, A = U* * U , of a "
85106 << " Hermitian positive-definite matrix A." << std::endl;
86107 std::cout << " A = " << std::endl;
87108 print_mat (' c' , x_mat, n, n);
88109}
89110
90111void Cholesky::print_result () {
91- std::cout << " L = " << std::endl;
112+ std::cout << " U = " << std::endl;
92113 print_mat (' c' , r_mat, n, n);
93114}
94115
0 commit comments