GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
lu.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2024 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 <algorithm>
31 
32 #include "CColVector.h"
33 #include "CMatrix.h"
34 #include "PermMatrix.h"
35 #include "dColVector.h"
36 #include "dMatrix.h"
37 #include "fCColVector.h"
38 #include "fCMatrix.h"
39 #include "fColVector.h"
40 #include "fMatrix.h"
41 #include "lo-error.h"
42 #include "lo-lapack-proto.h"
43 #include "lo-qrupdate-proto.h"
44 #include "lu.h"
45 #include "oct-locbuf.h"
46 
48 
50 
51 // FIXME: PermMatrix::col_perm_vec returns Array<octave_idx_type>
52 // but m_ipvt is an Array<octave_f77_int_type>. This could cause
53 // trouble for large arrays if octave_f77_int_type is 32-bits but
54 // octave_idx_type is 64. Since this constructor is called from
55 // Fluupdate, it could be given values that are out of range. We
56 // should ensure that the values are within range here.
57 
58 template <typename T>
59 lu<T>::lu (const T& l, const T& u, const PermMatrix& p)
60  : m_a_fact (u), m_L (l), m_ipvt (p.transpose ().col_perm_vec ())
61 {
62  if (l.columns () != u.rows ())
63  (*current_liboctave_error_handler) ("lu: dimension mismatch");
64 }
65 
66 template <typename T>
67 bool
68 lu<T>::packed () const
69 {
70  return m_L.dims () == dim_vector ();
71 }
72 
73 template <typename T>
74 void
76 {
77  if (packed ())
78  {
79  m_L = L ();
80  m_a_fact = U (); // FIXME: sub-optimal
81 
82  // FIXME: getp returns Array<octave_idx_type> but m_ipvt is
83  // Array<octave_f77_int_type>. However, getp produces its
84  // result from a valid m_ipvt array so validation should not be
85  // necessary. OTOH, it might be better to have a version of
86  // getp that doesn't cause us to convert from
87  // Array<octave_f77_int_type> to Array<octave_idx_type> and
88  // back again.
89 
90  m_ipvt = getp ();
91  }
92 }
93 
94 template <typename T>
95 T
96 lu<T>::L () const
97 {
98  if (packed ())
99  {
100  octave_idx_type a_nr = m_a_fact.rows ();
101  octave_idx_type a_nc = m_a_fact.columns ();
102  octave_idx_type mn = (a_nr < a_nc ? a_nr : a_nc);
103 
104  T l (a_nr, mn, ELT_T (0.0));
105 
106  for (octave_idx_type i = 0; i < a_nr; i++)
107  {
108  if (i < a_nc)
109  l.xelem (i, i) = 1.0;
110 
111  for (octave_idx_type j = 0; j < (i < a_nc ? i : a_nc); j++)
112  l.xelem (i, j) = m_a_fact.xelem (i, j);
113  }
114 
115  return l;
116  }
117  else
118  return m_L;
119 }
120 
121 template <typename T>
122 T
123 lu<T>::U () const
124 {
125  if (packed ())
126  {
127  octave_idx_type a_nr = m_a_fact.rows ();
128  octave_idx_type a_nc = m_a_fact.columns ();
129  octave_idx_type mn = (a_nr < a_nc ? a_nr : a_nc);
130 
131  T u (mn, a_nc, ELT_T (0.0));
132 
133  for (octave_idx_type i = 0; i < mn; i++)
134  {
135  for (octave_idx_type j = i; j < a_nc; j++)
136  u.xelem (i, j) = m_a_fact.xelem (i, j);
137  }
138 
139  return u;
140  }
141  else
142  return m_a_fact;
143 }
144 
145 template <typename T>
146 T
147 lu<T>::Y () const
148 {
149  if (! packed ())
150  (*current_liboctave_error_handler)
151  ("lu: Y () not implemented for unpacked form");
152 
153  return m_a_fact;
154 }
155 
156 template <typename T>
158 lu<T>::getp () const
159 {
160  if (packed ())
161  {
162  octave_idx_type a_nr = m_a_fact.rows ();
163 
164  Array<octave_idx_type> pvt (dim_vector (a_nr, 1));
165 
166  for (octave_idx_type i = 0; i < a_nr; i++)
167  pvt.xelem (i) = i;
168 
169  for (octave_idx_type i = 0; i < m_ipvt.numel (); i++)
170  {
171  octave_idx_type k = m_ipvt.xelem (i);
172 
173  if (k != i)
174  {
175  octave_idx_type tmp = pvt.xelem (k);
176  pvt.xelem (k) = pvt.xelem (i);
177  pvt.xelem (i) = tmp;
178  }
179  }
180 
181  return pvt;
182  }
183  else
184  return m_ipvt;
185 }
186 
187 template <typename T>
189 lu<T>::P () const
190 {
191  return PermMatrix (getp (), false);
192 }
193 
194 template <typename T>
196 lu<T>::P_vec () const
197 {
198  octave_idx_type a_nr = m_a_fact.rows ();
199 
200  ColumnVector p (a_nr);
201 
202  Array<octave_idx_type> pvt = getp ();
203 
204  for (octave_idx_type i = 0; i < a_nr; i++)
205  p.xelem (i) = static_cast<double> (pvt.xelem (i) + 1);
206 
207  return p;
208 }
209 
210 template <typename T>
211 bool
213 {
214  bool retval = true;
215 
216  octave_idx_type k = std::min (m_a_fact.rows (), m_a_fact.columns ());
217 
218  for (octave_idx_type i = 0; i < k; i++)
219  {
220  if (m_a_fact(i, i) == ELT_T ())
221  {
222  retval = false;
223  break;
224  }
225  }
226 
227  return retval;
228 }
229 
230 #if ! defined (HAVE_QRUPDATE_LUU)
231 
232 template <typename T>
233 void
234 lu<T>::update (const VT&, const VT&)
235 {
236  (*current_liboctave_error_handler)
237  ("luupdate: support for qrupdate with LU updates "
238  "was unavailable or disabled when liboctave was built");
239 }
240 
241 template <typename T>
242 void
243 lu<T>::update (const T&, const T&)
244 {
245  (*current_liboctave_error_handler)
246  ("luupdate: support for qrupdate with LU updates "
247  "was unavailable or disabled when liboctave was built");
248 }
249 
250 template <typename T>
251 void
252 lu<T>::update_piv (const VT&, const VT&)
253 {
254  (*current_liboctave_error_handler)
255  ("luupdate: support for qrupdate with LU updates "
256  "was unavailable or disabled when liboctave was built");
257 }
258 
259 template <typename T>
260 void
261 lu<T>::update_piv (const T&, const T&)
262 {
263  (*current_liboctave_error_handler)
264  ("luupdate: support for qrupdate with LU updates "
265  "was unavailable or disabled when liboctave was built");
266 }
267 
268 #endif
269 
270 // Specializations.
271 
272 template <>
275 {
276  F77_INT a_nr = to_f77_int (a.rows ());
277  F77_INT a_nc = to_f77_int (a.columns ());
278  F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);
279 
280  m_ipvt.resize (dim_vector (mn, 1));
281  F77_INT *pipvt = m_ipvt.fortran_vec ();
282 
283  m_a_fact = a;
284  double *tmp_data = m_a_fact.fortran_vec ();
285 
286  F77_INT info = 0;
287 
288  F77_XFCN (dgetrf, DGETRF, (a_nr, a_nc, tmp_data, a_nr, pipvt, info));
289 
290  for (F77_INT i = 0; i < mn; i++)
291  pipvt[i] -= 1;
292 }
293 
294 #if defined (HAVE_QRUPDATE_LUU)
295 
296 template <>
297 OCTAVE_API void
299 {
300  if (packed ())
301  unpack ();
302 
303  Matrix& l = m_L;
304  Matrix& r = m_a_fact;
305 
306  F77_INT m = to_f77_int (l.rows ());
307  F77_INT n = to_f77_int (r.columns ());
308  F77_INT k = to_f77_int (l.columns ());
309 
310  F77_INT u_nel = to_f77_int (u.numel ());
311  F77_INT v_nel = to_f77_int (v.numel ());
312 
313  if (u_nel != m || v_nel != n)
314  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
315 
316  ColumnVector utmp = u;
317  ColumnVector vtmp = v;
318  F77_XFCN (dlu1up, DLU1UP, (m, n, l.fortran_vec (), m, r.fortran_vec (),
319  k, utmp.fortran_vec (), vtmp.fortran_vec ()));
320 }
321 
322 template <>
323 OCTAVE_API void
324 lu<Matrix>::update (const Matrix& u, const Matrix& v)
325 {
326  if (packed ())
327  unpack ();
328 
329  Matrix& l = m_L;
330  Matrix& r = m_a_fact;
331 
332  F77_INT m = to_f77_int (l.rows ());
333  F77_INT n = to_f77_int (r.columns ());
334  F77_INT k = to_f77_int (l.columns ());
335 
336  F77_INT u_nr = to_f77_int (u.rows ());
337  F77_INT u_nc = to_f77_int (u.columns ());
338 
339  F77_INT v_nr = to_f77_int (v.rows ());
340  F77_INT v_nc = to_f77_int (v.columns ());
341 
342  if (u_nr != m || v_nr != n || u_nc != v_nc)
343  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
344 
345  for (volatile F77_INT i = 0; i < u_nc; i++)
346  {
347  ColumnVector utmp = u.column (i);
348  ColumnVector vtmp = v.column (i);
349  F77_XFCN (dlu1up, DLU1UP, (m, n, l.fortran_vec (),
350  m, r.fortran_vec (), k,
351  utmp.fortran_vec (), vtmp.fortran_vec ()));
352  }
353 }
354 
355 template <>
356 OCTAVE_API void
358 {
359  if (packed ())
360  unpack ();
361 
362  Matrix& l = m_L;
363  Matrix& r = m_a_fact;
364 
365  F77_INT m = to_f77_int (l.rows ());
366  F77_INT n = to_f77_int (r.columns ());
367  F77_INT k = to_f77_int (l.columns ());
368 
369  F77_INT u_nel = to_f77_int (u.numel ());
370  F77_INT v_nel = to_f77_int (v.numel ());
371 
372  if (u_nel != m || v_nel != n)
373  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
374 
375  ColumnVector utmp = u;
376  ColumnVector vtmp = v;
377  OCTAVE_LOCAL_BUFFER (double, w, m);
378  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
379  F77_XFCN (dlup1up, DLUP1UP, (m, n, l.fortran_vec (),
380  m, r.fortran_vec (), k,
381  m_ipvt.fortran_vec (),
382  utmp.data (), vtmp.data (), w));
383  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
384 }
385 
386 template <>
387 OCTAVE_API void
389 {
390  if (packed ())
391  unpack ();
392 
393  Matrix& l = m_L;
394  Matrix& r = m_a_fact;
395 
396  F77_INT m = to_f77_int (l.rows ());
397  F77_INT n = to_f77_int (r.columns ());
398  F77_INT k = to_f77_int (l.columns ());
399 
400  F77_INT u_nr = to_f77_int (u.rows ());
401  F77_INT u_nc = to_f77_int (u.columns ());
402 
403  F77_INT v_nr = to_f77_int (v.rows ());
404  F77_INT v_nc = to_f77_int (v.columns ());
405 
406  if (u_nr != m || v_nr != n || u_nc != v_nc)
407  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
408 
409  OCTAVE_LOCAL_BUFFER (double, w, m);
410  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
411  for (volatile F77_INT i = 0; i < u_nc; i++)
412  {
413  ColumnVector utmp = u.column (i);
414  ColumnVector vtmp = v.column (i);
415  F77_XFCN (dlup1up, DLUP1UP, (m, n, l.fortran_vec (),
416  m, r.fortran_vec (), k,
417  m_ipvt.fortran_vec (),
418  utmp.data (), vtmp.data (), w));
419  }
420  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
421 }
422 
423 #endif
424 
425 template <>
428 {
429  F77_INT a_nr = to_f77_int (a.rows ());
430  F77_INT a_nc = to_f77_int (a.columns ());
431  F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);
432 
433  m_ipvt.resize (dim_vector (mn, 1));
434  F77_INT *pipvt = m_ipvt.fortran_vec ();
435 
436  m_a_fact = a;
437  float *tmp_data = m_a_fact.fortran_vec ();
438 
439  F77_INT info = 0;
440 
441  F77_XFCN (sgetrf, SGETRF, (a_nr, a_nc, tmp_data, a_nr, pipvt, info));
442 
443  for (F77_INT i = 0; i < mn; i++)
444  pipvt[i] -= 1;
445 }
446 
447 #if defined (HAVE_QRUPDATE_LUU)
448 
449 template <>
450 OCTAVE_API void
452  const FloatColumnVector& v)
453 {
454  if (packed ())
455  unpack ();
456 
457  FloatMatrix& l = m_L;
458  FloatMatrix& r = m_a_fact;
459 
460  F77_INT m = to_f77_int (l.rows ());
461  F77_INT n = to_f77_int (r.columns ());
462  F77_INT k = to_f77_int (l.columns ());
463 
464  F77_INT u_nel = to_f77_int (u.numel ());
465  F77_INT v_nel = to_f77_int (v.numel ());
466 
467  if (u_nel != m || v_nel != n)
468  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
469 
470  FloatColumnVector utmp = u;
471  FloatColumnVector vtmp = v;
472  F77_XFCN (slu1up, SLU1UP, (m, n, l.fortran_vec (),
473  m, r.fortran_vec (), k,
474  utmp.fortran_vec (), vtmp.fortran_vec ()));
475 }
476 
477 template <>
478 OCTAVE_API void
480 {
481  if (packed ())
482  unpack ();
483 
484  FloatMatrix& l = m_L;
485  FloatMatrix& r = m_a_fact;
486 
487  F77_INT m = to_f77_int (l.rows ());
488  F77_INT n = to_f77_int (r.columns ());
489  F77_INT k = to_f77_int (l.columns ());
490 
491  F77_INT u_nr = to_f77_int (u.rows ());
492  F77_INT u_nc = to_f77_int (u.columns ());
493 
494  F77_INT v_nr = to_f77_int (v.rows ());
495  F77_INT v_nc = to_f77_int (v.columns ());
496 
497  if (u_nr != m || v_nr != n || u_nc != v_nc)
498  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
499 
500  for (volatile F77_INT i = 0; i < u_nc; i++)
501  {
502  FloatColumnVector utmp = u.column (i);
503  FloatColumnVector vtmp = v.column (i);
504  F77_XFCN (slu1up, SLU1UP, (m, n, l.fortran_vec (),
505  m, r.fortran_vec (), k,
506  utmp.fortran_vec (), vtmp.fortran_vec ()));
507  }
508 }
509 
510 template <>
511 OCTAVE_API void
513  const FloatColumnVector& v)
514 {
515  if (packed ())
516  unpack ();
517 
518  FloatMatrix& l = m_L;
519  FloatMatrix& r = m_a_fact;
520 
521  F77_INT m = to_f77_int (l.rows ());
522  F77_INT n = to_f77_int (r.columns ());
523  F77_INT k = to_f77_int (l.columns ());
524 
525  F77_INT u_nel = to_f77_int (u.numel ());
526  F77_INT v_nel = to_f77_int (v.numel ());
527 
528  if (u_nel != m || v_nel != n)
529  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
530 
531  FloatColumnVector utmp = u;
532  FloatColumnVector vtmp = v;
533  OCTAVE_LOCAL_BUFFER (float, w, m);
534  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
535  F77_XFCN (slup1up, SLUP1UP, (m, n, l.fortran_vec (),
536  m, r.fortran_vec (), k,
537  m_ipvt.fortran_vec (),
538  utmp.data (), vtmp.data (), w));
539  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
540 }
541 
542 template <>
543 OCTAVE_API void
545 {
546  if (packed ())
547  unpack ();
548 
549  FloatMatrix& l = m_L;
550  FloatMatrix& r = m_a_fact;
551 
552  F77_INT m = to_f77_int (l.rows ());
553  F77_INT n = to_f77_int (r.columns ());
554  F77_INT k = to_f77_int (l.columns ());
555 
556  F77_INT u_nr = to_f77_int (u.rows ());
557  F77_INT u_nc = to_f77_int (u.columns ());
558 
559  F77_INT v_nr = to_f77_int (v.rows ());
560  F77_INT v_nc = to_f77_int (v.columns ());
561 
562  if (u_nr != m || v_nr != n || u_nc != v_nc)
563  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
564 
565  OCTAVE_LOCAL_BUFFER (float, w, m);
566  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
567  for (volatile F77_INT i = 0; i < u_nc; i++)
568  {
569  FloatColumnVector utmp = u.column (i);
570  FloatColumnVector vtmp = v.column (i);
571  F77_XFCN (slup1up, SLUP1UP, (m, n, l.fortran_vec (),
572  m, r.fortran_vec (), k,
573  m_ipvt.fortran_vec (),
574  utmp.data (), vtmp.data (), w));
575  }
576  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
577 }
578 
579 #endif
580 
581 template <>
584 {
585  F77_INT a_nr = to_f77_int (a.rows ());
586  F77_INT a_nc = to_f77_int (a.columns ());
587  F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);
588 
589  m_ipvt.resize (dim_vector (mn, 1));
590  F77_INT *pipvt = m_ipvt.fortran_vec ();
591 
592  m_a_fact = a;
593  Complex *tmp_data = m_a_fact.fortran_vec ();
594 
595  F77_INT info = 0;
596 
597  F77_XFCN (zgetrf, ZGETRF, (a_nr, a_nc, F77_DBLE_CMPLX_ARG (tmp_data),
598  a_nr, pipvt, info));
599 
600  for (F77_INT i = 0; i < mn; i++)
601  pipvt[i] -= 1;
602 }
603 
604 #if defined (HAVE_QRUPDATE_LUU)
605 
606 template <>
607 OCTAVE_API void
609  const ComplexColumnVector& v)
610 {
611  if (packed ())
612  unpack ();
613 
614  ComplexMatrix& l = m_L;
615  ComplexMatrix& r = m_a_fact;
616 
617  F77_INT m = to_f77_int (l.rows ());
618  F77_INT n = to_f77_int (r.columns ());
619  F77_INT k = to_f77_int (l.columns ());
620 
621  F77_INT u_nel = to_f77_int (u.numel ());
622  F77_INT v_nel = to_f77_int (v.numel ());
623 
624  if (u_nel != m || v_nel != n)
625  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
626 
627  ComplexColumnVector utmp = u;
628  ComplexColumnVector vtmp = v;
629  F77_XFCN (zlu1up, ZLU1UP, (m, n, F77_DBLE_CMPLX_ARG (l.fortran_vec ()), m,
630  F77_DBLE_CMPLX_ARG (r.fortran_vec ()), k,
631  F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()),
632  F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ())));
633 }
634 
635 template <>
636 OCTAVE_API void
638 {
639  if (packed ())
640  unpack ();
641 
642  ComplexMatrix& l = m_L;
643  ComplexMatrix& r = m_a_fact;
644 
645  F77_INT m = to_f77_int (l.rows ());
646  F77_INT n = to_f77_int (r.columns ());
647  F77_INT k = to_f77_int (l.columns ());
648 
649  F77_INT u_nr = to_f77_int (u.rows ());
650  F77_INT u_nc = to_f77_int (u.columns ());
651 
652  F77_INT v_nr = to_f77_int (v.rows ());
653  F77_INT v_nc = to_f77_int (v.columns ());
654 
655  if (u_nr != m || v_nr != n || u_nc != v_nc)
656  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
657 
658  for (volatile F77_INT i = 0; i < u_nc; i++)
659  {
660  ComplexColumnVector utmp = u.column (i);
661  ComplexColumnVector vtmp = v.column (i);
662  F77_XFCN (zlu1up, ZLU1UP, (m, n,
664  m, F77_DBLE_CMPLX_ARG (r.fortran_vec ()),
665  k,
667  F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ())));
668  }
669 }
670 
671 template <>
672 OCTAVE_API void
674  const ComplexColumnVector& v)
675 {
676  if (packed ())
677  unpack ();
678 
679  ComplexMatrix& l = m_L;
680  ComplexMatrix& r = m_a_fact;
681 
682  F77_INT m = to_f77_int (l.rows ());
683  F77_INT n = to_f77_int (r.columns ());
684  F77_INT k = to_f77_int (l.columns ());
685 
686  F77_INT u_nel = to_f77_int (u.numel ());
687  F77_INT v_nel = to_f77_int (v.numel ());
688 
689  if (u_nel != m || v_nel != n)
690  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
691 
692  ComplexColumnVector utmp = u;
693  ComplexColumnVector vtmp = v;
695  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
696  F77_XFCN (zlup1up, ZLUP1UP, (m, n, F77_DBLE_CMPLX_ARG (l.fortran_vec ()),
697  m, F77_DBLE_CMPLX_ARG (r.fortran_vec ()), k,
698  m_ipvt.fortran_vec (),
699  F77_CONST_DBLE_CMPLX_ARG (utmp.data ()),
700  F77_CONST_DBLE_CMPLX_ARG (vtmp.data ()),
701  F77_DBLE_CMPLX_ARG (w)));
702  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
703 }
704 
705 template <>
706 OCTAVE_API void
708  const ComplexMatrix& v)
709 {
710  if (packed ())
711  unpack ();
712 
713  ComplexMatrix& l = m_L;
714  ComplexMatrix& r = m_a_fact;
715 
716  F77_INT m = to_f77_int (l.rows ());
717  F77_INT n = to_f77_int (r.columns ());
718  F77_INT k = to_f77_int (l.columns ());
719 
720  F77_INT u_nr = to_f77_int (u.rows ());
721  F77_INT u_nc = to_f77_int (u.columns ());
722 
723  F77_INT v_nr = to_f77_int (v.rows ());
724  F77_INT v_nc = to_f77_int (v.columns ());
725 
726  if (u_nr != m || v_nr != n || u_nc != v_nc)
727  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
728 
730  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
731  for (volatile F77_INT i = 0; i < u_nc; i++)
732  {
733  ComplexColumnVector utmp = u.column (i);
734  ComplexColumnVector vtmp = v.column (i);
735  F77_XFCN (zlup1up, ZLUP1UP, (m, n,
737  m,
738  F77_DBLE_CMPLX_ARG (r.fortran_vec ()),
739  k, m_ipvt.fortran_vec (),
740  F77_CONST_DBLE_CMPLX_ARG (utmp.data ()),
741  F77_CONST_DBLE_CMPLX_ARG (vtmp.data ()),
742  F77_DBLE_CMPLX_ARG (w)));
743  }
744  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
745 }
746 
747 #endif
748 
749 template <>
752 {
753  F77_INT a_nr = to_f77_int (a.rows ());
754  F77_INT a_nc = to_f77_int (a.columns ());
755  F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);
756 
757  m_ipvt.resize (dim_vector (mn, 1));
758  F77_INT *pipvt = m_ipvt.fortran_vec ();
759 
760  m_a_fact = a;
761  FloatComplex *tmp_data = m_a_fact.fortran_vec ();
762 
763  F77_INT info = 0;
764 
765  F77_XFCN (cgetrf, CGETRF, (a_nr, a_nc, F77_CMPLX_ARG (tmp_data), a_nr,
766  pipvt, info));
767 
768  for (F77_INT i = 0; i < mn; i++)
769  pipvt[i] -= 1;
770 }
771 
772 #if defined (HAVE_QRUPDATE_LUU)
773 
774 template <>
775 OCTAVE_API void
777  const FloatComplexColumnVector& v)
778 {
779  if (packed ())
780  unpack ();
781 
782  FloatComplexMatrix& l = m_L;
783  FloatComplexMatrix& r = m_a_fact;
784 
785  F77_INT m = to_f77_int (l.rows ());
786  F77_INT n = to_f77_int (r.columns ());
787  F77_INT k = to_f77_int (l.columns ());
788 
789  F77_INT u_nel = to_f77_int (u.numel ());
790  F77_INT v_nel = to_f77_int (v.numel ());
791 
792  if (u_nel != m || v_nel != n)
793  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
794 
795  FloatComplexColumnVector utmp = u;
796  FloatComplexColumnVector vtmp = v;
797  F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()), m,
798  F77_CMPLX_ARG (r.fortran_vec ()), k,
799  F77_CMPLX_ARG (utmp.fortran_vec ()),
800  F77_CMPLX_ARG (vtmp.fortran_vec ())));
801 }
802 
803 template <>
804 OCTAVE_API void
806  const FloatComplexMatrix& v)
807 {
808  if (packed ())
809  unpack ();
810 
811  FloatComplexMatrix& l = m_L;
812  FloatComplexMatrix& r = m_a_fact;
813 
814  F77_INT m = to_f77_int (l.rows ());
815  F77_INT n = to_f77_int (r.columns ());
816  F77_INT k = to_f77_int (l.columns ());
817 
818  F77_INT u_nr = to_f77_int (u.rows ());
819  F77_INT u_nc = to_f77_int (u.columns ());
820 
821  F77_INT v_nr = to_f77_int (v.rows ());
822  F77_INT v_nc = to_f77_int (v.columns ());
823 
824  if (u_nr != m || v_nr != n || u_nc != v_nc)
825  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
826 
827  for (volatile F77_INT i = 0; i < u_nc; i++)
828  {
829  FloatComplexColumnVector utmp = u.column (i);
830  FloatComplexColumnVector vtmp = v.column (i);
831  F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()),
832  m, F77_CMPLX_ARG (r.fortran_vec ()), k,
833  F77_CMPLX_ARG (utmp.fortran_vec ()),
834  F77_CMPLX_ARG (vtmp.fortran_vec ())));
835  }
836 }
837 
838 template <>
839 OCTAVE_API void
841  const FloatComplexColumnVector& v)
842 {
843  if (packed ())
844  unpack ();
845 
846  FloatComplexMatrix& l = m_L;
847  FloatComplexMatrix& r = m_a_fact;
848 
849  F77_INT m = to_f77_int (l.rows ());
850  F77_INT n = to_f77_int (r.columns ());
851  F77_INT k = to_f77_int (l.columns ());
852 
853  F77_INT u_nel = to_f77_int (u.numel ());
854  F77_INT v_nel = to_f77_int (v.numel ());
855 
856  if (u_nel != m || v_nel != n)
857  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
858 
859  FloatComplexColumnVector utmp = u;
860  FloatComplexColumnVector vtmp = v;
862  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
863  F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()),
864  m, F77_CMPLX_ARG (r.fortran_vec ()), k,
865  m_ipvt.fortran_vec (),
866  F77_CONST_CMPLX_ARG (utmp.data ()),
867  F77_CONST_CMPLX_ARG (vtmp.data ()),
868  F77_CMPLX_ARG (w)));
869  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
870 }
871 
872 template <>
873 OCTAVE_API void
875  const FloatComplexMatrix& v)
876 {
877  if (packed ())
878  unpack ();
879 
880  FloatComplexMatrix& l = m_L;
881  FloatComplexMatrix& r = m_a_fact;
882 
883  F77_INT m = to_f77_int (l.rows ());
884  F77_INT n = to_f77_int (r.columns ());
885  F77_INT k = to_f77_int (l.columns ());
886 
887  F77_INT u_nr = to_f77_int (u.rows ());
888  F77_INT u_nc = to_f77_int (u.columns ());
889 
890  F77_INT v_nr = to_f77_int (v.rows ());
891  F77_INT v_nc = to_f77_int (v.columns ());
892 
893  if (u_nr != m || v_nr != n || u_nc != v_nc)
894  (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
895 
897  for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
898  for (volatile F77_INT i = 0; i < u_nc; i++)
899  {
900  FloatComplexColumnVector utmp = u.column (i);
901  FloatComplexColumnVector vtmp = v.column (i);
902  F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()),
903  m, F77_CMPLX_ARG (r.fortran_vec ()), k,
904  m_ipvt.fortran_vec (),
905  F77_CONST_CMPLX_ARG (utmp.data ()),
906  F77_CONST_CMPLX_ARG (vtmp.data ()),
907  F77_CMPLX_ARG (w)));
908  }
909  for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
910 }
911 
912 #endif
913 
914 // Instantiations we need.
915 
916 template class lu<Matrix>;
917 
918 template class lu<FloatMatrix>;
919 
920 template class lu<ComplexMatrix>;
921 
922 template class lu<FloatComplexMatrix>;
923 
924 OCTAVE_END_NAMESPACE(math)
925 OCTAVE_END_NAMESPACE(octave)
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:207
T * fortran_vec()
Size of the specified dimension.
Definition: Array-base.cc:1764
octave_idx_type rows() const
Definition: Array.h:459
const T * data() const
Size of the specified dimension.
Definition: Array.h:663
octave_idx_type columns() const
Definition: Array.h:471
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:524
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
ComplexColumnVector column(octave_idx_type i) const
Definition: CMatrix.cc:708
FloatComplexColumnVector column(octave_idx_type i) const
Definition: fCMatrix.cc:711
FloatColumnVector column(octave_idx_type i) const
Definition: fMatrix.cc:428
Definition: dMatrix.h:42
ColumnVector column(octave_idx_type i) const
Definition: dMatrix.cc:422
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
Definition: lu.h:42
bool packed() const
Definition: lu.cc:68
lu()
Definition: lu.h:48
void update_piv(const VT &u, const VT &v)
T U() const
Definition: lu.cc:123
void unpack()
Definition: lu.cc:75
ColumnVector P_vec() const
Definition: lu.cc:196
bool regular() const
Definition: lu.cc:212
void update(const VT &u, const VT &v)
T::element_type ELT_T
Definition: lu.h:46
PermMatrix P() const
Definition: lu.cc:189
Array< octave_idx_type > getp() const
Definition: lu.cc:158
T L() const
Definition: lu.cc:96
T Y() const
Definition: lu.cc:147
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define F77_CONST_CMPLX_ARG(x)
Definition: f77-fcn.h:313
#define F77_DBLE_CMPLX_ARG(x)
Definition: f77-fcn.h:316
#define F77_CMPLX_ARG(x)
Definition: f77-fcn.h:310
#define F77_XFCN(f, F, args)
Definition: f77-fcn.h:45
octave_f77_int_type F77_INT
Definition: f77-fcn.h:306
#define F77_CONST_DBLE_CMPLX_ARG(x)
Definition: f77-fcn.h:319
#define OCTAVE_API
Definition: main.cc:55
T octave_idx_type m
Definition: mx-inlines.cc:781
octave_idx_type n
Definition: mx-inlines.cc:761
T * r
Definition: mx-inlines.cc:781
std::complex< double > w(std::complex< double > z, double relerr=0)
std::complex< double > Complex
Definition: oct-cmplx.h:33
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44