ov-base-mat.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 Copyright (C) 2009-2010 VZLU Prague
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include <iostream>
00029 
00030 #include "Cell.h"
00031 #include "oct-obj.h"
00032 #include "oct-map.h"
00033 #include "ov-base.h"
00034 #include "ov-base-mat.h"
00035 #include "ov-base-scalar.h"
00036 #include "pr-output.h"
00037 
00038 template <class MT>
00039 octave_value
00040 octave_base_matrix<MT>::subsref (const std::string& type,
00041                                  const std::list<octave_value_list>& idx)
00042 {
00043   octave_value retval;
00044 
00045   switch (type[0])
00046     {
00047     case '(':
00048       retval = do_index_op (idx.front ());
00049       break;
00050 
00051     case '{':
00052     case '.':
00053       {
00054         std::string nm = type_name ();
00055         error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
00056       }
00057       break;
00058 
00059     default:
00060       panic_impossible ();
00061     }
00062 
00063   return retval.next_subsref (type, idx);
00064 }
00065 
00066 template <class MT>
00067 octave_value
00068 octave_base_matrix<MT>::subsasgn (const std::string& type,
00069                                   const std::list<octave_value_list>& idx,
00070                                   const octave_value& rhs)
00071 {
00072   octave_value retval;
00073 
00074   switch (type[0])
00075     {
00076     case '(':
00077       {
00078         if (type.length () == 1)
00079           retval = numeric_assign (type, idx, rhs);
00080         else if (is_empty ())
00081           {
00082             // Allow conversion of empty matrix to some other type in
00083             // cases like
00084             //
00085             //  x = []; x(i).f = rhs
00086 
00087             if (type[1] == '.')
00088               {
00089                 octave_value tmp = octave_value::empty_conv (type, rhs);
00090 
00091                 retval = tmp.subsasgn (type, idx, rhs);
00092               }
00093             else
00094               error ("invalid assignment expression");
00095           }
00096         else
00097           {
00098             std::string nm = type_name ();
00099             error ("in indexed assignment of %s, last lhs index must be ()",
00100                    nm.c_str ());
00101           }
00102       }
00103       break;
00104 
00105     case '{':
00106     case '.':
00107       {
00108         if (is_empty ())
00109           {
00110             octave_value tmp = octave_value::empty_conv (type, rhs);
00111 
00112             retval = tmp.subsasgn (type, idx, rhs);
00113           }
00114         else
00115           {
00116             std::string nm = type_name ();
00117             error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
00118           }
00119       }
00120       break;
00121 
00122     default:
00123       panic_impossible ();
00124     }
00125 
00126   return retval;
00127 }
00128 
00129 template <class MT>
00130 octave_value
00131 octave_base_matrix<MT>::do_index_op (const octave_value_list& idx,
00132                                      bool resize_ok)
00133 {
00134   octave_value retval;
00135 
00136   octave_idx_type n_idx = idx.length ();
00137 
00138   int nd = matrix.ndims ();
00139   const MT& cmatrix = matrix;
00140 
00141   switch (n_idx)
00142     {
00143     case 0:
00144       retval = matrix;
00145       break;
00146 
00147     case 1:
00148       {
00149         idx_vector i = idx (0).index_vector ();
00150 
00151         if (! error_state)
00152           {
00153             // optimize single scalar index.
00154             if (! resize_ok && i.is_scalar ())
00155               retval = cmatrix.checkelem (i(0));
00156             else
00157               retval = MT (matrix.index (i, resize_ok));
00158           }
00159       }
00160       break;
00161 
00162     case 2:
00163       {
00164         idx_vector i = idx (0).index_vector ();
00165 
00166         if (! error_state)
00167           {
00168             idx_vector j = idx (1).index_vector ();
00169 
00170             if (! error_state)
00171               {
00172                 // optimize two scalar indices.
00173                 if (! resize_ok && i.is_scalar () && j.is_scalar ())
00174                   retval = cmatrix.checkelem (i(0), j(0));
00175                 else
00176                   retval = MT (matrix.index (i, j, resize_ok));
00177               }
00178           }
00179       }
00180       break;
00181 
00182     default:
00183       {
00184         Array<idx_vector> idx_vec (dim_vector (n_idx, 1));
00185         bool scalar_opt = n_idx == nd && ! resize_ok;
00186         const dim_vector dv = matrix.dims ();
00187 
00188         for (octave_idx_type i = 0; i < n_idx; i++)
00189           {
00190             idx_vec(i) = idx(i).index_vector ();
00191 
00192             if (error_state)
00193               break;
00194 
00195             scalar_opt = (scalar_opt && idx_vec(i).is_scalar ());
00196           }
00197 
00198         if (! error_state)
00199           {
00200             if (scalar_opt)
00201               retval = cmatrix.checkelem (conv_to_int_array (idx_vec));
00202             else
00203               retval = MT (matrix.index (idx_vec, resize_ok));
00204           }
00205       }
00206       break;
00207     }
00208 
00209   return retval;
00210 }
00211 
00212 template <class MT>
00213 void
00214 octave_base_matrix<MT>::assign (const octave_value_list& idx, const MT& rhs)
00215 {
00216   octave_idx_type n_idx = idx.length ();
00217 
00218   switch (n_idx)
00219     {
00220     case 0:
00221       panic_impossible ();
00222       break;
00223 
00224     case 1:
00225       {
00226         idx_vector i = idx (0).index_vector ();
00227 
00228         if (! error_state)
00229           matrix.assign (i, rhs);
00230       }
00231       break;
00232 
00233     case 2:
00234       {
00235         idx_vector i = idx (0).index_vector ();
00236 
00237         if (! error_state)
00238           {
00239             idx_vector j = idx (1).index_vector ();
00240 
00241             if (! error_state)
00242               matrix.assign (i, j, rhs);
00243           }
00244       }
00245       break;
00246 
00247     default:
00248       {
00249         Array<idx_vector> idx_vec (dim_vector (n_idx, 1));
00250 
00251         for (octave_idx_type i = 0; i < n_idx; i++)
00252           {
00253             idx_vec(i) = idx(i).index_vector ();
00254 
00255             if (error_state)
00256               break;
00257           }
00258 
00259         if (! error_state)
00260           matrix.assign (idx_vec, rhs);
00261       }
00262       break;
00263     }
00264 
00265   // Clear cache.
00266   clear_cached_info ();
00267 }
00268 
00269 template <class MT>
00270 MatrixType
00271 octave_base_matrix<MT>::matrix_type (const MatrixType& _typ) const
00272 {
00273   delete typ;
00274   typ = new MatrixType (_typ);
00275   return *typ;
00276 }
00277 
00278 template <class MT>
00279 void
00280 octave_base_matrix<MT>::assign (const octave_value_list& idx,
00281                                 typename MT::element_type rhs)
00282 {
00283   octave_idx_type n_idx = idx.length ();
00284 
00285   int nd = matrix.ndims ();
00286 
00287   MT mrhs (dim_vector (1, 1), rhs);
00288 
00289   switch (n_idx)
00290     {
00291     case 0:
00292       panic_impossible ();
00293       break;
00294 
00295     case 1:
00296       {
00297         idx_vector i = idx (0).index_vector ();
00298 
00299         if (! error_state)
00300           {
00301             // optimize single scalar index.
00302             if (i.is_scalar () && i(0) < matrix.numel ())
00303               matrix(i(0)) = rhs;
00304             else
00305               matrix.assign (i, mrhs);
00306           }
00307       }
00308       break;
00309 
00310     case 2:
00311       {
00312         idx_vector i = idx (0).index_vector ();
00313 
00314         if (! error_state)
00315           {
00316             idx_vector j = idx (1).index_vector ();
00317 
00318             if (! error_state)
00319               {
00320                 // optimize two scalar indices.
00321                 if (i.is_scalar () && j.is_scalar () && nd == 2
00322                     && i(0) < matrix.rows () && j(0) < matrix.columns ())
00323                   matrix(i(0), j(0)) = rhs;
00324                 else
00325                   matrix.assign (i, j, mrhs);
00326               }
00327           }
00328       }
00329       break;
00330 
00331     default:
00332       {
00333         Array<idx_vector> idx_vec (dim_vector (n_idx, 1));
00334         bool scalar_opt = n_idx == nd;
00335         const dim_vector dv = matrix.dims ().redim (n_idx);
00336 
00337         for (octave_idx_type i = 0; i < n_idx; i++)
00338           {
00339             idx_vec(i) = idx(i).index_vector ();
00340 
00341             if (error_state)
00342               break;
00343 
00344             scalar_opt = (scalar_opt && idx_vec(i).is_scalar ()
00345                           && idx_vec(i)(0) < dv(i));
00346           }
00347 
00348         if (! error_state)
00349           {
00350             if (scalar_opt)
00351               {
00352                 // optimize all scalar indices. Don't construct an index array,
00353                 // but rather calc a scalar index directly.
00354                 octave_idx_type k = 1, j = 0;
00355                 for (octave_idx_type i = 0; i < n_idx; i++)
00356                   {
00357                     j += idx_vec(i)(0) * k;
00358                     k *= dv (i);
00359                   }
00360                 matrix(j) = rhs;
00361               }
00362             else
00363               matrix.assign (idx_vec, mrhs);
00364           }
00365       }
00366       break;
00367     }
00368 
00369   // Clear cache.
00370   clear_cached_info ();
00371 }
00372 
00373 template <class MT>
00374 void
00375 octave_base_matrix<MT>::delete_elements (const octave_value_list& idx)
00376 {
00377   octave_idx_type len = idx.length ();
00378 
00379   Array<idx_vector> ra_idx (dim_vector (len, 1));
00380 
00381   for (octave_idx_type i = 0; i < len; i++)
00382     ra_idx(i) = idx(i).index_vector ();
00383 
00384   matrix.delete_elements (ra_idx);
00385 
00386   // Clear cache.
00387   clear_cached_info ();
00388 }
00389 
00390 template <class MT>
00391 octave_value
00392 octave_base_matrix<MT>::resize (const dim_vector& dv, bool fill) const
00393 {
00394   MT retval (matrix);
00395   if (fill)
00396     retval.resize (dv, 0);
00397   else
00398     retval.resize (dv);
00399   return retval;
00400 }
00401 
00402 template <class MT>
00403 bool
00404 octave_base_matrix<MT>::is_true (void) const
00405 {
00406   bool retval = false;
00407   dim_vector dv = matrix.dims ();
00408   int nel = dv.numel ();
00409 
00410   if (nel > 0)
00411     {
00412       MT t1 (matrix.reshape (dim_vector (nel, 1)));
00413 
00414       if (t1.any_element_is_nan ())
00415         gripe_nan_to_logical_conversion ();
00416       else
00417         {
00418           boolNDArray t2 = t1.all ();
00419 
00420           retval = t2(0);
00421         }
00422     }
00423 
00424   return retval;
00425 }
00426 
00427 template <class MT>
00428 bool
00429 octave_base_matrix<MT>::print_as_scalar (void) const
00430 {
00431   dim_vector dv = dims ();
00432 
00433   return (dv.all_ones () || dv.any_zero ());
00434 }
00435 
00436 template <class MT>
00437 void
00438 octave_base_matrix<MT>::print (std::ostream& os, bool pr_as_read_syntax) const
00439 {
00440   print_raw (os, pr_as_read_syntax);
00441   newline (os);
00442 }
00443 
00444 template <class MT>
00445 void
00446 octave_base_matrix<MT>::print_info (std::ostream& os,
00447                                     const std::string& prefix) const
00448 {
00449   matrix.print_info (os, prefix);
00450 }
00451 
00452 template <class MT>
00453 octave_value
00454 octave_base_matrix<MT>::fast_elem_extract (octave_idx_type n) const
00455 {
00456   if (n < matrix.numel ())
00457     return matrix(n);
00458   else
00459     return octave_value ();
00460 }
00461 
00462 template <class MT>
00463 bool
00464 octave_base_matrix<MT>::fast_elem_insert (octave_idx_type n,
00465                                           const octave_value& x)
00466 {
00467   if (n < matrix.numel ())
00468     {
00469       // Don't use builtin_type () here to avoid an extra VM call.
00470       typedef typename MT::element_type ET;
00471       const builtin_type_t btyp = class_to_btyp<ET>::btyp;
00472       if (btyp == btyp_unknown) // Dead branch?
00473         return false;
00474 
00475       // Set up the pointer to the proper place.
00476       void *here = reinterpret_cast<void *> (&matrix(n));
00477       // Ask x to store there if it can.
00478       return x.get_rep().fast_elem_insert_self (here, btyp);
00479     }
00480   else
00481     return false;
00482 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines