00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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 "byte-swap.h"
00037 #include "dMatrix.h"
00038 #include "dbleAEPBAL.h"
00039 #include "DET.h"
00040 #include "dbleSCHUR.h"
00041 #include "dbleSVD.h"
00042 #include "dbleCHOL.h"
00043 #include "f77-fcn.h"
00044 #include "functor.h"
00045 #include "lo-error.h"
00046 #include "oct-locbuf.h"
00047 #include "lo-ieee.h"
00048 #include "lo-mappers.h"
00049 #include "lo-utils.h"
00050 #include "mx-base.h"
00051 #include "mx-m-dm.h"
00052 #include "mx-dm-m.h"
00053 #include "mx-inlines.cc"
00054 #include "mx-op-defs.h"
00055 #include "oct-cmplx.h"
00056 #include "oct-fftw.h"
00057 #include "oct-norm.h"
00058 #include "quit.h"
00059
00060
00061
00062 extern "C"
00063 {
00064 F77_RET_T
00065 F77_FUNC (xilaenv, XILAENV) (const octave_idx_type&,
00066 F77_CONST_CHAR_ARG_DECL,
00067 F77_CONST_CHAR_ARG_DECL,
00068 const octave_idx_type&, const octave_idx_type&,
00069 const octave_idx_type&, const octave_idx_type&,
00070 octave_idx_type&
00071 F77_CHAR_ARG_LEN_DECL
00072 F77_CHAR_ARG_LEN_DECL);
00073
00074 F77_RET_T
00075 F77_FUNC (dgebal, DGEBAL) (F77_CONST_CHAR_ARG_DECL,
00076 const octave_idx_type&, double*,
00077 const octave_idx_type&, octave_idx_type&,
00078 octave_idx_type&, double*, octave_idx_type&
00079 F77_CHAR_ARG_LEN_DECL);
00080
00081 F77_RET_T
00082 F77_FUNC (dgebak, DGEBAK) (F77_CONST_CHAR_ARG_DECL,
00083 F77_CONST_CHAR_ARG_DECL,
00084 const octave_idx_type&, const octave_idx_type&,
00085 const octave_idx_type&, double*,
00086 const octave_idx_type&, double*,
00087 const octave_idx_type&, octave_idx_type&
00088 F77_CHAR_ARG_LEN_DECL
00089 F77_CHAR_ARG_LEN_DECL);
00090
00091
00092 F77_RET_T
00093 F77_FUNC (dgemm, DGEMM) (F77_CONST_CHAR_ARG_DECL,
00094 F77_CONST_CHAR_ARG_DECL,
00095 const octave_idx_type&, const octave_idx_type&,
00096 const octave_idx_type&, const double&,
00097 const double*, const octave_idx_type&,
00098 const double*, const octave_idx_type&,
00099 const double&, double*, const octave_idx_type&
00100 F77_CHAR_ARG_LEN_DECL
00101 F77_CHAR_ARG_LEN_DECL);
00102
00103 F77_RET_T
00104 F77_FUNC (dgemv, DGEMV) (F77_CONST_CHAR_ARG_DECL,
00105 const octave_idx_type&, const octave_idx_type&,
00106 const double&, const double*,
00107 const octave_idx_type&, const double*,
00108 const octave_idx_type&, const double&, double*,
00109 const octave_idx_type&
00110 F77_CHAR_ARG_LEN_DECL);
00111
00112 F77_RET_T
00113 F77_FUNC (xddot, XDDOT) (const octave_idx_type&, const double*,
00114 const octave_idx_type&, const double*,
00115 const octave_idx_type&, double&);
00116
00117 F77_RET_T
00118 F77_FUNC (dsyrk, DSYRK) (F77_CONST_CHAR_ARG_DECL,
00119 F77_CONST_CHAR_ARG_DECL,
00120 const octave_idx_type&, const octave_idx_type&,
00121 const double&, const double*, const octave_idx_type&,
00122 const double&, double*, const octave_idx_type&
00123 F77_CHAR_ARG_LEN_DECL
00124 F77_CHAR_ARG_LEN_DECL);
00125
00126 F77_RET_T
00127 F77_FUNC (dgetrf, DGETRF) (const octave_idx_type&, const octave_idx_type&,
00128 double*, const octave_idx_type&,
00129 octave_idx_type*, octave_idx_type&);
00130
00131 F77_RET_T
00132 F77_FUNC (dgetrs, DGETRS) (F77_CONST_CHAR_ARG_DECL,
00133 const octave_idx_type&, const octave_idx_type&,
00134 const double*, const octave_idx_type&,
00135 const octave_idx_type*, double*,
00136 const octave_idx_type&, octave_idx_type&
00137 F77_CHAR_ARG_LEN_DECL);
00138
00139 F77_RET_T
00140 F77_FUNC (dgetri, DGETRI) (const octave_idx_type&, double*,
00141 const octave_idx_type&, const octave_idx_type*,
00142 double*, const octave_idx_type&,
00143 octave_idx_type&);
00144
00145 F77_RET_T
00146 F77_FUNC (dgecon, DGECON) (F77_CONST_CHAR_ARG_DECL,
00147 const octave_idx_type&, double*,
00148 const octave_idx_type&, const double&, double&,
00149 double*, octave_idx_type*, octave_idx_type&
00150 F77_CHAR_ARG_LEN_DECL);
00151
00152 F77_RET_T
00153 F77_FUNC (dgelsy, DGELSY) (const octave_idx_type&, const octave_idx_type&,
00154 const octave_idx_type&, double*,
00155 const octave_idx_type&, double*,
00156 const octave_idx_type&, octave_idx_type*,
00157 double&, octave_idx_type&, double*,
00158 const octave_idx_type&, octave_idx_type&);
00159
00160 F77_RET_T
00161 F77_FUNC (dgelsd, DGELSD) (const octave_idx_type&, const octave_idx_type&,
00162 const octave_idx_type&, double*,
00163 const octave_idx_type&, double*,
00164 const octave_idx_type&, double*, double&,
00165 octave_idx_type&, double*,
00166 const octave_idx_type&, octave_idx_type*,
00167 octave_idx_type&);
00168
00169 F77_RET_T
00170 F77_FUNC (dpotrf, DPOTRF) (F77_CONST_CHAR_ARG_DECL,
00171 const octave_idx_type&, double *,
00172 const octave_idx_type&, octave_idx_type&
00173 F77_CHAR_ARG_LEN_DECL);
00174
00175 F77_RET_T
00176 F77_FUNC (dpocon, DPOCON) (F77_CONST_CHAR_ARG_DECL,
00177 const octave_idx_type&, double*,
00178 const octave_idx_type&, const double&,
00179 double&, double*, octave_idx_type*,
00180 octave_idx_type&
00181 F77_CHAR_ARG_LEN_DECL);
00182 F77_RET_T
00183 F77_FUNC (dpotrs, DPOTRS) (F77_CONST_CHAR_ARG_DECL,
00184 const octave_idx_type&, const octave_idx_type&,
00185 const double*, const octave_idx_type&, double*,
00186 const octave_idx_type&, octave_idx_type&
00187 F77_CHAR_ARG_LEN_DECL);
00188
00189 F77_RET_T
00190 F77_FUNC (dtrtri, DTRTRI) (F77_CONST_CHAR_ARG_DECL,
00191 F77_CONST_CHAR_ARG_DECL,
00192 const octave_idx_type&, const double*,
00193 const octave_idx_type&, octave_idx_type&
00194 F77_CHAR_ARG_LEN_DECL
00195 F77_CHAR_ARG_LEN_DECL);
00196 F77_RET_T
00197 F77_FUNC (dtrcon, DTRCON) (F77_CONST_CHAR_ARG_DECL,
00198 F77_CONST_CHAR_ARG_DECL,
00199 F77_CONST_CHAR_ARG_DECL,
00200 const octave_idx_type&, const double*,
00201 const octave_idx_type&, double&,
00202 double*, octave_idx_type*, octave_idx_type&
00203 F77_CHAR_ARG_LEN_DECL
00204 F77_CHAR_ARG_LEN_DECL
00205 F77_CHAR_ARG_LEN_DECL);
00206 F77_RET_T
00207 F77_FUNC (dtrtrs, DTRTRS) (F77_CONST_CHAR_ARG_DECL,
00208 F77_CONST_CHAR_ARG_DECL,
00209 F77_CONST_CHAR_ARG_DECL,
00210 const octave_idx_type&, const octave_idx_type&,
00211 const double*, const octave_idx_type&, double*,
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 (dlartg, DLARTG) (const double&, const double&, double&,
00219 double&, double&);
00220
00221 F77_RET_T
00222 F77_FUNC (dtrsyl, DTRSYL) (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 double*,
00226 const octave_idx_type&, const double*,
00227 const octave_idx_type&, const double*,
00228 const octave_idx_type&, double&, octave_idx_type&
00229 F77_CHAR_ARG_LEN_DECL
00230 F77_CHAR_ARG_LEN_DECL);
00231
00232 F77_RET_T
00233 F77_FUNC (xdlange, XDLANGE) (F77_CONST_CHAR_ARG_DECL,
00234 const octave_idx_type&, const octave_idx_type&,
00235 const double*, const octave_idx_type&,
00236 double*, double&
00237 F77_CHAR_ARG_LEN_DECL);
00238 }
00239
00240
00241
00242 Matrix::Matrix (const RowVector& rv)
00243 : MArray<double> (rv)
00244 {
00245 }
00246
00247 Matrix::Matrix (const ColumnVector& cv)
00248 : MArray<double> (cv)
00249 {
00250 }
00251
00252 Matrix::Matrix (const DiagMatrix& a)
00253 : MArray<double> (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 Matrix::Matrix (const PermMatrix& a)
00260 : MArray<double> (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
00273
00274
00275 Matrix::Matrix (const boolMatrix& a)
00276 : MArray<double> (a)
00277 {
00278 }
00279
00280 Matrix::Matrix (const charMatrix& a)
00281 : MArray<double> (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 Matrix::operator == (const Matrix& 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 Matrix::operator != (const Matrix& a) const
00299 {
00300 return !(*this == a);
00301 }
00302
00303 bool
00304 Matrix::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 Matrix&
00320 Matrix::insert (const Matrix& a, octave_idx_type r, octave_idx_type c)
00321 {
00322 Array<double>::insert (a, r, c);
00323 return *this;
00324 }
00325
00326 Matrix&
00327 Matrix::insert (const RowVector& 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 Matrix&
00349 Matrix::insert (const ColumnVector& 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 Matrix&
00371 Matrix::insert (const DiagMatrix& 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 Matrix&
00398 Matrix::fill (double 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 Matrix&
00416 Matrix::fill (double 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 Matrix
00444 Matrix::append (const Matrix& 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 Matrix ();
00452 }
00453
00454 octave_idx_type nc_insert = nc;
00455 Matrix retval (nr, nc + a.cols ());
00456 retval.insert (*this, 0, 0);
00457 retval.insert (a, 0, nc_insert);
00458 return retval;
00459 }
00460
00461 Matrix
00462 Matrix::append (const RowVector& 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 Matrix ();
00470 }
00471
00472 octave_idx_type nc_insert = nc;
00473 Matrix retval (nr, nc + a.length ());
00474 retval.insert (*this, 0, 0);
00475 retval.insert (a, 0, nc_insert);
00476 return retval;
00477 }
00478
00479 Matrix
00480 Matrix::append (const ColumnVector& 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 Matrix ();
00488 }
00489
00490 octave_idx_type nc_insert = nc;
00491 Matrix retval (nr, nc + 1);
00492 retval.insert (*this, 0, 0);
00493 retval.insert (a, 0, nc_insert);
00494 return retval;
00495 }
00496
00497 Matrix
00498 Matrix::append (const DiagMatrix& 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 Matrix retval (nr, nc + a.cols ());
00510 retval.insert (*this, 0, 0);
00511 retval.insert (a, 0, nc_insert);
00512 return retval;
00513 }
00514
00515 Matrix
00516 Matrix::stack (const Matrix& 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 Matrix ();
00525 }
00526
00527 octave_idx_type nr_insert = nr;
00528 Matrix retval (nr + a.rows (), nc);
00529 retval.insert (*this, 0, 0);
00530 retval.insert (a, nr_insert, 0);
00531 return retval;
00532 }
00533
00534 Matrix
00535 Matrix::stack (const RowVector& 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 Matrix ();
00544 }
00545
00546 octave_idx_type nr_insert = nr;
00547 Matrix retval (nr + 1, nc);
00548 retval.insert (*this, 0, 0);
00549 retval.insert (a, nr_insert, 0);
00550 return retval;
00551 }
00552
00553 Matrix
00554 Matrix::stack (const ColumnVector& 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 Matrix ();
00563 }
00564
00565 octave_idx_type nr_insert = nr;
00566 Matrix retval (nr + a.length (), nc);
00567 retval.insert (*this, 0, 0);
00568 retval.insert (a, nr_insert, 0);
00569 return retval;
00570 }
00571
00572 Matrix
00573 Matrix::stack (const DiagMatrix& 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 Matrix ();
00582 }
00583
00584 octave_idx_type nr_insert = nr;
00585 Matrix retval (nr + a.rows (), nc);
00586 retval.insert (*this, 0, 0);
00587 retval.insert (a, nr_insert, 0);
00588 return retval;
00589 }
00590
00591 Matrix
00592 real (const ComplexMatrix& a)
00593 {
00594 return do_mx_unary_op<double, Complex> (a, mx_inline_real);
00595 }
00596
00597 Matrix
00598 imag (const ComplexMatrix& a)
00599 {
00600 return do_mx_unary_op<double, Complex> (a, mx_inline_imag);
00601 }
00602
00603 Matrix
00604 Matrix::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 Matrix
00613 Matrix::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
00619
00620 RowVector
00621 Matrix::row (octave_idx_type i) const
00622 {
00623 return index (idx_vector (i), idx_vector::colon);
00624 }
00625
00626 ColumnVector
00627 Matrix::column (octave_idx_type i) const
00628 {
00629 return index (idx_vector::colon, idx_vector (i));
00630 }
00631
00632 Matrix
00633 Matrix::inverse (void) const
00634 {
00635 octave_idx_type info;
00636 double rcon;
00637 MatrixType mattype (*this);
00638 return inverse (mattype, info, rcon, 0, 0);
00639 }
00640
00641 Matrix
00642 Matrix::inverse (octave_idx_type& info) const
00643 {
00644 double rcon;
00645 MatrixType mattype (*this);
00646 return inverse (mattype, info, rcon, 0, 0);
00647 }
00648
00649 Matrix
00650 Matrix::inverse (octave_idx_type& info, double& 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 Matrix
00658 Matrix::inverse (MatrixType& mattype) const
00659 {
00660 octave_idx_type info;
00661 double rcon;
00662 return inverse (mattype, info, rcon, 0, 0);
00663 }
00664
00665 Matrix
00666 Matrix::inverse (MatrixType &mattype, octave_idx_type& info) const
00667 {
00668 double rcon;
00669 return inverse (mattype, info, rcon, 0, 0);
00670 }
00671
00672 Matrix
00673 Matrix::tinverse (MatrixType &mattype, octave_idx_type& info, double& rcon,
00674 int force, int calc_cond) const
00675 {
00676 Matrix 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 double *tmp_data = retval.fortran_vec ();
00690
00691 F77_XFCN (dtrtri, DTRTRI, (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
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 (double, work, 3 * nr);
00707 OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, nr);
00708
00709 F77_XFCN (dtrcon, DTRCON, (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;
00724 }
00725
00726 return retval;
00727 }
00728
00729
00730 Matrix
00731 Matrix::finverse (MatrixType &mattype, octave_idx_type& info, double& rcon,
00732 int force, int calc_cond) const
00733 {
00734 Matrix 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 double *tmp_data = retval.fortran_vec ();
00748
00749 Array<double> z (dim_vector (1, 1));
00750 octave_idx_type lwork = -1;
00751
00752
00753 F77_XFCN (dgetri, DGETRI, (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 double *pz = z.fortran_vec ();
00760
00761 info = 0;
00762
00763
00764 double anorm = 0;
00765 if (calc_cond)
00766 anorm = retval.abs().sum().row(static_cast<octave_idx_type>(0)).max();
00767
00768 F77_XFCN (dgetrf, DGETRF, (nc, nc, tmp_data, nr, pipvt, info));
00769
00770
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
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 (dgecon, DGECON, (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;
00793 else
00794 {
00795 octave_idx_type dgetri_info = 0;
00796
00797 F77_XFCN (dgetri, DGETRI, (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 Matrix
00812 Matrix::inverse (MatrixType &mattype, octave_idx_type& info, double& rcon,
00813 int force, int calc_cond) const
00814 {
00815 int typ = mattype.type (false);
00816 Matrix 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 CHOL 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 = Matrix (rows (), columns (), octave_Inf);
00845 }
00846
00847 return ret;
00848 }
00849
00850 Matrix
00851 Matrix::pseudo_inverse (double tol) const
00852 {
00853 SVD result (*this, SVD::economy);
00854
00855 DiagMatrix S = result.singular_values ();
00856 Matrix U = result.left_singular_matrix ();
00857 Matrix V = result.right_singular_matrix ();
00858
00859 ColumnVector 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 Matrix (nc, nr, 0.0);
00878 else
00879 {
00880 Matrix Ur = U.extract (0, 0, nr-1, r);
00881 DiagMatrix D = DiagMatrix (sigma.extract (0, r)) . inverse ();
00882 Matrix Vr = V.extract (0, 0, nc-1, r);
00883 return Vr * D * Ur.transpose ();
00884 }
00885 }
00886
00887 #if defined (HAVE_FFTW)
00888
00889 ComplexMatrix
00890 Matrix::fourier (void) const
00891 {
00892 size_t nr = rows ();
00893 size_t nc = cols ();
00894
00895 ComplexMatrix 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 double *in (fortran_vec ());
00911 Complex *out (retval.fortran_vec ());
00912
00913 octave_fftw::fft (in, out, npts, nsamples);
00914
00915 return retval;
00916 }
00917
00918 ComplexMatrix
00919 Matrix::ifourier (void) const
00920 {
00921 size_t nr = rows ();
00922 size_t nc = cols ();
00923
00924 ComplexMatrix 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 ComplexMatrix tmp (*this);
00940 Complex *in (tmp.fortran_vec ());
00941 Complex *out (retval.fortran_vec ());
00942
00943 octave_fftw::ifft (in, out, npts, nsamples);
00944
00945 return retval;
00946 }
00947
00948 ComplexMatrix
00949 Matrix::fourier2d (void) const
00950 {
00951 dim_vector dv(rows (), cols ());
00952
00953 const double *in = fortran_vec ();
00954 ComplexMatrix retval (rows (), cols ());
00955 octave_fftw::fftNd (in, retval.fortran_vec (), 2, dv);
00956
00957 return retval;
00958 }
00959
00960 ComplexMatrix
00961 Matrix::ifourier2d (void) const
00962 {
00963 dim_vector dv(rows (), cols ());
00964
00965 ComplexMatrix retval (*this);
00966 Complex *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
00978
00979
00980
00981
00982 F77_RET_T
00983 F77_FUNC (zffti, ZFFTI) (const octave_idx_type&, Complex*);
00984
00985 F77_RET_T
00986 F77_FUNC (zfftf, ZFFTF) (const octave_idx_type&, Complex*, Complex*);
00987
00988 F77_RET_T
00989 F77_FUNC (zfftb, ZFFTB) (const octave_idx_type&, Complex*, Complex*);
00990 }
00991
00992 ComplexMatrix
00993 Matrix::fourier (void) const
00994 {
00995 ComplexMatrix 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<Complex> wsave (dim_vector (nn, 1));
01016 Complex *pwsave = wsave.fortran_vec ();
01017
01018 retval = ComplexMatrix (*this);
01019 Complex *tmp_data = retval.fortran_vec ();
01020
01021 F77_FUNC (zffti, ZFFTI) (npts, pwsave);
01022
01023 for (octave_idx_type j = 0; j < nsamples; j++)
01024 {
01025 octave_quit ();
01026
01027 F77_FUNC (zfftf, ZFFTF) (npts, &tmp_data[npts*j], pwsave);
01028 }
01029
01030 return retval;
01031 }
01032
01033 ComplexMatrix
01034 Matrix::ifourier (void) const
01035 {
01036 ComplexMatrix 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<Complex> wsave (dim_vector (nn, 1));
01057 Complex *pwsave = wsave.fortran_vec ();
01058
01059 retval = ComplexMatrix (*this);
01060 Complex *tmp_data = retval.fortran_vec ();
01061
01062 F77_FUNC (zffti, ZFFTI) (npts, pwsave);
01063
01064 for (octave_idx_type j = 0; j < nsamples; j++)
01065 {
01066 octave_quit ();
01067
01068 F77_FUNC (zfftb, ZFFTB) (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<double> (npts);
01073
01074 return retval;
01075 }
01076
01077 ComplexMatrix
01078 Matrix::fourier2d (void) const
01079 {
01080 ComplexMatrix 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<Complex> wsave (dim_vector (nn, 1));
01101 Complex *pwsave = wsave.fortran_vec ();
01102
01103 retval = ComplexMatrix (*this);
01104 Complex *tmp_data = retval.fortran_vec ();
01105
01106 F77_FUNC (zffti, ZFFTI) (npts, pwsave);
01107
01108 for (octave_idx_type j = 0; j < nsamples; j++)
01109 {
01110 octave_quit ();
01111
01112 F77_FUNC (zfftf, ZFFTF) (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<Complex> tmp (dim_vector (npts, 1));
01123 Complex *prow = tmp.fortran_vec ();
01124
01125 F77_FUNC (zffti, ZFFTI) (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 (zfftf, ZFFTF) (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 ComplexMatrix
01144 Matrix::ifourier2d (void) const
01145 {
01146 ComplexMatrix 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<Complex> wsave (dim_vector (nn, 1));
01167 Complex *pwsave = wsave.fortran_vec ();
01168
01169 retval = ComplexMatrix (*this);
01170 Complex *tmp_data = retval.fortran_vec ();
01171
01172 F77_FUNC (zffti, ZFFTI) (npts, pwsave);
01173
01174 for (octave_idx_type j = 0; j < nsamples; j++)
01175 {
01176 octave_quit ();
01177
01178 F77_FUNC (zfftb, ZFFTB) (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<double> (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<Complex> tmp (dim_vector (npts, 1));
01192 Complex *prow = tmp.fortran_vec ();
01193
01194 F77_FUNC (zffti, ZFFTI) (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 (zfftb, ZFFTB) (npts, prow, pwsave);
01204
01205 for (octave_idx_type i = 0; i < npts; i++)
01206 tmp_data[i*nr + j] = prow[i] / static_cast<double> (npts);
01207 }
01208
01209 return retval;
01210 }
01211
01212 #endif
01213
01214 DET
01215 Matrix::determinant (void) const
01216 {
01217 octave_idx_type info;
01218 double rcon;
01219 return determinant (info, rcon, 0);
01220 }
01221
01222 DET
01223 Matrix::determinant (octave_idx_type& info) const
01224 {
01225 double rcon;
01226 return determinant (info, rcon, 0);
01227 }
01228
01229 DET
01230 Matrix::determinant (octave_idx_type& info, double& rcon, int calc_cond) const
01231 {
01232 MatrixType mattype (*this);
01233 return determinant (mattype, info, rcon, calc_cond);
01234 }
01235
01236 DET
01237 Matrix::determinant (MatrixType& mattype,
01238 octave_idx_type& info, double& rcon, int calc_cond) const
01239 {
01240 DET 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
01255
01256
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 Matrix atmp = *this;
01271 double *tmp_data = atmp.fortran_vec ();
01272
01273 double anorm = 0;
01274 if (calc_cond) anorm = xnorm (*this, 1);
01275
01276
01277 char job = 'L';
01278 F77_XFCN (dpotrf, DPOTRF, (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<double> z (dim_vector (3 * nc, 1));
01291 double *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 (dpocon, DPOCON, (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 Matrix atmp = *this;
01318 double *tmp_data = atmp.fortran_vec ();
01319
01320 info = 0;
01321
01322
01323 double anorm = 0;
01324 if (calc_cond) anorm = xnorm (*this, 1);
01325
01326 F77_XFCN (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, info));
01327
01328
01329 rcon = 0.0;
01330 if (info != 0)
01331 {
01332 info = -1;
01333 retval = DET ();
01334 }
01335 else
01336 {
01337 if (calc_cond)
01338 {
01339
01340 char job = '1';
01341 Array<double> z (dim_vector (4 * nc, 1));
01342 double *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 (dgecon, DGECON, (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 = DET ();
01356 }
01357 else
01358 {
01359 for (octave_idx_type i = 0; i < nc; i++)
01360 {
01361 double c = atmp(i,i);
01362 retval *= (ipvt(i) != (i+1)) ? -c : c;
01363 }
01364 }
01365 }
01366 }
01367 }
01368
01369 return retval;
01370 }
01371
01372 double
01373 Matrix::rcond (void) const
01374 {
01375 MatrixType mattype (*this);
01376 return rcond (mattype);
01377 }
01378
01379 double
01380 Matrix::rcond (MatrixType &mattype) const
01381 {
01382 double 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
01398 if (typ == MatrixType::Upper)
01399 {
01400 const double *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<double> z (dim_vector (3 * nc, 1));
01407 double *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 (dtrcon, DTRCON, (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 double *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<double> z (dim_vector (3 * nc, 1));
01435 double *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 (dtrcon, DTRCON, (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 double anorm = -1.0;
01457
01458 if (typ == MatrixType::Hermitian)
01459 {
01460 octave_idx_type info = 0;
01461 char job = 'L';
01462
01463 Matrix atmp = *this;
01464 double *tmp_data = atmp.fortran_vec ();
01465
01466 anorm = atmp.abs().sum().
01467 row(static_cast<octave_idx_type>(0)).max();
01468
01469 F77_XFCN (dpotrf, DPOTRF, (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<double> z (dim_vector (3 * nc, 1));
01482 double *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 (dpocon, DPOCON, (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 Matrix atmp = *this;
01501 double *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<double> z (dim_vector (4 * nc, 1));
01511 double *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 (dgetrf, DGETRF, (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 (dgecon, DGECON, (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 Matrix
01543 Matrix::utsolve (MatrixType &mattype, const Matrix& b, octave_idx_type& info,
01544 double& rcon, solve_singularity_handler sing_handler,
01545 bool calc_cond, blas_trans_type transt) const
01546 {
01547 Matrix 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 = Matrix (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 double *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<double> z (dim_vector (3 * nc, 1));
01584 double *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 (dtrcon, DTRCON, (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 double 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 double *result = retval.fortran_vec ();
01619
01620 char uplo = 'U';
01621 char trans = get_blas_char (transt);
01622 char dia = 'N';
01623
01624 F77_XFCN (dtrtrs, DTRTRS, (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 Matrix
01643 Matrix::ltsolve (MatrixType &mattype, const Matrix& b, octave_idx_type& info,
01644 double& rcon, solve_singularity_handler sing_handler,
01645 bool calc_cond, blas_trans_type transt) const
01646 {
01647 Matrix 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 = Matrix (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 double *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<double> z (dim_vector (3 * nc, 1));
01684 double *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 (dtrcon, DTRCON, (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 double 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 double *result = retval.fortran_vec ();
01719
01720 char uplo = 'L';
01721 char trans = get_blas_char (transt);
01722 char dia = 'N';
01723
01724 F77_XFCN (dtrtrs, DTRTRS, (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 Matrix
01743 Matrix::fsolve (MatrixType &mattype, const Matrix& b, octave_idx_type& info,
01744 double& rcon, solve_singularity_handler sing_handler,
01745 bool calc_cond) const
01746 {
01747 Matrix 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 = Matrix (nc, b.cols (), 0.0);
01757 else
01758 {
01759 volatile int typ = mattype.type ();
01760
01761
01762 double anorm = -1.;
01763
01764 if (typ == MatrixType::Hermitian)
01765 {
01766 info = 0;
01767 char job = 'L';
01768
01769 Matrix atmp = *this;
01770 double *tmp_data = atmp.fortran_vec ();
01771
01772 anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max();
01773
01774 F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
01775 tmp_data, nr, info
01776 F77_CHAR_ARG_LEN (1)));
01777
01778
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<double> z (dim_vector (3 * nc, 1));
01792 double *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 (dpocon, DPOCON, (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 double 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 double *result = retval.fortran_vec ();
01823
01824 octave_idx_type b_nc = b.cols ();
01825
01826 F77_XFCN (dpotrs, DPOTRS, (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 Matrix atmp = *this;
01847 double *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<double> z (dim_vector (4 * nc, 1));
01853 double *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 (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, info));
01858
01859
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
01878
01879 char job = '1';
01880 F77_XFCN (dgecon, DGECON, (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 double 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 double *result = retval.fortran_vec ();
01907
01908 octave_idx_type b_nc = b.cols ();
01909
01910 char job = 'N';
01911 F77_XFCN (dgetrs, DGETRS, (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 Matrix
01928 Matrix::solve (MatrixType &typ, const Matrix& b) const
01929 {
01930 octave_idx_type info;
01931 double rcon;
01932 return solve (typ, b, info, rcon, 0);
01933 }
01934
01935 Matrix
01936 Matrix::solve (MatrixType &typ, const Matrix& b, octave_idx_type& info) const
01937 {
01938 double rcon;
01939 return solve (typ, b, info, rcon, 0);
01940 }
01941
01942 Matrix
01943 Matrix::solve (MatrixType &typ, const Matrix& b, octave_idx_type& info,
01944 double& rcon) const
01945 {
01946 return solve (typ, b, info, rcon, 0);
01947 }
01948
01949 Matrix
01950 Matrix::solve (MatrixType &mattype, const Matrix& b, octave_idx_type& info,
01951 double& rcon, solve_singularity_handler sing_handler,
01952 bool singular_fallback, blas_trans_type transt) const
01953 {
01954 Matrix retval;
01955 int typ = mattype.type ();
01956
01957 if (typ == MatrixType::Unknown)
01958 typ = mattype.type (*this);
01959
01960
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 Matrix ();
01973 }
01974
01975
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 ComplexMatrix
01986 Matrix::solve (MatrixType &typ, const ComplexMatrix& b) const
01987 {
01988 octave_idx_type info;
01989 double rcon;
01990 return solve (typ, b, info, rcon, 0);
01991 }
01992
01993 ComplexMatrix
01994 Matrix::solve (MatrixType &typ, const ComplexMatrix& b,
01995 octave_idx_type& info) const
01996 {
01997 double rcon;
01998 return solve (typ, b, info, rcon, 0);
01999 }
02000
02001 ComplexMatrix
02002 Matrix::solve (MatrixType &typ, const ComplexMatrix& b, octave_idx_type& info,
02003 double& rcon) const
02004 {
02005 return solve (typ, b, info, rcon, 0);
02006 }
02007
02008 static Matrix
02009 stack_complex_matrix (const ComplexMatrix& cm)
02010 {
02011 octave_idx_type m = cm.rows (), n = cm.cols (), nel = m*n;
02012 Matrix retval (m, 2*n);
02013 const Complex *cmd = cm.data ();
02014 double *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 ComplexMatrix
02024 unstack_complex_matrix (const Matrix& sm)
02025 {
02026 octave_idx_type m = sm.rows (), n = sm.cols () / 2, nel = m*n;
02027 ComplexMatrix retval (m, n);
02028 const double *smd = sm.data ();
02029 Complex *rd = retval.fortran_vec ();
02030 for (octave_idx_type i = 0; i < nel; i++)
02031 rd[i] = Complex (smd[i], smd[nel+i]);
02032 return retval;
02033 }
02034
02035 ComplexMatrix
02036 Matrix::solve (MatrixType &typ, const ComplexMatrix& b, octave_idx_type& info,
02037 double& rcon, solve_singularity_handler sing_handler,
02038 bool singular_fallback, blas_trans_type transt) const
02039 {
02040 Matrix 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 ColumnVector
02046 Matrix::solve (MatrixType &typ, const ColumnVector& b) const
02047 {
02048 octave_idx_type info; double rcon;
02049 return solve (typ, b, info, rcon);
02050 }
02051
02052 ColumnVector
02053 Matrix::solve (MatrixType &typ, const ColumnVector& b,
02054 octave_idx_type& info) const
02055 {
02056 double rcon;
02057 return solve (typ, b, info, rcon);
02058 }
02059
02060 ColumnVector
02061 Matrix::solve (MatrixType &typ, const ColumnVector& b, octave_idx_type& info,
02062 double& rcon) const
02063 {
02064 return solve (typ, b, info, rcon, 0);
02065 }
02066
02067 ColumnVector
02068 Matrix::solve (MatrixType &typ, const ColumnVector& b, octave_idx_type& info,
02069 double& rcon, solve_singularity_handler sing_handler, blas_trans_type transt) const
02070 {
02071 Matrix 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 ComplexColumnVector
02077 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b) const
02078 {
02079 ComplexMatrix tmp (*this);
02080 return tmp.solve (typ, b);
02081 }
02082
02083 ComplexColumnVector
02084 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b,
02085 octave_idx_type& info) const
02086 {
02087 ComplexMatrix tmp (*this);
02088 return tmp.solve (typ, b, info);
02089 }
02090
02091 ComplexColumnVector
02092 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b,
02093 octave_idx_type& info, double& rcon) const
02094 {
02095 ComplexMatrix tmp (*this);
02096 return tmp.solve (typ, b, info, rcon);
02097 }
02098
02099 ComplexColumnVector
02100 Matrix::solve (MatrixType &typ, const ComplexColumnVector& b,
02101 octave_idx_type& info, double& rcon,
02102 solve_singularity_handler sing_handler, blas_trans_type transt) const
02103 {
02104 ComplexMatrix tmp (*this);
02105 return tmp.solve(typ, b, info, rcon, sing_handler, transt);
02106 }
02107
02108 Matrix
02109 Matrix::solve (const Matrix& b) const
02110 {
02111 octave_idx_type info;
02112 double rcon;
02113 return solve (b, info, rcon, 0);
02114 }
02115
02116 Matrix
02117 Matrix::solve (const Matrix& b, octave_idx_type& info) const
02118 {
02119 double rcon;
02120 return solve (b, info, rcon, 0);
02121 }
02122
02123 Matrix
02124 Matrix::solve (const Matrix& b, octave_idx_type& info, double& rcon) const
02125 {
02126 return solve (b, info, rcon, 0);
02127 }
02128
02129 Matrix
02130 Matrix::solve (const Matrix& b, octave_idx_type& info,
02131 double& 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 ComplexMatrix
02138 Matrix::solve (const ComplexMatrix& b) const
02139 {
02140 ComplexMatrix tmp (*this);
02141 return tmp.solve (b);
02142 }
02143
02144 ComplexMatrix
02145 Matrix::solve (const ComplexMatrix& b, octave_idx_type& info) const
02146 {
02147 ComplexMatrix tmp (*this);
02148 return tmp.solve (b, info);
02149 }
02150
02151 ComplexMatrix
02152 Matrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon) const
02153 {
02154 ComplexMatrix tmp (*this);
02155 return tmp.solve (b, info, rcon);
02156 }
02157
02158 ComplexMatrix
02159 Matrix::solve (const ComplexMatrix& b, octave_idx_type& info, double& rcon,
02160 solve_singularity_handler sing_handler, blas_trans_type transt) const
02161 {
02162 ComplexMatrix tmp (*this);
02163 return tmp.solve (b, info, rcon, sing_handler, transt);
02164 }
02165
02166 ColumnVector
02167 Matrix::solve (const ColumnVector& b) const
02168 {
02169 octave_idx_type info; double rcon;
02170 return solve (b, info, rcon);
02171 }
02172
02173 ColumnVector
02174 Matrix::solve (const ColumnVector& b, octave_idx_type& info) const
02175 {
02176 double rcon;
02177 return solve (b, info, rcon);
02178 }
02179
02180 ColumnVector
02181 Matrix::solve (const ColumnVector& b, octave_idx_type& info, double& rcon) const
02182 {
02183 return solve (b, info, rcon, 0);
02184 }
02185
02186 ColumnVector
02187 Matrix::solve (const ColumnVector& b, octave_idx_type& info, double& 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 ComplexColumnVector
02195 Matrix::solve (const ComplexColumnVector& b) const
02196 {
02197 ComplexMatrix tmp (*this);
02198 return tmp.solve (b);
02199 }
02200
02201 ComplexColumnVector
02202 Matrix::solve (const ComplexColumnVector& b, octave_idx_type& info) const
02203 {
02204 ComplexMatrix tmp (*this);
02205 return tmp.solve (b, info);
02206 }
02207
02208 ComplexColumnVector
02209 Matrix::solve (const ComplexColumnVector& b, octave_idx_type& info, double& rcon) const
02210 {
02211 ComplexMatrix tmp (*this);
02212 return tmp.solve (b, info, rcon);
02213 }
02214
02215 ComplexColumnVector
02216 Matrix::solve (const ComplexColumnVector& b, octave_idx_type& info, double& rcon,
02217 solve_singularity_handler sing_handler, blas_trans_type transt) const
02218 {
02219 ComplexMatrix tmp (*this);
02220 return tmp.solve (b, info, rcon, sing_handler, transt);
02221 }
02222
02223 Matrix
02224 Matrix::lssolve (const Matrix& b) const
02225 {
02226 octave_idx_type info;
02227 octave_idx_type rank;
02228 double rcon;
02229 return lssolve (b, info, rank, rcon);
02230 }
02231
02232 Matrix
02233 Matrix::lssolve (const Matrix& b, octave_idx_type& info) const
02234 {
02235 octave_idx_type rank;
02236 double rcon;
02237 return lssolve (b, info, rank, rcon);
02238 }
02239
02240 Matrix
02241 Matrix::lssolve (const Matrix& b, octave_idx_type& info,
02242 octave_idx_type& rank) const
02243 {
02244 double rcon;
02245 return lssolve (b, info, rank, rcon);
02246 }
02247
02248 Matrix
02249 Matrix::lssolve (const Matrix& b, octave_idx_type& info,
02250 octave_idx_type& rank, double &rcon) const
02251 {
02252 Matrix 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 = Matrix (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 = Matrix (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 Matrix atmp = *this;
02281 double *tmp_data = atmp.fortran_vec ();
02282
02283 double *pretval = retval.fortran_vec ();
02284 Array<double> s (dim_vector (minmn, 1));
02285 double *ps = s.fortran_vec ();
02286
02287
02288 octave_idx_type lwork = -1;
02289
02290 Array<double> work (dim_vector (1, 1));
02291
02292 octave_idx_type smlsiz;
02293 F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("DGELSD", 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 ("DGELSD", 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
02307
02308 double dminmn = static_cast<double> (minmn);
02309 double dsmlsizp1 = static_cast<double> (smlsiz+1);
02310 #if defined (HAVE_LOG2)
02311 double tmp = log2 (dminmn / dsmlsizp1);
02312 #else
02313 double 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 (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
02326 ps, rcon, rank, work.fortran_vec (),
02327 lwork, piwork, info));
02328
02329
02330
02331
02332
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 (dgelsd, DGELSD, (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 ComplexMatrix
02386 Matrix::lssolve (const ComplexMatrix& b) const
02387 {
02388 ComplexMatrix tmp (*this);
02389 octave_idx_type info;
02390 octave_idx_type rank;
02391 double rcon;
02392 return tmp.lssolve (b, info, rank, rcon);
02393 }
02394
02395 ComplexMatrix
02396 Matrix::lssolve (const ComplexMatrix& b, octave_idx_type& info) const
02397 {
02398 ComplexMatrix tmp (*this);
02399 octave_idx_type rank;
02400 double rcon;
02401 return tmp.lssolve (b, info, rank, rcon);
02402 }
02403
02404 ComplexMatrix
02405 Matrix::lssolve (const ComplexMatrix& b, octave_idx_type& info,
02406 octave_idx_type& rank) const
02407 {
02408 ComplexMatrix tmp (*this);
02409 double rcon;
02410 return tmp.lssolve (b, info, rank, rcon);
02411 }
02412
02413 ComplexMatrix
02414 Matrix::lssolve (const ComplexMatrix& b, octave_idx_type& info,
02415 octave_idx_type& rank, double& rcon) const
02416 {
02417 ComplexMatrix tmp (*this);
02418 return tmp.lssolve (b, info, rank, rcon);
02419 }
02420
02421 ColumnVector
02422 Matrix::lssolve (const ColumnVector& b) const
02423 {
02424 octave_idx_type info;
02425 octave_idx_type rank;
02426 double rcon;
02427 return lssolve (b, info, rank, rcon);
02428 }
02429
02430 ColumnVector
02431 Matrix::lssolve (const ColumnVector& b, octave_idx_type& info) const
02432 {
02433 octave_idx_type rank;
02434 double rcon;
02435 return lssolve (b, info, rank, rcon);
02436 }
02437
02438 ColumnVector
02439 Matrix::lssolve (const ColumnVector& b, octave_idx_type& info,
02440 octave_idx_type& rank) const
02441 {
02442 double rcon;
02443 return lssolve (b, info, rank, rcon);
02444 }
02445
02446 ColumnVector
02447 Matrix::lssolve (const ColumnVector& b, octave_idx_type& info,
02448 octave_idx_type& rank, double &rcon) const
02449 {
02450 ColumnVector 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 = ColumnVector (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 = ColumnVector (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 Matrix atmp = *this;
02479 double *tmp_data = atmp.fortran_vec ();
02480
02481 double *pretval = retval.fortran_vec ();
02482 Array<double> s (dim_vector (minmn, 1));
02483 double *ps = s.fortran_vec ();
02484
02485
02486 octave_idx_type lwork = -1;
02487
02488 Array<double> work (dim_vector (1, 1));
02489
02490 octave_idx_type smlsiz;
02491 F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("DGELSD", 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
02498
02499 double dminmn = static_cast<double> (minmn);
02500 double dsmlsizp1 = static_cast<double> (smlsiz+1);
02501 #if defined (HAVE_LOG2)
02502 double tmp = log2 (dminmn / dsmlsizp1);
02503 #else
02504 double 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 (dgelsd, DGELSD, (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 (dgelsd, DGELSD, (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 ComplexColumnVector
02543 Matrix::lssolve (const ComplexColumnVector& b) const
02544 {
02545 ComplexMatrix tmp (*this);
02546 octave_idx_type info;
02547 octave_idx_type rank;
02548 double rcon;
02549 return tmp.lssolve (b, info, rank, rcon);
02550 }
02551
02552 ComplexColumnVector
02553 Matrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info) const
02554 {
02555 ComplexMatrix tmp (*this);
02556 octave_idx_type rank;
02557 double rcon;
02558 return tmp.lssolve (b, info, rank, rcon);
02559 }
02560
02561 ComplexColumnVector
02562 Matrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info,
02563 octave_idx_type& rank) const
02564 {
02565 ComplexMatrix tmp (*this);
02566 double rcon;
02567 return tmp.lssolve (b, info, rank, rcon);
02568 }
02569
02570 ComplexColumnVector
02571 Matrix::lssolve (const ComplexColumnVector& b, octave_idx_type& info,
02572 octave_idx_type& rank, double &rcon) const
02573 {
02574 ComplexMatrix tmp (*this);
02575 return tmp.lssolve (b, info, rank, rcon);
02576 }
02577
02578 Matrix&
02579 Matrix::operator += (const DiagMatrix& 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 Matrix&
02600 Matrix::operator -= (const DiagMatrix& 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
02621
02622 boolMatrix
02623 Matrix::operator ! (void) const
02624 {
02625 if (any_element_is_nan ())
02626 gripe_nan_to_logical_conversion ();
02627
02628 return do_mx_unary_op<bool, double> (*this, mx_inline_not);
02629 }
02630
02631
02632
02633 Matrix
02634 operator * (const ColumnVector& v, const RowVector& a)
02635 {
02636 Matrix 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 = Matrix (len, a_len);
02645 double *c = retval.fortran_vec ();
02646
02647 F77_XFCN (dgemm, DGEMM, (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
02659
02660 bool
02661 Matrix::any_element_is_negative (bool neg_zero) const
02662 {
02663 return (neg_zero ? test_all (xnegative_sign)
02664 : do_mx_check<double> (*this, mx_inline_any_negative));
02665 }
02666
02667 bool
02668 Matrix::any_element_is_positive (bool neg_zero) const
02669 {
02670 return (neg_zero ? test_all (xpositive_sign)
02671 : do_mx_check<double> (*this, mx_inline_any_positive));
02672 }
02673
02674 bool
02675 Matrix::any_element_is_nan (void) const
02676 {
02677 return do_mx_check<double> (*this, mx_inline_any_nan);
02678 }
02679
02680 bool
02681 Matrix::any_element_is_inf_or_nan (void) const
02682 {
02683 return ! do_mx_check<double> (*this, mx_inline_all_finite);
02684 }
02685
02686 bool
02687 Matrix::any_element_not_one_or_zero (void) const
02688 {
02689 return ! test_all (xis_one_or_zero);
02690 }
02691
02692 bool
02693 Matrix::all_elements_are_int_or_inf_or_nan (void) const
02694 {
02695 return test_all (xis_int_or_inf_or_nan);
02696 }
02697
02698
02699
02700
02701 bool
02702 Matrix::all_integers (double& max_val, double& 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 double 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 Matrix::too_large_for_float (void) const
02733 {
02734 return test_all (xtoo_large_for_float);
02735 }
02736
02737
02738
02739
02740 boolMatrix
02741 Matrix::all (int dim) const
02742 {
02743 return do_mx_red_op<bool, double> (*this, dim, mx_inline_all);
02744 }
02745
02746 boolMatrix
02747 Matrix::any (int dim) const
02748 {
02749 return do_mx_red_op<bool, double> (*this, dim, mx_inline_any);
02750 }
02751
02752 Matrix
02753 Matrix::cumprod (int dim) const
02754 {
02755 return do_mx_cum_op<double, double> (*this, dim, mx_inline_cumprod);
02756 }
02757
02758 Matrix
02759 Matrix::cumsum (int dim) const
02760 {
02761 return do_mx_cum_op<double, double> (*this, dim, mx_inline_cumsum);
02762 }
02763
02764 Matrix
02765 Matrix::prod (int dim) const
02766 {
02767 return do_mx_red_op<double, double> (*this, dim, mx_inline_prod);
02768 }
02769
02770 Matrix
02771 Matrix::sum (int dim) const
02772 {
02773 return do_mx_red_op<double, double> (*this, dim, mx_inline_sum);
02774 }
02775
02776 Matrix
02777 Matrix::sumsq (int dim) const
02778 {
02779 return do_mx_red_op<double, double> (*this, dim, mx_inline_sumsq);
02780 }
02781
02782 Matrix
02783 Matrix::abs (void) const
02784 {
02785 return do_mx_unary_map<double, double, std::abs> (*this);
02786 }
02787
02788 Matrix
02789 Matrix::diag (octave_idx_type k) const
02790 {
02791 return MArray<double>::diag (k);
02792 }
02793
02794 ColumnVector
02795 Matrix::row_min (void) const
02796 {
02797 Array<octave_idx_type> dummy_idx;
02798 return row_min (dummy_idx);
02799 }
02800
02801 ColumnVector
02802 Matrix::row_min (Array<octave_idx_type>& idx_arg) const
02803 {
02804 ColumnVector 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 double tmp_min = octave_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 double 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 ColumnVector
02850 Matrix::row_max (void) const
02851 {
02852 Array<octave_idx_type> dummy_idx;
02853 return row_max (dummy_idx);
02854 }
02855
02856 ColumnVector
02857 Matrix::row_max (Array<octave_idx_type>& idx_arg) const
02858 {
02859 ColumnVector 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 double tmp_max = octave_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 double 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 RowVector
02905 Matrix::column_min (void) const
02906 {
02907 Array<octave_idx_type> dummy_idx;
02908 return column_min (dummy_idx);
02909 }
02910
02911 RowVector
02912 Matrix::column_min (Array<octave_idx_type>& idx_arg) const
02913 {
02914 RowVector 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 double tmp_min = octave_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 double 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 RowVector
02960 Matrix::column_max (void) const
02961 {
02962 Array<octave_idx_type> dummy_idx;
02963 return column_max (dummy_idx);
02964 }
02965
02966 RowVector
02967 Matrix::column_max (Array<octave_idx_type>& idx_arg) const
02968 {
02969 RowVector 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 double tmp_max = octave_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 double 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 Matrix& 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_double (os, a.elem (i, j));
03023 }
03024 os << "\n";
03025 }
03026 return os;
03027 }
03028
03029 std::istream&
03030 operator >> (std::istream& is, Matrix& 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 double 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<double> (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 Matrix
03055 Givens (double x, double y)
03056 {
03057 double cc, s, temp_r;
03058
03059 F77_FUNC (dlartg, DLARTG) (x, y, cc, s, temp_r);
03060
03061 Matrix 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 Matrix
03072 Sylvester (const Matrix& a, const Matrix& b, const Matrix& c)
03073 {
03074 Matrix retval;
03075
03076
03077
03078
03079
03080
03081 SCHUR as (a, "U");
03082 SCHUR bs (b, "U");
03083
03084
03085
03086 Matrix ua = as.unitary_matrix ();
03087 Matrix sch_a = as.schur_matrix ();
03088
03089 Matrix ub = bs.unitary_matrix ();
03090 Matrix sch_b = bs.schur_matrix ();
03091
03092 Matrix cx = ua.transpose () * c * ub;
03093
03094
03095
03096
03097 octave_idx_type a_nr = a.rows ();
03098 octave_idx_type b_nr = b.rows ();
03099
03100 double scale;
03101 octave_idx_type info;
03102
03103 double *pa = sch_a.fortran_vec ();
03104 double *pb = sch_b.fortran_vec ();
03105 double *px = cx.fortran_vec ();
03106
03107 F77_XFCN (dtrsyl, DTRSYL, (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
03116
03117 retval = -ua*cx*ub.transpose ();
03118
03119 return retval;
03120 }
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146 static inline char
03147 get_blas_trans_arg (bool trans)
03148 {
03149 return trans ? 'T' : 'N';
03150 }
03151
03152
03153
03154 Matrix
03155 xgemm (const Matrix& a, const Matrix& b,
03156 blas_trans_type transa, blas_trans_type transb)
03157 {
03158 Matrix retval;
03159
03160 bool tra = transa != blas_no_trans, trb = transb != blas_no_trans;
03161
03162 octave_idx_type a_nr = tra ? a.cols () : a.rows ();
03163 octave_idx_type a_nc = tra ? a.rows () : a.cols ();
03164
03165 octave_idx_type b_nr = trb ? b.cols () : b.rows ();
03166 octave_idx_type b_nc = trb ? b.rows () : b.cols ();
03167
03168 if (a_nc != b_nr)
03169 gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
03170 else
03171 {
03172 if (a_nr == 0 || a_nc == 0 || b_nc == 0)
03173 retval = Matrix (a_nr, b_nc, 0.0);
03174 else if (a.data () == b.data () && a_nr == b_nc && tra != trb)
03175 {
03176 octave_idx_type lda = a.rows ();
03177
03178 retval = Matrix (a_nr, b_nc);
03179 double *c = retval.fortran_vec ();
03180
03181 const char ctra = get_blas_trans_arg (tra);
03182 F77_XFCN (dsyrk, DSYRK, (F77_CONST_CHAR_ARG2 ("U", 1),
03183 F77_CONST_CHAR_ARG2 (&ctra, 1),
03184 a_nr, a_nc, 1.0,
03185 a.data (), lda, 0.0, c, a_nr
03186 F77_CHAR_ARG_LEN (1)
03187 F77_CHAR_ARG_LEN (1)));
03188 for (int j = 0; j < a_nr; j++)
03189 for (int i = 0; i < j; i++)
03190 retval.xelem (j,i) = retval.xelem (i,j);
03191
03192 }
03193 else
03194 {
03195 octave_idx_type lda = a.rows (), tda = a.cols ();
03196 octave_idx_type ldb = b.rows (), tdb = b.cols ();
03197
03198 retval = Matrix (a_nr, b_nc);
03199 double *c = retval.fortran_vec ();
03200
03201 if (b_nc == 1)
03202 {
03203 if (a_nr == 1)
03204 F77_FUNC (xddot, XDDOT) (a_nc, a.data (), 1, b.data (), 1, *c);
03205 else
03206 {
03207 const char ctra = get_blas_trans_arg (tra);
03208 F77_XFCN (dgemv, DGEMV, (F77_CONST_CHAR_ARG2 (&ctra, 1),
03209 lda, tda, 1.0, a.data (), lda,
03210 b.data (), 1, 0.0, c, 1
03211 F77_CHAR_ARG_LEN (1)));
03212 }
03213 }
03214 else if (a_nr == 1)
03215 {
03216 const char crevtrb = get_blas_trans_arg (! trb);
03217 F77_XFCN (dgemv, DGEMV, (F77_CONST_CHAR_ARG2 (&crevtrb, 1),
03218 ldb, tdb, 1.0, b.data (), ldb,
03219 a.data (), 1, 0.0, c, 1
03220 F77_CHAR_ARG_LEN (1)));
03221 }
03222 else
03223 {
03224 const char ctra = get_blas_trans_arg (tra);
03225 const char ctrb = get_blas_trans_arg (trb);
03226 F77_XFCN (dgemm, DGEMM, (F77_CONST_CHAR_ARG2 (&ctra, 1),
03227 F77_CONST_CHAR_ARG2 (&ctrb, 1),
03228 a_nr, b_nc, a_nc, 1.0, a.data (),
03229 lda, b.data (), ldb, 0.0, c, a_nr
03230 F77_CHAR_ARG_LEN (1)
03231 F77_CHAR_ARG_LEN (1)));
03232 }
03233 }
03234 }
03235
03236 return retval;
03237 }
03238
03239 Matrix
03240 operator * (const Matrix& a, const Matrix& b)
03241 {
03242 return xgemm (a, b);
03243 }
03244
03245
03246
03247
03248 #define EMPTY_RETURN_CHECK(T) \
03249 if (nr == 0 || nc == 0) \
03250 return T (nr, nc);
03251
03252 Matrix
03253 min (double d, const Matrix& m)
03254 {
03255 octave_idx_type nr = m.rows ();
03256 octave_idx_type nc = m.columns ();
03257
03258 EMPTY_RETURN_CHECK (Matrix);
03259
03260 Matrix result (nr, nc);
03261
03262 for (octave_idx_type j = 0; j < nc; j++)
03263 for (octave_idx_type i = 0; i < nr; i++)
03264 {
03265 octave_quit ();
03266 result (i, j) = xmin (d, m (i, j));
03267 }
03268
03269 return result;
03270 }
03271
03272 Matrix
03273 min (const Matrix& m, double d)
03274 {
03275 octave_idx_type nr = m.rows ();
03276 octave_idx_type nc = m.columns ();
03277
03278 EMPTY_RETURN_CHECK (Matrix);
03279
03280 Matrix result (nr, nc);
03281
03282 for (octave_idx_type j = 0; j < nc; j++)
03283 for (octave_idx_type i = 0; i < nr; i++)
03284 {
03285 octave_quit ();
03286 result (i, j) = xmin (m (i, j), d);
03287 }
03288
03289 return result;
03290 }
03291
03292 Matrix
03293 min (const Matrix& a, const Matrix& b)
03294 {
03295 octave_idx_type nr = a.rows ();
03296 octave_idx_type nc = a.columns ();
03297
03298 if (nr != b.rows () || nc != b.columns ())
03299 {
03300 (*current_liboctave_error_handler)
03301 ("two-arg min expecting args of same size");
03302 return Matrix ();
03303 }
03304
03305 EMPTY_RETURN_CHECK (Matrix);
03306
03307 Matrix result (nr, nc);
03308
03309 for (octave_idx_type j = 0; j < nc; j++)
03310 for (octave_idx_type i = 0; i < nr; i++)
03311 {
03312 octave_quit ();
03313 result (i, j) = xmin (a (i, j), b (i, j));
03314 }
03315
03316 return result;
03317 }
03318
03319 Matrix
03320 max (double d, const Matrix& m)
03321 {
03322 octave_idx_type nr = m.rows ();
03323 octave_idx_type nc = m.columns ();
03324
03325 EMPTY_RETURN_CHECK (Matrix);
03326
03327 Matrix result (nr, nc);
03328
03329 for (octave_idx_type j = 0; j < nc; j++)
03330 for (octave_idx_type i = 0; i < nr; i++)
03331 {
03332 octave_quit ();
03333 result (i, j) = xmax (d, m (i, j));
03334 }
03335
03336 return result;
03337 }
03338
03339 Matrix
03340 max (const Matrix& m, double d)
03341 {
03342 octave_idx_type nr = m.rows ();
03343 octave_idx_type nc = m.columns ();
03344
03345 EMPTY_RETURN_CHECK (Matrix);
03346
03347 Matrix result (nr, nc);
03348
03349 for (octave_idx_type j = 0; j < nc; j++)
03350 for (octave_idx_type i = 0; i < nr; i++)
03351 {
03352 octave_quit ();
03353 result (i, j) = xmax (m (i, j), d);
03354 }
03355
03356 return result;
03357 }
03358
03359 Matrix
03360 max (const Matrix& a, const Matrix& b)
03361 {
03362 octave_idx_type nr = a.rows ();
03363 octave_idx_type nc = a.columns ();
03364
03365 if (nr != b.rows () || nc != b.columns ())
03366 {
03367 (*current_liboctave_error_handler)
03368 ("two-arg max expecting args of same size");
03369 return Matrix ();
03370 }
03371
03372 EMPTY_RETURN_CHECK (Matrix);
03373
03374 Matrix result (nr, nc);
03375
03376 for (octave_idx_type j = 0; j < nc; j++)
03377 for (octave_idx_type i = 0; i < nr; i++)
03378 {
03379 octave_quit ();
03380 result (i, j) = xmax (a (i, j), b (i, j));
03381 }
03382
03383 return result;
03384 }
03385
03386 Matrix linspace (const ColumnVector& x1,
03387 const ColumnVector& x2,
03388 octave_idx_type n)
03389
03390 {
03391 if (n < 1) n = 1;
03392
03393 octave_idx_type m = x1.length ();
03394
03395 if (x2.length () != m)
03396 (*current_liboctave_error_handler) ("linspace: vectors must be of equal length");
03397
03398 NoAlias<Matrix> retval;
03399
03400 retval.clear (m, n);
03401 for (octave_idx_type i = 0; i < m; i++)
03402 retval(i, 0) = x1(i);
03403
03404
03405 double *delta = &retval(0, n-1);
03406 for (octave_idx_type i = 0; i < m; i++)
03407 delta[i] = (x2(i) - x1(i)) / (n - 1);
03408
03409 for (octave_idx_type j = 1; j < n-1; j++)
03410 for (octave_idx_type i = 0; i < m; i++)
03411 retval(i, j) = x1(i) + j*delta[i];
03412
03413 for (octave_idx_type i = 0; i < m; i++)
03414 retval(i, n-1) = x2(i);
03415
03416 return retval;
03417 }
03418
03419 MS_CMP_OPS (Matrix, double)
03420 MS_BOOL_OPS (Matrix, double)
03421
03422 SM_CMP_OPS (double, Matrix)
03423 SM_BOOL_OPS (double, Matrix)
03424
03425 MM_CMP_OPS (Matrix, Matrix)
03426 MM_BOOL_OPS (Matrix, Matrix)