GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ov-base-sparse.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2004-2015 David Bateman
4 Copyright (C) 1998-2004 Andy Adler
5 Copyright (C) 2010 VZLU Prague
6 
7 This file is part of Octave.
8 
9 Octave is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <iomanip>
30 #include <iostream>
31 
32 #include "oct-obj.h"
33 #include "ov-base.h"
34 #include "quit.h"
35 #include "pr-output.h"
36 
37 #include "byte-swap.h"
38 #include "ls-oct-ascii.h"
39 #include "ls-utils.h"
40 #include "ls-hdf5.h"
41 
42 #include "boolSparse.h"
43 #include "ov-base-sparse.h"
44 #include "pager.h"
45 #include "utils.h"
46 
47 template <class T>
50  bool resize_ok)
51 {
52  octave_value retval;
53 
54  octave_idx_type n_idx = idx.length ();
55 
56  switch (n_idx)
57  {
58  case 0:
59  retval = matrix;
60  break;
61 
62  case 1:
63  {
64  idx_vector i = idx (0).index_vector ();
65 
66  if (! error_state)
67  retval = octave_value (matrix.index (i, resize_ok));
68  }
69  break;
70 
71  case 2:
72  {
73  idx_vector i = idx (0).index_vector ();
74 
75  if (! error_state)
76  {
77  idx_vector j = idx (1).index_vector ();
78 
79  if (! error_state)
80  retval = octave_value (matrix.index (i, j, resize_ok));
81  }
82  }
83  break;
84  default:
85  error ("sparse indexing needs 1 or 2 indices");
86  }
87 
88  return retval;
89 }
90 
91 template <class T>
94  const std::list<octave_value_list>& idx)
95 {
96  octave_value retval;
97 
98  switch (type[0])
99  {
100  case '(':
101  retval = do_index_op (idx.front ());
102  break;
103 
104  case '{':
105  case '.':
106  {
107  std::string nm = type_name ();
108  error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
109  }
110  break;
111 
112  default:
113  panic_impossible ();
114  }
115 
116  return retval.next_subsref (type, idx);
117 }
118 
119 template <class T>
122  const std::list<octave_value_list>& idx,
123  const octave_value& rhs)
124 {
125  octave_value retval;
126 
127  switch (type[0])
128  {
129  case '(':
130  {
131  if (type.length () == 1)
132  retval = numeric_assign (type, idx, rhs);
133  else
134  {
135  std::string nm = type_name ();
136  error ("in indexed assignment of %s, last lhs index must be ()",
137  nm.c_str ());
138  }
139  }
140  break;
141 
142  case '{':
143  case '.':
144  {
145  if (is_empty ())
146  {
147  octave_value tmp = octave_value::empty_conv (type, rhs);
148 
149  retval = tmp.subsasgn (type, idx, rhs);
150  }
151  else
152  {
153  std::string nm = type_name ();
154  error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
155  }
156  }
157  break;
158 
159  default:
160  panic_impossible ();
161  }
162 
163  return retval;
164 }
165 
166 template <class T>
167 void
169 {
170 
171  octave_idx_type len = idx.length ();
172 
173  switch (len)
174  {
175  case 1:
176  {
177  idx_vector i = idx (0).index_vector ();
178 
179  if (! error_state)
180  matrix.assign (i, rhs);
181 
182  break;
183  }
184 
185  case 2:
186  {
187  idx_vector i = idx (0).index_vector ();
188 
189  if (! error_state)
190  {
191  idx_vector j = idx (1).index_vector ();
192 
193  if (! error_state)
194  matrix.assign (i, j, rhs);
195  }
196 
197  break;
198  }
199 
200  default:
201  error ("sparse indexing needs 1 or 2 indices");
202  }
203 
204 
205  // Invalidate matrix type.
206  typ.invalidate_type ();
207 }
208 
209 template <class MT>
210 void
212 {
213  octave_idx_type len = idx.length ();
214 
215  switch (len)
216  {
217  case 1:
218  {
219  idx_vector i = idx (0).index_vector ();
220 
221  if (! error_state)
222  matrix.delete_elements (i);
223 
224  break;
225  }
226 
227  case 2:
228  {
229  idx_vector i = idx (0).index_vector ();
230 
231  if (! error_state)
232  {
233  idx_vector j = idx (1).index_vector ();
234 
235  if (! error_state)
236  matrix.delete_elements (i, j);
237  }
238 
239  break;
240  }
241 
242  default:
243  error ("sparse indexing needs 1 or 2 indices");
244  }
245 
246  // Invalidate the matrix type
247  typ.invalidate_type ();
248 }
249 
250 template <class T>
253 {
254  T retval (matrix);
255  retval.resize (dv);
256  return retval;
257 }
258 
259 template <class T>
260 bool
262 {
263  bool retval = false;
264  dim_vector dv = matrix.dims ();
265  octave_idx_type nel = dv.numel ();
266  octave_idx_type nz = nnz ();
267 
268  if (nz == nel && nel > 0)
269  {
270  T t1 (matrix.reshape (dim_vector (nel, 1)));
271 
272  SparseBoolMatrix t2 = t1.all ();
273 
274  retval = t2(0);
275  }
276 
277  return retval;
278 }
279 
280 template <class T>
281 bool
283 {
284  dim_vector dv = dims ();
285 
286  return (dv.all_ones () || dv.any_zero ());
287 }
288 
289 template <class T>
290 void
291 octave_base_sparse<T>::print (std::ostream& os, bool pr_as_read_syntax)
292 {
293  print_raw (os, pr_as_read_syntax);
294  newline (os);
295 }
296 
297 template <class T>
298 void
300  const std::string& prefix) const
301 {
302  matrix.print_info (os, prefix);
303 }
304 
305 template <class T>
306 void
308  bool pr_as_read_syntax) const
309 {
310  octave_preserve_stream_state stream_state (os);
311 
312  octave_idx_type nr = matrix.rows ();
313  octave_idx_type nc = matrix.cols ();
314  octave_idx_type nz = nnz ();
315 
316  // FIXME: this should probably all be handled by a
317  // separate octave_print_internal function that can handle format
318  // compact, loose, etc.
319 
320  os << "Compressed Column Sparse (rows = " << nr
321  << ", cols = " << nc
322  << ", nnz = " << nz;
323 
324  // Avoid calling numel here since it can easily overflow
325  // octave_idx_type even when there is no real problem storing the
326  // sparse array.
327 
328  double dnr = nr;
329  double dnc = nc;
330  double dnel = dnr * dnc;
331 
332  if (dnel > 0)
333  {
334  double pct = (nz / dnel * 100);
335 
336  int prec = 2;
337 
338  // Display at least 2 significant figures and up to 4 as we
339  // approach 100%. Avoid having limited precision of the display
340  // result in reporting 100% for matrices that are not actually
341  // 100% full.
342 
343  if (pct == 100)
344  prec = 3;
345  else
346  {
347  if (pct > 99.9)
348  prec = 4;
349  else if (pct > 99)
350  prec = 3;
351 
352  if (pct > 99.99)
353  pct = 99.99;
354  }
355 
356  os << " [" << std::setprecision (prec) << pct << "%]";
357  }
358 
359  os << ")\n";
360 
361  // add one to the printed indices to go from
362  // zero-based to one-based arrays
363 
364  if (nz != 0)
365  {
366  for (octave_idx_type j = 0; j < nc; j++)
367  {
368  octave_quit ();
369 
370  // FIXME: is there an easy way to get the max row
371  // and column indices so we can set the width appropriately
372  // and line up the columns here? Similarly, we should look
373  // at all the nonzero values and display them with the same
374  // formatting rules that apply to columns of a matrix.
375 
376  for (octave_idx_type i = matrix.cidx (j); i < matrix.cidx (j+1); i++)
377  {
378  os << "\n";
379  os << " (" << matrix.ridx (i)+1 << ", " << j+1 << ") -> ";
380 
381  octave_print_internal (os, matrix.data (i), pr_as_read_syntax);
382  }
383  }
384  }
385 }
386 
387 template <class T>
388 bool
390 {
391  dim_vector dv = this->dims ();
392 
393  // Ensure that additional memory is deallocated
394  matrix.maybe_compress ();
395 
396  os << "# nnz: " << nnz () << "\n";
397  os << "# rows: " << dv (0) << "\n";
398  os << "# columns: " << dv (1) << "\n";
399 
400  os << this->matrix;
401 
402  return true;
403 }
404 
405 template <class T>
406 bool
408 {
409  octave_idx_type nz = 0;
410  octave_idx_type nr = 0;
411  octave_idx_type nc = 0;
412  bool success = true;
413 
414  if (extract_keyword (is, "nnz", nz, true)
415  && extract_keyword (is, "rows", nr, true)
416  && extract_keyword (is, "columns", nc, true))
417  {
418  T tmp (nr, nc, nz);
419 
420  is >> tmp;
421 
422  if (!is)
423  {
424  error ("load: failed to load matrix constant");
425  success = false;
426  }
427 
428  matrix = tmp;
429  }
430  else
431  {
432  error ("load: failed to extract number of rows and columns");
433  success = false;
434  }
435 
436  return success;
437 }
438 
439 
440 template <class T>
443 {
444  octave_idx_type nr = matrix.rows ();
445  octave_idx_type nc = matrix.cols ();
446 
447  octave_idx_type i = n % nr;
448  octave_idx_type j = n / nr;
449 
450  return (i < nr && j < nc) ? octave_value (matrix(i,j)) : octave_value ();
451 }
452 
453 template <class T>
456 {
457  if (umap == umap_xtolower || umap == umap_xtoupper)
458  return matrix;
459 
460  // Try the map on the dense value.
461  // FIXME: We should probably be smarter about this, especially for the
462  // cases that are expected to return sparse matrices.
463  octave_value retval = this->full_value ().map (umap);
464 
465  // Sparsify the result if possible.
466 
467  switch (umap)
468  {
469  case umap_xisalnum:
470  case umap_xisalpha:
471  case umap_xisascii:
472  case umap_xiscntrl:
473  case umap_xisdigit:
474  case umap_xisgraph:
475  case umap_xislower:
476  case umap_xisprint:
477  case umap_xispunct:
478  case umap_xisspace:
479  case umap_xisupper:
480  case umap_xisxdigit:
481  case umap_xtoascii:
482  // FIXME: intentionally skip this step for string mappers.
483  // Is this wanted?
484  break;
485 
486  default:
487  {
488  switch (retval.builtin_type ())
489  {
490  case btyp_double:
491  retval = retval.sparse_matrix_value ();
492  break;
493 
494  case btyp_complex:
495  retval = retval.sparse_complex_matrix_value ();
496  break;
497 
498  case btyp_bool:
499  retval = retval.sparse_bool_matrix_value ();
500  break;
501 
502  default:
503  break;
504  }
505  }
506  }
507 
508  return retval;
509 }
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
octave_idx_type length(void) const
Definition: oct-obj.h:89
bool load_ascii(std::istream &is)
void error(const char *fmt,...)
Definition: error.cc:476
octave_value map(octave_base_value::unary_mapper_t umap) const
Definition: ov.h:1226
bool print_as_scalar(void) const
bool all_ones(void) const
Definition: dim-vector.h:349
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:361
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov.cc:1414
void assign(const octave_value_list &idx, const T &rhs)
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
Definition: ls-oct-ascii.cc:80
SparseBoolMatrix all(int dim=-1) const
Definition: boolSparse.cc:138
octave_value map(octave_base_value::unary_mapper_t umap) const
int error_state
Definition: error.cc:101
SparseBoolMatrix sparse_bool_matrix_value(bool warn=false) const
Definition: ov.h:827
#define panic_impossible()
Definition: error.h:33
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
void print(std::ostream &os, bool pr_as_read_syntax=false)
void print_info(std::ostream &os, const std::string &prefix) const
bool any_zero(void) const
Definition: dim-vector.h:331
SparseComplexMatrix sparse_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:824
bool save_ascii(std::ostream &os)
void delete_elements(const octave_value_list &idx)
octave_value fast_elem_extract(octave_idx_type n) const
octave_value resize(const dim_vector &dv, bool=false) const
void octave_print_internal(std::ostream &, char, bool)
Definition: pr-output.cc:1715
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
SparseMatrix sparse_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:820
builtin_type_t builtin_type(void) const
Definition: ov.h:603
bool is_true(void) const
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, size_t skip=1)
Definition: ov.cc:1317
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
static octave_value empty_conv(const std::string &type, const octave_value &rhs=octave_value())
Definition: ov.cc:2829