comparison liboctave/numeric/sparse-lu.cc @ 21146:ea9c05014809

revamp sparse LU factorization classes * sparse-lu.h, sparse-lu.cc: Rename from sparse-base-lu.h and sparse-base-lu.cc, respectively. (class sparse_lu): Rename from sparse_base_lu. Incorporate code from SparseCmplxLU and SparsedbleLU classes into the sparse_lu template. * sparse-lu-inst.cc: New file. * SparseCmplxLU.cc, SparseCmplxLU.h, SparsedbleLU.cc, SparsedbleLU.h: Delete. * lu.cc, luinc.cc, CSparse.cc, dSparse.cc, eigs-base.cc: Change all uses of SparsedbleLU and SparseCmplxLU to use new sparse_lu template class. * liboctave/numeric/module.mk: Update.
author John W. Eaton <jwe@octave.org>
date Thu, 28 Jan 2016 00:15:33 -0500
parents liboctave/numeric/sparse-base-lu.cc@538b57866b90
children a10f60e13243
comparison
equal deleted inserted replaced
21145:307096fb67e1 21146:ea9c05014809
1 /*
2
3 Copyright (C) 2004-2015 David Bateman
4 Copyright (C) 1998-2004 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 "CSparse.h"
29 #include "PermMatrix.h"
30 #include "dSparse.h"
31 #include "lo-error.h"
32 #include "oct-locbuf.h"
33 #include "oct-sparse.h"
34 #include "oct-spparms.h"
35 #include "sparse-lu.h"
36
37 // Wrappers for SuiteSparse (formerly UMFPACK) functions that have
38 // different names depending on the sparse matrix data type.
39 //
40 // All of these functions must be specialized to forward to the correct
41 // SuiteSparse functions.
42
43 template <typename T>
44 void
45 umfpack_defaults (double *Control);
46
47 template <typename T>
48 void
49 umfpack_free_numeric (void **Numeric);
50
51 template <typename T>
52 void
53 umfpack_free_symbolic (void **Symbolic);
54
55 template <typename T>
56 octave_idx_type
57 umfpack_get_lunz (octave_idx_type *lnz, octave_idx_type *unz, void *Numeric);
58
59 template <typename T>
60 octave_idx_type
61 umfpack_get_numeric (octave_idx_type *Lp, octave_idx_type *Lj,
62 T *Lx, // Or Lz_packed
63 octave_idx_type *Up, octave_idx_type *Ui,
64 T *Ux, // Or Uz_packed
65 octave_idx_type *p, octave_idx_type *q,
66 double *Dz_packed, octave_idx_type *do_recip,
67 double *Rs, void *Numeric);
68
69 template <typename T>
70 octave_idx_type
71 umfpack_numeric (const octave_idx_type *Ap, const octave_idx_type *Ai,
72 const T *Ax, // Or Az_packed
73 void *Symbolic, void **Numeric,
74 const double *Control, double *Info);
75
76 template <typename T>
77 octave_idx_type
78 umfpack_qsymbolic (octave_idx_type n_row, octave_idx_type n_col,
79 const octave_idx_type *Ap, const octave_idx_type *Ai,
80 const T *Ax, // Or Az_packed
81 const octave_idx_type *Qinit, void **Symbolic,
82 const double *Control, double *Info);
83
84 template <typename T>
85 void
86 umfpack_report_control (const double *Control);
87
88 template <typename T>
89 void
90 umfpack_report_info (const double *Control, const double *Info);
91
92 template <typename T>
93 void
94 umfpack_report_matrix (octave_idx_type n_row, octave_idx_type n_col,
95 const octave_idx_type *Ap, const octave_idx_type *Ai,
96 const T *Ax, // Or Az_packed
97 octave_idx_type col_form, const double *Control);
98
99 template <typename T>
100 void
101 umfpack_report_numeric (void *Numeric, const double *Control);
102
103 template <typename T>
104 void
105 umfpack_report_perm (octave_idx_type np, const octave_idx_type *Perm,
106 const double *Control);
107
108 template <typename T>
109 void
110 umfpack_report_status (double *Control, octave_idx_type status);
111
112 template <typename T>
113 void
114 umfpack_report_symbolic (void *Symbolic, const double *Control);
115
116 // SparseMatrix Specialization.
117
118 template <>
119 inline void
120 umfpack_defaults<double> (double *Control)
121 {
122 UMFPACK_DNAME (defaults) (Control);
123 }
124
125 template <>
126 inline void
127 umfpack_free_numeric<double> (void **Numeric)
128 {
129 UMFPACK_DNAME (free_numeric) (Numeric);
130 }
131
132 template <>
133 inline void
134 umfpack_free_symbolic<double> (void **Symbolic)
135 {
136 UMFPACK_DNAME (free_symbolic) (Symbolic);
137 }
138
139 template <>
140 inline octave_idx_type
141 umfpack_get_lunz<double>
142 (octave_idx_type *lnz, octave_idx_type *unz, void *Numeric)
143 {
144 octave_idx_type ignore1, ignore2, ignore3;
145
146 return UMFPACK_DNAME (get_lunz) (lnz, unz, &ignore1, &ignore2,
147 &ignore3, Numeric);
148 }
149
150 template <>
151 inline octave_idx_type
152 umfpack_get_numeric<double>
153 (octave_idx_type *Lp, octave_idx_type *Lj, double *Lx,
154 octave_idx_type *Up, octave_idx_type *Ui, double *Ux,
155 octave_idx_type *p, octave_idx_type *q, double *Dx,
156 octave_idx_type *do_recip, double *Rs, void *Numeric)
157 {
158 return UMFPACK_DNAME (get_numeric) (Lp, Lj, Lx, Up, Ui, Ux, p, q, Dx,
159 do_recip, Rs, Numeric);
160 }
161
162 template <>
163 inline octave_idx_type
164 umfpack_numeric<double>
165 (const octave_idx_type *Ap, const octave_idx_type *Ai,
166 const double *Ax, void *Symbolic, void **Numeric,
167 const double *Control, double *Info)
168 {
169 return UMFPACK_DNAME (numeric) (Ap, Ai, Ax, Symbolic, Numeric, Control,
170 Info);
171 }
172
173 template <>
174 inline octave_idx_type
175 umfpack_qsymbolic<double>
176 (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap,
177 const octave_idx_type *Ai, const double *Ax,
178 const octave_idx_type *Qinit, void **Symbolic,
179 const double *Control, double *Info)
180 {
181 return UMFPACK_DNAME (qsymbolic) (n_row, n_col, Ap, Ai, Ax, Qinit,
182 Symbolic, Control, Info);
183 }
184
185 template <>
186 inline void
187 umfpack_report_control<double> (const double *Control)
188 {
189 UMFPACK_DNAME (report_control) (Control);
190 }
191
192 template <>
193 inline void
194 umfpack_report_info<double> (const double *Control, const double *Info)
195 {
196 UMFPACK_DNAME (report_info) (Control, Info);
197 }
198
199 template <>
200 inline void
201 umfpack_report_matrix<double>
202 (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap,
203 const octave_idx_type *Ai, const double *Ax, octave_idx_type col_form,
204 const double *Control)
205 {
206 UMFPACK_DNAME (report_matrix) (n_row, n_col, Ap, Ai, Ax, col_form, Control);
207 }
208
209 template <>
210 inline void
211 umfpack_report_numeric<double> (void *Numeric, const double *Control)
212 {
213 UMFPACK_DNAME (report_numeric) (Numeric, Control);
214 }
215
216 template <>
217 inline void
218 umfpack_report_perm<double>
219 (octave_idx_type np, const octave_idx_type *Perm, const double *Control)
220 {
221 UMFPACK_DNAME (report_perm) (np, Perm, Control);
222 }
223
224 template <>
225 inline void
226 umfpack_report_status<double> (double *Control, octave_idx_type status)
227 {
228 UMFPACK_DNAME (report_status) (Control, status);
229 }
230
231 template <>
232 inline void
233 umfpack_report_symbolic<double> (void *Symbolic, const double *Control)
234 {
235 UMFPACK_DNAME (report_symbolic) (Symbolic, Control);
236 }
237
238 // SparseComplexMatrix specialization.
239
240 template <>
241 inline void
242 umfpack_defaults<Complex> (double *Control)
243 {
244 UMFPACK_ZNAME (defaults) (Control);
245 }
246
247 template <>
248 inline void
249 umfpack_free_numeric<Complex> (void **Numeric)
250 {
251 UMFPACK_ZNAME (free_numeric) (Numeric);
252 }
253
254 template <>
255 inline void
256 umfpack_free_symbolic<Complex> (void **Symbolic)
257 {
258 UMFPACK_ZNAME (free_symbolic) (Symbolic);
259 }
260
261 template <>
262 inline octave_idx_type
263 umfpack_get_lunz<Complex>
264 (octave_idx_type *lnz, octave_idx_type *unz, void *Numeric)
265 {
266 octave_idx_type ignore1, ignore2, ignore3;
267
268 return UMFPACK_ZNAME (get_lunz) (lnz, unz, &ignore1, &ignore2,
269 &ignore3, Numeric);
270 }
271
272 template <>
273 inline octave_idx_type
274 umfpack_get_numeric<Complex>
275 (octave_idx_type *Lp, octave_idx_type *Lj, Complex *Lz,
276 octave_idx_type *Up, octave_idx_type *Ui, Complex *Uz,
277 octave_idx_type *p, octave_idx_type *q, double *Dz,
278 octave_idx_type *do_recip, double *Rs, void *Numeric)
279 {
280 return UMFPACK_ZNAME (get_numeric) (Lp, Lj,
281 reinterpret_cast<double *> (Lz),
282 0, Up, Ui,
283 reinterpret_cast<double *> (Uz),
284 0, p, q,
285 reinterpret_cast<double *> (Dz),
286 0, do_recip, Rs, Numeric);
287 }
288
289 template <>
290 inline octave_idx_type
291 umfpack_numeric<Complex>
292 (const octave_idx_type *Ap, const octave_idx_type *Ai,
293 const Complex *Az, void *Symbolic, void **Numeric,
294 const double *Control, double *Info)
295 {
296 return UMFPACK_ZNAME (numeric) (Ap, Ai,
297 reinterpret_cast<const double *> (Az),
298 0, Symbolic, Numeric, Control, Info);
299 }
300
301
302 template <>
303 inline octave_idx_type
304 umfpack_qsymbolic<Complex>
305 (octave_idx_type n_row, octave_idx_type n_col,
306 const octave_idx_type *Ap, const octave_idx_type *Ai,
307 const Complex *Az, const octave_idx_type *Qinit,
308 void **Symbolic, const double *Control, double *Info)
309 {
310 return UMFPACK_ZNAME (qsymbolic) (n_row, n_col, Ap, Ai,
311 reinterpret_cast<const double *> (Az),
312 0, Qinit, Symbolic, Control, Info);
313 }
314
315
316 template <>
317 inline void
318 umfpack_report_control<Complex> (const double *Control)
319 {
320 UMFPACK_ZNAME (report_control) (Control);
321 }
322
323 template <>
324 inline void
325 umfpack_report_info<Complex> (const double *Control, const double *Info)
326 {
327 UMFPACK_ZNAME (report_info) (Control, Info);
328 }
329
330 template <>
331 inline void
332 umfpack_report_matrix<Complex>
333 (octave_idx_type n_row, octave_idx_type n_col,
334 const octave_idx_type *Ap, const octave_idx_type *Ai,
335 const Complex *Az, octave_idx_type col_form, const double *Control)
336 {
337 UMFPACK_ZNAME (report_matrix) (n_row, n_col, Ap, Ai,
338 reinterpret_cast<const double *> (Az),
339 0, col_form, Control);
340 }
341
342 template <>
343 inline void
344 umfpack_report_numeric<Complex> (void *Numeric, const double *Control)
345 {
346 UMFPACK_ZNAME (report_numeric) (Numeric, Control);
347 }
348
349 template <>
350 inline void
351 umfpack_report_perm<Complex>
352 (octave_idx_type np, const octave_idx_type *Perm, const double *Control)
353 {
354 UMFPACK_ZNAME (report_perm) (np, Perm, Control);
355 }
356
357 template <>
358 inline void
359 umfpack_report_status<Complex> (double *Control, octave_idx_type status)
360 {
361 UMFPACK_ZNAME (report_status) (Control, status);
362 }
363
364 template <>
365 inline void
366 umfpack_report_symbolic <Complex> (void *Symbolic, const double *Control)
367 {
368 UMFPACK_ZNAME (report_symbolic) (Symbolic, Control);
369 }
370
371 template <typename lu_type>
372 sparse_lu<lu_type>::sparse_lu (const lu_type& a, const Matrix& piv_thres,
373 bool scale)
374 : Lfact (), Ufact (), Rfact (), cond (0), P (), Q ()
375 {
376 #ifdef HAVE_UMFPACK
377 octave_idx_type nr = a.rows ();
378 octave_idx_type nc = a.cols ();
379
380 // Setup the control parameters
381 Matrix Control (UMFPACK_CONTROL, 1);
382 double *control = Control.fortran_vec ();
383 umfpack_defaults<lu_elt_type> (control);
384
385 double tmp = octave_sparse_params::get_key ("spumoni");
386 if (! xisnan (tmp))
387 Control (UMFPACK_PRL) = tmp;
388
389 if (piv_thres.numel () == 2)
390 {
391 tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0));
392 if (! xisnan (tmp))
393 Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
394 tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1));
395 if (! xisnan (tmp))
396 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
397 }
398 else
399 {
400 tmp = octave_sparse_params::get_key ("piv_tol");
401 if (! xisnan (tmp))
402 Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
403
404 tmp = octave_sparse_params::get_key ("sym_tol");
405 if (! xisnan (tmp))
406 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
407 }
408
409 // Set whether we are allowed to modify Q or not
410 tmp = octave_sparse_params::get_key ("autoamd");
411 if (! xisnan (tmp))
412 Control (UMFPACK_FIXQ) = tmp;
413
414 // Turn-off UMFPACK scaling for LU
415 if (scale)
416 Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM;
417 else
418 Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;
419
420 umfpack_report_control<lu_elt_type> (control);
421
422 const octave_idx_type *Ap = a.cidx ();
423 const octave_idx_type *Ai = a.ridx ();
424 const lu_elt_type *Ax = a.data ();
425
426 umfpack_report_matrix<lu_elt_type> (nr, nc, Ap, Ai, Ax, static_cast<octave_idx_type> (1), control);
427
428 void *Symbolic;
429 Matrix Info (1, UMFPACK_INFO);
430 double *info = Info.fortran_vec ();
431 int status = umfpack_qsymbolic<lu_elt_type> (nr, nc, Ap, Ai, Ax, 0, &Symbolic, control, info);
432
433 if (status < 0)
434 {
435 umfpack_report_status<lu_elt_type> (control, status);
436 umfpack_report_info<lu_elt_type> (control, info);
437
438 umfpack_free_symbolic<lu_elt_type> (&Symbolic);
439
440 (*current_liboctave_error_handler)
441 ("sparse_lu: symbolic factorization failed");
442 }
443 else
444 {
445 umfpack_report_symbolic<lu_elt_type> (Symbolic, control);
446
447 void *Numeric;
448 status = umfpack_numeric<lu_elt_type> (Ap, Ai, Ax, Symbolic, &Numeric, control, info);
449 umfpack_free_symbolic<lu_elt_type> (&Symbolic);
450
451 cond = Info (UMFPACK_RCOND);
452
453 if (status < 0)
454 {
455 umfpack_report_status<lu_elt_type> (control, status);
456 umfpack_report_info<lu_elt_type> (control, info);
457
458 umfpack_free_numeric<lu_elt_type> (&Numeric);
459
460 (*current_liboctave_error_handler)
461 ("sparse_lu: numeric factorization failed");
462 }
463 else
464 {
465 umfpack_report_numeric<lu_elt_type> (Numeric, control);
466
467 octave_idx_type lnz, unz;
468 status = umfpack_get_lunz<lu_elt_type> (&lnz, &unz, Numeric);
469
470 if (status < 0)
471 {
472 umfpack_report_status<lu_elt_type> (control, status);
473 umfpack_report_info<lu_elt_type> (control, info);
474
475 umfpack_free_numeric<lu_elt_type> (&Numeric);
476
477 (*current_liboctave_error_handler)
478 ("sparse_lu: extracting LU factors failed");
479 }
480 else
481 {
482 octave_idx_type n_inner = (nr < nc ? nr : nc);
483
484 if (lnz < 1)
485 Lfact = lu_type (n_inner, nr, static_cast<octave_idx_type> (1));
486 else
487 Lfact = lu_type (n_inner, nr, lnz);
488
489 octave_idx_type *Ltp = Lfact.cidx ();
490 octave_idx_type *Ltj = Lfact.ridx ();
491 lu_elt_type *Ltx = Lfact.data ();
492
493 if (unz < 1)
494 Ufact = lu_type (n_inner, nc, static_cast<octave_idx_type> (1));
495 else
496 Ufact = lu_type (n_inner, nc, unz);
497
498 octave_idx_type *Up = Ufact.cidx ();
499 octave_idx_type *Uj = Ufact.ridx ();
500 lu_elt_type *Ux = Ufact.data ();
501
502 Rfact = SparseMatrix (nr, nr, nr);
503 for (octave_idx_type i = 0; i < nr; i++)
504 {
505 Rfact.xridx (i) = i;
506 Rfact.xcidx (i) = i;
507 }
508 Rfact.xcidx (nr) = nr;
509 double *Rx = Rfact.data ();
510
511 P.resize (dim_vector (nr, 1));
512 octave_idx_type *p = P.fortran_vec ();
513
514 Q.resize (dim_vector (nc, 1));
515 octave_idx_type *q = Q.fortran_vec ();
516
517 octave_idx_type do_recip;
518 status = umfpack_get_numeric<lu_elt_type> (Ltp, Ltj, Ltx, Up, Uj, Ux, p, q, 0, &do_recip, Rx, Numeric);
519
520 umfpack_free_numeric<lu_elt_type> (&Numeric);
521
522 if (status < 0)
523 {
524 umfpack_report_status<lu_elt_type> (control, status);
525
526 (*current_liboctave_error_handler)
527 ("sparse_lu: extracting LU factors failed");
528 }
529 else
530 {
531 Lfact = Lfact.transpose ();
532
533 if (do_recip)
534 for (octave_idx_type i = 0; i < nr; i++)
535 Rx[i] = 1.0 / Rx[i];
536
537 umfpack_report_matrix<lu_elt_type> (nr, n_inner, Lfact.cidx (), Lfact.ridx (), Lfact.data (), static_cast<octave_idx_type> (1), control);
538 umfpack_report_matrix<lu_elt_type> (n_inner, nc, Ufact.cidx (), Ufact.ridx (), Ufact.data (), static_cast<octave_idx_type> (1), control);
539 umfpack_report_perm<lu_elt_type> (nr, p, control);
540 umfpack_report_perm<lu_elt_type> (nc, q, control);
541 }
542
543 umfpack_report_info<lu_elt_type> (control, info);
544 }
545 }
546 }
547
548 #else
549 (*current_liboctave_error_handler)
550 ("support for UMFPACK was unavailable or disabled when liboctave was built");
551 #endif
552 }
553
554 template <typename lu_type>
555 sparse_lu<lu_type>::sparse_lu (const lu_type& a,
556 const ColumnVector& Qinit,
557 const Matrix& piv_thres, bool scale,
558 bool FixedQ, double droptol,
559 bool milu, bool udiag)
560 : Lfact (), Ufact (), Rfact (), cond (0), P (), Q ()
561 {
562 #ifdef HAVE_UMFPACK
563 if (milu)
564 (*current_liboctave_error_handler)
565 ("Modified incomplete LU not implemented");
566
567 octave_idx_type nr = a.rows ();
568 octave_idx_type nc = a.cols ();
569
570 // Setup the control parameters
571 Matrix Control (UMFPACK_CONTROL, 1);
572 double *control = Control.fortran_vec ();
573 umfpack_defaults<lu_elt_type> (control);
574
575 double tmp = octave_sparse_params::get_key ("spumoni");
576 if (! xisnan (tmp))
577 Control (UMFPACK_PRL) = tmp;
578
579 if (piv_thres.numel () == 2)
580 {
581 tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0));
582 if (! xisnan (tmp))
583 Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
584 tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1));
585 if (! xisnan (tmp))
586 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
587 }
588 else
589 {
590 tmp = octave_sparse_params::get_key ("piv_tol");
591 if (! xisnan (tmp))
592 Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
593
594 tmp = octave_sparse_params::get_key ("sym_tol");
595 if (! xisnan (tmp))
596 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
597 }
598
599 if (droptol >= 0.)
600 Control (UMFPACK_DROPTOL) = droptol;
601
602 // Set whether we are allowed to modify Q or not
603 if (FixedQ)
604 Control (UMFPACK_FIXQ) = 1.0;
605 else
606 {
607 tmp = octave_sparse_params::get_key ("autoamd");
608 if (! xisnan (tmp))
609 Control (UMFPACK_FIXQ) = tmp;
610 }
611
612 // Turn-off UMFPACK scaling for LU
613 if (scale)
614 Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM;
615 else
616 Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;
617
618 umfpack_report_control<lu_elt_type> (control);
619
620 const octave_idx_type *Ap = a.cidx ();
621 const octave_idx_type *Ai = a.ridx ();
622 const lu_elt_type *Ax = a.data ();
623
624 umfpack_report_matrix<lu_elt_type> (nr, nc, Ap, Ai, Ax, static_cast<octave_idx_type> (1), control);
625
626 void *Symbolic;
627 Matrix Info (1, UMFPACK_INFO);
628 double *info = Info.fortran_vec ();
629 int status;
630
631 // Null loop so that qinit is imediately deallocated when not needed
632 do
633 {
634 OCTAVE_LOCAL_BUFFER (octave_idx_type, qinit, nc);
635
636 for (octave_idx_type i = 0; i < nc; i++)
637 qinit[i] = static_cast<octave_idx_type> (Qinit (i));
638
639 status = umfpack_qsymbolic<lu_elt_type> (nr, nc, Ap, Ai, Ax, qinit, &Symbolic, control, info);
640 }
641 while (0);
642
643 if (status < 0)
644 {
645 umfpack_report_status<lu_elt_type> (control, status);
646 umfpack_report_info<lu_elt_type> (control, info);
647
648 umfpack_free_symbolic<lu_elt_type> (&Symbolic);
649
650 (*current_liboctave_error_handler)
651 ("sparse_lu: symbolic factorization failed");
652 }
653 else
654 {
655 umfpack_report_symbolic<lu_elt_type> (Symbolic, control);
656
657 void *Numeric;
658 status = umfpack_numeric<lu_elt_type> (Ap, Ai, Ax, Symbolic, &Numeric, control, info);
659 umfpack_free_symbolic<lu_elt_type> (&Symbolic);
660
661 cond = Info (UMFPACK_RCOND);
662
663 if (status < 0)
664 {
665 umfpack_report_status<lu_elt_type> (control, status);
666 umfpack_report_info<lu_elt_type> (control, info);
667
668 umfpack_free_numeric<lu_elt_type> (&Numeric);
669
670 (*current_liboctave_error_handler)
671 ("sparse_lu: numeric factorization failed");
672 }
673 else
674 {
675 umfpack_report_numeric<lu_elt_type> (Numeric, control);
676
677 octave_idx_type lnz, unz;
678 status = umfpack_get_lunz<lu_elt_type> (&lnz, &unz, Numeric);
679
680 if (status < 0)
681 {
682 umfpack_report_status<lu_elt_type> (control, status);
683 umfpack_report_info<lu_elt_type> (control, info);
684
685 umfpack_free_numeric<lu_elt_type> (&Numeric);
686
687 (*current_liboctave_error_handler)
688 ("sparse_lu: extracting LU factors failed");
689 }
690 else
691 {
692 octave_idx_type n_inner = (nr < nc ? nr : nc);
693
694 if (lnz < 1)
695 Lfact = lu_type (n_inner, nr, static_cast<octave_idx_type> (1));
696 else
697 Lfact = lu_type (n_inner, nr, lnz);
698
699 octave_idx_type *Ltp = Lfact.cidx ();
700 octave_idx_type *Ltj = Lfact.ridx ();
701 lu_elt_type *Ltx = Lfact.data ();
702
703 if (unz < 1)
704 Ufact = lu_type (n_inner, nc, static_cast<octave_idx_type> (1));
705 else
706 Ufact = lu_type (n_inner, nc, unz);
707
708 octave_idx_type *Up = Ufact.cidx ();
709 octave_idx_type *Uj = Ufact.ridx ();
710 lu_elt_type *Ux = Ufact.data ();
711
712 Rfact = SparseMatrix (nr, nr, nr);
713 for (octave_idx_type i = 0; i < nr; i++)
714 {
715 Rfact.xridx (i) = i;
716 Rfact.xcidx (i) = i;
717 }
718 Rfact.xcidx (nr) = nr;
719 double *Rx = Rfact.data ();
720
721 P.resize (dim_vector (nr, 1));
722 octave_idx_type *p = P.fortran_vec ();
723
724 Q.resize (dim_vector (nc, 1));
725 octave_idx_type *q = Q.fortran_vec ();
726
727 octave_idx_type do_recip;
728 status = umfpack_get_numeric<lu_elt_type> (Ltp, Ltj, Ltx, Up, Uj, Ux, p, q, 0, &do_recip, Rx, Numeric);
729
730 umfpack_free_numeric<lu_elt_type> (&Numeric);
731
732 if (status < 0)
733 {
734 umfpack_report_status<lu_elt_type> (control, status);
735
736 (*current_liboctave_error_handler)
737 ("sparse_lu: extracting LU factors failed");
738 }
739 else
740 {
741 Lfact = Lfact.transpose ();
742
743 if (do_recip)
744 for (octave_idx_type i = 0; i < nr; i++)
745 Rx[i] = 1.0 / Rx[i];
746
747 umfpack_report_matrix<lu_elt_type> (nr, n_inner, Lfact.cidx (), Lfact.ridx (), Lfact.data (), static_cast<octave_idx_type> (1), control);
748 umfpack_report_matrix<lu_elt_type> (n_inner, nc, Ufact.cidx (), Ufact.ridx (), Ufact.data (), static_cast<octave_idx_type> (1), control);
749 umfpack_report_perm<lu_elt_type> (nr, p, control);
750 umfpack_report_perm<lu_elt_type> (nc, q, control);
751 }
752
753 umfpack_report_info<lu_elt_type> (control, info);
754 }
755 }
756 }
757
758 if (udiag)
759 (*current_liboctave_error_handler)
760 ("Option udiag of incomplete LU not implemented");
761
762 #else
763 (*current_liboctave_error_handler)
764 ("support for UMFPACK was unavailable or disabled when liboctave was built");
765 #endif
766 }
767
768 template <typename lu_type>
769 lu_type
770 sparse_lu<lu_type>::Y (void) const
771 {
772 octave_idx_type nr = Lfact.rows ();
773 octave_idx_type nz = Lfact.cols ();
774 octave_idx_type nc = Ufact.cols ();
775
776 lu_type Yout (nr, nc, Lfact.nnz () + Ufact.nnz () - (nr<nz?nr:nz));
777 octave_idx_type ii = 0;
778 Yout.xcidx (0) = 0;
779
780 for (octave_idx_type j = 0; j < nc; j++)
781 {
782 for (octave_idx_type i = Ufact.cidx (j); i < Ufact.cidx (j + 1); i++)
783 {
784 Yout.xridx (ii) = Ufact.ridx (i);
785 Yout.xdata (ii++) = Ufact.data (i);
786 }
787 if (j < nz)
788 {
789 // Note the +1 skips the 1.0 on the diagonal
790 for (octave_idx_type i = Lfact.cidx (j) + 1;
791 i < Lfact.cidx (j +1); i++)
792 {
793 Yout.xridx (ii) = Lfact.ridx (i);
794 Yout.xdata (ii++) = Lfact.data (i);
795 }
796 }
797 Yout.xcidx (j + 1) = ii;
798 }
799
800 return Yout;
801 }
802
803 template <typename lu_type>
804 SparseMatrix
805 sparse_lu<lu_type>::Pr (void) const
806 {
807
808 octave_idx_type nr = Lfact.rows ();
809
810 SparseMatrix Pout (nr, nr, nr);
811
812 for (octave_idx_type i = 0; i < nr; i++)
813 {
814 Pout.cidx (i) = i;
815 Pout.ridx (P (i)) = i;
816 Pout.data (i) = 1;
817 }
818 Pout.cidx (nr) = nr;
819
820 return Pout;
821 }
822
823 template <typename lu_type>
824 ColumnVector
825 sparse_lu<lu_type>::Pr_vec (void) const
826 {
827
828 octave_idx_type nr = Lfact.rows ();
829
830 ColumnVector Pout (nr);
831
832 for (octave_idx_type i = 0; i < nr; i++)
833 Pout.xelem (i) = static_cast<double> (P(i) + 1);
834
835 return Pout;
836 }
837
838 template <typename lu_type>
839 PermMatrix
840 sparse_lu<lu_type>::Pr_mat (void) const
841 {
842 return PermMatrix (P, false);
843 }
844
845 template <typename lu_type>
846 SparseMatrix
847 sparse_lu<lu_type>::Pc (void) const
848 {
849 octave_idx_type nc = Ufact.cols ();
850
851 SparseMatrix Pout (nc, nc, nc);
852
853 for (octave_idx_type i = 0; i < nc; i++)
854 {
855 Pout.cidx (i) = i;
856 Pout.ridx (i) = Q (i);
857 Pout.data (i) = 1;
858 }
859 Pout.cidx (nc) = nc;
860
861 return Pout;
862 }
863
864 template <typename lu_type>
865 ColumnVector
866 sparse_lu<lu_type>::Pc_vec (void) const
867 {
868
869 octave_idx_type nc = Ufact.cols ();
870
871 ColumnVector Pout (nc);
872
873 for (octave_idx_type i = 0; i < nc; i++)
874 Pout.xelem (i) = static_cast<double> (Q(i) + 1);
875
876 return Pout;
877 }
878
879 template <typename lu_type>
880 PermMatrix
881 sparse_lu<lu_type>::Pc_mat (void) const
882 {
883 return PermMatrix (Q, true);
884 }