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 | namespace ILNumerics {
|
---|
49 | public partial class ILMath {
|
---|
50 | |
---|
51 | /// <summary>
|
---|
52 | /// Singular value decomposition
|
---|
53 | /// </summary>
|
---|
54 | /// <param name="A">Input matrix A</param>
|
---|
55 | /// <returns>Vector with min(M,N) singular values of A as column vector</returns>
|
---|
56 | public static ILRetArray< double > svd(ILInArray< double > A) {
|
---|
57 | return svd(A,null, null, false, false);
|
---|
58 | }
|
---|
59 | |
---|
60 | #region HYCALPER AUTO GENERATED CODE
|
---|
61 | |
---|
62 | /// <summary>
|
---|
63 | /// Singular value decomposition
|
---|
64 | /// </summary>
|
---|
65 | /// <param name="A">Input matrix A</param>
|
---|
66 | /// <returns>Vector with min(M,N) singular values of A as column vector</returns>
|
---|
67 | public static ILRetArray< float > svd(ILInArray< float > A) {
|
---|
68 | return svd(A,null, null, false, false);
|
---|
69 | }
|
---|
70 | /// <summary>
|
---|
71 | /// Singular value decomposition
|
---|
72 | /// </summary>
|
---|
73 | /// <param name="A">Input matrix A</param>
|
---|
74 | /// <returns>Vector with min(M,N) singular values of A as column vector</returns>
|
---|
75 | public static ILRetArray< float > svd(ILInArray< fcomplex > A) {
|
---|
76 | return svd(A,null, null, false, false);
|
---|
77 | }
|
---|
78 | /// <summary>
|
---|
79 | /// Singular value decomposition
|
---|
80 | /// </summary>
|
---|
81 | /// <param name="A">Input matrix A</param>
|
---|
82 | /// <returns>Vector with min(M,N) singular values of A as column vector</returns>
|
---|
83 | public static ILRetArray< double > svd(ILInArray< complex > A) {
|
---|
84 | return svd(A,null, null, false, false);
|
---|
85 | }
|
---|
86 |
|
---|
87 | #endregion HYCALPER AUTO GENERATED CODE
|
---|
88 |
|
---|
89 | |
---|
90 | /// <summary>
|
---|
91 | /// Singular value decomposition
|
---|
92 | /// </summary>
|
---|
93 | /// <param name="A">Input matrix</param>
|
---|
94 | /// <param name="U">[Output] Left singular vectors of A as columns of matrix U.
|
---|
95 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
96 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
97 | public static ILRetArray< double > svd(ILInArray< double > A, ILOutArray< double > U) {
|
---|
98 | return svd(A, U, null , false,false);
|
---|
99 | }
|
---|
100 | |
---|
101 | #region HYCALPER AUTO GENERATED CODE
|
---|
102 | |
---|
103 | /// <summary>
|
---|
104 | /// Singular value decomposition
|
---|
105 | /// </summary>
|
---|
106 | /// <param name="A">Input matrix</param>
|
---|
107 | /// <param name="U">[Output] Left singular vectors of A as columns of matrix U.
|
---|
108 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
109 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
110 | public static ILRetArray< float > svd(ILInArray< float > A, ILOutArray< float > U) {
|
---|
111 | return svd(A, U, null , false,false);
|
---|
112 | }
|
---|
113 | /// <summary>
|
---|
114 | /// Singular value decomposition
|
---|
115 | /// </summary>
|
---|
116 | /// <param name="A">Input matrix</param>
|
---|
117 | /// <param name="U">[Output] Left singular vectors of A as columns of matrix U.
|
---|
118 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
119 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
120 | public static ILRetArray< float > svd(ILInArray< fcomplex > A, ILOutArray< fcomplex > U) {
|
---|
121 | return svd(A, U, null , false,false);
|
---|
122 | }
|
---|
123 | /// <summary>
|
---|
124 | /// Singular value decomposition
|
---|
125 | /// </summary>
|
---|
126 | /// <param name="A">Input matrix</param>
|
---|
127 | /// <param name="U">[Output] Left singular vectors of A as columns of matrix U.
|
---|
128 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
129 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
130 | public static ILRetArray< double > svd(ILInArray< complex > A, ILOutArray< complex > U) {
|
---|
131 | return svd(A, U, null , false,false);
|
---|
132 | }
|
---|
133 |
|
---|
134 | #endregion HYCALPER AUTO GENERATED CODE
|
---|
135 |
|
---|
136 | |
---|
137 | /// <summary>
|
---|
138 | /// Singular value decomposition
|
---|
139 | /// </summary>
|
---|
140 | /// <param name="A">Input matrix</param>
|
---|
141 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU.
|
---|
142 | /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values.</param>
|
---|
143 | /// <param name="small">If true: return only first min(M,N) columns of outU will be
|
---|
144 | /// of size [min(M,N),min(M,N)]</param>
|
---|
145 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
146 | public static ILRetArray< double > svd(ILInArray< double > A, ILOutArray< double > outU, bool small) {
|
---|
147 | return svd(A, outU, null, small,false);
|
---|
148 | }
|
---|
149 | |
---|
150 | #region HYCALPER AUTO GENERATED CODE
|
---|
151 | |
---|
152 | /// <summary>
|
---|
153 | /// Singular value decomposition
|
---|
154 | /// </summary>
|
---|
155 | /// <param name="A">Input matrix</param>
|
---|
156 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU.
|
---|
157 | /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values.</param>
|
---|
158 | /// <param name="small">If true: return only first min(M,N) columns of outU will be
|
---|
159 | /// of size [min(M,N),min(M,N)]</param>
|
---|
160 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
161 | public static ILRetArray< float > svd(ILInArray< float > A, ILOutArray< float > outU, bool small) {
|
---|
162 | return svd(A, outU, null, small,false);
|
---|
163 | }
|
---|
164 | /// <summary>
|
---|
165 | /// Singular value decomposition
|
---|
166 | /// </summary>
|
---|
167 | /// <param name="A">Input matrix</param>
|
---|
168 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU.
|
---|
169 | /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values.</param>
|
---|
170 | /// <param name="small">If true: return only first min(M,N) columns of outU will be
|
---|
171 | /// of size [min(M,N),min(M,N)]</param>
|
---|
172 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
173 | public static ILRetArray< float > svd(ILInArray< fcomplex > A, ILOutArray< fcomplex > outU, bool small) {
|
---|
174 | return svd(A, outU, null, small,false);
|
---|
175 | }
|
---|
176 | /// <summary>
|
---|
177 | /// Singular value decomposition
|
---|
178 | /// </summary>
|
---|
179 | /// <param name="A">Input matrix</param>
|
---|
180 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU.
|
---|
181 | /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values.</param>
|
---|
182 | /// <param name="small">If true: return only first min(M,N) columns of outU will be
|
---|
183 | /// of size [min(M,N),min(M,N)]</param>
|
---|
184 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
185 | public static ILRetArray< double > svd(ILInArray< complex > A, ILOutArray< complex > outU, bool small) {
|
---|
186 | return svd(A, outU, null, small,false);
|
---|
187 | }
|
---|
188 |
|
---|
189 | #endregion HYCALPER AUTO GENERATED CODE
|
---|
190 |
|
---|
191 | |
---|
192 | /// <summary>
|
---|
193 | /// Singular value decomposition
|
---|
194 | /// </summary>
|
---|
195 | /// <param name="A">Input matrix</param>
|
---|
196 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix U.
|
---|
197 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
198 | /// <param name="outV">[Output] Right singular vectors of X as rows of matrix V.
|
---|
199 | /// This parameter must not be null. It might be an empty array on input.</param>
|
---|
200 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
201 | public static ILRetArray< double > svd(ILInArray< double > A, ILOutArray< double > outU, ILOutArray< double > outV) {
|
---|
202 | return svd(A, outU, outV, false,false);
|
---|
203 | }
|
---|
204 | |
---|
205 | #region HYCALPER AUTO GENERATED CODE
|
---|
206 | |
---|
207 | /// <summary>
|
---|
208 | /// Singular value decomposition
|
---|
209 | /// </summary>
|
---|
210 | /// <param name="A">Input matrix</param>
|
---|
211 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix U.
|
---|
212 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
213 | /// <param name="outV">[Output] Right singular vectors of X as rows of matrix V.
|
---|
214 | /// This parameter must not be null. It might be an empty array on input.</param>
|
---|
215 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
216 | public static ILRetArray< float > svd(ILInArray< float > A, ILOutArray< float > outU, ILOutArray< float > outV) {
|
---|
217 | return svd(A, outU, outV, false,false);
|
---|
218 | }
|
---|
219 | /// <summary>
|
---|
220 | /// Singular value decomposition
|
---|
221 | /// </summary>
|
---|
222 | /// <param name="A">Input matrix</param>
|
---|
223 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix U.
|
---|
224 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
225 | /// <param name="outV">[Output] Right singular vectors of X as rows of matrix V.
|
---|
226 | /// This parameter must not be null. It might be an empty array on input.</param>
|
---|
227 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
228 | public static ILRetArray< float > svd(ILInArray< fcomplex > A, ILOutArray< fcomplex > outU, ILOutArray< fcomplex > outV) {
|
---|
229 | return svd(A, outU, outV, false,false);
|
---|
230 | }
|
---|
231 | /// <summary>
|
---|
232 | /// Singular value decomposition
|
---|
233 | /// </summary>
|
---|
234 | /// <param name="A">Input matrix</param>
|
---|
235 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix U.
|
---|
236 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
237 | /// <param name="outV">[Output] Right singular vectors of X as rows of matrix V.
|
---|
238 | /// This parameter must not be null. It might be an empty array on input.</param>
|
---|
239 | /// <returns>Singluar values as diagonal matrix of same size and type as A</returns>
|
---|
240 | public static ILRetArray< double > svd(ILInArray< complex > A, ILOutArray< complex > outU, ILOutArray< complex > outV) {
|
---|
241 | return svd(A, outU, outV, false,false);
|
---|
242 | }
|
---|
243 |
|
---|
244 | #endregion HYCALPER AUTO GENERATED CODE
|
---|
245 |
|
---|
246 | |
---|
247 | /// <summary>
|
---|
248 | /// singular value decomposition
|
---|
249 | /// </summary>
|
---|
250 | /// <param name="A">Input matrix</param>
|
---|
251 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU.
|
---|
252 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
253 | /// <param name="outV">[Output] Right singular vectors of X as rows of matrix outV.
|
---|
254 | /// This parameter must not be null. It might be an empty array on input.</param>
|
---|
255 | /// <param name="small">If true: return only first min(M,N) columns of outU and S (returned) will be
|
---|
256 | /// of size [min(M,N),min(M,N)]</param>
|
---|
257 | /// <param name="discardFiniteTest">If true: the matrix given will not be checked for infinte or NaN values. If such elements
|
---|
258 | /// exist nevertheless, this may result in failing convergence or error. In worst case
|
---|
259 | /// the function may hang inside the Lapack lib! Use with care! </param>
|
---|
260 | /// <returns>Singular values as diagonal matrix of same size and type as A</returns>
|
---|
261 | public static ILRetArray< double> svd( ILInArray< double> A, ILOutArray< double> outU,
|
---|
262 | ILOutArray< double> outV, bool small, bool discardFiniteTest ) {
|
---|
263 | if (object.Equals(A,null))
|
---|
264 | throw new ILArgumentException("input matrix X must not be null");
|
---|
265 | using (ILScope.Enter(A)) {
|
---|
266 |
|
---|
267 | if (!A.IsMatrix)
|
---|
268 | throw new ILArgumentSizeException("svd is defined for matrices only");
|
---|
269 | // early exit for small matrices
|
---|
270 | if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) {
|
---|
271 | switch (A.Size[0]) {
|
---|
272 | case 1:
|
---|
273 | if (!Object.Equals(outU, null))
|
---|
274 | outU.a = ( double)1.0;
|
---|
275 | if (!Object.Equals(outV, null))
|
---|
276 | outV.a = ( double)1.0;
|
---|
277 | return abs(A);
|
---|
278 | //case 2:
|
---|
279 | // return -1;
|
---|
280 | //case 3:
|
---|
281 | // return -1;
|
---|
282 | }
|
---|
283 | }
|
---|
284 | if (!discardFiniteTest && !allall(isfinite(A)))
|
---|
285 | throw new ILArgumentException("svd: input must have only finite elements");
|
---|
286 | if (Lapack == null)
|
---|
287 | throw new ILMathException("no Lapack package available");
|
---|
288 | // parameter evaluation
|
---|
289 | int M = A.Size[0]; int N = A.Size[1];
|
---|
290 | int minMN = (M < N) ? M : N;
|
---|
291 | int LDU = M; int LDVT = N;
|
---|
292 | int LDA = M, lenDU = 0, lenVT = 0;
|
---|
293 |
|
---|
294 | double[] dS = ILMemoryPool.Pool.New< double>(minMN);
|
---|
295 | char jobz = (small) ? 'S' : 'A';
|
---|
296 |
|
---|
297 | double[] dU = null;
|
---|
298 |
|
---|
299 | double[] dVT = null;
|
---|
300 | int info = 0;
|
---|
301 | if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
|
---|
302 | // need to return U and VT
|
---|
303 | if (small) {
|
---|
304 | lenDU = M * minMN;
|
---|
305 | dU = ILMemoryPool.Pool.New< double>(lenDU);
|
---|
306 | lenVT = N * minMN;
|
---|
307 | dVT = ILMemoryPool.Pool.New< double>(lenVT);
|
---|
308 | } else {
|
---|
309 | lenDU = M * M;
|
---|
310 | dU = ILMemoryPool.Pool.New< double>(lenDU);
|
---|
311 | lenVT = N * N;
|
---|
312 | dVT = ILMemoryPool.Pool.New< double>(lenVT);
|
---|
313 | }
|
---|
314 | } else {
|
---|
315 | jobz = 'N';
|
---|
316 | }
|
---|
317 |
|
---|
318 | // must create copy of input !
|
---|
319 |
|
---|
320 | double[] dInput = A.C.GetArrayForWrite();
|
---|
321 | /*!HC:lapack_dgesdd*/
|
---|
322 | Lapack.dgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info);
|
---|
323 | if (info < 0)
|
---|
324 | throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid");
|
---|
325 | if (info > 0)
|
---|
326 | throw new ILArgumentException("svd was not converging");
|
---|
327 | ILArray< double> ret = empty<double>(ILSize.Empty00);
|
---|
328 | if (info == 0) {
|
---|
329 | // success
|
---|
330 | if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
|
---|
331 | if (small) {
|
---|
332 | ret.a = zeros< double>(new ILSize(minMN, minMN));
|
---|
333 | } else {
|
---|
334 | ret.a = zeros< double>(new ILSize(M, N));
|
---|
335 | }
|
---|
336 | for (int i = 0; i < minMN; i++) {
|
---|
337 | ret.SetValue(dS[i], i, i);
|
---|
338 | }
|
---|
339 | ILMemoryPool.Pool.Free(dS);
|
---|
340 | if (!Object.Equals(outU, null)) {
|
---|
341 | outU.a = array< double>(dU, M, lenDU / M);
|
---|
342 | } else {
|
---|
343 | ILMemoryPool.Pool.Free(dU);
|
---|
344 | }
|
---|
345 | if (!Object.Equals(outV, null)) {
|
---|
346 |
|
---|
347 | outV.a = array< double>(dVT, N, lenVT / N).T;
|
---|
348 | } else {
|
---|
349 | ILMemoryPool.Pool.Free(dVT);
|
---|
350 | }
|
---|
351 | } else {
|
---|
352 | ret.a = array< double>(dS,minMN, 1);
|
---|
353 | }
|
---|
354 | }
|
---|
355 | return ret;
|
---|
356 | }
|
---|
357 | }
|
---|
358 | |
---|
359 | #region HYCALPER AUTO GENERATED CODE
|
---|
360 | |
---|
361 | /// <summary>
|
---|
362 | /// singular value decomposition
|
---|
363 | /// </summary>
|
---|
364 | /// <param name="A">Input matrix</param>
|
---|
365 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU.
|
---|
366 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
367 | /// <param name="outV">[Output] Right singular vectors of X as rows of matrix outV.
|
---|
368 | /// This parameter must not be null. It might be an empty array on input.</param>
|
---|
369 | /// <param name="small">If true: return only first min(M,N) columns of outU and S (returned) will be
|
---|
370 | /// of size [min(M,N),min(M,N)]</param>
|
---|
371 | /// <param name="discardFiniteTest">If true: the matrix given will not be checked for infinte or NaN values. If such elements
|
---|
372 | /// exist nevertheless, this may result in failing convergence or error. In worst case
|
---|
373 | /// the function may hang inside the Lapack lib! Use with care! </param>
|
---|
374 | /// <returns>Singular values as diagonal matrix of same size and type as A</returns>
|
---|
375 | public static ILRetArray< float> svd( ILInArray< float> A, ILOutArray< float> outU,
|
---|
376 | ILOutArray< float> outV, bool small, bool discardFiniteTest ) {
|
---|
377 | if (object.Equals(A,null))
|
---|
378 | throw new ILArgumentException("input matrix X must not be null");
|
---|
379 | using (ILScope.Enter(A)) {
|
---|
380 |
|
---|
381 | if (!A.IsMatrix)
|
---|
382 | throw new ILArgumentSizeException("svd is defined for matrices only");
|
---|
383 | // early exit for small matrices
|
---|
384 | if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) {
|
---|
385 | switch (A.Size[0]) {
|
---|
386 | case 1:
|
---|
387 | if (!Object.Equals(outU, null))
|
---|
388 | outU.a = ( float)1.0;
|
---|
389 | if (!Object.Equals(outV, null))
|
---|
390 | outV.a = ( float)1.0;
|
---|
391 | return abs(A);
|
---|
392 | //case 2:
|
---|
393 | // return -1;
|
---|
394 | //case 3:
|
---|
395 | // return -1;
|
---|
396 | }
|
---|
397 | }
|
---|
398 | if (!discardFiniteTest && !allall(isfinite(A)))
|
---|
399 | throw new ILArgumentException("svd: input must have only finite elements");
|
---|
400 | if (Lapack == null)
|
---|
401 | throw new ILMathException("no Lapack package available");
|
---|
402 | // parameter evaluation
|
---|
403 | int M = A.Size[0]; int N = A.Size[1];
|
---|
404 | int minMN = (M < N) ? M : N;
|
---|
405 | int LDU = M; int LDVT = N;
|
---|
406 | int LDA = M, lenDU = 0, lenVT = 0;
|
---|
407 |
|
---|
408 | float[] dS = ILMemoryPool.Pool.New< float>(minMN);
|
---|
409 | char jobz = (small) ? 'S' : 'A';
|
---|
410 |
|
---|
411 | float[] dU = null;
|
---|
412 |
|
---|
413 | float[] dVT = null;
|
---|
414 | int info = 0;
|
---|
415 | if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
|
---|
416 | // need to return U and VT
|
---|
417 | if (small) {
|
---|
418 | lenDU = M * minMN;
|
---|
419 | dU = ILMemoryPool.Pool.New< float>(lenDU);
|
---|
420 | lenVT = N * minMN;
|
---|
421 | dVT = ILMemoryPool.Pool.New< float>(lenVT);
|
---|
422 | } else {
|
---|
423 | lenDU = M * M;
|
---|
424 | dU = ILMemoryPool.Pool.New< float>(lenDU);
|
---|
425 | lenVT = N * N;
|
---|
426 | dVT = ILMemoryPool.Pool.New< float>(lenVT);
|
---|
427 | }
|
---|
428 | } else {
|
---|
429 | jobz = 'N';
|
---|
430 | }
|
---|
431 |
|
---|
432 | // must create copy of input !
|
---|
433 |
|
---|
434 | float[] dInput = A.C.GetArrayForWrite();
|
---|
435 | Lapack.sgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info);
|
---|
436 | if (info < 0)
|
---|
437 | throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid");
|
---|
438 | if (info > 0)
|
---|
439 | throw new ILArgumentException("svd was not converging");
|
---|
440 | ILArray< float> ret = empty<float>(ILSize.Empty00);
|
---|
441 | if (info == 0) {
|
---|
442 | // success
|
---|
443 | if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
|
---|
444 | if (small) {
|
---|
445 | ret.a = zeros< float>(new ILSize(minMN, minMN));
|
---|
446 | } else {
|
---|
447 | ret.a = zeros< float>(new ILSize(M, N));
|
---|
448 | }
|
---|
449 | for (int i = 0; i < minMN; i++) {
|
---|
450 | ret.SetValue(dS[i], i, i);
|
---|
451 | }
|
---|
452 | ILMemoryPool.Pool.Free(dS);
|
---|
453 | if (!Object.Equals(outU, null)) {
|
---|
454 | outU.a = array< float>(dU, M, lenDU / M);
|
---|
455 | } else {
|
---|
456 | ILMemoryPool.Pool.Free(dU);
|
---|
457 | }
|
---|
458 | if (!Object.Equals(outV, null)) {
|
---|
459 | outV.a = new ILRetArray<float> (dVT,N,lenVT / N).T;
|
---|
460 | } else {
|
---|
461 | ILMemoryPool.Pool.Free(dVT);
|
---|
462 | }
|
---|
463 | } else {
|
---|
464 | ret.a = array< float>(dS,minMN, 1);
|
---|
465 | }
|
---|
466 | }
|
---|
467 | return ret;
|
---|
468 | }
|
---|
469 | }
|
---|
470 | /// <summary>
|
---|
471 | /// singular value decomposition
|
---|
472 | /// </summary>
|
---|
473 | /// <param name="A">Input matrix</param>
|
---|
474 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU.
|
---|
475 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
476 | /// <param name="outV">[Output] Right singular vectors of X as rows of matrix outV.
|
---|
477 | /// This parameter must not be null. It might be an empty array on input.</param>
|
---|
478 | /// <param name="small">If true: return only first min(M,N) columns of outU and S (returned) will be
|
---|
479 | /// of size [min(M,N),min(M,N)]</param>
|
---|
480 | /// <param name="discardFiniteTest">If true: the matrix given will not be checked for infinte or NaN values. If such elements
|
---|
481 | /// exist nevertheless, this may result in failing convergence or error. In worst case
|
---|
482 | /// the function may hang inside the Lapack lib! Use with care! </param>
|
---|
483 | /// <returns>Singular values as diagonal matrix of same size and type as A</returns>
|
---|
484 | public static ILRetArray< float> svd( ILInArray< fcomplex> A, ILOutArray< fcomplex> outU,
|
---|
485 | ILOutArray< fcomplex> outV, bool small, bool discardFiniteTest ) {
|
---|
486 | if (object.Equals(A,null))
|
---|
487 | throw new ILArgumentException("input matrix X must not be null");
|
---|
488 | using (ILScope.Enter(A)) {
|
---|
489 |
|
---|
490 | if (!A.IsMatrix)
|
---|
491 | throw new ILArgumentSizeException("svd is defined for matrices only");
|
---|
492 | // early exit for small matrices
|
---|
493 | if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) {
|
---|
494 | switch (A.Size[0]) {
|
---|
495 | case 1:
|
---|
496 | if (!Object.Equals(outU, null))
|
---|
497 | outU.a = ( fcomplex)1.0;
|
---|
498 | if (!Object.Equals(outV, null))
|
---|
499 | outV.a = ( fcomplex)1.0;
|
---|
500 | return abs(A);
|
---|
501 | //case 2:
|
---|
502 | // return -1;
|
---|
503 | //case 3:
|
---|
504 | // return -1;
|
---|
505 | }
|
---|
506 | }
|
---|
507 | if (!discardFiniteTest && !allall(isfinite(A)))
|
---|
508 | throw new ILArgumentException("svd: input must have only finite elements");
|
---|
509 | if (Lapack == null)
|
---|
510 | throw new ILMathException("no Lapack package available");
|
---|
511 | // parameter evaluation
|
---|
512 | int M = A.Size[0]; int N = A.Size[1];
|
---|
513 | int minMN = (M < N) ? M : N;
|
---|
514 | int LDU = M; int LDVT = N;
|
---|
515 | int LDA = M, lenDU = 0, lenVT = 0;
|
---|
516 |
|
---|
517 | float[] dS = ILMemoryPool.Pool.New< float>(minMN);
|
---|
518 | char jobz = (small) ? 'S' : 'A';
|
---|
519 |
|
---|
520 | fcomplex[] dU = null;
|
---|
521 |
|
---|
522 | fcomplex[] dVT = null;
|
---|
523 | int info = 0;
|
---|
524 | if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
|
---|
525 | // need to return U and VT
|
---|
526 | if (small) {
|
---|
527 | lenDU = M * minMN;
|
---|
528 | dU = ILMemoryPool.Pool.New< fcomplex>(lenDU);
|
---|
529 | lenVT = N * minMN;
|
---|
530 | dVT = ILMemoryPool.Pool.New< fcomplex>(lenVT);
|
---|
531 | } else {
|
---|
532 | lenDU = M * M;
|
---|
533 | dU = ILMemoryPool.Pool.New< fcomplex>(lenDU);
|
---|
534 | lenVT = N * N;
|
---|
535 | dVT = ILMemoryPool.Pool.New< fcomplex>(lenVT);
|
---|
536 | }
|
---|
537 | } else {
|
---|
538 | jobz = 'N';
|
---|
539 | }
|
---|
540 |
|
---|
541 | // must create copy of input !
|
---|
542 |
|
---|
543 | fcomplex[] dInput = A.C.GetArrayForWrite();
|
---|
544 | Lapack.cgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info);
|
---|
545 | if (info < 0)
|
---|
546 | throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid");
|
---|
547 | if (info > 0)
|
---|
548 | throw new ILArgumentException("svd was not converging");
|
---|
549 | ILArray< float> ret = empty<float>(ILSize.Empty00);
|
---|
550 | if (info == 0) {
|
---|
551 | // success
|
---|
552 | if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
|
---|
553 | if (small) {
|
---|
554 | ret.a = zeros< float>(new ILSize(minMN, minMN));
|
---|
555 | } else {
|
---|
556 | ret.a = zeros< float>(new ILSize(M, N));
|
---|
557 | }
|
---|
558 | for (int i = 0; i < minMN; i++) {
|
---|
559 | ret.SetValue(dS[i], i, i);
|
---|
560 | }
|
---|
561 | ILMemoryPool.Pool.Free(dS);
|
---|
562 | if (!Object.Equals(outU, null)) {
|
---|
563 | outU.a = array< fcomplex>(dU, M, lenDU / M);
|
---|
564 | } else {
|
---|
565 | ILMemoryPool.Pool.Free(dU);
|
---|
566 | }
|
---|
567 | if (!Object.Equals(outV, null)) {
|
---|
568 | outV.a = conj(new ILRetArray<fcomplex> (dVT,N,lenVT / N).T);
|
---|
569 | } else {
|
---|
570 | ILMemoryPool.Pool.Free(dVT);
|
---|
571 | }
|
---|
572 | } else {
|
---|
573 | ret.a = array< float>(dS,minMN, 1);
|
---|
574 | }
|
---|
575 | }
|
---|
576 | return ret;
|
---|
577 | }
|
---|
578 | }
|
---|
579 | /// <summary>
|
---|
580 | /// singular value decomposition
|
---|
581 | /// </summary>
|
---|
582 | /// <param name="A">Input matrix</param>
|
---|
583 | /// <param name="outU">[Output] Left singular vectors of A as columns of matrix outU.
|
---|
584 | /// Setting this parameter to a non-null value signals the need of returning those values.</param>
|
---|
585 | /// <param name="outV">[Output] Right singular vectors of X as rows of matrix outV.
|
---|
586 | /// This parameter must not be null. It might be an empty array on input.</param>
|
---|
587 | /// <param name="small">If true: return only first min(M,N) columns of outU and S (returned) will be
|
---|
588 | /// of size [min(M,N),min(M,N)]</param>
|
---|
589 | /// <param name="discardFiniteTest">If true: the matrix given will not be checked for infinte or NaN values. If such elements
|
---|
590 | /// exist nevertheless, this may result in failing convergence or error. In worst case
|
---|
591 | /// the function may hang inside the Lapack lib! Use with care! </param>
|
---|
592 | /// <returns>Singular values as diagonal matrix of same size and type as A</returns>
|
---|
593 | public static ILRetArray< double> svd( ILInArray< complex> A, ILOutArray< complex> outU,
|
---|
594 | ILOutArray< complex> outV, bool small, bool discardFiniteTest ) {
|
---|
595 | if (object.Equals(A,null))
|
---|
596 | throw new ILArgumentException("input matrix X must not be null");
|
---|
597 | using (ILScope.Enter(A)) {
|
---|
598 |
|
---|
599 | if (!A.IsMatrix)
|
---|
600 | throw new ILArgumentSizeException("svd is defined for matrices only");
|
---|
601 | // early exit for small matrices
|
---|
602 | if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) {
|
---|
603 | switch (A.Size[0]) {
|
---|
604 | case 1:
|
---|
605 | if (!Object.Equals(outU, null))
|
---|
606 | outU.a = ( complex)1.0;
|
---|
607 | if (!Object.Equals(outV, null))
|
---|
608 | outV.a = ( complex)1.0;
|
---|
609 | return abs(A);
|
---|
610 | //case 2:
|
---|
611 | // return -1;
|
---|
612 | //case 3:
|
---|
613 | // return -1;
|
---|
614 | }
|
---|
615 | }
|
---|
616 | if (!discardFiniteTest && !allall(isfinite(A)))
|
---|
617 | throw new ILArgumentException("svd: input must have only finite elements");
|
---|
618 | if (Lapack == null)
|
---|
619 | throw new ILMathException("no Lapack package available");
|
---|
620 | // parameter evaluation
|
---|
621 | int M = A.Size[0]; int N = A.Size[1];
|
---|
622 | int minMN = (M < N) ? M : N;
|
---|
623 | int LDU = M; int LDVT = N;
|
---|
624 | int LDA = M, lenDU = 0, lenVT = 0;
|
---|
625 |
|
---|
626 | double[] dS = ILMemoryPool.Pool.New< double>(minMN);
|
---|
627 | char jobz = (small) ? 'S' : 'A';
|
---|
628 |
|
---|
629 | complex[] dU = null;
|
---|
630 |
|
---|
631 | complex[] dVT = null;
|
---|
632 | int info = 0;
|
---|
633 | if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
|
---|
634 | // need to return U and VT
|
---|
635 | if (small) {
|
---|
636 | lenDU = M * minMN;
|
---|
637 | dU = ILMemoryPool.Pool.New< complex>(lenDU);
|
---|
638 | lenVT = N * minMN;
|
---|
639 | dVT = ILMemoryPool.Pool.New< complex>(lenVT);
|
---|
640 | } else {
|
---|
641 | lenDU = M * M;
|
---|
642 | dU = ILMemoryPool.Pool.New< complex>(lenDU);
|
---|
643 | lenVT = N * N;
|
---|
644 | dVT = ILMemoryPool.Pool.New< complex>(lenVT);
|
---|
645 | }
|
---|
646 | } else {
|
---|
647 | jobz = 'N';
|
---|
648 | }
|
---|
649 |
|
---|
650 | // must create copy of input !
|
---|
651 |
|
---|
652 | complex[] dInput = A.C.GetArrayForWrite();
|
---|
653 | Lapack.zgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info);
|
---|
654 | if (info < 0)
|
---|
655 | throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid");
|
---|
656 | if (info > 0)
|
---|
657 | throw new ILArgumentException("svd was not converging");
|
---|
658 | ILArray< double> ret = empty<double>(ILSize.Empty00);
|
---|
659 | if (info == 0) {
|
---|
660 | // success
|
---|
661 | if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) {
|
---|
662 | if (small) {
|
---|
663 | ret.a = zeros< double>(new ILSize(minMN, minMN));
|
---|
664 | } else {
|
---|
665 | ret.a = zeros< double>(new ILSize(M, N));
|
---|
666 | }
|
---|
667 | for (int i = 0; i < minMN; i++) {
|
---|
668 | ret.SetValue(dS[i], i, i);
|
---|
669 | }
|
---|
670 | ILMemoryPool.Pool.Free(dS);
|
---|
671 | if (!Object.Equals(outU, null)) {
|
---|
672 | outU.a = array< complex>(dU, M, lenDU / M);
|
---|
673 | } else {
|
---|
674 | ILMemoryPool.Pool.Free(dU);
|
---|
675 | }
|
---|
676 | if (!Object.Equals(outV, null)) {
|
---|
677 | outV.a = conj(new ILRetArray<complex> (dVT,N,lenVT / N).T);
|
---|
678 | } else {
|
---|
679 | ILMemoryPool.Pool.Free(dVT);
|
---|
680 | }
|
---|
681 | } else {
|
---|
682 | ret.a = array< double>(dS,minMN, 1);
|
---|
683 | }
|
---|
684 | }
|
---|
685 | return ret;
|
---|
686 | }
|
---|
687 | }
|
---|
688 |
|
---|
689 | #endregion HYCALPER AUTO GENERATED CODE
|
---|
690 | }
|
---|
691 | }
|
---|