ov-base-sparse.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2004-2012 David Bateman
00004 Copyright (C) 1998-2004 Andy Adler
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 <iomanip>
00030 #include <iostream>
00031 
00032 #include "oct-obj.h"
00033 #include "ov-base.h"
00034 #include "quit.h"
00035 #include "pr-output.h"
00036 
00037 #include "byte-swap.h"
00038 #include "ls-oct-ascii.h"
00039 #include "ls-utils.h"
00040 #include "ls-hdf5.h"
00041 
00042 #include "boolSparse.h"
00043 #include "ov-base-sparse.h"
00044 #include "pager.h"
00045 
00046 template <class T>
00047 octave_value
00048 octave_base_sparse<T>::do_index_op (const octave_value_list& idx,
00049                                     bool resize_ok)
00050 {
00051   octave_value retval;
00052 
00053   octave_idx_type n_idx = idx.length ();
00054 
00055   switch (n_idx)
00056     {
00057     case 0:
00058       retval = matrix;
00059       break;
00060 
00061     case 1:
00062       {
00063         idx_vector i = idx (0).index_vector ();
00064 
00065         if (! error_state)
00066           retval = octave_value (matrix.index (i, resize_ok));
00067       }
00068       break;
00069 
00070     case 2:
00071       {
00072         idx_vector i = idx (0).index_vector ();
00073 
00074         if (! error_state)
00075           {
00076             idx_vector j = idx (1).index_vector ();
00077 
00078             if (! error_state)
00079               retval = octave_value (matrix.index (i, j, resize_ok));
00080           }
00081       }
00082       break;
00083     default:
00084       error ("sparse indexing needs 1 or 2 indices");
00085     }
00086 
00087   return retval;
00088 }
00089 
00090 template <class T>
00091 octave_value
00092 octave_base_sparse<T>::subsref (const std::string& type,
00093                                 const std::list<octave_value_list>& idx)
00094 {
00095   octave_value retval;
00096 
00097   switch (type[0])
00098     {
00099     case '(':
00100       retval = do_index_op (idx.front ());
00101       break;
00102 
00103     case '{':
00104     case '.':
00105       {
00106         std::string nm = type_name ();
00107         error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
00108       }
00109       break;
00110 
00111     default:
00112       panic_impossible ();
00113     }
00114 
00115   return retval.next_subsref (type, idx);
00116 }
00117 
00118 template <class T>
00119 octave_value
00120 octave_base_sparse<T>::subsasgn (const std::string& type,
00121                                  const std::list<octave_value_list>& idx,
00122                                  const octave_value& rhs)
00123 {
00124   octave_value retval;
00125 
00126   switch (type[0])
00127     {
00128     case '(':
00129       {
00130         if (type.length () == 1)
00131           retval = numeric_assign (type, idx, rhs);
00132         else
00133           {
00134             std::string nm = type_name ();
00135             error ("in indexed assignment of %s, last lhs index must be ()",
00136                    nm.c_str ());
00137           }
00138       }
00139       break;
00140 
00141     case '{':
00142     case '.':
00143       {
00144         if (is_empty ())
00145           {
00146             octave_value tmp = octave_value::empty_conv (type, rhs);
00147 
00148             retval = tmp.subsasgn (type, idx, rhs);
00149           }
00150         else
00151           {
00152             std::string nm = type_name ();
00153             error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
00154           }
00155       }
00156       break;
00157 
00158     default:
00159       panic_impossible ();
00160     }
00161 
00162   return retval;
00163 }
00164 
00165 template <class T>
00166 void
00167 octave_base_sparse<T>::assign (const octave_value_list& idx, const T& rhs)
00168 {
00169 
00170   octave_idx_type len = idx.length ();
00171 
00172   switch (len)
00173     {
00174     case 1:
00175       {
00176         idx_vector i = idx (0).index_vector ();
00177 
00178         if (! error_state)
00179           matrix.assign (i, rhs);
00180 
00181         break;
00182       }
00183 
00184     case 2:
00185       {
00186         idx_vector i = idx (0).index_vector ();
00187 
00188         if (! error_state)
00189           {
00190             idx_vector j = idx (1).index_vector ();
00191 
00192             if (! error_state)
00193               matrix.assign (i, j, rhs);
00194           }
00195 
00196         break;
00197       }
00198 
00199     default:
00200       error ("sparse indexing needs 1 or 2 indices");
00201     }
00202 
00203 
00204   // Invalidate matrix type.
00205   typ.invalidate_type ();
00206 }
00207 
00208 template <class MT>
00209 void
00210 octave_base_sparse<MT>::delete_elements (const octave_value_list& idx)
00211 {
00212   octave_idx_type len = idx.length ();
00213 
00214   switch (len)
00215     {
00216     case 1:
00217       {
00218         idx_vector i = idx (0).index_vector ();
00219 
00220         if (! error_state)
00221           matrix.delete_elements (i);
00222 
00223         break;
00224       }
00225 
00226     case 2:
00227       {
00228         idx_vector i = idx (0).index_vector ();
00229 
00230         if (! error_state)
00231           {
00232             idx_vector j = idx (1).index_vector ();
00233 
00234             if (! error_state)
00235               matrix.delete_elements (i, j);
00236           }
00237 
00238         break;
00239       }
00240 
00241     default:
00242       error ("sparse indexing needs 1 or 2 indices");
00243     }
00244 
00245   // Invalidate the matrix type
00246   typ.invalidate_type ();
00247 }
00248 
00249 template <class T>
00250 octave_value
00251 octave_base_sparse<T>::resize (const dim_vector& dv, bool) const
00252 {
00253   T retval (matrix);
00254   retval.resize (dv);
00255   return retval;
00256 }
00257 
00258 template <class T>
00259 bool
00260 octave_base_sparse<T>::is_true (void) const
00261 {
00262   bool retval = false;
00263   dim_vector dv = matrix.dims ();
00264   octave_idx_type nel = dv.numel ();
00265   octave_idx_type nz = nnz ();
00266 
00267   if (nz == nel && nel > 0)
00268     {
00269       T t1 (matrix.reshape (dim_vector (nel, 1)));
00270 
00271       SparseBoolMatrix t2 = t1.all ();
00272 
00273       retval = t2(0);
00274     }
00275 
00276   return retval;
00277 }
00278 
00279 template <class T>
00280 bool
00281 octave_base_sparse<T>::print_as_scalar (void) const
00282 {
00283   dim_vector dv = dims ();
00284 
00285   return (dv.all_ones () || dv.any_zero ());
00286 }
00287 
00288 template <class T>
00289 void
00290 octave_base_sparse<T>::print (std::ostream& os, bool pr_as_read_syntax) const
00291 {
00292   print_raw (os, pr_as_read_syntax);
00293   newline (os);
00294 }
00295 
00296 template <class T>
00297 void
00298 octave_base_sparse<T>::print_info (std::ostream& os,
00299                                    const std::string& prefix) const
00300 {
00301   matrix.print_info (os, prefix);
00302 }
00303 
00304 template <class T>
00305 void
00306 octave_base_sparse<T>::print_raw (std::ostream& os,
00307                                   bool pr_as_read_syntax) const
00308 {
00309   octave_idx_type nr = matrix.rows ();
00310   octave_idx_type nc = matrix.cols ();
00311   octave_idx_type nz = nnz ();
00312 
00313   // FIXME -- this should probably all be handled by a
00314   // separate octave_print_internal function that can handle format
00315   // compact, loose, etc.
00316 
00317   os << "Compressed Column Sparse (rows = " << nr
00318      << ", cols = " << nc
00319      << ", nnz = " << nz;
00320 
00321   // Avoid calling numel here since it can easily overflow
00322   // octave_idx_type even when there is no real problem storing the
00323   // sparse array.
00324 
00325   double dnr = nr;
00326   double dnc = nc;
00327   double dnel = dnr * dnc;
00328 
00329   if (dnel > 0)
00330     {
00331       double pct = (nz / dnel * 100);
00332 
00333       int prec = 2;
00334 
00335       // Display at least 2 significant figures and up to 4 as we
00336       // approach 100%.  Avoid having limited precision of the display
00337       // result in reporting 100% for matrices that are not actually
00338       // 100% full.
00339 
00340       if (pct == 100)
00341         prec = 3;
00342       else
00343         {
00344           if (pct > 99.9)
00345             prec = 4;
00346           else if (pct > 99)
00347             prec = 3;
00348 
00349           if (pct > 99.99)
00350             pct = 99.99;
00351         }
00352 
00353       os << " [" << std::setprecision (prec) << pct << "%]";
00354     }
00355 
00356   os << ")\n";
00357 
00358   // add one to the printed indices to go from
00359   //  zero-based to one-based arrays
00360 
00361   if (nz != 0)
00362     {
00363       for (octave_idx_type j = 0; j < nc; j++)
00364         {
00365           octave_quit ();
00366 
00367           // FIXME -- is there an easy way to get the max row
00368           // and column indices so we can set the width appropriately
00369           // and line up the columns here?  Similarly, we should look
00370           // at all the nonzero values and display them with the same
00371           // formatting rules that apply to columns of a matrix.
00372 
00373           for (octave_idx_type i = matrix.cidx(j); i < matrix.cidx(j+1); i++)
00374             {
00375               os << "\n";
00376               os << "  (" << matrix.ridx(i)+1 <<
00377                 ", "  << j+1 << ") -> ";
00378 
00379               octave_print_internal (os, matrix.data(i), pr_as_read_syntax);
00380             }
00381         }
00382     }
00383 }
00384 
00385 template <class T>
00386 bool
00387 octave_base_sparse<T>::save_ascii (std::ostream& os)
00388 {
00389   dim_vector dv = this->dims ();
00390 
00391   // Ensure that additional memory is deallocated
00392   matrix.maybe_compress ();
00393 
00394   os << "# nnz: "      << nnz () << "\n";
00395   os << "# rows: "     << dv (0) << "\n";
00396   os << "# columns: "  << dv (1) << "\n";
00397 
00398   os << this->matrix;
00399 
00400   return true;
00401 }
00402 
00403 template <class T>
00404 bool
00405 octave_base_sparse<T>::load_ascii (std::istream& is)
00406 {
00407   octave_idx_type nz = 0;
00408   octave_idx_type nr = 0;
00409   octave_idx_type nc = 0;
00410   bool success = true;
00411 
00412   if (extract_keyword (is, "nnz", nz, true) &&
00413       extract_keyword (is, "rows", nr, true) &&
00414       extract_keyword (is, "columns", nc, true))
00415     {
00416       T tmp (nr, nc, nz);
00417 
00418       is >> tmp;
00419 
00420       if (!is)
00421         {
00422           error ("load: failed to load matrix constant");
00423           success = false;
00424         }
00425 
00426       matrix = tmp;
00427     }
00428   else
00429     {
00430       error ("load: failed to extract number of rows and columns");
00431       success = false;
00432     }
00433 
00434   return success;
00435 }
00436 
00437 template <class T>
00438 octave_value
00439 octave_base_sparse<T>::map (octave_base_value::unary_mapper_t umap) const
00440 {
00441   // Try the map on the dense value.
00442   octave_value retval = this->full_value ().map (umap);
00443 
00444   // Sparsify the result if possible.
00445   // FIXME: intentionally skip this step for string mappers. Is this wanted?
00446   if (umap >= umap_xisalnum && umap <= umap_xtoupper)
00447     return retval;
00448 
00449   switch (retval.builtin_type ())
00450     {
00451     case btyp_double:
00452       retval = retval.sparse_matrix_value ();
00453       break;
00454     case btyp_complex:
00455       retval = retval.sparse_complex_matrix_value ();
00456       break;
00457     case btyp_bool:
00458       retval = retval.sparse_bool_matrix_value ();
00459       break;
00460     default:
00461       break;
00462     }
00463 
00464   return retval;
00465 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines