00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION)
00025 #pragma implementation
00026 #endif
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032 #include <iostream>
00033
00034 #include "Array-util.h"
00035 #include "lo-error.h"
00036 #include "mx-base.h"
00037 #include "mx-inlines.cc"
00038 #include "oct-cmplx.h"
00039
00040
00041
00042 ComplexDiagMatrix::ComplexDiagMatrix (const DiagMatrix& a)
00043 : MDiagArray2<Complex> (a.rows (), a.cols ())
00044 {
00045 for (int i = 0; i < length (); i++)
00046 elem (i, i) = a.elem (i, i);
00047 }
00048
00049 bool
00050 ComplexDiagMatrix::operator == (const ComplexDiagMatrix& a) const
00051 {
00052 if (rows () != a.rows () || cols () != a.cols ())
00053 return 0;
00054
00055 return mx_inline_equal (data (), a.data (), length ());
00056 }
00057
00058 bool
00059 ComplexDiagMatrix::operator != (const ComplexDiagMatrix& a) const
00060 {
00061 return !(*this == a);
00062 }
00063
00064 ComplexDiagMatrix&
00065 ComplexDiagMatrix::fill (double val)
00066 {
00067 for (int i = 0; i < length (); i++)
00068 elem (i, i) = val;
00069 return *this;
00070 }
00071
00072 ComplexDiagMatrix&
00073 ComplexDiagMatrix::fill (const Complex& val)
00074 {
00075 for (int i = 0; i < length (); i++)
00076 elem (i, i) = val;
00077 return *this;
00078 }
00079
00080 ComplexDiagMatrix&
00081 ComplexDiagMatrix::fill (double val, int beg, int end)
00082 {
00083 if (beg < 0 || end >= length () || end < beg)
00084 {
00085 (*current_liboctave_error_handler) ("range error for fill");
00086 return *this;
00087 }
00088
00089 for (int i = beg; i <= end; i++)
00090 elem (i, i) = val;
00091
00092 return *this;
00093 }
00094
00095 ComplexDiagMatrix&
00096 ComplexDiagMatrix::fill (const Complex& val, int beg, int end)
00097 {
00098 if (beg < 0 || end >= length () || end < beg)
00099 {
00100 (*current_liboctave_error_handler) ("range error for fill");
00101 return *this;
00102 }
00103
00104 for (int i = beg; i <= end; i++)
00105 elem (i, i) = val;
00106
00107 return *this;
00108 }
00109
00110 ComplexDiagMatrix&
00111 ComplexDiagMatrix::fill (const ColumnVector& a)
00112 {
00113 int len = length ();
00114 if (a.length () != len)
00115 {
00116 (*current_liboctave_error_handler) ("range error for fill");
00117 return *this;
00118 }
00119
00120 for (int i = 0; i < len; i++)
00121 elem (i, i) = a.elem (i);
00122
00123 return *this;
00124 }
00125
00126 ComplexDiagMatrix&
00127 ComplexDiagMatrix::fill (const ComplexColumnVector& a)
00128 {
00129 int len = length ();
00130 if (a.length () != len)
00131 {
00132 (*current_liboctave_error_handler) ("range error for fill");
00133 return *this;
00134 }
00135
00136 for (int i = 0; i < len; i++)
00137 elem (i, i) = a.elem (i);
00138
00139 return *this;
00140 }
00141
00142 ComplexDiagMatrix&
00143 ComplexDiagMatrix::fill (const RowVector& a)
00144 {
00145 int len = length ();
00146 if (a.length () != len)
00147 {
00148 (*current_liboctave_error_handler) ("range error for fill");
00149 return *this;
00150 }
00151
00152 for (int i = 0; i < len; i++)
00153 elem (i, i) = a.elem (i);
00154
00155 return *this;
00156 }
00157
00158 ComplexDiagMatrix&
00159 ComplexDiagMatrix::fill (const ComplexRowVector& a)
00160 {
00161 int len = length ();
00162 if (a.length () != len)
00163 {
00164 (*current_liboctave_error_handler) ("range error for fill");
00165 return *this;
00166 }
00167
00168 for (int i = 0; i < len; i++)
00169 elem (i, i) = a.elem (i);
00170
00171 return *this;
00172 }
00173
00174 ComplexDiagMatrix&
00175 ComplexDiagMatrix::fill (const ColumnVector& a, int beg)
00176 {
00177 int a_len = a.length ();
00178 if (beg < 0 || beg + a_len >= length ())
00179 {
00180 (*current_liboctave_error_handler) ("range error for fill");
00181 return *this;
00182 }
00183
00184 for (int i = 0; i < a_len; i++)
00185 elem (i+beg, i+beg) = a.elem (i);
00186
00187 return *this;
00188 }
00189
00190 ComplexDiagMatrix&
00191 ComplexDiagMatrix::fill (const ComplexColumnVector& a, int beg)
00192 {
00193 int a_len = a.length ();
00194 if (beg < 0 || beg + a_len >= length ())
00195 {
00196 (*current_liboctave_error_handler) ("range error for fill");
00197 return *this;
00198 }
00199
00200 for (int i = 0; i < a_len; i++)
00201 elem (i+beg, i+beg) = a.elem (i);
00202
00203 return *this;
00204 }
00205
00206 ComplexDiagMatrix&
00207 ComplexDiagMatrix::fill (const RowVector& a, int beg)
00208 {
00209 int a_len = a.length ();
00210 if (beg < 0 || beg + a_len >= length ())
00211 {
00212 (*current_liboctave_error_handler) ("range error for fill");
00213 return *this;
00214 }
00215
00216 for (int i = 0; i < a_len; i++)
00217 elem (i+beg, i+beg) = a.elem (i);
00218
00219 return *this;
00220 }
00221
00222 ComplexDiagMatrix&
00223 ComplexDiagMatrix::fill (const ComplexRowVector& a, int beg)
00224 {
00225 int a_len = a.length ();
00226 if (beg < 0 || beg + a_len >= length ())
00227 {
00228 (*current_liboctave_error_handler) ("range error for fill");
00229 return *this;
00230 }
00231
00232 for (int i = 0; i < a_len; i++)
00233 elem (i+beg, i+beg) = a.elem (i);
00234
00235 return *this;
00236 }
00237
00238 ComplexDiagMatrix
00239 ComplexDiagMatrix::hermitian (void) const
00240 {
00241 return ComplexDiagMatrix (mx_inline_conj_dup (data (), length ()),
00242 cols (), rows ());
00243 }
00244
00245 ComplexDiagMatrix
00246 ComplexDiagMatrix::transpose (void) const
00247 {
00248 return ComplexDiagMatrix (mx_inline_dup (data (), length ()),
00249 cols (), rows ());
00250 }
00251
00252 ComplexDiagMatrix
00253 conj (const ComplexDiagMatrix& a)
00254 {
00255 ComplexDiagMatrix retval;
00256 int a_len = a.length ();
00257 if (a_len > 0)
00258 retval = ComplexDiagMatrix (mx_inline_conj_dup (a.data (), a_len),
00259 a.rows (), a.cols ());
00260 return retval;
00261 }
00262
00263
00264
00265 ComplexMatrix
00266 ComplexDiagMatrix::extract (int r1, int c1, int r2, int c2) const
00267 {
00268 if (r1 > r2) { int tmp = r1; r1 = r2; r2 = tmp; }
00269 if (c1 > c2) { int tmp = c1; c1 = c2; c2 = tmp; }
00270
00271 int new_r = r2 - r1 + 1;
00272 int new_c = c2 - c1 + 1;
00273
00274 ComplexMatrix result (new_r, new_c);
00275
00276 for (int j = 0; j < new_c; j++)
00277 for (int i = 0; i < new_r; i++)
00278 result.elem (i, j) = elem (r1+i, c1+j);
00279
00280 return result;
00281 }
00282
00283
00284
00285 ComplexRowVector
00286 ComplexDiagMatrix::row (int i) const
00287 {
00288 int r = rows ();
00289 int c = cols ();
00290 if (i < 0 || i >= r)
00291 {
00292 (*current_liboctave_error_handler) ("invalid row selection");
00293 return ComplexRowVector ();
00294 }
00295
00296 ComplexRowVector retval (c, 0.0);
00297 if (r <= c || (r > c && i < c))
00298 retval.elem (i) = elem (i, i);
00299
00300 return retval;
00301 }
00302
00303 ComplexRowVector
00304 ComplexDiagMatrix::row (char *s) const
00305 {
00306 if (! s)
00307 {
00308 (*current_liboctave_error_handler) ("invalid row selection");
00309 return ComplexRowVector ();
00310 }
00311
00312 char c = *s;
00313 if (c == 'f' || c == 'F')
00314 return row (0);
00315 else if (c == 'l' || c == 'L')
00316 return row (rows () - 1);
00317 else
00318 {
00319 (*current_liboctave_error_handler) ("invalid row selection");
00320 return ComplexRowVector ();
00321 }
00322 }
00323
00324 ComplexColumnVector
00325 ComplexDiagMatrix::column (int i) const
00326 {
00327 int r = rows ();
00328 int c = cols ();
00329 if (i < 0 || i >= c)
00330 {
00331 (*current_liboctave_error_handler) ("invalid column selection");
00332 return ComplexColumnVector ();
00333 }
00334
00335 ComplexColumnVector retval (r, 0.0);
00336 if (r >= c || (r < c && i < r))
00337 retval.elem (i) = elem (i, i);
00338
00339 return retval;
00340 }
00341
00342 ComplexColumnVector
00343 ComplexDiagMatrix::column (char *s) const
00344 {
00345 if (! s)
00346 {
00347 (*current_liboctave_error_handler) ("invalid column selection");
00348 return ComplexColumnVector ();
00349 }
00350
00351 char c = *s;
00352 if (c == 'f' || c == 'F')
00353 return column (0);
00354 else if (c == 'l' || c == 'L')
00355 return column (cols () - 1);
00356 else
00357 {
00358 (*current_liboctave_error_handler) ("invalid column selection");
00359 return ComplexColumnVector ();
00360 }
00361 }
00362
00363 ComplexDiagMatrix
00364 ComplexDiagMatrix::inverse (void) const
00365 {
00366 int info;
00367 return inverse (info);
00368 }
00369
00370 ComplexDiagMatrix
00371 ComplexDiagMatrix::inverse (int& info) const
00372 {
00373 int r = rows ();
00374 int c = cols ();
00375 if (r != c)
00376 {
00377 (*current_liboctave_error_handler) ("inverse requires square matrix");
00378 return ComplexDiagMatrix ();
00379 }
00380
00381 ComplexDiagMatrix retval (r, c);
00382
00383 info = 0;
00384 for (int i = 0; i < length (); i++)
00385 {
00386 if (elem (i, i) == 0.0)
00387 {
00388 info = -1;
00389 return *this;
00390 }
00391 else
00392 retval.elem (i, i) = 1.0 / elem (i, i);
00393 }
00394
00395 return retval;
00396 }
00397
00398
00399
00400 ComplexDiagMatrix&
00401 ComplexDiagMatrix::operator += (const DiagMatrix& a)
00402 {
00403 int r = rows ();
00404 int c = cols ();
00405
00406 int a_nr = a.rows ();
00407 int a_nc = a.cols ();
00408
00409 if (r != a_nr || c != a_nc)
00410 {
00411 gripe_nonconformant ("operator +=", r, c, a_nr, a_nc);
00412 return *this;
00413 }
00414
00415 if (r == 0 || c == 0)
00416 return *this;
00417
00418 Complex *d = fortran_vec ();
00419
00420 mx_inline_add2 (d, a.data (), length ());
00421 return *this;
00422 }
00423
00424 ComplexDiagMatrix
00425 operator * (const ComplexDiagMatrix& a, const DiagMatrix& b)
00426 {
00427 int a_nr = a.rows ();
00428 int a_nc = a.cols ();
00429
00430 int b_nr = b.rows ();
00431 int b_nc = b.cols ();
00432
00433 if (a_nc != b_nr)
00434 {
00435 gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
00436 return ComplexDiagMatrix ();
00437 }
00438
00439 if (a_nr == 0 || a_nc == 0 || b_nc == 0)
00440 return ComplexDiagMatrix (a_nr, a_nc, 0.0);
00441
00442 ComplexDiagMatrix c (a_nr, b_nc);
00443
00444 int len = a_nr < b_nc ? a_nr : b_nc;
00445
00446 for (int i = 0; i < len; i++)
00447 {
00448 Complex a_element = a.elem (i, i);
00449 double b_element = b.elem (i, i);
00450
00451 if (a_element == 0.0 || b_element == 0.0)
00452 c.elem (i, i) = 0.0;
00453 else if (a_element == 1.0)
00454 c.elem (i, i) = b_element;
00455 else if (b_element == 1.0)
00456 c.elem (i, i) = a_element;
00457 else
00458 c.elem (i, i) = a_element * b_element;
00459 }
00460
00461 return c;
00462 }
00463
00464 ComplexDiagMatrix
00465 operator * (const DiagMatrix& a, const ComplexDiagMatrix& b)
00466 {
00467 int a_nr = a.rows ();
00468 int a_nc = a.cols ();
00469
00470 int b_nr = b.rows ();
00471 int b_nc = b.cols ();
00472
00473 if (a_nc != b_nr)
00474 {
00475 gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
00476 return ComplexDiagMatrix ();
00477 }
00478
00479 if (a_nr == 0 || a_nc == 0 || b_nc == 0)
00480 return ComplexDiagMatrix (a_nr, a_nc, 0.0);
00481
00482 ComplexDiagMatrix c (a_nr, b_nc);
00483
00484 int len = a_nr < b_nc ? a_nr : b_nc;
00485
00486 for (int i = 0; i < len; i++)
00487 {
00488 double a_element = a.elem (i, i);
00489 Complex b_element = b.elem (i, i);
00490
00491 if (a_element == 0.0 || b_element == 0.0)
00492 c.elem (i, i) = 0.0;
00493 else if (a_element == 1.0)
00494 c.elem (i, i) = b_element;
00495 else if (b_element == 1.0)
00496 c.elem (i, i) = a_element;
00497 else
00498 c.elem (i, i) = a_element * b_element;
00499 }
00500
00501 return c;
00502 }
00503
00504
00505
00506 ComplexColumnVector
00507 ComplexDiagMatrix::diag (void) const
00508 {
00509 return diag (0);
00510 }
00511
00512
00513
00514 ComplexColumnVector
00515 ComplexDiagMatrix::diag (int k) const
00516 {
00517 int nnr = rows ();
00518 int nnc = cols ();
00519 if (k > 0)
00520 nnc -= k;
00521 else if (k < 0)
00522 nnr += k;
00523
00524 ComplexColumnVector d;
00525
00526 if (nnr > 0 && nnc > 0)
00527 {
00528 int ndiag = (nnr < nnc) ? nnr : nnc;
00529
00530 d.resize (ndiag);
00531
00532 if (k > 0)
00533 {
00534 for (int i = 0; i < ndiag; i++)
00535 d.elem (i) = elem (i, i+k);
00536 }
00537 else if ( k < 0)
00538 {
00539 for (int i = 0; i < ndiag; i++)
00540 d.elem (i) = elem (i-k, i);
00541 }
00542 else
00543 {
00544 for (int i = 0; i < ndiag; i++)
00545 d.elem (i) = elem (i, i);
00546 }
00547 }
00548 else
00549 (*current_liboctave_error_handler)
00550 ("diag: requested diagonal out of range");
00551
00552 return d;
00553 }
00554
00555
00556
00557 std::ostream&
00558 operator << (std::ostream& os, const ComplexDiagMatrix& a)
00559 {
00560 Complex ZERO (0.0);
00561
00562 for (int i = 0; i < a.rows (); i++)
00563 {
00564 for (int j = 0; j < a.cols (); j++)
00565 {
00566 if (i == j)
00567 os << " " << a.elem (i, i);
00568 else
00569 os << " " << ZERO;
00570 }
00571 os << "\n";
00572 }
00573 return os;
00574 }
00575
00576
00577
00578
00579
00580