API Documentation
Loading...
Searching...
No Matches
LUDecomposition.hpp
Go to the documentation of this file.
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{
36 /**--------------------------------------------------------------------------------------------------
37 \brief Logic for performing LU Decomposition https://en.wikipedia.org/wiki/LU_decomposition
38 **/
39 template<class t_type, uint01 t_m, uint01 t_n>
41 {
42 public:
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
115 /** Is the matrix nonsingular?
116 @return true if U, and hence A, is nonsingular.
117 */
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
129 /** Return lower triangular factor
130 @return L
131 */
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
151 /** Return upper triangular factor
152 @return U
153 */
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
171 /** Return pivot permutation vector
172 @return piv
173 */
174 template<class t_pivot_type = sint04>
176 {
177 return piv.template as<t_m, t_pivot_type>();
178 }
179
180 /** Determinant
181 @return det(A)
182 @exception IllegalArgumentException Matrix must be square
183 */
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
194 /** Solve A*X = B
195 @param B A Matrix with as many rows as A and any number of columns.
196 @return X so that L*U*X = B(piv,:)
197 @exception IllegalArgumentException Matrix row dimensions must agree.
198 @exception RuntimeException Matrix is singular.
199 */
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; !IsInvalid(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
236 /** Row and column dimensions, and pivot sign.
237 @serial column dimension.
238 @serial row dimension.
239 @serial pivot sign.
240 */
241 sint04 pivsign;
242
243 /** Internal storage of pivot vector.
244 @serial pivot vector.
245 */
247 };
248}
249
#define lib_assert(expression, message)
Definition LibAssert.h:61
Logic for performing LU Decomposition https://en.wikipedia.org/wiki/LU_decomposition.
Definition LUDecomposition.hpp:41
Matrix< t_type, t_m, t_nx > solve(const Matrix< t_type, t_m, t_nx > &B)
Definition LUDecomposition.hpp:201
LUDecomposition(const Matrix< t_type, t_m, t_n > &A)
Definition LUDecomposition.hpp:43
bool isNonsingular() const
Definition LUDecomposition.hpp:119
Matrix< t_type, t_m, t_n > getU() const
Definition LUDecomposition.hpp:155
Vector< t_m, t_pivot_type > getPivot() const
Definition LUDecomposition.hpp:175
t_type det() const
Definition LUDecomposition.hpp:185
Matrix< t_type, t_m, t_n > getL() const
Definition LUDecomposition.hpp:133
Definition Matrix.hpp:176
A fixed-size array with better performance compared to dynamic containers.
Definition Vector.hpp:60
Definition ACIColor.h:37
int32_t sint04
-Defines an alias representing a 4 byte, signed integer. -Can represent exact integer values -2147483...
Definition BaseValues.hpp:64
constexpr bool IsInvalid(const t_type &value)
Query if 'value' is valid or invalid. Invalid values should return invalid if used for calculations o...
Definition BaseFunctions.hpp:170
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:80
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:375
constexpr Angle< t_angle_type > abs(const Angle< t_angle_type > &value)
Changes an input with a negative sign, to a positive sign.
Definition AngleFunctions.h:645
@ B
Definition BaseValues.hpp:170
@ A
Definition BaseValues.hpp:168
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...
Definition BaseFunctions.hpp:56