fMatrix.cc

Go to the documentation of this file.
00001 // Matrix manipulations.
00002 /*
00003 
00004 Copyright (C) 1994-2012 John W. Eaton
00005 Copyright (C) 2008-2009 Jaroslav Hajek
00006 Copyright (C) 2009 VZLU Prague, a.s.
00007 
00008 This file is part of Octave.
00009 
00010 Octave is free software; you can redistribute it and/or modify it
00011 under the terms of the GNU General Public License as published by the
00012 Free Software Foundation; either version 3 of the License, or (at your
00013 option) any later version.
00014 
00015 Octave is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00018 for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with Octave; see the file COPYING.  If not, see
00022 <http://www.gnu.org/licenses/>.
00023 
00024 */
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029 
00030 #include <cfloat>
00031 
00032 #include <iostream>
00033 #include <vector>
00034 
00035 #include "Array-util.h"
00036 #include "DET.h"
00037 #include "byte-swap.h"
00038 #include "f77-fcn.h"
00039 #include "fMatrix.h"
00040 #include "floatCHOL.h"
00041 #include "floatSCHUR.h"
00042 #include "floatSVD.h"
00043 #include "functor.h"
00044 #include "lo-error.h"
00045 #include "lo-ieee.h"
00046 #include "lo-mappers.h"
00047 #include "lo-utils.h"
00048 #include "mx-base.h"
00049 #include "mx-fdm-fm.h"
00050 #include "mx-fm-fdm.h"
00051 #include "mx-inlines.cc"
00052 #include "mx-op-defs.h"
00053 #include "oct-cmplx.h"
00054 #include "oct-fftw.h"
00055 #include "oct-locbuf.h"
00056 #include "oct-norm.h"
00057 #include "quit.h"
00058 
00059 // Fortran functions we call.
00060 
00061 extern "C"
00062 {
00063   F77_RET_T
00064   F77_FUNC (xilaenv, XILAENV) (const octave_idx_type&,
00065                                F77_CONST_CHAR_ARG_DECL,
00066                                F77_CONST_CHAR_ARG_DECL,
00067                                const octave_idx_type&, const octave_idx_type&,
00068                                const octave_idx_type&, const octave_idx_type&,
00069                                octave_idx_type&
00070                                F77_CHAR_ARG_LEN_DECL
00071                                F77_CHAR_ARG_LEN_DECL);
00072 
00073   F77_RET_T
00074   F77_FUNC (sgebal, SGEBAL) (F77_CONST_CHAR_ARG_DECL,
00075                              const octave_idx_type&, float*,
00076                              const octave_idx_type&, octave_idx_type&,
00077                              octave_idx_type&, float*, octave_idx_type&
00078                              F77_CHAR_ARG_LEN_DECL);
00079 
00080   F77_RET_T
00081   F77_FUNC (sgebak, SGEBAK) (F77_CONST_CHAR_ARG_DECL,
00082                              F77_CONST_CHAR_ARG_DECL,
00083                              const octave_idx_type&, const octave_idx_type&,
00084                              const octave_idx_type&, float*,
00085                              const octave_idx_type&, float*,
00086                              const octave_idx_type&, octave_idx_type&
00087                              F77_CHAR_ARG_LEN_DECL
00088                              F77_CHAR_ARG_LEN_DECL);
00089 
00090 
00091   F77_RET_T
00092   F77_FUNC (sgemm, SGEMM) (F77_CONST_CHAR_ARG_DECL,
00093                            F77_CONST_CHAR_ARG_DECL,
00094                            const octave_idx_type&, const octave_idx_type&,
00095                            const octave_idx_type&, const float&, const float*,
00096                            const octave_idx_type&, const float*,
00097                            const octave_idx_type&, const float&, float*,
00098                            const octave_idx_type&
00099                            F77_CHAR_ARG_LEN_DECL
00100                            F77_CHAR_ARG_LEN_DECL);
00101 
00102   F77_RET_T
00103   F77_FUNC (sgemv, SGEMV) (F77_CONST_CHAR_ARG_DECL,
00104                            const octave_idx_type&, const octave_idx_type&,
00105                            const float&, const float*,
00106                            const octave_idx_type&, const float*,
00107                            const octave_idx_type&, const float&, float*,
00108                            const octave_idx_type&
00109                            F77_CHAR_ARG_LEN_DECL);
00110 
00111   F77_RET_T
00112   F77_FUNC (xsdot, XSDOT) (const octave_idx_type&, const float*,
00113                            const octave_idx_type&, const float*,
00114                            const octave_idx_type&, float&);
00115 
00116   F77_RET_T
00117   F77_FUNC (ssyrk, SSYRK) (F77_CONST_CHAR_ARG_DECL,
00118                            F77_CONST_CHAR_ARG_DECL,
00119                            const octave_idx_type&, const octave_idx_type&,
00120                            const float&, const float*, const octave_idx_type&,
00121                            const float&, float*, const octave_idx_type&
00122                            F77_CHAR_ARG_LEN_DECL
00123                            F77_CHAR_ARG_LEN_DECL);
00124 
00125   F77_RET_T
00126   F77_FUNC (sgetrf, SGETRF) (const octave_idx_type&,
00127                              const octave_idx_type&, float*,
00128                              const octave_idx_type&,
00129                              octave_idx_type*, octave_idx_type&);
00130 
00131   F77_RET_T
00132   F77_FUNC (sgetrs, SGETRS) (F77_CONST_CHAR_ARG_DECL,
00133                              const octave_idx_type&, const octave_idx_type&,
00134                              const float*, const octave_idx_type&,
00135                              const octave_idx_type*, float*,
00136                              const octave_idx_type&, octave_idx_type&
00137                              F77_CHAR_ARG_LEN_DECL);
00138 
00139   F77_RET_T
00140   F77_FUNC (sgetri, SGETRI) (const octave_idx_type&, float*,
00141                              const octave_idx_type&, const octave_idx_type*,
00142                              float*, const octave_idx_type&, octave_idx_type&);
00143 
00144   F77_RET_T
00145   F77_FUNC (sgecon, SGECON) (F77_CONST_CHAR_ARG_DECL,
00146                              const octave_idx_type&, float*,
00147                              const octave_idx_type&, const float&, float&,
00148                              float*, octave_idx_type*, octave_idx_type&
00149                              F77_CHAR_ARG_LEN_DECL);
00150 
00151   F77_RET_T
00152   F77_FUNC (sgelsy, SGELSY) (const octave_idx_type&, const octave_idx_type&,
00153                              const octave_idx_type&, float*,
00154                              const octave_idx_type&, float*,
00155                              const octave_idx_type&, octave_idx_type*,
00156                              float&, octave_idx_type&, float*,
00157                              const octave_idx_type&, octave_idx_type&);
00158 
00159   F77_RET_T
00160   F77_FUNC (sgelsd, SGELSD) (const octave_idx_type&, const octave_idx_type&,
00161                              const octave_idx_type&, float*,
00162                              const octave_idx_type&, float*,
00163                              const octave_idx_type&, float*, float&,
00164                              octave_idx_type&, float*,
00165                              const octave_idx_type&, octave_idx_type*,
00166                              octave_idx_type&);
00167 
00168   F77_RET_T
00169   F77_FUNC (spotrf, SPOTRF) (F77_CONST_CHAR_ARG_DECL,
00170                              const octave_idx_type&, float *,
00171                              const octave_idx_type&, octave_idx_type&
00172                              F77_CHAR_ARG_LEN_DECL);
00173 
00174   F77_RET_T
00175   F77_FUNC (spocon, SPOCON) (F77_CONST_CHAR_ARG_DECL,
00176                              const octave_idx_type&, float*,
00177                              const octave_idx_type&, const float&,
00178                              float&, float*, octave_idx_type*,
00179                              octave_idx_type&
00180                              F77_CHAR_ARG_LEN_DECL);
00181   F77_RET_T
00182   F77_FUNC (spotrs, SPOTRS) (F77_CONST_CHAR_ARG_DECL,
00183                              const octave_idx_type&, const octave_idx_type&,
00184                              const float*, const octave_idx_type&, float*,
00185                              const octave_idx_type&, octave_idx_type&
00186                              F77_CHAR_ARG_LEN_DECL);
00187 
00188   F77_RET_T
00189   F77_FUNC (strtri, STRTRI) (F77_CONST_CHAR_ARG_DECL,
00190                              F77_CONST_CHAR_ARG_DECL,
00191                              const octave_idx_type&, const float*,
00192                              const octave_idx_type&, octave_idx_type&
00193                              F77_CHAR_ARG_LEN_DECL
00194                              F77_CHAR_ARG_LEN_DECL);
00195   F77_RET_T
00196   F77_FUNC (strcon, STRCON) (F77_CONST_CHAR_ARG_DECL,
00197                              F77_CONST_CHAR_ARG_DECL,
00198                              F77_CONST_CHAR_ARG_DECL,
00199                              const octave_idx_type&, const float*,
00200                              const octave_idx_type&, float&,
00201                              float*, octave_idx_type*, octave_idx_type&
00202                              F77_CHAR_ARG_LEN_DECL
00203                              F77_CHAR_ARG_LEN_DECL
00204                              F77_CHAR_ARG_LEN_DECL);
00205   F77_RET_T
00206   F77_FUNC (strtrs, STRTRS) (F77_CONST_CHAR_ARG_DECL,
00207                              F77_CONST_CHAR_ARG_DECL,
00208                              F77_CONST_CHAR_ARG_DECL,
00209                              const octave_idx_type&,
00210                              const octave_idx_type&, const float*,
00211                              const octave_idx_type&, float*,
00212                              const octave_idx_type&, octave_idx_type&
00213                              F77_CHAR_ARG_LEN_DECL
00214                              F77_CHAR_ARG_LEN_DECL
00215                              F77_CHAR_ARG_LEN_DECL);
00216 
00217   F77_RET_T
00218   F77_FUNC (slartg, SLARTG) (const float&, const float&, float&,
00219                              float&, float&);
00220 
00221   F77_RET_T
00222   F77_FUNC (strsyl, STRSYL) (F77_CONST_CHAR_ARG_DECL,
00223                              F77_CONST_CHAR_ARG_DECL,
00224                              const octave_idx_type&, const octave_idx_type&,
00225                              const octave_idx_type&, const float*,
00226                              const octave_idx_type&, const float*,
00227                              const octave_idx_type&, const float*,
00228                              const octave_idx_type&, float&, octave_idx_type&
00229                              F77_CHAR_ARG_LEN_DECL
00230                              F77_CHAR_ARG_LEN_DECL);
00231 
00232   F77_RET_T
00233   F77_FUNC (xslange, XSLANGE) (F77_CONST_CHAR_ARG_DECL,
00234                                const octave_idx_type&,
00235                                const octave_idx_type&, const float*,
00236                                const octave_idx_type&, float*, float&
00237                                F77_CHAR_ARG_LEN_DECL);
00238 }
00239 
00240 // Matrix class.
00241 
00242 FloatMatrix::FloatMatrix (const FloatRowVector& rv)
00243   : MArray<float> (rv)
00244 {
00245 }
00246 
00247 FloatMatrix::FloatMatrix (const FloatColumnVector& cv)
00248   : MArray<float> (cv)
00249 {
00250 }
00251 
00252 FloatMatrix::FloatMatrix (const FloatDiagMatrix& a)
00253   : MArray<float> (a.dims (), 0.0)
00254 {
00255   for (octave_idx_type i = 0; i < a.length (); i++)
00256     elem (i, i) = a.elem (i, i);
00257 }
00258 
00259 FloatMatrix::FloatMatrix (const PermMatrix& a)
00260   : MArray<float> (a.dims (), 0.0)
00261 {
00262   const Array<octave_idx_type> ia (a.pvec ());
00263   octave_idx_type len = a.rows ();
00264   if (a.is_col_perm ())
00265     for (octave_idx_type i = 0; i < len; i++)
00266       elem (ia(i), i) = 1.0;
00267   else
00268     for (octave_idx_type i = 0; i < len; i++)
00269       elem (i, ia(i)) = 1.0;
00270 }
00271 
00272 // FIXME -- could we use a templated mixed-type copy function
00273 // here?
00274 
00275 FloatMatrix::FloatMatrix (const boolMatrix& a)
00276   : MArray<float> (a)
00277 {
00278 }
00279 
00280 FloatMatrix::FloatMatrix (const charMatrix& a)
00281   : MArray<float> (a.dims ())
00282 {
00283   for (octave_idx_type i = 0; i < a.rows (); i++)
00284     for (octave_idx_type j = 0; j < a.cols (); j++)
00285       elem (i, j) = static_cast<unsigned char> (a.elem (i, j));
00286 }
00287 
00288 bool
00289 FloatMatrix::operator == (const FloatMatrix& a) const
00290 {
00291   if (rows () != a.rows () || cols () != a.cols ())
00292     return false;
00293 
00294   return mx_inline_equal (length (), data (), a.data ());
00295 }
00296 
00297 bool
00298 FloatMatrix::operator != (const FloatMatrix& a) const
00299 {
00300   return !(*this == a);
00301 }
00302 
00303 bool
00304 FloatMatrix::is_symmetric (void) const
00305 {
00306   if (is_square () && rows () > 0)
00307     {
00308       for (octave_idx_type i = 0; i < rows (); i++)
00309         for (octave_idx_type j = i+1; j < cols (); j++)
00310           if (elem (i, j) != elem (j, i))
00311             return false;
00312 
00313       return true;
00314     }
00315 
00316   return false;
00317 }
00318 
00319 FloatMatrix&
00320 FloatMatrix::insert (const FloatMatrix& a, octave_idx_type r, octave_idx_type c)
00321 {
00322   Array<float>::insert (a, r, c);
00323   return *this;
00324 }
00325 
00326 FloatMatrix&
00327 FloatMatrix::insert (const FloatRowVector& a, octave_idx_type r, octave_idx_type c)
00328 {
00329   octave_idx_type a_len = a.length ();
00330 
00331   if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ())
00332     {
00333       (*current_liboctave_error_handler) ("range error for insert");
00334       return *this;
00335     }
00336 
00337   if (a_len > 0)
00338     {
00339       make_unique ();
00340 
00341       for (octave_idx_type i = 0; i < a_len; i++)
00342         xelem (r, c+i) = a.elem (i);
00343     }
00344 
00345   return *this;
00346 }
00347 
00348 FloatMatrix&
00349 FloatMatrix::insert (const FloatColumnVector& a, octave_idx_type r, octave_idx_type c)
00350 {
00351   octave_idx_type a_len = a.length ();
00352 
00353   if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ())
00354     {
00355       (*current_liboctave_error_handler) ("range error for insert");
00356       return *this;
00357     }
00358 
00359   if (a_len > 0)
00360     {
00361       make_unique ();
00362 
00363       for (octave_idx_type i = 0; i < a_len; i++)
00364         xelem (r+i, c) = a.elem (i);
00365     }
00366 
00367   return *this;
00368 }
00369 
00370 FloatMatrix&
00371 FloatMatrix::insert (const FloatDiagMatrix& a, octave_idx_type r, octave_idx_type c)
00372 {
00373   octave_idx_type a_nr = a.rows ();
00374   octave_idx_type a_nc = a.cols ();
00375 
00376   if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())
00377     {
00378       (*current_liboctave_error_handler) ("range error for insert");
00379       return *this;
00380     }
00381 
00382   fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1);
00383 
00384   octave_idx_type a_len = a.length ();
00385 
00386   if (a_len > 0)
00387     {
00388       make_unique ();
00389 
00390       for (octave_idx_type i = 0; i < a_len; i++)
00391         xelem (r+i, c+i) = a.elem (i, i);
00392     }
00393 
00394   return *this;
00395 }
00396 
00397 FloatMatrix&
00398 FloatMatrix::fill (float val)
00399 {
00400   octave_idx_type nr = rows ();
00401   octave_idx_type nc = cols ();
00402 
00403   if (nr > 0 && nc > 0)
00404     {
00405       make_unique ();
00406 
00407       for (octave_idx_type j = 0; j < nc; j++)
00408         for (octave_idx_type i = 0; i < nr; i++)
00409           xelem (i, j) = val;
00410     }
00411 
00412   return *this;
00413 }
00414 
00415 FloatMatrix&
00416 FloatMatrix::fill (float val, octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2)
00417 {
00418   octave_idx_type nr = rows ();
00419   octave_idx_type nc = cols ();
00420 
00421   if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0
00422       || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)
00423     {
00424       (*current_liboctave_error_handler) ("range error for fill");
00425       return *this;
00426     }
00427 
00428   if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; }
00429   if (c1 > c2) { octave_idx_type tmp = c1; c1 = c2; c2 = tmp; }
00430 
00431   if (r2 >= r1 && c2 >= c1)
00432     {
00433       make_unique ();
00434 
00435       for (octave_idx_type j = c1; j <= c2; j++)
00436         for (octave_idx_type i = r1; i <= r2; i++)
00437           xelem (i, j) = val;
00438     }
00439 
00440   return *this;
00441 }
00442 
00443 FloatMatrix
00444 FloatMatrix::append (const FloatMatrix& a) const
00445 {
00446   octave_idx_type nr = rows ();
00447   octave_idx_type nc = cols ();
00448   if (nr != a.rows ())
00449     {
00450       (*current_liboctave_error_handler) ("row dimension mismatch for append");
00451       return FloatMatrix ();
00452     }
00453 
00454   octave_idx_type nc_insert = nc;
00455   FloatMatrix retval (nr, nc + a.cols ());
00456   retval.insert (*this, 0, 0);
00457   retval.insert (a, 0, nc_insert);
00458   return retval;
00459 }
00460 
00461 FloatMatrix
00462 FloatMatrix::append (const FloatRowVector& a) const
00463 {
00464   octave_idx_type nr = rows ();
00465   octave_idx_type nc = cols ();
00466   if (nr != 1)
00467     {
00468       (*current_liboctave_error_handler) ("row dimension mismatch for append");
00469       return FloatMatrix ();
00470     }
00471 
00472   octave_idx_type nc_insert = nc;
00473   FloatMatrix retval (nr, nc + a.length ());
00474   retval.insert (*this, 0, 0);
00475   retval.insert (a, 0, nc_insert);
00476   return retval;
00477 }
00478 
00479 FloatMatrix
00480 FloatMatrix::append (const FloatColumnVector& a) const
00481 {
00482   octave_idx_type nr = rows ();
00483   octave_idx_type nc = cols ();
00484   if (nr != a.length ())
00485     {
00486       (*current_liboctave_error_handler) ("row dimension mismatch for append");
00487       return FloatMatrix ();
00488     }
00489 
00490   octave_idx_type nc_insert = nc;
00491   FloatMatrix retval (nr, nc + 1);
00492   retval.insert (*this, 0, 0);
00493   retval.insert (a, 0, nc_insert);
00494   return retval;
00495 }
00496 
00497 FloatMatrix
00498 FloatMatrix::append (const FloatDiagMatrix& a) const
00499 {
00500   octave_idx_type nr = rows ();
00501   octave_idx_type nc = cols ();
00502   if (nr != a.rows ())
00503     {
00504       (*current_liboctave_error_handler) ("row dimension mismatch for append");
00505       return *this;
00506     }
00507 
00508   octave_idx_type nc_insert = nc;
00509   FloatMatrix retval (nr, nc + a.cols ());
00510   retval.insert (*this, 0, 0);
00511   retval.insert (a, 0, nc_insert);
00512   return retval;
00513 }
00514 
00515 FloatMatrix
00516 FloatMatrix::stack (const FloatMatrix& a) const
00517 {
00518   octave_idx_type nr = rows ();
00519   octave_idx_type nc = cols ();
00520   if (nc != a.cols ())
00521     {
00522       (*current_liboctave_error_handler)
00523         ("column dimension mismatch for stack");
00524       return FloatMatrix ();
00525     }
00526 
00527   octave_idx_type nr_insert = nr;
00528   FloatMatrix retval (nr + a.rows (), nc);
00529   retval.insert (*this, 0, 0);
00530   retval.insert (a, nr_insert, 0);
00531   return retval;
00532 }
00533 
00534 FloatMatrix
00535 FloatMatrix::stack (const FloatRowVector& a) const
00536 {
00537   octave_idx_type nr = rows ();
00538   octave_idx_type nc = cols ();
00539   if (nc != a.length ())
00540     {
00541       (*current_liboctave_error_handler)
00542         ("column dimension mismatch for stack");
00543       return FloatMatrix ();
00544     }
00545 
00546   octave_idx_type nr_insert = nr;
00547   FloatMatrix retval (nr + 1, nc);
00548   retval.insert (*this, 0, 0);
00549   retval.insert (a, nr_insert, 0);
00550   return retval;
00551 }
00552 
00553 FloatMatrix
00554 FloatMatrix::stack (const FloatColumnVector& a) const
00555 {
00556   octave_idx_type nr = rows ();
00557   octave_idx_type nc = cols ();
00558   if (nc != 1)
00559     {
00560       (*current_liboctave_error_handler)
00561         ("column dimension mismatch for stack");
00562       return FloatMatrix ();
00563     }
00564 
00565   octave_idx_type nr_insert = nr;
00566   FloatMatrix retval (nr + a.length (), nc);
00567   retval.insert (*this, 0, 0);
00568   retval.insert (a, nr_insert, 0);
00569   return retval;
00570 }
00571 
00572 FloatMatrix
00573 FloatMatrix::stack (const FloatDiagMatrix& a) const
00574 {
00575   octave_idx_type nr = rows ();
00576   octave_idx_type nc = cols ();
00577   if (nc != a.cols ())
00578     {
00579       (*current_liboctave_error_handler)
00580         ("column dimension mismatch for stack");
00581       return FloatMatrix ();
00582     }
00583 
00584   octave_idx_type nr_insert = nr;
00585   FloatMatrix retval (nr + a.rows (), nc);
00586   retval.insert (*this, 0, 0);
00587   retval.insert (a, nr_insert, 0);
00588   return retval;
00589 }
00590 
00591 FloatMatrix
00592 real (const FloatComplexMatrix& a)
00593 {
00594   return do_mx_unary_op<float, FloatComplex> (a, mx_inline_real);
00595 }
00596 
00597 FloatMatrix
00598 imag (const FloatComplexMatrix& a)
00599 {
00600   return do_mx_unary_op<float, FloatComplex> (a, mx_inline_imag);
00601 }
00602 
00603 FloatMatrix
00604 FloatMatrix::extract (octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
00605 {
00606   if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; }
00607   if (c1 > c2) { octave_idx_type tmp = c1; c1 = c2; c2 = tmp; }
00608 
00609   return index (idx_vector (r1, r2+1), idx_vector (c1, c2+1));
00610 }
00611 
00612 FloatMatrix
00613 FloatMatrix::extract_n (octave_idx_type r1, octave_idx_type c1, octave_idx_type nr, octave_idx_type nc) const
00614 {
00615   return index (idx_vector (r1, r1 + nr), idx_vector (c1, c1 + nc));
00616 }
00617 
00618 // extract row or column i.
00619 
00620 FloatRowVector
00621 FloatMatrix::row (octave_idx_type i) const
00622 {
00623   return index (idx_vector (i), idx_vector::colon);
00624 }
00625 
00626 FloatColumnVector
00627 FloatMatrix::column (octave_idx_type i) const
00628 {
00629   return index (idx_vector::colon, idx_vector (i));
00630 }
00631 
00632 FloatMatrix
00633 FloatMatrix::inverse (void) const
00634 {
00635   octave_idx_type info;
00636   float rcon;
00637   MatrixType mattype (*this);
00638   return inverse (mattype, info, rcon, 0, 0);
00639 }
00640 
00641 FloatMatrix
00642 FloatMatrix::inverse (octave_idx_type& info) const
00643 {
00644   float rcon;
00645   MatrixType mattype (*this);
00646   return inverse (mattype, info, rcon, 0, 0);
00647 }
00648 
00649 FloatMatrix
00650 FloatMatrix::inverse (octave_idx_type& info, float& rcon, int force,
00651                  int calc_cond) const
00652 {
00653   MatrixType mattype (*this);
00654   return inverse (mattype, info, rcon, force, calc_cond);
00655 }
00656 
00657 FloatMatrix
00658 FloatMatrix::inverse (MatrixType& mattype) const
00659 {
00660   octave_idx_type info;
00661   float rcon;
00662   return inverse (mattype, info, rcon, 0, 0);
00663 }
00664 
00665 FloatMatrix
00666 FloatMatrix::inverse (MatrixType &mattype, octave_idx_type& info) const
00667 {
00668   float rcon;
00669   return inverse (mattype, info, rcon, 0, 0);
00670 }
00671 
00672 FloatMatrix
00673 FloatMatrix::tinverse (MatrixType &mattype, octave_idx_type& info, float& rcon,
00674                   int force, int calc_cond) const
00675 {
00676   FloatMatrix retval;
00677 
00678   octave_idx_type nr = rows ();
00679   octave_idx_type nc = cols ();
00680 
00681   if (nr != nc || nr == 0 || nc == 0)
00682     (*current_liboctave_error_handler) ("inverse requires square matrix");
00683   else
00684     {
00685       int typ = mattype.type ();
00686       char uplo = (typ == MatrixType::Lower ? 'L' : 'U');
00687       char udiag = 'N';
00688       retval = *this;
00689       float *tmp_data = retval.fortran_vec ();
00690 
00691       F77_XFCN (strtri, STRTRI, (F77_CONST_CHAR_ARG2 (&uplo, 1),
00692                                  F77_CONST_CHAR_ARG2 (&udiag, 1),
00693                                  nr, tmp_data, nr, info
00694                                  F77_CHAR_ARG_LEN (1)
00695                                  F77_CHAR_ARG_LEN (1)));
00696 
00697       // Throw-away extra info LAPACK gives so as to not change output.
00698       rcon = 0.0;
00699       if (info != 0)
00700         info = -1;
00701       else if (calc_cond)
00702         {
00703           octave_idx_type dtrcon_info = 0;
00704           char job = '1';
00705 
00706           OCTAVE_LOCAL_BUFFER (float, work, 3 * nr);
00707           OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, nr);
00708 
00709           F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&job, 1),
00710                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
00711                                      F77_CONST_CHAR_ARG2 (&udiag, 1),
00712                                      nr, tmp_data, nr, rcon,
00713                                      work, iwork, dtrcon_info
00714                                      F77_CHAR_ARG_LEN (1)
00715                                      F77_CHAR_ARG_LEN (1)
00716                                      F77_CHAR_ARG_LEN (1)));
00717 
00718           if (dtrcon_info != 0)
00719             info = -1;
00720         }
00721 
00722       if (info == -1 && ! force)
00723         retval = *this; // Restore matrix contents.
00724     }
00725 
00726   return retval;
00727 }
00728 
00729 
00730 FloatMatrix
00731 FloatMatrix::finverse (MatrixType &mattype, octave_idx_type& info, float& rcon,
00732                   int force, int calc_cond) const
00733 {
00734   FloatMatrix retval;
00735 
00736   octave_idx_type nr = rows ();
00737   octave_idx_type nc = cols ();
00738 
00739   if (nr != nc || nr == 0 || nc == 0)
00740     (*current_liboctave_error_handler) ("inverse requires square matrix");
00741   else
00742     {
00743       Array<octave_idx_type> ipvt (dim_vector (nr, 1));
00744       octave_idx_type *pipvt = ipvt.fortran_vec ();
00745 
00746       retval = *this;
00747       float *tmp_data = retval.fortran_vec ();
00748 
00749       Array<float> z(dim_vector (1, 1));
00750       octave_idx_type lwork = -1;
00751 
00752       // Query the optimum work array size.
00753       F77_XFCN (sgetri, SGETRI, (nc, tmp_data, nr, pipvt,
00754                                  z.fortran_vec (), lwork, info));
00755 
00756       lwork = static_cast<octave_idx_type> (z(0));
00757       lwork = (lwork < 2 *nc ? 2*nc : lwork);
00758       z.resize (dim_vector (lwork, 1));
00759       float *pz = z.fortran_vec ();
00760 
00761       info = 0;
00762 
00763       // Calculate the norm of the matrix, for later use.
00764       float anorm = 0;
00765       if (calc_cond)
00766         anorm = retval.abs().sum().row(static_cast<octave_idx_type>(0)).max();
00767 
00768       F77_XFCN (sgetrf, SGETRF, (nc, nc, tmp_data, nr, pipvt, info));
00769 
00770       // Throw-away extra info LAPACK gives so as to not change output.
00771       rcon = 0.0;
00772       if (info != 0)
00773         info = -1;
00774       else if (calc_cond)
00775         {
00776           octave_idx_type dgecon_info = 0;
00777 
00778           // Now calculate the condition number for non-singular matrix.
00779           char job = '1';
00780           Array<octave_idx_type> iz (dim_vector (nc, 1));
00781           octave_idx_type *piz = iz.fortran_vec ();
00782           F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
00783                                      nc, tmp_data, nr, anorm,
00784                                      rcon, pz, piz, dgecon_info
00785                                      F77_CHAR_ARG_LEN (1)));
00786 
00787           if (dgecon_info != 0)
00788             info = -1;
00789         }
00790 
00791       if (info == -1 && ! force)
00792         retval = *this; // Restore matrix contents.
00793       else
00794         {
00795           octave_idx_type dgetri_info = 0;
00796 
00797           F77_XFCN (sgetri, SGETRI, (nc, tmp_data, nr, pipvt,
00798                                      pz, lwork, dgetri_info));
00799 
00800           if (dgetri_info != 0)
00801             info = -1;
00802         }
00803 
00804       if (info != 0)
00805         mattype.mark_as_rectangular();
00806     }
00807 
00808   return retval;
00809 }
00810 
00811 FloatMatrix
00812 FloatMatrix::inverse (MatrixType &mattype, octave_idx_type& info, float& rcon,
00813                  int force, int calc_cond) const
00814 {
00815   int typ = mattype.type (false);
00816   FloatMatrix ret;
00817 
00818   if (typ == MatrixType::Unknown)
00819     typ = mattype.type (*this);
00820 
00821   if (typ == MatrixType::Upper || typ == MatrixType::Lower)
00822     ret = tinverse (mattype, info, rcon, force, calc_cond);
00823   else
00824     {
00825       if (mattype.is_hermitian ())
00826         {
00827           FloatCHOL chol (*this, info, calc_cond);
00828           if (info == 0)
00829             {
00830               if (calc_cond)
00831                 rcon = chol.rcond ();
00832               else
00833                 rcon = 1.0;
00834               ret = chol.inverse ();
00835             }
00836           else
00837             mattype.mark_as_unsymmetric ();
00838         }
00839 
00840       if (!mattype.is_hermitian ())
00841         ret = finverse(mattype, info, rcon, force, calc_cond);
00842 
00843       if ((mattype.is_hermitian () || calc_cond) && rcon == 0.)
00844         ret = FloatMatrix (rows (), columns (), octave_Float_Inf);
00845     }
00846 
00847   return ret;
00848 }
00849 
00850 FloatMatrix
00851 FloatMatrix::pseudo_inverse (float tol) const
00852 {
00853   FloatSVD result (*this, SVD::economy);
00854 
00855   FloatDiagMatrix S = result.singular_values ();
00856   FloatMatrix U = result.left_singular_matrix ();
00857   FloatMatrix V = result.right_singular_matrix ();
00858 
00859   FloatColumnVector sigma = S.diag ();
00860 
00861   octave_idx_type r = sigma.length () - 1;
00862   octave_idx_type nr = rows ();
00863   octave_idx_type nc = cols ();
00864 
00865   if (tol <= 0.0)
00866     {
00867       if (nr > nc)
00868         tol = nr * sigma.elem (0) * DBL_EPSILON;
00869       else
00870         tol = nc * sigma.elem (0) * DBL_EPSILON;
00871     }
00872 
00873   while (r >= 0 && sigma.elem (r) < tol)
00874     r--;
00875 
00876   if (r < 0)
00877     return FloatMatrix (nc, nr, 0.0);
00878   else
00879     {
00880       FloatMatrix Ur = U.extract (0, 0, nr-1, r);
00881       FloatDiagMatrix D = FloatDiagMatrix (sigma.extract (0, r)) . inverse ();
00882       FloatMatrix Vr = V.extract (0, 0, nc-1, r);
00883       return Vr * D * Ur.transpose ();
00884     }
00885 }
00886 
00887 #if defined (HAVE_FFTW)
00888 
00889 FloatComplexMatrix
00890 FloatMatrix::fourier (void) const
00891 {
00892   size_t nr = rows ();
00893   size_t nc = cols ();
00894 
00895   FloatComplexMatrix retval (nr, nc);
00896 
00897   size_t npts, nsamples;
00898 
00899   if (nr == 1 || nc == 1)
00900     {
00901       npts = nr > nc ? nr : nc;
00902       nsamples = 1;
00903     }
00904   else
00905     {
00906       npts = nr;
00907       nsamples = nc;
00908     }
00909 
00910   const float *in (fortran_vec ());
00911   FloatComplex *out (retval.fortran_vec ());
00912 
00913   octave_fftw::fft (in, out, npts, nsamples);
00914 
00915   return retval;
00916 }
00917 
00918 FloatComplexMatrix
00919 FloatMatrix::ifourier (void) const
00920 {
00921   size_t nr = rows ();
00922   size_t nc = cols ();
00923 
00924   FloatComplexMatrix retval (nr, nc);
00925 
00926   size_t npts, nsamples;
00927 
00928   if (nr == 1 || nc == 1)
00929     {
00930       npts = nr > nc ? nr : nc;
00931       nsamples = 1;
00932     }
00933   else
00934     {
00935       npts = nr;
00936       nsamples = nc;
00937     }
00938 
00939   FloatComplexMatrix tmp (*this);
00940   FloatComplex *in (tmp.fortran_vec ());
00941   FloatComplex *out (retval.fortran_vec ());
00942 
00943   octave_fftw::ifft (in, out, npts, nsamples);
00944 
00945   return retval;
00946 }
00947 
00948 FloatComplexMatrix
00949 FloatMatrix::fourier2d (void) const
00950 {
00951   dim_vector dv(rows (), cols ());
00952 
00953   const float *in = fortran_vec ();
00954   FloatComplexMatrix retval (rows (), cols ());
00955   octave_fftw::fftNd (in, retval.fortran_vec (), 2, dv);
00956 
00957   return retval;
00958 }
00959 
00960 FloatComplexMatrix
00961 FloatMatrix::ifourier2d (void) const
00962 {
00963   dim_vector dv(rows (), cols ());
00964 
00965   FloatComplexMatrix retval (*this);
00966   FloatComplex *out (retval.fortran_vec ());
00967 
00968   octave_fftw::ifftNd (out, out, 2, dv);
00969 
00970   return retval;
00971 }
00972 
00973 #else
00974 
00975 extern "C"
00976 {
00977   // Note that the original complex fft routines were not written for
00978   // float complex arguments.  They have been modified by adding an
00979   // implicit float precision (a-h,o-z) statement at the beginning of
00980   // each subroutine.
00981 
00982   F77_RET_T
00983   F77_FUNC (cffti, CFFTI) (const octave_idx_type&, FloatComplex*);
00984 
00985   F77_RET_T
00986   F77_FUNC (cfftf, CFFTF) (const octave_idx_type&, FloatComplex*, FloatComplex*);
00987 
00988   F77_RET_T
00989   F77_FUNC (cfftb, CFFTB) (const octave_idx_type&, FloatComplex*, FloatComplex*);
00990 }
00991 
00992 FloatComplexMatrix
00993 FloatMatrix::fourier (void) const
00994 {
00995   FloatComplexMatrix retval;
00996 
00997   octave_idx_type nr = rows ();
00998   octave_idx_type nc = cols ();
00999 
01000   octave_idx_type npts, nsamples;
01001 
01002   if (nr == 1 || nc == 1)
01003     {
01004       npts = nr > nc ? nr : nc;
01005       nsamples = 1;
01006     }
01007   else
01008     {
01009       npts = nr;
01010       nsamples = nc;
01011     }
01012 
01013   octave_idx_type nn = 4*npts+15;
01014 
01015   Array<FloatComplex> wsave (dim_vector (nn, 1));
01016   FloatComplex *pwsave = wsave.fortran_vec ();
01017 
01018   retval = FloatComplexMatrix (*this);
01019   FloatComplex *tmp_data = retval.fortran_vec ();
01020 
01021   F77_FUNC (cffti, CFFTI) (npts, pwsave);
01022 
01023   for (octave_idx_type j = 0; j < nsamples; j++)
01024     {
01025       octave_quit ();
01026 
01027       F77_FUNC (cfftf, CFFTF) (npts, &tmp_data[npts*j], pwsave);
01028     }
01029 
01030   return retval;
01031 }
01032 
01033 FloatComplexMatrix
01034 FloatMatrix::ifourier (void) const
01035 {
01036   FloatComplexMatrix retval;
01037 
01038   octave_idx_type nr = rows ();
01039   octave_idx_type nc = cols ();
01040 
01041   octave_idx_type npts, nsamples;
01042 
01043   if (nr == 1 || nc == 1)
01044     {
01045       npts = nr > nc ? nr : nc;
01046       nsamples = 1;
01047     }
01048   else
01049     {
01050       npts = nr;
01051       nsamples = nc;
01052     }
01053 
01054   octave_idx_type nn = 4*npts+15;
01055 
01056   Array<FloatComplex> wsave (dim_vector (nn, 1));
01057   FloatComplex *pwsave = wsave.fortran_vec ();
01058 
01059   retval = FloatComplexMatrix (*this);
01060   FloatComplex *tmp_data = retval.fortran_vec ();
01061 
01062   F77_FUNC (cffti, CFFTI) (npts, pwsave);
01063 
01064   for (octave_idx_type j = 0; j < nsamples; j++)
01065     {
01066       octave_quit ();
01067 
01068       F77_FUNC (cfftb, CFFTB) (npts, &tmp_data[npts*j], pwsave);
01069     }
01070 
01071   for (octave_idx_type j = 0; j < npts*nsamples; j++)
01072     tmp_data[j] = tmp_data[j] / static_cast<float> (npts);
01073 
01074   return retval;
01075 }
01076 
01077 FloatComplexMatrix
01078 FloatMatrix::fourier2d (void) const
01079 {
01080   FloatComplexMatrix retval;
01081 
01082   octave_idx_type nr = rows ();
01083   octave_idx_type nc = cols ();
01084 
01085   octave_idx_type npts, nsamples;
01086 
01087   if (nr == 1 || nc == 1)
01088     {
01089       npts = nr > nc ? nr : nc;
01090       nsamples = 1;
01091     }
01092   else
01093     {
01094       npts = nr;
01095       nsamples = nc;
01096     }
01097 
01098   octave_idx_type nn = 4*npts+15;
01099 
01100   Array<FloatComplex> wsave (dim_vector (nn, 1));
01101   FloatComplex *pwsave = wsave.fortran_vec ();
01102 
01103   retval = FloatComplexMatrix (*this);
01104   FloatComplex *tmp_data = retval.fortran_vec ();
01105 
01106   F77_FUNC (cffti, CFFTI) (npts, pwsave);
01107 
01108   for (octave_idx_type j = 0; j < nsamples; j++)
01109     {
01110       octave_quit ();
01111 
01112       F77_FUNC (cfftf, CFFTF) (npts, &tmp_data[npts*j], pwsave);
01113     }
01114 
01115   npts = nc;
01116   nsamples = nr;
01117   nn = 4*npts+15;
01118 
01119   wsave.resize (dim_vector (nn, 1));
01120   pwsave = wsave.fortran_vec ();
01121 
01122   Array<FloatComplex> tmp (dim_vector (npts, 1));
01123   FloatComplex *prow = tmp.fortran_vec ();
01124 
01125   F77_FUNC (cffti, CFFTI) (npts, pwsave);
01126 
01127   for (octave_idx_type j = 0; j < nsamples; j++)
01128     {
01129       octave_quit ();
01130 
01131       for (octave_idx_type i = 0; i < npts; i++)
01132         prow[i] = tmp_data[i*nr + j];
01133 
01134       F77_FUNC (cfftf, CFFTF) (npts, prow, pwsave);
01135 
01136       for (octave_idx_type i = 0; i < npts; i++)
01137         tmp_data[i*nr + j] = prow[i];
01138     }
01139 
01140   return retval;
01141 }
01142 
01143 FloatComplexMatrix
01144 FloatMatrix::ifourier2d (void) const
01145 {
01146   FloatComplexMatrix retval;
01147 
01148   octave_idx_type nr = rows ();
01149   octave_idx_type nc = cols ();
01150 
01151   octave_idx_type npts, nsamples;
01152 
01153   if (nr == 1 || nc == 1)
01154     {
01155       npts = nr > nc ? nr : nc;
01156       nsamples = 1;
01157     }
01158   else
01159     {
01160       npts = nr;
01161       nsamples = nc;
01162     }
01163 
01164   octave_idx_type nn = 4*npts+15;
01165 
01166   Array<FloatComplex> wsave (dim_vector (nn, 1));
01167   FloatComplex *pwsave = wsave.fortran_vec ();
01168 
01169   retval = FloatComplexMatrix (*this);
01170   FloatComplex *tmp_data = retval.fortran_vec ();
01171 
01172   F77_FUNC (cffti, CFFTI) (npts, pwsave);
01173 
01174   for (octave_idx_type j = 0; j < nsamples; j++)
01175     {
01176       octave_quit ();
01177 
01178       F77_FUNC (cfftb, CFFTB) (npts, &tmp_data[npts*j], pwsave);
01179     }
01180 
01181   for (octave_idx_type j = 0; j < npts*nsamples; j++)
01182     tmp_data[j] = tmp_data[j] / static_cast<float> (npts);
01183 
01184   npts = nc;
01185   nsamples = nr;
01186   nn = 4*npts+15;
01187 
01188   wsave.resize (dim_vector (nn, 1));
01189   pwsave = wsave.fortran_vec ();
01190 
01191   Array<FloatComplex> tmp (dim_vector (npts, 1));
01192   FloatComplex *prow = tmp.fortran_vec ();
01193 
01194   F77_FUNC (cffti, CFFTI) (npts, pwsave);
01195 
01196   for (octave_idx_type j = 0; j < nsamples; j++)
01197     {
01198       octave_quit ();
01199 
01200       for (octave_idx_type i = 0; i < npts; i++)
01201         prow[i] = tmp_data[i*nr + j];
01202 
01203       F77_FUNC (cfftb, CFFTB) (npts, prow, pwsave);
01204 
01205       for (octave_idx_type i = 0; i < npts; i++)
01206         tmp_data[i*nr + j] = prow[i] / static_cast<float> (npts);
01207     }
01208 
01209   return retval;
01210 }
01211 
01212 #endif
01213 
01214 FloatDET
01215 FloatMatrix::determinant (void) const
01216 {
01217   octave_idx_type info;
01218   float rcon;
01219   return determinant (info, rcon, 0);
01220 }
01221 
01222 FloatDET
01223 FloatMatrix::determinant (octave_idx_type& info) const
01224 {
01225   float rcon;
01226   return determinant (info, rcon, 0);
01227 }
01228 
01229 FloatDET
01230 FloatMatrix::determinant (octave_idx_type& info, float& rcon, int calc_cond) const
01231 {
01232   MatrixType mattype (*this);
01233   return determinant (mattype, info, rcon, calc_cond);
01234 }
01235 
01236 FloatDET
01237 FloatMatrix::determinant (MatrixType& mattype,
01238                           octave_idx_type& info, float& rcon, int calc_cond) const
01239 {
01240   FloatDET retval (1.0);
01241 
01242   info = 0;
01243   rcon = 0.0;
01244 
01245   octave_idx_type nr = rows ();
01246   octave_idx_type nc = cols ();
01247 
01248   if (nr != nc)
01249     (*current_liboctave_error_handler) ("matrix must be square");
01250   else
01251     {
01252       volatile int typ = mattype.type ();
01253 
01254       // Even though the matrix is marked as singular (Rectangular), we may
01255       // still get a useful number from the LU factorization, because it always
01256       // completes.
01257 
01258       if (typ == MatrixType::Unknown)
01259         typ = mattype.type (*this);
01260       else if (typ == MatrixType::Rectangular)
01261         typ = MatrixType::Full;
01262 
01263       if (typ == MatrixType::Lower || typ == MatrixType::Upper)
01264         {
01265           for (octave_idx_type i = 0; i < nc; i++)
01266             retval *= elem (i,i);
01267         }
01268       else if (typ == MatrixType::Hermitian)
01269         {
01270           FloatMatrix atmp = *this;
01271           float *tmp_data = atmp.fortran_vec ();
01272 
01273           float anorm = 0;
01274           if (calc_cond) anorm = xnorm (*this, 1);
01275 
01276 
01277           char job = 'L';
01278           F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
01279                                      tmp_data, nr, info
01280                                      F77_CHAR_ARG_LEN (1)));
01281 
01282           if (info != 0)
01283             {
01284               rcon = 0.0;
01285               mattype.mark_as_unsymmetric ();
01286               typ = MatrixType::Full;
01287             }
01288           else
01289             {
01290               Array<float> z (dim_vector (3 * nc, 1));
01291               float *pz = z.fortran_vec ();
01292               Array<octave_idx_type> iz (dim_vector (nc, 1));
01293               octave_idx_type *piz = iz.fortran_vec ();
01294 
01295               F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
01296                                          nr, tmp_data, nr, anorm,
01297                                          rcon, pz, piz, info
01298                                          F77_CHAR_ARG_LEN (1)));
01299 
01300               if (info != 0)
01301                 rcon = 0.0;
01302 
01303               for (octave_idx_type i = 0; i < nc; i++)
01304                 retval *= atmp (i,i);
01305 
01306               retval = retval.square ();
01307             }
01308         }
01309       else if (typ != MatrixType::Full)
01310         (*current_liboctave_error_handler) ("det: invalid dense matrix type");
01311 
01312       if (typ == MatrixType::Full)
01313         {
01314           Array<octave_idx_type> ipvt (dim_vector (nr, 1));
01315           octave_idx_type *pipvt = ipvt.fortran_vec ();
01316 
01317           FloatMatrix atmp = *this;
01318           float *tmp_data = atmp.fortran_vec ();
01319 
01320           info = 0;
01321 
01322           // Calculate the norm of the matrix, for later use.
01323           float anorm = 0;
01324           if (calc_cond) anorm = xnorm (*this, 1);
01325 
01326           F77_XFCN (sgetrf, SGETRF, (nr, nr, tmp_data, nr, pipvt, info));
01327 
01328           // Throw-away extra info LAPACK gives so as to not change output.
01329           rcon = 0.0;
01330           if (info != 0)
01331             {
01332               info = -1;
01333               retval = FloatDET ();
01334             }
01335           else
01336             {
01337               if (calc_cond)
01338                 {
01339                   // Now calc the condition number for non-singular matrix.
01340                   char job = '1';
01341                   Array<float> z (dim_vector (4 * nc, 1));
01342                   float *pz = z.fortran_vec ();
01343                   Array<octave_idx_type> iz (dim_vector (nc, 1));
01344                   octave_idx_type *piz = iz.fortran_vec ();
01345 
01346                   F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
01347                                              nc, tmp_data, nr, anorm,
01348                                              rcon, pz, piz, info
01349                                              F77_CHAR_ARG_LEN (1)));
01350                 }
01351 
01352               if (info != 0)
01353                 {
01354                   info = -1;
01355                   retval = FloatDET ();
01356                 }
01357               else
01358                 {
01359                   for (octave_idx_type i = 0; i < nc; i++)
01360                     {
01361                       float c = atmp(i,i);
01362                       retval *= (ipvt(i) != (i+1)) ? -c : c;
01363                     }
01364                 }
01365             }
01366         }
01367     }
01368 
01369   return retval;
01370 }
01371 
01372 float
01373 FloatMatrix::rcond (void) const
01374 {
01375   MatrixType mattype (*this);
01376   return rcond (mattype);
01377 }
01378 
01379 float
01380 FloatMatrix::rcond (MatrixType &mattype) const
01381 {
01382   float rcon;
01383   octave_idx_type nr = rows ();
01384   octave_idx_type nc = cols ();
01385 
01386   if (nr != nc)
01387     (*current_liboctave_error_handler) ("matrix must be square");
01388   else if (nr == 0 || nc == 0)
01389     rcon = octave_Inf;
01390   else
01391     {
01392       int typ = mattype.type ();
01393 
01394       if (typ == MatrixType::Unknown)
01395         typ = mattype.type (*this);
01396 
01397       // Only calculate the condition number for LU/Cholesky
01398       if (typ == MatrixType::Upper)
01399         {
01400           const float *tmp_data = fortran_vec ();
01401           octave_idx_type info = 0;
01402           char norm = '1';
01403           char uplo = 'U';
01404           char dia = 'N';
01405 
01406           Array<float> z (dim_vector (3 * nc, 1));
01407           float *pz = z.fortran_vec ();
01408           Array<octave_idx_type> iz (dim_vector (nc, 1));
01409           octave_idx_type *piz = iz.fortran_vec ();
01410 
01411           F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
01412                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
01413                                      F77_CONST_CHAR_ARG2 (&dia, 1),
01414                                      nr, tmp_data, nr, rcon,
01415                                      pz, piz, info
01416                                      F77_CHAR_ARG_LEN (1)
01417                                      F77_CHAR_ARG_LEN (1)
01418                                      F77_CHAR_ARG_LEN (1)));
01419 
01420           if (info != 0)
01421             rcon = 0.0;
01422         }
01423       else if  (typ == MatrixType::Permuted_Upper)
01424         (*current_liboctave_error_handler)
01425           ("permuted triangular matrix not implemented");
01426       else if (typ == MatrixType::Lower)
01427         {
01428           const float *tmp_data = fortran_vec ();
01429           octave_idx_type info = 0;
01430           char norm = '1';
01431           char uplo = 'L';
01432           char dia = 'N';
01433 
01434           Array<float> z (dim_vector (3 * nc, 1));
01435           float *pz = z.fortran_vec ();
01436           Array<octave_idx_type> iz (dim_vector (nc, 1));
01437           octave_idx_type *piz = iz.fortran_vec ();
01438 
01439           F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
01440                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
01441                                      F77_CONST_CHAR_ARG2 (&dia, 1),
01442                                      nr, tmp_data, nr, rcon,
01443                                      pz, piz, info
01444                                      F77_CHAR_ARG_LEN (1)
01445                                      F77_CHAR_ARG_LEN (1)
01446                                      F77_CHAR_ARG_LEN (1)));
01447 
01448           if (info != 0)
01449             rcon = 0.0;
01450         }
01451       else if (typ == MatrixType::Permuted_Lower)
01452         (*current_liboctave_error_handler)
01453           ("permuted triangular matrix not implemented");
01454       else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
01455         {
01456           float anorm = -1.0;
01457 
01458           if (typ == MatrixType::Hermitian)
01459             {
01460               octave_idx_type info = 0;
01461               char job = 'L';
01462 
01463               FloatMatrix atmp = *this;
01464               float *tmp_data = atmp.fortran_vec ();
01465 
01466               anorm = atmp.abs().sum().
01467                 row(static_cast<octave_idx_type>(0)).max();
01468 
01469               F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
01470                                          tmp_data, nr, info
01471                                          F77_CHAR_ARG_LEN (1)));
01472 
01473               if (info != 0)
01474                 {
01475                   rcon = 0.0;
01476                   mattype.mark_as_unsymmetric ();
01477                   typ = MatrixType::Full;
01478                 }
01479               else
01480                 {
01481                   Array<float> z (dim_vector (3 * nc, 1));
01482                   float *pz = z.fortran_vec ();
01483                   Array<octave_idx_type> iz (dim_vector (nc, 1));
01484                   octave_idx_type *piz = iz.fortran_vec ();
01485 
01486                   F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
01487                                              nr, tmp_data, nr, anorm,
01488                                              rcon, pz, piz, info
01489                                              F77_CHAR_ARG_LEN (1)));
01490 
01491                   if (info != 0)
01492                     rcon = 0.0;
01493                 }
01494             }
01495 
01496           if (typ == MatrixType::Full)
01497             {
01498               octave_idx_type info = 0;
01499 
01500               FloatMatrix atmp = *this;
01501               float *tmp_data = atmp.fortran_vec ();
01502 
01503               Array<octave_idx_type> ipvt (dim_vector (nr, 1));
01504               octave_idx_type *pipvt = ipvt.fortran_vec ();
01505 
01506               if(anorm < 0.)
01507                 anorm = atmp.abs().sum().
01508                   row(static_cast<octave_idx_type>(0)).max();
01509 
01510               Array<float> z (dim_vector (4 * nc, 1));
01511               float *pz = z.fortran_vec ();
01512               Array<octave_idx_type> iz (dim_vector (nc, 1));
01513               octave_idx_type *piz = iz.fortran_vec ();
01514 
01515               F77_XFCN (sgetrf, SGETRF, (nr, nr, tmp_data, nr, pipvt, info));
01516 
01517               if (info != 0)
01518                 {
01519                   rcon = 0.0;
01520                   mattype.mark_as_rectangular ();
01521                 }
01522               else
01523                 {
01524                   char job = '1';
01525                   F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
01526                                              nc, tmp_data, nr, anorm,
01527                                              rcon, pz, piz, info
01528                                              F77_CHAR_ARG_LEN (1)));
01529 
01530                   if (info != 0)
01531                     rcon = 0.0;
01532                 }
01533             }
01534         }
01535       else
01536         rcon = 0.0;
01537     }
01538 
01539   return rcon;
01540 }
01541 
01542 FloatMatrix
01543 FloatMatrix::utsolve (MatrixType &mattype, const FloatMatrix& b, octave_idx_type& info,
01544                 float& rcon, solve_singularity_handler sing_handler,
01545                 bool calc_cond, blas_trans_type transt) const
01546 {
01547   FloatMatrix retval;
01548 
01549   octave_idx_type nr = rows ();
01550   octave_idx_type nc = cols ();
01551 
01552   if (nr != b.rows ())
01553     (*current_liboctave_error_handler)
01554       ("matrix dimension mismatch solution of linear equations");
01555   else if (nr == 0 || nc == 0 || b.cols () == 0)
01556     retval = FloatMatrix (nc, b.cols (), 0.0);
01557   else
01558     {
01559       volatile int typ = mattype.type ();
01560 
01561       if (typ == MatrixType::Permuted_Upper ||
01562           typ == MatrixType::Upper)
01563         {
01564           octave_idx_type b_nc = b.cols ();
01565           rcon = 1.;
01566           info = 0;
01567 
01568           if (typ == MatrixType::Permuted_Upper)
01569             {
01570               (*current_liboctave_error_handler)
01571                 ("permuted triangular matrix not implemented");
01572             }
01573           else
01574             {
01575               const float *tmp_data = fortran_vec ();
01576 
01577               if (calc_cond)
01578                 {
01579                   char norm = '1';
01580                   char uplo = 'U';
01581                   char dia = 'N';
01582 
01583                   Array<float> z (dim_vector (3 * nc, 1));
01584                   float *pz = z.fortran_vec ();
01585                   Array<octave_idx_type> iz (dim_vector (nc, 1));
01586                   octave_idx_type *piz = iz.fortran_vec ();
01587 
01588                   F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
01589                                              F77_CONST_CHAR_ARG2 (&uplo, 1),
01590                                              F77_CONST_CHAR_ARG2 (&dia, 1),
01591                                              nr, tmp_data, nr, rcon,
01592                                              pz, piz, info
01593                                              F77_CHAR_ARG_LEN (1)
01594                                              F77_CHAR_ARG_LEN (1)
01595                                              F77_CHAR_ARG_LEN (1)));
01596 
01597                   if (info != 0)
01598                     info = -2;
01599 
01600                   volatile float rcond_plus_one = rcon + 1.0;
01601 
01602                   if (rcond_plus_one == 1.0 || xisnan (rcon))
01603                     {
01604                       info = -2;
01605 
01606                       if (sing_handler)
01607                         sing_handler (rcon);
01608                       else
01609                         (*current_liboctave_error_handler)
01610                           ("matrix singular to machine precision, rcond = %g",
01611                            rcon);
01612                     }
01613                 }
01614 
01615               if (info == 0)
01616                 {
01617                   retval = b;
01618                   float *result = retval.fortran_vec ();
01619 
01620                   char uplo = 'U';
01621                   char trans = get_blas_char (transt);
01622                   char dia = 'N';
01623 
01624                   F77_XFCN (strtrs, STRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
01625                                              F77_CONST_CHAR_ARG2 (&trans, 1),
01626                                              F77_CONST_CHAR_ARG2 (&dia, 1),
01627                                              nr, b_nc, tmp_data, nr,
01628                                              result, nr, info
01629                                              F77_CHAR_ARG_LEN (1)
01630                                              F77_CHAR_ARG_LEN (1)
01631                                              F77_CHAR_ARG_LEN (1)));
01632                 }
01633             }
01634         }
01635       else
01636         (*current_liboctave_error_handler) ("incorrect matrix type");
01637     }
01638 
01639   return retval;
01640 }
01641 
01642 FloatMatrix
01643 FloatMatrix::ltsolve (MatrixType &mattype, const FloatMatrix& b, octave_idx_type& info,
01644                 float& rcon, solve_singularity_handler sing_handler,
01645                 bool calc_cond, blas_trans_type transt) const
01646 {
01647   FloatMatrix retval;
01648 
01649   octave_idx_type nr = rows ();
01650   octave_idx_type nc = cols ();
01651 
01652   if (nr != b.rows ())
01653     (*current_liboctave_error_handler)
01654       ("matrix dimension mismatch solution of linear equations");
01655   else if (nr == 0 || nc == 0 || b.cols () == 0)
01656     retval = FloatMatrix (nc, b.cols (), 0.0);
01657   else
01658     {
01659       volatile int typ = mattype.type ();
01660 
01661       if (typ == MatrixType::Permuted_Lower ||
01662           typ == MatrixType::Lower)
01663         {
01664           octave_idx_type b_nc = b.cols ();
01665           rcon = 1.;
01666           info = 0;
01667 
01668           if (typ == MatrixType::Permuted_Lower)
01669             {
01670               (*current_liboctave_error_handler)
01671                 ("permuted triangular matrix not implemented");
01672             }
01673           else
01674             {
01675               const float *tmp_data = fortran_vec ();
01676 
01677               if (calc_cond)
01678                 {
01679                   char norm = '1';
01680                   char uplo = 'L';
01681                   char dia = 'N';
01682 
01683                   Array<float> z (dim_vector (3 * nc, 1));
01684                   float *pz = z.fortran_vec ();
01685                   Array<octave_idx_type> iz (dim_vector (nc, 1));
01686                   octave_idx_type *piz = iz.fortran_vec ();
01687 
01688                   F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
01689                                              F77_CONST_CHAR_ARG2 (&uplo, 1),
01690                                              F77_CONST_CHAR_ARG2 (&dia, 1),
01691                                              nr, tmp_data, nr, rcon,
01692                                              pz, piz, info
01693                                              F77_CHAR_ARG_LEN (1)
01694                                              F77_CHAR_ARG_LEN (1)
01695                                              F77_CHAR_ARG_LEN (1)));
01696 
01697                   if (info != 0)
01698                     info = -2;
01699 
01700                   volatile float rcond_plus_one = rcon + 1.0;
01701 
01702                   if (rcond_plus_one == 1.0 || xisnan (rcon))
01703                     {
01704                       info = -2;
01705 
01706                       if (sing_handler)
01707                         sing_handler (rcon);
01708                       else
01709                         (*current_liboctave_error_handler)
01710                           ("matrix singular to machine precision, rcond = %g",
01711                            rcon);
01712                     }
01713                 }
01714 
01715               if (info == 0)
01716                 {
01717                   retval = b;
01718                   float *result = retval.fortran_vec ();
01719 
01720                   char uplo = 'L';
01721                   char trans = get_blas_char (transt);
01722                   char dia = 'N';
01723 
01724                   F77_XFCN (strtrs, STRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
01725                                              F77_CONST_CHAR_ARG2 (&trans, 1),
01726                                              F77_CONST_CHAR_ARG2 (&dia, 1),
01727                                              nr, b_nc, tmp_data, nr,
01728                                              result, nr, info
01729                                              F77_CHAR_ARG_LEN (1)
01730                                              F77_CHAR_ARG_LEN (1)
01731                                              F77_CHAR_ARG_LEN (1)));
01732                 }
01733             }
01734         }
01735       else
01736         (*current_liboctave_error_handler) ("incorrect matrix type");
01737     }
01738 
01739   return retval;
01740 }
01741 
01742 FloatMatrix
01743 FloatMatrix::fsolve (MatrixType &mattype, const FloatMatrix& b, octave_idx_type& info,
01744                 float& rcon, solve_singularity_handler sing_handler,
01745                 bool calc_cond) const
01746 {
01747   FloatMatrix retval;
01748 
01749   octave_idx_type nr = rows ();
01750   octave_idx_type nc = cols ();
01751 
01752   if (nr != nc || nr != b.rows ())
01753     (*current_liboctave_error_handler)
01754       ("matrix dimension mismatch solution of linear equations");
01755   else if (nr == 0 || b.cols () == 0)
01756     retval = FloatMatrix (nc, b.cols (), 0.0);
01757   else
01758     {
01759       volatile int typ = mattype.type ();
01760 
01761      // Calculate the norm of the matrix, for later use.
01762       float anorm = -1.;
01763 
01764       if (typ == MatrixType::Hermitian)
01765         {
01766           info = 0;
01767           char job = 'L';
01768 
01769           FloatMatrix atmp = *this;
01770           float *tmp_data = atmp.fortran_vec ();
01771 
01772           anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max();
01773 
01774           F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
01775                                      tmp_data, nr, info
01776                                      F77_CHAR_ARG_LEN (1)));
01777 
01778           // Throw-away extra info LAPACK gives so as to not change output.
01779           rcon = 0.0;
01780           if (info != 0)
01781             {
01782               info = -2;
01783 
01784               mattype.mark_as_unsymmetric ();
01785               typ = MatrixType::Full;
01786             }
01787           else
01788             {
01789               if (calc_cond)
01790                 {
01791                   Array<float> z (dim_vector (3 * nc, 1));
01792                   float *pz = z.fortran_vec ();
01793                   Array<octave_idx_type> iz (dim_vector (nc, 1));
01794                   octave_idx_type *piz = iz.fortran_vec ();
01795 
01796                   F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
01797                                              nr, tmp_data, nr, anorm,
01798                                              rcon, pz, piz, info
01799                                              F77_CHAR_ARG_LEN (1)));
01800 
01801                   if (info != 0)
01802                     info = -2;
01803 
01804                   volatile float rcond_plus_one = rcon + 1.0;
01805 
01806                   if (rcond_plus_one == 1.0 || xisnan (rcon))
01807                     {
01808                       info = -2;
01809 
01810                       if (sing_handler)
01811                         sing_handler (rcon);
01812                       else
01813                         (*current_liboctave_error_handler)
01814                           ("matrix singular to machine precision, rcond = %g",
01815                            rcon);
01816                     }
01817                 }
01818 
01819               if (info == 0)
01820                 {
01821                   retval = b;
01822                   float *result = retval.fortran_vec ();
01823 
01824                   octave_idx_type b_nc = b.cols ();
01825 
01826                   F77_XFCN (spotrs, SPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),
01827                                              nr, b_nc, tmp_data, nr,
01828                                              result, b.rows(), info
01829                                              F77_CHAR_ARG_LEN (1)));
01830                 }
01831               else
01832                 {
01833                   mattype.mark_as_unsymmetric ();
01834                   typ = MatrixType::Full;
01835                 }
01836             }
01837         }
01838 
01839       if (typ == MatrixType::Full)
01840         {
01841           info = 0;
01842 
01843           Array<octave_idx_type> ipvt (dim_vector (nr, 1));
01844           octave_idx_type *pipvt = ipvt.fortran_vec ();
01845 
01846           FloatMatrix atmp = *this;
01847           float *tmp_data = atmp.fortran_vec ();
01848 
01849           if(anorm < 0.)
01850             anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max();
01851 
01852           Array<float> z (dim_vector (4 * nc, 1));
01853           float *pz = z.fortran_vec ();
01854           Array<octave_idx_type> iz (dim_vector (nc, 1));
01855           octave_idx_type *piz = iz.fortran_vec ();
01856 
01857           F77_XFCN (sgetrf, SGETRF, (nr, nr, tmp_data, nr, pipvt, info));
01858 
01859           // Throw-away extra info LAPACK gives so as to not change output.
01860           rcon = 0.0;
01861           if (info != 0)
01862             {
01863               info = -2;
01864 
01865               if (sing_handler)
01866                 sing_handler (rcon);
01867               else
01868                 (*current_liboctave_error_handler)
01869                   ("matrix singular to machine precision");
01870 
01871               mattype.mark_as_rectangular ();
01872             }
01873           else
01874             {
01875               if (calc_cond)
01876                 {
01877                   // Now calculate the condition number for
01878                   // non-singular matrix.
01879                   char job = '1';
01880                   F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
01881                                              nc, tmp_data, nr, anorm,
01882                                              rcon, pz, piz, info
01883                                              F77_CHAR_ARG_LEN (1)));
01884 
01885                   if (info != 0)
01886                     info = -2;
01887 
01888                   volatile float rcond_plus_one = rcon + 1.0;
01889 
01890                   if (rcond_plus_one == 1.0 || xisnan (rcon))
01891                     {
01892                       info = -2;
01893 
01894                       if (sing_handler)
01895                         sing_handler (rcon);
01896                       else
01897                         (*current_liboctave_error_handler)
01898                           ("matrix singular to machine precision, rcond = %g",
01899                            rcon);
01900                     }
01901                 }
01902 
01903               if (info == 0)
01904                 {
01905                   retval = b;
01906                   float *result = retval.fortran_vec ();
01907 
01908                   octave_idx_type b_nc = b.cols ();
01909 
01910                   char job = 'N';
01911                   F77_XFCN (sgetrs, SGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),
01912                                              nr, b_nc, tmp_data, nr,
01913                                              pipvt, result, b.rows(), info
01914                                              F77_CHAR_ARG_LEN (1)));
01915                 }
01916               else
01917                 mattype.mark_as_rectangular ();
01918             }
01919         }
01920       else if (typ != MatrixType::Hermitian)
01921         (*current_liboctave_error_handler) ("incorrect matrix type");
01922     }
01923 
01924   return retval;
01925 }
01926 
01927 FloatMatrix
01928 FloatMatrix::solve (MatrixType &typ, const FloatMatrix& b) const
01929 {
01930   octave_idx_type info;
01931   float rcon;
01932   return solve (typ, b, info, rcon, 0);
01933 }
01934 
01935 FloatMatrix
01936 FloatMatrix::solve (MatrixType &typ, const FloatMatrix& b, octave_idx_type& info) const
01937 {
01938   float rcon;
01939   return solve (typ, b, info, rcon, 0);
01940 }
01941 
01942 FloatMatrix
01943 FloatMatrix::solve (MatrixType &typ, const FloatMatrix& b, octave_idx_type& info,
01944                float& rcon) const
01945 {
01946   return solve (typ, b, info, rcon, 0);
01947 }
01948 
01949 FloatMatrix
01950 FloatMatrix::solve (MatrixType &mattype, const FloatMatrix& b, octave_idx_type& info,
01951                float& rcon, solve_singularity_handler sing_handler,
01952                bool singular_fallback, blas_trans_type transt) const
01953 {
01954   FloatMatrix retval;
01955   int typ = mattype.type ();
01956 
01957   if (typ == MatrixType::Unknown)
01958     typ = mattype.type (*this);
01959 
01960   // Only calculate the condition number for LU/Cholesky
01961   if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
01962     retval = utsolve (mattype, b, info, rcon, sing_handler, false, transt);
01963   else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
01964     retval = ltsolve (mattype, b, info, rcon, sing_handler, false, transt);
01965   else if (transt == blas_trans || transt == blas_conj_trans)
01966     return transpose ().solve (mattype, b, info, rcon, sing_handler, singular_fallback);
01967   else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
01968     retval = fsolve (mattype, b, info, rcon, sing_handler, true);
01969   else if (typ != MatrixType::Rectangular)
01970     {
01971       (*current_liboctave_error_handler) ("unknown matrix type");
01972       return FloatMatrix ();
01973     }
01974 
01975   // Rectangular or one of the above solvers flags a singular matrix
01976   if (singular_fallback && mattype.type () == MatrixType::Rectangular)
01977     {
01978       octave_idx_type rank;
01979       retval = lssolve (b, info, rank, rcon);
01980     }
01981 
01982   return retval;
01983 }
01984 
01985 FloatComplexMatrix
01986 FloatMatrix::solve (MatrixType &typ, const FloatComplexMatrix& b) const
01987 {
01988   octave_idx_type info;
01989   float rcon;
01990   return solve (typ, b, info, rcon, 0);
01991 }
01992 
01993 FloatComplexMatrix
01994 FloatMatrix::solve (MatrixType &typ, const FloatComplexMatrix& b,
01995   octave_idx_type& info) const
01996 {
01997   float rcon;
01998   return solve (typ, b, info, rcon, 0);
01999 }
02000 
02001 FloatComplexMatrix
02002 FloatMatrix::solve (MatrixType &typ, const FloatComplexMatrix& b, octave_idx_type& info,
02003                float& rcon) const
02004 {
02005   return solve (typ, b, info, rcon, 0);
02006 }
02007 
02008 static FloatMatrix
02009 stack_complex_matrix (const FloatComplexMatrix& cm)
02010 {
02011   octave_idx_type m = cm.rows (), n = cm.cols (), nel = m*n;
02012   FloatMatrix retval (m, 2*n);
02013   const FloatComplex *cmd = cm.data ();
02014   float *rd = retval.fortran_vec ();
02015   for (octave_idx_type i = 0; i < nel; i++)
02016     {
02017       rd[i] = std::real (cmd[i]);
02018       rd[nel+i] = std::imag (cmd[i]);
02019     }
02020   return retval;
02021 }
02022 
02023 static FloatComplexMatrix
02024 unstack_complex_matrix (const FloatMatrix& sm)
02025 {
02026   octave_idx_type m = sm.rows (), n = sm.cols () / 2, nel = m*n;
02027   FloatComplexMatrix retval (m, n);
02028   const float *smd = sm.data ();
02029   FloatComplex *rd = retval.fortran_vec ();
02030   for (octave_idx_type i = 0; i < nel; i++)
02031     rd[i] = FloatComplex (smd[i], smd[nel+i]);
02032   return retval;
02033 }
02034 
02035 FloatComplexMatrix
02036 FloatMatrix::solve (MatrixType &typ, const FloatComplexMatrix& b, octave_idx_type& info,
02037                float& rcon, solve_singularity_handler sing_handler,
02038                bool singular_fallback, blas_trans_type transt) const
02039 {
02040   FloatMatrix tmp = stack_complex_matrix (b);
02041   tmp = solve (typ, tmp, info, rcon, sing_handler, singular_fallback, transt);
02042   return unstack_complex_matrix (tmp);
02043 }
02044 
02045 FloatColumnVector
02046 FloatMatrix::solve (MatrixType &typ, const FloatColumnVector& b) const
02047 {
02048   octave_idx_type info; float rcon;
02049   return solve (typ, b, info, rcon);
02050 }
02051 
02052 FloatColumnVector
02053 FloatMatrix::solve (MatrixType &typ, const FloatColumnVector& b,
02054                octave_idx_type& info) const
02055 {
02056   float rcon;
02057   return solve (typ, b, info, rcon);
02058 }
02059 
02060 FloatColumnVector
02061 FloatMatrix::solve (MatrixType &typ, const FloatColumnVector& b, octave_idx_type& info,
02062                float& rcon) const
02063 {
02064   return solve (typ, b, info, rcon, 0);
02065 }
02066 
02067 FloatColumnVector
02068 FloatMatrix::solve (MatrixType &typ, const FloatColumnVector& b, octave_idx_type& info,
02069                float& rcon, solve_singularity_handler sing_handler, blas_trans_type transt) const
02070 {
02071   FloatMatrix tmp (b);
02072   tmp = solve (typ, tmp, info, rcon, sing_handler, true, transt);
02073   return tmp.column(static_cast<octave_idx_type> (0));
02074 }
02075 
02076 FloatComplexColumnVector
02077 FloatMatrix::solve (MatrixType &typ, const FloatComplexColumnVector& b) const
02078 {
02079   FloatComplexMatrix tmp (*this);
02080   return tmp.solve (typ, b);
02081 }
02082 
02083 FloatComplexColumnVector
02084 FloatMatrix::solve (MatrixType &typ, const FloatComplexColumnVector& b,
02085                octave_idx_type& info) const
02086 {
02087   FloatComplexMatrix tmp (*this);
02088   return tmp.solve (typ, b, info);
02089 }
02090 
02091 FloatComplexColumnVector
02092 FloatMatrix::solve (MatrixType &typ, const FloatComplexColumnVector& b,
02093                octave_idx_type& info, float& rcon) const
02094 {
02095   FloatComplexMatrix tmp (*this);
02096   return tmp.solve (typ, b, info, rcon);
02097 }
02098 
02099 FloatComplexColumnVector
02100 FloatMatrix::solve (MatrixType &typ, const FloatComplexColumnVector& b,
02101                octave_idx_type& info, float& rcon,
02102                solve_singularity_handler sing_handler, blas_trans_type transt) const
02103 {
02104   FloatComplexMatrix tmp (*this);
02105   return tmp.solve(typ, b, info, rcon, sing_handler, transt);
02106 }
02107 
02108 FloatMatrix
02109 FloatMatrix::solve (const FloatMatrix& b) const
02110 {
02111   octave_idx_type info;
02112   float rcon;
02113   return solve (b, info, rcon, 0);
02114 }
02115 
02116 FloatMatrix
02117 FloatMatrix::solve (const FloatMatrix& b, octave_idx_type& info) const
02118 {
02119   float rcon;
02120   return solve (b, info, rcon, 0);
02121 }
02122 
02123 FloatMatrix
02124 FloatMatrix::solve (const FloatMatrix& b, octave_idx_type& info, float& rcon) const
02125 {
02126   return solve (b, info, rcon, 0);
02127 }
02128 
02129 FloatMatrix
02130 FloatMatrix::solve (const FloatMatrix& b, octave_idx_type& info,
02131                float& rcon, solve_singularity_handler sing_handler, blas_trans_type transt) const
02132 {
02133   MatrixType mattype (*this);
02134   return solve (mattype, b, info, rcon, sing_handler, true, transt);
02135 }
02136 
02137 FloatComplexMatrix
02138 FloatMatrix::solve (const FloatComplexMatrix& b) const
02139 {
02140   FloatComplexMatrix tmp (*this);
02141   return tmp.solve (b);
02142 }
02143 
02144 FloatComplexMatrix
02145 FloatMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info) const
02146 {
02147   FloatComplexMatrix tmp (*this);
02148   return tmp.solve (b, info);
02149 }
02150 
02151 FloatComplexMatrix
02152 FloatMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info, float& rcon) const
02153 {
02154   FloatComplexMatrix tmp (*this);
02155   return tmp.solve (b, info, rcon);
02156 }
02157 
02158 FloatComplexMatrix
02159 FloatMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info, float& rcon,
02160                solve_singularity_handler sing_handler, blas_trans_type transt) const
02161 {
02162   FloatComplexMatrix tmp (*this);
02163   return tmp.solve (b, info, rcon, sing_handler, transt);
02164 }
02165 
02166 FloatColumnVector
02167 FloatMatrix::solve (const FloatColumnVector& b) const
02168 {
02169   octave_idx_type info; float rcon;
02170   return solve (b, info, rcon);
02171 }
02172 
02173 FloatColumnVector
02174 FloatMatrix::solve (const FloatColumnVector& b, octave_idx_type& info) const
02175 {
02176   float rcon;
02177   return solve (b, info, rcon);
02178 }
02179 
02180 FloatColumnVector
02181 FloatMatrix::solve (const FloatColumnVector& b, octave_idx_type& info, float& rcon) const
02182 {
02183   return solve (b, info, rcon, 0);
02184 }
02185 
02186 FloatColumnVector
02187 FloatMatrix::solve (const FloatColumnVector& b, octave_idx_type& info, float& rcon,
02188                solve_singularity_handler sing_handler, blas_trans_type transt) const
02189 {
02190   MatrixType mattype (*this);
02191   return solve (mattype, b, info, rcon, sing_handler, transt);
02192 }
02193 
02194 FloatComplexColumnVector
02195 FloatMatrix::solve (const FloatComplexColumnVector& b) const
02196 {
02197   FloatComplexMatrix tmp (*this);
02198   return tmp.solve (b);
02199 }
02200 
02201 FloatComplexColumnVector
02202 FloatMatrix::solve (const FloatComplexColumnVector& b, octave_idx_type& info) const
02203 {
02204   FloatComplexMatrix tmp (*this);
02205   return tmp.solve (b, info);
02206 }
02207 
02208 FloatComplexColumnVector
02209 FloatMatrix::solve (const FloatComplexColumnVector& b, octave_idx_type& info, float& rcon) const
02210 {
02211   FloatComplexMatrix tmp (*this);
02212   return tmp.solve (b, info, rcon);
02213 }
02214 
02215 FloatComplexColumnVector
02216 FloatMatrix::solve (const FloatComplexColumnVector& b, octave_idx_type& info, float& rcon,
02217                solve_singularity_handler sing_handler, blas_trans_type transt) const
02218 {
02219   FloatComplexMatrix tmp (*this);
02220   return tmp.solve (b, info, rcon, sing_handler, transt);
02221 }
02222 
02223 FloatMatrix
02224 FloatMatrix::lssolve (const FloatMatrix& b) const
02225 {
02226   octave_idx_type info;
02227   octave_idx_type rank;
02228   float rcon;
02229   return lssolve (b, info, rank, rcon);
02230 }
02231 
02232 FloatMatrix
02233 FloatMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info) const
02234 {
02235   octave_idx_type rank;
02236   float rcon;
02237   return lssolve (b, info, rank, rcon);
02238 }
02239 
02240 FloatMatrix
02241 FloatMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info,
02242                  octave_idx_type& rank) const
02243 {
02244   float rcon;
02245   return lssolve (b, info, rank, rcon);
02246 }
02247 
02248 FloatMatrix
02249 FloatMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info,
02250                  octave_idx_type& rank, float &rcon) const
02251 {
02252   FloatMatrix retval;
02253 
02254   octave_idx_type nrhs = b.cols ();
02255 
02256   octave_idx_type m = rows ();
02257   octave_idx_type n = cols ();
02258 
02259   if (m != b.rows ())
02260     (*current_liboctave_error_handler)
02261       ("matrix dimension mismatch solution of linear equations");
02262   else if (m == 0 || n == 0 || b.cols () == 0)
02263     retval = FloatMatrix (n, b.cols (), 0.0);
02264   else
02265     {
02266       volatile octave_idx_type minmn = (m < n ? m : n);
02267       octave_idx_type maxmn = m > n ? m : n;
02268       rcon = -1.0;
02269       if (m != n)
02270         {
02271           retval = FloatMatrix (maxmn, nrhs, 0.0);
02272 
02273           for (octave_idx_type j = 0; j < nrhs; j++)
02274             for (octave_idx_type i = 0; i < m; i++)
02275               retval.elem (i, j) = b.elem (i, j);
02276         }
02277       else
02278         retval = b;
02279 
02280       FloatMatrix atmp = *this;
02281       float *tmp_data = atmp.fortran_vec ();
02282 
02283       float *pretval = retval.fortran_vec ();
02284       Array<float> s (dim_vector (minmn, 1));
02285       float *ps = s.fortran_vec ();
02286 
02287       // Ask DGELSD what the dimension of WORK should be.
02288       octave_idx_type lwork = -1;
02289 
02290       Array<float> work (dim_vector (1, 1));
02291 
02292       octave_idx_type smlsiz;
02293       F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("SGELSD", 6),
02294                                    F77_CONST_CHAR_ARG2 (" ", 1),
02295                                    0, 0, 0, 0, smlsiz
02296                                    F77_CHAR_ARG_LEN (6)
02297                                    F77_CHAR_ARG_LEN (1));
02298 
02299       octave_idx_type mnthr;
02300       F77_FUNC (xilaenv, XILAENV) (6, F77_CONST_CHAR_ARG2 ("SGELSD", 6),
02301                                    F77_CONST_CHAR_ARG2 (" ", 1),
02302                                    m, n, nrhs, -1, mnthr
02303                                    F77_CHAR_ARG_LEN (6)
02304                                    F77_CHAR_ARG_LEN (1));
02305 
02306       // We compute the size of iwork because DGELSD in older versions
02307       // of LAPACK does not return it on a query call.
02308       float dminmn = static_cast<float> (minmn);
02309       float dsmlsizp1 = static_cast<float> (smlsiz+1);
02310 #if defined (HAVE_LOG2)
02311       float tmp = log2 (dminmn / dsmlsizp1);
02312 #else
02313       float tmp = log (dminmn / dsmlsizp1) / log (2.0);
02314 #endif
02315       octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1;
02316       if (nlvl < 0)
02317         nlvl = 0;
02318 
02319       octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn;
02320       if (liwork < 1)
02321         liwork = 1;
02322       Array<octave_idx_type> iwork (dim_vector (liwork, 1));
02323       octave_idx_type* piwork = iwork.fortran_vec ();
02324 
02325       F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
02326                                  ps, rcon, rank, work.fortran_vec (),
02327                                  lwork, piwork, info));
02328 
02329       // The workspace query is broken in at least LAPACK 3.0.0
02330       // through 3.1.1 when n >= mnthr.  The obtuse formula below
02331       // should provide sufficient workspace for DGELSD to operate
02332       // efficiently.
02333       if (n > m && n >= mnthr)
02334         {
02335           const octave_idx_type wlalsd
02336             = 9*m + 2*m*smlsiz + 8*m*nlvl + m*nrhs + (smlsiz+1)*(smlsiz+1);
02337 
02338           octave_idx_type addend = m;
02339 
02340           if (2*m-4 > addend)
02341             addend = 2*m-4;
02342 
02343           if (nrhs > addend)
02344             addend = nrhs;
02345 
02346           if (n-3*m > addend)
02347             addend = n-3*m;
02348 
02349           if (wlalsd > addend)
02350             addend = wlalsd;
02351 
02352           const octave_idx_type lworkaround = 4*m + m*m + addend;
02353 
02354           if (work(0) < lworkaround)
02355             work(0) = lworkaround;
02356         }
02357       else if (m >= n)
02358         {
02359           octave_idx_type lworkaround
02360             = 12*n + 2*n*smlsiz + 8*n*nlvl + n*nrhs + (smlsiz+1)*(smlsiz+1);
02361 
02362           if (work(0) < lworkaround)
02363             work(0) = lworkaround;
02364         }
02365 
02366       lwork = static_cast<octave_idx_type> (work(0));
02367       work.resize (dim_vector (lwork, 1));
02368 
02369       F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval,
02370                                  maxmn, ps, rcon, rank,
02371                                  work.fortran_vec (), lwork,
02372                                  piwork, info));
02373 
02374       if (s.elem (0) == 0.0)
02375         rcon = 0.0;
02376       else
02377         rcon = s.elem (minmn - 1) / s.elem (0);
02378 
02379       retval.resize (n, nrhs);
02380     }
02381 
02382   return retval;
02383 }
02384 
02385 FloatComplexMatrix
02386 FloatMatrix::lssolve (const FloatComplexMatrix& b) const
02387 {
02388   FloatComplexMatrix tmp (*this);
02389   octave_idx_type info;
02390   octave_idx_type rank;
02391   float rcon;
02392   return tmp.lssolve (b, info, rank, rcon);
02393 }
02394 
02395 FloatComplexMatrix
02396 FloatMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info) const
02397 {
02398   FloatComplexMatrix tmp (*this);
02399   octave_idx_type rank;
02400   float rcon;
02401   return tmp.lssolve (b, info, rank, rcon);
02402 }
02403 
02404 FloatComplexMatrix
02405 FloatMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info,
02406                  octave_idx_type& rank) const
02407 {
02408   FloatComplexMatrix tmp (*this);
02409   float rcon;
02410   return tmp.lssolve (b, info, rank, rcon);
02411 }
02412 
02413 FloatComplexMatrix
02414 FloatMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info,
02415                  octave_idx_type& rank, float& rcon) const
02416 {
02417   FloatComplexMatrix tmp (*this);
02418   return tmp.lssolve (b, info, rank, rcon);
02419 }
02420 
02421 FloatColumnVector
02422 FloatMatrix::lssolve (const FloatColumnVector& b) const
02423 {
02424   octave_idx_type info;
02425   octave_idx_type rank;
02426   float rcon;
02427   return lssolve (b, info, rank, rcon);
02428 }
02429 
02430 FloatColumnVector
02431 FloatMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info) const
02432 {
02433   octave_idx_type rank;
02434   float rcon;
02435   return lssolve (b, info, rank, rcon);
02436 }
02437 
02438 FloatColumnVector
02439 FloatMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info,
02440                  octave_idx_type& rank) const
02441 {
02442   float rcon;
02443   return lssolve (b, info, rank, rcon);
02444 }
02445 
02446 FloatColumnVector
02447 FloatMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info,
02448                  octave_idx_type& rank, float &rcon) const
02449 {
02450   FloatColumnVector retval;
02451 
02452   octave_idx_type nrhs = 1;
02453 
02454   octave_idx_type m = rows ();
02455   octave_idx_type n = cols ();
02456 
02457   if (m != b.length ())
02458     (*current_liboctave_error_handler)
02459       ("matrix dimension mismatch solution of linear equations");
02460   else if (m == 0 || n == 0)
02461     retval = FloatColumnVector (n, 0.0);
02462   else
02463     {
02464       volatile octave_idx_type minmn = (m < n ? m : n);
02465       octave_idx_type maxmn = m > n ? m : n;
02466       rcon = -1.0;
02467 
02468       if (m != n)
02469         {
02470           retval = FloatColumnVector (maxmn, 0.0);
02471 
02472           for (octave_idx_type i = 0; i < m; i++)
02473             retval.elem (i) = b.elem (i);
02474         }
02475       else
02476         retval = b;
02477 
02478       FloatMatrix atmp = *this;
02479       float *tmp_data = atmp.fortran_vec ();
02480 
02481       float *pretval = retval.fortran_vec ();
02482       Array<float> s (dim_vector (minmn, 1));
02483       float *ps = s.fortran_vec ();
02484 
02485       // Ask DGELSD what the dimension of WORK should be.
02486       octave_idx_type lwork = -1;
02487 
02488       Array<float> work (dim_vector (1, 1));
02489 
02490       octave_idx_type smlsiz;
02491       F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("SGELSD", 6),
02492                                    F77_CONST_CHAR_ARG2 (" ", 1),
02493                                    0, 0, 0, 0, smlsiz
02494                                    F77_CHAR_ARG_LEN (6)
02495                                    F77_CHAR_ARG_LEN (1));
02496 
02497       // We compute the size of iwork because DGELSD in older versions
02498       // of LAPACK does not return it on a query call.
02499       float dminmn = static_cast<float> (minmn);
02500       float dsmlsizp1 = static_cast<float> (smlsiz+1);
02501 #if defined (HAVE_LOG2)
02502       float tmp = log2 (dminmn / dsmlsizp1);
02503 #else
02504       float tmp = log (dminmn / dsmlsizp1) / log (2.0);
02505 #endif
02506       octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1;
02507       if (nlvl < 0)
02508         nlvl = 0;
02509 
02510       octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn;
02511       if (liwork < 1)
02512         liwork = 1;
02513       Array<octave_idx_type> iwork (dim_vector (liwork, 1));
02514       octave_idx_type* piwork = iwork.fortran_vec ();
02515 
02516       F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
02517                                  ps, rcon, rank, work.fortran_vec (),
02518                                  lwork, piwork, info));
02519 
02520       lwork = static_cast<octave_idx_type> (work(0));
02521       work.resize (dim_vector (lwork, 1));
02522 
02523       F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval,
02524                                  maxmn, ps, rcon, rank,
02525                                  work.fortran_vec (), lwork,
02526                                  piwork, info));
02527 
02528       if (rank < minmn)
02529         {
02530           if (s.elem (0) == 0.0)
02531             rcon = 0.0;
02532           else
02533             rcon = s.elem (minmn - 1) / s.elem (0);
02534         }
02535 
02536       retval.resize (n, nrhs);
02537     }
02538 
02539   return retval;
02540 }
02541 
02542 FloatComplexColumnVector
02543 FloatMatrix::lssolve (const FloatComplexColumnVector& b) const
02544 {
02545   FloatComplexMatrix tmp (*this);
02546   octave_idx_type info;
02547   octave_idx_type rank;
02548   float rcon;
02549   return tmp.lssolve (b, info, rank, rcon);
02550 }
02551 
02552 FloatComplexColumnVector
02553 FloatMatrix::lssolve (const FloatComplexColumnVector& b, octave_idx_type& info) const
02554 {
02555   FloatComplexMatrix tmp (*this);
02556   octave_idx_type rank;
02557   float rcon;
02558   return tmp.lssolve (b, info, rank, rcon);
02559 }
02560 
02561 FloatComplexColumnVector
02562 FloatMatrix::lssolve (const FloatComplexColumnVector& b, octave_idx_type& info,
02563                  octave_idx_type& rank) const
02564 {
02565   FloatComplexMatrix tmp (*this);
02566   float rcon;
02567   return tmp.lssolve (b, info, rank, rcon);
02568 }
02569 
02570 FloatComplexColumnVector
02571 FloatMatrix::lssolve (const FloatComplexColumnVector& b, octave_idx_type& info,
02572                  octave_idx_type& rank, float &rcon) const
02573 {
02574   FloatComplexMatrix tmp (*this);
02575   return tmp.lssolve (b, info, rank, rcon);
02576 }
02577 
02578 FloatMatrix&
02579 FloatMatrix::operator += (const FloatDiagMatrix& a)
02580 {
02581   octave_idx_type nr = rows ();
02582   octave_idx_type nc = cols ();
02583 
02584   octave_idx_type a_nr = a.rows ();
02585   octave_idx_type a_nc = a.cols ();
02586 
02587   if (nr != a_nr || nc != a_nc)
02588     {
02589       gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc);
02590       return *this;
02591     }
02592 
02593   for (octave_idx_type i = 0; i < a.length (); i++)
02594     elem (i, i) += a.elem (i, i);
02595 
02596   return *this;
02597 }
02598 
02599 FloatMatrix&
02600 FloatMatrix::operator -= (const FloatDiagMatrix& a)
02601 {
02602   octave_idx_type nr = rows ();
02603   octave_idx_type nc = cols ();
02604 
02605   octave_idx_type a_nr = a.rows ();
02606   octave_idx_type a_nc = a.cols ();
02607 
02608   if (nr != a_nr || nc != a_nc)
02609     {
02610       gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc);
02611       return *this;
02612     }
02613 
02614   for (octave_idx_type i = 0; i < a.length (); i++)
02615     elem (i, i) -= a.elem (i, i);
02616 
02617   return *this;
02618 }
02619 
02620 // unary operations
02621 
02622 boolMatrix
02623 FloatMatrix::operator ! (void) const
02624 {
02625   if (any_element_is_nan ())
02626     gripe_nan_to_logical_conversion ();
02627 
02628   return do_mx_unary_op<bool, float> (*this, mx_inline_not);
02629 }
02630 
02631 // column vector by row vector -> matrix operations
02632 
02633 FloatMatrix
02634 operator * (const FloatColumnVector& v, const FloatRowVector& a)
02635 {
02636   FloatMatrix retval;
02637 
02638   octave_idx_type len = v.length ();
02639 
02640   if (len != 0)
02641     {
02642       octave_idx_type a_len = a.length ();
02643 
02644       retval = FloatMatrix (len, a_len);
02645       float *c = retval.fortran_vec ();
02646 
02647       F77_XFCN (sgemm, SGEMM, (F77_CONST_CHAR_ARG2 ("N", 1),
02648                                F77_CONST_CHAR_ARG2 ("N", 1),
02649                                len, a_len, 1, 1.0, v.data (), len,
02650                                a.data (), 1, 0.0, c, len
02651                                F77_CHAR_ARG_LEN (1)
02652                                F77_CHAR_ARG_LEN (1)));
02653     }
02654 
02655   return retval;
02656 }
02657 
02658 // other operations.
02659 
02660 bool
02661 FloatMatrix::any_element_is_negative (bool neg_zero) const
02662 {
02663   return (neg_zero ? test_all (xnegative_sign)
02664           : do_mx_check<float> (*this, mx_inline_any_negative));
02665 }
02666 
02667 bool
02668 FloatMatrix::any_element_is_positive (bool neg_zero) const
02669 {
02670   return (neg_zero ? test_all (xpositive_sign)
02671           : do_mx_check<float> (*this, mx_inline_any_positive));
02672 }
02673 
02674 bool
02675 FloatMatrix::any_element_is_nan (void) const
02676 {
02677   return do_mx_check<float> (*this, mx_inline_any_nan);
02678 }
02679 
02680 bool
02681 FloatMatrix::any_element_is_inf_or_nan (void) const
02682 {
02683   return ! do_mx_check<float> (*this, mx_inline_all_finite);
02684 }
02685 
02686 bool
02687 FloatMatrix::any_element_not_one_or_zero (void) const
02688 {
02689   return ! test_all (xis_one_or_zero);
02690 }
02691 
02692 bool
02693 FloatMatrix::all_elements_are_int_or_inf_or_nan (void) const
02694 {
02695   return test_all (xis_int_or_inf_or_nan);
02696 }
02697 
02698 // Return nonzero if any element of M is not an integer.  Also extract
02699 // the largest and smallest values and return them in MAX_VAL and MIN_VAL.
02700 
02701 bool
02702 FloatMatrix::all_integers (float& max_val, float& min_val) const
02703 {
02704   octave_idx_type nel = nelem ();
02705 
02706   if (nel > 0)
02707     {
02708       max_val = elem (0);
02709       min_val = elem (0);
02710     }
02711   else
02712     return false;
02713 
02714   for (octave_idx_type i = 0; i < nel; i++)
02715     {
02716       float val = elem (i);
02717 
02718       if (val > max_val)
02719         max_val = val;
02720 
02721       if (val < min_val)
02722         min_val = val;
02723 
02724       if (! xisinteger (val))
02725         return false;
02726     }
02727 
02728   return true;
02729 }
02730 
02731 bool
02732 FloatMatrix::too_large_for_float (void) const
02733 {
02734   return false;
02735 }
02736 
02737 // FIXME Do these really belong here?  Maybe they should be
02738 // in a base class?
02739 
02740 boolMatrix
02741 FloatMatrix::all (int dim) const
02742 {
02743   return do_mx_red_op<bool, float> (*this, dim, mx_inline_all);
02744 }
02745 
02746 boolMatrix
02747 FloatMatrix::any (int dim) const
02748 {
02749   return do_mx_red_op<bool, float> (*this, dim, mx_inline_any);
02750 }
02751 
02752 FloatMatrix
02753 FloatMatrix::cumprod (int dim) const
02754 {
02755   return do_mx_cum_op<float, float> (*this, dim, mx_inline_cumprod);
02756 }
02757 
02758 FloatMatrix
02759 FloatMatrix::cumsum (int dim) const
02760 {
02761   return do_mx_cum_op<float, float> (*this, dim, mx_inline_cumsum);
02762 }
02763 
02764 FloatMatrix
02765 FloatMatrix::prod (int dim) const
02766 {
02767   return do_mx_red_op<float, float> (*this, dim, mx_inline_prod);
02768 }
02769 
02770 FloatMatrix
02771 FloatMatrix::sum (int dim) const
02772 {
02773   return do_mx_red_op<float, float> (*this, dim, mx_inline_sum);
02774 }
02775 
02776 FloatMatrix
02777 FloatMatrix::sumsq (int dim) const
02778 {
02779   return do_mx_red_op<float, float> (*this, dim, mx_inline_sumsq);
02780 }
02781 
02782 FloatMatrix
02783 FloatMatrix::abs (void) const
02784 {
02785   return do_mx_unary_map<float, float, std::abs> (*this);
02786 }
02787 
02788 FloatMatrix
02789 FloatMatrix::diag (octave_idx_type k) const
02790 {
02791   return MArray<float>::diag (k);
02792 }
02793 
02794 FloatColumnVector
02795 FloatMatrix::row_min (void) const
02796 {
02797   Array<octave_idx_type> dummy_idx;
02798   return row_min (dummy_idx);
02799 }
02800 
02801 FloatColumnVector
02802 FloatMatrix::row_min (Array<octave_idx_type>& idx_arg) const
02803 {
02804   FloatColumnVector result;
02805 
02806   octave_idx_type nr = rows ();
02807   octave_idx_type nc = cols ();
02808 
02809   if (nr > 0 && nc > 0)
02810     {
02811       result.resize (nr);
02812       idx_arg.resize (dim_vector (nr, 1));
02813 
02814       for (octave_idx_type i = 0; i < nr; i++)
02815         {
02816           octave_idx_type idx_j;
02817 
02818           float tmp_min = octave_Float_NaN;
02819 
02820           for (idx_j = 0; idx_j < nc; idx_j++)
02821             {
02822               tmp_min = elem (i, idx_j);
02823 
02824               if (! xisnan (tmp_min))
02825                 break;
02826             }
02827 
02828           for (octave_idx_type j = idx_j+1; j < nc; j++)
02829             {
02830               float tmp = elem (i, j);
02831 
02832               if (xisnan (tmp))
02833                 continue;
02834               else if (tmp < tmp_min)
02835                 {
02836                   idx_j = j;
02837                   tmp_min = tmp;
02838                 }
02839             }
02840 
02841           result.elem (i) = tmp_min;
02842           idx_arg.elem (i) = xisnan (tmp_min) ? 0 : idx_j;
02843         }
02844     }
02845 
02846   return result;
02847 }
02848 
02849 FloatColumnVector
02850 FloatMatrix::row_max (void) const
02851 {
02852   Array<octave_idx_type> dummy_idx;
02853   return row_max (dummy_idx);
02854 }
02855 
02856 FloatColumnVector
02857 FloatMatrix::row_max (Array<octave_idx_type>& idx_arg) const
02858 {
02859   FloatColumnVector result;
02860 
02861   octave_idx_type nr = rows ();
02862   octave_idx_type nc = cols ();
02863 
02864   if (nr > 0 && nc > 0)
02865     {
02866       result.resize (nr);
02867       idx_arg.resize (dim_vector (nr, 1));
02868 
02869       for (octave_idx_type i = 0; i < nr; i++)
02870         {
02871           octave_idx_type idx_j;
02872 
02873           float tmp_max = octave_Float_NaN;
02874 
02875           for (idx_j = 0; idx_j < nc; idx_j++)
02876             {
02877               tmp_max = elem (i, idx_j);
02878 
02879               if (! xisnan (tmp_max))
02880                 break;
02881             }
02882 
02883           for (octave_idx_type j = idx_j+1; j < nc; j++)
02884             {
02885               float tmp = elem (i, j);
02886 
02887               if (xisnan (tmp))
02888                 continue;
02889               else if (tmp > tmp_max)
02890                 {
02891                   idx_j = j;
02892                   tmp_max = tmp;
02893                 }
02894             }
02895 
02896           result.elem (i) = tmp_max;
02897           idx_arg.elem (i) = xisnan (tmp_max) ? 0 : idx_j;
02898         }
02899     }
02900 
02901   return result;
02902 }
02903 
02904 FloatRowVector
02905 FloatMatrix::column_min (void) const
02906 {
02907   Array<octave_idx_type> dummy_idx;
02908   return column_min (dummy_idx);
02909 }
02910 
02911 FloatRowVector
02912 FloatMatrix::column_min (Array<octave_idx_type>& idx_arg) const
02913 {
02914   FloatRowVector result;
02915 
02916   octave_idx_type nr = rows ();
02917   octave_idx_type nc = cols ();
02918 
02919   if (nr > 0 && nc > 0)
02920     {
02921       result.resize (nc);
02922       idx_arg.resize (dim_vector (1, nc));
02923 
02924       for (octave_idx_type j = 0; j < nc; j++)
02925         {
02926           octave_idx_type idx_i;
02927 
02928           float tmp_min = octave_Float_NaN;
02929 
02930           for (idx_i = 0; idx_i < nr; idx_i++)
02931             {
02932               tmp_min = elem (idx_i, j);
02933 
02934               if (! xisnan (tmp_min))
02935                 break;
02936             }
02937 
02938           for (octave_idx_type i = idx_i+1; i < nr; i++)
02939             {
02940               float tmp = elem (i, j);
02941 
02942               if (xisnan (tmp))
02943                 continue;
02944               else if (tmp < tmp_min)
02945                 {
02946                   idx_i = i;
02947                   tmp_min = tmp;
02948                 }
02949             }
02950 
02951           result.elem (j) = tmp_min;
02952           idx_arg.elem (j) = xisnan (tmp_min) ? 0 : idx_i;
02953         }
02954     }
02955 
02956   return result;
02957 }
02958 
02959 FloatRowVector
02960 FloatMatrix::column_max (void) const
02961 {
02962   Array<octave_idx_type> dummy_idx;
02963   return column_max (dummy_idx);
02964 }
02965 
02966 FloatRowVector
02967 FloatMatrix::column_max (Array<octave_idx_type>& idx_arg) const
02968 {
02969   FloatRowVector result;
02970 
02971   octave_idx_type nr = rows ();
02972   octave_idx_type nc = cols ();
02973 
02974   if (nr > 0 && nc > 0)
02975     {
02976       result.resize (nc);
02977       idx_arg.resize (dim_vector (1, nc));
02978 
02979       for (octave_idx_type j = 0; j < nc; j++)
02980         {
02981           octave_idx_type idx_i;
02982 
02983           float tmp_max = octave_Float_NaN;
02984 
02985           for (idx_i = 0; idx_i < nr; idx_i++)
02986             {
02987               tmp_max = elem (idx_i, j);
02988 
02989               if (! xisnan (tmp_max))
02990                 break;
02991             }
02992 
02993           for (octave_idx_type i = idx_i+1; i < nr; i++)
02994             {
02995               float tmp = elem (i, j);
02996 
02997               if (xisnan (tmp))
02998                 continue;
02999               else if (tmp > tmp_max)
03000                 {
03001                   idx_i = i;
03002                   tmp_max = tmp;
03003                 }
03004             }
03005 
03006           result.elem (j) = tmp_max;
03007           idx_arg.elem (j) = xisnan (tmp_max) ? 0 : idx_i;
03008         }
03009     }
03010 
03011   return result;
03012 }
03013 
03014 std::ostream&
03015 operator << (std::ostream& os, const FloatMatrix& a)
03016 {
03017   for (octave_idx_type i = 0; i < a.rows (); i++)
03018     {
03019       for (octave_idx_type j = 0; j < a.cols (); j++)
03020         {
03021           os << " ";
03022           octave_write_float (os, a.elem (i, j));
03023         }
03024       os << "\n";
03025     }
03026   return os;
03027 }
03028 
03029 std::istream&
03030 operator >> (std::istream& is, FloatMatrix& a)
03031 {
03032   octave_idx_type nr = a.rows ();
03033   octave_idx_type nc = a.cols ();
03034 
03035   if (nr > 0 && nc > 0)
03036     {
03037       float tmp;
03038       for (octave_idx_type i = 0; i < nr; i++)
03039         for (octave_idx_type j = 0; j < nc; j++)
03040           {
03041             tmp = octave_read_value<float> (is);
03042             if (is)
03043               a.elem (i, j) = tmp;
03044             else
03045               goto done;
03046           }
03047     }
03048 
03049  done:
03050 
03051   return is;
03052 }
03053 
03054 FloatMatrix
03055 Givens (float x, float y)
03056 {
03057   float cc, s, temp_r;
03058 
03059   F77_FUNC (slartg, SLARTG) (x, y, cc, s, temp_r);
03060 
03061   FloatMatrix g (2, 2);
03062 
03063   g.elem (0, 0) = cc;
03064   g.elem (1, 1) = cc;
03065   g.elem (0, 1) = s;
03066   g.elem (1, 0) = -s;
03067 
03068   return g;
03069 }
03070 
03071 FloatMatrix
03072 Sylvester (const FloatMatrix& a, const FloatMatrix& b, const FloatMatrix& c)
03073 {
03074   FloatMatrix retval;
03075 
03076   // FIXME -- need to check that a, b, and c are all the same
03077   // size.
03078 
03079   // Compute Schur decompositions.
03080 
03081   FloatSCHUR as (a, "U");
03082   FloatSCHUR bs (b, "U");
03083 
03084   // Transform c to new coordinates.
03085 
03086   FloatMatrix ua = as.unitary_matrix ();
03087   FloatMatrix sch_a = as.schur_matrix ();
03088 
03089   FloatMatrix ub = bs.unitary_matrix ();
03090   FloatMatrix sch_b = bs.schur_matrix ();
03091 
03092   FloatMatrix cx = ua.transpose () * c * ub;
03093 
03094   // Solve the sylvester equation, back-transform, and return the
03095   // solution.
03096 
03097   octave_idx_type a_nr = a.rows ();
03098   octave_idx_type b_nr = b.rows ();
03099 
03100   float scale;
03101   octave_idx_type info;
03102 
03103   float *pa = sch_a.fortran_vec ();
03104   float *pb = sch_b.fortran_vec ();
03105   float *px = cx.fortran_vec ();
03106 
03107   F77_XFCN (strsyl, STRSYL, (F77_CONST_CHAR_ARG2 ("N", 1),
03108                              F77_CONST_CHAR_ARG2 ("N", 1),
03109                              1, a_nr, b_nr, pa, a_nr, pb,
03110                              b_nr, px, a_nr, scale, info
03111                              F77_CHAR_ARG_LEN (1)
03112                              F77_CHAR_ARG_LEN (1)));
03113 
03114 
03115   // FIXME -- check info?
03116 
03117   retval = -ua*cx*ub.transpose ();
03118 
03119   return retval;
03120 }
03121 
03122 // matrix by matrix -> matrix operations
03123 
03124 /* Simple Dot Product, Matrix-Vector and Matrix-Matrix Unit tests
03125 %!assert(single([1 2 3]) * single([ 4 ; 5 ; 6]), single(32), 5e-7)
03126 %!assert(single([1 2 ; 3 4 ]) * single([5 ; 6]), single([17 ; 39 ]), 5e-7)
03127 %!assert(single([1 2 ; 3 4 ]) * single([5 6 ; 7 8]), single([19 22; 43 50]), 5e-7)
03128 */
03129 
03130 /* Test some simple identities
03131 %!shared M, cv, rv
03132 %! M = single(randn(10,10));
03133 %! cv = single(randn(10,1));
03134 %! rv = single(randn(1,10));
03135 %!assert([M*cv,M*cv],M*[cv,cv],5e-6)
03136 %!assert([M'*cv,M'*cv],M'*[cv,cv],5e-6)
03137 %!assert([rv*M;rv*M],[rv;rv]*M,5e-6)
03138 %!assert([rv*M';rv*M'],[rv;rv]*M',5e-6)
03139 %!assert(2*rv*cv,[rv,rv]*[cv;cv],5e-6)
03140 */
03141 
03142 static char
03143 get_blas_trans_arg (bool trans)
03144 {
03145   return trans ? 'T' : 'N';
03146 }
03147 
03148 // the general GEMM operation
03149 
03150 FloatMatrix
03151 xgemm (const FloatMatrix& a, const FloatMatrix& b,
03152        blas_trans_type transa, blas_trans_type transb)
03153 {
03154   FloatMatrix retval;
03155 
03156   bool tra = transa != blas_no_trans, trb = transb != blas_no_trans;
03157 
03158   octave_idx_type a_nr = tra ? a.cols () : a.rows ();
03159   octave_idx_type a_nc = tra ? a.rows () : a.cols ();
03160 
03161   octave_idx_type b_nr = trb ? b.cols () : b.rows ();
03162   octave_idx_type b_nc = trb ? b.rows () : b.cols ();
03163 
03164   if (a_nc != b_nr)
03165     gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
03166   else
03167     {
03168       if (a_nr == 0 || a_nc == 0 || b_nc == 0)
03169         retval = FloatMatrix (a_nr, b_nc, 0.0);
03170       else if (a.data () == b.data () && a_nr == b_nc && tra != trb)
03171         {
03172           octave_idx_type lda = a.rows ();
03173 
03174           retval = FloatMatrix (a_nr, b_nc);
03175           float *c = retval.fortran_vec ();
03176 
03177           const char ctra = get_blas_trans_arg (tra);
03178           F77_XFCN (ssyrk, SSYRK, (F77_CONST_CHAR_ARG2 ("U", 1),
03179                                    F77_CONST_CHAR_ARG2 (&ctra, 1),
03180                                    a_nr, a_nc, 1.0,
03181                                    a.data (), lda, 0.0, c, a_nr
03182                                    F77_CHAR_ARG_LEN (1)
03183                                    F77_CHAR_ARG_LEN (1)));
03184           for (int j = 0; j < a_nr; j++)
03185             for (int i = 0; i < j; i++)
03186               retval.xelem (j,i) = retval.xelem (i,j);
03187 
03188         }
03189       else
03190         {
03191           octave_idx_type lda = a.rows (), tda = a.cols ();
03192           octave_idx_type ldb = b.rows (), tdb = b.cols ();
03193 
03194           retval = FloatMatrix (a_nr, b_nc);
03195           float *c = retval.fortran_vec ();
03196 
03197           if (b_nc == 1)
03198             {
03199               if (a_nr == 1)
03200                 F77_FUNC (xsdot, XSDOT) (a_nc, a.data (), 1, b.data (), 1, *c);
03201               else
03202                 {
03203                   const char ctra = get_blas_trans_arg (tra);
03204                   F77_XFCN (sgemv, SGEMV, (F77_CONST_CHAR_ARG2 (&ctra, 1),
03205                                            lda, tda, 1.0,  a.data (), lda,
03206                                            b.data (), 1, 0.0, c, 1
03207                                            F77_CHAR_ARG_LEN (1)));
03208                 }
03209             }
03210           else if (a_nr == 1)
03211             {
03212               const char crevtrb = get_blas_trans_arg (! trb);
03213               F77_XFCN (sgemv, SGEMV, (F77_CONST_CHAR_ARG2 (&crevtrb, 1),
03214                                        ldb, tdb, 1.0,  b.data (), ldb,
03215                                        a.data (), 1, 0.0, c, 1
03216                                        F77_CHAR_ARG_LEN (1)));
03217             }
03218           else
03219             {
03220               const char ctra = get_blas_trans_arg (tra);
03221               const char ctrb = get_blas_trans_arg (trb);
03222               F77_XFCN (sgemm, SGEMM, (F77_CONST_CHAR_ARG2 (&ctra, 1),
03223                                        F77_CONST_CHAR_ARG2 (&ctrb, 1),
03224                                        a_nr, b_nc, a_nc, 1.0, a.data (),
03225                                        lda, b.data (), ldb, 0.0, c, a_nr
03226                                        F77_CHAR_ARG_LEN (1)
03227                                        F77_CHAR_ARG_LEN (1)));
03228             }
03229         }
03230     }
03231 
03232   return retval;
03233 }
03234 
03235 FloatMatrix
03236 operator * (const FloatMatrix& a, const FloatMatrix& b)
03237 {
03238   return xgemm (a, b);
03239 }
03240 
03241 // FIXME -- it would be nice to share code among the min/max
03242 // functions below.
03243 
03244 #define EMPTY_RETURN_CHECK(T) \
03245   if (nr == 0 || nc == 0) \
03246     return T (nr, nc);
03247 
03248 FloatMatrix
03249 min (float d, const FloatMatrix& m)
03250 {
03251   octave_idx_type nr = m.rows ();
03252   octave_idx_type nc = m.columns ();
03253 
03254   EMPTY_RETURN_CHECK (FloatMatrix);
03255 
03256   FloatMatrix result (nr, nc);
03257 
03258   for (octave_idx_type j = 0; j < nc; j++)
03259     for (octave_idx_type i = 0; i < nr; i++)
03260       {
03261         octave_quit ();
03262         result (i, j) = xmin (d, m (i, j));
03263       }
03264 
03265   return result;
03266 }
03267 
03268 FloatMatrix
03269 min (const FloatMatrix& m, float d)
03270 {
03271   octave_idx_type nr = m.rows ();
03272   octave_idx_type nc = m.columns ();
03273 
03274   EMPTY_RETURN_CHECK (FloatMatrix);
03275 
03276   FloatMatrix result (nr, nc);
03277 
03278   for (octave_idx_type j = 0; j < nc; j++)
03279     for (octave_idx_type i = 0; i < nr; i++)
03280       {
03281         octave_quit ();
03282         result (i, j) = xmin (m (i, j), d);
03283       }
03284 
03285   return result;
03286 }
03287 
03288 FloatMatrix
03289 min (const FloatMatrix& a, const FloatMatrix& b)
03290 {
03291   octave_idx_type nr = a.rows ();
03292   octave_idx_type nc = a.columns ();
03293 
03294   if (nr != b.rows () || nc != b.columns ())
03295     {
03296       (*current_liboctave_error_handler)
03297         ("two-arg min expecting args of same size");
03298       return FloatMatrix ();
03299     }
03300 
03301   EMPTY_RETURN_CHECK (FloatMatrix);
03302 
03303   FloatMatrix result (nr, nc);
03304 
03305   for (octave_idx_type j = 0; j < nc; j++)
03306     for (octave_idx_type i = 0; i < nr; i++)
03307       {
03308         octave_quit ();
03309         result (i, j) = xmin (a (i, j), b (i, j));
03310       }
03311 
03312   return result;
03313 }
03314 
03315 FloatMatrix
03316 max (float d, const FloatMatrix& m)
03317 {
03318   octave_idx_type nr = m.rows ();
03319   octave_idx_type nc = m.columns ();
03320 
03321   EMPTY_RETURN_CHECK (FloatMatrix);
03322 
03323   FloatMatrix result (nr, nc);
03324 
03325   for (octave_idx_type j = 0; j < nc; j++)
03326     for (octave_idx_type i = 0; i < nr; i++)
03327       {
03328         octave_quit ();
03329         result (i, j) = xmax (d, m (i, j));
03330       }
03331 
03332   return result;
03333 }
03334 
03335 FloatMatrix
03336 max (const FloatMatrix& m, float d)
03337 {
03338   octave_idx_type nr = m.rows ();
03339   octave_idx_type nc = m.columns ();
03340 
03341   EMPTY_RETURN_CHECK (FloatMatrix);
03342 
03343   FloatMatrix result (nr, nc);
03344 
03345   for (octave_idx_type j = 0; j < nc; j++)
03346     for (octave_idx_type i = 0; i < nr; i++)
03347       {
03348         octave_quit ();
03349         result (i, j) = xmax (m (i, j), d);
03350       }
03351 
03352   return result;
03353 }
03354 
03355 FloatMatrix
03356 max (const FloatMatrix& a, const FloatMatrix& b)
03357 {
03358   octave_idx_type nr = a.rows ();
03359   octave_idx_type nc = a.columns ();
03360 
03361   if (nr != b.rows () || nc != b.columns ())
03362     {
03363       (*current_liboctave_error_handler)
03364         ("two-arg max expecting args of same size");
03365       return FloatMatrix ();
03366     }
03367 
03368   EMPTY_RETURN_CHECK (FloatMatrix);
03369 
03370   FloatMatrix result (nr, nc);
03371 
03372   for (octave_idx_type j = 0; j < nc; j++)
03373     for (octave_idx_type i = 0; i < nr; i++)
03374       {
03375         octave_quit ();
03376         result (i, j) = xmax (a (i, j), b (i, j));
03377       }
03378 
03379   return result;
03380 }
03381 
03382 FloatMatrix linspace (const FloatColumnVector& x1,
03383                       const FloatColumnVector& x2,
03384                       octave_idx_type n)
03385 
03386 {
03387   if (n < 1) n = 1;
03388 
03389   octave_idx_type m = x1.length ();
03390 
03391   if (x2.length () != m)
03392     (*current_liboctave_error_handler) ("linspace: vectors must be of equal length");
03393 
03394   NoAlias<FloatMatrix> retval;
03395 
03396   retval.clear (m, n);
03397   for (octave_idx_type i = 0; i < m; i++)
03398     retval(i, 0) = x1(i);
03399 
03400   // The last column is not needed while using delta.
03401   float *delta = &retval(0, n-1);
03402   for (octave_idx_type i = 0; i < m; i++)
03403     delta[i] = (x2(i) - x1(i)) / (n - 1);
03404 
03405   for (octave_idx_type j = 1; j < n-1; j++)
03406     for (octave_idx_type i = 0; i < m; i++)
03407       retval(i, j) = x1(i) + j*delta[i];
03408 
03409   for (octave_idx_type i = 0; i < m; i++)
03410     retval(i, n-1) = x2(i);
03411 
03412   return retval;
03413 }
03414 
03415 MS_CMP_OPS (FloatMatrix, float)
03416 MS_BOOL_OPS (FloatMatrix, float)
03417 
03418 SM_CMP_OPS (float, FloatMatrix)
03419 SM_BOOL_OPS (float, FloatMatrix)
03420 
03421 MM_CMP_OPS (FloatMatrix, FloatMatrix)
03422 MM_BOOL_OPS (FloatMatrix, FloatMatrix)
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines