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
Sparse.h
Go to the documentation of this file.
1 // Template sparse classes
2 /*
3 
4 Copyright (C) 2004-2013 David Bateman
5 Copyright (C) 1998-2004 Andy Adler
6 Copyright (C) 2010 VZLU Prague
7 
8 This file is part of Octave.
9 
10 Octave is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 3 of the License, or (at your
13 option) any later version.
14 
15 Octave is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with Octave; see the file COPYING. If not, see
22 <http://www.gnu.org/licenses/>.
23 
24 */
25 
26 #if !defined (octave_Sparse_h)
27 #define octave_Sparse_h 1
28 
29 #include <cassert>
30 #include <cstddef>
31 
32 #include <iosfwd>
33 #include <algorithm>
34 
35 #include "Array.h"
36 #include "dim-vector.h"
37 #include "lo-error.h"
38 #include "lo-utils.h"
39 
40 #include "oct-sort.h"
41 #include "oct-mem.h"
42 
43 class idx_vector;
44 class PermMatrix;
45 
46 // Two dimensional sparse class. Handles the reference counting for
47 // all the derived classes.
48 
49 template <class T>
50 class
51 Sparse
52 {
53 public:
54 
55  typedef T element_type;
56 
57 protected:
58  //--------------------------------------------------------------------
59  // The real representation of all Sparse arrays.
60  //--------------------------------------------------------------------
61 
62  class OCTAVE_API SparseRep
63  {
64  public:
65 
66  T *d;
73 
74  SparseRep (void)
75  : d (0), r (0), c (new octave_idx_type [1]), nzmx (0), nrows (0),
76  ncols (0), count (1)
77  {
78  c[0] = 0;
79  }
80 
82  : d (0), r (0), c (new octave_idx_type [n+1]), nzmx (0), nrows (n),
83  ncols (n), count (1)
84  {
85  for (octave_idx_type i = 0; i < n + 1; i++)
86  c[i] = 0;
87  }
88 
90  : d (nz > 0 ? new T [nz] : 0),
91  r (nz > 0 ? new octave_idx_type [nz] : 0),
92  c (new octave_idx_type [nc+1]), nzmx (nz), nrows (nr),
93  ncols (nc), count (1)
94  {
95  for (octave_idx_type i = 0; i < nc + 1; i++)
96  c[i] = 0;
97  }
98 
99  SparseRep (const SparseRep& a)
100  : d (new T [a.nzmx]), r (new octave_idx_type [a.nzmx]),
101  c (new octave_idx_type [a.ncols + 1]),
102  nzmx (a.nzmx), nrows (a.nrows), ncols (a.ncols), count (1)
103  {
104  octave_idx_type nz = a.nnz ();
105  copy_or_memcpy (nz, a.d, d);
106  copy_or_memcpy (nz, a.r, r);
107  copy_or_memcpy (ncols + 1, a.c, c);
108  }
109 
110  ~SparseRep (void) { delete [] d; delete [] r; delete [] c; }
111 
112  octave_idx_type length (void) const { return nzmx; }
113 
114  octave_idx_type nnz (void) const { return c[ncols]; }
115 
117 
118  T celem (octave_idx_type _r, octave_idx_type _c) const;
119 
120  T& data (octave_idx_type i) { return d[i]; }
121 
122  T cdata (octave_idx_type i) const { return d[i]; }
123 
124  octave_idx_type& ridx (octave_idx_type i) { return r[i]; }
125 
126  octave_idx_type cridx (octave_idx_type i) const { return r[i]; }
127 
128  octave_idx_type& cidx (octave_idx_type i) { return c[i]; }
129 
130  octave_idx_type ccidx (octave_idx_type i) const { return c[i]; }
131 
132  void maybe_compress (bool remove_zeros);
133 
134  void change_length (octave_idx_type nz);
135 
136  bool indices_ok (void) const;
137 
138  private:
139 
140  // No assignment!
141 
142  SparseRep& operator = (const SparseRep& a);
143  };
144 
145  //--------------------------------------------------------------------
146 
147  void make_unique (void)
148  {
149  if (rep->count > 1)
150  {
151  SparseRep *r = new SparseRep (*rep);
152 
153  if (--rep->count == 0)
154  delete rep;
155 
156  rep = r;
157  }
158  }
159 
160 public:
161 
162  // !!! WARNING !!! -- these should be protected, not public. You
163  // should not access these data members directly!
164 
166 
168 
169 private:
170 
171  typename Sparse<T>::SparseRep *nil_rep (void) const
172  {
173  static typename Sparse<T>::SparseRep nr;
174  return &nr;
175  }
176 
177 public:
178 
179  Sparse (void)
180  : rep (nil_rep ()), dimensions (dim_vector(0,0))
181  {
182  rep->count++;
183  }
184 
185  explicit Sparse (octave_idx_type n)
186  : rep (new typename Sparse<T>::SparseRep (n)),
187  dimensions (dim_vector (n, n)) { }
188 
190  : rep (new typename Sparse<T>::SparseRep (nr, nc)),
191  dimensions (dim_vector (nr, nc)) { }
192 
193  explicit Sparse (octave_idx_type nr, octave_idx_type nc, T val);
194 
196  : rep (new typename Sparse<T>::SparseRep (dv(0), dv(1), nz)),
197  dimensions (dv) { }
198 
200  : rep (new typename Sparse<T>::SparseRep (nr, nc, nz)),
201  dimensions (dim_vector (nr, nc)) { }
202 
203  // Both SparseMatrix and SparseBoolMatrix need this ctor, and this
204  // is their only common ancestor.
205  explicit Sparse (const PermMatrix& a);
206 
207  // Type conversion case. Preserves capacity ().
208  template <class U>
209  Sparse (const Sparse<U>& a)
210  : rep (new typename Sparse<T>::SparseRep (a.rep->nrows, a.rep->ncols,
211  a.rep->nzmx)),
212  dimensions (a.dimensions)
213  {
214  octave_idx_type nz = a.nnz ();
215  std::copy (a.rep->d, a.rep->d + nz, rep->d);
216  copy_or_memcpy (nz, a.rep->r, rep->r);
217  copy_or_memcpy (rep->ncols + 1, a.rep->c, rep->c);
218  }
219 
220  // No type conversion case.
221  Sparse (const Sparse<T>& a)
222  : rep (a.rep), dimensions (a.dimensions)
223  {
224  rep->count++;
225  }
226 
227 public:
228 
229  Sparse (const dim_vector& dv);
230 
231  Sparse (const Sparse<T>& a, const dim_vector& dv);
232 
233  Sparse (const Array<T>& a, const idx_vector& r, const idx_vector& c,
234  octave_idx_type nr = -1, octave_idx_type nc = -1,
235  bool sum_terms = true, octave_idx_type nzm = -1);
236 
237  // Sparsify a normal matrix
238  Sparse (const Array<T>& a);
239 
240  virtual ~Sparse (void);
241 
242  Sparse<T>& operator = (const Sparse<T>& a);
243 
244  // Note that nzmax and capacity are the amount of storage for
245  // non-zero elements, while nnz is the actual number of non-zero
246  // terms.
247  octave_idx_type nzmax (void) const { return rep->length (); }
248  octave_idx_type capacity (void) const { return nzmax (); }
249  octave_idx_type nnz (void) const { return rep->nnz (); }
250 
251  // Querying the number of elements (incl. zeros) may overflow the index type,
252  // so don't do it unless you really need it.
253  octave_idx_type numel (void) const
254  {
255  return dimensions.safe_numel ();
256  }
257 
258  octave_idx_type nelem (void) const { return capacity (); }
259  octave_idx_type length (void) const { return numel (); }
260 
261  octave_idx_type dim1 (void) const { return dimensions(0); }
262  octave_idx_type dim2 (void) const { return dimensions(1); }
263 
264  octave_idx_type rows (void) const { return dim1 (); }
265  octave_idx_type cols (void) const { return dim2 (); }
266  octave_idx_type columns (void) const { return dim2 (); }
267 
270  {
271  octave_idx_type ret = 0;
272  while (cidx (ret+1) < k)
273  ret++;
274  return ret;
275  }
276 
277  size_t byte_size (void) const
278  {
279  return (static_cast<size_t>(cols () + 1) * sizeof (octave_idx_type)
280  + static_cast<size_t> (capacity ())
281  * (sizeof (T) + sizeof (octave_idx_type)));
282  }
283 
284  dim_vector dims (void) const { return dimensions; }
285 
286  Sparse<T> squeeze (void) const { return *this; }
287 
289 
290  T range_error (const char *fcn, octave_idx_type n) const;
291  T& range_error (const char *fcn, octave_idx_type n);
292 
293  T range_error (const char *fcn, octave_idx_type i, octave_idx_type j) const;
294  T& range_error (const char *fcn, octave_idx_type i, octave_idx_type j);
295 
296  T range_error (const char *fcn, const Array<octave_idx_type>& ra_idx) const;
297  T& range_error (const char *fcn, const Array<octave_idx_type>& ra_idx);
298 
299  // No checking, even for multiple references, ever.
300 
301  T& xelem (octave_idx_type n)
302  {
303  octave_idx_type i = n % rows (), j = n / rows ();
304  return xelem (i, j);
305  }
306 
307  T xelem (octave_idx_type n) const
308  {
309  octave_idx_type i = n % rows (), j = n / rows ();
310  return xelem (i, j);
311  }
312 
313  T& xelem (octave_idx_type i, octave_idx_type j) { return rep->elem (i, j); }
314  T xelem (octave_idx_type i, octave_idx_type j) const
315  {
316  return rep->celem (i, j);
317  }
318 
319  T& xelem (const Array<octave_idx_type>& ra_idx)
320  { return xelem (compute_index (ra_idx)); }
321 
322  T xelem (const Array<octave_idx_type>& ra_idx) const
323  { return xelem (compute_index (ra_idx)); }
324 
325  // FIXME: would be nice to fix this so that we don't
326  // unnecessarily force a copy, but that is not so easy, and I see no
327  // clean way to do it.
328 
329  T& checkelem (octave_idx_type n)
330  {
331  if (n < 0 || n >= numel ())
332  return range_error ("T& Sparse<T>::checkelem", n);
333  else
334  {
335  make_unique ();
336  return xelem (n);
337  }
338  }
339 
340  T& checkelem (octave_idx_type i, octave_idx_type j)
341  {
342  if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ())
343  return range_error ("T& Sparse<T>::checkelem", i, j);
344  else
345  {
346  make_unique ();
347  return xelem (i, j);
348  }
349  }
350 
351  T& checkelem (const Array<octave_idx_type>& ra_idx)
352  {
353  octave_idx_type i = compute_index (ra_idx);
354 
355  if (i < 0)
356  return range_error ("T& Sparse<T>::checkelem", ra_idx);
357  else
358  return elem (i);
359  }
360 
362  {
363  make_unique ();
364  return xelem (n);
365  }
366 
368  {
369  make_unique ();
370  return xelem (i, j);
371  }
372 
373  T& elem (const Array<octave_idx_type>& ra_idx)
374  { return Sparse<T>::elem (compute_index (ra_idx)); }
375 
376 #if defined (BOUNDS_CHECKING)
377  T& operator () (octave_idx_type n)
378  {
379  return checkelem (n);
380  }
381 
382  T& operator () (octave_idx_type i, octave_idx_type j)
383  {
384  return checkelem (i, j);
385  }
386 
387  T& operator () (const Array<octave_idx_type>& ra_idx)
388  {
389  return checkelem (ra_idx);
390  }
391 
392 #else
393  T& operator () (octave_idx_type n)
394  {
395  return elem (n);
396  }
397 
398  T& operator () (octave_idx_type i, octave_idx_type j)
399  {
400  return elem (i, j);
401  }
402 
403  T& operator () (const Array<octave_idx_type>& ra_idx)
404  {
405  return elem (ra_idx);
406  }
407 
408 #endif
409 
410  T checkelem (octave_idx_type n) const
411  {
412  if (n < 0 || n >= numel ())
413  return range_error ("T Sparse<T>::checkelem", n);
414  else
415  return xelem (n);
416  }
417 
418  T checkelem (octave_idx_type i, octave_idx_type j) const
419  {
420  if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ())
421  return range_error ("T Sparse<T>::checkelem", i, j);
422  else
423  return xelem (i, j);
424  }
425 
426  T checkelem (const Array<octave_idx_type>& ra_idx) const
427  {
428  octave_idx_type i = compute_index (ra_idx);
429 
430  if (i < 0)
431  return range_error ("T Sparse<T>::checkelem", ra_idx);
432  else
433  return Sparse<T>::elem (i);
434  }
435 
436  T elem (octave_idx_type n) const { return xelem (n); }
437 
438  T elem (octave_idx_type i, octave_idx_type j) const { return xelem (i, j); }
439 
440  T elem (const Array<octave_idx_type>& ra_idx) const
441  { return Sparse<T>::elem (compute_index (ra_idx)); }
442 
443 #if defined (BOUNDS_CHECKING)
444  T operator () (octave_idx_type n) const { return checkelem (n); }
445  T operator () (octave_idx_type i, octave_idx_type j) const
446  {
447  return checkelem (i, j);
448  }
449 
450  T operator () (const Array<octave_idx_type>& ra_idx) const
451  {
452  return checkelem (ra_idx);
453  }
454 
455 #else
456  T operator () (octave_idx_type n) const { return elem (n); }
457  T operator () (octave_idx_type i, octave_idx_type j) const
458  {
459  return elem (i, j);
460  }
461 
462  T operator () (const Array<octave_idx_type>& ra_idx) const
463  {
464  return elem (ra_idx);
465  }
466 #endif
467 
468  Sparse<T> maybe_compress (bool remove_zeros = false)
469  {
470  if (remove_zeros)
471  make_unique (); // Needs to unshare because elements are removed.
472 
473  rep->maybe_compress (remove_zeros);
474  return (*this);
475  }
476 
477  Sparse<T> reshape (const dim_vector& new_dims) const;
478 
479  Sparse<T> permute (const Array<octave_idx_type>& vec, bool inv = false) const;
480 
481  Sparse<T> ipermute (const Array<octave_idx_type>& vec) const
482  {
483  return permute (vec, true);
484  }
485 
486  void resize1 (octave_idx_type n);
487 
488  void resize (octave_idx_type r, octave_idx_type c);
489 
490  void resize (const dim_vector& dv);
491 
492  void change_capacity (octave_idx_type nz)
493  {
494  if (nz < nnz ())
495  make_unique (); // Unshare now because elements will be truncated.
496  rep->change_length (nz);
497  }
498 
499  Sparse<T>& insert (const Sparse<T>& a, octave_idx_type r, octave_idx_type c);
500  Sparse<T>& insert (const Sparse<T>& a, const Array<octave_idx_type>& idx);
501 
502  bool is_square (void) const { return (dim1 () == dim2 ()); }
503 
504  bool is_empty (void) const { return (rows () < 1 && cols () < 1); }
505 
506  Sparse<T> transpose (void) const;
507 
508  T* data (void) { make_unique (); return rep->d; }
509  T& data (octave_idx_type i) { make_unique (); return rep->data (i); }
510  T* xdata (void) { return rep->d; }
511  T& xdata (octave_idx_type i) { return rep->data (i); }
512 
513  T data (octave_idx_type i) const { return rep->data (i); }
514  // FIXME: shouldn't this be returning const T*?
515  T* data (void) const { return rep->d; }
516 
517  octave_idx_type* ridx (void) { make_unique (); return rep->r; }
519  {
520  make_unique (); return rep->ridx (i);
521  }
522 
523  octave_idx_type* xridx (void) { return rep->r; }
524  octave_idx_type& xridx (octave_idx_type i) { return rep->ridx (i); }
525 
526  octave_idx_type ridx (octave_idx_type i) const { return rep->cridx (i); }
527  // FIXME: shouldn't this be returning const octave_idx_type*?
528  octave_idx_type* ridx (void) const { return rep->r; }
529 
530  octave_idx_type* cidx (void) { make_unique (); return rep->c; }
532  {
533  make_unique (); return rep->cidx (i);
534  }
535 
536  octave_idx_type* xcidx (void) { return rep->c; }
537  octave_idx_type& xcidx (octave_idx_type i) { return rep->cidx (i); }
538 
539  octave_idx_type cidx (octave_idx_type i) const { return rep->ccidx (i); }
540  // FIXME: shouldn't this be returning const octave_idx_type*?
541  octave_idx_type* cidx (void) const { return rep->c; }
542 
543  octave_idx_type ndims (void) const { return dimensions.length (); }
544 
545  void delete_elements (const idx_vector& i);
546 
547  void delete_elements (int dim, const idx_vector& i);
548 
549  void delete_elements (const idx_vector& i, const idx_vector& j);
550 
551  Sparse<T> index (const idx_vector& i, bool resize_ok = false) const;
552 
553  Sparse<T> index (const idx_vector& i, const idx_vector& j,
554  bool resize_ok = false) const;
555 
556  void assign (const idx_vector& i, const Sparse<T>& rhs);
557 
558  void assign (const idx_vector& i, const idx_vector& j, const Sparse<T>& rhs);
559 
560  void print_info (std::ostream& os, const std::string& prefix) const;
561 
562  // Unsafe. These functions exist to support the MEX interface.
563  // You should not use them anywhere else.
564  void *mex_get_data (void) const { return const_cast<T *> (data ()); }
565 
566  octave_idx_type *mex_get_ir (void) const
567  {
568  return const_cast<octave_idx_type *> (ridx ());
569  }
570 
571  octave_idx_type *mex_get_jc (void) const
572  {
573  return const_cast<octave_idx_type *> (cidx ());
574  }
575 
576  Sparse<T> sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;
577  Sparse<T> sort (Array<octave_idx_type> &sidx, octave_idx_type dim = 0,
578  sortmode mode = ASCENDING) const;
579 
580  Sparse<T> diag (octave_idx_type k = 0) const;
581 
582  // dim = -1 and dim = -2 are special; see Array<T>::cat description.
583  static Sparse<T>
584  cat (int dim, octave_idx_type n, const Sparse<T> *sparse_list);
585 
586  Array<T> array_value (void) const;
587 
588  // Generic any/all test functionality with arbitrary predicate.
589  template <class F, bool zero>
590  bool test (F fcn) const
591  {
592  return any_all_test<F, T, zero> (fcn, data (), nnz ());
593  }
594 
595  // Simpler calls.
596  template <class F>
597  bool test_any (F fcn) const
598  { return test<F, false> (fcn); }
599 
600  template <class F>
601  bool test_all (F fcn) const
602  { return test<F, true> (fcn); }
603 
604  // Overloads for function references.
605  bool test_any (bool (&fcn) (T)) const
606  { return test<bool (&) (T), false> (fcn); }
607 
608  bool test_any (bool (&fcn) (const T&)) const
609  { return test<bool (&) (const T&), false> (fcn); }
610 
611  bool test_all (bool (&fcn) (T)) const
612  { return test<bool (&) (T), true> (fcn); }
613 
614  bool test_all (bool (&fcn) (const T&)) const
615  { return test<bool (&) (const T&), true> (fcn); }
616 
617  template <class U, class F>
618  Sparse<U>
619  map (F fcn) const
620  {
621  Sparse<U> result;
622  U f_zero = fcn (0.);
623 
624  if (f_zero != 0.)
625  {
626  octave_idx_type nr = rows ();
627  octave_idx_type nc = cols ();
628 
629  result = Sparse<U> (nr, nc, f_zero);
630 
631  for (octave_idx_type j = 0; j < nc; j++)
632  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)
633  {
634  octave_quit ();
635  /* Use data instead of elem for better performance. */
636  result.data (ridx (i) + j * nr) = fcn (data (i));
637  }
638 
639  result.maybe_compress (true);
640  }
641  else
642  {
643  octave_idx_type nz = nnz ();
644  octave_idx_type nr = rows ();
645  octave_idx_type nc = cols ();
646 
647  result = Sparse<U> (nr, nc, nz);
648  octave_idx_type ii = 0;
649  result.cidx (ii) = 0;
650 
651  for (octave_idx_type j = 0; j < nc; j++)
652  {
653  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)
654  {
655  U val = fcn (data (i));
656  if (val != 0.0)
657  {
658  result.data (ii) = val;
659  result.ridx (ii++) = ridx (i);
660  }
661  octave_quit ();
662  }
663  result.cidx (j+1) = ii;
664  }
665 
666  result.maybe_compress (false);
667  }
668 
669  return result;
670  }
671 
672  // Overloads for function references.
673  template <class U>
674  Sparse<U>
675  map (U (&fcn) (T)) const
676  { return map<U, U (&) (T)> (fcn); }
677 
678  template <class U>
679  Sparse<U>
680  map (U (&fcn) (const T&)) const
681  { return map<U, U (&) (const T&)> (fcn); }
682 
683  bool indices_ok (void) const { return rep->indices_ok (); }
684 };
685 
686 template<typename T>
687 std::istream&
688 read_sparse_matrix (std::istream& is, Sparse<T>& a,
689  T (*read_fcn) (std::istream&))
690 {
691  octave_idx_type nr = a.rows ();
692  octave_idx_type nc = a.cols ();
693  octave_idx_type nz = a.nzmax ();
694 
695  if (nr > 0 && nc > 0)
696  {
697  octave_idx_type itmp;
698  octave_idx_type jtmp;
699  octave_idx_type iold = 0;
700  octave_idx_type jold = 0;
701  octave_idx_type ii = 0;
702  T tmp;
703 
704  a.cidx (0) = 0;
705  for (octave_idx_type i = 0; i < nz; i++)
706  {
707  itmp = 0; jtmp = 0;
708  is >> itmp;
709  itmp--;
710 
711  is >> jtmp;
712  jtmp--;
713 
714  if (itmp < 0 || itmp >= nr)
715  {
716  (*current_liboctave_error_handler)
717  ("invalid sparse matrix: row index = %d out of range",
718  itmp + 1);
719  is.setstate (std::ios::failbit);
720  goto done;
721  }
722 
723  if (jtmp < 0 || jtmp >= nc)
724  {
725  (*current_liboctave_error_handler)
726  ("invalid sparse matrix: column index = %d out of range",
727  jtmp + 1);
728  is.setstate (std::ios::failbit);
729  goto done;
730  }
731 
732  if (jtmp < jold)
733  {
734  (*current_liboctave_error_handler)
735  ("invalid sparse matrix: column indices must appear in ascending order");
736  is.setstate (std::ios::failbit);
737  goto done;
738  }
739  else if (jtmp > jold)
740  {
741  for (octave_idx_type j = jold; j < jtmp; j++)
742  a.cidx (j+1) = ii;
743  }
744  else if (itmp < iold)
745  {
746  (*current_liboctave_error_handler)
747  ("invalid sparse matrix: row indices must appear in ascending order in each column");
748  is.setstate (std::ios::failbit);
749  goto done;
750  }
751 
752  iold = itmp;
753  jold = jtmp;
754 
755  tmp = read_fcn (is);
756 
757  if (is)
758  {
759  a.data (ii) = tmp;
760  a.ridx (ii++) = itmp;
761  }
762  else
763  goto done;
764  }
765 
766  for (octave_idx_type j = jold; j < nc; j++)
767  a.cidx (j+1) = ii;
768  }
769 
770 done:
771 
772  return is;
773 }
774 
775 #endif