MyraMath
cCholeskySolver


Source: tests/dense/ZCholeskySolver.cpp

1 // ========================================================================= //
2 // This file is part of MyraMath, copyright (c) 2014-2019 by Ryan A Chilton //
3 // and distributed by MyraCore, LLC. See LICENSE.txt for license terms. //
4 // ========================================================================= //
5 
11 // Containers.
13 #include <myramath/dense/Matrix.h>
15 
16 // Algorithms.
17 #include <myramath/dense/gemm.h>
18 #include <myramath/dense/herk.h>
23 
24 // Solver class under test.
26 
27 // Serialization testing.
29 
30 // Reporting.
31 #include <tests/myratest.h>
32 
33 using namespace myra;
34 
35 namespace {
36 
37 template<class Precision> void test(int I, int J, Precision tolerance)
38  {
39  typedef std::complex<Precision> Number;
40  myra::out() << typestring<Number>() << std::endl;
41  // Construct random symmetric positive definite matrix, A = G'*G
43  Matrix<Number> A = gemm(G,'H',G);
44  // Restrict A to lower triangle, generate cholesky solver for it.
45  LowerMatrix<Number> L = herk(G,'H');
46  typedef ZCholeskySolver<Precision> Solver;
47  Solver solver(L);
48  // Total of 8 solve() variations to validiate, side['L',R'] x op['N','T','H','C']
49  // Solve A*X=B
50  {
51  auto X = Matrix<Number>::random(I,J);
52  auto B = A*X;
53  solver.solve(B,'L','N');
54  Precision error = frobenius(X-B)/frobenius(X);
55  myra::out() << " |inv(A)*B-X| = " << error << std::endl;
56  REQUIRE(error < tolerance);
57  }
58  // Solve transpose(A)*X=B
59  {
60  auto X = Matrix<Number>::random(I,J);
61  auto B = transpose(A)*X;
62  solver.solve(B,'L','T');
63  Precision error = frobenius(X-B)/frobenius(X);
64  myra::out() << " |inv(A^T)*B-X| = " << error << std::endl;
65  REQUIRE(error < tolerance);
66  }
67  // Solve hermitian(A)*X=B
68  {
69  auto X = Matrix<Number>::random(I,J);
70  auto B = hermitian(A)*X;
71  solver.solve(B,'L','H');
72  Precision error = frobenius(X-B)/frobenius(X);
73  myra::out() << " |inv(A^H)*B-X| = " << error << std::endl;
74  REQUIRE(error < tolerance);
75  }
76  // Solve conjugate(A)*X=B
77  {
78  auto X = Matrix<Number>::random(I,J);
79  auto B = conjugate(A)*X;
80  solver.solve(B,'L','C');
81  Precision error = frobenius(X-B)/frobenius(X);
82  myra::out() << " |inv(A^C)*B-X| = " << error << std::endl;
83  REQUIRE(error < tolerance);
84  }
85  // Solve X*A=B
86  {
87  auto X = Matrix<Number>::random(J,I);
88  auto B = X*A;
89  solver.solve(B,'R','N');
90  Precision error = frobenius(X-B)/frobenius(X);
91  myra::out() << " |B*inv(A)-X| = " << error << std::endl;
92  REQUIRE(error < tolerance);
93  }
94  // Solve X*transpose(A)=B
95  {
96  auto X = Matrix<Number>::random(J,I);
97  auto B = X*transpose(A);
98  solver.solve(B,'R','T');
99  Precision error = frobenius(X-B)/frobenius(X);
100  myra::out() << " |B*inv(A^T)-X| = " << error << std::endl;
101  REQUIRE(error < tolerance);
102  }
103  // Solve X*hermitian(A)=B
104  {
105  auto X = Matrix<Number>::random(J,I);
106  auto B = X*hermitian(A);
107  solver.solve(B,'R','H');
108  Precision error = frobenius(X-B)/frobenius(X);
109  myra::out() << " |B*inv(A^H)-X| = " << error << std::endl;
110  REQUIRE(error < tolerance);
111  }
112  // Solve X*conjugate(A)=B
113  {
114  auto X = Matrix<Number>::random(J,I);
115  auto B = X*conjugate(A);
116  solver.solve(B,'R','C');
117  Precision error = frobenius(X-B)/frobenius(X);
118  myra::out() << " |B*inv(A^C)-X| = " << error << std::endl;
119  REQUIRE(error < tolerance);
120  }
121 
122  // Save solver to disk, then solve A*X=B again.
123  {
124  VectorStream inout;
125  solver.write(inout);
126  Solver saved(inout);
127  auto X = Matrix<Number>::random(I,J);
128  auto B = A*X;
129  saved.solve(B,'L','N');
130  Precision error = frobenius(X-B)/frobenius(X);
131  myra::out() << " |inv(A)*B-X| (saved) = " << error << std::endl;
132  REQUIRE(error < tolerance);
133  }
134  }
135 
136 } // namespace
137 
138 ADD_TEST("cCholeskySolver","[dense][solver]")
139  { test<float>(25,14,1.0e-2f); }
140 
141 ADD_TEST("zCholeskySolver","[dense][solver]")
142  { test<double>(82,45,1.0e-10); }
143 
Returns a conjugated copy of a Matrix or Vector. Or, conjugate one inplace.
Tabulates an IxJ matrix. Allows random access, has column major layout to be compatible with BLAS/LAP...
Definition: bdsqr.h:20
Routines for hermitian rank-k updates, a specialized form of Matrix*Matrix multiplication.
Routines for computing Frobenius norms of various algebraic containers.
static Matrix< Number > random(int I, int J)
Generates a random Matrix of specified size.
Definition: Matrix.cpp:353
Wraps a std::vector<char>, presents it as both an InputStream and OutputStream. Useful for hygienic u...
Definition: VectorStream.h:22
Definition: syntax.dox:1
Specialized container for a lower triangular matrix, O(N^2/2) storage. Used by symmetry exploiting ma...
Returns a transposed copy of a Matrix. The inplace version only works on a square operand...
Various utility functions/classes related to scalar Number types.
A stream that serialize/deserializes to std::vector<char> buffer.
General purpose dense matrix container, O(i*j) storage.
A solver suitable for a complex hermitian positive definite Matrix.
Returns a hermitian copy of a Matrix. The inplace version only works on a square operand.
Factors complex hermitian A into L*L&#39;, presents solve methods.
Definition: ZCholeskySolver.h:27
Stores a lower triangular matrix in rectangular packed format.
Definition: conjugate.h:22
Variety of routines all for dense Matrix*Matrix multiplies. Delegates to the BLAS.


Results: [PASS]

std::complex<float>
|inv(A)*B-X| = 0.000104123
|inv(A^T)*B-X| = 7.04116e-05
|inv(A^H)*B-X| = 7.60055e-05
|inv(A^C)*B-X| = 7.6966e-05
|B*inv(A)-X| = 9.24632e-05
|B*inv(A^T)-X| = 7.76659e-05
|B*inv(A^H)-X| = 7.61976e-05
|B*inv(A^C)-X| = 7.70546e-05
|inv(A)*B-X| (saved) = 7.50411e-05


Go back to Summary of /test programs.