comparison src/DLD-FUNCTIONS/symbfact.cc @ 7515:f3c00dc0912b

Eliminate the rest of the dispatched sparse functions
author David Bateman <dbateman@free.fr>
date Fri, 22 Feb 2008 15:50:51 +0100
parents src/DLD-FUNCTIONS/spchol.cc@daff886a8e2a
children b166043585a8
comparison
equal deleted inserted replaced
7514:4f6a73fd8df9 7515:f3c00dc0912b
1 /*
2
3 Copyright (C) 2005, 2006, 2007 David Bateman
4 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Andy Adler
5
6 This file is part of Octave.
7
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include "SparseCmplxCHOL.h"
29 #include "SparsedbleCHOL.h"
30 #include "oct-spparms.h"
31 #include "sparse-util.h"
32
33 #include "ov-re-sparse.h"
34 #include "ov-cx-sparse.h"
35 #include "defun-dld.h"
36 #include "error.h"
37 #include "gripes.h"
38 #include "oct-obj.h"
39 #include "utils.h"
40
41 DEFUN_DLD (symbfact, args, nargout,
42 "-*- texinfo -*-\n\
43 @deftypefn {Loadable Function} {[@var{count}, @var{h}, @var{parent}, @var{post}, @var{r}] =} symbfact (@var{s}, @var{typ}, @var{mode})\n\
44 \n\
45 Performs a symbolic factorization analysis on the sparse matrix @var{s}.\n\
46 Where\n\
47 \n\
48 @table @asis\n\
49 @item @var{s}\n\
50 @var{s} is a complex or real sparse matrix.\n\
51 \n\
52 @item @var{typ}\n\
53 Is the type of the factorization and can be one of\n\
54 \n\
55 @table @code\n\
56 @item sym\n\
57 Factorize @var{s}. This is the default.\n\
58 \n\
59 @item col\n\
60 Factorize @code{@var{s}' * @var{s}}.\n\
61 @item row\n\
62 Factorize @code{@var{s} * @var{s}'}.\n\
63 @item lo\n\
64 Factorize @code{@var{s}'}\n\
65 @end table\n\
66 \n\
67 @item @var{mode}\n\
68 The default is to return the Cholesky factorization for @var{r}, and if\n\
69 @var{mode} is 'L', the conjugate transpose of the Cholesky factorization\n\
70 is returned. The conjugate transpose version is faster and uses less\n\
71 memory, but returns the same values for @var{count}, @var{h}, @var{parent}\n\
72 and @var{post} outputs.\n\
73 @end table\n\
74 \n\
75 The output variables are\n\
76 \n\
77 @table @asis\n\
78 @item @var{count}\n\
79 The row counts of the Cholesky factorization as determined by @var{typ}.\n\
80 \n\
81 @item @var{h}\n\
82 The height of the elimination tree.\n\
83 \n\
84 @item @var{parent}\n\
85 The elimination tree itself.\n\
86 \n\
87 @item @var{post}\n\
88 A sparse boolean matrix whose structure is that of the Cholesky\n\
89 factorization as determined by @var{typ}.\n\
90 @end table\n\
91 @end deftypefn")
92 {
93 octave_value_list retval;
94 int nargin = args.length ();
95
96 if (nargin < 1 || nargin > 3 || nargout > 5)
97 {
98 print_usage ();
99 return retval;
100 }
101
102 #ifdef HAVE_CHOLMOD
103
104 cholmod_common Common;
105 cholmod_common *cm = &Common;
106 CHOLMOD_NAME(start) (cm);
107
108 double spu = octave_sparse_params::get_key ("spumoni");
109 if (spu == 0.)
110 {
111 cm->print = -1;
112 cm->print_function = NULL;
113 }
114 else
115 {
116 cm->print = static_cast<int> (spu) + 2;
117 cm->print_function =&SparseCholPrint;
118 }
119
120 cm->error_handler = &SparseCholError;
121 cm->complex_divide = CHOLMOD_NAME(divcomplex);
122 cm->hypotenuse = CHOLMOD_NAME(hypot);
123
124 double dummy;
125 cholmod_sparse Astore;
126 cholmod_sparse *A = &Astore;
127 A->packed = true;
128 A->sorted = true;
129 A->nz = NULL;
130 #ifdef IDX_TYPE_LONG
131 A->itype = CHOLMOD_LONG;
132 #else
133 A->itype = CHOLMOD_INT;
134 #endif
135 A->dtype = CHOLMOD_DOUBLE;
136 A->stype = 1;
137 A->x = &dummy;
138
139 if (args(0).is_real_type ())
140 {
141 const SparseMatrix a = args(0).sparse_matrix_value();
142 A->nrow = a.rows();
143 A->ncol = a.cols();
144 A->p = a.cidx();
145 A->i = a.ridx();
146 A->nzmax = a.nnz();
147 A->xtype = CHOLMOD_REAL;
148
149 if (a.rows() > 0 && a.cols() > 0)
150 A->x = a.data();
151 }
152 else if (args(0).is_complex_type ())
153 {
154 const SparseComplexMatrix a = args(0).sparse_complex_matrix_value();
155 A->nrow = a.rows();
156 A->ncol = a.cols();
157 A->p = a.cidx();
158 A->i = a.ridx();
159 A->nzmax = a.nnz();
160 A->xtype = CHOLMOD_COMPLEX;
161
162 if (a.rows() > 0 && a.cols() > 0)
163 A->x = a.data();
164 }
165 else
166 gripe_wrong_type_arg ("symbfact", arg(0));
167
168 octave_idx_type coletree = false;
169 octave_idx_type n = A->nrow;
170
171 if (nargin > 1)
172 {
173 char ch;
174 std::string str = args(1).string_value();
175 ch = tolower (str.c_str()[0]);
176 if (ch == 'r')
177 A->stype = 0;
178 else if (ch == 'c')
179 {
180 n = A->ncol;
181 coletree = true;
182 A->stype = 0;
183 }
184 else if (ch == 's')
185 A->stype = 1;
186 else if (ch == 's')
187 A->stype = -1;
188 else
189 error ("Unrecognized typ in symbolic factorization");
190 }
191
192 if (A->stype && A->nrow != A->ncol)
193 error ("Matrix must be square");
194
195 if (!error_state)
196 {
197 OCTAVE_LOCAL_BUFFER (octave_idx_type, Parent, n);
198 OCTAVE_LOCAL_BUFFER (octave_idx_type, Post, n);
199 OCTAVE_LOCAL_BUFFER (octave_idx_type, ColCount, n);
200 OCTAVE_LOCAL_BUFFER (octave_idx_type, First, n);
201 OCTAVE_LOCAL_BUFFER (octave_idx_type, Level, n);
202
203 cholmod_sparse *F = CHOLMOD_NAME(transpose) (A, 0, cm);
204 cholmod_sparse *Aup, *Alo;
205
206 if (A->stype == 1 || coletree)
207 {
208 Aup = A ;
209 Alo = F ;
210 }
211 else
212 {
213 Aup = F ;
214 Alo = A ;
215 }
216
217 CHOLMOD_NAME(etree) (Aup, Parent, cm);
218
219 if (cm->status < CHOLMOD_OK)
220 {
221 error("matrix corrupted");
222 goto symbfact_error;
223 }
224
225 if (CHOLMOD_NAME(postorder) (Parent, n, NULL, Post, cm) != n)
226 {
227 error("postorder failed");
228 goto symbfact_error;
229 }
230
231 CHOLMOD_NAME(rowcolcounts) (Alo, NULL, 0, Parent, Post, NULL,
232 ColCount, First, Level, cm);
233
234 if (cm->status < CHOLMOD_OK)
235 {
236 error("matrix corrupted");
237 goto symbfact_error;
238 }
239
240 if (nargout > 4)
241 {
242 cholmod_sparse *A1, *A2;
243
244 if (A->stype == 1)
245 {
246 A1 = A;
247 A2 = NULL;
248 }
249 else if (A->stype == -1)
250 {
251 A1 = F;
252 A2 = NULL;
253 }
254 else if (coletree)
255 {
256 A1 = F;
257 A2 = A;
258 }
259 else
260 {
261 A1 = A;
262 A2 = F;
263 }
264
265 // count the total number of entries in L
266 octave_idx_type lnz = 0 ;
267 for (octave_idx_type j = 0 ; j < n ; j++)
268 lnz += ColCount [j] ;
269
270
271 // allocate the output matrix L (pattern-only)
272 SparseBoolMatrix L (n, n, lnz);
273
274 // initialize column pointers
275 lnz = 0;
276 for (octave_idx_type j = 0 ; j < n ; j++)
277 {
278 L.xcidx(j) = lnz;
279 lnz += ColCount [j];
280 }
281 L.xcidx(n) = lnz;
282
283
284 /* create a copy of the column pointers */
285 octave_idx_type *W = First;
286 for (octave_idx_type j = 0 ; j < n ; j++)
287 W [j] = L.xcidx(j);
288
289 // get workspace for computing one row of L
290 cholmod_sparse *R = cholmod_allocate_sparse (n, 1, n, false, true,
291 0, CHOLMOD_PATTERN, cm);
292 octave_idx_type *Rp = static_cast<octave_idx_type *>(R->p);
293 octave_idx_type *Ri = static_cast<octave_idx_type *>(R->i);
294
295 // compute L one row at a time
296 for (octave_idx_type k = 0 ; k < n ; k++)
297 {
298 // get the kth row of L and store in the columns of L
299 CHOLMOD_NAME (row_subtree) (A1, A2, k, Parent, R, cm) ;
300 for (octave_idx_type p = 0 ; p < Rp [1] ; p++)
301 L.xridx (W [Ri [p]]++) = k ;
302
303 // add the diagonal entry
304 L.xridx (W [k]++) = k ;
305 }
306
307 // free workspace
308 cholmod_free_sparse (&R, cm) ;
309
310
311 // transpose L to get R, or leave as is
312 if (nargin < 3)
313 L = L.transpose ();
314
315 // fill numerical values of L with one's
316 for (octave_idx_type p = 0 ; p < lnz ; p++)
317 L.xdata(p) = true;
318
319 retval(4) = L;
320 }
321
322 ColumnVector tmp (n);
323 if (nargout > 3)
324 {
325 for (octave_idx_type i = 0; i < n; i++)
326 tmp(i) = Post[i] + 1;
327 retval(3) = tmp;
328 }
329
330 if (nargout > 2)
331 {
332 for (octave_idx_type i = 0; i < n; i++)
333 tmp(i) = Parent[i] + 1;
334 retval(2) = tmp;
335 }
336
337 if (nargout > 1)
338 {
339 /* compute the elimination tree height */
340 octave_idx_type height = 0 ;
341 for (int i = 0 ; i < n ; i++)
342 height = (height > Level[i] ? height : Level[i]);
343 height++ ;
344 retval(1) = static_cast<double> (height);
345 }
346
347 for (octave_idx_type i = 0; i < n; i++)
348 tmp(i) = ColCount[i];
349 retval(0) = tmp;
350 }
351
352 symbfact_error:
353 #else
354 error ("symbfact: not available in this version of Octave");
355 #endif
356
357 return retval;
358 }
359
360 /*
361 ;;; Local Variables: ***
362 ;;; mode: C++ ***
363 ;;; End: ***
364 */
365