MyraMath
sLUSolver


Source: tests/dense/LUSolver.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>
22 
23 // Solver class under test.
25 
26 // Serialization testing.
28 
29 // Reporting.
30 #include <tests/myratest.h>
31 
32 using namespace myra;
33 
34 namespace {
35 
36 template<class Number> void test(int I, int J, typename ReflectPrecision<Number>::type tolerance)
37  {
38  typedef typename ReflectPrecision<Number>::type Precision;
39  myra::out() << typestring<Number>() << std::endl;
40  // Construct random matrix and a solver for it.
41  const auto A = Matrix<Number>::random(I,I);
42  typedef LUSolver<Number> Solver;
43  Solver solver(A);
44  // Total of 8 solve() variations to validiate, side['L',R'] x op['N','T','H','C']
45  // Solve A*X=B
46  {
47  auto X = Matrix<Number>::random(I,J);
48  auto B = A*X;
49  solver.solve(B,'L','N');
50  Precision error = frobenius(B-X)/frobenius(X);
51  myra::out() << " |inv(A)*B-X| = " << error << std::endl;
52  REQUIRE(error < tolerance);
53  }
54  // Solve transpose(A)*X=B
55  {
56  auto X = Matrix<Number>::random(I,J);
57  auto B = transpose(A)*X;
58  solver.solve(B,'L','T');
59  Precision error = frobenius(B-X)/frobenius(X);
60  myra::out() << " |inv(A^T)*B-X| = " << error << std::endl;
61  REQUIRE(error < tolerance);
62  }
63  // Solve hermitian(A)*X=B
64  {
65  auto X = Matrix<Number>::random(I,J);
66  auto B = hermitian(A)*X;
67  solver.solve(B,'L','H');
68  Precision error = frobenius(B-X)/frobenius(X);
69  myra::out() << " |inv(A^H)*B-X| = " << error << std::endl;
70  REQUIRE(error < tolerance);
71  }
72  // Solve conjugate(A)*X=B
73  {
74  auto X = Matrix<Number>::random(I,J);
75  auto B = conjugate(A)*X;
76  solver.solve(B,'L','C');
77  Precision error = frobenius(B-X)/frobenius(X);
78  myra::out() << " |inv(A^C)*B-X| = " << error << std::endl;
79  REQUIRE(error < tolerance);
80  }
81  // Solve X*A=B
82  {
83  auto X = Matrix<Number>::random(J,I);
84  auto B = X*A;
85  solver.solve(B,'R','N');
86  Precision error = frobenius(B-X)/frobenius(X);
87  myra::out() << " |B*inv(A)-X| = " << error << std::endl;
88  REQUIRE(error < tolerance);
89  }
90  // Solve X*transpose(A)=B
91  {
92  auto X = Matrix<Number>::random(J,I);
93  auto B = X*transpose(A);
94  solver.solve(B,'R','T');
95  Precision error = frobenius(B-X)/frobenius(X);
96  myra::out() << " |B*inv(A^T)-X| = " << error << std::endl;
97  REQUIRE(error < tolerance);
98  }
99  // Solve X*hermitian(A)=B
100  {
101  auto X = Matrix<Number>::random(J,I);
102  auto B = X*hermitian(A);
103  solver.solve(B,'R','H');
104  Precision error = frobenius(B-X)/frobenius(X);
105  myra::out() << " |B*inv(A^H)-X| = " << error << std::endl;
106  REQUIRE(error < tolerance);
107  }
108  // Solve X*conjugate(A)=B
109  {
110  auto X = Matrix<Number>::random(J,I);
111  auto B = X*conjugate(A);
112  solver.solve(B,'R','C');
113  Precision error = frobenius(B-X)/frobenius(X);
114  myra::out() << " |B*inv(A^C)-X| = " << error << std::endl;
115  REQUIRE(error < tolerance);
116  }
117  // Save solver to disk, then solve A*X=B again.
118  {
119  VectorStream inout;
120  solver.write(inout);
121  Solver saved(inout);
122  auto X = Matrix<Number>::random(I,J);
123  auto B = A*X;
124  saved.solve(B,'L','N');
125  Precision error = frobenius(B-X)/frobenius(X);
126  myra::out() << " |inv(A)*B-X| = " << error << std::endl;
127  REQUIRE(error < tolerance);
128  }
129  }
130 
131 } // namespace
132 
133 ADD_TEST("sLUSolver","[dense][solver]")
134  { test<NumberS>(200,120,1.0e-2f); }
135 
136 ADD_TEST("dLUSolver","[dense][solver]")
137  { test<NumberD>(200,120,1.0e-10); }
138 
139 ADD_TEST("cLUSolver","[dense][solver]")
140  { test<NumberC>(200,120,1.0e-2f); }
141 
142 ADD_TEST("zLUSolver","[dense][solver]")
143  { test<NumberZ>(200,120,1.0e-10); }
144 
Returns a conjugated copy of a Matrix or Vector. Or, conjugate one inplace.
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
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.
Reflects Precision trait for a Number, scalar Number types should specialize it.
Definition: Number.h:33
General purpose linear solver, no symmetry/definiteness assumptions upon A (just square) ...
Factors a square matrix A into L*U, presents solve methods.
Definition: LUSolver.h:30
Returns a hermitian copy of a Matrix. The inplace version only works on a square operand.
Variety of routines all for dense Matrix*Matrix multiplies. Delegates to the BLAS.
Interface class for representing subranges of contiguous int&#39;s.


Results: [PASS]

float
|inv(A)*B-X| = 3.68887e-05
|inv(A^T)*B-X| = 3.32098e-05
|inv(A^H)*B-X| = 3.51799e-05
|inv(A^C)*B-X| = 3.56567e-05
|B*inv(A)-X| = 3.65621e-05
|B*inv(A^T)-X| = 3.51074e-05
|B*inv(A^H)-X| = 3.84602e-05
|B*inv(A^C)-X| = 3.20167e-05
|inv(A)*B-X| = 3.6994e-05


Go back to Summary of /test programs.