Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/lu.cs @ 10355

Last change on this file since 10355 was 9102, checked in by gkronber, 12 years ago

#1967: ILNumerics source for experimentation

File size: 48.7 KB
Line 
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
40using System;
41using System.Collections.Generic;
42using System.Text;
43using ILNumerics.Storage;
44using ILNumerics.Misc;
45using ILNumerics.Exceptions;
46 
47
48
49namespace 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&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
95        /// // now X.ToString() will give something like:
96        /// // {&lt;Double&gt; 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&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
104        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U);
105        ///
106        /// // L.ToString() is now:
107        /// // {&lt;Double&gt; 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        /// //{&lt;Double&gt; 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&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
146        /// // now X.ToString() will give something like:
147        /// // {&lt;Double&gt; 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&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
155        /// ILArray&lt;double&gt; P = new ILArray&lt;double&gt;.empty();
156        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U, ref P);
157        ///
158        /// // L.ToString() is now:
159        /// // {&lt;Double&gt; 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        /// //{&lt;Double&gt; 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        /// //{&lt;Double&gt; 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        /// //{&lt;Double&gt; 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&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
282        /// // now X.ToString() will give something like:
283        /// // {&lt;Double&gt; 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&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
291        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U);
292        ///
293        /// // L.ToString() is now:
294        /// // {&lt;Double&gt; 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        /// //{&lt;Double&gt; 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&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
333        /// // now X.ToString() will give something like:
334        /// // {&lt;Double&gt; 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&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
342        /// ILArray&lt;double&gt; P = new ILArray&lt;double&gt;.empty();
343        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U, ref P);
344        ///
345        /// // L.ToString() is now:
346        /// // {&lt;Double&gt; 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        /// //{&lt;Double&gt; 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        /// //{&lt;Double&gt; 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        /// //{&lt;Double&gt; 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&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
466        /// // now X.ToString() will give something like:
467        /// // {&lt;Double&gt; 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&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
475        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U);
476        ///
477        /// // L.ToString() is now:
478        /// // {&lt;Double&gt; 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        /// //{&lt;Double&gt; 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&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
517        /// // now X.ToString() will give something like:
518        /// // {&lt;Double&gt; 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&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
526        /// ILArray&lt;double&gt; P = new ILArray&lt;double&gt;.empty();
527        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U, ref P);
528        ///
529        /// // L.ToString() is now:
530        /// // {&lt;Double&gt; 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        /// //{&lt;Double&gt; 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        /// //{&lt;Double&gt; 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        /// //{&lt;Double&gt; 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&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
650        /// // now X.ToString() will give something like:
651        /// // {&lt;Double&gt; 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&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
659        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U);
660        ///
661        /// // L.ToString() is now:
662        /// // {&lt;Double&gt; 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        /// //{&lt;Double&gt; 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&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
701        /// // now X.ToString() will give something like:
702        /// // {&lt;Double&gt; 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&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
710        /// ILArray&lt;double&gt; P = new ILArray&lt;double&gt;.empty();
711        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U, ref P);
712        ///
713        /// // L.ToString() is now:
714        /// // {&lt;Double&gt; 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        /// //{&lt;Double&gt; 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        /// //{&lt;Double&gt; 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        /// //{&lt;Double&gt; 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}
Note: See TracBrowser for help on using the repository browser.