NDEVR
API Documentation
LUDecomposition.hpp
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: LUDecomposition
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/Matrix.h>
34namespace NDEVR
35{
39 template<class t_type, uint01 t_m, uint01 t_n>
40 class LUDecomposition
41 {
42 public:
43 LUDecomposition(const Matrix<t_type, t_m, t_n>& A)
44 : LU(A)
45 {
46
47 // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
48
49 for (uint01 i = 0; i < t_m; i++)
50 {
51 piv[i] = i;
52 }
53 pivsign = 1;
54 Vector<t_m, t_type> LUrowi(0.0);
55 Vector<t_m, t_type> LUcolj(0.0);
56
57 // Outer loop.
58
59 for (uint01 j = 0; j < t_n; j++)
60 {
61
62 // Make a copy of the j-th column to localize references.
63 for (uint01 i = 0; i < t_m; i++)
64 LUcolj[i] = LU[i][j];
65
66 // Apply previous transformations.
67
68 for (uint01 i = 0; i < t_m; i++)
69 {
70 LUrowi = LU[i];
71
72 // Most of the time is spent in the following dot product.
73
74 uint01 kmax = getMin(i, j);
75 t_type s(0);
76 for (uint01 k = 0; k < kmax; k++)
77 s += LUrowi[k] * LUcolj[k];
78
79 LUrowi[j] = LUcolj[i] -= s;
80 }
81
82 // Find pivot and exchange if necessary.
83
84 uint01 p = j;
85 for (uint01 i = j + 1; i < t_m; i++)
86 {
87 if (abs(LUcolj[i]) > abs(LUcolj[p]))
88 p = i;
89 }
90 if (p != j)
91 {
92 for (uint01 k = 0; k < t_n; k++)
93 {
94 std::swap(LU[p][k], LU[j][k]);
95 }
96 std::swap(piv[p], piv[j]);
97 pivsign = -pivsign;
98 }
99
100 // Compute multipliers.
101
102 if (j < t_m && LU[j][j] != 0.0)
103 {
104 for (uint01 i = j + 1; i < t_m; i++) {
105 LU[i][j] /= LU[j][j];
106 }
107 }
108 }
109 }
110
111 /* ------------------------
112 Public Methods
113 * ------------------------ */
114
118
119 bool isNonsingular() const
120 {
121 for (uint01 j = 0; j < t_n; j++)
122 {
123 if (LU[j][j] == 0)
124 return false;
125 }
126 return true;
127 }
128
132
134 {
136 for (uint01 i = 0; i < t_m; i++)
137 {
138 for (uint01 j = 0; j < t_n; j++)
139 {
140 if (i > j)
141 mat[i][j] = LU[i][j];
142 else if (i == j)
143 mat[i][j] = t_type(1);
144 else
145 mat[i][j] = t_type(0);
146 }
147 }
148 return mat;
149 }
150
154
156 {
158 for (uint01 i = 0; i < t_n; i++)
159 {
160 for (uint01 j = 0; j < t_n; j++)
161 {
162 if (i <= j)
163 mat[i][j] = LU[i][j];
164 else
165 mat[i][j] = t_type(0);
166 }
167 }
168 return mat;
169 }
170
174 template<class t_pivot_type = sint04>
176 {
177 return piv.template as<t_m, t_pivot_type>();
178 }
179
184
185 t_type det() const
186 {
187 static_assert(t_m == t_n, "Matrix must be square.");
188 t_type d = cast<t_type>(pivsign);
189 for (uint01 j = 0; j < t_n; j++)
190 d *= LU[j][j];
191 return d;
192 }
193
200 template<uint01 t_nx>
202 {
203 lib_assert(isNonsingular(), "Matrix cannot be singular.");
204
205 // Copy right hand side with pivoting
206 Matrix<t_type, t_m, t_nx> mat = B.template subMatrix<0, t_nx - 1>(piv);
207
208 // Solve L*Y = B(piv,:)
209 for (uint01 k = 0; k < t_n; k++)
210 {
211 for (uint01 i = k + 1; i < t_n; i++)
212 {
213 for (uint01 j = 0; j < t_nx; j++)
214 {
215 mat[i][j] -= mat[k][j] * LU[i][k];
216 }
217 }
218 }
219 // Solve U*X = Y;
220 for (uint01 k = t_n - 1; IsValid(k); k--)
221 {
222 for (uint01 j = 0; j < t_nx; j++)
223 mat[k][j] /= LU[k][k];
224 for (uint01 i = 0; i < k; i++)
225 {
226 for (uint01 j = 0; j < t_nx; j++)
227 mat[i][j] -= mat[k][j] * LU[i][k];
228 }
229 }
230 return mat;
231 }
232
233 private:
235
241 sint04 pivsign;
242
247 };
248}
249
Matrix< t_type, t_m, t_n > getL() const
Return lower triangular factor.
t_type det() const
Determinant.
Vector< t_m, t_pivot_type > getPivot() const
Return pivot permutation vector.
Matrix< t_type, t_m, t_nx > solve(const Matrix< t_type, t_m, t_nx > &B)
Solve A*X = B.
bool isNonsingular() const
Is the matrix nonsingular?
Matrix< t_type, t_m, t_n > getU() const
Return upper triangular factor.
Templated logic for doing matrix multiplication.
Definition Matrix.hpp:182
A fixed-size array with N dimensions used as the basis for geometric and mathematical types.
Definition Vector.hpp:62
The primary namespace for the NDEVR SDK.
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator Author: Tyler Parke Date: 2017-11-05...
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
Definition Angle.h:398
constexpr Angle< t_angle_type > abs(const Angle< t_angle_type > &value)
Changes an input with a negative sign, to a positive sign.
int32_t sint04
-Defines an alias representing a 4 byte, signed integer.
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408