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