1 | ///
|
---|
2 | /// This file is part of ILNumerics Community Edition.
|
---|
3 | ///
|
---|
4 | /// ILNumerics Community Edition - high performance computing for applications.
|
---|
5 | /// Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
|
---|
6 | ///
|
---|
7 | /// ILNumerics Community Edition is free software: you can redistribute it and/or modify
|
---|
8 | /// it under the terms of the GNU General Public License version 3 as published by
|
---|
9 | /// the Free Software Foundation.
|
---|
10 | ///
|
---|
11 | /// ILNumerics Community Edition is distributed in the hope that it will be useful,
|
---|
12 | /// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | /// GNU General Public License for more details.
|
---|
15 | ///
|
---|
16 | /// You should have received a copy of the GNU General Public License
|
---|
17 | /// along with ILNumerics Community Edition. See the file License.txt in the root
|
---|
18 | /// of your distribution package. If not, see <http://www.gnu.org/licenses/>.
|
---|
19 | ///
|
---|
20 | /// In addition this software uses the following components and/or licenses:
|
---|
21 | ///
|
---|
22 | /// =================================================================================
|
---|
23 | /// The Open Toolkit Library License
|
---|
24 | ///
|
---|
25 | /// Copyright (c) 2006 - 2009 the Open Toolkit library.
|
---|
26 | ///
|
---|
27 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
|
---|
28 | /// of this software and associated documentation files (the "Software"), to deal
|
---|
29 | /// in the Software without restriction, including without limitation the rights to
|
---|
30 | /// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
---|
31 | /// the Software, and to permit persons to whom the Software is furnished to do
|
---|
32 | /// so, subject to the following conditions:
|
---|
33 | ///
|
---|
34 | /// The above copyright notice and this permission notice shall be included in all
|
---|
35 | /// copies or substantial portions of the Software.
|
---|
36 | ///
|
---|
37 | /// =================================================================================
|
---|
38 | ///
|
---|
39 |
|
---|
40 | using System;
|
---|
41 | using System.Collections.Generic;
|
---|
42 | using System.Text;
|
---|
43 | using ILNumerics.Storage;
|
---|
44 | using ILNumerics.Misc;
|
---|
45 | using ILNumerics.Exceptions;
|
---|
46 |
|
---|
47 |
|
---|
48 |
|
---|
49 | namespace ILNumerics {
|
---|
50 | public partial class ILMath {
|
---|
51 |
|
---|
52 | |
---|
53 | /// <summary>
|
---|
54 | /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
|
---|
55 | /// </summary>
|
---|
56 | /// <param name="A">Input matrix. Size [m x n]</param>
|
---|
57 | /// <returns>Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]</returns>
|
---|
58 | /// <remarks><para>The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.</para>
|
---|
59 | /// <code>
|
---|
60 | /// :'''''''|
|
---|
61 | /// |1 \ |
|
---|
62 | /// | 1 \ R |
|
---|
63 | /// | 1 \ |
|
---|
64 | /// | L 1 \ |
|
---|
65 | /// | 1 \|
|
---|
66 | /// '''''''''
|
---|
67 | /// </code>
|
---|
68 | /// <para>This overload is mainly needed for further operations via Lapack libraries. If you need the
|
---|
69 | /// L and U matrices directly, you'd better use one of the overloaded versions
|
---|
70 | /// <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
71 | /// or <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> instead.</para>
|
---|
72 | /// <para>The matrix L will be a solid ILArray.</para>
|
---|
73 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
74 | /// </remarks>
|
---|
75 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
|
---|
76 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
77 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
78 | public static ILRetArray< double > lu(ILInArray<double> A) {
|
---|
79 | ILArray< double > U = null;
|
---|
80 | ILArray< double > P = null;
|
---|
81 | return lu(A, U, P);
|
---|
82 | }
|
---|
83 | /// <summary>
|
---|
84 | /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
|
---|
85 | /// </summary>
|
---|
86 | /// <param name="A">Input matrix to be decomposed. Size [m x n]</param>
|
---|
87 | /// <param name="U">[Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.</param>
|
---|
88 | /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
|
---|
89 | /// <remarks>A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
|
---|
90 | /// <para>L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order
|
---|
91 | /// to fullfill <c>ILMath.multiply(L,U) == A</c></para>
|
---|
92 | /// <example> <code>
|
---|
93 | /// //we construct a matrix X:
|
---|
94 | /// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
|
---|
95 | /// // now X.ToString() will give something like:
|
---|
96 | /// // {<Double> 63238509 [3x3] Ref(2)
|
---|
97 | /// //(:,:)
|
---|
98 | /// // 1,00000 2,00000 3,00000
|
---|
99 | /// // 4,00000 4,00000 4,00000
|
---|
100 | /// // 5,00000 6,00000 7,00000
|
---|
101 | /// //}
|
---|
102 | /// // construct reference on U and call the decomposition
|
---|
103 | /// ILArray<double> U = new ILArray<double>.empty();
|
---|
104 | /// ILArray<double> L = ILMath.lu(X, ref U);
|
---|
105 | ///
|
---|
106 | /// // L.ToString() is now:
|
---|
107 | /// // {<Double> 19634871 [3x3] Phys.
|
---|
108 | /// //(:,:)
|
---|
109 | /// // 0,20000 -1,00000 1,00000
|
---|
110 | /// // 0,80000 1,00000 0,00000
|
---|
111 | /// // 1,00000 0,00000 0,00000
|
---|
112 | /// //}
|
---|
113 | /// // and U is now:
|
---|
114 | /// //{<Double> 22584602 [3x3] Phys.
|
---|
115 | /// //(:,:)
|
---|
116 | /// // 5,00000 6,00000 7,00000
|
---|
117 | /// // 0,00000 -0,80000 -1,60000
|
---|
118 | /// // 0,00000 0,00000 0,00000
|
---|
119 | /// //}
|
---|
120 | /// </code>
|
---|
121 | /// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf. </example>
|
---|
122 | /// <para>In order to access the permutation of L, one can use the overloaded version <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> which returns the permuation matrix P also.</para>
|
---|
123 | /// <para>All of the matrices U and L returned will be solid ILArrays.</para>
|
---|
124 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
125 | /// </remarks>
|
---|
126 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
|
---|
127 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
|
---|
128 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
129 | public static ILRetArray< double> lu(ILInArray<double> A, ILOutArray<double> U) {
|
---|
130 | return lu(A,U,null);
|
---|
131 | }
|
---|
132 | /// <summary>
|
---|
133 | /// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also.
|
---|
134 | /// </summary>
|
---|
135 | /// <param name="A">Input matrix. Size [m x n]</param>
|
---|
136 | /// <param name="U">[Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.</param>
|
---|
137 | /// <param name="P">[Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.</param>
|
---|
138 | /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
|
---|
139 | /// <remarks>A is decomposed into L and U, so that the equation
|
---|
140 | /// <c>ILMath.multiply(L,U) == ILMath.multiply(P,A)</c>
|
---|
141 | /// will hold except for round off error.
|
---|
142 | /// <para>L and U will be true lower triangular matrices.</para>
|
---|
143 | /// <example> <code>
|
---|
144 | /// //Let's construct a matrix X:
|
---|
145 | /// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
|
---|
146 | /// // now X.ToString() will give something like:
|
---|
147 | /// // {<Double> 63238509 [3x3] Ref(2)
|
---|
148 | /// //(:,:)
|
---|
149 | /// // 1,00000 2,00000 3,00000
|
---|
150 | /// // 4,00000 4,00000 4,00000
|
---|
151 | /// // 5,00000 6,00000 7,00000
|
---|
152 | /// //}
|
---|
153 | /// // construct references on U and P and call the decomposition
|
---|
154 | /// ILArray<double> U = new ILArray<double>.empty();
|
---|
155 | /// ILArray<double> P = new ILArray<double>.empty();
|
---|
156 | /// ILArray<double> L = ILMath.lu(X, ref U, ref P);
|
---|
157 | ///
|
---|
158 | /// // L.ToString() is now:
|
---|
159 | /// // {<Double> 19634871 [3x3] Phys.
|
---|
160 | /// //(:,:)
|
---|
161 | /// // 1,00000 0,00000 0,00000
|
---|
162 | /// // 0,80000 1,00000 0,00000
|
---|
163 | /// // 0,20000 -1,00000 1,00000
|
---|
164 | /// //}
|
---|
165 | /// // U is now:
|
---|
166 | /// //{<Double> 22584602 [3x3] Phys.
|
---|
167 | /// //(:,:)
|
---|
168 | /// // 5,00000 6,00000 7,00000
|
---|
169 | /// // 0,00000 -0,80000 -1,60000
|
---|
170 | /// // 0,00000 0,00000 0,00000
|
---|
171 | /// //}
|
---|
172 | /// // and P is:
|
---|
173 | /// //{<Double> 2192437 [3x3] Phys.
|
---|
174 | /// //(:,:)
|
---|
175 | /// // 0,00000 0,00000 1,00000
|
---|
176 | /// // 0,00000 1,00000 0,00000
|
---|
177 | /// // 1,00000 0,00000 0,00000
|
---|
178 | /// //}
|
---|
179 | /// </code>
|
---|
180 | /// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
|
---|
181 | /// <code>
|
---|
182 | /// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
|
---|
183 | /// // will give:
|
---|
184 | /// //{<Double> 59192235 [3x3] Phys.
|
---|
185 | /// //(:,:)
|
---|
186 | /// // 0,00000 0,00000 0,00000
|
---|
187 | /// // 0,00000 0,00000 0,00000
|
---|
188 | /// // 0,00000 0,00000 0,00000
|
---|
189 | /// //}
|
---|
190 | /// </code>
|
---|
191 | /// </example>
|
---|
192 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
193 | /// <para>All of the matrices U,L,P returned will be solid ILArrays.</para>
|
---|
194 | /// </remarks>
|
---|
195 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
|
---|
196 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
197 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
198 | public static ILRetArray< double> lu(ILInArray<double> A, ILOutArray<double> U
|
---|
199 | , ILOutArray< double> P) {
|
---|
200 | using (ILScope.Enter(A)) {
|
---|
201 | if (!A.IsMatrix)
|
---|
202 | throw new ILArgumentSizeException("lu is defined for matrices only!");
|
---|
203 | int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
|
---|
204 | ILArray< double> L = A.C;
|
---|
205 | int[] pivInd = ILMemoryPool.Pool.New<int>(minMN);
|
---|
206 | /*!HC:lapack_*getrf*/
|
---|
207 | Lapack.dgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
|
---|
208 | if (info < 0) {
|
---|
209 | ILMemoryPool.Pool.Free(pivInd);
|
---|
210 | throw new ILArgumentException("invalid parameter");
|
---|
211 | //} else if (info > 0) {
|
---|
212 | // // singular diagonal entry found
|
---|
213 |
|
---|
214 | } else {
|
---|
215 | // completed successfuly
|
---|
216 | if (!Object.Equals(U, null)) {
|
---|
217 | if (!Object.Equals(P, null)) {
|
---|
218 | pivInd = perm2indicesForward(pivInd);
|
---|
219 | U.a = copyUpperTriangle<double>(L, minMN, n);
|
---|
220 | L.a = copyLowerTriangle<double>(L, m, minMN, 1);
|
---|
221 | P.a = zeros< double>(new ILSize(minMN, minMN));
|
---|
222 | // construct permutation matrix P
|
---|
223 | for (int r = 0; r < m; r++) {
|
---|
224 | P[r, pivInd[r]] = 1.0;
|
---|
225 | }
|
---|
226 | } else {
|
---|
227 | pivInd = perm2indicesBackward(pivInd);
|
---|
228 | U.a = copyUpperTriangle<double>(L, minMN, n);
|
---|
229 | L.a = copyLowerTrianglePerm< double>(L, m, minMN, 1, pivInd);
|
---|
230 | }
|
---|
231 | }
|
---|
232 | }
|
---|
233 | ILMemoryPool.Pool.Free(pivInd);
|
---|
234 | return L;
|
---|
235 | }
|
---|
236 | }
|
---|
237 | |
---|
238 | #region HYCALPER AUTO GENERATED CODE
|
---|
239 | |
---|
240 | /// <summary>
|
---|
241 | /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
|
---|
242 | /// </summary>
|
---|
243 | /// <param name="A">Input matrix. Size [m x n]</param>
|
---|
244 | /// <returns>Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]</returns>
|
---|
245 | /// <remarks><para>The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.</para>
|
---|
246 | /// <code>
|
---|
247 | /// :'''''''|
|
---|
248 | /// |1 \ |
|
---|
249 | /// | 1 \ R |
|
---|
250 | /// | 1 \ |
|
---|
251 | /// | L 1 \ |
|
---|
252 | /// | 1 \|
|
---|
253 | /// '''''''''
|
---|
254 | /// </code>
|
---|
255 | /// <para>This overload is mainly needed for further operations via Lapack libraries. If you need the
|
---|
256 | /// L and U matrices directly, you'd better use one of the overloaded versions
|
---|
257 | /// <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
258 | /// or <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> instead.</para>
|
---|
259 | /// <para>The matrix L will be a solid ILArray.</para>
|
---|
260 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
261 | /// </remarks>
|
---|
262 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
|
---|
263 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
264 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
265 | public static ILRetArray< float > lu(ILInArray<float> A) {
|
---|
266 | ILArray< float > U = null;
|
---|
267 | ILArray< float > P = null;
|
---|
268 | return lu(A, U, P);
|
---|
269 | }
|
---|
270 | /// <summary>
|
---|
271 | /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
|
---|
272 | /// </summary>
|
---|
273 | /// <param name="A">Input matrix to be decomposed. Size [m x n]</param>
|
---|
274 | /// <param name="U">[Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.</param>
|
---|
275 | /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
|
---|
276 | /// <remarks>A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
|
---|
277 | /// <para>L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order
|
---|
278 | /// to fullfill <c>ILMath.multiply(L,U) == A</c></para>
|
---|
279 | /// <example> <code>
|
---|
280 | /// //we construct a matrix X:
|
---|
281 | /// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
|
---|
282 | /// // now X.ToString() will give something like:
|
---|
283 | /// // {<Double> 63238509 [3x3] Ref(2)
|
---|
284 | /// //(:,:)
|
---|
285 | /// // 1,00000 2,00000 3,00000
|
---|
286 | /// // 4,00000 4,00000 4,00000
|
---|
287 | /// // 5,00000 6,00000 7,00000
|
---|
288 | /// //}
|
---|
289 | /// // construct reference on U and call the decomposition
|
---|
290 | /// ILArray<double> U = new ILArray<double>.empty();
|
---|
291 | /// ILArray<double> L = ILMath.lu(X, ref U);
|
---|
292 | ///
|
---|
293 | /// // L.ToString() is now:
|
---|
294 | /// // {<Double> 19634871 [3x3] Phys.
|
---|
295 | /// //(:,:)
|
---|
296 | /// // 0,20000 -1,00000 1,00000
|
---|
297 | /// // 0,80000 1,00000 0,00000
|
---|
298 | /// // 1,00000 0,00000 0,00000
|
---|
299 | /// //}
|
---|
300 | /// // and U is now:
|
---|
301 | /// //{<Double> 22584602 [3x3] Phys.
|
---|
302 | /// //(:,:)
|
---|
303 | /// // 5,00000 6,00000 7,00000
|
---|
304 | /// // 0,00000 -0,80000 -1,60000
|
---|
305 | /// // 0,00000 0,00000 0,00000
|
---|
306 | /// //}
|
---|
307 | /// </code>
|
---|
308 | /// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf. </example>
|
---|
309 | /// <para>In order to access the permutation of L, one can use the overloaded version <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> which returns the permuation matrix P also.</para>
|
---|
310 | /// <para>All of the matrices U and L returned will be solid ILArrays.</para>
|
---|
311 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
312 | /// </remarks>
|
---|
313 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
|
---|
314 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
|
---|
315 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
316 | public static ILRetArray< float> lu(ILInArray<float> A, ILOutArray<float> U) {
|
---|
317 | return lu(A,U,null);
|
---|
318 | }
|
---|
319 | /// <summary>
|
---|
320 | /// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also.
|
---|
321 | /// </summary>
|
---|
322 | /// <param name="A">Input matrix. Size [m x n]</param>
|
---|
323 | /// <param name="U">[Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.</param>
|
---|
324 | /// <param name="P">[Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.</param>
|
---|
325 | /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
|
---|
326 | /// <remarks>A is decomposed into L and U, so that the equation
|
---|
327 | /// <c>ILMath.multiply(L,U) == ILMath.multiply(P,A)</c>
|
---|
328 | /// will hold except for round off error.
|
---|
329 | /// <para>L and U will be true lower triangular matrices.</para>
|
---|
330 | /// <example> <code>
|
---|
331 | /// //Let's construct a matrix X:
|
---|
332 | /// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
|
---|
333 | /// // now X.ToString() will give something like:
|
---|
334 | /// // {<Double> 63238509 [3x3] Ref(2)
|
---|
335 | /// //(:,:)
|
---|
336 | /// // 1,00000 2,00000 3,00000
|
---|
337 | /// // 4,00000 4,00000 4,00000
|
---|
338 | /// // 5,00000 6,00000 7,00000
|
---|
339 | /// //}
|
---|
340 | /// // construct references on U and P and call the decomposition
|
---|
341 | /// ILArray<double> U = new ILArray<double>.empty();
|
---|
342 | /// ILArray<double> P = new ILArray<double>.empty();
|
---|
343 | /// ILArray<double> L = ILMath.lu(X, ref U, ref P);
|
---|
344 | ///
|
---|
345 | /// // L.ToString() is now:
|
---|
346 | /// // {<Double> 19634871 [3x3] Phys.
|
---|
347 | /// //(:,:)
|
---|
348 | /// // 1,00000 0,00000 0,00000
|
---|
349 | /// // 0,80000 1,00000 0,00000
|
---|
350 | /// // 0,20000 -1,00000 1,00000
|
---|
351 | /// //}
|
---|
352 | /// // U is now:
|
---|
353 | /// //{<Double> 22584602 [3x3] Phys.
|
---|
354 | /// //(:,:)
|
---|
355 | /// // 5,00000 6,00000 7,00000
|
---|
356 | /// // 0,00000 -0,80000 -1,60000
|
---|
357 | /// // 0,00000 0,00000 0,00000
|
---|
358 | /// //}
|
---|
359 | /// // and P is:
|
---|
360 | /// //{<Double> 2192437 [3x3] Phys.
|
---|
361 | /// //(:,:)
|
---|
362 | /// // 0,00000 0,00000 1,00000
|
---|
363 | /// // 0,00000 1,00000 0,00000
|
---|
364 | /// // 1,00000 0,00000 0,00000
|
---|
365 | /// //}
|
---|
366 | /// </code>
|
---|
367 | /// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
|
---|
368 | /// <code>
|
---|
369 | /// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
|
---|
370 | /// // will give:
|
---|
371 | /// //{<Double> 59192235 [3x3] Phys.
|
---|
372 | /// //(:,:)
|
---|
373 | /// // 0,00000 0,00000 0,00000
|
---|
374 | /// // 0,00000 0,00000 0,00000
|
---|
375 | /// // 0,00000 0,00000 0,00000
|
---|
376 | /// //}
|
---|
377 | /// </code>
|
---|
378 | /// </example>
|
---|
379 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
380 | /// <para>All of the matrices U,L,P returned will be solid ILArrays.</para>
|
---|
381 | /// </remarks>
|
---|
382 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
|
---|
383 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
384 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
385 | public static ILRetArray< float> lu(ILInArray<float> A, ILOutArray<float> U
|
---|
386 | , ILOutArray< float> P) {
|
---|
387 | using (ILScope.Enter(A)) {
|
---|
388 | if (!A.IsMatrix)
|
---|
389 | throw new ILArgumentSizeException("lu is defined for matrices only!");
|
---|
390 | int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
|
---|
391 | ILArray< float> L = A.C;
|
---|
392 | int[] pivInd = ILMemoryPool.Pool.New<int>(minMN);
|
---|
393 |
|
---|
394 | Lapack.sgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
|
---|
395 | if (info < 0) {
|
---|
396 | ILMemoryPool.Pool.Free(pivInd);
|
---|
397 | throw new ILArgumentException("invalid parameter");
|
---|
398 | //} else if (info > 0) {
|
---|
399 | // // singular diagonal entry found
|
---|
400 |
|
---|
401 | } else {
|
---|
402 | // completed successfuly
|
---|
403 | if (!Object.Equals(U, null)) {
|
---|
404 | if (!Object.Equals(P, null)) {
|
---|
405 | pivInd = perm2indicesForward(pivInd);
|
---|
406 | U.a = copyUpperTriangle<float>(L, minMN, n);
|
---|
407 | L.a = copyLowerTriangle<float>(L, m, minMN, 1.0f);
|
---|
408 | P.a = zeros< float>(new ILSize(minMN, minMN));
|
---|
409 | // construct permutation matrix P
|
---|
410 | for (int r = 0; r < m; r++) {
|
---|
411 | P[r, pivInd[r]] = 1.0f;
|
---|
412 | }
|
---|
413 | } else {
|
---|
414 | pivInd = perm2indicesBackward(pivInd);
|
---|
415 | U.a = copyUpperTriangle<float>(L, minMN, n);
|
---|
416 | L.a = copyLowerTrianglePerm< float>(L, m, minMN, 1.0f, pivInd);
|
---|
417 | }
|
---|
418 | }
|
---|
419 | }
|
---|
420 | ILMemoryPool.Pool.Free(pivInd);
|
---|
421 | return L;
|
---|
422 | }
|
---|
423 | }
|
---|
424 | /// <summary>
|
---|
425 | /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
|
---|
426 | /// </summary>
|
---|
427 | /// <param name="A">Input matrix. Size [m x n]</param>
|
---|
428 | /// <returns>Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]</returns>
|
---|
429 | /// <remarks><para>The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.</para>
|
---|
430 | /// <code>
|
---|
431 | /// :'''''''|
|
---|
432 | /// |1 \ |
|
---|
433 | /// | 1 \ R |
|
---|
434 | /// | 1 \ |
|
---|
435 | /// | L 1 \ |
|
---|
436 | /// | 1 \|
|
---|
437 | /// '''''''''
|
---|
438 | /// </code>
|
---|
439 | /// <para>This overload is mainly needed for further operations via Lapack libraries. If you need the
|
---|
440 | /// L and U matrices directly, you'd better use one of the overloaded versions
|
---|
441 | /// <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
442 | /// or <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> instead.</para>
|
---|
443 | /// <para>The matrix L will be a solid ILArray.</para>
|
---|
444 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
445 | /// </remarks>
|
---|
446 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
|
---|
447 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
448 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
449 | public static ILRetArray< fcomplex > lu(ILInArray<fcomplex> A) {
|
---|
450 | ILArray< fcomplex > U = null;
|
---|
451 | ILArray< fcomplex > P = null;
|
---|
452 | return lu(A, U, P);
|
---|
453 | }
|
---|
454 | /// <summary>
|
---|
455 | /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
|
---|
456 | /// </summary>
|
---|
457 | /// <param name="A">Input matrix to be decomposed. Size [m x n]</param>
|
---|
458 | /// <param name="U">[Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.</param>
|
---|
459 | /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
|
---|
460 | /// <remarks>A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
|
---|
461 | /// <para>L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order
|
---|
462 | /// to fullfill <c>ILMath.multiply(L,U) == A</c></para>
|
---|
463 | /// <example> <code>
|
---|
464 | /// //we construct a matrix X:
|
---|
465 | /// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
|
---|
466 | /// // now X.ToString() will give something like:
|
---|
467 | /// // {<Double> 63238509 [3x3] Ref(2)
|
---|
468 | /// //(:,:)
|
---|
469 | /// // 1,00000 2,00000 3,00000
|
---|
470 | /// // 4,00000 4,00000 4,00000
|
---|
471 | /// // 5,00000 6,00000 7,00000
|
---|
472 | /// //}
|
---|
473 | /// // construct reference on U and call the decomposition
|
---|
474 | /// ILArray<double> U = new ILArray<double>.empty();
|
---|
475 | /// ILArray<double> L = ILMath.lu(X, ref U);
|
---|
476 | ///
|
---|
477 | /// // L.ToString() is now:
|
---|
478 | /// // {<Double> 19634871 [3x3] Phys.
|
---|
479 | /// //(:,:)
|
---|
480 | /// // 0,20000 -1,00000 1,00000
|
---|
481 | /// // 0,80000 1,00000 0,00000
|
---|
482 | /// // 1,00000 0,00000 0,00000
|
---|
483 | /// //}
|
---|
484 | /// // and U is now:
|
---|
485 | /// //{<Double> 22584602 [3x3] Phys.
|
---|
486 | /// //(:,:)
|
---|
487 | /// // 5,00000 6,00000 7,00000
|
---|
488 | /// // 0,00000 -0,80000 -1,60000
|
---|
489 | /// // 0,00000 0,00000 0,00000
|
---|
490 | /// //}
|
---|
491 | /// </code>
|
---|
492 | /// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf. </example>
|
---|
493 | /// <para>In order to access the permutation of L, one can use the overloaded version <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> which returns the permuation matrix P also.</para>
|
---|
494 | /// <para>All of the matrices U and L returned will be solid ILArrays.</para>
|
---|
495 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
496 | /// </remarks>
|
---|
497 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
|
---|
498 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
|
---|
499 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
500 | public static ILRetArray< fcomplex> lu(ILInArray<fcomplex> A, ILOutArray<fcomplex> U) {
|
---|
501 | return lu(A,U,null);
|
---|
502 | }
|
---|
503 | /// <summary>
|
---|
504 | /// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also.
|
---|
505 | /// </summary>
|
---|
506 | /// <param name="A">Input matrix. Size [m x n]</param>
|
---|
507 | /// <param name="U">[Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.</param>
|
---|
508 | /// <param name="P">[Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.</param>
|
---|
509 | /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
|
---|
510 | /// <remarks>A is decomposed into L and U, so that the equation
|
---|
511 | /// <c>ILMath.multiply(L,U) == ILMath.multiply(P,A)</c>
|
---|
512 | /// will hold except for round off error.
|
---|
513 | /// <para>L and U will be true lower triangular matrices.</para>
|
---|
514 | /// <example> <code>
|
---|
515 | /// //Let's construct a matrix X:
|
---|
516 | /// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
|
---|
517 | /// // now X.ToString() will give something like:
|
---|
518 | /// // {<Double> 63238509 [3x3] Ref(2)
|
---|
519 | /// //(:,:)
|
---|
520 | /// // 1,00000 2,00000 3,00000
|
---|
521 | /// // 4,00000 4,00000 4,00000
|
---|
522 | /// // 5,00000 6,00000 7,00000
|
---|
523 | /// //}
|
---|
524 | /// // construct references on U and P and call the decomposition
|
---|
525 | /// ILArray<double> U = new ILArray<double>.empty();
|
---|
526 | /// ILArray<double> P = new ILArray<double>.empty();
|
---|
527 | /// ILArray<double> L = ILMath.lu(X, ref U, ref P);
|
---|
528 | ///
|
---|
529 | /// // L.ToString() is now:
|
---|
530 | /// // {<Double> 19634871 [3x3] Phys.
|
---|
531 | /// //(:,:)
|
---|
532 | /// // 1,00000 0,00000 0,00000
|
---|
533 | /// // 0,80000 1,00000 0,00000
|
---|
534 | /// // 0,20000 -1,00000 1,00000
|
---|
535 | /// //}
|
---|
536 | /// // U is now:
|
---|
537 | /// //{<Double> 22584602 [3x3] Phys.
|
---|
538 | /// //(:,:)
|
---|
539 | /// // 5,00000 6,00000 7,00000
|
---|
540 | /// // 0,00000 -0,80000 -1,60000
|
---|
541 | /// // 0,00000 0,00000 0,00000
|
---|
542 | /// //}
|
---|
543 | /// // and P is:
|
---|
544 | /// //{<Double> 2192437 [3x3] Phys.
|
---|
545 | /// //(:,:)
|
---|
546 | /// // 0,00000 0,00000 1,00000
|
---|
547 | /// // 0,00000 1,00000 0,00000
|
---|
548 | /// // 1,00000 0,00000 0,00000
|
---|
549 | /// //}
|
---|
550 | /// </code>
|
---|
551 | /// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
|
---|
552 | /// <code>
|
---|
553 | /// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
|
---|
554 | /// // will give:
|
---|
555 | /// //{<Double> 59192235 [3x3] Phys.
|
---|
556 | /// //(:,:)
|
---|
557 | /// // 0,00000 0,00000 0,00000
|
---|
558 | /// // 0,00000 0,00000 0,00000
|
---|
559 | /// // 0,00000 0,00000 0,00000
|
---|
560 | /// //}
|
---|
561 | /// </code>
|
---|
562 | /// </example>
|
---|
563 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
564 | /// <para>All of the matrices U,L,P returned will be solid ILArrays.</para>
|
---|
565 | /// </remarks>
|
---|
566 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
|
---|
567 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
568 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
569 | public static ILRetArray< fcomplex> lu(ILInArray<fcomplex> A, ILOutArray<fcomplex> U
|
---|
570 | , ILOutArray< fcomplex> P) {
|
---|
571 | using (ILScope.Enter(A)) {
|
---|
572 | if (!A.IsMatrix)
|
---|
573 | throw new ILArgumentSizeException("lu is defined for matrices only!");
|
---|
574 | int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
|
---|
575 | ILArray< fcomplex> L = A.C;
|
---|
576 | int[] pivInd = ILMemoryPool.Pool.New<int>(minMN);
|
---|
577 |
|
---|
578 | Lapack.cgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
|
---|
579 | if (info < 0) {
|
---|
580 | ILMemoryPool.Pool.Free(pivInd);
|
---|
581 | throw new ILArgumentException("invalid parameter");
|
---|
582 | //} else if (info > 0) {
|
---|
583 | // // singular diagonal entry found
|
---|
584 |
|
---|
585 | } else {
|
---|
586 | // completed successfuly
|
---|
587 | if (!Object.Equals(U, null)) {
|
---|
588 | if (!Object.Equals(P, null)) {
|
---|
589 | pivInd = perm2indicesForward(pivInd);
|
---|
590 | U.a = copyUpperTriangle<fcomplex>(L, minMN, n);
|
---|
591 | L.a = copyLowerTriangle<fcomplex>(L, m, minMN, new fcomplex(1.0f,0.0f));
|
---|
592 | P.a = zeros< fcomplex>(new ILSize(minMN, minMN));
|
---|
593 | // construct permutation matrix P
|
---|
594 | for (int r = 0; r < m; r++) {
|
---|
595 | P[r, pivInd[r]] = new fcomplex(1.0f,0.0f);
|
---|
596 | }
|
---|
597 | } else {
|
---|
598 | pivInd = perm2indicesBackward(pivInd);
|
---|
599 | U.a = copyUpperTriangle<fcomplex>(L, minMN, n);
|
---|
600 | L.a = copyLowerTrianglePerm< fcomplex>(L, m, minMN, new fcomplex(1.0f,0.0f), pivInd);
|
---|
601 | }
|
---|
602 | }
|
---|
603 | }
|
---|
604 | ILMemoryPool.Pool.Free(pivInd);
|
---|
605 | return L;
|
---|
606 | }
|
---|
607 | }
|
---|
608 | /// <summary>
|
---|
609 | /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
|
---|
610 | /// </summary>
|
---|
611 | /// <param name="A">Input matrix. Size [m x n]</param>
|
---|
612 | /// <returns>Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]</returns>
|
---|
613 | /// <remarks><para>The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.</para>
|
---|
614 | /// <code>
|
---|
615 | /// :'''''''|
|
---|
616 | /// |1 \ |
|
---|
617 | /// | 1 \ R |
|
---|
618 | /// | 1 \ |
|
---|
619 | /// | L 1 \ |
|
---|
620 | /// | 1 \|
|
---|
621 | /// '''''''''
|
---|
622 | /// </code>
|
---|
623 | /// <para>This overload is mainly needed for further operations via Lapack libraries. If you need the
|
---|
624 | /// L and U matrices directly, you'd better use one of the overloaded versions
|
---|
625 | /// <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
626 | /// or <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> instead.</para>
|
---|
627 | /// <para>The matrix L will be a solid ILArray.</para>
|
---|
628 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
629 | /// </remarks>
|
---|
630 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
|
---|
631 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
632 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
633 | public static ILRetArray< complex > lu(ILInArray<complex> A) {
|
---|
634 | ILArray< complex > U = null;
|
---|
635 | ILArray< complex > P = null;
|
---|
636 | return lu(A, U, P);
|
---|
637 | }
|
---|
638 | /// <summary>
|
---|
639 | /// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
|
---|
640 | /// </summary>
|
---|
641 | /// <param name="A">Input matrix to be decomposed. Size [m x n]</param>
|
---|
642 | /// <param name="U">[Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.</param>
|
---|
643 | /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
|
---|
644 | /// <remarks>A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
|
---|
645 | /// <para>L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order
|
---|
646 | /// to fullfill <c>ILMath.multiply(L,U) == A</c></para>
|
---|
647 | /// <example> <code>
|
---|
648 | /// //we construct a matrix X:
|
---|
649 | /// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
|
---|
650 | /// // now X.ToString() will give something like:
|
---|
651 | /// // {<Double> 63238509 [3x3] Ref(2)
|
---|
652 | /// //(:,:)
|
---|
653 | /// // 1,00000 2,00000 3,00000
|
---|
654 | /// // 4,00000 4,00000 4,00000
|
---|
655 | /// // 5,00000 6,00000 7,00000
|
---|
656 | /// //}
|
---|
657 | /// // construct reference on U and call the decomposition
|
---|
658 | /// ILArray<double> U = new ILArray<double>.empty();
|
---|
659 | /// ILArray<double> L = ILMath.lu(X, ref U);
|
---|
660 | ///
|
---|
661 | /// // L.ToString() is now:
|
---|
662 | /// // {<Double> 19634871 [3x3] Phys.
|
---|
663 | /// //(:,:)
|
---|
664 | /// // 0,20000 -1,00000 1,00000
|
---|
665 | /// // 0,80000 1,00000 0,00000
|
---|
666 | /// // 1,00000 0,00000 0,00000
|
---|
667 | /// //}
|
---|
668 | /// // and U is now:
|
---|
669 | /// //{<Double> 22584602 [3x3] Phys.
|
---|
670 | /// //(:,:)
|
---|
671 | /// // 5,00000 6,00000 7,00000
|
---|
672 | /// // 0,00000 -0,80000 -1,60000
|
---|
673 | /// // 0,00000 0,00000 0,00000
|
---|
674 | /// //}
|
---|
675 | /// </code>
|
---|
676 | /// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf. </example>
|
---|
677 | /// <para>In order to access the permutation of L, one can use the overloaded version <see cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/> which returns the permuation matrix P also.</para>
|
---|
678 | /// <para>All of the matrices U and L returned will be solid ILArrays.</para>
|
---|
679 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
680 | /// </remarks>
|
---|
681 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double}, ILOutArray{double})"/>
|
---|
682 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
|
---|
683 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
684 | public static ILRetArray< complex> lu(ILInArray<complex> A, ILOutArray<complex> U) {
|
---|
685 | return lu(A,U,null);
|
---|
686 | }
|
---|
687 | /// <summary>
|
---|
688 | /// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also.
|
---|
689 | /// </summary>
|
---|
690 | /// <param name="A">Input matrix. Size [m x n]</param>
|
---|
691 | /// <param name="U">[Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.</param>
|
---|
692 | /// <param name="P">[Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.</param>
|
---|
693 | /// <returns>Lower triangular matrix L of size [m x min(m,n)]</returns>
|
---|
694 | /// <remarks>A is decomposed into L and U, so that the equation
|
---|
695 | /// <c>ILMath.multiply(L,U) == ILMath.multiply(P,A)</c>
|
---|
696 | /// will hold except for round off error.
|
---|
697 | /// <para>L and U will be true lower triangular matrices.</para>
|
---|
698 | /// <example> <code>
|
---|
699 | /// //Let's construct a matrix X:
|
---|
700 | /// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
|
---|
701 | /// // now X.ToString() will give something like:
|
---|
702 | /// // {<Double> 63238509 [3x3] Ref(2)
|
---|
703 | /// //(:,:)
|
---|
704 | /// // 1,00000 2,00000 3,00000
|
---|
705 | /// // 4,00000 4,00000 4,00000
|
---|
706 | /// // 5,00000 6,00000 7,00000
|
---|
707 | /// //}
|
---|
708 | /// // construct references on U and P and call the decomposition
|
---|
709 | /// ILArray<double> U = new ILArray<double>.empty();
|
---|
710 | /// ILArray<double> P = new ILArray<double>.empty();
|
---|
711 | /// ILArray<double> L = ILMath.lu(X, ref U, ref P);
|
---|
712 | ///
|
---|
713 | /// // L.ToString() is now:
|
---|
714 | /// // {<Double> 19634871 [3x3] Phys.
|
---|
715 | /// //(:,:)
|
---|
716 | /// // 1,00000 0,00000 0,00000
|
---|
717 | /// // 0,80000 1,00000 0,00000
|
---|
718 | /// // 0,20000 -1,00000 1,00000
|
---|
719 | /// //}
|
---|
720 | /// // U is now:
|
---|
721 | /// //{<Double> 22584602 [3x3] Phys.
|
---|
722 | /// //(:,:)
|
---|
723 | /// // 5,00000 6,00000 7,00000
|
---|
724 | /// // 0,00000 -0,80000 -1,60000
|
---|
725 | /// // 0,00000 0,00000 0,00000
|
---|
726 | /// //}
|
---|
727 | /// // and P is:
|
---|
728 | /// //{<Double> 2192437 [3x3] Phys.
|
---|
729 | /// //(:,:)
|
---|
730 | /// // 0,00000 0,00000 1,00000
|
---|
731 | /// // 0,00000 1,00000 0,00000
|
---|
732 | /// // 1,00000 0,00000 0,00000
|
---|
733 | /// //}
|
---|
734 | /// </code>
|
---|
735 | /// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
|
---|
736 | /// <code>
|
---|
737 | /// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
|
---|
738 | /// // will give:
|
---|
739 | /// //{<Double> 59192235 [3x3] Phys.
|
---|
740 | /// //(:,:)
|
---|
741 | /// // 0,00000 0,00000 0,00000
|
---|
742 | /// // 0,00000 0,00000 0,00000
|
---|
743 | /// // 0,00000 0,00000 0,00000
|
---|
744 | /// //}
|
---|
745 | /// </code>
|
---|
746 | /// </example>
|
---|
747 | /// <para>lu uses the Lapack function ?getrf.</para>
|
---|
748 | /// <para>All of the matrices U,L,P returned will be solid ILArrays.</para>
|
---|
749 | /// </remarks>
|
---|
750 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double})"/>
|
---|
751 | /// <seealso cref="ILNumerics.ILMath.lu(ILInArray{double}, ILOutArray{double})"/>
|
---|
752 | /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
|
---|
753 | public static ILRetArray< complex> lu(ILInArray<complex> A, ILOutArray<complex> U
|
---|
754 | , ILOutArray< complex> P) {
|
---|
755 | using (ILScope.Enter(A)) {
|
---|
756 | if (!A.IsMatrix)
|
---|
757 | throw new ILArgumentSizeException("lu is defined for matrices only!");
|
---|
758 | int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
|
---|
759 | ILArray< complex> L = A.C;
|
---|
760 | int[] pivInd = ILMemoryPool.Pool.New<int>(minMN);
|
---|
761 |
|
---|
762 | Lapack.zgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
|
---|
763 | if (info < 0) {
|
---|
764 | ILMemoryPool.Pool.Free(pivInd);
|
---|
765 | throw new ILArgumentException("invalid parameter");
|
---|
766 | //} else if (info > 0) {
|
---|
767 | // // singular diagonal entry found
|
---|
768 |
|
---|
769 | } else {
|
---|
770 | // completed successfuly
|
---|
771 | if (!Object.Equals(U, null)) {
|
---|
772 | if (!Object.Equals(P, null)) {
|
---|
773 | pivInd = perm2indicesForward(pivInd);
|
---|
774 | U.a = copyUpperTriangle<complex>(L, minMN, n);
|
---|
775 | L.a = copyLowerTriangle<complex>(L, m, minMN, new complex(1.0,0.0));
|
---|
776 | P.a = zeros< complex>(new ILSize(minMN, minMN));
|
---|
777 | // construct permutation matrix P
|
---|
778 | for (int r = 0; r < m; r++) {
|
---|
779 | P[r, pivInd[r]] = new complex(1.0,0.0);
|
---|
780 | }
|
---|
781 | } else {
|
---|
782 | pivInd = perm2indicesBackward(pivInd);
|
---|
783 | U.a = copyUpperTriangle<complex>(L, minMN, n);
|
---|
784 | L.a = copyLowerTrianglePerm< complex>(L, m, minMN, new complex(1.0,0.0), pivInd);
|
---|
785 | }
|
---|
786 | }
|
---|
787 | }
|
---|
788 | ILMemoryPool.Pool.Free(pivInd);
|
---|
789 | return L;
|
---|
790 | }
|
---|
791 | }
|
---|
792 |
|
---|
793 | #endregion HYCALPER AUTO GENERATED CODE
|
---|
794 |
|
---|
795 | /// <summary>
|
---|
796 | /// Copy upper triangle from PHYSICAL array A
|
---|
797 | /// </summary>
|
---|
798 | /// <typeparam name="T">Arbitrary inner type </typeparam>
|
---|
799 | /// <param name="A">PHYSICAL ILArray</param>
|
---|
800 | /// <param name="m">Number of rows</param>
|
---|
801 | /// <param name="n">Number of columns</param>
|
---|
802 | /// <returns>Newly created physical array with the upper triangle of A</returns>
|
---|
803 | /// <remarks>No checks are made for m,n fit inside A!</remarks>
|
---|
804 | internal static ILRetArray<T> copyUpperTriangle<T>(ILInArray<T> A, int m, int n) {
|
---|
805 | using (ILScope.Enter(A)) {
|
---|
806 | T[] arr = ILMemoryPool.Pool.New<T>(m * n);
|
---|
807 | for (int r = 0; r < m; r++) {
|
---|
808 | for (int c = r; c < n; c++) {
|
---|
809 | arr[r + c * m] = A.GetValue(r, c);
|
---|
810 | }
|
---|
811 | }
|
---|
812 | return new ILRetArray<T>(arr, m, n);
|
---|
813 | }
|
---|
814 | }
|
---|
815 | /// <summary>
|
---|
816 | /// Copy upper triangle from system array A
|
---|
817 | /// </summary>
|
---|
818 | /// <typeparam name="T">Arbitrary inner type </typeparam>
|
---|
819 | /// <param name="arrIn">System array, size (m x n), column wise ordered</param>
|
---|
820 | /// <param name="arrInM">Number of rows</param>
|
---|
821 | /// <param name="arrInN">Number of columns</param>
|
---|
822 | /// <param name="outM">Number of rows in output matrix</param>
|
---|
823 | /// <returns>Newly created physical array with the upper triangle of A</returns>
|
---|
824 | /// <remarks>No checks are made for m,n fit inside A! copies the main diagonal also.
|
---|
825 | /// the array returned will be of size (min(m,n) x n)</remarks>
|
---|
826 | private static ILRetArray<T> copyUpperTriangle<T>(T[] arrIn, int arrInM, int arrInN, int outM) {
|
---|
827 | T[] arrOu = ILMemoryPool.Pool.New<T>(outM * arrInN);
|
---|
828 | for (int c = 0; c < arrInN; c++) {
|
---|
829 | for (int r = 0; r <= c && r < outM; r++) {
|
---|
830 | arrOu[c * outM + r] = arrIn[c * arrInM + r];
|
---|
831 | }
|
---|
832 | }
|
---|
833 | return new ILRetArray<T> (arrOu,outM,arrInN);
|
---|
834 | }
|
---|
835 | /// <summary>
|
---|
836 | /// Copy lower triangle from PHYSICAL array A, set diagonal to val
|
---|
837 | /// </summary>
|
---|
838 | /// <typeparam name="T">Arbitrary inner type </typeparam>
|
---|
839 | /// <param name="A">PHYSICAL ILArray</param>
|
---|
840 | /// <param name="m">Number of rows</param>
|
---|
841 | /// <param name="n">Number of columns</param>
|
---|
842 | /// <param name="val">Value for diagonal entries</param>
|
---|
843 | /// <returns>Newly created physical array with the lower triangle of A</returns>
|
---|
844 | /// <remarks>No checks are made for m,n fit inside A!</remarks>
|
---|
845 | private static ILRetArray<T> copyLowerTriangle<T>(ILInArray<T> A, int m, int n, T val) {
|
---|
846 | using (ILScope.Enter(A)) {
|
---|
847 | T[] arr = ILMemoryPool.Pool.New<T>(m * n);
|
---|
848 | for (int r = 0; r < m; r++) {
|
---|
849 | for (int c = r + 1; c-- > 0; ) {
|
---|
850 | arr[r + m * c] = A.GetValue(r, c);
|
---|
851 | }
|
---|
852 | arr[r + m * r] = val;
|
---|
853 | }
|
---|
854 | return new ILRetArray<T>(arr, m, n);
|
---|
855 | }
|
---|
856 | }
|
---|
857 | /// <summary>
|
---|
858 | /// Copy lower triangle from PHYSICAL array A, set diagonal to val, permuted version
|
---|
859 | /// </summary>
|
---|
860 | /// <typeparam name="T">Arbitrary inner type </typeparam>
|
---|
861 | /// <param name="A">PHYSICAL ILArray</param>
|
---|
862 | /// <param name="m">Number of rows</param>
|
---|
863 | /// <param name="n">Number of columns</param>
|
---|
864 | /// <param name="perm">Mapping for rows, must be converted fom LAPACK version to single indices </param>
|
---|
865 | /// <param name="val">Value for diagonal entries</param>
|
---|
866 | /// <returns>Newly created physical array with the lower triangle of A</returns>
|
---|
867 | /// <remarks>No checks are made for m,n fit inside A!</remarks>
|
---|
868 | private static ILRetArray<T> copyLowerTrianglePerm<T>(ILInArray<T> A, int m, int n, T val, int[] perm) {
|
---|
869 | using (ILScope.Enter(A)) {
|
---|
870 | T[] arr = ILMemoryPool.Pool.New<T>(m * n);
|
---|
871 | int trueRow;
|
---|
872 | for (int r = 0; r < perm.Length; r++) {
|
---|
873 | trueRow = perm[r];
|
---|
874 | for (int c = 0; c < trueRow; c++) {
|
---|
875 | arr[r + c * m] = A.GetValue(trueRow, c);
|
---|
876 | }
|
---|
877 | arr[r + m * trueRow] = val;
|
---|
878 | }
|
---|
879 | return new ILRetArray<T>(arr, m, n);
|
---|
880 | }
|
---|
881 | }
|
---|
882 |
|
---|
883 | /// <summary>
|
---|
884 | /// Relabel permutation indices from LAPACK ?getrf
|
---|
885 | /// </summary>
|
---|
886 | /// <param name="perm">Lapack pivoting permutation array</param>
|
---|
887 | /// <returns>Index mapping for direct addressing the rows </returns>
|
---|
888 | /// <remarks>Exchange the row labels in the same manner as LAPACK did for pivoting</remarks>
|
---|
889 | private static int[] perm2indicesForward(int[] perm) {
|
---|
890 | int [] ret = ILMemoryPool.Pool.New<int>(perm.Length);
|
---|
891 | for (int i = 0; i < ret.Length; i++) {
|
---|
892 | ret[i] = i;
|
---|
893 | }
|
---|
894 | int tmp;
|
---|
895 | for (int i = 0; i < ret.Length; i++) {
|
---|
896 | if (perm[i] != i+1) {
|
---|
897 | tmp = ret[perm[i]-1];
|
---|
898 | ret[perm[i]-1] = i;
|
---|
899 | ret[i] = tmp;
|
---|
900 | }
|
---|
901 | }
|
---|
902 | return ret;
|
---|
903 | }
|
---|
904 | /// <summary>
|
---|
905 | /// Relabel permutation indices from LAPACK ?getrf - backward version
|
---|
906 | /// </summary>
|
---|
907 | /// <param name="perm">Lapack pivoting permutation array</param>
|
---|
908 | /// <returns>Index mapping for direct addressing the rows </returns>
|
---|
909 | /// <remarks>Exchange the row labels in the same manner as LAPACK did for pivoting, but backwards</remarks>
|
---|
910 | private static int[] perm2indicesBackward(int[] perm) {
|
---|
911 | int [] ret = ILMemoryPool.Pool.New<int>(perm.Length);
|
---|
912 | for (int i = 0; i < ret.Length; i++) {
|
---|
913 | ret[i] = i;
|
---|
914 | }
|
---|
915 | int tmp;
|
---|
916 | for (int i = ret.Length - 1; i-->0;) {
|
---|
917 | if (perm[i] != i+1) {
|
---|
918 | tmp = ret[perm[i]-1];
|
---|
919 | ret[perm[i]-1] = i;
|
---|
920 | ret[i] = tmp;
|
---|
921 | }
|
---|
922 | }
|
---|
923 | return ret;
|
---|
924 | }
|
---|
925 |
|
---|
926 | }
|
---|
927 | }
|
---|