GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
sparse-lu.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1998-2022 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include "CSparse.h"
31#include "PermMatrix.h"
32#include "dSparse.h"
33#include "lo-error.h"
34#include "lo-mappers.h"
35#include "oct-locbuf.h"
36#include "oct-sparse.h"
37#include "oct-spparms.h"
38#include "sparse-lu.h"
39
40namespace octave
41{
42 namespace math
43 {
44 // Wrappers for SuiteSparse (formerly UMFPACK) functions that have
45 // different names depending on the sparse matrix data type.
46 //
47 // All of these functions must be specialized to forward to the correct
48 // SuiteSparse functions.
49
50 template <typename T>
51 void
52 umfpack_defaults (double *Control);
53
54 template <typename T>
55 void
56 umfpack_free_numeric (void **Numeric);
57
58 template <typename T>
59 void
60 umfpack_free_symbolic (void **Symbolic);
61
62 template <typename T>
65 void *Numeric);
66
67 template <typename T>
70 T *Lx, // Or Lz_packed
72 T *Ux, // Or Uz_packed
74 double *Dz_packed, octave_idx_type *do_recip,
75 double *Rs, void *Numeric);
76
77 template <typename T>
80 const T *Ax, // Or Az_packed
81 void *Symbolic, void **Numeric,
82 const double *Control, double *Info);
83
84 template <typename T>
87 const octave_idx_type *Ap, const octave_idx_type *Ai,
88 const T *Ax, // Or Az_packed
89 const octave_idx_type *Qinit, void **Symbolic,
90 const double *Control, double *Info);
91
92 template <typename T>
93 void
94 umfpack_report_control (const double *Control);
95
96 template <typename T>
97 void
98 umfpack_report_info (const double *Control, const double *Info);
99
100 template <typename T>
101 void
103 const octave_idx_type *Ap,
104 const octave_idx_type *Ai,
105 const T *Ax, // Or Az_packed
106 octave_idx_type col_form, const double *Control);
107
108 template <typename T>
109 void
110 umfpack_report_numeric (void *Numeric, const double *Control);
111
112 template <typename T>
113 void
115 const double *Control);
116
117 template <typename T>
118 void
119 umfpack_report_status (double *Control, octave_idx_type status);
120
121 template <typename T>
122 void
123 umfpack_report_symbolic (void *Symbolic, const double *Control);
124
125#if defined (HAVE_UMFPACK)
126
127 // SparseMatrix Specialization.
128
129 template <>
130 inline OCTAVE_API void
131 umfpack_defaults<double> (double *Control)
132 {
133 UMFPACK_DNAME (defaults) (Control);
134 }
135
136 template <>
137 inline OCTAVE_API void
138 umfpack_free_numeric<double> (void **Numeric)
139 {
140 UMFPACK_DNAME (free_numeric) (Numeric);
141 }
142
143 template <>
144 inline OCTAVE_API void
145 umfpack_free_symbolic<double> (void **Symbolic)
146 {
147 UMFPACK_DNAME (free_symbolic) (Symbolic);
148 }
149
150 template <>
153 (octave_idx_type *lnz, octave_idx_type *unz, void *Numeric)
154 {
155 suitesparse_integer ignore1, ignore2, ignore3;
156
157 return UMFPACK_DNAME (get_lunz) (to_suitesparse_intptr (lnz),
159 &ignore1, &ignore2, &ignore3, Numeric);
160 }
161
162 template <>
165 (octave_idx_type *Lp, octave_idx_type *Lj, double *Lx,
166 octave_idx_type *Up, octave_idx_type *Ui, double *Ux,
167 octave_idx_type *p, octave_idx_type *q, double *Dx,
168 octave_idx_type *do_recip, double *Rs, void *Numeric)
169 {
170 return UMFPACK_DNAME (get_numeric) (to_suitesparse_intptr (Lp),
172 Lx, to_suitesparse_intptr (Up),
175 to_suitesparse_intptr (q), Dx,
176 to_suitesparse_intptr (do_recip),
177 Rs, Numeric);
178 }
179
180 template <>
183 (const octave_idx_type *Ap, const octave_idx_type *Ai,
184 const double *Ax, void *Symbolic, void **Numeric,
185 const double *Control, double *Info)
186 {
187 return UMFPACK_DNAME (numeric) (to_suitesparse_intptr (Ap),
189 Ax, Symbolic, Numeric, Control, Info);
190 }
191
192 template <>
195 (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap,
196 const octave_idx_type *Ai, const double *Ax,
197 const octave_idx_type *Qinit, void **Symbolic,
198 const double *Control, double *Info)
199 {
200 return UMFPACK_DNAME (qsymbolic) (n_row, n_col,
202 to_suitesparse_intptr (Ai), Ax,
203 to_suitesparse_intptr (Qinit),
204 Symbolic, Control, Info);
205 }
206
207 template <>
208 inline OCTAVE_API void
209 umfpack_report_control<double> (const double *Control)
210 {
211 UMFPACK_DNAME (report_control) (Control);
212 }
213
214 template <>
215 inline OCTAVE_API void
216 umfpack_report_info<double> (const double *Control, const double *Info)
217 {
218 UMFPACK_DNAME (report_info) (Control, Info);
219 }
220
221 template <>
222 inline OCTAVE_API void
224 (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap,
225 const octave_idx_type *Ai, const double *Ax, octave_idx_type col_form,
226 const double *Control)
227 {
228 UMFPACK_DNAME (report_matrix) (n_row, n_col,
230 to_suitesparse_intptr (Ai), Ax,
231 col_form, Control);
232 }
233
234 template <>
235 inline OCTAVE_API void
236 umfpack_report_numeric<double> (void *Numeric, const double *Control)
237 {
238 UMFPACK_DNAME (report_numeric) (Numeric, Control);
239 }
240
241 template <>
242 inline OCTAVE_API void
244 (octave_idx_type np, const octave_idx_type *Perm, const double *Control)
245 {
246 UMFPACK_DNAME (report_perm) (np, to_suitesparse_intptr (Perm), Control);
247 }
248
249 template <>
250 inline OCTAVE_API void
251 umfpack_report_status<double> (double *Control, octave_idx_type status)
252 {
253 UMFPACK_DNAME (report_status) (Control, status);
254 }
255
256 template <>
257 inline OCTAVE_API void
258 umfpack_report_symbolic<double> (void *Symbolic, const double *Control)
259 {
260 UMFPACK_DNAME (report_symbolic) (Symbolic, Control);
261 }
262
263 // SparseComplexMatrix specialization.
264
265 template <>
266 inline OCTAVE_API void
267 umfpack_defaults<Complex> (double *Control)
268 {
269 UMFPACK_ZNAME (defaults) (Control);
270 }
271
272 template <>
273 inline OCTAVE_API void
274 umfpack_free_numeric<Complex> (void **Numeric)
275 {
276 UMFPACK_ZNAME (free_numeric) (Numeric);
277 }
278
279 template <>
280 inline OCTAVE_API void
281 umfpack_free_symbolic<Complex> (void **Symbolic)
282 {
283 UMFPACK_ZNAME (free_symbolic) (Symbolic);
284 }
285
286 template <>
289 (octave_idx_type *lnz, octave_idx_type *unz, void *Numeric)
290 {
291 suitesparse_integer ignore1, ignore2, ignore3;
292
293 return UMFPACK_ZNAME (get_lunz) (to_suitesparse_intptr (lnz),
295 &ignore1, &ignore2, &ignore3, Numeric);
296 }
297
298 template <>
303 octave_idx_type *p, octave_idx_type *q, double *Dz,
304 octave_idx_type *do_recip, double *Rs, void *Numeric)
305 {
306 return UMFPACK_ZNAME (get_numeric) (to_suitesparse_intptr (Lp),
308 reinterpret_cast<double *> (Lz),
309 nullptr, to_suitesparse_intptr (Up),
311 reinterpret_cast<double *> (Uz),
312 nullptr, to_suitesparse_intptr (p),
314 reinterpret_cast<double *> (Dz),
315 nullptr, to_suitesparse_intptr (do_recip),
316 Rs, Numeric);
317 }
318
319 template <>
322 (const octave_idx_type *Ap, const octave_idx_type *Ai,
323 const Complex *Az, void *Symbolic, void **Numeric,
324 const double *Control, double *Info)
325 {
326 return UMFPACK_ZNAME (numeric) (to_suitesparse_intptr (Ap),
328 reinterpret_cast<const double *> (Az),
329 nullptr, Symbolic, Numeric, Control, Info);
330 }
331
332 template <>
335 (octave_idx_type n_row, octave_idx_type n_col,
336 const octave_idx_type *Ap, const octave_idx_type *Ai,
337 const Complex *Az, const octave_idx_type *Qinit,
338 void **Symbolic, const double *Control, double *Info)
339 {
340 return UMFPACK_ZNAME (qsymbolic) (n_row, n_col,
343 reinterpret_cast<const double *> (Az),
344 nullptr, to_suitesparse_intptr (Qinit),
345 Symbolic, Control, Info);
346 }
347
348 template <>
349 inline OCTAVE_API void
350 umfpack_report_control<Complex> (const double *Control)
351 {
352 UMFPACK_ZNAME (report_control) (Control);
353 }
354
355 template <>
356 inline OCTAVE_API void
357 umfpack_report_info<Complex> (const double *Control, const double *Info)
358 {
359 UMFPACK_ZNAME (report_info) (Control, Info);
360 }
361
362 template <>
363 inline OCTAVE_API void
365 (octave_idx_type n_row, octave_idx_type n_col,
366 const octave_idx_type *Ap, const octave_idx_type *Ai,
367 const Complex *Az, octave_idx_type col_form, const double *Control)
368 {
369 UMFPACK_ZNAME (report_matrix) (n_row, n_col,
372 reinterpret_cast<const double *> (Az),
373 nullptr, col_form, Control);
374 }
375
376 template <>
377 inline OCTAVE_API void
378 umfpack_report_numeric<Complex> (void *Numeric, const double *Control)
379 {
380 UMFPACK_ZNAME (report_numeric) (Numeric, Control);
381 }
382
383 template <>
384 inline OCTAVE_API void
386 (octave_idx_type np, const octave_idx_type *Perm, const double *Control)
387 {
388 UMFPACK_ZNAME (report_perm) (np, to_suitesparse_intptr (Perm), Control);
389 }
390
391 template <>
392 inline OCTAVE_API void
393 umfpack_report_status<Complex> (double *Control, octave_idx_type status)
394 {
395 UMFPACK_ZNAME (report_status) (Control, status);
396 }
397
398 template <>
399 inline OCTAVE_API void
400 umfpack_report_symbolic <Complex> (void *Symbolic, const double *Control)
401 {
402 UMFPACK_ZNAME (report_symbolic) (Symbolic, Control);
403 }
404
405#endif
406
407 template <typename lu_type>
408 sparse_lu<lu_type>::sparse_lu (const lu_type& a, const Matrix& piv_thres,
409 bool scale)
410 : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q ()
411 {
412#if defined (HAVE_UMFPACK)
413 octave_idx_type nr = a.rows ();
414 octave_idx_type nc = a.cols ();
415
416 // Setup the control parameters
417 Matrix Control (UMFPACK_CONTROL, 1);
418 double *control = Control.fortran_vec ();
419 umfpack_defaults<lu_elt_type> (control);
420
421 double tmp = sparse_params::get_key ("spumoni");
422 if (! math::isnan (tmp))
423 Control (UMFPACK_PRL) = tmp;
424
425 if (piv_thres.numel () == 2)
426 {
427 tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0));
428 if (! math::isnan (tmp))
429 Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
430
431 tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1));
432 if (! math::isnan (tmp))
433 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
434 }
435 else
436 {
437 tmp = sparse_params::get_key ("piv_tol");
438 if (! math::isnan (tmp))
439 Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
440
441 tmp = sparse_params::get_key ("sym_tol");
442 if (! math::isnan (tmp))
443 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
444 }
445
446 // Set whether we are allowed to modify Q or not
447 tmp = sparse_params::get_key ("autoamd");
448 if (! math::isnan (tmp))
449 Control (UMFPACK_FIXQ) = tmp;
450
451 // Turn-off UMFPACK scaling for LU
452 if (scale)
453 Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM;
454 else
455 Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;
456
457 umfpack_report_control<lu_elt_type> (control);
458
459 const octave_idx_type *Ap = a.cidx ();
460 const octave_idx_type *Ai = a.ridx ();
461 const lu_elt_type *Ax = a.data ();
462
463 umfpack_report_matrix<lu_elt_type> (nr, nc, Ap, Ai, Ax,
464 static_cast<octave_idx_type> (1),
465 control);
466
467 void *Symbolic;
468 Matrix Info (1, UMFPACK_INFO);
469 double *info = Info.fortran_vec ();
470 int status = umfpack_qsymbolic<lu_elt_type> (nr, nc, Ap, Ai, Ax, nullptr,
471 &Symbolic, control, info);
472
473 if (status < 0)
474 {
475 umfpack_report_status<lu_elt_type> (control, status);
476 umfpack_report_info<lu_elt_type> (control, info);
477
478 umfpack_free_symbolic<lu_elt_type> (&Symbolic);
479
480 (*current_liboctave_error_handler)
481 ("sparse_lu: symbolic factorization failed");
482 }
483 else
484 {
485 umfpack_report_symbolic<lu_elt_type> (Symbolic, control);
486
487 void *Numeric;
488 status = umfpack_numeric<lu_elt_type> (Ap, Ai, Ax, Symbolic,
489 &Numeric, control, info);
490 umfpack_free_symbolic<lu_elt_type> (&Symbolic);
491
492 m_cond = Info (UMFPACK_RCOND);
493
494 if (status < 0)
495 {
496 umfpack_report_status<lu_elt_type> (control, status);
497 umfpack_report_info<lu_elt_type> (control, info);
498
499 umfpack_free_numeric<lu_elt_type> (&Numeric);
500
501 (*current_liboctave_error_handler)
502 ("sparse_lu: numeric factorization failed");
503 }
504 else
505 {
506 umfpack_report_numeric<lu_elt_type> (Numeric, control);
507
508 octave_idx_type lnz, unz;
509 status = umfpack_get_lunz<lu_elt_type> (&lnz, &unz, Numeric);
510
511 if (status < 0)
512 {
513 umfpack_report_status<lu_elt_type> (control, status);
514 umfpack_report_info<lu_elt_type> (control, info);
515
516 umfpack_free_numeric<lu_elt_type> (&Numeric);
517
518 (*current_liboctave_error_handler)
519 ("sparse_lu: extracting LU factors failed");
520 }
521 else
522 {
523 octave_idx_type n_inner = (nr < nc ? nr : nc);
524
525 if (lnz < 1)
526 m_L = lu_type (n_inner, nr,
527 static_cast<octave_idx_type> (1));
528 else
529 m_L = lu_type (n_inner, nr, lnz);
530
531 octave_idx_type *Ltp = m_L.cidx ();
532 octave_idx_type *Ltj = m_L.ridx ();
533 lu_elt_type *Ltx = m_L.data ();
534
535 if (unz < 1)
536 m_U = lu_type (n_inner, nc,
537 static_cast<octave_idx_type> (1));
538 else
539 m_U = lu_type (n_inner, nc, unz);
540
541 octave_idx_type *Up = m_U.cidx ();
542 octave_idx_type *Uj = m_U.ridx ();
543 lu_elt_type *Ux = m_U.data ();
544
545 m_R = SparseMatrix (nr, nr, nr);
546 for (octave_idx_type i = 0; i < nr; i++)
547 {
548 m_R.xridx (i) = i;
549 m_R.xcidx (i) = i;
550 }
551 m_R.xcidx (nr) = nr;
552 double *Rx = m_R.data ();
553
554 m_P.resize (dim_vector (nr, 1));
556
557 m_Q.resize (dim_vector (nc, 1));
559
560 octave_idx_type do_recip;
561 status = umfpack_get_numeric<lu_elt_type> (Ltp, Ltj, Ltx,
562 Up, Uj, Ux,
563 p, q, nullptr,
564 &do_recip, Rx,
565 Numeric);
566
567 umfpack_free_numeric<lu_elt_type> (&Numeric);
568
569 if (status < 0)
570 {
571 umfpack_report_status<lu_elt_type> (control, status);
572
573 (*current_liboctave_error_handler)
574 ("sparse_lu: extracting LU factors failed");
575 }
576 else
577 {
578 m_L = m_L.transpose ();
579
580 if (do_recip)
581 for (octave_idx_type i = 0; i < nr; i++)
582 Rx[i] = 1.0 / Rx[i];
583
584 umfpack_report_matrix<lu_elt_type> (nr, n_inner,
585 m_L.cidx (),
586 m_L.ridx (),
587 m_L.data (),
588 static_cast<octave_idx_type> (1),
589 control);
590 umfpack_report_matrix<lu_elt_type> (n_inner, nc,
591 m_U.cidx (),
592 m_U.ridx (),
593 m_U.data (),
594 static_cast<octave_idx_type> (1),
595 control);
596 umfpack_report_perm<lu_elt_type> (nr, p, control);
597 umfpack_report_perm<lu_elt_type> (nc, q, control);
598 }
599
600 umfpack_report_info<lu_elt_type> (control, info);
601 }
602 }
603 }
604
605#else
606
607 octave_unused_parameter (a);
608 octave_unused_parameter (piv_thres);
609 octave_unused_parameter (scale);
610
611 (*current_liboctave_error_handler)
612 ("support for UMFPACK was unavailable or disabled when liboctave was built");
613
614#endif
615 }
616
617 template <typename lu_type>
619 const ColumnVector& Qinit,
620 const Matrix& piv_thres, bool scale,
621 bool FixedQ, double droptol,
622 bool milu, bool udiag)
623 : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q ()
624 {
625#if defined (HAVE_UMFPACK)
626
627 if (milu)
628 (*current_liboctave_error_handler)
629 ("Modified incomplete LU not implemented");
630
631 octave_idx_type nr = a.rows ();
632 octave_idx_type nc = a.cols ();
633
634 // Setup the control parameters
635 Matrix Control (UMFPACK_CONTROL, 1);
636 double *control = Control.fortran_vec ();
637 umfpack_defaults<lu_elt_type> (control);
638
639 double tmp = sparse_params::get_key ("spumoni");
640 if (! math::isnan (tmp))
641 Control (UMFPACK_PRL) = tmp;
642
643 if (piv_thres.numel () == 2)
644 {
645 tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0));
646 if (! math::isnan (tmp))
647 Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
648 tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1));
649 if (! math::isnan (tmp))
650 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
651 }
652 else
653 {
654 tmp = sparse_params::get_key ("piv_tol");
655 if (! math::isnan (tmp))
656 Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
657
658 tmp = sparse_params::get_key ("sym_tol");
659 if (! math::isnan (tmp))
660 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
661 }
662
663 if (droptol >= 0.)
664 Control (UMFPACK_DROPTOL) = droptol;
665
666 // Set whether we are allowed to modify Q or not
667 if (FixedQ)
668 Control (UMFPACK_FIXQ) = 1.0;
669 else
670 {
671 tmp = sparse_params::get_key ("autoamd");
672 if (! math::isnan (tmp))
673 Control (UMFPACK_FIXQ) = tmp;
674 }
675
676 // Turn-off UMFPACK scaling for LU
677 if (scale)
678 Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM;
679 else
680 Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;
681
682 umfpack_report_control<lu_elt_type> (control);
683
684 const octave_idx_type *Ap = a.cidx ();
685 const octave_idx_type *Ai = a.ridx ();
686 const lu_elt_type *Ax = a.data ();
687
688 umfpack_report_matrix<lu_elt_type> (nr, nc, Ap, Ai, Ax,
689 static_cast<octave_idx_type> (1),
690 control);
691
692 void *Symbolic;
693 Matrix Info (1, UMFPACK_INFO);
694 double *info = Info.fortran_vec ();
695 int status;
696
697 // Null loop so that qinit is immediately deallocated when not needed
698 do
699 {
701
702 for (octave_idx_type i = 0; i < nc; i++)
703 qinit[i] = static_cast<octave_idx_type> (Qinit (i));
704
705 status = umfpack_qsymbolic<lu_elt_type> (nr, nc, Ap, Ai, Ax,
706 qinit, &Symbolic, control,
707 info);
708 }
709 while (0);
710
711 if (status < 0)
712 {
713 umfpack_report_status<lu_elt_type> (control, status);
714 umfpack_report_info<lu_elt_type> (control, info);
715
716 umfpack_free_symbolic<lu_elt_type> (&Symbolic);
717
718 (*current_liboctave_error_handler)
719 ("sparse_lu: symbolic factorization failed");
720 }
721 else
722 {
723 umfpack_report_symbolic<lu_elt_type> (Symbolic, control);
724
725 void *Numeric;
726 status = umfpack_numeric<lu_elt_type> (Ap, Ai, Ax, Symbolic,
727 &Numeric, control, info);
728 umfpack_free_symbolic<lu_elt_type> (&Symbolic);
729
730 m_cond = Info (UMFPACK_RCOND);
731
732 if (status < 0)
733 {
734 umfpack_report_status<lu_elt_type> (control, status);
735 umfpack_report_info<lu_elt_type> (control, info);
736
737 umfpack_free_numeric<lu_elt_type> (&Numeric);
738
739 (*current_liboctave_error_handler)
740 ("sparse_lu: numeric factorization failed");
741 }
742 else
743 {
744 umfpack_report_numeric<lu_elt_type> (Numeric, control);
745
746 octave_idx_type lnz, unz;
747 status = umfpack_get_lunz<lu_elt_type> (&lnz, &unz, Numeric);
748
749 if (status < 0)
750 {
751 umfpack_report_status<lu_elt_type> (control, status);
752 umfpack_report_info<lu_elt_type> (control, info);
753
754 umfpack_free_numeric<lu_elt_type> (&Numeric);
755
756 (*current_liboctave_error_handler)
757 ("sparse_lu: extracting LU factors failed");
758 }
759 else
760 {
761 octave_idx_type n_inner = (nr < nc ? nr : nc);
762
763 if (lnz < 1)
764 m_L = lu_type (n_inner, nr,
765 static_cast<octave_idx_type> (1));
766 else
767 m_L = lu_type (n_inner, nr, lnz);
768
769 octave_idx_type *Ltp = m_L.cidx ();
770 octave_idx_type *Ltj = m_L.ridx ();
771 lu_elt_type *Ltx = m_L.data ();
772
773 if (unz < 1)
774 m_U = lu_type (n_inner, nc,
775 static_cast<octave_idx_type> (1));
776 else
777 m_U = lu_type (n_inner, nc, unz);
778
779 octave_idx_type *Up = m_U.cidx ();
780 octave_idx_type *Uj = m_U.ridx ();
781 lu_elt_type *Ux = m_U.data ();
782
783 m_R = SparseMatrix (nr, nr, nr);
784 for (octave_idx_type i = 0; i < nr; i++)
785 {
786 m_R.xridx (i) = i;
787 m_R.xcidx (i) = i;
788 }
789 m_R.xcidx (nr) = nr;
790 double *Rx = m_R.data ();
791
792 m_P.resize (dim_vector (nr, 1));
794
795 m_Q.resize (dim_vector (nc, 1));
797
798 octave_idx_type do_recip;
799 status = umfpack_get_numeric<lu_elt_type> (Ltp, Ltj, Ltx,
800 Up, Uj, Ux,
801 p, q, nullptr,
802 &do_recip,
803 Rx, Numeric);
804
805 umfpack_free_numeric<lu_elt_type> (&Numeric);
806
807 if (status < 0)
808 {
809 umfpack_report_status<lu_elt_type> (control, status);
810
811 (*current_liboctave_error_handler)
812 ("sparse_lu: extracting LU factors failed");
813 }
814 else
815 {
816 m_L = m_L.transpose ();
817
818 if (do_recip)
819 for (octave_idx_type i = 0; i < nr; i++)
820 Rx[i] = 1.0 / Rx[i];
821
822 umfpack_report_matrix<lu_elt_type> (nr, n_inner,
823 m_L.cidx (),
824 m_L.ridx (),
825 m_L.data (),
826 static_cast<octave_idx_type> (1),
827 control);
828 umfpack_report_matrix<lu_elt_type> (n_inner, nc,
829 m_U.cidx (),
830 m_U.ridx (),
831 m_U.data (),
832 static_cast<octave_idx_type> (1),
833 control);
834 umfpack_report_perm<lu_elt_type> (nr, p, control);
835 umfpack_report_perm<lu_elt_type> (nc, q, control);
836 }
837
838 umfpack_report_info<lu_elt_type> (control, info);
839 }
840 }
841 }
842
843 if (udiag)
844 (*current_liboctave_error_handler)
845 ("Option udiag of incomplete LU not implemented");
846
847#else
848
849 octave_unused_parameter (a);
850 octave_unused_parameter (Qinit);
851 octave_unused_parameter (piv_thres);
852 octave_unused_parameter (scale);
853 octave_unused_parameter (FixedQ);
854 octave_unused_parameter (droptol);
855 octave_unused_parameter (milu);
856 octave_unused_parameter (udiag);
857
858 (*current_liboctave_error_handler)
859 ("support for UMFPACK was unavailable or disabled when liboctave was built");
860
861#endif
862 }
863
864 template <typename lu_type>
865 lu_type
867 {
868 octave_idx_type nr = m_L.rows ();
869 octave_idx_type nz = m_L.cols ();
870 octave_idx_type nc = m_U.cols ();
871
872 lu_type Yout (nr, nc, m_L.nnz () + m_U.nnz () - (nr<nz?nr:nz));
873 octave_idx_type ii = 0;
874 Yout.xcidx (0) = 0;
875
876 for (octave_idx_type j = 0; j < nc; j++)
877 {
878 for (octave_idx_type i = m_U.cidx (j); i < m_U.cidx (j + 1); i++)
879 {
880 Yout.xridx (ii) = m_U.ridx (i);
881 Yout.xdata (ii++) = m_U.data (i);
882 }
883
884 if (j < nz)
885 {
886 // Note the +1 skips the 1.0 on the diagonal
887 for (octave_idx_type i = m_L.cidx (j) + 1;
888 i < m_L.cidx (j +1); i++)
889 {
890 Yout.xridx (ii) = m_L.ridx (i);
891 Yout.xdata (ii++) = m_L.data (i);
892 }
893 }
894
895 Yout.xcidx (j + 1) = ii;
896 }
897
898 return Yout;
899 }
900
901 template <typename lu_type>
904 {
905 octave_idx_type nr = m_L.rows ();
906
907 SparseMatrix Pout (nr, nr, nr);
908
909 for (octave_idx_type i = 0; i < nr; i++)
910 {
911 Pout.cidx (i) = i;
912 Pout.ridx (m_P(i)) = i;
913 Pout.data (i) = 1;
914 }
915
916 Pout.cidx (nr) = nr;
917
918 return Pout;
919 }
920
921 template <typename lu_type>
924 {
925 octave_idx_type nr = m_L.rows ();
926
927 ColumnVector Pout (nr);
928
929 for (octave_idx_type i = 0; i < nr; i++)
930 Pout.xelem (i) = static_cast<double> (m_P(i) + 1);
931
932 return Pout;
933 }
934
935 template <typename lu_type>
938 {
939 return PermMatrix (m_P, false);
940 }
941
942 template <typename lu_type>
945 {
946 octave_idx_type nc = m_U.cols ();
947
948 SparseMatrix Pout (nc, nc, nc);
949
950 for (octave_idx_type i = 0; i < nc; i++)
951 {
952 Pout.cidx (i) = i;
953 Pout.ridx (i) = m_Q(i);
954 Pout.data (i) = 1;
955 }
956
957 Pout.cidx (nc) = nc;
958
959 return Pout;
960 }
961
962 template <typename lu_type>
965 {
966 octave_idx_type nc = m_U.cols ();
967
968 ColumnVector Pout (nc);
969
970 for (octave_idx_type i = 0; i < nc; i++)
971 Pout.xelem (i) = static_cast<double> (m_Q(i) + 1);
972
973 return Pout;
974 }
975
976 template <typename lu_type>
979 {
980 return PermMatrix (m_Q, true);
981 }
982
983 // Instantiations we need.
985
987 }
988}
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:504
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:411
OCTARRAY_API void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array.cc:1010
OCTARRAY_API T * fortran_vec(void)
Size of the specified dimension.
Definition: Array.cc:1744
Definition: dMatrix.h:42
T * data(void)
Definition: Sparse.h:574
octave_idx_type * xridx(void)
Definition: Sparse.h:589
octave_idx_type * ridx(void)
Definition: Sparse.h:583
octave_idx_type * cidx(void)
Definition: Sparse.h:596
octave_idx_type * xcidx(void)
Definition: Sparse.h:602
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
OCTAVE_API PermMatrix Pc_mat(void) const
Definition: sparse-lu.cc:978
OCTAVE_API ColumnVector Pc_vec(void) const
Definition: sparse-lu.cc:964
lu_type::element_type lu_elt_type
Definition: sparse-lu.h:53
MArray< octave_idx_type > m_Q
Definition: sparse-lu.h:124
OCTAVE_API PermMatrix Pr_mat(void) const
Definition: sparse-lu.cc:937
OCTAVE_API SparseMatrix Pr(void) const
Definition: sparse-lu.cc:903
OCTAVE_API ColumnVector Pr_vec(void) const
Definition: sparse-lu.cc:923
OCTAVE_API SparseMatrix Pc(void) const
Definition: sparse-lu.cc:944
MArray< octave_idx_type > m_P
Definition: sparse-lu.h:123
OCTAVE_API lu_type Y(void) const
Definition: sparse-lu.cc:866
static double get_key(const std::string &key)
Definition: oct-spparms.cc:87
void scale(Matrix &m, double x, double y, double z)
Definition: graphics.cc:5893
#define OCTAVE_API
Definition: main.in.cc:55
class OCTAVE_API SparseMatrix
Definition: mx-fwd.h:55
class OCTAVE_API PermMatrix
Definition: mx-fwd.h:64
OCTAVE_API void umfpack_report_symbolic< double >(void *Symbolic, const double *Control)
Definition: sparse-lu.cc:258
OCTAVE_API void umfpack_report_status< double >(double *Control, octave_idx_type status)
Definition: sparse-lu.cc:251
OCTAVE_API void umfpack_defaults< Complex >(double *Control)
Definition: sparse-lu.cc:267
OCTAVE_API void umfpack_report_info< double >(const double *Control, const double *Info)
Definition: sparse-lu.cc:216
OCTAVE_API void umfpack_report_symbolic< Complex >(void *Symbolic, const double *Control)
Definition: sparse-lu.cc:400
OCTAVE_API void umfpack_free_numeric< Complex >(void **Numeric)
Definition: sparse-lu.cc:274
OCTAVE_API octave_idx_type umfpack_qsymbolic< double >(octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const double *Ax, const octave_idx_type *Qinit, void **Symbolic, const double *Control, double *Info)
Definition: sparse-lu.cc:195
void umfpack_report_matrix(octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const T *Ax, octave_idx_type col_form, const double *Control)
OCTAVE_API void umfpack_report_status< Complex >(double *Control, octave_idx_type status)
Definition: sparse-lu.cc:393
OCTAVE_API octave_idx_type umfpack_get_numeric< double >(octave_idx_type *Lp, octave_idx_type *Lj, double *Lx, octave_idx_type *Up, octave_idx_type *Ui, double *Ux, octave_idx_type *p, octave_idx_type *q, double *Dx, octave_idx_type *do_recip, double *Rs, void *Numeric)
Definition: sparse-lu.cc:165
void umfpack_report_numeric(void *Numeric, const double *Control)
void umfpack_free_symbolic(void **Symbolic)
OCTAVE_API void umfpack_report_matrix< Complex >(octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const Complex *Az, octave_idx_type col_form, const double *Control)
Definition: sparse-lu.cc:365
OCTAVE_API void umfpack_free_symbolic< double >(void **Symbolic)
Definition: sparse-lu.cc:145
bool isnan(bool)
Definition: lo-mappers.h:178
OCTAVE_API octave_idx_type umfpack_get_lunz< Complex >(octave_idx_type *lnz, octave_idx_type *unz, void *Numeric)
Definition: sparse-lu.cc:289
OCTAVE_API void umfpack_report_perm< Complex >(octave_idx_type np, const octave_idx_type *Perm, const double *Control)
Definition: sparse-lu.cc:386
void umfpack_report_control(const double *Control)
OCTAVE_API octave_idx_type umfpack_qsymbolic< Complex >(octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const Complex *Az, const octave_idx_type *Qinit, void **Symbolic, const double *Control, double *Info)
Definition: sparse-lu.cc:335
octave_idx_type umfpack_get_lunz(octave_idx_type *lnz, octave_idx_type *unz, void *Numeric)
OCTAVE_API void umfpack_report_control< Complex >(const double *Control)
Definition: sparse-lu.cc:350
OCTAVE_API void umfpack_report_numeric< Complex >(void *Numeric, const double *Control)
Definition: sparse-lu.cc:378
OCTAVE_API octave_idx_type umfpack_get_numeric< Complex >(octave_idx_type *Lp, octave_idx_type *Lj, Complex *Lz, octave_idx_type *Up, octave_idx_type *Ui, Complex *Uz, octave_idx_type *p, octave_idx_type *q, double *Dz, octave_idx_type *do_recip, double *Rs, void *Numeric)
Definition: sparse-lu.cc:301
OCTAVE_API void umfpack_report_numeric< double >(void *Numeric, const double *Control)
Definition: sparse-lu.cc:236
OCTAVE_API void umfpack_report_control< double >(const double *Control)
Definition: sparse-lu.cc:209
OCTAVE_API void umfpack_free_numeric< double >(void **Numeric)
Definition: sparse-lu.cc:138
OCTAVE_API octave_idx_type umfpack_numeric< Complex >(const octave_idx_type *Ap, const octave_idx_type *Ai, const Complex *Az, void *Symbolic, void **Numeric, const double *Control, double *Info)
Definition: sparse-lu.cc:322
OCTAVE_API void umfpack_defaults< double >(double *Control)
Definition: sparse-lu.cc:131
void umfpack_free_numeric(void **Numeric)
octave_idx_type umfpack_numeric(const octave_idx_type *Ap, const octave_idx_type *Ai, const T *Ax, void *Symbolic, void **Numeric, const double *Control, double *Info)
OCTAVE_API octave_idx_type umfpack_get_lunz< double >(octave_idx_type *lnz, octave_idx_type *unz, void *Numeric)
Definition: sparse-lu.cc:153
OCTAVE_API void umfpack_free_symbolic< Complex >(void **Symbolic)
Definition: sparse-lu.cc:281
OCTAVE_API void umfpack_report_matrix< double >(octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const double *Ax, octave_idx_type col_form, const double *Control)
Definition: sparse-lu.cc:224
OCTAVE_API octave_idx_type umfpack_numeric< double >(const octave_idx_type *Ap, const octave_idx_type *Ai, const double *Ax, void *Symbolic, void **Numeric, const double *Control, double *Info)
Definition: sparse-lu.cc:183
void umfpack_report_perm(octave_idx_type np, const octave_idx_type *Perm, const double *Control)
OCTAVE_API void umfpack_report_perm< double >(octave_idx_type np, const octave_idx_type *Perm, const double *Control)
Definition: sparse-lu.cc:244
void umfpack_report_status(double *Control, octave_idx_type status)
void umfpack_defaults(double *Control)
OCTAVE_API void umfpack_report_info< Complex >(const double *Control, const double *Info)
Definition: sparse-lu.cc:357
octave_idx_type umfpack_get_numeric(octave_idx_type *Lp, octave_idx_type *Lj, T *Lx, octave_idx_type *Up, octave_idx_type *Ui, T *Ux, octave_idx_type *p, octave_idx_type *q, double *Dz_packed, octave_idx_type *do_recip, double *Rs, void *Numeric)
octave_idx_type umfpack_qsymbolic(octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, const octave_idx_type *Ai, const T *Ax, const octave_idx_type *Qinit, void **Symbolic, const double *Control, double *Info)
void umfpack_report_symbolic(void *Symbolic, const double *Control)
void umfpack_report_info(const double *Control, const double *Info)
suitesparse_integer * to_suitesparse_intptr(octave_idx_type *i)
Definition: oct-sparse.cc:51
std::complex< double > Complex
Definition: oct-cmplx.h:33
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44
#define UMFPACK_ZNAME(name)
Definition: oct-sparse.h:159
#define UMFPACK_DNAME(name)
Definition: oct-sparse.h:158