MyraMath
Kernel.h
Go to the documentation of this file.
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 
6 #ifndef MYRAMATH_MULTIFRONTAL_RLDLT_KERNEL_H
7 #define MYRAMATH_MULTIFRONTAL_RLDLT_KERNEL_H
8 
16 
17 #include <myramath/io/Streams.h>
19 #include <myramath/io/detail/vector.h>
20 
22 #include <myramath/dense/sytrf.h>
23 #include <myramath/dense/trsm.h>
24 #include <myramath/dense/swaps.h>
25 #include <myramath/dense/detail/nwork.h>
26 
27 #include <stdint.h>
28 
29 namespace myra {
30 
31 // Forward declarations.
32 class InputStream;
33 class OutputStream;
34 template<class Number> class MatrixRange;
35 template<class Number> class LowerMatrix;
36 
38 template<class Precision> class LIBPUBLIC RLDLTKernel
39  {
40  public:
41 
43  explicit RLDLTKernel()
44  { }
45 
48  { }
49 
52  { in >> P_swaps >> Q_swaps >> R >> n_plus >> n_minus; }
53 
55  void write(OutputStream& out) const
56  { out << P_swaps << Q_swaps << R << n_plus << n_minus; }
57 
59  uint64_t factor()
60  {
61  // LDLSwaps<Precision> result = sytrf_inplace(L);
62  LDLSwaps<Precision> result = sytrf_outplace(L);
63  P_swaps = result.P_swaps;
64  Q_swaps = result.Q_swaps;
65  R = result.R;
66  n_plus = result.n_plus;
67  n_minus = result.n_minus;
68  // Return flop count.
69  uint64_t n_work = L.size();
70  return n_work*(n_work+1)*(n_work+2)/6;
71  }
72 
74  // side = Solve by L from the 'L'eft or from std::cout << "exit solveL" << std::endl; the 'R'ight?
75  // op = Apply an operation to L? ('T'ranspose, 'H'ermitian, 'C'onjugate or 'N'othing)
76  uint64_t solveL(const MatrixRange<Precision>& B, char side, char op) const
77  {
78  int N = this->size();
79  // Internally L is decomposed into P'*L*Q', so solving by it always takes a few steps.
80  // Solve by L from the 'L'eft:
81  if (side == 'L')
82  {
83  // Check size.
84  if (B.I != N) throw eprintf("RLDLTKernel::solveL('L'eft), size mismatch B.I != N [%d != %d]", B.I, N);
85  // Since L is real, L^N == L^C
86  if (op == 'N' || op == 'C')
87  {
88  swap_rows(P_swaps,B);
89  uint64_t w = trsm_nwork('L','N',L,B);
90  R.solve(B,'L','N');
91  swap_rows(Q_swaps,B);
92  return w;
93  }
94  // Since L is real, L^T == L^H
95  else if (op == 'T' || op == 'H')
96  {
97  iswap_rows(Q_swaps,B);
98  R.solve(B,'L','T');
99  uint64_t w = trsm_nwork('L','T',L,B);
100  iswap_rows(P_swaps,B);
101  return w;
102  }
103  else throw eprintf("RLDLTKernel::solveL('L'eft), didn't understand op = %c", op);
104  }
105  // Solve by L from the 'R'ight:
106  else if (side == 'R')
107  {
108  // Check size.
109  if (B.J != N) throw eprintf("RLDLTKernel::solveL('R'ight), size mismatch B.J != N [%d != %d]", B.J, N);
110  // Since L is real, L^N == L^C
111  if (op == 'N' || op == 'C')
112  {
113  swap_columns(Q_swaps,B);
114  R.solve(B,'R','N');
115  uint64_t w = trsm_nwork('R','N',L,B);
116  swap_columns(P_swaps,B);
117  return w;
118  }
119  // Since L is real, L^T == L^H
120  else if (op == 'T' || op == 'H')
121  {
122  iswap_columns(P_swaps,B);
123  uint64_t w = trsm_nwork('R','T',L,B);
124  R.solve(B,'R','T');
125  iswap_columns(Q_swaps,B);
126  return w;
127  }
128  else throw eprintf("RLDLTKernel::solveL('R'ight), didn't understand op = %c", op);
129  }
130  else throw eprintf("RLDLTKernel::solveL(), didn't understand side = %c", side);
131  }
132 
134  void solveI(const MatrixRange<Precision>& B, char side) const
135  {
136  if (side == 'L')
137  B.bottom(n_minus) *= -Precision(1);
138  else if (side == 'R')
139  B.right(n_minus) *= -Precision(1);
140  else throw eprintf("RLDLTKernel::solveI(), didn't understand side = %c", side);
141  }
142 
144  std::pair<int,int> inertia() const
145  { return std::pair<int,int>(n_plus, n_minus); }
146 
148  int size() const
149  { return L.size(); }
150 
151  private:
152 
153  // Points to underlying data.
155 
156  // For applying permutation P.
157  std::vector<int> P_swaps;
158 
159  // For applying permutation Q.
160  std::vector<int> Q_swaps;
161 
162  // For applying pivot rotations R.
164 
165  // Encodes inertia.
166  int n_plus;
167  int n_minus;
168 
169  };
170 
172 template<class Precision> class ReflectNumber< RLDLTKernel<Precision> >
173  { public: typedef Precision type; };
174 
175 } // namespace myra
176 
177 #endif
Factors A into L*L&#39;, presents solve methods.
Definition: Kernel.h:38
Reflects Number trait for a Container, containers of Numbers (Matrix&#39;s, Vector&#39;s, etc) should special...
Definition: Number.h:55
RLDLTKernel()
Default constructor, initializes to 0 size.
Definition: Kernel.h:43
Returns a std::runtime_error() whose message has been populated using printf()-style formatting...
int J
---------— Data members, all public ----------------—
Definition: MatrixRange.h:43
int size() const
Size inspector.
Definition: Kernel.h:148
int I
---------— Data members, all public ----------------—
Definition: MatrixRange.h:42
uint64_t factor()
Factors A = L*I*L&#39;.
Definition: Kernel.h:59
uint64_t solveL(const MatrixRange< Precision > &B, char side, char op) const
Solves op(L)*X=B or X*op(L)=B, overwrites B with X.
Definition: Kernel.h:76
RLDLTKernel(LowerMatrixRange< Precision > &A, InputStream &in)
Constructs from an InputStream, after seating reference to L.
Definition: Kernel.h:51
ReaderWriter<T>, encapsulates a read()/write() pair for type T.
Range construct for a lower triangular matrix stored in rectangular packed format.
Definition: syntax.dox:1
void solveI(const MatrixRange< Precision > &B, char side) const
Solves I*X=B or X*I=B, overwrites B with X.
Definition: Kernel.h:134
Routines for backsolving by a triangular Matrix or LowerMatrix.
Abstraction layer, serializable objects write themselves to these.
Definition: Streams.h:39
LDL&#39; decompositions for real symmetric Matrix A (indefinite is fine).
RLDLTKernel(LowerMatrixRange< Precision > &A)
Seats reference to L, to be factor()&#39;d later.
Definition: Kernel.h:47
Various utility functions/classes related to scalar Number types.
Routines related to swap sequences, often used during pivoting.
void write(OutputStream &out) const
Writes to an OutputStream.
Definition: Kernel.h:55
Represents a mutable MatrixRange.
Definition: conjugate.h:26
Abstraction layer, deserializable objects read themselves from these.
Definition: Streams.h:47
std::pair< int, int > inertia() const
Returns inertia I, (n_plus, n_minus). Useful for schur downdates.
Definition: Kernel.h:144
MatrixRange< Number > bottom(int i) const
Returns the i bottommost rows, this(I-i:I,:)
Definition: MatrixRange.cpp:186
MatrixRange< Number > right(int j) const
Returns the j rightmost columns, this(:,J-j:J)
Definition: MatrixRange.cpp:235
Bases classes for binary input/output streams.
Return type of sytrf_inplace() and hetrf_inplace(), holds pivoting metadata.
Definition: LDLSwaps.h:21