Mercurial > octave-nkf
comparison src/DLD-FUNCTIONS/splu.cc @ 5164:57077d0ddc8e
[project @ 2005-02-25 19:55:24 by jwe]
author | jwe |
---|---|
date | Fri, 25 Feb 2005 19:55:28 +0000 |
parents | |
children | 5bdc3f24cd5f |
comparison
equal
deleted
inserted
replaced
5163:9f3299378193 | 5164:57077d0ddc8e |
---|---|
1 /* | |
2 | |
3 Copyright (C) 2004 David Bateman | |
4 Copyright (C) 1998-2004 Andy Adler | |
5 | |
6 Octave is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 2, or (at your option) any | |
9 later version. | |
10 | |
11 Octave is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with this program; see the file COPYING. If not, write to the Free | |
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
19 | |
20 */ | |
21 | |
22 #ifdef HAVE_CONFIG_H | |
23 #include <config.h> | |
24 #endif | |
25 | |
26 #include "defun-dld.h" | |
27 #include "error.h" | |
28 #include "gripes.h" | |
29 #include "oct-obj.h" | |
30 #include "utils.h" | |
31 | |
32 #include "SparseCmplxLU.h" | |
33 #include "SparsedbleLU.h" | |
34 #include "ov-re-sparse.h" | |
35 #include "ov-cx-sparse.h" | |
36 | |
37 // PKG_ADD: dispatch ("lu", "splu", "sparse matrix") | |
38 // PKG_ADD: dispatch ("lu", "splu", "sparse complex matrix") | |
39 // PKG_ADD: dispatch ("lu", "splu", "sparse bool matrix") | |
40 DEFUN_DLD (splu, args, nargout, | |
41 "-*- texinfo -*-\n\ | |
42 @deftypefn {Loadable Function} {[@var{l}, @var{u}] =} splu (@var{a})\n\ | |
43 @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}] =} splu (@var{a})\n\ | |
44 @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}, @var{Q}] =} splu (@var{a})\n\ | |
45 @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}, @var{Q}] =} splu (@dots{}, @var{thres})\n\ | |
46 @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}] =} splu (@dots{}, @var{Q})\n\ | |
47 @cindex LU decomposition\n\ | |
48 Compute the LU decomposition of the sparse matrix @var{a}, using\n\ | |
49 subroutines from UMFPACK. The result is returned in a permuted\n\ | |
50 form, according to the optional return values @var{P} and @var{Q}.\n\ | |
51 \n\ | |
52 Called with two or three output arguments and a single input argument,\n\ | |
53 @dfn{splu} is a replacement for @dfn{lu}, and therefore the sparsity\n\ | |
54 preserving column permutations @var{Q} are not performed. Called with\n\ | |
55 a fourth output argument, the sparsity preserving column transformation\n\ | |
56 @var{Q} is returned, such that @code{@var{P} * @var{a} * @var{Q} =\n\ | |
57 @var{l} * @var{u}}.\n\ | |
58 \n\ | |
59 An additional input argument @var{thres}, that defines the pivoting\n\ | |
60 threshold can be given. Alternatively, the desired sparsity preserving\n\ | |
61 column permutations @var{Q} can be passed. Note that @var{Q} is assumed\n\ | |
62 to be fixed if three are fewer than four output arguments. Otherwise,\n\ | |
63 the updated column permutations are returned as the fourth argument.\n\ | |
64 \n\ | |
65 With two output arguments, returns the permuted forms of the upper and\n\ | |
66 lower triangular matrices, such that @code{@var{a} = @var{l} * @var{u}}.\n\ | |
67 With two or three output arguments, if a user-defined @var{Q} is given,\n\ | |
68 then @code{@var{u} * @var{Q}'} is returned. The matrix is not required to\n\ | |
69 be square.\n\ | |
70 @end deftypefn\n\ | |
71 @seealso{sparse, spinv, colamd, symamd}") | |
72 { | |
73 octave_value_list retval; | |
74 | |
75 int nargin = args.length (); | |
76 | |
77 if (nargin < 1 || nargin > 3 || nargout > 4) | |
78 { | |
79 print_usage ("splu"); | |
80 return retval; | |
81 } | |
82 | |
83 octave_value arg = args(0); | |
84 | |
85 int nr = arg.rows (); | |
86 int nc = arg.columns (); | |
87 | |
88 int arg_is_empty = empty_arg ("splu", nr, nc); | |
89 | |
90 if (arg_is_empty < 0) | |
91 return retval; | |
92 else if (arg_is_empty > 0) | |
93 return octave_value_list (3, SparseMatrix ()); | |
94 | |
95 ColumnVector Qinit; | |
96 bool have_Qinit = false; | |
97 double thres = -1.; | |
98 | |
99 for (int k = 1; k < nargin; k++) | |
100 { | |
101 if (args(k).class_name () == "sparse") | |
102 { | |
103 SparseMatrix tmp = args (k).sparse_matrix_value (); | |
104 | |
105 if (error_state) | |
106 { | |
107 error ("splu: Not a valid permutation/threshold"); | |
108 return retval; | |
109 } | |
110 | |
111 dim_vector dv = tmp.dims (); | |
112 | |
113 if (dv(0) == 1 && dv(1) == 1) | |
114 thres = tmp (0); | |
115 else if (dv(0) == 1 || dv(1) == 1) | |
116 { | |
117 int nel = tmp.numel (); | |
118 Qinit.resize (nel); | |
119 for (int i = 0; i < nel; i++) | |
120 Qinit (i) = tmp (i) - 1; | |
121 have_Qinit = true; | |
122 } | |
123 else | |
124 { | |
125 int t_nc = tmp.cols (); | |
126 | |
127 if (tmp.nnz () != t_nc) | |
128 error ("splu: Not a valid permutation matrix"); | |
129 else | |
130 { | |
131 for (int i = 0; i < t_nc + 1; i++) | |
132 if (tmp.cidx(i) != i) | |
133 { | |
134 error ("splu: Not a valid permutation matrix"); | |
135 break; | |
136 } | |
137 } | |
138 | |
139 if (!error_state) | |
140 { | |
141 for (int i = 0; i < t_nc; i++) | |
142 if (tmp.data (i) != 1.) | |
143 { | |
144 error ("splu: Not a valid permutation matrix"); | |
145 break; | |
146 } | |
147 else | |
148 Qinit (i) = tmp.ridx (i) - 1; | |
149 } | |
150 | |
151 if (! error_state) | |
152 have_Qinit = true; | |
153 } | |
154 } | |
155 else | |
156 { | |
157 NDArray tmp = args(k).array_value (); | |
158 | |
159 if (error_state) | |
160 return retval; | |
161 | |
162 dim_vector dv = tmp.dims (); | |
163 if (dv.length () > 2) | |
164 { | |
165 error ("splu: second argument must be a vector/matrix or a scalar"); | |
166 } | |
167 else if (dv(0) == 1 && dv(1) == 1) | |
168 thres = tmp (0); | |
169 else if (dv(0) == 1 || dv(1) == 1) | |
170 { | |
171 int nel = tmp.numel (); | |
172 Qinit.resize (nel); | |
173 for (int i = 0; i < nel; i++) | |
174 Qinit (i) = tmp (i) - 1; | |
175 have_Qinit = true; | |
176 } | |
177 else | |
178 { | |
179 SparseMatrix tmp2 (tmp); | |
180 | |
181 int t_nc = tmp2.cols (); | |
182 | |
183 if (tmp2.nnz () != t_nc) | |
184 error ("splu: Not a valid permutation matrix"); | |
185 else | |
186 { | |
187 for (int i = 0; i < t_nc + 1; i++) | |
188 if (tmp2.cidx(i) != i) | |
189 { | |
190 error ("splu: Not a valid permutation matrix"); | |
191 break; | |
192 } | |
193 } | |
194 | |
195 if (!error_state) | |
196 { | |
197 for (int i = 0; i < t_nc; i++) | |
198 if (tmp2.data (i) != 1.) | |
199 { | |
200 error ("splu: Not a valid permutation matrix"); | |
201 break; | |
202 } | |
203 else | |
204 Qinit (i) = tmp2.ridx (i) - 1; | |
205 } | |
206 | |
207 if (! error_state) | |
208 have_Qinit = true; | |
209 } | |
210 } | |
211 } | |
212 | |
213 if (error_state) | |
214 return retval; | |
215 | |
216 if (arg.is_real_type ()) | |
217 { | |
218 SparseMatrix m = arg.sparse_matrix_value (); | |
219 | |
220 if (nargout < 4 && ! have_Qinit) | |
221 { | |
222 int m_nc = m.cols (); | |
223 Qinit.resize (m_nc); | |
224 for (int i = 0; i < m_nc; i++) | |
225 Qinit (i) = i; | |
226 } | |
227 | |
228 if (! error_state) | |
229 { | |
230 switch (nargout) | |
231 { | |
232 case 0: | |
233 case 1: | |
234 case 2: | |
235 { | |
236 SparseLU fact (m, Qinit, thres, true); | |
237 | |
238 SparseMatrix P = fact.Pr (); | |
239 SparseMatrix L = P.transpose () * fact.L (); | |
240 if (have_Qinit) | |
241 retval(1) = fact.U () * fact.Pc ().transpose (); | |
242 else | |
243 retval(1) = fact.U (); | |
244 | |
245 retval(0) = L; | |
246 } | |
247 break; | |
248 | |
249 case 3: | |
250 { | |
251 SparseLU fact (m, Qinit, thres, true); | |
252 | |
253 retval(2) = fact.Pr (); | |
254 if (have_Qinit) | |
255 retval(1) = fact.U () * fact.Pc ().transpose (); | |
256 else | |
257 retval(1) = fact.U (); | |
258 retval(0) = fact.L (); | |
259 } | |
260 break; | |
261 | |
262 case 4: | |
263 default: | |
264 { | |
265 if (have_Qinit) | |
266 { | |
267 SparseLU fact (m, Qinit, thres, false); | |
268 | |
269 retval(3) = fact.Pc (); | |
270 retval(2) = fact.Pr (); | |
271 retval(1) = fact.U (); | |
272 retval(0) = fact.L (); | |
273 } | |
274 else | |
275 { | |
276 SparseLU fact (m, thres); | |
277 | |
278 retval(3) = fact.Pc (); | |
279 retval(2) = fact.Pr (); | |
280 retval(1) = fact.U (); | |
281 retval(0) = fact.L (); | |
282 } | |
283 } | |
284 break; | |
285 } | |
286 } | |
287 } | |
288 else if (arg.is_complex_type ()) | |
289 { | |
290 SparseComplexMatrix m = arg.sparse_complex_matrix_value (); | |
291 | |
292 if (nargout < 4 && ! have_Qinit) | |
293 { | |
294 int m_nc = m.cols (); | |
295 Qinit.resize (m_nc); | |
296 for (int i = 0; i < m_nc; i++) | |
297 Qinit (i) = i; | |
298 } | |
299 | |
300 if (! error_state) | |
301 { | |
302 switch (nargout) | |
303 { | |
304 case 0: | |
305 case 1: | |
306 case 2: | |
307 { | |
308 SparseComplexLU fact (m, Qinit, thres, true); | |
309 | |
310 SparseMatrix P = fact.Pr (); | |
311 SparseComplexMatrix L = P.transpose () * fact.L (); | |
312 | |
313 if (have_Qinit) | |
314 retval(1) = fact.U () * fact.Pc ().transpose (); | |
315 else | |
316 retval(1) = fact.U (); | |
317 retval(0) = L; | |
318 } | |
319 break; | |
320 | |
321 case 3: | |
322 { | |
323 SparseComplexLU fact (m, Qinit, thres, true); | |
324 | |
325 retval(2) = fact.Pr (); | |
326 if (have_Qinit) | |
327 retval(1) = fact.U () * fact.Pc ().transpose (); | |
328 else | |
329 retval(1) = fact.U (); | |
330 retval(0) = fact.L (); | |
331 } | |
332 break; | |
333 | |
334 case 4: | |
335 default: | |
336 { | |
337 if (have_Qinit) | |
338 { | |
339 SparseComplexLU fact (m, Qinit, thres, false); | |
340 | |
341 retval(3) = fact.Pc (); | |
342 retval(2) = fact.Pr (); | |
343 retval(1) = fact.U (); | |
344 retval(0) = fact.L (); | |
345 } | |
346 else | |
347 { | |
348 SparseComplexLU fact (m, thres); | |
349 | |
350 retval(3) = fact.Pc (); | |
351 retval(2) = fact.Pr (); | |
352 retval(1) = fact.U (); | |
353 retval(0) = fact.L (); | |
354 } | |
355 } | |
356 break; | |
357 } | |
358 } | |
359 } | |
360 else | |
361 { | |
362 gripe_wrong_type_arg ("splu", arg); | |
363 } | |
364 | |
365 return retval; | |
366 } | |
367 | |
368 // PKG_ADD: dispatch ("inv", "spinv", "sparse matrix") | |
369 // PKG_ADD: dispatch ("inv", "spinv", "sparse complex matrix") | |
370 // PKG_ADD: dispatch ("inv", "spinv", "sparse bool matrix") | |
371 // PKG_ADD: dispatch ("inverse", "spinv", "sparse matrix") | |
372 // PKG_ADD: dispatch ("inverse", "spinv", "sparse complex matrix") | |
373 // PKG_ADD: dispatch ("inverse", "spinv", "sparse bool matrix") | |
374 DEFUN_DLD (spinv, args, nargout, | |
375 "-*- texinfo -*-\n\ | |
376 @deftypefn {Loadable Function} {[@var{x}, @var{rcond}] = } spinv (@var{a}, @var{Q})\n\ | |
377 @deftypefnx {Loadable Function} {[@var{x}, @var{rcond}, @var{Q}] = } spinv (@var{a}, @var{Q})\n\ | |
378 Compute the inverse of the square matrix @var{a}. Return an estimate\n\ | |
379 of the reciprocal condition number if requested, otherwise warn of an\n\ | |
380 ill-conditioned matrix if the reciprocal condition number is small.\n\ | |
381 \n\ | |
382 An optional second input argument @var{Q} is the optional pre-ordering of\n\ | |
383 the matrix, such that @code{@var{x} = inv (@var{a} (:, @var{Q}))}. @var{Q}\n\ | |
384 can equally be a matrix, in which case @code{@var{x} = inv (@var{a} *\n\ | |
385 @var{Q}))}.\n\ | |
386 \n\ | |
387 If a third output argument is given then the permuations to achieve a sparse\n\ | |
388 inverse are returned. It is not required that the return column permutations\n\ | |
389 @var{Q} and the same as the user supplied permutations\n\ | |
390 @end deftypefn") | |
391 { | |
392 error ("spinv: not implemented yet"); | |
393 return octave_value (); | |
394 } | |
395 | |
396 /* | |
397 ;;; Local Variables: *** | |
398 ;;; mode: C++ *** | |
399 ;;; End: *** | |
400 */ |