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