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 "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
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
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
00273
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
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
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;
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
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
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
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 (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;
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
00978
00979
00980
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
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 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
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
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
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
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
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
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
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 (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
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
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
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
02307
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
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 (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
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
02498
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
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
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
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
02699
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
02738
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
03077
03078
03079
03080
03081 FloatSCHUR as (a, "U");
03082 FloatSCHUR bs (b, "U");
03083
03084
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
03095
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
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 static char
03143 get_blas_trans_arg (bool trans)
03144 {
03145 return trans ? 'T' : 'N';
03146 }
03147
03148
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
03242
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
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)