GNU Octave  3.8.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-2013 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) const
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 template <class T>
442 {
443  // Try the map on the dense value.
444  octave_value retval = this->full_value ().map (umap);
445 
446  // Sparsify the result if possible.
447  // FIXME: intentionally skip this step for string mappers. Is this wanted?
448  if (umap >= umap_xisalnum && umap <= umap_xtoupper)
449  return retval;
450 
451  switch (retval.builtin_type ())
452  {
453  case btyp_double:
454  retval = retval.sparse_matrix_value ();
455  break;
456  case btyp_complex:
457  retval = retval.sparse_complex_matrix_value ();
458  break;
459  case btyp_bool:
460  retval = retval.sparse_bool_matrix_value ();
461  break;
462  default:
463  break;
464  }
465 
466  return retval;
467 }