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 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028
00029 #include <vector>
00030
00031 #include "MatrixType.h"
00032 #include "dMatrix.h"
00033 #include "CMatrix.h"
00034 #include "dSparse.h"
00035 #include "CSparse.h"
00036 #include "oct-spparms.h"
00037 #include "oct-locbuf.h"
00038
00039
00040
00041 MatrixType::MatrixType (void)
00042 : typ (MatrixType::Unknown),
00043 sp_bandden (octave_sparse_params::get_bandden()),
00044 bandden (0), upper_band (0),
00045 lower_band (0), dense (false), full (false), nperm (0), perm (0) { }
00046
00047 MatrixType::MatrixType (const MatrixType &a)
00048 : typ (a.typ), sp_bandden (a.sp_bandden), bandden (a.bandden),
00049 upper_band (a.upper_band), lower_band (a.lower_band),
00050 dense (a.dense), full (a.full), nperm (a.nperm), perm (0)
00051 {
00052 if (nperm != 0)
00053 {
00054 perm = new octave_idx_type [nperm];
00055 for (octave_idx_type i = 0; i < nperm; i++)
00056 perm[i] = a.perm[i];
00057 }
00058 }
00059
00060 template<class T>
00061 MatrixType::matrix_type
00062 matrix_real_probe (const MArray<T>& a)
00063 {
00064 MatrixType::matrix_type typ;
00065 octave_idx_type nrows = a.rows ();
00066 octave_idx_type ncols = a.cols ();
00067
00068 const T zero = 0;
00069
00070 if (ncols == nrows)
00071 {
00072 bool upper = true;
00073 bool lower = true;
00074 bool hermitian = true;
00075
00076
00077 OCTAVE_LOCAL_BUFFER(T, diag, ncols);
00078
00079 for (octave_idx_type j = 0;
00080 j < ncols && upper; j++)
00081 {
00082 T d = a.elem (j,j);
00083 upper = upper && (d != zero);
00084 lower = lower && (d != zero);
00085 hermitian = hermitian && (d > zero);
00086 diag[j] = d;
00087 }
00088
00089 for (octave_idx_type j = 0;
00090 j < ncols && (upper || lower || hermitian); j++)
00091 {
00092 for (octave_idx_type i = 0; i < j; i++)
00093 {
00094 double aij = a.elem (i,j), aji = a.elem (j,i);
00095 lower = lower && (aij == zero);
00096 upper = upper && (aji == zero);
00097 hermitian = hermitian && (aij == aji
00098 && aij*aij < diag[i]*diag[j]);
00099 }
00100 }
00101
00102 if (upper)
00103 typ = MatrixType::Upper;
00104 else if (lower)
00105 typ = MatrixType::Lower;
00106 else if (hermitian)
00107 typ = MatrixType::Hermitian;
00108 else
00109 typ = MatrixType::Full;
00110 }
00111 else
00112 typ = MatrixType::Rectangular;
00113
00114 return typ;
00115 }
00116
00117 template<class T>
00118 MatrixType::matrix_type
00119 matrix_complex_probe (const MArray<std::complex<T> >& a)
00120 {
00121 MatrixType::matrix_type typ;
00122 octave_idx_type nrows = a.rows ();
00123 octave_idx_type ncols = a.cols ();
00124
00125 const T zero = 0;
00126
00127
00128 if (ncols == nrows)
00129 {
00130 bool upper = true;
00131 bool lower = true;
00132 bool hermitian = true;
00133
00134
00135 OCTAVE_LOCAL_BUFFER(T, diag, ncols);
00136
00137 for (octave_idx_type j = 0;
00138 j < ncols && upper; j++)
00139 {
00140 std::complex<T> d = a.elem (j,j);
00141 upper = upper && (d != zero);
00142 lower = lower && (d != zero);
00143 hermitian = hermitian && (d.real() > zero && d.imag() == zero);
00144 diag[j] = d.real();
00145 }
00146
00147 for (octave_idx_type j = 0;
00148 j < ncols && (upper || lower || hermitian); j++)
00149 {
00150 for (octave_idx_type i = 0; i < j; i++)
00151 {
00152 std::complex<T> aij = a.elem (i,j), aji = a.elem (j,i);
00153 lower = lower && (aij == zero);
00154 upper = upper && (aji == zero);
00155 hermitian = hermitian && (aij == std::conj (aji)
00156 && std::norm (aij) < diag[i]*diag[j]);
00157 }
00158 }
00159
00160
00161 if (upper)
00162 typ = MatrixType::Upper;
00163 else if (lower)
00164 typ = MatrixType::Lower;
00165 else if (hermitian)
00166 typ = MatrixType::Hermitian;
00167 else if (ncols == nrows)
00168 typ = MatrixType::Full;
00169 }
00170 else
00171 typ = MatrixType::Rectangular;
00172
00173 return typ;
00174 }
00175
00176 MatrixType::MatrixType (const Matrix &a)
00177 : typ (MatrixType::Unknown),
00178 sp_bandden (0), bandden (0), upper_band (0), lower_band (0),
00179 dense (false), full (true), nperm (0), perm (0)
00180 {
00181 typ = matrix_real_probe (a);
00182 }
00183
00184 MatrixType::MatrixType (const ComplexMatrix &a)
00185 : typ (MatrixType::Unknown),
00186 sp_bandden (0), bandden (0), upper_band (0), lower_band (0),
00187 dense (false), full (true), nperm (0), perm (0)
00188 {
00189 typ = matrix_complex_probe (a);
00190 }
00191
00192
00193 MatrixType::MatrixType (const FloatMatrix &a)
00194 : typ (MatrixType::Unknown),
00195 sp_bandden (0), bandden (0), upper_band (0), lower_band (0),
00196 dense (false), full (true), nperm (0), perm (0)
00197 {
00198 typ = matrix_real_probe (a);
00199 }
00200
00201 MatrixType::MatrixType (const FloatComplexMatrix &a)
00202 : typ (MatrixType::Unknown),
00203 sp_bandden (0), bandden (0), upper_band (0), lower_band (0),
00204 dense (false), full (true), nperm (0), perm (0)
00205 {
00206 typ = matrix_complex_probe (a);
00207 }
00208
00209 MatrixType::MatrixType (const SparseMatrix &a)
00210 : typ (MatrixType::Unknown),
00211 sp_bandden (0), bandden (0), upper_band (0), lower_band (0),
00212 dense (false), full (false), nperm (0), perm (0)
00213 {
00214 octave_idx_type nrows = a.rows ();
00215 octave_idx_type ncols = a.cols ();
00216 octave_idx_type nm = (ncols < nrows ? ncols : nrows);
00217 octave_idx_type nnz = a.nnz ();
00218
00219 if (octave_sparse_params::get_key ("spumoni") != 0.)
00220 (*current_liboctave_warning_handler)
00221 ("Calculating Sparse Matrix Type");
00222
00223 sp_bandden = octave_sparse_params::get_bandden();
00224 bool maybe_hermitian = false;
00225 typ = MatrixType::Full;
00226
00227 if (nnz == nm)
00228 {
00229 matrix_type tmp_typ = MatrixType::Diagonal;
00230 octave_idx_type i;
00231
00232 for (i = 0; i < nm; i++)
00233 {
00234 if (a.cidx(i+1) != a.cidx(i) + 1)
00235 {
00236 tmp_typ = MatrixType::Full;
00237 break;
00238 }
00239 if (a.ridx(i) != i)
00240 {
00241 tmp_typ = MatrixType::Permuted_Diagonal;
00242 break;
00243 }
00244 }
00245
00246 if (tmp_typ == MatrixType::Permuted_Diagonal)
00247 {
00248 std::vector<bool> found (nrows);
00249
00250 for (octave_idx_type j = 0; j < i; j++)
00251 found [j] = true;
00252 for (octave_idx_type j = i; j < nrows; j++)
00253 found [j] = false;
00254
00255 for (octave_idx_type j = i; j < nm; j++)
00256 {
00257 if ((a.cidx(j+1) > a.cidx(j) + 1) ||
00258 ((a.cidx(j+1) == a.cidx(j) + 1) && found [a.ridx(j)]))
00259 {
00260 tmp_typ = MatrixType::Full;
00261 break;
00262 }
00263 found [a.ridx(j)] = true;
00264 }
00265 }
00266 typ = tmp_typ;
00267 }
00268
00269 if (typ == MatrixType::Full)
00270 {
00271
00272 bool singular = false;
00273 upper_band = 0;
00274 lower_band = 0;
00275 for (octave_idx_type j = 0; j < ncols; j++)
00276 {
00277 bool zero_on_diagonal = false;
00278 if (j < nrows)
00279 {
00280 zero_on_diagonal = true;
00281 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00282 if (a.ridx(i) == j)
00283 {
00284 zero_on_diagonal = false;
00285 break;
00286 }
00287 }
00288
00289 if (zero_on_diagonal)
00290 {
00291 singular = true;
00292 break;
00293 }
00294
00295 if (a.cidx(j+1) != a.cidx(j))
00296 {
00297 octave_idx_type ru = a.ridx(a.cidx(j));
00298 octave_idx_type rl = a.ridx(a.cidx(j+1)-1);
00299
00300 if (j - ru > upper_band)
00301 upper_band = j - ru;
00302
00303 if (rl - j > lower_band)
00304 lower_band = rl - j;
00305 }
00306 }
00307
00308 if (!singular)
00309 {
00310 bandden = double (nnz) /
00311 (double (ncols) * (double (lower_band) +
00312 double (upper_band)) -
00313 0.5 * double (upper_band + 1) * double (upper_band) -
00314 0.5 * double (lower_band + 1) * double (lower_band));
00315
00316 if (nrows == ncols && sp_bandden != 1. && bandden > sp_bandden)
00317 {
00318 if (upper_band == 1 && lower_band == 1)
00319 typ = MatrixType::Tridiagonal;
00320 else
00321 typ = MatrixType::Banded;
00322
00323 octave_idx_type nnz_in_band =
00324 (upper_band + lower_band + 1) * nrows -
00325 (1 + upper_band) * upper_band / 2 -
00326 (1 + lower_band) * lower_band / 2;
00327 if (nnz_in_band == nnz)
00328 dense = true;
00329 else
00330 dense = false;
00331 }
00332 else if (upper_band == 0)
00333 typ = MatrixType::Lower;
00334 else if (lower_band == 0)
00335 typ = MatrixType::Upper;
00336
00337 if (upper_band == lower_band && nrows == ncols)
00338 maybe_hermitian = true;
00339 }
00340
00341 if (typ == MatrixType::Full)
00342 {
00343
00344
00345
00346
00347
00348 bool found = false;
00349
00350 nperm = ncols;
00351 perm = new octave_idx_type [ncols];
00352
00353 for (octave_idx_type i = 0; i < ncols; i++)
00354 perm [i] = -1;
00355
00356 for (octave_idx_type i = 0; i < nm; i++)
00357 {
00358 found = false;
00359
00360 for (octave_idx_type j = 0; j < ncols; j++)
00361 {
00362 if ((a.cidx(j+1) - a.cidx(j)) > 0 &&
00363 (a.ridx(a.cidx(j+1)-1) == i))
00364 {
00365 perm [i] = j;
00366 found = true;
00367 break;
00368 }
00369 }
00370
00371 if (!found)
00372 break;
00373 }
00374
00375 if (found)
00376 {
00377 typ = MatrixType::Permuted_Upper;
00378 if (ncols > nrows)
00379 {
00380 octave_idx_type k = nrows;
00381 for (octave_idx_type i = 0; i < ncols; i++)
00382 if (perm [i] == -1)
00383 perm[i] = k++;
00384 }
00385 }
00386 else if (a.cidx(nm) == a.cidx(ncols))
00387 {
00388 nperm = nrows;
00389 delete [] perm;
00390 perm = new octave_idx_type [nrows];
00391 OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, nrows);
00392
00393 for (octave_idx_type i = 0; i < nrows; i++)
00394 {
00395 perm [i] = -1;
00396 tmp [i] = -1;
00397 }
00398
00399 for (octave_idx_type j = 0; j < ncols; j++)
00400 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00401 perm [a.ridx(i)] = j;
00402
00403 found = true;
00404 for (octave_idx_type i = 0; i < nm; i++)
00405 if (perm[i] == -1)
00406 {
00407 found = false;
00408 break;
00409 }
00410 else
00411 {
00412 tmp[perm[i]] = 1;
00413 }
00414
00415 if (found)
00416 {
00417 octave_idx_type k = ncols;
00418 for (octave_idx_type i = 0; i < nrows; i++)
00419 {
00420 if (tmp[i] == -1)
00421 {
00422 if (k < nrows)
00423 {
00424 perm[k++] = i;
00425 }
00426 else
00427 {
00428 found = false;
00429 break;
00430 }
00431 }
00432 }
00433 }
00434
00435 if (found)
00436 typ = MatrixType::Permuted_Lower;
00437 else
00438 {
00439 delete [] perm;
00440 nperm = 0;
00441 }
00442 }
00443 else
00444 {
00445 delete [] perm;
00446 nperm = 0;
00447 }
00448 }
00449
00450
00451
00452
00453
00454 if (((typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
00455 && nrows > ncols) ||
00456 ((typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
00457 && nrows < ncols))
00458 {
00459 if (typ == MatrixType::Permuted_Upper ||
00460 typ == MatrixType::Permuted_Lower)
00461 delete [] perm;
00462 nperm = 0;
00463 typ = MatrixType::Rectangular;
00464 }
00465
00466 if (typ == MatrixType::Full && ncols != nrows)
00467 typ = MatrixType::Rectangular;
00468
00469 if (maybe_hermitian && (typ == MatrixType::Full ||
00470 typ == MatrixType::Tridiagonal ||
00471 typ == MatrixType::Banded))
00472 {
00473 bool is_herm = true;
00474
00475
00476 ColumnVector diag (ncols);
00477
00478 for (octave_idx_type j = 0; is_herm && j < ncols; j++)
00479 {
00480 is_herm = false;
00481 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00482 {
00483 if (a.ridx(i) == j)
00484 {
00485 double d = a.data(i);
00486 is_herm = d > 0.;
00487 diag(j) = d;
00488 break;
00489 }
00490 }
00491 }
00492
00493
00494
00495
00496 for (octave_idx_type j = 0; is_herm && j < ncols; j++)
00497 for (octave_idx_type i = a.cidx(j); is_herm && i < a.cidx(j+1); i++)
00498 {
00499 octave_idx_type k = a.ridx(i);
00500 is_herm = k == j;
00501 if (is_herm)
00502 continue;
00503 double d = a.data(i);
00504 if (d*d < diag(j)*diag(k))
00505 {
00506 for (octave_idx_type l = a.cidx(k); l < a.cidx(k+1); l++)
00507 {
00508 if (a.ridx(l) == j)
00509 {
00510 is_herm = a.data(l) == d;
00511 break;
00512 }
00513 }
00514 }
00515 }
00516
00517 if (is_herm)
00518 {
00519 if (typ == MatrixType::Full)
00520 typ = MatrixType::Hermitian;
00521 else if (typ == MatrixType::Banded)
00522 typ = MatrixType::Banded_Hermitian;
00523 else
00524 typ = MatrixType::Tridiagonal_Hermitian;
00525 }
00526 }
00527 }
00528 }
00529
00530 MatrixType::MatrixType (const SparseComplexMatrix &a)
00531 : typ (MatrixType::Unknown),
00532 sp_bandden (0), bandden (0), upper_band (0), lower_band (0),
00533 dense (false), full (false), nperm (0), perm (0)
00534 {
00535 octave_idx_type nrows = a.rows ();
00536 octave_idx_type ncols = a.cols ();
00537 octave_idx_type nm = (ncols < nrows ? ncols : nrows);
00538 octave_idx_type nnz = a.nnz ();
00539
00540 if (octave_sparse_params::get_key ("spumoni") != 0.)
00541 (*current_liboctave_warning_handler)
00542 ("Calculating Sparse Matrix Type");
00543
00544 sp_bandden = octave_sparse_params::get_bandden();
00545 bool maybe_hermitian = false;
00546 typ = MatrixType::Full;
00547
00548 if (nnz == nm)
00549 {
00550 matrix_type tmp_typ = MatrixType::Diagonal;
00551 octave_idx_type i;
00552
00553 for (i = 0; i < nm; i++)
00554 {
00555 if (a.cidx(i+1) != a.cidx(i) + 1)
00556 {
00557 tmp_typ = MatrixType::Full;
00558 break;
00559 }
00560 if (a.ridx(i) != i)
00561 {
00562 tmp_typ = MatrixType::Permuted_Diagonal;
00563 break;
00564 }
00565 }
00566
00567 if (tmp_typ == MatrixType::Permuted_Diagonal)
00568 {
00569 std::vector<bool> found (nrows);
00570
00571 for (octave_idx_type j = 0; j < i; j++)
00572 found [j] = true;
00573 for (octave_idx_type j = i; j < nrows; j++)
00574 found [j] = false;
00575
00576 for (octave_idx_type j = i; j < nm; j++)
00577 {
00578 if ((a.cidx(j+1) > a.cidx(j) + 1) ||
00579 ((a.cidx(j+1) == a.cidx(j) + 1) && found [a.ridx(j)]))
00580 {
00581 tmp_typ = MatrixType::Full;
00582 break;
00583 }
00584 found [a.ridx(j)] = true;
00585 }
00586 }
00587 typ = tmp_typ;
00588 }
00589
00590 if (typ == MatrixType::Full)
00591 {
00592
00593 bool singular = false;
00594 upper_band = 0;
00595 lower_band = 0;
00596 for (octave_idx_type j = 0; j < ncols; j++)
00597 {
00598 bool zero_on_diagonal = false;
00599 if (j < nrows)
00600 {
00601 zero_on_diagonal = true;
00602 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00603 if (a.ridx(i) == j)
00604 {
00605 zero_on_diagonal = false;
00606 break;
00607 }
00608 }
00609
00610 if (zero_on_diagonal)
00611 {
00612 singular = true;
00613 break;
00614 }
00615
00616 if (a.cidx(j+1) != a.cidx(j))
00617 {
00618 octave_idx_type ru = a.ridx(a.cidx(j));
00619 octave_idx_type rl = a.ridx(a.cidx(j+1)-1);
00620
00621 if (j - ru > upper_band)
00622 upper_band = j - ru;
00623
00624 if (rl - j > lower_band)
00625 lower_band = rl - j;
00626 }
00627 }
00628
00629 if (!singular)
00630 {
00631 bandden = double (nnz) /
00632 (double (ncols) * (double (lower_band) +
00633 double (upper_band)) -
00634 0.5 * double (upper_band + 1) * double (upper_band) -
00635 0.5 * double (lower_band + 1) * double (lower_band));
00636
00637 if (nrows == ncols && sp_bandden != 1. && bandden > sp_bandden)
00638 {
00639 if (upper_band == 1 && lower_band == 1)
00640 typ = MatrixType::Tridiagonal;
00641 else
00642 typ = MatrixType::Banded;
00643
00644 octave_idx_type nnz_in_band =
00645 (upper_band + lower_band + 1) * nrows -
00646 (1 + upper_band) * upper_band / 2 -
00647 (1 + lower_band) * lower_band / 2;
00648 if (nnz_in_band == nnz)
00649 dense = true;
00650 else
00651 dense = false;
00652 }
00653 else if (upper_band == 0)
00654 typ = MatrixType::Lower;
00655 else if (lower_band == 0)
00656 typ = MatrixType::Upper;
00657
00658 if (upper_band == lower_band && nrows == ncols)
00659 maybe_hermitian = true;
00660 }
00661
00662 if (typ == MatrixType::Full)
00663 {
00664
00665
00666
00667
00668
00669 bool found = false;
00670
00671 nperm = ncols;
00672 perm = new octave_idx_type [ncols];
00673
00674 for (octave_idx_type i = 0; i < ncols; i++)
00675 perm [i] = -1;
00676
00677 for (octave_idx_type i = 0; i < nm; i++)
00678 {
00679 found = false;
00680
00681 for (octave_idx_type j = 0; j < ncols; j++)
00682 {
00683 if ((a.cidx(j+1) - a.cidx(j)) > 0 &&
00684 (a.ridx(a.cidx(j+1)-1) == i))
00685 {
00686 perm [i] = j;
00687 found = true;
00688 break;
00689 }
00690 }
00691
00692 if (!found)
00693 break;
00694 }
00695
00696 if (found)
00697 {
00698 typ = MatrixType::Permuted_Upper;
00699 if (ncols > nrows)
00700 {
00701 octave_idx_type k = nrows;
00702 for (octave_idx_type i = 0; i < ncols; i++)
00703 if (perm [i] == -1)
00704 perm[i] = k++;
00705 }
00706 }
00707 else if (a.cidx(nm) == a.cidx(ncols))
00708 {
00709 nperm = nrows;
00710 delete [] perm;
00711 perm = new octave_idx_type [nrows];
00712 OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, nrows);
00713
00714 for (octave_idx_type i = 0; i < nrows; i++)
00715 {
00716 perm [i] = -1;
00717 tmp [i] = -1;
00718 }
00719
00720 for (octave_idx_type j = 0; j < ncols; j++)
00721 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00722 perm [a.ridx(i)] = j;
00723
00724 found = true;
00725 for (octave_idx_type i = 0; i < nm; i++)
00726 if (perm[i] == -1)
00727 {
00728 found = false;
00729 break;
00730 }
00731 else
00732 {
00733 tmp[perm[i]] = 1;
00734 }
00735
00736 if (found)
00737 {
00738 octave_idx_type k = ncols;
00739 for (octave_idx_type i = 0; i < nrows; i++)
00740 {
00741 if (tmp[i] == -1)
00742 {
00743 if (k < nrows)
00744 {
00745 perm[k++] = i;
00746 }
00747 else
00748 {
00749 found = false;
00750 break;
00751 }
00752 }
00753 }
00754 }
00755
00756 if (found)
00757 typ = MatrixType::Permuted_Lower;
00758 else
00759 {
00760 delete [] perm;
00761 nperm = 0;
00762 }
00763 }
00764 else
00765 {
00766 delete [] perm;
00767 nperm = 0;
00768 }
00769 }
00770
00771
00772
00773
00774
00775 if (((typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
00776 && nrows > ncols) ||
00777 ((typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
00778 && nrows < ncols))
00779 {
00780 if (typ == MatrixType::Permuted_Upper ||
00781 typ == MatrixType::Permuted_Lower)
00782 delete [] perm;
00783 nperm = 0;
00784 typ = MatrixType::Rectangular;
00785 }
00786
00787 if (typ == MatrixType::Full && ncols != nrows)
00788 typ = MatrixType::Rectangular;
00789
00790 if (maybe_hermitian && (typ == MatrixType::Full ||
00791 typ == MatrixType::Tridiagonal ||
00792 typ == MatrixType::Banded))
00793 {
00794 bool is_herm = true;
00795
00796
00797 ColumnVector diag (ncols);
00798
00799 for (octave_idx_type j = 0; is_herm && j < ncols; j++)
00800 {
00801 is_herm = false;
00802 for (octave_idx_type i = a.cidx(j); i < a.cidx(j+1); i++)
00803 {
00804 if (a.ridx(i) == j)
00805 {
00806 Complex d = a.data(i);
00807 is_herm = d.real() > 0. && d.imag() == 0.;
00808 diag(j) = d.real();
00809 break;
00810 }
00811 }
00812 }
00813
00814
00815
00816 for (octave_idx_type j = 0; is_herm && j < ncols; j++)
00817 for (octave_idx_type i = a.cidx(j); is_herm && i < a.cidx(j+1); i++)
00818 {
00819 octave_idx_type k = a.ridx(i);
00820 is_herm = k == j;
00821 if (is_herm)
00822 continue;
00823 Complex d = a.data(i);
00824 if (std::norm (d) < diag(j)*diag(k))
00825 {
00826 d = std::conj (d);
00827 for (octave_idx_type l = a.cidx(k); l < a.cidx(k+1); l++)
00828 {
00829 if (a.ridx(l) == j)
00830 {
00831 is_herm = a.data(l) == d;
00832 break;
00833 }
00834 }
00835 }
00836 }
00837
00838
00839 if (is_herm)
00840 {
00841 if (typ == MatrixType::Full)
00842 typ = MatrixType::Hermitian;
00843 else if (typ == MatrixType::Banded)
00844 typ = MatrixType::Banded_Hermitian;
00845 else
00846 typ = MatrixType::Tridiagonal_Hermitian;
00847 }
00848 }
00849 }
00850 }
00851 MatrixType::MatrixType (const matrix_type t, bool _full)
00852 : typ (MatrixType::Unknown),
00853 sp_bandden (octave_sparse_params::get_bandden()),
00854 bandden (0), upper_band (0), lower_band (0),
00855 dense (false), full (_full), nperm (0), perm (0)
00856 {
00857 if (t == MatrixType::Unknown || t == MatrixType::Full
00858 || t == MatrixType::Diagonal || t == MatrixType::Permuted_Diagonal
00859 || t == MatrixType::Upper || t == MatrixType::Lower
00860 || t == MatrixType::Tridiagonal || t == MatrixType::Tridiagonal_Hermitian
00861 || t == MatrixType::Rectangular)
00862 typ = t;
00863 else
00864 (*current_liboctave_warning_handler) ("Invalid matrix type");
00865 }
00866
00867 MatrixType::MatrixType (const matrix_type t, const octave_idx_type np,
00868 const octave_idx_type *p, bool _full)
00869 : typ (MatrixType::Unknown),
00870 sp_bandden (octave_sparse_params::get_bandden()),
00871 bandden (0), upper_band (0), lower_band (0),
00872 dense (false), full (_full), nperm (0), perm (0)
00873 {
00874 if ((t == MatrixType::Permuted_Upper || t == MatrixType::Permuted_Lower) &&
00875 np > 0 && p != 0)
00876 {
00877 typ = t;
00878 nperm = np;
00879 perm = new octave_idx_type [nperm];
00880 for (octave_idx_type i = 0; i < nperm; i++)
00881 perm[i] = p[i];
00882 }
00883 else
00884 (*current_liboctave_warning_handler) ("Invalid matrix type");
00885 }
00886
00887 MatrixType::MatrixType (const matrix_type t, const octave_idx_type ku,
00888 const octave_idx_type kl, bool _full)
00889 : typ (MatrixType::Unknown),
00890 sp_bandden (octave_sparse_params::get_bandden()),
00891 bandden (0), upper_band (0), lower_band (0),
00892 dense (false), full (_full), nperm (0), perm (0)
00893 {
00894 if (t == MatrixType::Banded || t == MatrixType::Banded_Hermitian)
00895 {
00896 typ = t;
00897 upper_band = ku;
00898 lower_band = kl;
00899 }
00900 else
00901 (*current_liboctave_warning_handler) ("Invalid sparse matrix type");
00902 }
00903
00904 MatrixType::~MatrixType (void)
00905 {
00906 if (nperm != 0)
00907 {
00908 delete [] perm;
00909 }
00910 }
00911
00912 MatrixType&
00913 MatrixType::operator = (const MatrixType& a)
00914 {
00915 if (this != &a)
00916 {
00917 typ = a.typ;
00918 sp_bandden = a.sp_bandden;
00919 bandden = a.bandden;
00920 upper_band = a.upper_band;
00921 lower_band = a.lower_band;
00922 dense = a.dense;
00923 full = a.full;
00924
00925 if (nperm)
00926 {
00927 delete[] perm;
00928 }
00929
00930 if (a.nperm != 0)
00931 {
00932 perm = new octave_idx_type [a.nperm];
00933 for (octave_idx_type i = 0; i < a.nperm; i++)
00934 perm[i] = a.perm[i];
00935 }
00936
00937 nperm = a.nperm;
00938 }
00939
00940 return *this;
00941 }
00942
00943 int
00944 MatrixType::type (bool quiet)
00945 {
00946 if (typ != MatrixType::Unknown && (full ||
00947 sp_bandden == octave_sparse_params::get_bandden()))
00948 {
00949 if (!quiet &&
00950 octave_sparse_params::get_key ("spumoni") != 0.)
00951 (*current_liboctave_warning_handler)
00952 ("Using Cached Matrix Type");
00953
00954 return typ;
00955 }
00956
00957 if (typ != MatrixType::Unknown &&
00958 octave_sparse_params::get_key ("spumoni") != 0.)
00959 (*current_liboctave_warning_handler)
00960 ("Invalidating Matrix Type");
00961
00962 typ = MatrixType::Unknown;
00963
00964 return typ;
00965 }
00966
00967 int
00968 MatrixType::type (const SparseMatrix &a)
00969 {
00970 if (typ != MatrixType::Unknown && (full ||
00971 sp_bandden == octave_sparse_params::get_bandden()))
00972 {
00973 if (octave_sparse_params::get_key ("spumoni") != 0.)
00974 (*current_liboctave_warning_handler)
00975 ("Using Cached Matrix Type");
00976
00977 return typ;
00978 }
00979
00980 MatrixType tmp_typ (a);
00981 typ = tmp_typ.typ;
00982 sp_bandden = tmp_typ.sp_bandden;
00983 bandden = tmp_typ.bandden;
00984 upper_band = tmp_typ.upper_band;
00985 lower_band = tmp_typ.lower_band;
00986 dense = tmp_typ.dense;
00987 full = tmp_typ.full;
00988 nperm = tmp_typ.nperm;
00989
00990 if (nperm != 0)
00991 {
00992 perm = new octave_idx_type [nperm];
00993 for (octave_idx_type i = 0; i < nperm; i++)
00994 perm[i] = tmp_typ.perm[i];
00995 }
00996
00997 return typ;
00998 }
00999
01000 int
01001 MatrixType::type (const SparseComplexMatrix &a)
01002 {
01003 if (typ != MatrixType::Unknown && (full ||
01004 sp_bandden == octave_sparse_params::get_bandden()))
01005 {
01006 if (octave_sparse_params::get_key ("spumoni") != 0.)
01007 (*current_liboctave_warning_handler)
01008 ("Using Cached Matrix Type");
01009
01010 return typ;
01011 }
01012
01013 MatrixType tmp_typ (a);
01014 typ = tmp_typ.typ;
01015 sp_bandden = tmp_typ.sp_bandden;
01016 bandden = tmp_typ.bandden;
01017 upper_band = tmp_typ.upper_band;
01018 lower_band = tmp_typ.lower_band;
01019 dense = tmp_typ.dense;
01020 full = tmp_typ.full;
01021 nperm = tmp_typ.nperm;
01022
01023 if (nperm != 0)
01024 {
01025 perm = new octave_idx_type [nperm];
01026 for (octave_idx_type i = 0; i < nperm; i++)
01027 perm[i] = tmp_typ.perm[i];
01028 }
01029
01030 return typ;
01031 }
01032
01033 int
01034 MatrixType::type (const Matrix &a)
01035 {
01036 if (typ != MatrixType::Unknown)
01037 {
01038 if (octave_sparse_params::get_key ("spumoni") != 0.)
01039 (*current_liboctave_warning_handler)
01040 ("Using Cached Matrix Type");
01041
01042 return typ;
01043 }
01044
01045 MatrixType tmp_typ (a);
01046 typ = tmp_typ.typ;
01047 full = tmp_typ.full;
01048 nperm = tmp_typ.nperm;
01049
01050 if (nperm != 0)
01051 {
01052 perm = new octave_idx_type [nperm];
01053 for (octave_idx_type i = 0; i < nperm; i++)
01054 perm[i] = tmp_typ.perm[i];
01055 }
01056
01057 return typ;
01058 }
01059
01060 int
01061 MatrixType::type (const ComplexMatrix &a)
01062 {
01063 if (typ != MatrixType::Unknown)
01064 {
01065 if (octave_sparse_params::get_key ("spumoni") != 0.)
01066 (*current_liboctave_warning_handler)
01067 ("Using Cached Matrix Type");
01068
01069 return typ;
01070 }
01071
01072 MatrixType tmp_typ (a);
01073 typ = tmp_typ.typ;
01074 full = tmp_typ.full;
01075 nperm = tmp_typ.nperm;
01076
01077 if (nperm != 0)
01078 {
01079 perm = new octave_idx_type [nperm];
01080 for (octave_idx_type i = 0; i < nperm; i++)
01081 perm[i] = tmp_typ.perm[i];
01082 }
01083
01084 return typ;
01085 }
01086
01087 int
01088 MatrixType::type (const FloatMatrix &a)
01089 {
01090 if (typ != MatrixType::Unknown)
01091 {
01092 if (octave_sparse_params::get_key ("spumoni") != 0.)
01093 (*current_liboctave_warning_handler)
01094 ("Using Cached Matrix Type");
01095
01096 return typ;
01097 }
01098
01099 MatrixType tmp_typ (a);
01100 typ = tmp_typ.typ;
01101 full = tmp_typ.full;
01102 nperm = tmp_typ.nperm;
01103
01104 if (nperm != 0)
01105 {
01106 perm = new octave_idx_type [nperm];
01107 for (octave_idx_type i = 0; i < nperm; i++)
01108 perm[i] = tmp_typ.perm[i];
01109 }
01110
01111 return typ;
01112 }
01113
01114 int
01115 MatrixType::type (const FloatComplexMatrix &a)
01116 {
01117 if (typ != MatrixType::Unknown)
01118 {
01119 if (octave_sparse_params::get_key ("spumoni") != 0.)
01120 (*current_liboctave_warning_handler)
01121 ("Using Cached Matrix Type");
01122
01123 return typ;
01124 }
01125
01126 MatrixType tmp_typ (a);
01127 typ = tmp_typ.typ;
01128 full = tmp_typ.full;
01129 nperm = tmp_typ.nperm;
01130
01131 if (nperm != 0)
01132 {
01133 perm = new octave_idx_type [nperm];
01134 for (octave_idx_type i = 0; i < nperm; i++)
01135 perm[i] = tmp_typ.perm[i];
01136 }
01137
01138 return typ;
01139 }
01140
01141 void
01142 MatrixType::info () const
01143 {
01144 if (octave_sparse_params::get_key ("spumoni") != 0.)
01145 {
01146 if (typ == MatrixType::Unknown)
01147 (*current_liboctave_warning_handler)
01148 ("Unknown Matrix Type");
01149 else if (typ == MatrixType::Diagonal)
01150 (*current_liboctave_warning_handler)
01151 ("Diagonal Sparse Matrix");
01152 else if (typ == MatrixType::Permuted_Diagonal)
01153 (*current_liboctave_warning_handler)
01154 ("Permuted Diagonal Sparse Matrix");
01155 else if (typ == MatrixType::Upper)
01156 (*current_liboctave_warning_handler)
01157 ("Upper Triangular Matrix");
01158 else if (typ == MatrixType::Lower)
01159 (*current_liboctave_warning_handler)
01160 ("Lower Triangular Matrix");
01161 else if (typ == MatrixType::Permuted_Upper)
01162 (*current_liboctave_warning_handler)
01163 ("Permuted Upper Triangular Matrix");
01164 else if (typ == MatrixType::Permuted_Lower)
01165 (*current_liboctave_warning_handler)
01166 ("Permuted Lower Triangular Matrix");
01167 else if (typ == MatrixType::Banded)
01168 (*current_liboctave_warning_handler)
01169 ("Banded Sparse Matrix %d-1-%d (Density %f)", lower_band,
01170 upper_band, bandden);
01171 else if (typ == MatrixType::Banded_Hermitian)
01172 (*current_liboctave_warning_handler)
01173 ("Banded Hermitian/Symmetric Sparse Matrix %d-1-%d (Density %f)",
01174 lower_band, upper_band, bandden);
01175 else if (typ == MatrixType::Hermitian)
01176 (*current_liboctave_warning_handler)
01177 ("Hermitian/Symmetric Matrix");
01178 else if (typ == MatrixType::Tridiagonal)
01179 (*current_liboctave_warning_handler)
01180 ("Tridiagonal Sparse Matrix");
01181 else if (typ == MatrixType::Tridiagonal_Hermitian)
01182 (*current_liboctave_warning_handler)
01183 ("Hermitian/Symmetric Tridiagonal Sparse Matrix");
01184 else if (typ == MatrixType::Rectangular)
01185 (*current_liboctave_warning_handler)
01186 ("Rectangular/Singular Matrix");
01187 else if (typ == MatrixType::Full)
01188 (*current_liboctave_warning_handler)
01189 ("Full Matrix");
01190 }
01191 }
01192
01193 void
01194 MatrixType::mark_as_symmetric (void)
01195 {
01196 if (typ == MatrixType::Tridiagonal ||
01197 typ == MatrixType::Tridiagonal_Hermitian)
01198 typ = MatrixType::Tridiagonal_Hermitian;
01199 else if (typ == MatrixType::Banded ||
01200 typ == MatrixType::Banded_Hermitian)
01201 typ = MatrixType::Banded_Hermitian;
01202 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian ||
01203 typ == MatrixType::Unknown)
01204 typ = MatrixType::Hermitian;
01205 else
01206 (*current_liboctave_error_handler)
01207 ("Can not mark current matrix type as symmetric");
01208 }
01209
01210 void
01211 MatrixType::mark_as_unsymmetric (void)
01212 {
01213 if (typ == MatrixType::Tridiagonal ||
01214 typ == MatrixType::Tridiagonal_Hermitian)
01215 typ = MatrixType::Tridiagonal;
01216 else if (typ == MatrixType::Banded ||
01217 typ == MatrixType::Banded_Hermitian)
01218 typ = MatrixType::Banded;
01219 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian ||
01220 typ == MatrixType::Unknown)
01221 typ = MatrixType::Full;
01222 }
01223
01224 void
01225 MatrixType::mark_as_permuted (const octave_idx_type np, const octave_idx_type *p)
01226 {
01227 nperm = np;
01228 perm = new octave_idx_type [nperm];
01229 for (octave_idx_type i = 0; i < nperm; i++)
01230 perm[i] = p[i];
01231
01232 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)
01233 typ = MatrixType::Permuted_Diagonal;
01234 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
01235 typ = MatrixType::Permuted_Upper;
01236 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
01237 typ = MatrixType::Permuted_Lower;
01238 else
01239 (*current_liboctave_error_handler)
01240 ("Can not mark current matrix type as symmetric");
01241 }
01242
01243 void
01244 MatrixType::mark_as_unpermuted (void)
01245 {
01246 if (nperm)
01247 {
01248 nperm = 0;
01249 delete [] perm;
01250 }
01251
01252 if (typ == MatrixType::Diagonal || typ == MatrixType::Permuted_Diagonal)
01253 typ = MatrixType::Diagonal;
01254 else if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
01255 typ = MatrixType::Upper;
01256 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
01257 typ = MatrixType::Lower;
01258 }
01259
01260 MatrixType
01261 MatrixType::transpose (void) const
01262 {
01263 MatrixType retval (*this);
01264 if (typ == MatrixType::Upper)
01265 retval.typ = MatrixType::Lower;
01266 else if (typ == MatrixType::Permuted_Upper)
01267 retval.typ = MatrixType::Permuted_Lower;
01268 else if (typ == MatrixType::Lower)
01269 retval.typ = MatrixType::Upper;
01270 else if (typ == MatrixType::Permuted_Lower)
01271 retval.typ = MatrixType::Permuted_Upper;
01272 else if (typ == MatrixType::Banded)
01273 {
01274 retval.upper_band = lower_band;
01275 retval.lower_band = upper_band;
01276 }
01277
01278 return retval;
01279 }