CColVector.cc

Go to the documentation of this file.
00001 // ColumnVector manipulations.
00002 /*
00003 
00004 Copyright (C) 1994-2012 John W. Eaton
00005 Copyright (C) 2010 VZLU Prague
00006 
00007 This file is part of Octave.
00008 
00009 Octave is free software; you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License as published by the
00011 Free Software Foundation; either version 3 of the License, or (at your
00012 option) any later version.
00013 
00014 Octave is distributed in the hope that it will be useful, but WITHOUT
00015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00017 for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with Octave; see the file COPYING.  If not, see
00021 <http://www.gnu.org/licenses/>.
00022 
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028 
00029 #include <iostream>
00030 
00031 #include "Array-util.h"
00032 #include "f77-fcn.h"
00033 #include "functor.h"
00034 #include "lo-error.h"
00035 #include "mx-base.h"
00036 #include "mx-inlines.cc"
00037 #include "oct-cmplx.h"
00038 
00039 // Fortran functions we call.
00040 
00041 extern "C"
00042 {
00043   F77_RET_T
00044   F77_FUNC (zgemv, ZGEMV) (F77_CONST_CHAR_ARG_DECL,
00045                            const octave_idx_type&, const octave_idx_type&,
00046                            const Complex&, const Complex*,
00047                            const octave_idx_type&, const Complex*,
00048                            const octave_idx_type&, const Complex&,
00049                            Complex*, const octave_idx_type&
00050                            F77_CHAR_ARG_LEN_DECL);
00051 }
00052 
00053 // Complex Column Vector class
00054 
00055 ComplexColumnVector::ComplexColumnVector (const ColumnVector& a)
00056    : MArray<Complex> (a)
00057 {
00058 }
00059 
00060 bool
00061 ComplexColumnVector::operator == (const ComplexColumnVector& a) const
00062 {
00063   octave_idx_type len = length ();
00064   if (len != a.length ())
00065     return 0;
00066   return mx_inline_equal (len, data (), a.data ());
00067 }
00068 
00069 bool
00070 ComplexColumnVector::operator != (const ComplexColumnVector& a) const
00071 {
00072   return !(*this == a);
00073 }
00074 
00075 // destructive insert/delete/reorder operations
00076 
00077 ComplexColumnVector&
00078 ComplexColumnVector::insert (const ColumnVector& a, octave_idx_type r)
00079 {
00080   octave_idx_type a_len = a.length ();
00081 
00082   if (r < 0 || r + a_len > length ())
00083     {
00084       (*current_liboctave_error_handler) ("range error for insert");
00085       return *this;
00086     }
00087 
00088   if (a_len > 0)
00089     {
00090       make_unique ();
00091 
00092       for (octave_idx_type i = 0; i < a_len; i++)
00093         xelem (r+i) = a.elem (i);
00094     }
00095 
00096   return *this;
00097 }
00098 
00099 ComplexColumnVector&
00100 ComplexColumnVector::insert (const ComplexColumnVector& a, octave_idx_type r)
00101 {
00102   octave_idx_type a_len = a.length ();
00103 
00104   if (r < 0 || r + a_len > length ())
00105     {
00106       (*current_liboctave_error_handler) ("range error for insert");
00107       return *this;
00108     }
00109 
00110   if (a_len > 0)
00111     {
00112       make_unique ();
00113 
00114       for (octave_idx_type i = 0; i < a_len; i++)
00115         xelem (r+i) = a.elem (i);
00116     }
00117 
00118   return *this;
00119 }
00120 
00121 ComplexColumnVector&
00122 ComplexColumnVector::fill (double val)
00123 {
00124   octave_idx_type len = length ();
00125 
00126   if (len > 0)
00127     {
00128       make_unique ();
00129 
00130       for (octave_idx_type i = 0; i < len; i++)
00131         xelem (i) = val;
00132     }
00133 
00134   return *this;
00135 }
00136 
00137 ComplexColumnVector&
00138 ComplexColumnVector::fill (const Complex& val)
00139 {
00140   octave_idx_type len = length ();
00141 
00142   if (len > 0)
00143     {
00144       make_unique ();
00145 
00146       for (octave_idx_type i = 0; i < len; i++)
00147         xelem (i) = val;
00148     }
00149 
00150 
00151   return *this;
00152 }
00153 
00154 ComplexColumnVector&
00155 ComplexColumnVector::fill (double val, octave_idx_type r1, octave_idx_type r2)
00156 {
00157   octave_idx_type len = length ();
00158 
00159   if (r1 < 0 || r2 < 0 || r1 >= len || r2 >= len)
00160     {
00161       (*current_liboctave_error_handler) ("range error for fill");
00162       return *this;
00163     }
00164 
00165   if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; }
00166 
00167   if (r2 >= r1)
00168     {
00169       make_unique ();
00170 
00171       for (octave_idx_type i = r1; i <= r2; i++)
00172         xelem (i) = val;
00173     }
00174 
00175   return *this;
00176 }
00177 
00178 ComplexColumnVector&
00179 ComplexColumnVector::fill (const Complex& val, octave_idx_type r1, octave_idx_type r2)
00180 {
00181   octave_idx_type len = length ();
00182 
00183   if (r1 < 0 || r2 < 0 || r1 >= len || r2 >= len)
00184     {
00185       (*current_liboctave_error_handler) ("range error for fill");
00186       return *this;
00187     }
00188 
00189   if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; }
00190 
00191   if (r2 >= r1)
00192     {
00193       make_unique ();
00194 
00195       for (octave_idx_type i = r1; i <= r2; i++)
00196         xelem (i) = val;
00197     }
00198 
00199   return *this;
00200 }
00201 
00202 ComplexColumnVector
00203 ComplexColumnVector::stack (const ColumnVector& a) const
00204 {
00205   octave_idx_type len = length ();
00206   octave_idx_type nr_insert = len;
00207   ComplexColumnVector retval (len + a.length ());
00208   retval.insert (*this, 0);
00209   retval.insert (a, nr_insert);
00210   return retval;
00211 }
00212 
00213 ComplexColumnVector
00214 ComplexColumnVector::stack (const ComplexColumnVector& a) const
00215 {
00216   octave_idx_type len = length ();
00217   octave_idx_type nr_insert = len;
00218   ComplexColumnVector retval (len + a.length ());
00219   retval.insert (*this, 0);
00220   retval.insert (a, nr_insert);
00221   return retval;
00222 }
00223 
00224 ComplexRowVector
00225 ComplexColumnVector::hermitian (void) const
00226 {
00227   return MArray<Complex>::hermitian (std::conj);
00228 }
00229 
00230 ComplexRowVector
00231 ComplexColumnVector::transpose (void) const
00232 {
00233   return MArray<Complex>::transpose ();
00234 }
00235 
00236 ColumnVector
00237 ComplexColumnVector::abs (void) const
00238 {
00239   return do_mx_unary_map<double, Complex, std::abs> (*this);
00240 }
00241 
00242 ComplexColumnVector
00243 conj (const ComplexColumnVector& a)
00244 {
00245   return do_mx_unary_map<Complex, Complex, std::conj<double> > (a);
00246 }
00247 
00248 // resize is the destructive equivalent for this one
00249 
00250 ComplexColumnVector
00251 ComplexColumnVector::extract (octave_idx_type r1, octave_idx_type r2) const
00252 {
00253   if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; }
00254 
00255   octave_idx_type new_r = r2 - r1 + 1;
00256 
00257   ComplexColumnVector result (new_r);
00258 
00259   for (octave_idx_type i = 0; i < new_r; i++)
00260     result.elem (i) = elem (r1+i);
00261 
00262   return result;
00263 }
00264 
00265 ComplexColumnVector
00266 ComplexColumnVector::extract_n (octave_idx_type r1, octave_idx_type n) const
00267 {
00268   ComplexColumnVector result (n);
00269 
00270   for (octave_idx_type i = 0; i < n; i++)
00271     result.elem (i) = elem (r1+i);
00272 
00273   return result;
00274 }
00275 
00276 // column vector by column vector -> column vector operations
00277 
00278 ComplexColumnVector&
00279 ComplexColumnVector::operator += (const ColumnVector& a)
00280 {
00281   octave_idx_type len = length ();
00282 
00283   octave_idx_type a_len = a.length ();
00284 
00285   if (len != a_len)
00286     {
00287       gripe_nonconformant ("operator +=", len, a_len);
00288       return *this;
00289     }
00290 
00291   if (len == 0)
00292     return *this;
00293 
00294   Complex *d = fortran_vec (); // Ensures only one reference to my privates!
00295 
00296   mx_inline_add2 (len, d, a.data ());
00297   return *this;
00298 }
00299 
00300 ComplexColumnVector&
00301 ComplexColumnVector::operator -= (const ColumnVector& a)
00302 {
00303   octave_idx_type len = length ();
00304 
00305   octave_idx_type a_len = a.length ();
00306 
00307   if (len != a_len)
00308     {
00309       gripe_nonconformant ("operator -=", len, a_len);
00310       return *this;
00311     }
00312 
00313   if (len == 0)
00314     return *this;
00315 
00316   Complex *d = fortran_vec (); // Ensures only one reference to my privates!
00317 
00318   mx_inline_sub2 (len, d, a.data ());
00319   return *this;
00320 }
00321 
00322 // matrix by column vector -> column vector operations
00323 
00324 ComplexColumnVector
00325 operator * (const ComplexMatrix& m, const ColumnVector& a)
00326 {
00327   ComplexColumnVector tmp (a);
00328   return m * tmp;
00329 }
00330 
00331 ComplexColumnVector
00332 operator * (const ComplexMatrix& m, const ComplexColumnVector& a)
00333 {
00334   ComplexColumnVector retval;
00335 
00336   octave_idx_type nr = m.rows ();
00337   octave_idx_type nc = m.cols ();
00338 
00339   octave_idx_type a_len = a.length ();
00340 
00341   if (nc != a_len)
00342     gripe_nonconformant ("operator *", nr, nc, a_len, 1);
00343   else
00344     {
00345       retval.clear (nr);
00346 
00347       if (nr != 0)
00348         {
00349           if (nc == 0)
00350             retval.fill (0.0);
00351           else
00352             {
00353               Complex *y = retval.fortran_vec ();
00354 
00355               F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 ("N", 1),
00356                                        nr, nc, 1.0, m.data (), nr,
00357                                        a.data (), 1, 0.0, y, 1
00358                                        F77_CHAR_ARG_LEN (1)));
00359             }
00360         }
00361 
00362     }
00363 
00364   return retval;
00365 }
00366 
00367 // matrix by column vector -> column vector operations
00368 
00369 ComplexColumnVector
00370 operator * (const Matrix& m, const ComplexColumnVector& a)
00371 {
00372   ComplexMatrix tmp (m);
00373   return tmp * a;
00374 }
00375 
00376 // diagonal matrix by column vector -> column vector operations
00377 
00378 ComplexColumnVector
00379 operator * (const DiagMatrix& m, const ComplexColumnVector& a)
00380 {
00381   octave_idx_type nr = m.rows ();
00382   octave_idx_type nc = m.cols ();
00383 
00384   octave_idx_type a_len = a.length ();
00385 
00386   if (nc != a_len)
00387     {
00388       gripe_nonconformant ("operator *", nr, nc, a_len, 1);
00389       return ComplexColumnVector ();
00390     }
00391 
00392   if (nc == 0 || nr == 0)
00393     return ComplexColumnVector (0);
00394 
00395   ComplexColumnVector result (nr);
00396 
00397   for (octave_idx_type i = 0; i < a_len; i++)
00398     result.elem (i) = a.elem (i) * m.elem (i, i);
00399 
00400   for (octave_idx_type i = a_len; i < nr; i++)
00401     result.elem (i) = 0.0;
00402 
00403   return result;
00404 }
00405 
00406 ComplexColumnVector
00407 operator * (const ComplexDiagMatrix& m, const ColumnVector& a)
00408 {
00409   octave_idx_type nr = m.rows ();
00410   octave_idx_type nc = m.cols ();
00411 
00412   octave_idx_type a_len = a.length ();
00413 
00414   if (nc != a_len)
00415     {
00416       gripe_nonconformant ("operator *", nr, nc, a_len, 1);
00417       return ComplexColumnVector ();
00418     }
00419 
00420   if (nc == 0 || nr == 0)
00421     return ComplexColumnVector (0);
00422 
00423   ComplexColumnVector result (nr);
00424 
00425   for (octave_idx_type i = 0; i < a_len; i++)
00426     result.elem (i) = a.elem (i) * m.elem (i, i);
00427 
00428   for (octave_idx_type i = a_len; i < nr; i++)
00429     result.elem (i) = 0.0;
00430 
00431   return result;
00432 }
00433 
00434 ComplexColumnVector
00435 operator * (const ComplexDiagMatrix& m, const ComplexColumnVector& a)
00436 {
00437   octave_idx_type nr = m.rows ();
00438   octave_idx_type nc = m.cols ();
00439 
00440   octave_idx_type a_len = a.length ();
00441 
00442   if (nc != a_len)
00443     {
00444       gripe_nonconformant ("operator *", nr, nc, a_len, 1);
00445       return ComplexColumnVector ();
00446     }
00447 
00448   if (nc == 0 || nr == 0)
00449     return ComplexColumnVector (0);
00450 
00451   ComplexColumnVector result (nr);
00452 
00453   for (octave_idx_type i = 0; i < a_len; i++)
00454     result.elem (i) = a.elem (i) * m.elem (i, i);
00455 
00456   for (octave_idx_type i = a_len; i < nr; i++)
00457     result.elem (i) = 0.0;
00458 
00459   return result;
00460 }
00461 
00462 // other operations
00463 
00464 Complex
00465 ComplexColumnVector::min (void) const
00466 {
00467   octave_idx_type len = length ();
00468   if (len == 0)
00469     return 0.0;
00470 
00471   Complex res = elem (0);
00472   double absres = std::abs (res);
00473 
00474   for (octave_idx_type i = 1; i < len; i++)
00475     if (std::abs (elem (i)) < absres)
00476       {
00477         res = elem (i);
00478         absres = std::abs (res);
00479       }
00480 
00481   return res;
00482 }
00483 
00484 Complex
00485 ComplexColumnVector::max (void) const
00486 {
00487   octave_idx_type len = length ();
00488   if (len == 0)
00489     return 0.0;
00490 
00491   Complex res = elem (0);
00492   double absres = std::abs (res);
00493 
00494   for (octave_idx_type i = 1; i < len; i++)
00495     if (std::abs (elem (i)) > absres)
00496       {
00497         res = elem (i);
00498         absres = std::abs (res);
00499       }
00500 
00501   return res;
00502 }
00503 
00504 // i/o
00505 
00506 std::ostream&
00507 operator << (std::ostream& os, const ComplexColumnVector& a)
00508 {
00509 //  int field_width = os.precision () + 7;
00510   for (octave_idx_type i = 0; i < a.length (); i++)
00511     os << /* setw (field_width) << */ a.elem (i) << "\n";
00512   return os;
00513 }
00514 
00515 std::istream&
00516 operator >> (std::istream& is, ComplexColumnVector& a)
00517 {
00518   octave_idx_type len = a.length();
00519 
00520   if (len > 0)
00521     {
00522       double tmp;
00523       for (octave_idx_type i = 0; i < len; i++)
00524         {
00525           is >> tmp;
00526           if (is)
00527             a.elem (i) = tmp;
00528           else
00529             break;
00530         }
00531     }
00532   return is;
00533 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines