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
fMatrix.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1994-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 #include <istream>
32 #include <limits>
33 #include <ostream>
34 
35 #include "Array-util.h"
36 #include "DET.h"
37 #include "PermMatrix.h"
38 #include "boolMatrix.h"
39 #include "byte-swap.h"
40 #include "chMatrix.h"
41 #include "chol.h"
42 #include "fCColVector.h"
43 #include "fCMatrix.h"
44 #include "fColVector.h"
45 #include "fDiagMatrix.h"
46 #include "fMatrix.h"
47 #include "fMatrix.h"
48 #include "fNDArray.h"
49 #include "fRowVector.h"
50 #include "lo-blas-proto.h"
51 #include "lo-error.h"
52 #include "lo-ieee.h"
53 #include "lo-lapack-proto.h"
54 #include "lo-mappers.h"
55 #include "lo-utils.h"
56 #include "mx-fdm-fm.h"
57 #include "mx-fm-fdm.h"
58 #include "mx-inlines.cc"
59 #include "mx-op-defs.h"
60 #include "oct-cmplx.h"
61 #include "oct-fftw.h"
62 #include "oct-locbuf.h"
63 #include "oct-norm.h"
64 #include "quit.h"
65 #include "schur.h"
66 #include "svd.h"
67 
68 // Matrix class.
69 
71  : FloatNDArray (rv)
72 { }
73 
75  : FloatNDArray (cv)
76 { }
77 
79  : FloatNDArray (a.dims (), 0.0)
80 {
81  for (octave_idx_type i = 0; i < a.length (); i++)
82  elem (i, i) = a.elem (i, i);
83 }
84 
86  : FloatNDArray (a.dims (), 0.0)
87 {
88  for (octave_idx_type i = 0; i < a.length (); i++)
89  elem (i, i) = a.elem (i, i);
90 }
91 
93  : FloatNDArray (a.dims (), 0.0)
94 {
95  for (octave_idx_type i = 0; i < a.length (); i++)
96  elem (i, i) = a.elem (i, i);
97 }
98 
100  : FloatNDArray (a.dims (), 0.0)
101 {
102  const Array<octave_idx_type> ia (a.col_perm_vec ());
103  octave_idx_type len = a.rows ();
104  for (octave_idx_type i = 0; i < len; i++)
105  elem (ia(i), i) = 1.0;
106 }
107 
108 // FIXME: could we use a templated mixed-type copy function here?
109 
111  : FloatNDArray (a)
112 { }
113 
115  : FloatNDArray (a.dims ())
116 {
117  for (octave_idx_type i = 0; i < a.rows (); i++)
118  for (octave_idx_type j = 0; j < a.cols (); j++)
119  elem (i, j) = static_cast<unsigned char> (a.elem (i, j));
120 }
121 
122 bool
124 {
125  if (rows () != a.rows () || cols () != a.cols ())
126  return false;
127 
128  return mx_inline_equal (numel (), data (), a.data ());
129 }
130 
131 bool
133 {
134  return !(*this == a);
135 }
136 
137 bool
139 {
140  if (issquare () && rows () > 0)
141  {
142  for (octave_idx_type i = 0; i < rows (); i++)
143  for (octave_idx_type j = i+1; j < cols (); j++)
144  if (elem (i, j) != elem (j, i))
145  return false;
146 
147  return true;
148  }
149 
150  return false;
151 }
152 
156 {
157  FloatNDArray::insert (a, r, c);
158  return *this;
159 }
160 
164 {
165  octave_idx_type a_len = a.numel ();
166 
167  if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ())
168  (*current_liboctave_error_handler) ("range error for insert");
169 
170  if (a_len > 0)
171  {
172  make_unique ();
173 
174  for (octave_idx_type i = 0; i < a_len; i++)
175  xelem (r, c+i) = a.elem (i);
176  }
177 
178  return *this;
179 }
180 
184 {
185  octave_idx_type a_len = a.numel ();
186 
187  if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ())
188  (*current_liboctave_error_handler) ("range error for insert");
189 
190  if (a_len > 0)
191  {
192  make_unique ();
193 
194  for (octave_idx_type i = 0; i < a_len; i++)
195  xelem (r+i, c) = a.elem (i);
196  }
197 
198  return *this;
199 }
200 
204 {
205  octave_idx_type a_nr = a.rows ();
206  octave_idx_type a_nc = a.cols ();
207 
208  if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())
209  (*current_liboctave_error_handler) ("range error for insert");
210 
211  fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1);
212 
213  octave_idx_type a_len = a.length ();
214 
215  if (a_len > 0)
216  {
217  make_unique ();
218 
219  for (octave_idx_type i = 0; i < a_len; i++)
220  xelem (r+i, c+i) = a.elem (i, i);
221  }
222 
223  return *this;
224 }
225 
227 FloatMatrix::fill (float val)
228 {
229  octave_idx_type nr = rows ();
230  octave_idx_type nc = cols ();
231 
232  if (nr > 0 && nc > 0)
233  {
234  make_unique ();
235 
236  for (octave_idx_type j = 0; j < nc; j++)
237  for (octave_idx_type i = 0; i < nr; i++)
238  xelem (i, j) = val;
239  }
240 
241  return *this;
242 }
243 
247 {
248  octave_idx_type nr = rows ();
249  octave_idx_type nc = cols ();
250 
251  if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0
252  || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)
253  (*current_liboctave_error_handler) ("range error for fill");
254 
255  if (r1 > r2) { std::swap (r1, r2); }
256  if (c1 > c2) { std::swap (c1, c2); }
257 
258  if (r2 >= r1 && c2 >= c1)
259  {
260  make_unique ();
261 
262  for (octave_idx_type j = c1; j <= c2; j++)
263  for (octave_idx_type i = r1; i <= r2; i++)
264  xelem (i, j) = val;
265  }
266 
267  return *this;
268 }
269 
272 {
273  octave_idx_type nr = rows ();
274  octave_idx_type nc = cols ();
275  if (nr != a.rows ())
276  (*current_liboctave_error_handler) ("row dimension mismatch for append");
277 
278  octave_idx_type nc_insert = nc;
279  FloatMatrix retval (nr, nc + a.cols ());
280  retval.insert (*this, 0, 0);
281  retval.insert (a, 0, nc_insert);
282  return retval;
283 }
284 
287 {
288  octave_idx_type nr = rows ();
289  octave_idx_type nc = cols ();
290  if (nr != 1)
291  (*current_liboctave_error_handler) ("row dimension mismatch for append");
292 
293  octave_idx_type nc_insert = nc;
294  FloatMatrix retval (nr, nc + a.numel ());
295  retval.insert (*this, 0, 0);
296  retval.insert (a, 0, nc_insert);
297  return retval;
298 }
299 
302 {
303  octave_idx_type nr = rows ();
304  octave_idx_type nc = cols ();
305  if (nr != a.numel ())
306  (*current_liboctave_error_handler) ("row dimension mismatch for append");
307 
308  octave_idx_type nc_insert = nc;
309  FloatMatrix retval (nr, nc + 1);
310  retval.insert (*this, 0, 0);
311  retval.insert (a, 0, nc_insert);
312  return retval;
313 }
314 
317 {
318  octave_idx_type nr = rows ();
319  octave_idx_type nc = cols ();
320  if (nr != a.rows ())
321  (*current_liboctave_error_handler) ("row dimension mismatch for append");
322 
323  octave_idx_type nc_insert = nc;
324  FloatMatrix retval (nr, nc + a.cols ());
325  retval.insert (*this, 0, 0);
326  retval.insert (a, 0, nc_insert);
327  return retval;
328 }
329 
332 {
333  octave_idx_type nr = rows ();
334  octave_idx_type nc = cols ();
335  if (nc != a.cols ())
336  (*current_liboctave_error_handler) ("column dimension mismatch for stack");
337 
338  octave_idx_type nr_insert = nr;
339  FloatMatrix retval (nr + a.rows (), nc);
340  retval.insert (*this, 0, 0);
341  retval.insert (a, nr_insert, 0);
342  return retval;
343 }
344 
347 {
348  octave_idx_type nr = rows ();
349  octave_idx_type nc = cols ();
350  if (nc != a.numel ())
351  (*current_liboctave_error_handler) ("column dimension mismatch for stack");
352 
353  octave_idx_type nr_insert = nr;
354  FloatMatrix retval (nr + 1, nc);
355  retval.insert (*this, 0, 0);
356  retval.insert (a, nr_insert, 0);
357  return retval;
358 }
359 
362 {
363  octave_idx_type nr = rows ();
364  octave_idx_type nc = cols ();
365  if (nc != 1)
366  (*current_liboctave_error_handler) ("column dimension mismatch for stack");
367 
368  octave_idx_type nr_insert = nr;
369  FloatMatrix retval (nr + a.numel (), nc);
370  retval.insert (*this, 0, 0);
371  retval.insert (a, nr_insert, 0);
372  return retval;
373 }
374 
377 {
378  octave_idx_type nr = rows ();
379  octave_idx_type nc = cols ();
380  if (nc != a.cols ())
381  (*current_liboctave_error_handler) ("column dimension mismatch for stack");
382 
383  octave_idx_type nr_insert = nr;
384  FloatMatrix retval (nr + a.rows (), nc);
385  retval.insert (*this, 0, 0);
386  retval.insert (a, nr_insert, 0);
387  return retval;
388 }
389 
392 {
393  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_real);
394 }
395 
398 {
399  return do_mx_unary_op<float, FloatComplex> (a, mx_inline_imag);
400 }
401 
404  octave_idx_type r2, octave_idx_type c2) const
405 {
406  if (r1 > r2) { std::swap (r1, r2); }
407  if (c1 > c2) { std::swap (c1, c2); }
408 
409  return index (octave::idx_vector (r1, r2+1), octave::idx_vector (c1, c2+1));
410 }
411 
414  octave_idx_type nr, octave_idx_type nc) const
415 {
416  return index (octave::idx_vector (r1, r1 + nr), octave::idx_vector (c1, c1 + nc));
417 }
418 
419 // extract row or column i.
420 
423 {
424  return index (octave::idx_vector (i), octave::idx_vector::colon);
425 }
426 
429 {
430  return index (octave::idx_vector::colon, octave::idx_vector (i));
431 }
432 
433 // Local function to calculate the 1-norm.
434 static
435 float
436 norm1 (const FloatMatrix& a)
437 {
438  float anorm = 0.0;
439  FloatRowVector colsum = a.abs ().sum ().row (0);
440 
441  for (octave_idx_type i = 0; i < colsum.numel (); i++)
442  {
443  float sum = colsum.xelem (i);
444  if (octave::math::isinf (sum) || octave::math::isnan (sum))
445  {
446  anorm = sum; // Pass Inf or NaN to output
447  break;
448  }
449  else
450  anorm = std::max (anorm, sum);
451  }
452 
453  return anorm;
454 }
455 
458 {
459  octave_idx_type info;
460  float rcon;
461  MatrixType mattype (*this);
462  return inverse (mattype, info, rcon, 0, 0);
463 }
464 
467 {
468  float rcon;
469  MatrixType mattype (*this);
470  return inverse (mattype, info, rcon, 0, 0);
471 }
472 
474 FloatMatrix::inverse (octave_idx_type& info, float& rcon, bool force,
475  bool calc_cond) const
476 {
477  MatrixType mattype (*this);
478  return inverse (mattype, info, rcon, force, calc_cond);
479 }
480 
483 {
484  octave_idx_type info;
485  float rcon;
486  return inverse (mattype, info, rcon, 0, 0);
487 }
488 
491 {
492  float rcon;
493  return inverse (mattype, info, rcon, 0, 0);
494 }
495 
497 FloatMatrix::tinverse (MatrixType& mattype, octave_idx_type& info, float& rcon,
498  bool force, bool calc_cond) const
499 {
500  FloatMatrix retval;
501 
502  F77_INT nr = octave::to_f77_int (rows ());
503  F77_INT nc = octave::to_f77_int (cols ());
504 
505  if (nr != nc || nr == 0 || nc == 0)
506  (*current_liboctave_error_handler) ("inverse requires square matrix");
507 
508  int typ = mattype.type ();
509  char uplo = (typ == MatrixType::Lower ? 'L' : 'U');
510  char udiag = 'N';
511  retval = *this;
512  float *tmp_data = retval.fortran_vec ();
513 
514  F77_INT tmp_info = 0;
515 
516  F77_XFCN (strtri, STRTRI, (F77_CONST_CHAR_ARG2 (&uplo, 1),
517  F77_CONST_CHAR_ARG2 (&udiag, 1),
518  nr, tmp_data, nr, tmp_info
519  F77_CHAR_ARG_LEN (1)
520  F77_CHAR_ARG_LEN (1)));
521 
522  info = tmp_info;
523 
524  // Throw away extra info LAPACK gives so as to not change output.
525  rcon = 0.0;
526  if (info != 0)
527  info = -1;
528  else if (calc_cond)
529  {
530  F77_INT dtrcon_info = 0;
531  char job = '1';
532 
533  OCTAVE_LOCAL_BUFFER (float, work, 3 * nr);
534  OCTAVE_LOCAL_BUFFER (F77_INT, iwork, nr);
535 
536  F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&job, 1),
537  F77_CONST_CHAR_ARG2 (&uplo, 1),
538  F77_CONST_CHAR_ARG2 (&udiag, 1),
539  nr, tmp_data, nr, rcon,
540  work, iwork, dtrcon_info
541  F77_CHAR_ARG_LEN (1)
542  F77_CHAR_ARG_LEN (1)
543  F77_CHAR_ARG_LEN (1)));
544 
545  if (dtrcon_info != 0)
546  info = -1;
547  }
548 
549  if (info == -1 && ! force)
550  retval = *this; // Restore matrix contents.
551 
552  return retval;
553 }
554 
556 FloatMatrix::finverse (MatrixType& mattype, octave_idx_type& info, float& rcon,
557  bool force, bool calc_cond) const
558 {
559  FloatMatrix retval;
560 
561  F77_INT nr = octave::to_f77_int (rows ());
562  F77_INT nc = octave::to_f77_int (cols ());
563 
564  if (nr != nc || nr == 0 || nc == 0)
565  (*current_liboctave_error_handler) ("inverse requires square matrix");
566 
567  Array<F77_INT> ipvt (dim_vector (nr, 1));
568  F77_INT *pipvt = ipvt.fortran_vec ();
569 
570  retval = *this;
571  float *tmp_data = retval.fortran_vec ();
572 
573  Array<float> z (dim_vector (1, 1));
574  F77_INT lwork = -1;
575 
576  F77_INT tmp_info = 0;
577 
578  // Query the optimum work array size.
579  F77_XFCN (sgetri, SGETRI, (nc, tmp_data, nr, pipvt,
580  z.fortran_vec (), lwork, tmp_info));
581 
582  lwork = static_cast<F77_INT> (z(0));
583  lwork = (lwork < 4 * nc ? 4 * nc : lwork);
584  z.resize (dim_vector (lwork, 1));
585  float *pz = z.fortran_vec ();
586 
587  info = 0;
588  tmp_info = 0;
589 
590  // Calculate the norm of the matrix for later use when determining rcon.
591  float anorm;
592  if (calc_cond)
593  anorm = norm1 (retval);
594 
595  F77_XFCN (sgetrf, SGETRF, (nc, nc, tmp_data, nr, pipvt, tmp_info));
596 
597  info = tmp_info;
598 
599  // Throw away extra info LAPACK gives so as to not change output.
600  rcon = 0.0;
601  if (info != 0)
602  info = -1;
603  else if (calc_cond)
604  {
605  if (octave::math::isnan (anorm))
607  else
608  {
609  F77_INT sgecon_info = 0;
610 
611  // Now calculate the condition number for non-singular matrix.
612  char job = '1';
613  Array<F77_INT> iz (dim_vector (nc, 1));
614  F77_INT *piz = iz.fortran_vec ();
615  F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
616  nc, tmp_data, nr, anorm,
617  rcon, pz, piz, sgecon_info
618  F77_CHAR_ARG_LEN (1)));
619 
620  if (sgecon_info != 0)
621  info = -1;
622  }
623  }
624 
625  if (info == -1 && ! force)
626  retval = *this; // Restore matrix contents.
627  else
628  {
629  F77_INT dgetri_info = 0;
630 
631  F77_XFCN (sgetri, SGETRI, (nc, tmp_data, nr, pipvt,
632  pz, lwork, dgetri_info));
633 
634  if (dgetri_info != 0)
635  info = -1;
636  }
637 
638  if (info != 0)
639  mattype.mark_as_rectangular ();
640 
641  return retval;
642 }
643 
645 FloatMatrix::inverse (MatrixType& mattype, octave_idx_type& info, float& rcon,
646  bool force, bool calc_cond) const
647 {
648  int typ = mattype.type (false);
649  FloatMatrix ret;
650 
651  if (typ == MatrixType::Unknown)
652  typ = mattype.type (*this);
653 
654  if (typ == MatrixType::Diagonal) // a scalar is classified as Diagonal.
655  {
656  ret = 1 / (*this);
657  if (calc_cond)
658  {
659  float scalar = this->elem (0);
660  if (octave::math::isfinite (scalar) && scalar != 0)
661  rcon = 1.0f;
662  else if (octave::math::isinf (scalar) || scalar == 0)
663  rcon = 0.0f;
664  else
666  }
667  }
668  else if (typ == MatrixType::Upper || typ == MatrixType::Lower)
669  ret = tinverse (mattype, info, rcon, force, calc_cond);
670  else
671  {
672  if (mattype.ishermitian ())
673  {
674  octave::math::chol<FloatMatrix> chol (*this, info, true, calc_cond);
675  if (info == 0)
676  {
677  if (calc_cond)
678  rcon = chol.rcond ();
679  else
680  rcon = 1.0;
681  ret = chol.inverse ();
682  }
683  else
684  mattype.mark_as_unsymmetric ();
685  }
686 
687  if (! mattype.ishermitian ())
688  ret = finverse (mattype, info, rcon, force, calc_cond);
689 
690  if ((calc_cond || mattype.ishermitian ()) && rcon == 0.0)
691  ret = FloatMatrix (rows (), columns (),
693  }
694 
695  return ret;
696 }
697 
700 {
701  octave::math::svd<FloatMatrix> result (*this,
702  octave::math::svd<FloatMatrix>::Type::economy);
703 
704  FloatDiagMatrix S = result.singular_values ();
705  FloatMatrix U = result.left_singular_matrix ();
706  FloatMatrix V = result.right_singular_matrix ();
707 
708  FloatColumnVector sigma = S.extract_diag ();
709 
710  octave_idx_type r = sigma.numel () - 1;
711  octave_idx_type nr = rows ();
712  octave_idx_type nc = cols ();
713 
714  if (tol <= 0.0)
715  {
716  tol = std::max (nr, nc) * sigma.elem (0)
717  * std::numeric_limits<float>::epsilon ();
718 
719  if (tol == 0)
721  }
722 
723  while (r >= 0 && sigma.elem (r) < tol)
724  r--;
725 
726  if (r < 0)
727  return FloatMatrix (nc, nr, 0.0);
728  else
729  {
730  FloatMatrix Ur = U.extract (0, 0, nr-1, r);
731  FloatDiagMatrix D = FloatDiagMatrix (sigma.extract (0, r)).inverse ();
732  FloatMatrix Vr = V.extract (0, 0, nc-1, r);
733  return Vr * D * Ur.transpose ();
734  }
735 }
736 
737 #if defined (HAVE_FFTW)
738 
741 {
742  std::size_t nr = rows ();
743  std::size_t nc = cols ();
744 
745  FloatComplexMatrix retval (nr, nc);
746 
747  std::size_t npts, nsamples;
748 
749  if (nr == 1 || nc == 1)
750  {
751  npts = (nr > nc ? nr : nc);
752  nsamples = 1;
753  }
754  else
755  {
756  npts = nr;
757  nsamples = nc;
758  }
759 
760  const float *in (data ());
761  FloatComplex *out (retval.fortran_vec ());
762 
763  octave::fftw::fft (in, out, npts, nsamples);
764 
765  return retval;
766 }
767 
770 {
771  std::size_t nr = rows ();
772  std::size_t nc = cols ();
773 
774  FloatComplexMatrix retval (nr, nc);
775 
776  std::size_t npts, nsamples;
777 
778  if (nr == 1 || nc == 1)
779  {
780  npts = (nr > nc ? nr : nc);
781  nsamples = 1;
782  }
783  else
784  {
785  npts = nr;
786  nsamples = nc;
787  }
788 
789  FloatComplexMatrix tmp (*this);
790  FloatComplex *in (tmp.fortran_vec ());
791  FloatComplex *out (retval.fortran_vec ());
792 
793  octave::fftw::ifft (in, out, npts, nsamples);
794 
795  return retval;
796 }
797 
800 {
801  dim_vector dv (rows (), cols ());
802 
803  const float *in = data ();
804  FloatComplexMatrix retval (rows (), cols ());
805  octave::fftw::fftNd (in, retval.fortran_vec (), 2, dv);
806 
807  return retval;
808 }
809 
812 {
813  dim_vector dv (rows (), cols ());
814 
815  FloatComplexMatrix retval (*this);
816  FloatComplex *out (retval.fortran_vec ());
817 
818  octave::fftw::ifftNd (out, out, 2, dv);
819 
820  return retval;
821 }
822 
823 #else
824 
826 FloatMatrix::fourier () const
827 {
828  (*current_liboctave_error_handler)
829  ("support for FFTW was unavailable or disabled when liboctave was built");
830 
831  return FloatComplexMatrix ();
832 }
833 
835 FloatMatrix::ifourier () const
836 {
837  (*current_liboctave_error_handler)
838  ("support for FFTW was unavailable or disabled when liboctave was built");
839 
840  return FloatComplexMatrix ();
841 }
842 
844 FloatMatrix::fourier2d () const
845 {
846  (*current_liboctave_error_handler)
847  ("support for FFTW was unavailable or disabled when liboctave was built");
848 
849  return FloatComplexMatrix ();
850 }
851 
854 {
855  (*current_liboctave_error_handler)
856  ("support for FFTW was unavailable or disabled when liboctave was built");
857 
858  return FloatComplexMatrix ();
859 }
860 
861 #endif
862 
863 FloatDET
865 {
866  octave_idx_type info;
867  float rcon;
868  return determinant (info, rcon, 0);
869 }
870 
871 FloatDET
873 {
874  float rcon;
875  return determinant (info, rcon, 0);
876 }
877 
878 FloatDET
880  bool calc_cond) const
881 {
882  MatrixType mattype (*this);
883  return determinant (mattype, info, rcon, calc_cond);
884 }
885 
886 FloatDET
888  octave_idx_type& info, float& rcon,
889  bool calc_cond) const
890 {
891  FloatDET retval (1.0);
892 
893  info = 0;
894  rcon = 0.0;
895 
896  F77_INT nr = octave::to_f77_int (rows ());
897  F77_INT nc = octave::to_f77_int (cols ());
898 
899  if (nr != nc)
900  (*current_liboctave_error_handler) ("matrix must be square");
901 
902  volatile int typ = mattype.type ();
903 
904  // Even though the matrix is marked as singular (Rectangular), we may
905  // still get a useful number from the LU factorization, because it always
906  // completes.
907 
908  if (typ == MatrixType::Unknown)
909  typ = mattype.type (*this);
910  else if (typ == MatrixType::Rectangular)
911  typ = MatrixType::Full;
912 
913  if (typ == MatrixType::Lower || typ == MatrixType::Upper)
914  {
915  for (F77_INT i = 0; i < nc; i++)
916  retval *= elem (i, i);
917  }
918  else if (typ == MatrixType::Hermitian)
919  {
920  FloatMatrix atmp = *this;
921  float *tmp_data = atmp.fortran_vec ();
922 
923  // Calculate the norm of the matrix for later use when determining rcon.
924  float anorm;
925  if (calc_cond)
926  anorm = norm1 (*this);
927 
928  F77_INT tmp_info = 0;
929 
930  char job = 'L';
931  F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
932  tmp_data, nr, tmp_info
933  F77_CHAR_ARG_LEN (1)));
934 
935  info = tmp_info;
936 
937  if (info != 0)
938  {
939  rcon = 0.0;
940  mattype.mark_as_unsymmetric ();
941  typ = MatrixType::Full;
942  }
943  else
944  {
945  if (calc_cond)
946  {
947  Array<float> z (dim_vector (3 * nc, 1));
948  float *pz = z.fortran_vec ();
949  Array<F77_INT> iz (dim_vector (nc, 1));
950  F77_INT *piz = iz.fortran_vec ();
951 
952  F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
953  nr, tmp_data, nr, anorm,
954  rcon, pz, piz, tmp_info
955  F77_CHAR_ARG_LEN (1)));
956 
957  info = tmp_info;
958 
959  if (info != 0)
960  rcon = 0.0;
961  }
962 
963  for (F77_INT i = 0; i < nc; i++)
964  retval *= atmp(i, i);
965 
966  retval = retval.square ();
967  }
968  }
969  else if (typ != MatrixType::Full)
970  (*current_liboctave_error_handler) ("det: invalid dense matrix type");
971 
972  if (typ == MatrixType::Full)
973  {
974  Array<F77_INT> ipvt (dim_vector (nr, 1));
975  F77_INT *pipvt = ipvt.fortran_vec ();
976 
977  FloatMatrix atmp = *this;
978  float *tmp_data = atmp.fortran_vec ();
979 
980  info = 0;
981  F77_INT tmp_info = 0;
982 
983  // Calculate the norm of the matrix for later use when determining rcon.
984  float anorm;
985  if (calc_cond)
986  anorm = norm1 (*this);
987 
988  F77_XFCN (sgetrf, SGETRF, (nr, nr, tmp_data, nr, pipvt, tmp_info));
989 
990  info = tmp_info;
991 
992  // Throw away extra info LAPACK gives so as to not change output.
993  rcon = 0.0;
994  if (info != 0)
995  {
996  info = -1;
997  retval = FloatDET ();
998  }
999  else
1000  {
1001  if (calc_cond)
1002  {
1003  // Now calc the condition number for non-singular matrix.
1004  char job = '1';
1005  Array<float> z (dim_vector (4 * nc, 1));
1006  float *pz = z.fortran_vec ();
1007  Array<F77_INT> iz (dim_vector (nc, 1));
1008  F77_INT *piz = iz.fortran_vec ();
1009 
1010  F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
1011  nc, tmp_data, nr, anorm,
1012  rcon, pz, piz, tmp_info
1013  F77_CHAR_ARG_LEN (1)));
1014 
1015  info = tmp_info;
1016  }
1017 
1018  if (info != 0)
1019  {
1020  info = -1;
1021  retval = FloatDET ();
1022  }
1023  else
1024  {
1025  for (F77_INT i = 0; i < nc; i++)
1026  {
1027  float c = atmp(i, i);
1028  retval *= (ipvt(i) != (i+1)) ? -c : c;
1029  }
1030  }
1031  }
1032  }
1033 
1034  return retval;
1035 }
1036 
1037 float
1039 {
1040  MatrixType mattype (*this);
1041  return rcond (mattype);
1042 }
1043 
1044 float
1046 {
1047  float rcon = octave::numeric_limits<float>::NaN ();
1048  F77_INT nr = octave::to_f77_int (rows ());
1049  F77_INT nc = octave::to_f77_int (cols ());
1050 
1051  if (nr != nc)
1052  (*current_liboctave_error_handler) ("matrix must be square");
1053 
1054  if (nr == 0 || nc == 0)
1056  else
1057  {
1058  volatile int typ = mattype.type ();
1059 
1060  if (typ == MatrixType::Unknown)
1061  typ = mattype.type (*this);
1062 
1063  // Only calculate the condition number for LU/Cholesky
1064  if (typ == MatrixType::Upper)
1065  {
1066  const float *tmp_data = data ();
1067  F77_INT info = 0;
1068  char norm = '1';
1069  char uplo = 'U';
1070  char dia = 'N';
1071 
1072  Array<float> z (dim_vector (3 * nc, 1));
1073  float *pz = z.fortran_vec ();
1074  Array<F77_INT> iz (dim_vector (nc, 1));
1075  F77_INT *piz = iz.fortran_vec ();
1076 
1077  F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
1078  F77_CONST_CHAR_ARG2 (&uplo, 1),
1079  F77_CONST_CHAR_ARG2 (&dia, 1),
1080  nr, tmp_data, nr, rcon,
1081  pz, piz, info
1082  F77_CHAR_ARG_LEN (1)
1083  F77_CHAR_ARG_LEN (1)
1084  F77_CHAR_ARG_LEN (1)));
1085 
1086  if (info != 0)
1087  rcon = 0.0;
1088  }
1089  else if (typ == MatrixType::Permuted_Upper)
1090  (*current_liboctave_error_handler)
1091  ("permuted triangular matrix not implemented");
1092  else if (typ == MatrixType::Lower)
1093  {
1094  const float *tmp_data = data ();
1095  F77_INT info = 0;
1096  char norm = '1';
1097  char uplo = 'L';
1098  char dia = 'N';
1099 
1100  Array<float> z (dim_vector (3 * nc, 1));
1101  float *pz = z.fortran_vec ();
1102  Array<F77_INT> iz (dim_vector (nc, 1));
1103  F77_INT *piz = iz.fortran_vec ();
1104 
1105  F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
1106  F77_CONST_CHAR_ARG2 (&uplo, 1),
1107  F77_CONST_CHAR_ARG2 (&dia, 1),
1108  nr, tmp_data, nr, rcon,
1109  pz, piz, info
1110  F77_CHAR_ARG_LEN (1)
1111  F77_CHAR_ARG_LEN (1)
1112  F77_CHAR_ARG_LEN (1)));
1113 
1114  if (info != 0)
1115  rcon = 0.0;
1116  }
1117  else if (typ == MatrixType::Permuted_Lower)
1118  (*current_liboctave_error_handler)
1119  ("permuted triangular matrix not implemented");
1120  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
1121  {
1122  float anorm = -1.0;
1123 
1124  if (typ == MatrixType::Hermitian)
1125  {
1126  F77_INT info = 0;
1127  char job = 'L';
1128 
1129  FloatMatrix atmp = *this;
1130  float *tmp_data = atmp.fortran_vec ();
1131 
1132  anorm = norm1 (atmp);
1133 
1134  F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
1135  tmp_data, nr, info
1136  F77_CHAR_ARG_LEN (1)));
1137 
1138  if (info != 0)
1139  {
1140  rcon = 0.0;
1141  mattype.mark_as_unsymmetric ();
1142  typ = MatrixType::Full;
1143  }
1144  else
1145  {
1146  Array<float> z (dim_vector (3 * nc, 1));
1147  float *pz = z.fortran_vec ();
1148  Array<F77_INT> iz (dim_vector (nc, 1));
1149  F77_INT *piz = iz.fortran_vec ();
1150 
1151  F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
1152  nr, tmp_data, nr, anorm,
1153  rcon, pz, piz, info
1154  F77_CHAR_ARG_LEN (1)));
1155 
1156  if (info != 0)
1157  rcon = 0.0;
1158  }
1159  }
1160 
1161  if (typ == MatrixType::Full)
1162  {
1163  F77_INT info = 0;
1164 
1165  FloatMatrix atmp = *this;
1166  float *tmp_data = atmp.fortran_vec ();
1167 
1168  Array<F77_INT> ipvt (dim_vector (nr, 1));
1169  F77_INT *pipvt = ipvt.fortran_vec ();
1170 
1171  if (anorm < 0.0)
1172  anorm = norm1 (atmp);
1173 
1174  Array<float> z (dim_vector (4 * nc, 1));
1175  float *pz = z.fortran_vec ();
1176  Array<F77_INT> iz (dim_vector (nc, 1));
1177  F77_INT *piz = iz.fortran_vec ();
1178 
1179  F77_XFCN (sgetrf, SGETRF, (nr, nr, tmp_data, nr, pipvt, info));
1180 
1181  if (info != 0)
1182  {
1183  rcon = 0.0;
1184  mattype.mark_as_rectangular ();
1185  }
1186  else
1187  {
1188  char job = '1';
1189  F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
1190  nc, tmp_data, nr, anorm,
1191  rcon, pz, piz, info
1192  F77_CHAR_ARG_LEN (1)));
1193 
1194  if (info != 0)
1195  rcon = 0.0;
1196  }
1197  }
1198  }
1199  else
1200  rcon = 0.0;
1201  }
1202 
1203  return rcon;
1204 }
1205 
1207 FloatMatrix::utsolve (MatrixType& mattype, const FloatMatrix& b,
1208  octave_idx_type& info,
1209  float& rcon, solve_singularity_handler sing_handler,
1210  bool calc_cond, blas_trans_type transt) const
1211 {
1212  FloatMatrix retval;
1213 
1214  F77_INT nr = octave::to_f77_int (rows ());
1215  F77_INT nc = octave::to_f77_int (cols ());
1216 
1217  F77_INT b_nr = octave::to_f77_int (b.rows ());
1218  F77_INT b_nc = octave::to_f77_int (b.cols ());
1219 
1220  if (nr != b_nr)
1221  (*current_liboctave_error_handler)
1222  ("matrix dimension mismatch solution of linear equations");
1223 
1224  if (nr == 0 || nc == 0 || b_nc == 0)
1225  retval = FloatMatrix (nc, b_nc, 0.0);
1226  else
1227  {
1228  volatile int typ = mattype.type ();
1229 
1230  if (typ == MatrixType::Permuted_Upper || typ == MatrixType::Upper)
1231  {
1232  rcon = 1.0;
1233  info = 0;
1234 
1235  if (typ == MatrixType::Permuted_Upper)
1236  (*current_liboctave_error_handler)
1237  ("permuted triangular matrix not implemented");
1238  else
1239  {
1240  const float *tmp_data = data ();
1241 
1242  retval = b;
1243  float *result = retval.fortran_vec ();
1244 
1245  char uplo = 'U';
1246  char trans = get_blas_char (transt);
1247  char dia = 'N';
1248 
1249  F77_INT tmp_info = 0;
1250 
1251  F77_XFCN (strtrs, STRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
1252  F77_CONST_CHAR_ARG2 (&trans, 1),
1253  F77_CONST_CHAR_ARG2 (&dia, 1),
1254  nr, b_nc, tmp_data, nr,
1255  result, nr, tmp_info
1256  F77_CHAR_ARG_LEN (1)
1257  F77_CHAR_ARG_LEN (1)
1258  F77_CHAR_ARG_LEN (1)));
1259 
1260  info = tmp_info;
1261 
1262  if (calc_cond)
1263  {
1264  char norm = '1';
1265  uplo = 'U';
1266  dia = 'N';
1267 
1268  Array<float> z (dim_vector (3 * nc, 1));
1269  float *pz = z.fortran_vec ();
1270  Array<F77_INT> iz (dim_vector (nc, 1));
1271  F77_INT *piz = iz.fortran_vec ();
1272 
1273  F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
1274  F77_CONST_CHAR_ARG2 (&uplo, 1),
1275  F77_CONST_CHAR_ARG2 (&dia, 1),
1276  nr, tmp_data, nr, rcon,
1277  pz, piz, tmp_info
1278  F77_CHAR_ARG_LEN (1)
1279  F77_CHAR_ARG_LEN (1)
1280  F77_CHAR_ARG_LEN (1)));
1281 
1282  info = tmp_info;
1283 
1284  if (info != 0)
1285  info = -2;
1286 
1287  volatile float rcond_plus_one = rcon + 1.0;
1288 
1289  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
1290  {
1291  info = -2;
1292 
1293  if (sing_handler)
1294  sing_handler (rcon);
1295  else
1297  }
1298  }
1299 
1300  }
1301  }
1302  else
1303  (*current_liboctave_error_handler) ("incorrect matrix type");
1304  }
1305 
1306  return retval;
1307 }
1308 
1310 FloatMatrix::ltsolve (MatrixType& mattype, const FloatMatrix& b,
1311  octave_idx_type& info,
1312  float& rcon, solve_singularity_handler sing_handler,
1313  bool calc_cond, blas_trans_type transt) const
1314 {
1315  FloatMatrix retval;
1316 
1317  F77_INT nr = octave::to_f77_int (rows ());
1318  F77_INT nc = octave::to_f77_int (cols ());
1319 
1320  F77_INT b_nr = octave::to_f77_int (b.rows ());
1321  F77_INT b_nc = octave::to_f77_int (b.cols ());
1322 
1323  if (nr != b_nr)
1324  (*current_liboctave_error_handler)
1325  ("matrix dimension mismatch solution of linear equations");
1326 
1327  if (nr == 0 || nc == 0 || b_nc == 0)
1328  retval = FloatMatrix (nc, b_nc, 0.0);
1329  else
1330  {
1331  volatile int typ = mattype.type ();
1332 
1333  if (typ == MatrixType::Permuted_Lower || typ == MatrixType::Lower)
1334  {
1335  rcon = 1.0;
1336  info = 0;
1337 
1338  if (typ == MatrixType::Permuted_Lower)
1339  (*current_liboctave_error_handler)
1340  ("permuted triangular matrix not implemented");
1341  else
1342  {
1343  const float *tmp_data = data ();
1344 
1345  retval = b;
1346  float *result = retval.fortran_vec ();
1347 
1348  char uplo = 'L';
1349  char trans = get_blas_char (transt);
1350  char dia = 'N';
1351 
1352  F77_INT tmp_info = 0;
1353 
1354  F77_XFCN (strtrs, STRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
1355  F77_CONST_CHAR_ARG2 (&trans, 1),
1356  F77_CONST_CHAR_ARG2 (&dia, 1),
1357  nr, b_nc, tmp_data, nr,
1358  result, nr, tmp_info
1359  F77_CHAR_ARG_LEN (1)
1360  F77_CHAR_ARG_LEN (1)
1361  F77_CHAR_ARG_LEN (1)));
1362 
1363  info = tmp_info;
1364 
1365  if (calc_cond)
1366  {
1367  char norm = '1';
1368  uplo = 'L';
1369  dia = 'N';
1370 
1371  Array<float> z (dim_vector (3 * nc, 1));
1372  float *pz = z.fortran_vec ();
1373  Array<F77_INT> iz (dim_vector (nc, 1));
1374  F77_INT *piz = iz.fortran_vec ();
1375 
1376  F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
1377  F77_CONST_CHAR_ARG2 (&uplo, 1),
1378  F77_CONST_CHAR_ARG2 (&dia, 1),
1379  nr, tmp_data, nr, rcon,
1380  pz, piz, tmp_info
1381  F77_CHAR_ARG_LEN (1)
1382  F77_CHAR_ARG_LEN (1)
1383  F77_CHAR_ARG_LEN (1)));
1384 
1385  info = tmp_info;
1386 
1387  if (info != 0)
1388  info = -2;
1389 
1390  volatile float rcond_plus_one = rcon + 1.0;
1391 
1392  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
1393  {
1394  info = -2;
1395 
1396  if (sing_handler)
1397  sing_handler (rcon);
1398  else
1400  }
1401  }
1402  }
1403  }
1404  else
1405  (*current_liboctave_error_handler) ("incorrect matrix type");
1406  }
1407 
1408  return retval;
1409 }
1410 
1412 FloatMatrix::fsolve (MatrixType& mattype, const FloatMatrix& b,
1413  octave_idx_type& info,
1414  float& rcon, solve_singularity_handler sing_handler,
1415  bool calc_cond) const
1416 {
1417  FloatMatrix retval;
1418 
1419  F77_INT nr = octave::to_f77_int (rows ());
1420  F77_INT nc = octave::to_f77_int (cols ());
1421 
1422  F77_INT b_nr = octave::to_f77_int (b.rows ());
1423  F77_INT b_nc = octave::to_f77_int (b.cols ());
1424 
1425  if (nr != nc || nr != b_nr)
1426  (*current_liboctave_error_handler)
1427  ("matrix dimension mismatch solution of linear equations");
1428 
1429  if (nr == 0 || b_nc == 0)
1430  retval = FloatMatrix (nc, b_nc, 0.0);
1431  else
1432  {
1433  volatile int typ = mattype.type ();
1434 
1435  // Calculate the norm of the matrix for later use when determining rcon.
1436  float anorm = -1.0;
1437 
1438  if (typ == MatrixType::Hermitian)
1439  {
1440  info = 0;
1441  char job = 'L';
1442 
1443  FloatMatrix atmp = *this;
1444  float *tmp_data = atmp.fortran_vec ();
1445 
1446  // The norm of the matrix for later use when determining rcon.
1447  if (calc_cond)
1448  anorm = norm1 (atmp);
1449 
1450  F77_INT tmp_info = 0;
1451 
1452  F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
1453  tmp_data, nr, tmp_info
1454  F77_CHAR_ARG_LEN (1)));
1455 
1456  info = tmp_info;
1457 
1458  // Throw away extra info LAPACK gives so as to not change output.
1459  rcon = 0.0;
1460  if (info != 0)
1461  {
1462  info = -2;
1463 
1464  mattype.mark_as_unsymmetric ();
1465  typ = MatrixType::Full;
1466  }
1467  else
1468  {
1469  if (calc_cond)
1470  {
1471  Array<float> z (dim_vector (3 * nc, 1));
1472  float *pz = z.fortran_vec ();
1473  Array<F77_INT> iz (dim_vector (nc, 1));
1474  F77_INT *piz = iz.fortran_vec ();
1475 
1476  F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
1477  nr, tmp_data, nr, anorm,
1478  rcon, pz, piz, tmp_info
1479  F77_CHAR_ARG_LEN (1)));
1480 
1481  info = tmp_info;
1482 
1483  if (info != 0)
1484  info = -2;
1485 
1486  volatile float rcond_plus_one = rcon + 1.0;
1487 
1488  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
1489  {
1490  info = -2;
1491 
1492  if (sing_handler)
1493  sing_handler (rcon);
1494  else
1496  }
1497  }
1498 
1499  if (info == 0)
1500  {
1501  retval = b;
1502  float *result = retval.fortran_vec ();
1503 
1504  F77_XFCN (spotrs, SPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),
1505  nr, b_nc, tmp_data, nr,
1506  result, b_nr, tmp_info
1507  F77_CHAR_ARG_LEN (1)));
1508 
1509  info = tmp_info;
1510  }
1511  else
1512  {
1513  mattype.mark_as_unsymmetric ();
1514  typ = MatrixType::Full;
1515  }
1516  }
1517  }
1518 
1519  if (typ == MatrixType::Full)
1520  {
1521  info = 0;
1522 
1523  Array<F77_INT> ipvt (dim_vector (nr, 1));
1524  F77_INT *pipvt = ipvt.fortran_vec ();
1525 
1526  FloatMatrix atmp = *this;
1527  float *tmp_data = atmp.fortran_vec ();
1528 
1529  if (calc_cond && anorm < 0.0)
1530  anorm = norm1 (atmp);
1531 
1532  Array<float> z (dim_vector (4 * nc, 1));
1533  float *pz = z.fortran_vec ();
1534  Array<F77_INT> iz (dim_vector (nc, 1));
1535  F77_INT *piz = iz.fortran_vec ();
1536 
1537  F77_INT tmp_info = 0;
1538 
1539  F77_XFCN (sgetrf, SGETRF, (nr, nr, tmp_data, nr, pipvt, tmp_info));
1540 
1541  info = tmp_info;
1542 
1543  // Throw away extra info LAPACK gives so as to not change output.
1544  rcon = 0.0;
1545  if (info != 0)
1546  {
1547  info = -2;
1548 
1549  if (sing_handler)
1550  sing_handler (rcon);
1551  else
1553 
1554  mattype.mark_as_rectangular ();
1555  }
1556  else
1557  {
1558  if (calc_cond)
1559  {
1560  // Calculate the condition number for non-singular matrix.
1561  char job = '1';
1562  F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
1563  nc, tmp_data, nr, anorm,
1564  rcon, pz, piz, tmp_info
1565  F77_CHAR_ARG_LEN (1)));
1566 
1567  info = tmp_info;
1568 
1569  if (info != 0)
1570  info = -2;
1571 
1572  volatile float rcond_plus_one = rcon + 1.0;
1573 
1574  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
1575  {
1576  if (sing_handler)
1577  sing_handler (rcon);
1578  else
1580  }
1581  }
1582 
1583  if (info == 0)
1584  {
1585  retval = b;
1586  float *result = retval.fortran_vec ();
1587 
1588  char job = 'N';
1589  F77_XFCN (sgetrs, SGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),
1590  nr, b_nc, tmp_data, nr,
1591  pipvt, result, b_nr, tmp_info
1592  F77_CHAR_ARG_LEN (1)));
1593 
1594  info = tmp_info;
1595  }
1596  else
1597  mattype.mark_as_rectangular ();
1598  }
1599  }
1600  else if (typ != MatrixType::Hermitian)
1601  (*current_liboctave_error_handler) ("incorrect matrix type");
1602  }
1603 
1604  return retval;
1605 }
1606 
1608 FloatMatrix::solve (MatrixType& mattype, const FloatMatrix& b) const
1609 {
1610  octave_idx_type info;
1611  float rcon;
1612  return solve (mattype, b, info, rcon, nullptr);
1613 }
1614 
1617  octave_idx_type& info) const
1618 {
1619  float rcon;
1620  return solve (mattype, b, info, rcon, nullptr);
1621 }
1622 
1625  octave_idx_type& info, float& rcon) const
1626 {
1627  return solve (mattype, b, info, rcon, nullptr);
1628 }
1629 
1632  octave_idx_type& info,
1633  float& rcon, solve_singularity_handler sing_handler,
1634  bool singular_fallback, blas_trans_type transt) const
1635 {
1636  FloatMatrix retval;
1637  int typ = mattype.type ();
1638 
1639  if (typ == MatrixType::Unknown)
1640  typ = mattype.type (*this);
1641 
1642  // Only calculate the condition number for LU/Cholesky
1643  if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
1644  retval = utsolve (mattype, b, info, rcon, sing_handler, true, transt);
1645  else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
1646  retval = ltsolve (mattype, b, info, rcon, sing_handler, true, transt);
1647  else if (transt == blas_trans || transt == blas_conj_trans)
1648  return transpose ().solve (mattype, b, info, rcon, sing_handler,
1649  singular_fallback);
1650  else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
1651  retval = fsolve (mattype, b, info, rcon, sing_handler, true);
1652  else if (typ != MatrixType::Rectangular)
1653  (*current_liboctave_error_handler) ("unknown matrix type");
1654 
1655  // Rectangular or one of the above solvers flags a singular matrix
1656  if (singular_fallback && mattype.type () == MatrixType::Rectangular)
1657  {
1658  octave_idx_type rank;
1659  retval = lssolve (b, info, rank, rcon);
1660  }
1661 
1662  return retval;
1663 }
1664 
1667 {
1668  octave_idx_type info;
1669  float rcon;
1670  return solve (mattype, b, info, rcon, nullptr);
1671 }
1672 
1675  octave_idx_type& info) const
1676 {
1677  float rcon;
1678  return solve (mattype, b, info, rcon, nullptr);
1679 }
1680 
1683  octave_idx_type& info,
1684  float& rcon) const
1685 {
1686  return solve (mattype, b, info, rcon, nullptr);
1687 }
1688 
1689 static FloatMatrix
1690 stack_complex_matrix (const FloatComplexMatrix& cm)
1691 {
1692  octave_idx_type m = cm.rows ();
1693  octave_idx_type n = cm.cols ();
1694  octave_idx_type nel = m*n;
1695  FloatMatrix retval (m, 2*n);
1696  const FloatComplex *cmd = cm.data ();
1697  float *rd = retval.fortran_vec ();
1698  for (octave_idx_type i = 0; i < nel; i++)
1699  {
1700  rd[i] = std::real (cmd[i]);
1701  rd[nel+i] = std::imag (cmd[i]);
1702  }
1703  return retval;
1704 }
1705 
1706 static FloatComplexMatrix
1707 unstack_complex_matrix (const FloatMatrix& sm)
1708 {
1709  octave_idx_type m = sm.rows ();
1710  octave_idx_type n = sm.cols () / 2;
1711  octave_idx_type nel = m*n;
1712  FloatComplexMatrix retval (m, n);
1713  const float *smd = sm.data ();
1714  FloatComplex *rd = retval.fortran_vec ();
1715  for (octave_idx_type i = 0; i < nel; i++)
1716  rd[i] = FloatComplex (smd[i], smd[nel+i]);
1717  return retval;
1718 }
1719 
1722  octave_idx_type& info,
1723  float& rcon, solve_singularity_handler sing_handler,
1724  bool singular_fallback, blas_trans_type transt) const
1725 {
1726  FloatMatrix tmp = stack_complex_matrix (b);
1727  tmp = solve (mattype, tmp, info, rcon, sing_handler, singular_fallback,
1728  transt);
1729  return unstack_complex_matrix (tmp);
1730 }
1731 
1734 {
1735  octave_idx_type info;
1736  float rcon;
1737  return solve (mattype, b, info, rcon);
1738 }
1739 
1742  octave_idx_type& info) const
1743 {
1744  float rcon;
1745  return solve (mattype, b, info, rcon);
1746 }
1747 
1750  octave_idx_type& info,
1751  float& rcon) const
1752 {
1753  return solve (mattype, b, info, rcon, nullptr);
1754 }
1755 
1758  octave_idx_type& info,
1759  float& rcon, solve_singularity_handler sing_handler,
1760  blas_trans_type transt) const
1761 {
1762  FloatMatrix tmp (b);
1763  tmp = solve (mattype, tmp, info, rcon, sing_handler, true, transt);
1764  return tmp.column (static_cast<octave_idx_type> (0));
1765 }
1766 
1769  const FloatComplexColumnVector& b) const
1770 {
1771  FloatComplexMatrix tmp (*this);
1772  return tmp.solve (mattype, b);
1773 }
1774 
1777  octave_idx_type& info) const
1778 {
1779  FloatComplexMatrix tmp (*this);
1780  return tmp.solve (mattype, b, info);
1781 }
1782 
1785  octave_idx_type& info, float& rcon) const
1786 {
1787  FloatComplexMatrix tmp (*this);
1788  return tmp.solve (mattype, b, info, rcon);
1789 }
1790 
1793  octave_idx_type& info, float& rcon,
1794  solve_singularity_handler sing_handler,
1795  blas_trans_type transt) const
1796 {
1797  FloatComplexMatrix tmp (*this);
1798  return tmp.solve (mattype, b, info, rcon, sing_handler, transt);
1799 }
1800 
1803 {
1804  octave_idx_type info;
1805  float rcon;
1806  return solve (b, info, rcon, nullptr);
1807 }
1808 
1811 {
1812  float rcon;
1813  return solve (b, info, rcon, nullptr);
1814 }
1815 
1818  float& rcon) const
1819 {
1820  return solve (b, info, rcon, nullptr);
1821 }
1822 
1825  float& rcon, solve_singularity_handler sing_handler,
1826  blas_trans_type transt) const
1827 {
1828  MatrixType mattype (*this);
1829  return solve (mattype, b, info, rcon, sing_handler, true, transt);
1830 }
1831 
1834 {
1835  FloatComplexMatrix tmp (*this);
1836  return tmp.solve (b);
1837 }
1838 
1841 {
1842  FloatComplexMatrix tmp (*this);
1843  return tmp.solve (b, info);
1844 }
1845 
1848  float& rcon) const
1849 {
1850  FloatComplexMatrix tmp (*this);
1851  return tmp.solve (b, info, rcon);
1852 }
1853 
1856  float& rcon,
1857  solve_singularity_handler sing_handler,
1858  blas_trans_type transt) const
1859 {
1860  FloatComplexMatrix tmp (*this);
1861  return tmp.solve (b, info, rcon, sing_handler, transt);
1862 }
1863 
1866 {
1867  octave_idx_type info; float rcon;
1868  return solve (b, info, rcon);
1869 }
1870 
1873 {
1874  float rcon;
1875  return solve (b, info, rcon);
1876 }
1877 
1880  float& rcon) const
1881 {
1882  return solve (b, info, rcon, nullptr);
1883 }
1884 
1887  float& rcon, solve_singularity_handler sing_handler,
1888  blas_trans_type transt) const
1889 {
1890  MatrixType mattype (*this);
1891  return solve (mattype, b, info, rcon, sing_handler, transt);
1892 }
1893 
1896 {
1897  FloatComplexMatrix tmp (*this);
1898  return tmp.solve (b);
1899 }
1900 
1903  octave_idx_type& info) const
1904 {
1905  FloatComplexMatrix tmp (*this);
1906  return tmp.solve (b, info);
1907 }
1908 
1911  float& rcon) const
1912 {
1913  FloatComplexMatrix tmp (*this);
1914  return tmp.solve (b, info, rcon);
1915 }
1916 
1919  float& rcon, solve_singularity_handler sing_handler,
1920  blas_trans_type transt) const
1921 {
1922  FloatComplexMatrix tmp (*this);
1923  return tmp.solve (b, info, rcon, sing_handler, transt);
1924 }
1925 
1928 {
1929  octave_idx_type info;
1930  octave_idx_type rank;
1931  float rcon;
1932  return lssolve (b, info, rank, rcon);
1933 }
1934 
1937 {
1938  octave_idx_type rank;
1939  float rcon;
1940  return lssolve (b, info, rank, rcon);
1941 }
1942 
1945  octave_idx_type& rank) const
1946 {
1947  float rcon;
1948  return lssolve (b, info, rank, rcon);
1949 }
1950 
1951 
1954  octave_idx_type& rank, float& rcon) const
1955 {
1956  FloatMatrix retval;
1957 
1958  F77_INT m = octave::to_f77_int (rows ());
1959  F77_INT n = octave::to_f77_int (cols ());
1960 
1961  F77_INT b_nr = octave::to_f77_int (b.rows ());
1962  F77_INT b_nc = octave::to_f77_int (b.cols ());
1963  F77_INT nrhs = b_nc; // alias for code readability
1964 
1965  if (m != b_nr)
1966  (*current_liboctave_error_handler)
1967  ("matrix dimension mismatch solution of linear equations");
1968 
1969  if (m == 0 || n == 0 || b_nc == 0)
1970  retval = FloatMatrix (n, b_nc, 0.0);
1971  else
1972  {
1973  volatile F77_INT minmn = (m < n ? m : n);
1974  F77_INT maxmn = (m > n ? m : n);
1975  rcon = -1.0;
1976  if (m != n)
1977  {
1978  retval = FloatMatrix (maxmn, nrhs, 0.0);
1979 
1980  for (F77_INT j = 0; j < nrhs; j++)
1981  for (F77_INT i = 0; i < m; i++)
1982  retval.elem (i, j) = b.elem (i, j);
1983  }
1984  else
1985  retval = b;
1986 
1987  FloatMatrix atmp = *this;
1988  float *tmp_data = atmp.fortran_vec ();
1989 
1990  float *pretval = retval.fortran_vec ();
1991  Array<float> s (dim_vector (minmn, 1));
1992  float *ps = s.fortran_vec ();
1993 
1994  // Ask DGELSD what the dimension of WORK should be.
1995  F77_INT lwork = -1;
1996 
1997  Array<float> work (dim_vector (1, 1));
1998 
1999  F77_INT smlsiz;
2000  F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("SGELSD", 6),
2001  F77_CONST_CHAR_ARG2 (" ", 1),
2002  0, 0, 0, 0, smlsiz
2003  F77_CHAR_ARG_LEN (6)
2004  F77_CHAR_ARG_LEN (1));
2005 
2006  F77_INT mnthr;
2007  F77_FUNC (xilaenv, XILAENV) (6, F77_CONST_CHAR_ARG2 ("SGELSD", 6),
2008  F77_CONST_CHAR_ARG2 (" ", 1),
2009  m, n, nrhs, -1, mnthr
2010  F77_CHAR_ARG_LEN (6)
2011  F77_CHAR_ARG_LEN (1));
2012 
2013  // We compute the size of iwork because DGELSD in older versions
2014  // of LAPACK does not return it on a query call.
2015  float dminmn = static_cast<float> (minmn);
2016  float dsmlsizp1 = static_cast<float> (smlsiz+1);
2017  float tmp = octave::math::log2 (dminmn / dsmlsizp1);
2018 
2019  F77_INT nlvl = static_cast<F77_INT> (tmp) + 1;
2020  if (nlvl < 0)
2021  nlvl = 0;
2022 
2023  F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;
2024  if (liwork < 1)
2025  liwork = 1;
2026  Array<F77_INT> iwork (dim_vector (liwork, 1));
2027  F77_INT *piwork = iwork.fortran_vec ();
2028 
2029  F77_INT tmp_info = 0;
2030  F77_INT tmp_rank = 0;
2031 
2032  F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
2033  ps, rcon, tmp_rank, work.fortran_vec (),
2034  lwork, piwork, tmp_info));
2035 
2036  info = tmp_info;
2037  rank = tmp_rank;
2038 
2039  // The workspace query is broken in at least LAPACK 3.0.0
2040  // through 3.1.1 when n >= mnthr. The obtuse formula below
2041  // should provide sufficient workspace for DGELSD to operate
2042  // efficiently.
2043  if (n > m && n >= mnthr)
2044  {
2045  const F77_INT wlalsd
2046  = 9*m + 2*m*smlsiz + 8*m*nlvl + m*nrhs + (smlsiz+1)*(smlsiz+1);
2047 
2048  F77_INT addend = m;
2049 
2050  if (2*m-4 > addend)
2051  addend = 2*m-4;
2052 
2053  if (nrhs > addend)
2054  addend = nrhs;
2055 
2056  if (n-3*m > addend)
2057  addend = n-3*m;
2058 
2059  if (wlalsd > addend)
2060  addend = wlalsd;
2061 
2062  const F77_INT lworkaround = 4*m + m*m + addend;
2063 
2064  if (work(0) < lworkaround)
2065  work(0) = lworkaround;
2066  }
2067  else if (m >= n)
2068  {
2069  F77_INT lworkaround
2070  = 12*n + 2*n*smlsiz + 8*n*nlvl + n*nrhs + (smlsiz+1)*(smlsiz+1);
2071 
2072  if (work(0) < lworkaround)
2073  work(0) = lworkaround;
2074  }
2075 
2076  lwork = static_cast<F77_INT> (work(0));
2077  work.resize (dim_vector (lwork, 1));
2078 
2079  float anorm = norm1 (*this);
2080 
2081  if (octave::math::isinf (anorm))
2082  {
2083  rcon = 0.0;
2084  retval = FloatMatrix (n, b_nc, 0.0);
2085  }
2086  else if (octave::math::isnan (anorm))
2087  {
2089  retval = FloatMatrix (n, b_nc,
2091  }
2092  else
2093  {
2094  F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval,
2095  maxmn, ps, rcon, tmp_rank,
2096  work.fortran_vec (), lwork,
2097  piwork, tmp_info));
2098 
2099  info = tmp_info;
2100  rank = tmp_rank;
2101 
2102  if (s.elem (0) == 0.0)
2103  rcon = 0.0;
2104  else
2105  rcon = s.elem (minmn - 1) / s.elem (0);
2106 
2107  retval.resize (n, nrhs);
2108  }
2109  }
2110 
2111  return retval;
2112 }
2113 
2116 {
2117  FloatComplexMatrix tmp (*this);
2118  octave_idx_type info;
2119  octave_idx_type rank;
2120  float rcon;
2121  return tmp.lssolve (b, info, rank, rcon);
2122 }
2123 
2126 {
2127  FloatComplexMatrix tmp (*this);
2128  octave_idx_type rank;
2129  float rcon;
2130  return tmp.lssolve (b, info, rank, rcon);
2131 }
2132 
2135  octave_idx_type& rank) const
2136 {
2137  FloatComplexMatrix tmp (*this);
2138  float rcon;
2139  return tmp.lssolve (b, info, rank, rcon);
2140 }
2141 
2144  octave_idx_type& rank, float& rcon) const
2145 {
2146  FloatComplexMatrix tmp (*this);
2147  return tmp.lssolve (b, info, rank, rcon);
2148 }
2149 
2152 {
2153  octave_idx_type info;
2154  octave_idx_type rank;
2155  float rcon;
2156  return lssolve (b, info, rank, rcon);
2157 }
2158 
2161 {
2162  octave_idx_type rank;
2163  float rcon;
2164  return lssolve (b, info, rank, rcon);
2165 }
2166 
2169  octave_idx_type& rank) const
2170 {
2171  float rcon;
2172  return lssolve (b, info, rank, rcon);
2173 }
2174 
2177  octave_idx_type& rank, float& rcon) const
2178 {
2179  FloatColumnVector retval;
2180 
2181  F77_INT nrhs = 1;
2182 
2183  F77_INT m = octave::to_f77_int (rows ());
2184  F77_INT n = octave::to_f77_int (cols ());
2185 
2186  if (m != b.numel ())
2187  (*current_liboctave_error_handler)
2188  ("matrix dimension mismatch solution of linear equations");
2189 
2190  if (m == 0 || n == 0)
2191  retval = FloatColumnVector (n, 0.0);
2192  else
2193  {
2194  volatile F77_INT minmn = (m < n ? m : n);
2195  F77_INT maxmn = (m > n ? m : n);
2196  rcon = -1.0;
2197 
2198  if (m != n)
2199  {
2200  retval = FloatColumnVector (maxmn, 0.0);
2201 
2202  for (F77_INT i = 0; i < m; i++)
2203  retval.elem (i) = b.elem (i);
2204  }
2205  else
2206  retval = b;
2207 
2208  FloatMatrix atmp = *this;
2209  float *tmp_data = atmp.fortran_vec ();
2210 
2211  float *pretval = retval.fortran_vec ();
2212  Array<float> s (dim_vector (minmn, 1));
2213  float *ps = s.fortran_vec ();
2214 
2215  // Ask DGELSD what the dimension of WORK should be.
2216  F77_INT lwork = -1;
2217 
2218  Array<float> work (dim_vector (1, 1));
2219 
2220  F77_INT smlsiz;
2221  F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("SGELSD", 6),
2222  F77_CONST_CHAR_ARG2 (" ", 1),
2223  0, 0, 0, 0, smlsiz
2224  F77_CHAR_ARG_LEN (6)
2225  F77_CHAR_ARG_LEN (1));
2226 
2227  // We compute the size of iwork because DGELSD in older versions
2228  // of LAPACK does not return it on a query call.
2229  float dminmn = static_cast<float> (minmn);
2230  float dsmlsizp1 = static_cast<float> (smlsiz+1);
2231  float tmp = octave::math::log2 (dminmn / dsmlsizp1);
2232 
2233  F77_INT nlvl = static_cast<F77_INT> (tmp) + 1;
2234  if (nlvl < 0)
2235  nlvl = 0;
2236 
2237  F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;
2238  if (liwork < 1)
2239  liwork = 1;
2240  Array<F77_INT> iwork (dim_vector (liwork, 1));
2241  F77_INT *piwork = iwork.fortran_vec ();
2242 
2243  F77_INT tmp_info = 0;
2244  F77_INT tmp_rank = 0;
2245 
2246  F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
2247  ps, rcon, tmp_rank, work.fortran_vec (),
2248  lwork, piwork, tmp_info));
2249 
2250  info = tmp_info;
2251  rank = tmp_rank;
2252 
2253  lwork = static_cast<F77_INT> (work(0));
2254  work.resize (dim_vector (lwork, 1));
2255 
2256  F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval,
2257  maxmn, ps, rcon, tmp_rank,
2258  work.fortran_vec (), lwork,
2259  piwork, tmp_info));
2260 
2261  info = tmp_info;
2262  rank = tmp_rank;
2263 
2264  if (rank < minmn)
2265  {
2266  if (s.elem (0) == 0.0)
2267  rcon = 0.0;
2268  else
2269  rcon = s.elem (minmn - 1) / s.elem (0);
2270  }
2271 
2272  retval.resize (n);
2273  }
2274 
2275  return retval;
2276 }
2277 
2280 {
2281  FloatComplexMatrix tmp (*this);
2282  octave_idx_type info;
2283  octave_idx_type rank;
2284  float rcon;
2285  return tmp.lssolve (b, info, rank, rcon);
2286 }
2287 
2290  octave_idx_type& info) const
2291 {
2292  FloatComplexMatrix tmp (*this);
2293  octave_idx_type rank;
2294  float rcon;
2295  return tmp.lssolve (b, info, rank, rcon);
2296 }
2297 
2300  octave_idx_type& rank) const
2301 {
2302  FloatComplexMatrix tmp (*this);
2303  float rcon;
2304  return tmp.lssolve (b, info, rank, rcon);
2305 }
2306 
2309  octave_idx_type& rank, float& rcon) const
2310 {
2311  FloatComplexMatrix tmp (*this);
2312  return tmp.lssolve (b, info, rank, rcon);
2313 }
2314 
2315 FloatMatrix&
2317 {
2318  octave_idx_type nr = rows ();
2319  octave_idx_type nc = cols ();
2320 
2321  octave_idx_type a_nr = a.rows ();
2322  octave_idx_type a_nc = a.cols ();
2323 
2324  if (nr != a_nr || nc != a_nc)
2325  octave::err_nonconformant ("operator +=", nr, nc, a_nr, a_nc);
2326 
2327  for (octave_idx_type i = 0; i < a.length (); i++)
2328  elem (i, i) += a.elem (i, i);
2329 
2330  return *this;
2331 }
2332 
2333 FloatMatrix&
2335 {
2336  octave_idx_type nr = rows ();
2337  octave_idx_type nc = cols ();
2338 
2339  octave_idx_type a_nr = a.rows ();
2340  octave_idx_type a_nc = a.cols ();
2341 
2342  if (nr != a_nr || nc != a_nc)
2343  octave::err_nonconformant ("operator -=", nr, nc, a_nr, a_nc);
2344 
2345  for (octave_idx_type i = 0; i < a.length (); i++)
2346  elem (i, i) -= a.elem (i, i);
2347 
2348  return *this;
2349 }
2350 
2351 // column vector by row vector -> matrix operations
2352 
2355 {
2356  FloatMatrix retval;
2357 
2358  F77_INT len = octave::to_f77_int (v.numel ());
2359 
2360  if (len != 0)
2361  {
2362  F77_INT a_len = octave::to_f77_int (a.numel ());
2363 
2364  retval = FloatMatrix (len, a_len);
2365  float *c = retval.fortran_vec ();
2366 
2367  F77_XFCN (sgemm, SGEMM, (F77_CONST_CHAR_ARG2 ("N", 1),
2368  F77_CONST_CHAR_ARG2 ("N", 1),
2369  len, a_len, 1, 1.0, v.data (), len,
2370  a.data (), 1, 0.0, c, len
2371  F77_CHAR_ARG_LEN (1)
2372  F77_CHAR_ARG_LEN (1)));
2373  }
2374 
2375  return retval;
2376 }
2377 
2378 // FIXME: Do these really belong here? Maybe they should be in a base class?
2379 
2381 FloatMatrix::cumprod (int dim) const
2382 {
2383  return FloatNDArray::cumprod (dim);
2384 }
2385 
2387 FloatMatrix::cumsum (int dim) const
2388 {
2389  return FloatNDArray::cumsum (dim);
2390 }
2391 
2393 FloatMatrix::prod (int dim) const
2394 {
2395  return FloatNDArray::prod (dim);
2396 }
2397 
2399 FloatMatrix::sum (int dim) const
2400 {
2401  return FloatNDArray::sum (dim);
2402 }
2403 
2405 FloatMatrix::sumsq (int dim) const
2406 {
2407  return FloatNDArray::sumsq (dim);
2408 }
2409 
2412 {
2413  return FloatNDArray::abs ();
2414 }
2415 
2418 {
2419  return FloatNDArray::diag (k);
2420 }
2421 
2424 {
2425  FloatDiagMatrix retval;
2426 
2427  octave_idx_type nr = rows ();
2428  octave_idx_type nc = cols ();
2429 
2430  if (nr == 1 || nc == 1)
2431  retval = FloatDiagMatrix (*this, m, n);
2432  else
2433  (*current_liboctave_error_handler) ("diag: expecting vector argument");
2434 
2435  return retval;
2436 }
2437 
2440 {
2441  Array<octave_idx_type> dummy_idx;
2442  return row_min (dummy_idx);
2443 }
2444 
2447 {
2448  FloatColumnVector result;
2449 
2450  octave_idx_type nr = rows ();
2451  octave_idx_type nc = cols ();
2452 
2453  if (nr > 0 && nc > 0)
2454  {
2455  result.resize (nr);
2456  idx_arg.resize (dim_vector (nr, 1));
2457 
2458  for (octave_idx_type i = 0; i < nr; i++)
2459  {
2460  octave_idx_type idx_j;
2461 
2462  float tmp_min = octave::numeric_limits<float>::NaN ();
2463 
2464  for (idx_j = 0; idx_j < nc; idx_j++)
2465  {
2466  tmp_min = elem (i, idx_j);
2467 
2468  if (! octave::math::isnan (tmp_min))
2469  break;
2470  }
2471 
2472  for (octave_idx_type j = idx_j+1; j < nc; j++)
2473  {
2474  float tmp = elem (i, j);
2475 
2476  if (octave::math::isnan (tmp))
2477  continue;
2478  else if (tmp < tmp_min)
2479  {
2480  idx_j = j;
2481  tmp_min = tmp;
2482  }
2483  }
2484 
2485  result.elem (i) = tmp_min;
2486  idx_arg.elem (i) = (octave::math::isnan (tmp_min) ? 0 : idx_j);
2487  }
2488  }
2489 
2490  return result;
2491 }
2492 
2495 {
2496  Array<octave_idx_type> dummy_idx;
2497  return row_max (dummy_idx);
2498 }
2499 
2502 {
2503  FloatColumnVector result;
2504 
2505  octave_idx_type nr = rows ();
2506  octave_idx_type nc = cols ();
2507 
2508  if (nr > 0 && nc > 0)
2509  {
2510  result.resize (nr);
2511  idx_arg.resize (dim_vector (nr, 1));
2512 
2513  for (octave_idx_type i = 0; i < nr; i++)
2514  {
2515  octave_idx_type idx_j;
2516 
2517  float tmp_max = octave::numeric_limits<float>::NaN ();
2518 
2519  for (idx_j = 0; idx_j < nc; idx_j++)
2520  {
2521  tmp_max = elem (i, idx_j);
2522 
2523  if (! octave::math::isnan (tmp_max))
2524  break;
2525  }
2526 
2527  for (octave_idx_type j = idx_j+1; j < nc; j++)
2528  {
2529  float tmp = elem (i, j);
2530 
2531  if (octave::math::isnan (tmp))
2532  continue;
2533  else if (tmp > tmp_max)
2534  {
2535  idx_j = j;
2536  tmp_max = tmp;
2537  }
2538  }
2539 
2540  result.elem (i) = tmp_max;
2541  idx_arg.elem (i) = (octave::math::isnan (tmp_max) ? 0 : idx_j);
2542  }
2543  }
2544 
2545  return result;
2546 }
2547 
2550 {
2551  Array<octave_idx_type> dummy_idx;
2552  return column_min (dummy_idx);
2553 }
2554 
2557 {
2558  FloatRowVector result;
2559 
2560  octave_idx_type nr = rows ();
2561  octave_idx_type nc = cols ();
2562 
2563  if (nr > 0 && nc > 0)
2564  {
2565  result.resize (nc);
2566  idx_arg.resize (dim_vector (1, nc));
2567 
2568  for (octave_idx_type j = 0; j < nc; j++)
2569  {
2570  octave_idx_type idx_i;
2571 
2572  float tmp_min = octave::numeric_limits<float>::NaN ();
2573 
2574  for (idx_i = 0; idx_i < nr; idx_i++)
2575  {
2576  tmp_min = elem (idx_i, j);
2577 
2578  if (! octave::math::isnan (tmp_min))
2579  break;
2580  }
2581 
2582  for (octave_idx_type i = idx_i+1; i < nr; i++)
2583  {
2584  float tmp = elem (i, j);
2585 
2586  if (octave::math::isnan (tmp))
2587  continue;
2588  else if (tmp < tmp_min)
2589  {
2590  idx_i = i;
2591  tmp_min = tmp;
2592  }
2593  }
2594 
2595  result.elem (j) = tmp_min;
2596  idx_arg.elem (j) = (octave::math::isnan (tmp_min) ? 0 : idx_i);
2597  }
2598  }
2599 
2600  return result;
2601 }
2602 
2605 {
2606  Array<octave_idx_type> dummy_idx;
2607  return column_max (dummy_idx);
2608 }
2609 
2612 {
2613  FloatRowVector result;
2614 
2615  octave_idx_type nr = rows ();
2616  octave_idx_type nc = cols ();
2617 
2618  if (nr > 0 && nc > 0)
2619  {
2620  result.resize (nc);
2621  idx_arg.resize (dim_vector (1, nc));
2622 
2623  for (octave_idx_type j = 0; j < nc; j++)
2624  {
2625  octave_idx_type idx_i;
2626 
2627  float tmp_max = octave::numeric_limits<float>::NaN ();
2628 
2629  for (idx_i = 0; idx_i < nr; idx_i++)
2630  {
2631  tmp_max = elem (idx_i, j);
2632 
2633  if (! octave::math::isnan (tmp_max))
2634  break;
2635  }
2636 
2637  for (octave_idx_type i = idx_i+1; i < nr; i++)
2638  {
2639  float tmp = elem (i, j);
2640 
2641  if (octave::math::isnan (tmp))
2642  continue;
2643  else if (tmp > tmp_max)
2644  {
2645  idx_i = i;
2646  tmp_max = tmp;
2647  }
2648  }
2649 
2650  result.elem (j) = tmp_max;
2651  idx_arg.elem (j) = (octave::math::isnan (tmp_max) ? 0 : idx_i);
2652  }
2653  }
2654 
2655  return result;
2656 }
2657 
2658 std::ostream&
2659 operator << (std::ostream& os, const FloatMatrix& a)
2660 {
2661  for (octave_idx_type i = 0; i < a.rows (); i++)
2662  {
2663  for (octave_idx_type j = 0; j < a.cols (); j++)
2664  {
2665  os << ' ';
2666  octave::write_value<float> (os, a.elem (i, j));
2667  }
2668  os << "\n";
2669  }
2670  return os;
2671 }
2672 
2673 std::istream&
2674 operator >> (std::istream& is, FloatMatrix& a)
2675 {
2676  octave_idx_type nr = a.rows ();
2677  octave_idx_type nc = a.cols ();
2678 
2679  if (nr > 0 && nc > 0)
2680  {
2681  float tmp;
2682  for (octave_idx_type i = 0; i < nr; i++)
2683  for (octave_idx_type j = 0; j < nc; j++)
2684  {
2685  tmp = octave::read_value<float> (is);
2686  if (is)
2687  a.elem (i, j) = tmp;
2688  else
2689  return is;
2690  }
2691  }
2692 
2693  return is;
2694 }
2695 
2697 Givens (float x, float y)
2698 {
2699  float cc, s, temp_r;
2700 
2701  F77_FUNC (slartg, SLARTG) (x, y, cc, s, temp_r);
2702 
2703  FloatMatrix g (2, 2);
2704 
2705  g.elem (0, 0) = cc;
2706  g.elem (1, 1) = cc;
2707  g.elem (0, 1) = s;
2708  g.elem (1, 0) = -s;
2709 
2710  return g;
2711 }
2712 
2714 Sylvester (const FloatMatrix& a, const FloatMatrix& b, const FloatMatrix& c)
2715 {
2716  FloatMatrix retval;
2717 
2718  // FIXME: need to check that a, b, and c are all the same size.
2719 
2720  // Compute Schur decompositions.
2721 
2722  octave::math::schur<FloatMatrix> as (a, "U");
2723  octave::math::schur<FloatMatrix> bs (b, "U");
2724 
2725  // Transform c to new coordinates.
2726 
2727  FloatMatrix ua = as.unitary_schur_matrix ();
2728  FloatMatrix sch_a = as.schur_matrix ();
2729 
2730  FloatMatrix ub = bs.unitary_schur_matrix ();
2731  FloatMatrix sch_b = bs.schur_matrix ();
2732 
2733  FloatMatrix cx = ua.transpose () * c * ub;
2734 
2735  // Solve the sylvester equation, back-transform, and return the
2736  // solution.
2737 
2738  F77_INT a_nr = octave::to_f77_int (a.rows ());
2739  F77_INT b_nr = octave::to_f77_int (b.rows ());
2740 
2741  float scale;
2742  F77_INT info;
2743 
2744  float *pa = sch_a.fortran_vec ();
2745  float *pb = sch_b.fortran_vec ();
2746  float *px = cx.fortran_vec ();
2747 
2748  F77_XFCN (strsyl, STRSYL, (F77_CONST_CHAR_ARG2 ("N", 1),
2749  F77_CONST_CHAR_ARG2 ("N", 1),
2750  1, a_nr, b_nr, pa, a_nr, pb,
2751  b_nr, px, a_nr, scale, info
2752  F77_CHAR_ARG_LEN (1)
2753  F77_CHAR_ARG_LEN (1)));
2754 
2755  // FIXME: check info?
2756 
2757  retval = ua*cx*ub.transpose ();
2758 
2759  return retval;
2760 }
2761 
2762 // matrix by matrix -> matrix operations
2763 
2764 /*
2765 ## Simple Dot Product, Matrix-Vector, and Matrix-Matrix Unit tests
2766 %!assert (single ([1 2 3]) * single ([ 4 ; 5 ; 6]), single (32), 5e-7)
2767 %!assert (single ([1 2 ; 3 4]) * single ([5 ; 6]), single ([17 ; 39]), 5e-7)
2768 %!assert (single ([1 2 ; 3 4]) * single ([5 6 ; 7 8]), single ([19 22; 43 50]), 5e-7)
2769 
2770 ## Test some simple identities
2771 %!shared M, cv, rv
2772 %! M = single (randn (10,10));
2773 %! cv = single (randn (10,1));
2774 %! rv = single (randn (1,10));
2775 %!assert ([M*cv,M*cv], M*[cv,cv], 5e-6)
2776 %!assert ([M'*cv,M'*cv], M'*[cv,cv], 5e-6)
2777 %!assert ([rv*M;rv*M], [rv;rv]*M, 5e-6)
2778 %!assert ([rv*M';rv*M'], [rv;rv]*M', 5e-6)
2779 %!assert (2*rv*cv, [rv,rv]*[cv;cv], 5e-6)
2780 
2781 */
2782 
2783 static char
2784 get_blas_trans_arg (bool trans)
2785 {
2786  return trans ? 'T' : 'N';
2787 }
2788 
2789 // the general GEMM operation
2790 
2792 xgemm (const FloatMatrix& a, const FloatMatrix& b,
2793  blas_trans_type transa, blas_trans_type transb)
2794 {
2795  FloatMatrix retval;
2796 
2797  bool tra = transa != blas_no_trans;
2798  bool trb = transb != blas_no_trans;
2799 
2800  F77_INT a_nr = octave::to_f77_int (tra ? a.cols () : a.rows ());
2801  F77_INT a_nc = octave::to_f77_int (tra ? a.rows () : a.cols ());
2802 
2803  F77_INT b_nr = octave::to_f77_int (trb ? b.cols () : b.rows ());
2804  F77_INT b_nc = octave::to_f77_int (trb ? b.rows () : b.cols ());
2805 
2806  if (a_nc != b_nr)
2807  octave::err_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
2808 
2809  if (a_nr == 0 || a_nc == 0 || b_nc == 0)
2810  retval = FloatMatrix (a_nr, b_nc, 0.0);
2811  else if (a.data () == b.data () && a_nr == b_nc && tra != trb)
2812  {
2813  F77_INT lda = octave::to_f77_int (a.rows ());
2814 
2815  retval = FloatMatrix (a_nr, b_nc);
2816  float *c = retval.fortran_vec ();
2817 
2818  const char ctra = get_blas_trans_arg (tra);
2819  F77_XFCN (ssyrk, SSYRK, (F77_CONST_CHAR_ARG2 ("U", 1),
2820  F77_CONST_CHAR_ARG2 (&ctra, 1),
2821  a_nr, a_nc, 1.0,
2822  a.data (), lda, 0.0, c, a_nr
2823  F77_CHAR_ARG_LEN (1)
2824  F77_CHAR_ARG_LEN (1)));
2825  for (int j = 0; j < a_nr; j++)
2826  for (int i = 0; i < j; i++)
2827  retval.xelem (j, i) = retval.xelem (i, j);
2828 
2829  }
2830  else
2831  {
2832  F77_INT lda = octave::to_f77_int (a.rows ());
2833  F77_INT tda = octave::to_f77_int (a.cols ());
2834  F77_INT ldb = octave::to_f77_int (b.rows ());
2835  F77_INT tdb = octave::to_f77_int (b.cols ());
2836 
2837  retval = FloatMatrix (a_nr, b_nc);
2838  float *c = retval.fortran_vec ();
2839 
2840  if (b_nc == 1)
2841  {
2842  if (a_nr == 1)
2843  F77_FUNC (xsdot, XSDOT) (a_nc, a.data (), 1, b.data (), 1, *c);
2844  else
2845  {
2846  const char ctra = get_blas_trans_arg (tra);
2847  F77_XFCN (sgemv, SGEMV, (F77_CONST_CHAR_ARG2 (&ctra, 1),
2848  lda, tda, 1.0, a.data (), lda,
2849  b.data (), 1, 0.0, c, 1
2850  F77_CHAR_ARG_LEN (1)));
2851  }
2852  }
2853  else if (a_nr == 1)
2854  {
2855  const char crevtrb = get_blas_trans_arg (! trb);
2856  F77_XFCN (sgemv, SGEMV, (F77_CONST_CHAR_ARG2 (&crevtrb, 1),
2857  ldb, tdb, 1.0, b.data (), ldb,
2858  a.data (), 1, 0.0, c, 1
2859  F77_CHAR_ARG_LEN (1)));
2860  }
2861  else
2862  {
2863  const char ctra = get_blas_trans_arg (tra);
2864  const char ctrb = get_blas_trans_arg (trb);
2865  F77_XFCN (sgemm, SGEMM, (F77_CONST_CHAR_ARG2 (&ctra, 1),
2866  F77_CONST_CHAR_ARG2 (&ctrb, 1),
2867  a_nr, b_nc, a_nc, 1.0, a.data (),
2868  lda, b.data (), ldb, 0.0, c, a_nr
2869  F77_CHAR_ARG_LEN (1)
2870  F77_CHAR_ARG_LEN (1)));
2871  }
2872  }
2873 
2874  return retval;
2875 }
2876 
2879 {
2880  return xgemm (a, b);
2881 }
2882 
2883 // FIXME: it would be nice to share code among the min/max functions below.
2884 
2885 #define EMPTY_RETURN_CHECK(T) \
2886  if (nr == 0 || nc == 0) \
2887  return T (nr, nc);
2888 
2890 min (float d, const FloatMatrix& m)
2891 {
2892  octave_idx_type nr = m.rows ();
2893  octave_idx_type nc = m.columns ();
2894 
2896 
2897  FloatMatrix result (nr, nc);
2898 
2899  for (octave_idx_type j = 0; j < nc; j++)
2900  for (octave_idx_type i = 0; i < nr; i++)
2901  {
2902  octave_quit ();
2903  result(i, j) = octave::math::min (d, m(i, j));
2904  }
2905 
2906  return result;
2907 }
2908 
2910 min (const FloatMatrix& m, float d)
2911 {
2912  octave_idx_type nr = m.rows ();
2913  octave_idx_type nc = m.columns ();
2914 
2916 
2917  FloatMatrix result (nr, nc);
2918 
2919  for (octave_idx_type j = 0; j < nc; j++)
2920  for (octave_idx_type i = 0; i < nr; i++)
2921  {
2922  octave_quit ();
2923  result(i, j) = octave::math::min (m(i, j), d);
2924  }
2925 
2926  return result;
2927 }
2928 
2930 min (const FloatMatrix& a, const FloatMatrix& b)
2931 {
2932  octave_idx_type nr = a.rows ();
2933  octave_idx_type nc = a.columns ();
2934 
2935  if (nr != b.rows () || nc != b.columns ())
2936  (*current_liboctave_error_handler)
2937  ("two-arg min requires same size arguments");
2938 
2940 
2941  FloatMatrix result (nr, nc);
2942 
2943  for (octave_idx_type j = 0; j < nc; j++)
2944  for (octave_idx_type i = 0; i < nr; i++)
2945  {
2946  octave_quit ();
2947  result(i, j) = octave::math::min (a(i, j), b(i, j));
2948  }
2949 
2950  return result;
2951 }
2952 
2954 max (float d, const FloatMatrix& m)
2955 {
2956  octave_idx_type nr = m.rows ();
2957  octave_idx_type nc = m.columns ();
2958 
2960 
2961  FloatMatrix result (nr, nc);
2962 
2963  for (octave_idx_type j = 0; j < nc; j++)
2964  for (octave_idx_type i = 0; i < nr; i++)
2965  {
2966  octave_quit ();
2967  result(i, j) = octave::math::max (d, m(i, j));
2968  }
2969 
2970  return result;
2971 }
2972 
2974 max (const FloatMatrix& m, float d)
2975 {
2976  octave_idx_type nr = m.rows ();
2977  octave_idx_type nc = m.columns ();
2978 
2980 
2981  FloatMatrix result (nr, nc);
2982 
2983  for (octave_idx_type j = 0; j < nc; j++)
2984  for (octave_idx_type i = 0; i < nr; i++)
2985  {
2986  octave_quit ();
2987  result(i, j) = octave::math::max (m(i, j), d);
2988  }
2989 
2990  return result;
2991 }
2992 
2994 max (const FloatMatrix& a, const FloatMatrix& b)
2995 {
2996  octave_idx_type nr = a.rows ();
2997  octave_idx_type nc = a.columns ();
2998 
2999  if (nr != b.rows () || nc != b.columns ())
3000  (*current_liboctave_error_handler)
3001  ("two-arg max requires same size arguments");
3002 
3004 
3005  FloatMatrix result (nr, nc);
3006 
3007  for (octave_idx_type j = 0; j < nc; j++)
3008  for (octave_idx_type i = 0; i < nr; i++)
3009  {
3010  octave_quit ();
3011  result(i, j) = octave::math::max (a(i, j), b(i, j));
3012  }
3013 
3014  return result;
3015 }
3016 
3019  const FloatColumnVector& x2,
3021 
3022 {
3023  octave_idx_type m = x1.numel ();
3024 
3025  if (x2.numel () != m)
3026  (*current_liboctave_error_handler)
3027  ("linspace: vectors must be of equal length");
3028 
3029  FloatMatrix retval;
3030 
3031  if (n < 1)
3032  {
3033  retval.clear (m, 0);
3034  return retval;
3035  }
3036 
3037  retval.clear (m, n);
3038  for (octave_idx_type i = 0; i < m; i++)
3039  retval.insert (linspace (x1(i), x2(i), n), i, 0);
3040 
3041  return retval;
3042 }
3043 
3046 
3049 
base_det< float > FloatDET
Definition: DET.h:87
#define Inf
Definition: Faddeeva.cc:260
#define NaN
Definition: Faddeeva.cc:261
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:562
T * fortran_vec()
Size of the specified dimension.
Definition: Array-base.cc:1764
Array< T, Alloc > index(const octave::idx_vector &i) const
Indexing without resizing.
Definition: Array-base.cc:710
bool issquare() const
Size of the specified dimension.
Definition: Array.h:648
void clear()
Definition: Array-base.cc:109
octave_idx_type rows() const
Definition: Array.h:459
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array-base.cc:1023
const T * data() const
Size of the specified dimension.
Definition: Array.h:663
octave_idx_type columns() const
Definition: Array.h:471
octave_idx_type cols() const
Definition: Array.h:469
void make_unique()
Definition: Array.h:216
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
octave_idx_type rows() const
Definition: DiagArray2.h:89
octave_idx_type length() const
Definition: DiagArray2.h:95
T elem(octave_idx_type r, octave_idx_type c) const
Definition: DiagArray2.h:117
octave_idx_type cols() const
Definition: DiagArray2.h:90
void resize(octave_idx_type n, const float &rfv=0)
Definition: fColVector.h:118
FloatColumnVector extract(octave_idx_type r1, octave_idx_type r2) const
Definition: fColVector.cc:151
FloatComplexMatrix lssolve(const FloatMatrix &b) const
Definition: fCMatrix.cc:2245
FloatComplexMatrix solve(MatrixType &mattype, const FloatMatrix &b) const
Definition: fCMatrix.cc:1942
FloatDiagMatrix inverse() const
Definition: fDiagMatrix.cc:227
FloatColumnVector extract_diag(octave_idx_type k=0) const
Definition: fDiagMatrix.h:110
FloatMatrix sumsq(int dim=-1) const
Definition: fMatrix.cc:2405
FloatMatrix sum(int dim=-1) const
Definition: fMatrix.cc:2399
bool operator==(const FloatMatrix &a) const
Definition: fMatrix.cc:123
void resize(octave_idx_type nr, octave_idx_type nc, float rfv=0)
Definition: fMatrix.h:158
FloatColumnVector row_max() const
Definition: fMatrix.cc:2494
FloatMatrix lssolve(const FloatMatrix &b) const
Definition: fMatrix.cc:1927
FloatComplexMatrix fourier2d() const
Definition: fMatrix.cc:799
friend class FloatComplexMatrix
Definition: fMatrix.h:137
FloatMatrix abs() const
Definition: fMatrix.cc:2411
FloatMatrix & fill(float val)
Definition: fMatrix.cc:227
FloatMatrix inverse() const
Definition: fMatrix.cc:457
FloatMatrix prod(int dim=-1) const
Definition: fMatrix.cc:2393
FloatMatrix & insert(const FloatMatrix &a, octave_idx_type r, octave_idx_type c)
Definition: fMatrix.cc:154
FloatRowVector row(octave_idx_type i) const
Definition: fMatrix.cc:422
FloatMatrix & operator-=(const FloatDiagMatrix &a)
Definition: fMatrix.cc:2334
FloatComplexMatrix ifourier2d() const
Definition: fMatrix.cc:811
FloatMatrix & operator+=(const FloatDiagMatrix &a)
Definition: fMatrix.cc:2316
float rcond() const
Definition: fMatrix.cc:1038
bool issymmetric() const
Definition: fMatrix.cc:138
FloatComplexMatrix ifourier() const
Definition: fMatrix.cc:769
FloatMatrix solve(MatrixType &mattype, const FloatMatrix &b) const
Definition: fMatrix.cc:1608
FloatMatrix cumsum(int dim=-1) const
Definition: fMatrix.cc:2387
FloatComplexMatrix fourier() const
Definition: fMatrix.cc:740
FloatRowVector column_min() const
Definition: fMatrix.cc:2549
FloatMatrix append(const FloatMatrix &a) const
Definition: fMatrix.cc:271
FloatRowVector column_max() const
Definition: fMatrix.cc:2604
FloatMatrix diag(octave_idx_type k=0) const
Definition: fMatrix.cc:2417
bool operator!=(const FloatMatrix &a) const
Definition: fMatrix.cc:132
FloatColumnVector row_min() const
Definition: fMatrix.cc:2439
FloatMatrix extract(octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
Definition: fMatrix.cc:403
FloatMatrix()=default
FloatMatrix cumprod(int dim=-1) const
Definition: fMatrix.cc:2381
FloatMatrix extract_n(octave_idx_type r1, octave_idx_type c1, octave_idx_type nr, octave_idx_type nc) const
Definition: fMatrix.cc:413
FloatColumnVector column(octave_idx_type i) const
Definition: fMatrix.cc:428
FloatDET determinant() const
Definition: fMatrix.cc:864
FloatMatrix transpose() const
Definition: fMatrix.h:140
FloatMatrix stack(const FloatMatrix &a) const
Definition: fMatrix.cc:331
FloatMatrix pseudo_inverse(float tol=0.0) const
Definition: fMatrix.cc:699
FloatNDArray sum(int dim=-1) const
Definition: fNDArray.cc:388
FloatNDArray prod(int dim=-1) const
Definition: fNDArray.cc:376
FloatNDArray abs() const
Definition: fNDArray.cc:538
FloatNDArray cumprod(int dim=-1) const
Definition: fNDArray.cc:364
FloatNDArray & insert(const FloatNDArray &a, octave_idx_type r, octave_idx_type c)
Definition: fNDArray.cc:522
FloatNDArray cumsum(int dim=-1) const
Definition: fNDArray.cc:370
FloatNDArray sumsq(int dim=-1) const
Definition: fNDArray.cc:400
FloatNDArray diag(octave_idx_type k=0) const
Definition: fNDArray.cc:577
void resize(octave_idx_type n, const float &rfv=0)
Definition: fRowVector.h:109
bool ishermitian() const
Definition: MatrixType.h:122
void mark_as_unsymmetric()
Definition: MatrixType.cc:920
@ Permuted_Lower
Definition: MatrixType.h:48
@ Permuted_Upper
Definition: MatrixType.h:47
int type(bool quiet=true)
Definition: MatrixType.cc:656
void mark_as_rectangular()
Definition: MatrixType.h:155
octave_idx_type rows() const
Definition: PermMatrix.h:62
const Array< octave_idx_type > & col_perm_vec() const
Definition: PermMatrix.h:83
Definition: DET.h:39
base_det square() const
Definition: DET.h:68
Definition: chol.h:38
COND_T rcond() const
Definition: chol.h:63
T inverse() const
Definition: chol.cc:250
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
#define F77_XFCN(f, F, args)
Definition: f77-fcn.h:45
octave_f77_int_type F77_INT
Definition: f77-fcn.h:306
std::ostream & operator<<(std::ostream &os, const FloatMatrix &a)
Definition: fMatrix.cc:2659
FloatMatrix operator*(const FloatColumnVector &v, const FloatRowVector &a)
Definition: fMatrix.cc:2354
FloatMatrix linspace(const FloatColumnVector &x1, const FloatColumnVector &x2, octave_idx_type n)
Definition: fMatrix.cc:3018
FloatMatrix min(float d, const FloatMatrix &m)
Definition: fMatrix.cc:2890
#define EMPTY_RETURN_CHECK(T)
Definition: fMatrix.cc:2885
FloatMatrix real(const FloatComplexMatrix &a)
Definition: fMatrix.cc:391
FloatMatrix imag(const FloatComplexMatrix &a)
Definition: fMatrix.cc:397
FloatMatrix max(float d, const FloatMatrix &m)
Definition: fMatrix.cc:2954
std::istream & operator>>(std::istream &is, FloatMatrix &a)
Definition: fMatrix.cc:2674
FloatMatrix Givens(float x, float y)
Definition: fMatrix.cc:2697
FloatMatrix Sylvester(const FloatMatrix &a, const FloatMatrix &b, const FloatMatrix &c)
Definition: fMatrix.cc:2714
FloatMatrix xgemm(const FloatMatrix &a, const FloatMatrix &b, blas_trans_type transa, blas_trans_type transb)
Definition: fMatrix.cc:2792
double norm(const ColumnVector &v)
Definition: graphics.cc:5547
void scale(Matrix &m, double x, double y, double z)
Definition: graphics.cc:5500
octave::idx_vector idx_vector
Definition: idx-vector.h:1022
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
void warn_singular_matrix(double rcond)
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:41
F77_RET_T const F77_INT const F77_INT const F77_INT const F77_DBLE const F77_DBLE F77_INT F77_DBLE * V
Complex log2(const Complex &x)
Definition: lo-mappers.cc:141
bool isfinite(double x)
Definition: lo-mappers.h:192
bool isinf(double x)
Definition: lo-mappers.h:203
bool isnan(bool)
Definition: lo-mappers.h:178
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T const F77_DBLE * x
blas_trans_type
Definition: mx-defs.h:80
@ blas_no_trans
Definition: mx-defs.h:81
@ blas_conj_trans
Definition: mx-defs.h:83
@ blas_trans
Definition: mx-defs.h:82
char get_blas_char(blas_trans_type transt)
Definition: mx-defs.h:87
bool mx_inline_equal(std::size_t n, const T1 *x, const T2 *y)
Definition: mx-inlines.cc:577
void mx_inline_real(std::size_t n, T *r, const std::complex< T > *x)
Definition: mx-inlines.cc:325
void mx_inline_imag(std::size_t n, T *r, const std::complex< T > *x)
Definition: mx-inlines.cc:333
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
#define MM_BOOL_OPS(M1, M2)
Definition: mx-op-defs.h:213
#define MM_CMP_OPS(M1, M2)
Definition: mx-op-defs.h:196
#define MS_CMP_OPS(M, S)
Definition: mx-op-defs.h:110
#define SM_CMP_OPS(S, M)
Definition: mx-op-defs.h:153
#define SM_BOOL_OPS(S, M)
Definition: mx-op-defs.h:170
#define MS_BOOL_OPS(M, S)
Definition: mx-op-defs.h:127
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44
F77_RET_T F77_FUNC(xerbla, XERBLA)(F77_CONST_CHAR_ARG_DEF(s_arg
F77_RET_T len
Definition: xerbla.cc:61
subroutine xilaenv(ispec, name, opts, n1, n2, n3, n4, retval)
Definition: xilaenv.f:2
subroutine xsdot(n, dx, incx, dy, incy, retval)
Definition: xsdot.f:2