00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <algorithm>
00028
00029 #include "ov.h"
00030 #include "defun-dld.h"
00031 #include "error.h"
00032 #include "ov-re-mat.h"
00033 #include "ov-cx-mat.h"
00034 #include "ov-re-sparse.h"
00035 #include "ov-cx-sparse.h"
00036 #include "MatrixType.h"
00037 #include "oct-locbuf.h"
00038
00039 DEFUN_DLD (matrix_type, args, ,
00040 "-*- texinfo -*-\n\
00041 @deftypefn {Loadable Function} {@var{type} =} matrix_type (@var{A})\n\
00042 @deftypefnx {Loadable Function} {@var{type} =} matrix_type (@var{A}, 'nocompute')\n\
00043 @deftypefnx {Loadable Function} {@var{A} =} matrix_type (@var{A}, @var{type})\n\
00044 @deftypefnx {Loadable Function} {@var{A} =} matrix_type (@var{A}, 'upper', @var{perm})\n\
00045 @deftypefnx {Loadable Function} {@var{A} =} matrix_type (@var{A}, 'lower', @var{perm})\n\
00046 @deftypefnx {Loadable Function} {@var{A} =} matrix_type (@var{A}, 'banded', @var{nl}, @var{nu})\n\
00047 Identify the matrix type or mark a matrix as a particular type. This allows\n\
00048 more rapid solutions of linear equations involving @var{A} to be performed.\n\
00049 Called with a single argument, @code{matrix_type} returns the type of the\n\
00050 matrix and caches it for future use. Called with more than one argument,\n\
00051 @code{matrix_type} allows the type of the matrix to be defined.\n\
00052 \n\
00053 If the option 'nocompute' is given, the function will not attempt to guess\n\
00054 the type if it is still unknown. This is useful for debugging purposes.\n\
00055 \n\
00056 The possible matrix types depend on whether the matrix is full or sparse, and\n\
00057 can be one of the following\n\
00058 \n\
00059 @table @asis\n\
00060 @item 'unknown'\n\
00061 Remove any previously cached matrix type, and mark type as unknown.\n\
00062 \n\
00063 @item 'full'\n\
00064 Mark the matrix as full.\n\
00065 \n\
00066 @item 'positive definite'\n\
00067 Probable full positive definite matrix.\n\
00068 \n\
00069 @item 'diagonal'\n\
00070 Diagonal matrix. (Sparse matrices only)\n\
00071 \n\
00072 @item 'permuted diagonal'\n\
00073 Permuted Diagonal matrix. The permutation does not need to be specifically\n\
00074 indicated, as the structure of the matrix explicitly gives this. (Sparse\n\
00075 matrices only)\n\
00076 \n\
00077 @item 'upper'\n\
00078 Upper triangular. If the optional third argument @var{perm} is given, the\n\
00079 matrix is assumed to be a permuted upper triangular with the permutations\n\
00080 defined by the vector @var{perm}.\n\
00081 \n\
00082 @item 'lower'\n\
00083 Lower triangular. If the optional third argument @var{perm} is given, the\n\
00084 matrix is assumed to be a permuted lower triangular with the permutations\n\
00085 defined by the vector @var{perm}.\n\
00086 \n\
00087 @item 'banded'\n\
00088 @itemx 'banded positive definite'\n\
00089 Banded matrix with the band size of @var{nl} below the diagonal and @var{nu}\n\
00090 above it. If @var{nl} and @var{nu} are 1, then the matrix is tridiagonal and\n\
00091 treated with specialized code. In addition the matrix can be marked as\n\
00092 probably a positive definite. (Sparse matrices only)\n\
00093 \n\
00094 @item 'singular'\n\
00095 The matrix is assumed to be singular and will be treated with a minimum norm\n\
00096 solution.\n\
00097 \n\
00098 @end table\n\
00099 \n\
00100 Note that the matrix type will be discovered automatically on the first\n\
00101 attempt to solve a linear equation involving @var{A}. Therefore\n\
00102 @code{matrix_type} is only useful to give Octave hints of the matrix type.\n\
00103 Incorrectly defining the matrix type will result in incorrect results from\n\
00104 solutions of linear equations; it is entirely @strong{the responsibility of\n\
00105 the user} to correctly identify the matrix type.\n\
00106 \n\
00107 Also, the test for positive definiteness is a low-cost test for a Hermitian\n\
00108 matrix with a real positive diagonal. This does not guarantee that the\n\
00109 matrix is positive definite, but only that it is a probable candidate. When\n\
00110 such a matrix is factorized, a Cholesky@tie{}factorization is first\n\
00111 attempted, and if that fails the matrix is then treated with an\n\
00112 LU@tie{}factorization. Once the matrix has been factorized,\n\
00113 @code{matrix_type} will return the correct classification of the matrix.\n\
00114 @end deftypefn")
00115 {
00116 int nargin = args.length ();
00117 octave_value retval;
00118
00119 if (nargin == 0)
00120 print_usage ();
00121 else if (nargin > 4)
00122 error ("matrix_type: incorrect number of arguments");
00123 else
00124 {
00125 bool autocomp = true;
00126 if (nargin == 2 && args(1).is_string () && args(1).string_value () == "nocompute")
00127 {
00128 nargin = 1;
00129 autocomp = false;
00130 }
00131
00132 if (args(0).is_scalar_type())
00133 {
00134 if (nargin == 1)
00135 retval = octave_value ("Diagonal");
00136 else
00137 retval = args(0);
00138 }
00139 else if (args(0).is_sparse_type ())
00140 {
00141 if (nargin == 1)
00142 {
00143 MatrixType mattyp;
00144
00145 if (args(0).is_complex_type ())
00146 {
00147 mattyp = args(0).matrix_type ();
00148
00149 if (mattyp.is_unknown () && autocomp )
00150 {
00151 SparseComplexMatrix m =
00152 args(0).sparse_complex_matrix_value ();
00153 if (!error_state)
00154 {
00155 mattyp = MatrixType (m);
00156 args(0).matrix_type (mattyp);
00157 }
00158 }
00159 }
00160 else
00161 {
00162 mattyp = args(0).matrix_type ();
00163
00164 if (mattyp.is_unknown () && autocomp)
00165 {
00166 SparseMatrix m = args(0).sparse_matrix_value ();
00167 if (!error_state)
00168 {
00169 mattyp = MatrixType (m);
00170 args(0).matrix_type (mattyp);
00171 }
00172 }
00173 }
00174
00175 int typ = mattyp.type ();
00176
00177 if (typ == MatrixType::Diagonal)
00178 retval = octave_value ("Diagonal");
00179 else if (typ == MatrixType::Permuted_Diagonal)
00180 retval = octave_value ("Permuted Diagonal");
00181 else if (typ == MatrixType::Upper)
00182 retval = octave_value ("Upper");
00183 else if (typ == MatrixType::Permuted_Upper)
00184 retval = octave_value ("Permuted Upper");
00185 else if (typ == MatrixType::Lower)
00186 retval = octave_value ("Lower");
00187 else if (typ == MatrixType::Permuted_Lower)
00188 retval = octave_value ("Permuted Lower");
00189 else if (typ == MatrixType::Banded)
00190 retval = octave_value ("Banded");
00191 else if (typ == MatrixType::Banded_Hermitian)
00192 retval = octave_value ("Banded Positive Definite");
00193 else if (typ == MatrixType::Tridiagonal)
00194 retval = octave_value ("Tridiagonal");
00195 else if (typ == MatrixType::Tridiagonal_Hermitian)
00196 retval = octave_value ("Tridiagonal Positive Definite");
00197 else if (typ == MatrixType::Hermitian)
00198 retval = octave_value ("Positive Definite");
00199 else if (typ == MatrixType::Rectangular)
00200 {
00201 if (args(0).rows() == args(0).columns())
00202 retval = octave_value ("Singular");
00203 else
00204 retval = octave_value ("Rectangular");
00205 }
00206 else if (typ == MatrixType::Full)
00207 retval = octave_value ("Full");
00208 else
00209 retval = octave_value ("Unknown");
00210 }
00211 else
00212 {
00213
00214 std::string str_typ = args(1).string_value ();
00215
00216
00217 MatrixType mattyp = MatrixType ();
00218
00219 octave_idx_type nl = 0;
00220 octave_idx_type nu = 0;
00221
00222 if (error_state)
00223 error ("matrix_type: TYPE must be a string");
00224 else
00225 {
00226
00227 std::transform (str_typ.begin (), str_typ.end (),
00228 str_typ.begin (), tolower);
00229
00230 if (str_typ == "diagonal")
00231 mattyp.mark_as_diagonal ();
00232 if (str_typ == "permuted diagonal")
00233 mattyp.mark_as_permuted_diagonal ();
00234 else if (str_typ == "upper")
00235 mattyp.mark_as_upper_triangular ();
00236 else if (str_typ == "lower")
00237 mattyp.mark_as_lower_triangular ();
00238 else if (str_typ == "banded" || str_typ == "banded positive definite")
00239 {
00240 if (nargin != 4)
00241 error ("matrix_type: banded matrix type requires 4 arguments");
00242 else
00243 {
00244 nl = args(2).nint_value ();
00245 nu = args(3).nint_value ();
00246
00247 if (error_state)
00248 error ("matrix_type: band size NL, NU must be integers");
00249 else
00250 {
00251 if (nl == 1 && nu == 1)
00252 mattyp.mark_as_tridiagonal ();
00253 else
00254 mattyp.mark_as_banded (nu, nl);
00255
00256 if (str_typ == "banded positive definite")
00257 mattyp.mark_as_symmetric ();
00258 }
00259 }
00260 }
00261 else if (str_typ == "positive definite")
00262 {
00263 mattyp.mark_as_full ();
00264 mattyp.mark_as_symmetric ();
00265 }
00266 else if (str_typ == "singular")
00267 mattyp.mark_as_rectangular ();
00268 else if (str_typ == "full")
00269 mattyp.mark_as_full ();
00270 else if (str_typ == "unknown")
00271 mattyp.invalidate_type ();
00272 else
00273 error ("matrix_type: Unknown matrix type %s", str_typ.c_str());
00274
00275 if (! error_state)
00276 {
00277 if (nargin == 3 && (str_typ == "upper" || str_typ == "lower"))
00278 {
00279 const ColumnVector perm =
00280 ColumnVector (args (2).vector_value ());
00281
00282 if (error_state)
00283 error ("matrix_type: Invalid permutation vector PERM");
00284 else
00285 {
00286 octave_idx_type len = perm.length ();
00287 dim_vector dv = args(0).dims ();
00288
00289 if (len != dv(0))
00290 error ("matrix_type: Invalid permutation vector PERM");
00291 else
00292 {
00293 OCTAVE_LOCAL_BUFFER (octave_idx_type, p, len);
00294
00295 for (octave_idx_type i = 0; i < len; i++)
00296 p[i] = static_cast<octave_idx_type> (perm (i)) - 1;
00297
00298 if (str_typ == "upper")
00299 mattyp.mark_as_permuted (len, p);
00300 else
00301 mattyp.mark_as_permuted (len, p);
00302 }
00303 }
00304 }
00305 else if (nargin != 2 && str_typ != "banded positive definite" &&
00306 str_typ != "banded")
00307 error ("matrix_type: Invalid number of arguments");
00308
00309 if (! error_state)
00310 {
00311
00312 if (args(0).is_complex_type ())
00313 retval =
00314 octave_value (args(0).sparse_complex_matrix_value (),
00315 mattyp);
00316 else
00317 retval = octave_value (args(0).sparse_matrix_value (),
00318 mattyp);
00319 }
00320 }
00321 }
00322 }
00323 }
00324 else
00325 {
00326 if (nargin == 1)
00327 {
00328 MatrixType mattyp;
00329
00330 if (args(0).is_complex_type ())
00331 {
00332 mattyp = args(0).matrix_type ();
00333
00334 if (mattyp.is_unknown () && autocomp)
00335 {
00336 if (args(0).is_single_type ())
00337 {
00338 FloatComplexMatrix m = args(0).float_complex_matrix_value ();
00339 if (!error_state)
00340 {
00341 mattyp = MatrixType (m);
00342 args(0).matrix_type (mattyp);
00343 }
00344 }
00345 else
00346 {
00347 ComplexMatrix m = args(0).complex_matrix_value ();
00348 if (!error_state)
00349 {
00350 mattyp = MatrixType (m);
00351 args(0).matrix_type (mattyp);
00352 }
00353 }
00354 }
00355 }
00356 else
00357 {
00358 mattyp = args(0).matrix_type ();
00359
00360 if (mattyp.is_unknown () && autocomp)
00361 {
00362 if (args(0).is_single_type ())
00363 {
00364 FloatMatrix m = args(0).float_matrix_value ();
00365 if (!error_state)
00366 {
00367 mattyp = MatrixType (m);
00368 args(0).matrix_type (mattyp);
00369 }
00370 }
00371 else
00372 {
00373 Matrix m = args(0).matrix_value ();
00374 if (!error_state)
00375 {
00376 mattyp = MatrixType (m);
00377 args(0).matrix_type (mattyp);
00378 }
00379 }
00380 }
00381 }
00382
00383 int typ = mattyp.type ();
00384
00385 if (typ == MatrixType::Upper)
00386 retval = octave_value ("Upper");
00387 else if (typ == MatrixType::Permuted_Upper)
00388 retval = octave_value ("Permuted Upper");
00389 else if (typ == MatrixType::Lower)
00390 retval = octave_value ("Lower");
00391 else if (typ == MatrixType::Permuted_Lower)
00392 retval = octave_value ("Permuted Lower");
00393 else if (typ == MatrixType::Hermitian)
00394 retval = octave_value ("Positive Definite");
00395 else if (typ == MatrixType::Rectangular)
00396 {
00397 if (args(0).rows() == args(0).columns())
00398 retval = octave_value ("Singular");
00399 else
00400 retval = octave_value ("Rectangular");
00401 }
00402 else if (typ == MatrixType::Full)
00403 retval = octave_value ("Full");
00404 else
00405 retval = octave_value ("Unknown");
00406 }
00407 else
00408 {
00409
00410 std::string str_typ = args(1).string_value ();
00411
00412
00413 MatrixType mattyp = MatrixType (MatrixType::Unknown, true);
00414
00415 if (error_state)
00416 error ("matrix_type: TYPE must be a string");
00417 else
00418 {
00419
00420 std::transform (str_typ.begin (), str_typ.end (),
00421 str_typ.begin (), tolower);
00422
00423 if (str_typ == "upper")
00424 mattyp.mark_as_upper_triangular ();
00425 else if (str_typ == "lower")
00426 mattyp.mark_as_lower_triangular ();
00427 else if (str_typ == "positive definite")
00428 {
00429 mattyp.mark_as_full ();
00430 mattyp.mark_as_symmetric ();
00431 }
00432 else if (str_typ == "singular")
00433 mattyp.mark_as_rectangular ();
00434 else if (str_typ == "full")
00435 mattyp.mark_as_full ();
00436 else if (str_typ == "unknown")
00437 mattyp.invalidate_type ();
00438 else
00439 error ("matrix_type: Unknown matrix type %s", str_typ.c_str());
00440
00441 if (! error_state)
00442 {
00443 if (nargin == 3 && (str_typ == "upper"
00444 || str_typ == "lower"))
00445 {
00446 const ColumnVector perm =
00447 ColumnVector (args (2).vector_value ());
00448
00449 if (error_state)
00450 error ("matrix_type: Invalid permutation vector PERM");
00451 else
00452 {
00453 octave_idx_type len = perm.length ();
00454 dim_vector dv = args(0).dims ();
00455
00456 if (len != dv(0))
00457 error ("matrix_type: Invalid permutation vector PERM");
00458 else
00459 {
00460 OCTAVE_LOCAL_BUFFER (octave_idx_type, p, len);
00461
00462 for (octave_idx_type i = 0; i < len; i++)
00463 p[i] = static_cast<octave_idx_type> (perm (i)) - 1;
00464
00465 if (str_typ == "upper")
00466 mattyp.mark_as_permuted (len, p);
00467 else
00468 mattyp.mark_as_permuted (len, p);
00469 }
00470 }
00471 }
00472 else if (nargin != 2)
00473 error ("matrix_type: Invalid number of arguments");
00474
00475 if (! error_state)
00476 {
00477
00478 if (args(0).is_single_type ())
00479 {
00480 if (args(0).is_complex_type())
00481 retval = octave_value
00482 (args(0).float_complex_matrix_value (),
00483 mattyp);
00484 else
00485 retval = octave_value
00486 (args(0).float_matrix_value (),
00487 mattyp);
00488 }
00489 else
00490 {
00491 if (args(0).is_complex_type())
00492 retval = octave_value
00493 (args(0).complex_matrix_value (),
00494 mattyp);
00495 else
00496 retval = octave_value
00497 (args(0).matrix_value (),
00498 mattyp);
00499 }
00500 }
00501 }
00502 }
00503 }
00504 }
00505 }
00506
00507 return retval;
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617