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.cc
Go to the documentation of this file.
1 // Template sparse array class
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 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #include <cassert>
31 
32 #include <algorithm>
33 #include <iostream>
34 #include <limits>
35 #include <sstream>
36 #include <vector>
37 
38 #include "Array.h"
39 #include "MArray.h"
40 #include "Array-util.h"
41 #include "Range.h"
42 #include "idx-vector.h"
43 #include "lo-error.h"
44 #include "quit.h"
45 #include "oct-locbuf.h"
46 
47 #include "Sparse.h"
48 #include "sparse-sort.h"
49 #include "sparse-util.h"
50 #include "oct-spparms.h"
51 #include "mx-inlines.cc"
52 
53 #include "PermMatrix.h"
54 
55 template <class T>
57  : rep (new typename Sparse<T>::SparseRep (a.rows (), a.cols (), a.rows ())),
58  dimensions (dim_vector (a.rows (), a.cols ()))
59 {
60  octave_idx_type n = a.rows ();
61  for (octave_idx_type i = 0; i <= n; i++)
62  cidx (i) = i;
63 
64  const Array<octave_idx_type> pv = a.pvec ();
65 
66  if (a.is_row_perm ())
67  {
68  for (octave_idx_type i = 0; i < n; i++)
69  ridx (pv(i)) = i;
70  }
71  else
72  {
73  for (octave_idx_type i = 0; i < n; i++)
74  ridx (i) = pv(i);
75  }
76 
77  for (octave_idx_type i = 0; i < n; i++)
78  data (i) = 1.0;
79 }
80 
81 template <class T>
82 T&
84 {
86 
87  if (nzmx > 0)
88  {
89  for (i = c[_c]; i < c[_c + 1]; i++)
90  if (r[i] == _r)
91  return d[i];
92  else if (r[i] > _r)
93  break;
94 
95  // Ok, If we've gotten here, we're in trouble.. Have to create a
96  // new element in the sparse array. This' gonna be slow!!!
97  if (c[ncols] == nzmx)
98  {
99  (*current_liboctave_error_handler)
100  ("Sparse::SparseRep::elem (octave_idx_type, octave_idx_type): sparse matrix filled");
101  return *d;
102  }
103 
104  octave_idx_type to_move = c[ncols] - i;
105  if (to_move != 0)
106  {
107  for (octave_idx_type j = c[ncols]; j > i; j--)
108  {
109  d[j] = d[j-1];
110  r[j] = r[j-1];
111  }
112  }
113 
114  for (octave_idx_type j = _c + 1; j < ncols + 1; j++)
115  c[j] = c[j] + 1;
116 
117  d[i] = 0.;
118  r[i] = _r;
119 
120  return d[i];
121  }
122  else
123  {
124  (*current_liboctave_error_handler)
125  ("Sparse::SparseRep::elem (octave_idx_type, octave_idx_type): sparse matrix filled");
126  return *d;
127  }
128 }
129 
130 template <class T>
131 T
133 {
134  if (nzmx > 0)
135  for (octave_idx_type i = c[_c]; i < c[_c + 1]; i++)
136  if (r[i] == _r)
137  return d[i];
138  return T ();
139 }
140 
141 template <class T>
142 void
144 {
145  if (remove_zeros)
146  {
147  octave_idx_type i = 0, k = 0;
148  for (octave_idx_type j = 1; j <= ncols; j++)
149  {
150  octave_idx_type u = c[j];
151  for (i = i; i < u; i++)
152  if (d[i] != T ())
153  {
154  d[k] = d[i];
155  r[k++] = r[i];
156  }
157  c[j] = k;
158  }
159  }
160 
161  change_length (c[ncols]);
162 }
163 
164 template <class T>
165 void
167 {
168  for (octave_idx_type j = ncols; j > 0 && c[j] > nz; j--)
169  c[j] = nz;
170 
171  // We shall skip reallocation if we have less than 1/frac extra elements to
172  // discard.
173  static const int frac = 5;
174  if (nz > nzmx || nz < nzmx - nzmx/frac)
175  {
176  // Reallocate.
177  octave_idx_type min_nzmx = std::min (nz, nzmx);
178 
179  octave_idx_type * new_ridx = new octave_idx_type [nz];
180  copy_or_memcpy (min_nzmx, r, new_ridx);
181 
182  delete [] r;
183  r = new_ridx;
184 
185  T * new_data = new T [nz];
186  copy_or_memcpy (min_nzmx, d, new_data);
187 
188  delete [] d;
189  d = new_data;
190 
191  nzmx = nz;
192  }
193 }
194 
195 template <class T>
196 bool
198 {
199  return sparse_indices_ok (r, c, nrows, ncols, nnz ());
200 }
201 
202 template <class T>
204  : rep (0), dimensions (dim_vector (nr, nc))
205 {
206  if (val != T ())
207  {
208  rep = new typename Sparse<T>::SparseRep (nr, nc, dimensions.safe_numel ());
209 
210  octave_idx_type ii = 0;
211  xcidx (0) = 0;
212  for (octave_idx_type j = 0; j < nc; j++)
213  {
214  for (octave_idx_type i = 0; i < nr; i++)
215  {
216  xdata (ii) = val;
217  xridx (ii++) = i;
218  }
219  xcidx (j+1) = ii;
220  }
221  }
222  else
223  {
224  rep = new typename Sparse<T>::SparseRep (nr, nc, 0);
225  for (octave_idx_type j = 0; j < nc+1; j++)
226  xcidx (j) = 0;
227  }
228 }
229 
230 template <class T>
232  : rep (0), dimensions (dv)
233 {
234  if (dv.length () != 2)
236  ("Sparse::Sparse (const dim_vector&): dimension mismatch");
237  else
238  rep = new typename Sparse<T>::SparseRep (dv(0), dv(1), 0);
239 }
240 
241 template <class T>
243  : rep (0), dimensions (dv)
244 {
245 
246  // Work in unsigned long long to avoid overflow issues with numel
247  unsigned long long a_nel = static_cast<unsigned long long>(a.rows ()) *
248  static_cast<unsigned long long>(a.cols ());
249  unsigned long long dv_nel = static_cast<unsigned long long>(dv (0)) *
250  static_cast<unsigned long long>(dv (1));
251 
252  if (a_nel != dv_nel)
253  (*current_liboctave_error_handler)
254  ("Sparse::Sparse (const Sparse&, const dim_vector&): dimension mismatch");
255  else
256  {
257  dim_vector old_dims = a.dims ();
258  octave_idx_type new_nzmx = a.nnz ();
259  octave_idx_type new_nr = dv (0);
260  octave_idx_type new_nc = dv (1);
261  octave_idx_type old_nr = old_dims (0);
262  octave_idx_type old_nc = old_dims (1);
263 
264  rep = new typename Sparse<T>::SparseRep (new_nr, new_nc, new_nzmx);
265 
266  octave_idx_type kk = 0;
267  xcidx (0) = 0;
268  for (octave_idx_type i = 0; i < old_nc; i++)
269  for (octave_idx_type j = a.cidx (i); j < a.cidx (i+1); j++)
270  {
271  octave_idx_type tmp = i * old_nr + a.ridx (j);
272  octave_idx_type ii = tmp % new_nr;
273  octave_idx_type jj = (tmp - ii) / new_nr;
274  for (octave_idx_type k = kk; k < jj; k++)
275  xcidx (k+1) = j;
276  kk = jj;
277  xdata (j) = a.data (j);
278  xridx (j) = ii;
279  }
280  for (octave_idx_type k = kk; k < new_nc; k++)
281  xcidx (k+1) = new_nzmx;
282  }
283 }
284 
285 template <class T>
287  const idx_vector& c, octave_idx_type nr,
288  octave_idx_type nc, bool sum_terms,
289  octave_idx_type nzm)
290  : rep (0), dimensions ()
291 {
292  if (nr < 0)
293  nr = r.extent (0);
294  else if (r.extent (nr) > nr)
295  (*current_liboctave_error_handler) ("sparse: row index %d out of bound %d",
296  r.extent (nr), nr);
297 
298  if (nc < 0)
299  nc = c.extent (0);
300  else if (c.extent (nc) > nc)
302  ("sparse: column index %d out of bound %d", r.extent (nc), nc);
303 
304  dimensions = dim_vector (nr, nc);
305 
306  octave_idx_type n = a.numel (), rl = r.length (nr), cl = c.length (nc);
307  bool a_scalar = n == 1;
308  if (a_scalar)
309  {
310  if (rl != 1)
311  n = rl;
312  else if (cl != 1)
313  n = cl;
314  }
315 
316  if ((rl != 1 && rl != n) || (cl != 1 && cl != n))
317  (*current_liboctave_error_handler) ("sparse: dimension mismatch");
318 
319  // Only create rep after input validation to avoid memory leak.
320  rep = new typename Sparse<T>::SparseRep (nr, nc, (nzm > 0 ? nzm : 0));
321 
322  if (rl <= 1 && cl <= 1)
323  {
324  if (n == 1 && a(0) != T ())
325  {
326  change_capacity (nzm > 1 ? nzm : 1);
327  xcidx(0) = 0;
328  xridx(0) = r(0);
329  xdata(0) = a(0);
330 
331  for (octave_idx_type j = 0; j < nc; j++)
332  xcidx (j+1) = j >= c(0);
333  }
334  }
335  else if (a_scalar)
336  {
337  // This is completely specialized, because the sorts can be simplified.
338  T a0 = a(0);
339  if (a0 == T ())
340  {
341  // Do nothing, it's an empty matrix.
342  }
343  else if (cl == 1)
344  {
345  // Sparse column vector. Sort row indices.
346  idx_vector rs = r.sorted ();
347 
348  octave_quit ();
349 
350  const octave_idx_type *rd = rs.raw ();
351  // Count unique indices.
352  octave_idx_type new_nz = 1;
353  for (octave_idx_type i = 1; i < n; i++)
354  new_nz += rd[i-1] != rd[i];
355  // Allocate result.
356  change_capacity (nzm > new_nz ? nzm : new_nz);
357  xcidx (0) = 0;
358  xcidx (1) = new_nz;
359  octave_idx_type *rri = ridx ();
360  T *rrd = data ();
361 
362  octave_quit ();
363 
364  octave_idx_type k = -1, l = -1;
365 
366  if (sum_terms)
367  {
368  // Sum repeated indices.
369  for (octave_idx_type i = 0; i < n; i++)
370  {
371  if (rd[i] != l)
372  {
373  l = rd[i];
374  rri[++k] = rd[i];
375  rrd[k] = a0;
376  }
377  else
378  rrd[k] += a0;
379  }
380  }
381  else
382  {
383  // Pick the last one.
384  for (octave_idx_type i = 0; i < n; i++)
385  {
386  if (rd[i] != l)
387  {
388  l = rd[i];
389  rri[++k] = rd[i];
390  rrd[k] = a0;
391  }
392  }
393  }
394 
395  }
396  else
397  {
398  idx_vector rr = r, cc = c;
399  const octave_idx_type *rd = rr.raw (), *cd = cc.raw ();
401  ci[0] = 0;
402  // Bin counts of column indices.
403  for (octave_idx_type i = 0; i < n; i++)
404  ci[cd[i]+1]++;
405  // Make them cumulative, shifted one to right.
406  for (octave_idx_type i = 1, s = 0; i <= nc; i++)
407  {
408  octave_idx_type s1 = s + ci[i];
409  ci[i] = s;
410  s = s1;
411  }
412 
413  octave_quit ();
414 
415  // Bucket sort.
417  for (octave_idx_type i = 0; i < n; i++)
418  if (rl == 1)
419  sidx[ci[cd[i]+1]++] = rd[0];
420  else
421  sidx[ci[cd[i]+1]++] = rd[i];
422 
423  // Subsorts. We don't need a stable sort, all values are equal.
424  xcidx (0) = 0;
425  for (octave_idx_type j = 0; j < nc; j++)
426  {
427  std::sort (sidx + ci[j], sidx + ci[j+1]);
428  octave_idx_type l = -1, nzj = 0;
429  // Count.
430  for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)
431  {
432  octave_idx_type k = sidx[i];
433  if (k != l)
434  {
435  l = k;
436  nzj++;
437  }
438  }
439  // Set column pointer.
440  xcidx (j+1) = xcidx (j) + nzj;
441  }
442 
443  change_capacity (nzm > xcidx (nc) ? nzm : xcidx (nc));
444  octave_idx_type *rri = ridx ();
445  T *rrd = data ();
446 
447  // Fill-in data.
448  for (octave_idx_type j = 0, jj = -1; j < nc; j++)
449  {
450  octave_quit ();
451  octave_idx_type l = -1;
452  if (sum_terms)
453  {
454  // Sum adjacent terms.
455  for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)
456  {
457  octave_idx_type k = sidx[i];
458  if (k != l)
459  {
460  l = k;
461  rrd[++jj] = a0;
462  rri[jj] = k;
463  }
464  else
465  rrd[jj] += a0;
466  }
467  }
468  else
469  {
470  // Use the last one.
471  for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)
472  {
473  octave_idx_type k = sidx[i];
474  if (k != l)
475  {
476  l = k;
477  rrd[++jj] = a0;
478  rri[jj] = k;
479  }
480  }
481  }
482  }
483  }
484  }
485  else if (cl == 1)
486  {
487  // Sparse column vector. Sort row indices.
489  idx_vector rs = r.sorted (rsi);
490 
491  octave_quit ();
492 
493  const octave_idx_type *rd = rs.raw (), *rdi = rsi.data ();
494  // Count unique indices.
495  octave_idx_type new_nz = 1;
496  for (octave_idx_type i = 1; i < n; i++)
497  new_nz += rd[i-1] != rd[i];
498  // Allocate result.
499  change_capacity (nzm > new_nz ? nzm : new_nz);
500  xcidx(0) = 0;
501  xcidx(1) = new_nz;
502  octave_idx_type *rri = ridx ();
503  T *rrd = data ();
504 
505  octave_quit ();
506 
507  octave_idx_type k = 0;
508  rri[k] = rd[0];
509  rrd[k] = a(rdi[0]);
510 
511  if (sum_terms)
512  {
513  // Sum repeated indices.
514  for (octave_idx_type i = 1; i < n; i++)
515  {
516  if (rd[i] != rd[i-1])
517  {
518  rri[++k] = rd[i];
519  rrd[k] = a(rdi[i]);
520  }
521  else
522  rrd[k] += a(rdi[i]);
523  }
524  }
525  else
526  {
527  // Pick the last one.
528  for (octave_idx_type i = 1; i < n; i++)
529  {
530  if (rd[i] != rd[i-1])
531  rri[++k] = rd[i];
532  rrd[k] = a(rdi[i]);
533  }
534  }
535 
536  maybe_compress (true);
537  }
538  else
539  {
540  idx_vector rr = r, cc = c;
541  const octave_idx_type *rd = rr.raw (), *cd = cc.raw ();
543  ci[0] = 0;
544  // Bin counts of column indices.
545  for (octave_idx_type i = 0; i < n; i++)
546  ci[cd[i]+1]++;
547  // Make them cumulative, shifted one to right.
548  for (octave_idx_type i = 1, s = 0; i <= nc; i++)
549  {
550  octave_idx_type s1 = s + ci[i];
551  ci[i] = s;
552  s = s1;
553  }
554 
555  octave_quit ();
556 
557  typedef std::pair<octave_idx_type, octave_idx_type> idx_pair;
558  // Bucket sort.
559  OCTAVE_LOCAL_BUFFER (idx_pair, spairs, n);
560  for (octave_idx_type i = 0; i < n; i++)
561  {
562  idx_pair& p = spairs[ci[cd[i]+1]++];
563  if (rl == 1)
564  p.first = rd[0];
565  else
566  p.first = rd[i];
567  p.second = i;
568  }
569 
570  // Subsorts. We don't need a stable sort, the second index stabilizes it.
571  xcidx (0) = 0;
572  for (octave_idx_type j = 0; j < nc; j++)
573  {
574  std::sort (spairs + ci[j], spairs + ci[j+1]);
575  octave_idx_type l = -1, nzj = 0;
576  // Count.
577  for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)
578  {
579  octave_idx_type k = spairs[i].first;
580  if (k != l)
581  {
582  l = k;
583  nzj++;
584  }
585  }
586  // Set column pointer.
587  xcidx (j+1) = xcidx (j) + nzj;
588  }
589 
590  change_capacity (nzm > xcidx (nc) ? nzm : xcidx (nc));
591  octave_idx_type *rri = ridx ();
592  T *rrd = data ();
593 
594  // Fill-in data.
595  for (octave_idx_type j = 0, jj = -1; j < nc; j++)
596  {
597  octave_quit ();
598  octave_idx_type l = -1;
599  if (sum_terms)
600  {
601  // Sum adjacent terms.
602  for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)
603  {
604  octave_idx_type k = spairs[i].first;
605  if (k != l)
606  {
607  l = k;
608  rrd[++jj] = a(spairs[i].second);
609  rri[jj] = k;
610  }
611  else
612  rrd[jj] += a(spairs[i].second);
613  }
614  }
615  else
616  {
617  // Use the last one.
618  for (octave_idx_type i = ci[j]; i < ci[j+1]; i++)
619  {
620  octave_idx_type k = spairs[i].first;
621  if (k != l)
622  {
623  l = k;
624  rri[++jj] = k;
625  }
626  rrd[jj] = a(spairs[i].second);
627  }
628  }
629  }
630 
631  maybe_compress (true);
632  }
633 }
634 
635 template <class T>
637  : rep (0), dimensions (a.dims ())
638 {
639  if (dimensions.length () > 2)
641  ("Sparse::Sparse (const Array<T>&): dimension mismatch");
642  else
643  {
644  octave_idx_type nr = rows ();
645  octave_idx_type nc = cols ();
646  octave_idx_type len = a.length ();
647  octave_idx_type new_nzmx = 0;
648 
649  // First count the number of non-zero terms
650  for (octave_idx_type i = 0; i < len; i++)
651  if (a(i) != T ())
652  new_nzmx++;
653 
654  rep = new typename Sparse<T>::SparseRep (nr, nc, new_nzmx);
655 
656  octave_idx_type ii = 0;
657  xcidx (0) = 0;
658  for (octave_idx_type j = 0; j < nc; j++)
659  {
660  for (octave_idx_type i = 0; i < nr; i++)
661  if (a.elem (i,j) != T ())
662  {
663  xdata (ii) = a.elem (i,j);
664  xridx (ii++) = i;
665  }
666  xcidx (j+1) = ii;
667  }
668  }
669 }
670 
671 template <class T>
673 {
674  if (--rep->count == 0)
675  delete rep;
676 }
677 
678 template <class T>
679 Sparse<T>&
681 {
682  if (this != &a)
683  {
684  if (--rep->count == 0)
685  delete rep;
686 
687  rep = a.rep;
688  rep->count++;
689 
690  dimensions = a.dimensions;
691  }
692 
693  return *this;
694 }
695 
696 template <class T>
699 {
700  octave_idx_type retval = -1;
701 
702  octave_idx_type n = dimensions.length ();
703 
704  if (n > 0 && n == ra_idx.length ())
705  {
706  retval = ra_idx(--n);
707 
708  while (--n >= 0)
709  {
710  retval *= dimensions(n);
711  retval += ra_idx(n);
712  }
713  }
714  else
716  ("Sparse<T>::compute_index: invalid ra_idxing operation");
717 
718  return retval;
719 }
720 
721 template <class T>
722 T
723 Sparse<T>::range_error (const char *fcn, octave_idx_type n) const
724 {
725  (*current_liboctave_error_handler) ("%s (%d): range error", fcn, n);
726  return T ();
727 }
728 
729 template <class T>
730 T&
732 {
733  (*current_liboctave_error_handler) ("%s (%d): range error", fcn, n);
734  static T foo;
735  return foo;
736 }
737 
738 template <class T>
739 T
741  octave_idx_type j) const
742 {
743  (*current_liboctave_error_handler)
744  ("%s (%d, %d): range error", fcn, i, j);
745  return T ();
746 }
747 
748 template <class T>
749 T&
751 {
752  (*current_liboctave_error_handler)
753  ("%s (%d, %d): range error", fcn, i, j);
754  static T foo;
755  return foo;
756 }
757 
758 template <class T>
759 T
760 Sparse<T>::range_error (const char *fcn,
761  const Array<octave_idx_type>& ra_idx) const
762 {
763  std::ostringstream buf;
764 
765  buf << fcn << " (";
766 
767  octave_idx_type n = ra_idx.length ();
768 
769  if (n > 0)
770  buf << ra_idx(0);
771 
772  for (octave_idx_type i = 1; i < n; i++)
773  buf << ", " << ra_idx(i);
774 
775  buf << "): range error";
776 
777  std::string buf_str = buf.str ();
778 
779  (*current_liboctave_error_handler) (buf_str.c_str ());
780 
781  return T ();
782 }
783 
784 template <class T>
785 T&
786 Sparse<T>::range_error (const char *fcn, const Array<octave_idx_type>& ra_idx)
787 {
788  std::ostringstream buf;
789 
790  buf << fcn << " (";
791 
792  octave_idx_type n = ra_idx.length ();
793 
794  if (n > 0)
795  buf << ra_idx(0);
796 
797  for (octave_idx_type i = 1; i < n; i++)
798  buf << ", " << ra_idx(i);
799 
800  buf << "): range error";
801 
802  std::string buf_str = buf.str ();
803 
804  (*current_liboctave_error_handler) (buf_str.c_str ());
805 
806  static T foo;
807  return foo;
808 }
809 
810 template <class T>
811 Sparse<T>
812 Sparse<T>::reshape (const dim_vector& new_dims) const
813 {
814  Sparse<T> retval;
815  dim_vector dims2 = new_dims;
816 
817  if (dims2.length () > 2)
818  {
819  (*current_liboctave_warning_handler)
820  ("reshape: sparse reshape to N-d array smashes dims");
821 
822  for (octave_idx_type i = 2; i < dims2.length (); i++)
823  dims2(1) *= dims2(i);
824 
825  dims2.resize (2);
826  }
827 
828  if (dimensions != dims2)
829  {
830  if (dimensions.numel () == dims2.numel ())
831  {
832  octave_idx_type new_nnz = nnz ();
833  octave_idx_type new_nr = dims2 (0);
834  octave_idx_type new_nc = dims2 (1);
835  octave_idx_type old_nr = rows ();
836  octave_idx_type old_nc = cols ();
837  retval = Sparse<T> (new_nr, new_nc, new_nnz);
838 
839  octave_idx_type kk = 0;
840  retval.xcidx (0) = 0;
841  for (octave_idx_type i = 0; i < old_nc; i++)
842  for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)
843  {
844  octave_idx_type tmp = i * old_nr + ridx (j);
845  octave_idx_type ii = tmp % new_nr;
846  octave_idx_type jj = (tmp - ii) / new_nr;
847  for (octave_idx_type k = kk; k < jj; k++)
848  retval.xcidx (k+1) = j;
849  kk = jj;
850  retval.xdata (j) = data (j);
851  retval.xridx (j) = ii;
852  }
853  for (octave_idx_type k = kk; k < new_nc; k++)
854  retval.xcidx (k+1) = new_nnz;
855  }
856  else
857  {
858  std::string dimensions_str = dimensions.str ();
859  std::string new_dims_str = new_dims.str ();
860 
861  (*current_liboctave_error_handler)
862  ("reshape: can't reshape %s array to %s array",
863  dimensions_str.c_str (), new_dims_str.c_str ());
864  }
865  }
866  else
867  retval = *this;
868 
869  return retval;
870 }
871 
872 template <class T>
873 Sparse<T>
874 Sparse<T>::permute (const Array<octave_idx_type>& perm_vec, bool) const
875 {
876  // The only valid permutations of a sparse array are [1, 2] and [2, 1].
877 
878  bool fail = false;
879  bool trans = false;
880 
881  if (perm_vec.length () == 2)
882  {
883  if (perm_vec(0) == 0 && perm_vec(1) == 1)
884  /* do nothing */;
885  else if (perm_vec(0) == 1 && perm_vec(1) == 0)
886  trans = true;
887  else
888  fail = true;
889  }
890  else
891  fail = true;
892 
893  if (fail)
894  (*current_liboctave_error_handler)
895  ("permutation vector contains an invalid element");
896 
897  return trans ? this->transpose () : *this;
898 }
899 
900 template <class T>
901 void
903 {
904  octave_idx_type nr = rows (), nc = cols ();
905 
906  if (nr == 0)
907  resize (1, std::max (nc, n));
908  else if (nc == 0)
909  resize (nr, (n + nr - 1) / nr); // Ain't it wicked?
910  else if (nr == 1)
911  resize (1, n);
912  else if (nc == 1)
913  resize (n, 1);
914  else
916 }
917 
918 template <class T>
919 void
921 {
922  octave_idx_type n = dv.length ();
923 
924  if (n != 2)
925  {
926  (*current_liboctave_error_handler) ("sparse array must be 2-D");
927  return;
928  }
929 
930  resize (dv(0), dv(1));
931 }
932 
933 template <class T>
934 void
936 {
937  if (r < 0 || c < 0)
938  {
939  (*current_liboctave_error_handler)
940  ("can't resize to negative dimension");
941  return;
942  }
943 
944  if (r == dim1 () && c == dim2 ())
945  return;
946 
947  // This wouldn't be necessary for r >= rows () if nrows wasn't part of the
948  // Sparse rep. It is not good for anything in there.
949  make_unique ();
950 
951  if (r < rows ())
952  {
953  octave_idx_type i = 0, k = 0;
954  for (octave_idx_type j = 1; j <= rep->ncols; j++)
955  {
956  octave_idx_type u = xcidx (j);
957  for (i = i; i < u; i++)
958  if (xridx (i) < r)
959  {
960  xdata (k) = xdata (i);
961  xridx (k++) = xridx (i);
962  }
963  xcidx (j) = k;
964  }
965  }
966 
967  rep->nrows = dimensions(0) = r;
968 
969  if (c != rep->ncols)
970  {
971  octave_idx_type *new_cidx = new octave_idx_type [c+1];
972  copy_or_memcpy (std::min (c, rep->ncols)+1, rep->c, new_cidx);
973  delete [] rep->c;
974  rep->c = new_cidx;
975 
976  if (c > rep->ncols)
977  fill_or_memset (c - rep->ncols, rep->c[rep->ncols],
978  rep->c + rep->ncols + 1);
979  }
980 
981  rep->ncols = dimensions(1) = c;
982 
983  rep->change_length (rep->nnz ());
984 }
985 
986 template <class T>
987 Sparse<T>&
989 {
990  octave_idx_type a_rows = a.rows ();
991  octave_idx_type a_cols = a.cols ();
992  octave_idx_type nr = rows ();
993  octave_idx_type nc = cols ();
994 
995  if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ())
996  {
997  (*current_liboctave_error_handler) ("range error for insert");
998  return *this;
999  }
1000 
1001  // First count the number of elements in the final array
1002  octave_idx_type nel = cidx (c) + a.nnz ();
1003 
1004  if (c + a_cols < nc)
1005  nel += cidx (nc) - cidx (c + a_cols);
1006 
1007  for (octave_idx_type i = c; i < c + a_cols; i++)
1008  for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)
1009  if (ridx (j) < r || ridx (j) >= r + a_rows)
1010  nel++;
1011 
1012  Sparse<T> tmp (*this);
1013  --rep->count;
1014  rep = new typename Sparse<T>::SparseRep (nr, nc, nel);
1015 
1016  for (octave_idx_type i = 0; i < tmp.cidx (c); i++)
1017  {
1018  data (i) = tmp.data (i);
1019  ridx (i) = tmp.ridx (i);
1020  }
1021  for (octave_idx_type i = 0; i < c + 1; i++)
1022  cidx (i) = tmp.cidx (i);
1023 
1024  octave_idx_type ii = cidx (c);
1025 
1026  for (octave_idx_type i = c; i < c + a_cols; i++)
1027  {
1028  octave_quit ();
1029 
1030  for (octave_idx_type j = tmp.cidx (i); j < tmp.cidx (i+1); j++)
1031  if (tmp.ridx (j) < r)
1032  {
1033  data (ii) = tmp.data (j);
1034  ridx (ii++) = tmp.ridx (j);
1035  }
1036 
1037  octave_quit ();
1038 
1039  for (octave_idx_type j = a.cidx (i-c); j < a.cidx (i-c+1); j++)
1040  {
1041  data (ii) = a.data (j);
1042  ridx (ii++) = r + a.ridx (j);
1043  }
1044 
1045  octave_quit ();
1046 
1047  for (octave_idx_type j = tmp.cidx (i); j < tmp.cidx (i+1); j++)
1048  if (tmp.ridx (j) >= r + a_rows)
1049  {
1050  data (ii) = tmp.data (j);
1051  ridx (ii++) = tmp.ridx (j);
1052  }
1053 
1054  cidx (i+1) = ii;
1055  }
1056 
1057  for (octave_idx_type i = c + a_cols; i < nc; i++)
1058  {
1059  for (octave_idx_type j = tmp.cidx (i); j < tmp.cidx (i+1); j++)
1060  {
1061  data (ii) = tmp.data (j);
1062  ridx (ii++) = tmp.ridx (j);
1063  }
1064  cidx (i+1) = ii;
1065  }
1066 
1067  return *this;
1068 }
1069 
1070 template <class T>
1071 Sparse<T>&
1073 {
1074 
1075  if (ra_idx.length () != 2)
1076  {
1077  (*current_liboctave_error_handler) ("range error for insert");
1078  return *this;
1079  }
1080 
1081  return insert (a, ra_idx (0), ra_idx (1));
1082 }
1083 
1084 template <class T>
1085 Sparse<T>
1087 {
1088  assert (ndims () == 2);
1089 
1090  octave_idx_type nr = rows ();
1091  octave_idx_type nc = cols ();
1092  octave_idx_type nz = nnz ();
1093  Sparse<T> retval (nc, nr, nz);
1094 
1095  for (octave_idx_type i = 0; i < nz; i++)
1096  retval.xcidx (ridx (i) + 1)++;
1097  // retval.xcidx[1:nr] holds the row degrees for rows 0:(nr-1)
1098  nz = 0;
1099  for (octave_idx_type i = 1; i <= nr; i++)
1100  {
1101  const octave_idx_type tmp = retval.xcidx (i);
1102  retval.xcidx (i) = nz;
1103  nz += tmp;
1104  }
1105  // retval.xcidx[1:nr] holds row entry *start* offsets for rows 0:(nr-1)
1106 
1107  for (octave_idx_type j = 0; j < nc; j++)
1108  for (octave_idx_type k = cidx (j); k < cidx (j+1); k++)
1109  {
1110  octave_idx_type q = retval.xcidx (ridx (k) + 1)++;
1111  retval.xridx (q) = j;
1112  retval.xdata (q) = data (k);
1113  }
1114  assert (nnz () == retval.xcidx (nr));
1115  // retval.xcidx[1:nr] holds row entry *end* offsets for rows 0:(nr-1)
1116  // and retval.xcidx[0:(nr-1)] holds their row entry *start* offsets
1117 
1118  return retval;
1119 }
1120 
1121 // Lower bound lookup. Could also use octave_sort, but that has upper bound
1122 // semantics, so requires some manipulation to set right. Uses a plain loop for
1123 // small columns.
1124 static octave_idx_type
1126  octave_idx_type ri)
1127 {
1128  if (nr <= 8)
1129  {
1130  octave_idx_type l;
1131  for (l = 0; l < nr; l++)
1132  if (ridx[l] >= ri)
1133  break;
1134  return l;
1135  }
1136  else
1137  return std::lower_bound (ridx, ridx + nr, ri) - ridx;
1138 }
1139 
1140 template <class T>
1141 void
1143 {
1144  Sparse<T> retval;
1145 
1146  assert (ndims () == 2);
1147 
1148  octave_idx_type nr = dim1 ();
1149  octave_idx_type nc = dim2 ();
1150  octave_idx_type nz = nnz ();
1151 
1152  octave_idx_type nel = numel (); // Can throw.
1153 
1154  const dim_vector idx_dims = idx.orig_dimensions ();
1155 
1156  if (idx.extent (nel) > nel)
1157  gripe_del_index_out_of_range (true, idx.extent (nel), nel);
1158  else if (nc == 1)
1159  {
1160  // Sparse column vector.
1161  const Sparse<T> tmp = *this; // constant copy to prevent COW.
1162 
1163  octave_idx_type lb, ub;
1164 
1165  if (idx.is_cont_range (nel, lb, ub))
1166  {
1167  // Special-case a contiguous range.
1168  // Look-up indices first.
1169  octave_idx_type li = lblookup (tmp.ridx (), nz, lb);
1170  octave_idx_type ui = lblookup (tmp.ridx (), nz, ub);
1171  // Copy data and adjust indices.
1172  octave_idx_type nz_new = nz - (ui - li);
1173  *this = Sparse<T> (nr - (ub - lb), 1, nz_new);
1174  copy_or_memcpy (li, tmp.data (), data ());
1175  copy_or_memcpy (li, tmp.ridx (), xridx ());
1176  copy_or_memcpy (nz - ui, tmp.data () + ui, xdata () + li);
1177  mx_inline_sub (nz - ui, xridx () + li, tmp.ridx () + ui, ub - lb);
1178  xcidx (1) = nz_new;
1179  }
1180  else
1181  {
1182  OCTAVE_LOCAL_BUFFER (octave_idx_type, ridx_new, nz);
1183  OCTAVE_LOCAL_BUFFER (T, data_new, nz);
1184  idx_vector sidx = idx.sorted (true);
1185  const octave_idx_type *sj = sidx.raw ();
1186  octave_idx_type sl = sidx.length (nel), nz_new = 0, j = 0;
1187  for (octave_idx_type i = 0; i < nz; i++)
1188  {
1189  octave_idx_type r = tmp.ridx (i);
1190  for (; j < sl && sj[j] < r; j++) ;
1191  if (j == sl || sj[j] > r)
1192  {
1193  data_new[nz_new] = tmp.data (i);
1194  ridx_new[nz_new++] = r - j;
1195  }
1196  }
1197 
1198  *this = Sparse<T> (nr - sl, 1, nz_new);
1199  copy_or_memcpy (nz_new, ridx_new, ridx ());
1200  copy_or_memcpy (nz_new, data_new, xdata ());
1201  xcidx (1) = nz_new;
1202  }
1203  }
1204  else if (nr == 1)
1205  {
1206  // Sparse row vector.
1207  octave_idx_type lb, ub;
1208  if (idx.is_cont_range (nc, lb, ub))
1209  {
1210  const Sparse<T> tmp = *this;
1211  octave_idx_type lbi = tmp.cidx (lb);
1212  octave_idx_type ubi = tmp.cidx (ub);
1213  octave_idx_type new_nz = nz - (ubi - lbi);
1214  *this = Sparse<T> (1, nc - (ub - lb), new_nz);
1215  copy_or_memcpy (lbi, tmp.data (), data ());
1216  copy_or_memcpy (nz - ubi, tmp.data () + ubi, xdata () + lbi);
1217  fill_or_memset (new_nz, static_cast<octave_idx_type> (0), ridx ());
1218  copy_or_memcpy (lb, tmp.cidx () + 1, cidx () + 1);
1219  mx_inline_sub (nc - ub, xcidx () + 1, tmp.cidx () + ub + 1,
1220  ubi - lbi);
1221  }
1222  else
1223  *this = index (idx.complement (nc));
1224  }
1225  else if (idx.length (nel) != 0)
1226  {
1227  if (idx.is_colon_equiv (nel))
1228  *this = Sparse<T> ();
1229  else
1230  {
1231  *this = index (idx_vector::colon);
1232  delete_elements (idx);
1233  *this = transpose (); // We want a row vector.
1234  }
1235  }
1236 }
1237 
1238 template <class T>
1239 void
1241 {
1242  assert (ndims () == 2);
1243 
1244  octave_idx_type nr = dim1 ();
1245  octave_idx_type nc = dim2 ();
1246  octave_idx_type nz = nnz ();
1247 
1248  if (idx_i.is_colon ())
1249  {
1250  // Deleting columns.
1251  octave_idx_type lb, ub;
1252  if (idx_j.extent (nc) > nc)
1253  gripe_del_index_out_of_range (false, idx_j.extent (nc), nc);
1254  else if (idx_j.is_cont_range (nc, lb, ub))
1255  {
1256  if (lb == 0 && ub == nc)
1257  {
1258  // Delete all rows and columns.
1259  *this = Sparse<T> (nr, 0);
1260  }
1261  else if (nz == 0)
1262  {
1263  // No elements to preserve; adjust dimensions.
1264  *this = Sparse<T> (nr, nc - (ub - lb));
1265  }
1266  else
1267  {
1268  const Sparse<T> tmp = *this;
1269  octave_idx_type lbi = tmp.cidx(lb);
1270  octave_idx_type ubi = tmp.cidx(ub);
1271  octave_idx_type new_nz = nz - (ubi - lbi);
1272 
1273  *this = Sparse<T> (nr, nc - (ub - lb), new_nz);
1274  copy_or_memcpy (lbi, tmp.data (), data ());
1275  copy_or_memcpy (lbi, tmp.ridx (), ridx ());
1276  copy_or_memcpy (nz - ubi, tmp.data () + ubi, xdata () + lbi);
1277  copy_or_memcpy (nz - ubi, tmp.ridx () + ubi, xridx () + lbi);
1278  copy_or_memcpy (lb, tmp.cidx () + 1, cidx () + 1);
1279  mx_inline_sub (nc - ub, xcidx () + lb + 1,
1280  tmp.cidx () + ub + 1, ubi - lbi);
1281  }
1282  }
1283  else
1284  *this = index (idx_i, idx_j.complement (nc));
1285  }
1286  else if (idx_j.is_colon ())
1287  {
1288  // Deleting rows.
1289  octave_idx_type lb, ub;
1290  if (idx_i.extent (nr) > nr)
1291  gripe_del_index_out_of_range (false, idx_i.extent (nr), nr);
1292  else if (idx_i.is_cont_range (nr, lb, ub))
1293  {
1294  if (lb == 0 && ub == nr)
1295  {
1296  // Delete all rows and columns.
1297  *this = Sparse<T> (0, nc);
1298  }
1299  else if (nz == 0)
1300  {
1301  // No elements to preserve; adjust dimensions.
1302  *this = Sparse<T> (nr - (ub - lb), nc);
1303  }
1304  else
1305  {
1306  // This is more memory-efficient than the approach below.
1307  const Sparse<T> tmpl = index (idx_vector (0, lb), idx_j);
1308  const Sparse<T> tmpu = index (idx_vector (ub, nr), idx_j);
1309  *this = Sparse<T> (nr - (ub - lb), nc,
1310  tmpl.nnz () + tmpu.nnz ());
1311  for (octave_idx_type j = 0, k = 0; j < nc; j++)
1312  {
1313  for (octave_idx_type i = tmpl.cidx(j); i < tmpl.cidx(j+1);
1314  i++)
1315  {
1316  xdata(k) = tmpl.data(i);
1317  xridx(k++) = tmpl.ridx(i);
1318  }
1319  for (octave_idx_type i = tmpu.cidx(j); i < tmpu.cidx(j+1);
1320  i++)
1321  {
1322  xdata(k) = tmpu.data(i);
1323  xridx(k++) = tmpu.ridx(i) + lb;
1324  }
1325 
1326  xcidx(j+1) = k;
1327  }
1328  }
1329  }
1330  else
1331  {
1332  // This is done by transposing, deleting columns, then transposing
1333  // again.
1334  Sparse<T> tmp = transpose ();
1335  tmp.delete_elements (idx_j, idx_i);
1336  *this = tmp.transpose ();
1337  }
1338  }
1339  else
1340  {
1341  // Empty assignment (no elements to delete) is OK if there is at
1342  // least one zero-length index and at most one other index that is
1343  // non-colon (or equivalent) index. Since we only have two
1344  // indices, we just need to check that we have at least one zero
1345  // length index. Matlab considers "[]" to be an empty index but
1346  // not "false". We accept both.
1347 
1348  bool empty_assignment
1349  = (idx_i.length (nr) == 0 || idx_j.length (nc) == 0);
1350 
1351  if (! empty_assignment)
1352  (*current_liboctave_error_handler)
1353  ("a null assignment can only have one non-colon index");
1354  }
1355 }
1356 
1357 template <class T>
1358 void
1360 {
1361  if (dim == 0)
1362  delete_elements (idx, idx_vector::colon);
1363  else if (dim == 1)
1364  delete_elements (idx_vector::colon, idx);
1365  else
1366  {
1367  (*current_liboctave_error_handler)
1368  ("invalid dimension in delete_elements");
1369  return;
1370  }
1371 }
1372 
1373 template <class T>
1374 Sparse<T>
1375 Sparse<T>::index (const idx_vector& idx, bool resize_ok) const
1376 {
1377  Sparse<T> retval;
1378 
1379  assert (ndims () == 2);
1380 
1381  octave_idx_type nr = dim1 ();
1382  octave_idx_type nc = dim2 ();
1383  octave_idx_type nz = nnz ();
1384 
1385  octave_idx_type nel = numel (); // Can throw.
1386 
1387  const dim_vector idx_dims = idx.orig_dimensions ();
1388 
1389  if (idx_dims.length () > 2)
1391  ("cannot index sparse matrix with an N-D Array");
1392  else if (idx.is_colon ())
1393  {
1394  if (nc == 1)
1395  retval = *this;
1396  else
1397  {
1398  // Fast magic colon processing.
1399  retval = Sparse<T> (nel, 1, nz);
1400 
1401  for (octave_idx_type i = 0; i < nc; i++)
1402  {
1403  for (octave_idx_type j = cidx (i); j < cidx (i+1); j++)
1404  {
1405  retval.xdata (j) = data (j);
1406  retval.xridx (j) = ridx (j) + i * nr;
1407  }
1408  }
1409 
1410  retval.xcidx (0) = 0;
1411  retval.xcidx (1) = nz;
1412  }
1413  }
1414  else if (idx.extent (nel) > nel)
1415  {
1416  // resize_ok is completely handled here.
1417  if (resize_ok)
1418  {
1419  octave_idx_type ext = idx.extent (nel);
1420  Sparse<T> tmp = *this;
1421  tmp.resize1 (ext);
1422  retval = tmp.index (idx);
1423  }
1424  else
1425  gripe_index_out_of_range (1, 1, idx.extent (nel), nel);
1426  }
1427  else if (nr == 1 && nc == 1)
1428  {
1429  // You have to be pretty sick to get to this bit of code,
1430  // since you have a scalar stored as a sparse matrix, and
1431  // then want to make a dense matrix with sparse
1432  // representation. Ok, we'll do it, but you deserve what
1433  // you get!!
1434  retval = Sparse<T> (idx_dims(0), idx_dims(1), nz ? data (0) : T ());
1435  }
1436  else if (nc == 1)
1437  {
1438  // Sparse column vector.
1439  octave_idx_type lb, ub;
1440 
1441  if (idx.is_scalar ())
1442  {
1443  // Scalar index - just a binary lookup.
1444  octave_idx_type i = lblookup (ridx (), nz, idx(0));
1445  if (i < nz && ridx (i) == idx(0))
1446  retval = Sparse (1, 1, data (i));
1447  else
1448  retval = Sparse (1, 1);
1449  }
1450  else if (idx.is_cont_range (nel, lb, ub))
1451  {
1452  // Special-case a contiguous range.
1453  // Look-up indices first.
1454  octave_idx_type li = lblookup (ridx (), nz, lb);
1455  octave_idx_type ui = lblookup (ridx (), nz, ub);
1456  // Copy data and adjust indices.
1457  octave_idx_type nz_new = ui - li;
1458  retval = Sparse<T> (ub - lb, 1, nz_new);
1459  copy_or_memcpy (nz_new, data () + li, retval.data ());
1460  mx_inline_sub (nz_new, retval.xridx (), ridx () + li, lb);
1461  retval.xcidx (1) = nz_new;
1462  }
1463  else if (idx.is_permutation (nel) && idx.is_vector ())
1464  {
1465  if (idx.is_range () && idx.increment () == -1)
1466  {
1467  retval = Sparse<T> (nr, 1, nz);
1468 
1469  for (octave_idx_type j = 0; j < nz; j++)
1470  retval.ridx (j) = nr - ridx (nz - j - 1) - 1;
1471 
1472  copy_or_memcpy (2, cidx (), retval.cidx ());
1473  std::reverse_copy (data (), data () + nz, retval.data ());
1474  }
1475  else
1476  {
1477  Array<T> tmp = array_value ();
1478  tmp = tmp.index (idx);
1479  retval = Sparse<T> (tmp);
1480  }
1481  }
1482  else
1483  {
1484  // If indexing a sparse column vector by a vector, the result is a
1485  // sparse column vector, otherwise it inherits the shape of index.
1486  // Vector transpose is cheap, so do it right here.
1487  const Array<octave_idx_type> idxa = (idx_dims(0) == 1
1488  ? idx.as_array ().transpose ()
1489  : idx.as_array ());
1490 
1491  octave_idx_type new_nr = idxa.rows (), new_nc = idxa.cols ();
1492 
1493  // Lookup.
1494  // FIXME: Could specialize for sorted idx?
1495  NoAlias< Array<octave_idx_type> > lidx (dim_vector (new_nr, new_nc));
1496  for (octave_idx_type i = 0; i < new_nr*new_nc; i++)
1497  lidx(i) = lblookup (ridx (), nz, idxa(i));
1498 
1499  // Count matches.
1500  retval = Sparse<T> (idxa.rows (), idxa.cols ());
1501  for (octave_idx_type j = 0; j < new_nc; j++)
1502  {
1503  octave_idx_type nzj = 0;
1504  for (octave_idx_type i = 0; i < new_nr; i++)
1505  {
1506  octave_idx_type l = lidx(i, j);
1507  if (l < nz && ridx (l) == idxa(i, j))
1508  nzj++;
1509  else
1510  lidx(i, j) = nz;
1511  }
1512  retval.xcidx (j+1) = retval.xcidx (j) + nzj;
1513  }
1514 
1515  retval.change_capacity (retval.xcidx (new_nc));
1516 
1517  // Copy data and set row indices.
1518  octave_idx_type k = 0;
1519  for (octave_idx_type j = 0; j < new_nc; j++)
1520  for (octave_idx_type i = 0; i < new_nr; i++)
1521  {
1522  octave_idx_type l = lidx(i, j);
1523  if (l < nz)
1524  {
1525  retval.data (k) = data (l);
1526  retval.xridx (k++) = i;
1527  }
1528  }
1529  }
1530  }
1531  else if (nr == 1)
1532  {
1533  octave_idx_type lb, ub;
1534  if (idx.is_scalar ())
1535  retval = Sparse<T> (1, 1, elem (0, idx(0)));
1536  else if (idx.is_cont_range (nel, lb, ub))
1537  {
1538  // Special-case a contiguous range.
1539  octave_idx_type lbi = cidx (lb), ubi = cidx (ub), new_nz = ubi - lbi;
1540  retval = Sparse<T> (1, ub - lb, new_nz);
1541  copy_or_memcpy (new_nz, data () + lbi, retval.data ());
1542  fill_or_memset (new_nz, static_cast<octave_idx_type> (0),
1543  retval.ridx ());
1544  mx_inline_sub (ub - lb + 1, retval.cidx (), cidx () + lb, lbi);
1545  }
1546  else
1547  {
1548  // Sparse row vectors occupy O(nr) storage anyway, so let's just
1549  // convert the matrix to full, index, and sparsify the result.
1550  retval = Sparse<T> (array_value ().index (idx));
1551  }
1552  }
1553  else
1554  {
1555  if (nr != 0 && idx.is_scalar ())
1556  retval = Sparse<T> (1, 1, elem (idx(0) % nr, idx(0) / nr));
1557  else
1558  {
1559  // Indexing a non-vector sparse matrix by linear indexing.
1560  // I suppose this is rare (and it may easily overflow), so let's take
1561  // the easy way, and reshape first to column vector, which is already
1562  // handled above.
1563  retval = index (idx_vector::colon).index (idx);
1564  // In this case we're supposed to always inherit the shape, but
1565  // column(row) doesn't do it, so we'll do it instead.
1566  if (idx_dims(0) == 1 && idx_dims(1) != 1)
1567  retval = retval.transpose ();
1568  }
1569  }
1570 
1571  return retval;
1572 }
1573 
1574 template <class T>
1575 Sparse<T>
1576 Sparse<T>::index (const idx_vector& idx_i, const idx_vector& idx_j,
1577  bool resize_ok) const
1578 {
1579  Sparse<T> retval;
1580 
1581  assert (ndims () == 2);
1582 
1583  octave_idx_type nr = dim1 ();
1584  octave_idx_type nc = dim2 ();
1585 
1586  octave_idx_type n = idx_i.length (nr);
1587  octave_idx_type m = idx_j.length (nc);
1588 
1589  octave_idx_type lb, ub;
1590 
1591  if (idx_i.extent (nr) > nr || idx_j.extent (nc) > nc)
1592  {
1593  // resize_ok is completely handled here.
1594  if (resize_ok)
1595  {
1596  octave_idx_type ext_i = idx_i.extent (nr);
1597  octave_idx_type ext_j = idx_j.extent (nc);
1598  Sparse<T> tmp = *this;
1599  tmp.resize (ext_i, ext_j);
1600  retval = tmp.index (idx_i, idx_j);
1601  }
1602  else if (idx_i.extent (nr) > nr)
1603  gripe_index_out_of_range (2, 1, idx_i.extent (nr), nr);
1604  else
1605  gripe_index_out_of_range (2, 2, idx_j.extent (nc), nc);
1606  }
1607  else if (nr == 1 && nc == 1)
1608  {
1609  // Scalars stored as sparse matrices occupy more memory than
1610  // a scalar, so let's just convert the matrix to full, index,
1611  // and sparsify the result.
1612 
1613  retval = Sparse<T> (array_value ().index (idx_i, idx_j));
1614  }
1615  else if (idx_i.is_colon ())
1616  {
1617  // Great, we're just manipulating columns. This is going to be quite
1618  // efficient, because the columns can stay compressed as they are.
1619  if (idx_j.is_colon ())
1620  retval = *this; // Shallow copy.
1621  else if (idx_j.is_cont_range (nc, lb, ub))
1622  {
1623  // Special-case a contiguous range.
1624  octave_idx_type lbi = cidx (lb), ubi = cidx (ub), new_nz = ubi - lbi;
1625  retval = Sparse<T> (nr, ub - lb, new_nz);
1626  copy_or_memcpy (new_nz, data () + lbi, retval.data ());
1627  copy_or_memcpy (new_nz, ridx () + lbi, retval.ridx ());
1628  mx_inline_sub (ub - lb + 1, retval.cidx (), cidx () + lb, lbi);
1629  }
1630  else
1631  {
1632  // Count new nonzero elements.
1633  retval = Sparse<T> (nr, m);
1634  for (octave_idx_type j = 0; j < m; j++)
1635  {
1636  octave_idx_type jj = idx_j(j);
1637  retval.xcidx (j+1) = retval.xcidx (j) + (cidx (jj+1) - cidx (jj));
1638  }
1639 
1640  retval.change_capacity (retval.xcidx (m));
1641 
1642  // Copy data & indices.
1643  for (octave_idx_type j = 0; j < m; j++)
1644  {
1645  octave_idx_type ljj = cidx (idx_j(j));
1646  octave_idx_type lj = retval.xcidx (j);
1647  octave_idx_type nzj = retval.xcidx (j+1) - lj;
1648 
1649  copy_or_memcpy (nzj, data () + ljj, retval.data () + lj);
1650  copy_or_memcpy (nzj, ridx () + ljj, retval.ridx () + lj);
1651  }
1652  }
1653  }
1654  else if (nc == 1 && idx_j.is_colon_equiv (nc) && idx_i.is_vector ())
1655  {
1656  // It's actually vector indexing. The 1D index is specialized for that.
1657  retval = index (idx_i);
1658 
1659  // If nr == 1 then the vector indexing will return a column vector!!
1660  if (nr == 1)
1661  retval.transpose ();
1662  }
1663  else if (idx_i.is_scalar ())
1664  {
1665  octave_idx_type ii = idx_i(0);
1666  retval = Sparse<T> (1, m);
1668  for (octave_idx_type j = 0; j < m; j++)
1669  {
1670  octave_quit ();
1671  octave_idx_type jj = idx_j(j);
1672  octave_idx_type lj = cidx (jj);
1673  octave_idx_type nzj = cidx (jj+1) - cidx (jj);
1674 
1675  // Scalar index - just a binary lookup.
1676  octave_idx_type i = lblookup (ridx () + lj, nzj, ii);
1677  if (i < nzj && ridx (i+lj) == ii)
1678  {
1679  ij[j] = i + lj;
1680  retval.xcidx (j+1) = retval.xcidx (j) + 1;
1681  }
1682  else
1683  retval.xcidx (j+1) = retval.xcidx (j);
1684  }
1685 
1686  retval.change_capacity (retval.xcidx (m));
1687 
1688  // Copy data, adjust row indices.
1689  for (octave_idx_type j = 0; j < m; j++)
1690  {
1691  octave_idx_type i = retval.xcidx (j);
1692  if (retval.xcidx (j+1) > i)
1693  {
1694  retval.xridx (i) = 0;
1695  retval.xdata (i) = data (ij[j]);
1696  }
1697  }
1698  }
1699  else if (idx_i.is_cont_range (nr, lb, ub))
1700  {
1701  retval = Sparse<T> (n, m);
1704  for (octave_idx_type j = 0; j < m; j++)
1705  {
1706  octave_quit ();
1707  octave_idx_type jj = idx_j(j);
1708  octave_idx_type lj = cidx (jj);
1709  octave_idx_type nzj = cidx (jj+1) - cidx (jj);
1710  octave_idx_type lij, uij;
1711 
1712  // Lookup indices.
1713  li[j] = lij = lblookup (ridx () + lj, nzj, lb) + lj;
1714  ui[j] = uij = lblookup (ridx () + lj, nzj, ub) + lj;
1715  retval.xcidx (j+1) = retval.xcidx (j) + ui[j] - li[j];
1716  }
1717 
1718  retval.change_capacity (retval.xcidx (m));
1719 
1720  // Copy data, adjust row indices.
1721  for (octave_idx_type j = 0, k = 0; j < m; j++)
1722  {
1723  octave_quit ();
1724  for (octave_idx_type i = li[j]; i < ui[j]; i++)
1725  {
1726  retval.xdata (k) = data (i);
1727  retval.xridx (k++) = ridx (i) - lb;
1728  }
1729  }
1730  }
1731  else if (idx_i.is_permutation (nr))
1732  {
1733  // The columns preserve their length, just need to renumber and sort them.
1734  // Count new nonzero elements.
1735  retval = Sparse<T> (nr, m);
1736  for (octave_idx_type j = 0; j < m; j++)
1737  {
1738  octave_idx_type jj = idx_j(j);
1739  retval.xcidx (j+1) = retval.xcidx (j) + (cidx (jj+1) - cidx (jj));
1740  }
1741 
1742  retval.change_capacity (retval.xcidx (m));
1743 
1744  octave_quit ();
1745 
1746  if (idx_i.is_range () && idx_i.increment () == -1)
1747  {
1748  // It's nr:-1:1. Just flip all columns.
1749  for (octave_idx_type j = 0; j < m; j++)
1750  {
1751  octave_quit ();
1752  octave_idx_type jj = idx_j(j);
1753  octave_idx_type lj = cidx (jj);
1754  octave_idx_type nzj = cidx (jj+1) - cidx (jj);
1755  octave_idx_type li = retval.xcidx (j), uj = lj + nzj - 1;
1756  for (octave_idx_type i = 0; i < nzj; i++)
1757  {
1758  retval.xdata (li + i) = data (uj - i); // Copy in reverse order.
1759  retval.xridx (li + i) = nr - 1 - ridx (uj - i); // Ditto with transform.
1760  }
1761  }
1762  }
1763  else
1764  {
1765  // Get inverse permutation.
1766  idx_vector idx_iinv = idx_i.inverse_permutation (nr);
1767  const octave_idx_type *iinv = idx_iinv.raw ();
1768 
1769  // Scatter buffer.
1770  OCTAVE_LOCAL_BUFFER (T, scb, nr);
1771  octave_idx_type *rri = retval.ridx ();
1772 
1773  for (octave_idx_type j = 0; j < m; j++)
1774  {
1775  octave_quit ();
1776  octave_idx_type jj = idx_j(j);
1777  octave_idx_type lj = cidx (jj);
1778  octave_idx_type nzj = cidx (jj+1) - cidx (jj);
1779  octave_idx_type li = retval.xcidx (j);
1780  // Scatter the column, transform indices.
1781  for (octave_idx_type i = 0; i < nzj; i++)
1782  scb[rri[li + i] = iinv[ridx (lj + i)]] = data (lj + i);
1783 
1784  octave_quit ();
1785 
1786  // Sort them.
1787  std::sort (rri + li, rri + li + nzj);
1788 
1789  // Gather.
1790  for (octave_idx_type i = 0; i < nzj; i++)
1791  retval.xdata (li + i) = scb[rri[li + i]];
1792  }
1793  }
1794 
1795  }
1796  else if (idx_j.is_colon ())
1797  {
1798  // This requires uncompressing columns, which is generally costly,
1799  // so we rely on the efficient transpose to handle this.
1800  // It may still make sense to optimize some cases here.
1801  retval = transpose ();
1802  retval = retval.index (idx_vector::colon, idx_i);
1803  retval = retval.transpose ();
1804  }
1805  else
1806  {
1807  // A(I, J) is decomposed into A(:, J)(I, :).
1808  retval = index (idx_vector::colon, idx_j);
1809  retval = retval.index (idx_i, idx_vector::colon);
1810  }
1811 
1812  return retval;
1813 }
1814 
1815 template <class T>
1816 void
1817 Sparse<T>::assign (const idx_vector& idx, const Sparse<T>& rhs)
1818 {
1819  Sparse<T> retval;
1820 
1821  assert (ndims () == 2);
1822 
1823  octave_idx_type nr = dim1 ();
1824  octave_idx_type nc = dim2 ();
1825  octave_idx_type nz = nnz ();
1826 
1827  octave_idx_type n = numel (); // Can throw.
1828 
1829  octave_idx_type rhl = rhs.numel ();
1830 
1831  if (idx.length (n) == rhl)
1832  {
1833  if (rhl == 0)
1834  return;
1835 
1836  octave_idx_type nx = idx.extent (n);
1837  // Try to resize first if necessary.
1838  if (nx != n)
1839  {
1840  resize1 (nx);
1841  n = numel ();
1842  nr = rows ();
1843  nc = cols ();
1844  // nz is preserved.
1845  }
1846 
1847  if (idx.is_colon ())
1848  {
1849  *this = rhs.reshape (dimensions);
1850  }
1851  else if (nc == 1 && rhs.cols () == 1)
1852  {
1853  // Sparse column vector to sparse column vector assignment.
1854 
1855  octave_idx_type lb, ub;
1856  if (idx.is_cont_range (nr, lb, ub))
1857  {
1858  // Special-case a contiguous range.
1859  // Look-up indices first.
1860  octave_idx_type li = lblookup (ridx (), nz, lb);
1861  octave_idx_type ui = lblookup (ridx (), nz, ub);
1862  octave_idx_type rnz = rhs.nnz (), new_nz = nz - (ui - li) + rnz;
1863 
1864  if (new_nz >= nz && new_nz <= capacity ())
1865  {
1866  // Adding/overwriting elements, enough capacity allocated.
1867 
1868  if (new_nz > nz)
1869  {
1870  // Make room first.
1871  std::copy_backward (data () + ui, data () + nz,
1872  data () + nz + rnz);
1873  std::copy_backward (ridx () + ui, ridx () + nz,
1874  ridx () + nz + rnz);
1875  }
1876 
1877  // Copy data and adjust indices from rhs.
1878  copy_or_memcpy (rnz, rhs.data (), data () + li);
1879  mx_inline_add (rnz, ridx () + li, rhs.ridx (), lb);
1880  }
1881  else
1882  {
1883  // Clearing elements or exceeding capacity, allocate afresh
1884  // and paste pieces.
1885  const Sparse<T> tmp = *this;
1886  *this = Sparse<T> (nr, 1, new_nz);
1887 
1888  // Head ...
1889  copy_or_memcpy (li, tmp.data (), data ());
1890  copy_or_memcpy (li, tmp.ridx (), ridx ());
1891 
1892  // new stuff ...
1893  copy_or_memcpy (rnz, rhs.data (), data () + li);
1894  mx_inline_add (rnz, ridx () + li, rhs.ridx (), lb);
1895 
1896  // ...tail
1897  copy_or_memcpy (nz - ui, tmp.data () + ui,
1898  data () + li + rnz);
1899  copy_or_memcpy (nz - ui, tmp.ridx () + ui,
1900  ridx () + li + rnz);
1901  }
1902 
1903  cidx (1) = new_nz;
1904  }
1905  else if (idx.is_range () && idx.increment () == -1)
1906  {
1907  // It's s(u:-1:l) = r. Reverse the assignment.
1908  assign (idx.sorted (), rhs.index (idx_vector (rhl - 1, 0, -1)));
1909  }
1910  else if (idx.is_permutation (n))
1911  {
1912  *this = rhs.index (idx.inverse_permutation (n));
1913  }
1914  else if (rhs.nnz () == 0)
1915  {
1916  // Elements are being zeroed.
1917  octave_idx_type *ri = ridx ();
1918  for (octave_idx_type i = 0; i < rhl; i++)
1919  {
1920  octave_idx_type iidx = idx(i);
1921  octave_idx_type li = lblookup (ri, nz, iidx);
1922  if (li != nz && ri[li] == iidx)
1923  xdata (li) = T ();
1924  }
1925 
1926  maybe_compress (true);
1927  }
1928  else
1929  {
1930  const Sparse<T> tmp = *this;
1931  octave_idx_type new_nz = nz + rhl;
1932  // Disassembly our matrix...
1933  Array<octave_idx_type> new_ri (dim_vector (new_nz, 1));
1934  Array<T> new_data (dim_vector (new_nz, 1));
1935  copy_or_memcpy (nz, tmp.ridx (), new_ri.fortran_vec ());
1936  copy_or_memcpy (nz, tmp.data (), new_data.fortran_vec ());
1937  // ... insert new data (densified) ...
1938  idx.copy_data (new_ri.fortran_vec () + nz);
1939  new_data.assign (idx_vector (nz, new_nz), rhs.array_value ());
1940  // ... reassembly.
1941  *this = Sparse<T> (new_data, new_ri,
1942  static_cast<octave_idx_type> (0),
1943  nr, nc, false);
1944  }
1945  }
1946  else
1947  {
1948  dim_vector save_dims = dimensions;
1949  *this = index (idx_vector::colon);
1950  assign (idx, rhs.index (idx_vector::colon));
1951  *this = reshape (save_dims);
1952  }
1953  }
1954  else if (rhl == 1)
1955  {
1956  rhl = idx.length (n);
1957  if (rhs.nnz () != 0)
1958  assign (idx, Sparse<T> (rhl, 1, rhs.data (0)));
1959  else
1960  assign (idx, Sparse<T> (rhl, 1));
1961  }
1962  else
1964 }
1965 
1966 template <class T>
1967 void
1969  const idx_vector& idx_j, const Sparse<T>& rhs)
1970 {
1971  Sparse<T> retval;
1972 
1973  assert (ndims () == 2);
1974 
1975  octave_idx_type nr = dim1 ();
1976  octave_idx_type nc = dim2 ();
1977  octave_idx_type nz = nnz ();
1978 
1979  octave_idx_type n = rhs.rows ();
1980  octave_idx_type m = rhs.columns ();
1981 
1982  // FIXME: this should probably be written more like the
1983  // Array<T>::assign function...
1984 
1985  bool orig_zero_by_zero = (nr == 0 && nc == 0);
1986 
1987  if (orig_zero_by_zero || (idx_i.length (nr) == n && idx_j.length (nc) == m))
1988  {
1989  octave_idx_type nrx;
1990  octave_idx_type ncx;
1991 
1992  if (orig_zero_by_zero)
1993  {
1994  if (idx_i.is_colon ())
1995  {
1996  nrx = n;
1997 
1998  if (idx_j.is_colon ())
1999  ncx = m;
2000  else
2001  ncx = idx_j.extent (nc);
2002  }
2003  else if (idx_j.is_colon ())
2004  {
2005  nrx = idx_i.extent (nr);
2006  ncx = m;
2007  }
2008  else
2009  {
2010  nrx = idx_i.extent (nr);
2011  ncx = idx_j.extent (nc);
2012  }
2013  }
2014  else
2015  {
2016  nrx = idx_i.extent (nr);
2017  ncx = idx_j.extent (nc);
2018  }
2019 
2020  // Try to resize first if necessary.
2021  if (nrx != nr || ncx != nc)
2022  {
2023  resize (nrx, ncx);
2024  nr = rows ();
2025  nc = cols ();
2026  // nz is preserved.
2027  }
2028 
2029  if (n == 0 || m == 0)
2030  return;
2031 
2032  if (idx_i.is_colon ())
2033  {
2034  octave_idx_type lb, ub;
2035  // Great, we're just manipulating columns. This is going to be quite
2036  // efficient, because the columns can stay compressed as they are.
2037  if (idx_j.is_colon ())
2038  *this = rhs; // Shallow copy.
2039  else if (idx_j.is_cont_range (nc, lb, ub))
2040  {
2041  // Special-case a contiguous range.
2042  octave_idx_type li = cidx (lb), ui = cidx (ub);
2043  octave_idx_type rnz = rhs.nnz (), new_nz = nz - (ui - li) + rnz;
2044 
2045  if (new_nz >= nz && new_nz <= capacity ())
2046  {
2047  // Adding/overwriting elements, enough capacity allocated.
2048 
2049  if (new_nz > nz)
2050  {
2051  // Make room first.
2052  std::copy (data () + ui, data () + nz,
2053  data () + li + rnz);
2054  std::copy (ridx () + ui, ridx () + nz,
2055  ridx () + li + rnz);
2056  mx_inline_add2 (nc - ub, cidx () + ub + 1, new_nz - nz);
2057  }
2058 
2059  // Copy data and indices from rhs.
2060  copy_or_memcpy (rnz, rhs.data (), data () + li);
2061  copy_or_memcpy (rnz, rhs.ridx (), ridx () + li);
2062  mx_inline_add (ub - lb, cidx () + lb + 1, rhs.cidx () + 1,
2063  li);
2064 
2065  assert (nnz () == new_nz);
2066  }
2067  else
2068  {
2069  // Clearing elements or exceeding capacity, allocate afresh
2070  // and paste pieces.
2071  const Sparse<T> tmp = *this;
2072  *this = Sparse<T> (nr, nc, new_nz);
2073 
2074  // Head...
2075  copy_or_memcpy (li, tmp.data (), data ());
2076  copy_or_memcpy (li, tmp.ridx (), ridx ());
2077  copy_or_memcpy (lb, tmp.cidx () + 1, cidx () + 1);
2078 
2079  // new stuff...
2080  copy_or_memcpy (rnz, rhs.data (), data () + li);
2081  copy_or_memcpy (rnz, rhs.ridx (), ridx () + li);
2082  mx_inline_add (ub - lb, cidx () + lb + 1, rhs.cidx () + 1,
2083  li);
2084 
2085  // ...tail.
2086  copy_or_memcpy (nz - ui, tmp.data () + ui,
2087  data () + li + rnz);
2088  copy_or_memcpy (nz - ui, tmp.ridx () + ui,
2089  ridx () + li + rnz);
2090  mx_inline_add (nc - ub, cidx () + ub + 1,
2091  tmp.cidx () + ub + 1, new_nz - nz);
2092 
2093  assert (nnz () == new_nz);
2094  }
2095  }
2096  else if (idx_j.is_range () && idx_j.increment () == -1)
2097  {
2098  // It's s(:,u:-1:l) = r. Reverse the assignment.
2099  assign (idx_i, idx_j.sorted (),
2100  rhs.index (idx_i, idx_vector (m - 1, 0, -1)));
2101  }
2102  else if (idx_j.is_permutation (nc))
2103  {
2104  *this = rhs.index (idx_i, idx_j.inverse_permutation (nc));
2105  }
2106  else
2107  {
2108  const Sparse<T> tmp = *this;
2109  *this = Sparse<T> (nr, nc);
2110  OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, jsav, nc, -1);
2111 
2112  // Assemble column lengths.
2113  for (octave_idx_type i = 0; i < nc; i++)
2114  xcidx (i+1) = tmp.cidx (i+1) - tmp.cidx (i);
2115 
2116  for (octave_idx_type i = 0; i < m; i++)
2117  {
2118  octave_idx_type j =idx_j(i);
2119  jsav[j] = i;
2120  xcidx (j+1) = rhs.cidx (i+1) - rhs.cidx (i);
2121  }
2122 
2123  // Make cumulative.
2124  for (octave_idx_type i = 0; i < nc; i++)
2125  xcidx (i+1) += xcidx (i);
2126 
2127  change_capacity (nnz ());
2128 
2129  // Merge columns.
2130  for (octave_idx_type i = 0; i < nc; i++)
2131  {
2132  octave_idx_type l = xcidx (i), u = xcidx (i+1), j = jsav[i];
2133  if (j >= 0)
2134  {
2135  // from rhs
2136  octave_idx_type k = rhs.cidx (j);
2137  copy_or_memcpy (u - l, rhs.data () + k, xdata () + l);
2138  copy_or_memcpy (u - l, rhs.ridx () + k, xridx () + l);
2139  }
2140  else
2141  {
2142  // original
2143  octave_idx_type k = tmp.cidx (i);
2144  copy_or_memcpy (u - l, tmp.data () + k, xdata () + l);
2145  copy_or_memcpy (u - l, tmp.ridx () + k, xridx () + l);
2146  }
2147  }
2148 
2149  }
2150  }
2151  else if (nc == 1 && idx_j.is_colon_equiv (nc) && idx_i.is_vector ())
2152  {
2153  // It's just vector indexing. The 1D assign is specialized for that.
2154  assign (idx_i, rhs);
2155  }
2156  else if (idx_j.is_colon ())
2157  {
2158  if (idx_i.is_permutation (nr))
2159  {
2160  *this = rhs.index (idx_i.inverse_permutation (nr), idx_j);
2161  }
2162  else
2163  {
2164  // FIXME: optimize more special cases?
2165  // In general this requires unpacking the columns, which is slow,
2166  // especially for many small columns. OTOH, transpose is an
2167  // efficient O(nr+nc+nnz) operation.
2168  *this = transpose ();
2169  assign (idx_vector::colon, idx_i, rhs.transpose ());
2170  *this = transpose ();
2171  }
2172  }
2173  else
2174  {
2175  // Split it into 2 assignments and one indexing.
2176  Sparse<T> tmp = index (idx_vector::colon, idx_j);
2177  tmp.assign (idx_i, idx_vector::colon, rhs);
2178  assign (idx_vector::colon, idx_j, tmp);
2179  }
2180  }
2181  else if (m == 1 && n == 1)
2182  {
2183  n = idx_i.length (nr);
2184  m = idx_j.length (nc);
2185  if (rhs.nnz () != 0)
2186  assign (idx_i, idx_j, Sparse<T> (n, m, rhs.data (0)));
2187  else
2188  assign (idx_i, idx_j, Sparse<T> (n, m));
2189  }
2190  else
2192 }
2193 
2194 // Can't use versions of these in Array.cc due to duplication of the
2195 // instantiations for Array<double and Sparse<double>, etc
2196 template <class T>
2197 bool
2199  typename ref_param<T>::type b)
2200 {
2201  return (a < b);
2202 }
2203 
2204 template <class T>
2205 bool
2207  typename ref_param<T>::type b)
2208 {
2209  return (a > b);
2210 }
2211 
2212 template <class T>
2213 Sparse<T>
2215 {
2216  Sparse<T> m = *this;
2217 
2218  octave_idx_type nr = m.rows ();
2219  octave_idx_type nc = m.columns ();
2220 
2221  if (m.length () < 1 || dim > 1)
2222  return m;
2223 
2224  if (dim > 0)
2225  {
2226  m = m.transpose ();
2227  nr = m.rows ();
2228  nc = m.columns ();
2229  }
2230 
2231  octave_sort<T> lsort;
2232 
2233  if (mode == ASCENDING)
2234  lsort.set_compare (sparse_ascending_compare<T>);
2235  else if (mode == DESCENDING)
2236  lsort.set_compare (sparse_descending_compare<T>);
2237  else
2238  abort ();
2239 
2240  T *v = m.data ();
2241  octave_idx_type *mcidx = m.cidx ();
2242  octave_idx_type *mridx = m.ridx ();
2243 
2244  for (octave_idx_type j = 0; j < nc; j++)
2245  {
2246  octave_idx_type ns = mcidx[j + 1] - mcidx[j];
2247  lsort.sort (v, ns);
2248 
2249  octave_idx_type i;
2250  if (mode == ASCENDING)
2251  {
2252  for (i = 0; i < ns; i++)
2253  if (sparse_ascending_compare<T> (static_cast<T> (0), v[i]))
2254  break;
2255  }
2256  else
2257  {
2258  for (i = 0; i < ns; i++)
2259  if (sparse_descending_compare<T> (static_cast<T> (0), v[i]))
2260  break;
2261  }
2262  for (octave_idx_type k = 0; k < i; k++)
2263  mridx[k] = k;
2264  for (octave_idx_type k = i; k < ns; k++)
2265  mridx[k] = k - ns + nr;
2266 
2267  v += ns;
2268  mridx += ns;
2269  }
2270 
2271  if (dim > 0)
2272  m = m.transpose ();
2273 
2274  return m;
2275 }
2276 
2277 template <class T>
2278 Sparse<T>
2280  sortmode mode) const
2281 {
2282  Sparse<T> m = *this;
2283 
2284  octave_idx_type nr = m.rows ();
2285  octave_idx_type nc = m.columns ();
2286 
2287  if (m.length () < 1 || dim > 1)
2288  {
2289  sidx = Array<octave_idx_type> (dim_vector (nr, nc), 1);
2290  return m;
2291  }
2292 
2293  if (dim > 0)
2294  {
2295  m = m.transpose ();
2296  nr = m.rows ();
2297  nc = m.columns ();
2298  }
2299 
2300  octave_sort<T> indexed_sort;
2301 
2302  if (mode == ASCENDING)
2303  indexed_sort.set_compare (sparse_ascending_compare<T>);
2304  else if (mode == DESCENDING)
2305  indexed_sort.set_compare (sparse_descending_compare<T>);
2306  else
2307  abort ();
2308 
2309  T *v = m.data ();
2310  octave_idx_type *mcidx = m.cidx ();
2311  octave_idx_type *mridx = m.ridx ();
2312 
2313  sidx = Array<octave_idx_type> (dim_vector (nr, nc));
2315 
2316  for (octave_idx_type j = 0; j < nc; j++)
2317  {
2318  octave_idx_type ns = mcidx[j + 1] - mcidx[j];
2319  octave_idx_type offset = j * nr;
2320 
2321  if (ns == 0)
2322  {
2323  for (octave_idx_type k = 0; k < nr; k++)
2324  sidx (offset + k) = k;
2325  }
2326  else
2327  {
2328  for (octave_idx_type i = 0; i < ns; i++)
2329  vi[i] = mridx[i];
2330 
2331  indexed_sort.sort (v, vi, ns);
2332 
2333  octave_idx_type i;
2334  if (mode == ASCENDING)
2335  {
2336  for (i = 0; i < ns; i++)
2337  if (sparse_ascending_compare<T> (static_cast<T> (0), v[i]))
2338  break;
2339  }
2340  else
2341  {
2342  for (i = 0; i < ns; i++)
2343  if (sparse_descending_compare<T> (static_cast<T> (0), v[i]))
2344  break;
2345  }
2346 
2347  octave_idx_type ii = 0;
2348  octave_idx_type jj = i;
2349  for (octave_idx_type k = 0; k < nr; k++)
2350  {
2351  if (ii < ns && mridx[ii] == k)
2352  ii++;
2353  else
2354  sidx (offset + jj++) = k;
2355  }
2356 
2357  for (octave_idx_type k = 0; k < i; k++)
2358  {
2359  sidx (k + offset) = vi[k];
2360  mridx[k] = k;
2361  }
2362 
2363  for (octave_idx_type k = i; k < ns; k++)
2364  {
2365  sidx (k - ns + nr + offset) = vi[k];
2366  mridx[k] = k - ns + nr;
2367  }
2368 
2369  v += ns;
2370  mridx += ns;
2371  }
2372  }
2373 
2374  if (dim > 0)
2375  {
2376  m = m.transpose ();
2377  sidx = sidx.transpose ();
2378  }
2379 
2380  return m;
2381 }
2382 
2383 template <class T>
2384 Sparse<T>
2386 {
2387  octave_idx_type nnr = rows ();
2388  octave_idx_type nnc = cols ();
2389  Sparse<T> d;
2390 
2391  if (nnr == 0 || nnc == 0)
2392  ; // do nothing
2393  else if (nnr != 1 && nnc != 1)
2394  {
2395  if (k > 0)
2396  nnc -= k;
2397  else if (k < 0)
2398  nnr += k;
2399 
2400  if (nnr > 0 && nnc > 0)
2401  {
2402  octave_idx_type ndiag = (nnr < nnc) ? nnr : nnc;
2403 
2404  // Count the number of non-zero elements
2405  octave_idx_type nel = 0;
2406  if (k > 0)
2407  {
2408  for (octave_idx_type i = 0; i < ndiag; i++)
2409  if (elem (i, i+k) != 0.)
2410  nel++;
2411  }
2412  else if ( k < 0)
2413  {
2414  for (octave_idx_type i = 0; i < ndiag; i++)
2415  if (elem (i-k, i) != 0.)
2416  nel++;
2417  }
2418  else
2419  {
2420  for (octave_idx_type i = 0; i < ndiag; i++)
2421  if (elem (i, i) != 0.)
2422  nel++;
2423  }
2424 
2425  d = Sparse<T> (ndiag, 1, nel);
2426  d.xcidx (0) = 0;
2427  d.xcidx (1) = nel;
2428 
2429  octave_idx_type ii = 0;
2430  if (k > 0)
2431  {
2432  for (octave_idx_type i = 0; i < ndiag; i++)
2433  {
2434  T tmp = elem (i, i+k);
2435  if (tmp != 0.)
2436  {
2437  d.xdata (ii) = tmp;
2438  d.xridx (ii++) = i;
2439  }
2440  }
2441  }
2442  else if ( k < 0)
2443  {
2444  for (octave_idx_type i = 0; i < ndiag; i++)
2445  {
2446  T tmp = elem (i-k, i);
2447  if (tmp != 0.)
2448  {
2449  d.xdata (ii) = tmp;
2450  d.xridx (ii++) = i;
2451  }
2452  }
2453  }
2454  else
2455  {
2456  for (octave_idx_type i = 0; i < ndiag; i++)
2457  {
2458  T tmp = elem (i, i);
2459  if (tmp != 0.)
2460  {
2461  d.xdata (ii) = tmp;
2462  d.xridx (ii++) = i;
2463  }
2464  }
2465  }
2466  }
2467  else
2469  ("diag: requested diagonal out of range");
2470  }
2471  else if (nnr != 0 && nnc != 0)
2472  {
2473  octave_idx_type roff = 0;
2474  octave_idx_type coff = 0;
2475  if (k > 0)
2476  {
2477  roff = 0;
2478  coff = k;
2479  }
2480  else if (k < 0)
2481  {
2482  roff = -k;
2483  coff = 0;
2484  }
2485 
2486  if (nnr == 1)
2487  {
2488  octave_idx_type n = nnc + std::abs (k);
2489  octave_idx_type nz = nnz ();
2490 
2491  d = Sparse<T> (n, n, nz);
2492 
2493  if (nnz () > 0)
2494  {
2495  for (octave_idx_type i = 0; i < coff+1; i++)
2496  d.xcidx (i) = 0;
2497 
2498  for (octave_idx_type j = 0; j < nnc; j++)
2499  {
2500  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)
2501  {
2502  d.xdata (i) = data (i);
2503  d.xridx (i) = j + roff;
2504  }
2505  d.xcidx (j + coff + 1) = cidx (j+1);
2506  }
2507 
2508  for (octave_idx_type i = nnc + coff + 1; i < n + 1; i++)
2509  d.xcidx (i) = nz;
2510  }
2511  }
2512  else
2513  {
2514  octave_idx_type n = nnr + std::abs (k);
2515  octave_idx_type nz = nnz ();
2516 
2517  d = Sparse<T> (n, n, nz);
2518 
2519  if (nnz () > 0)
2520  {
2521  octave_idx_type ii = 0;
2522  octave_idx_type ir = ridx (0);
2523 
2524  for (octave_idx_type i = 0; i < coff+1; i++)
2525  d.xcidx (i) = 0;
2526 
2527  for (octave_idx_type i = 0; i < nnr; i++)
2528  {
2529  if (ir == i)
2530  {
2531  d.xdata (ii) = data (ii);
2532  d.xridx (ii++) = ir + roff;
2533 
2534  if (ii != nz)
2535  ir = ridx (ii);
2536  }
2537  d.xcidx (i + coff + 1) = ii;
2538  }
2539 
2540  for (octave_idx_type i = nnr + coff + 1; i < n+1; i++)
2541  d.xcidx (i) = nz;
2542  }
2543  }
2544  }
2545 
2546  return d;
2547 }
2548 
2549 template <class T>
2550 Sparse<T>
2551 Sparse<T>::cat (int dim, octave_idx_type n, const Sparse<T> *sparse_list)
2552 {
2553  // Default concatenation.
2554  bool (dim_vector::*concat_rule) (const dim_vector&, int) = &dim_vector::concat;
2555 
2556  if (dim == -1 || dim == -2)
2557  {
2558  concat_rule = &dim_vector::hvcat;
2559  dim = -dim - 1;
2560  }
2561  else if (dim < 0)
2562  (*current_liboctave_error_handler)
2563  ("cat: invalid dimension");
2564 
2565  dim_vector dv;
2566  octave_idx_type total_nz = 0;
2567  if (dim == 0 || dim == 1)
2568  {
2569  if (n == 1)
2570  return sparse_list[0];
2571 
2572  for (octave_idx_type i = 0; i < n; i++)
2573  {
2574  if (! (dv.*concat_rule) (sparse_list[i].dims (), dim))
2575  (*current_liboctave_error_handler)
2576  ("cat: dimension mismatch");
2577  total_nz += sparse_list[i].nnz ();
2578  }
2579  }
2580  else
2582  ("cat: invalid dimension for sparse concatenation");
2583 
2584  Sparse<T> retval (dv, total_nz);
2585 
2586  if (retval.is_empty ())
2587  return retval;
2588 
2589  switch (dim)
2590  {
2591  case 0:
2592  {
2593  // sparse vertcat. This is not efficiently handled by assignment,
2594  // so we'll do it directly.
2595  octave_idx_type l = 0;
2596  for (octave_idx_type j = 0; j < dv(1); j++)
2597  {
2598  octave_quit ();
2599 
2600  octave_idx_type rcum = 0;
2601  for (octave_idx_type i = 0; i < n; i++)
2602  {
2603  const Sparse<T>& spi = sparse_list[i];
2604  // Skipping empty matrices. See the comment in Array.cc.
2605  if (spi.is_empty ())
2606  continue;
2607 
2608  octave_idx_type kl = spi.cidx (j), ku = spi.cidx (j+1);
2609  for (octave_idx_type k = kl; k < ku; k++, l++)
2610  {
2611  retval.xridx (l) = spi.ridx (k) + rcum;
2612  retval.xdata (l) = spi.data (k);
2613  }
2614 
2615  rcum += spi.rows ();
2616  }
2617 
2618  retval.xcidx (j+1) = l;
2619  }
2620 
2621  break;
2622  }
2623  case 1:
2624  {
2625  octave_idx_type l = 0;
2626  for (octave_idx_type i = 0; i < n; i++)
2627  {
2628  octave_quit ();
2629 
2630  // Skipping empty matrices. See the comment in Array.cc.
2631  if (sparse_list[i].is_empty ())
2632  continue;
2633 
2634  octave_idx_type u = l + sparse_list[i].columns ();
2635  retval.assign (idx_vector::colon, idx_vector (l, u),
2636  sparse_list[i]);
2637  l = u;
2638  }
2639 
2640  break;
2641  }
2642  default:
2643  assert (false);
2644  }
2645 
2646  return retval;
2647 }
2648 
2649 template <class T>
2650 Array<T>
2652 {
2653  NoAlias< Array<T> > retval (dims (), T ());
2654  if (rows () == 1)
2655  {
2656  octave_idx_type i = 0;
2657  for (octave_idx_type j = 0, nc = cols (); j < nc; j++)
2658  {
2659  if (cidx (j+1) > i)
2660  retval(j) = data (i++);
2661  }
2662  }
2663  else
2664  {
2665  for (octave_idx_type j = 0, nc = cols (); j < nc; j++)
2666  for (octave_idx_type i = cidx (j), iu = cidx (j+1); i < iu; i++)
2667  retval(ridx (i), j) = data (i);
2668  }
2669 
2670  return retval;
2671 }
2672 
2673 /*
2674  * Tests
2675  *
2676 
2677 %!function x = set_slice (x, dim, slice, arg)
2678 %! switch (dim)
2679 %! case 11
2680 %! x(slice) = 2;
2681 %! case 21
2682 %! x(slice, :) = 2;
2683 %! case 22
2684 %! x(:, slice) = 2;
2685 %! otherwise
2686 %! error ("invalid dim, '%d'", dim);
2687 %! endswitch
2688 %!endfunction
2689 
2690 %!function x = set_slice2 (x, dim, slice)
2691 %! switch (dim)
2692 %! case 11
2693 %! x(slice) = 2 * ones (size (slice));
2694 %! case 21
2695 %! x(slice, :) = 2 * ones (length (slice), columns (x));
2696 %! case 22
2697 %! x(:, slice) = 2 * ones (rows (x), length (slice));
2698 %! otherwise
2699 %! error ("invalid dim, '%d'", dim);
2700 %! endswitch
2701 %!endfunction
2702 
2703 %!function test_sparse_slice (size, dim, slice)
2704 %! x = ones (size);
2705 %! s = set_slice (sparse (x), dim, slice);
2706 %! f = set_slice (x, dim, slice);
2707 %! assert (nnz (s), nnz (f));
2708 %! assert (full (s), f);
2709 %! s = set_slice2 (sparse (x), dim, slice);
2710 %! f = set_slice2 (x, dim, slice);
2711 %! assert (nnz (s), nnz (f));
2712 %! assert (full (s), f);
2713 %!endfunction
2714 
2715 #### 1d indexing
2716 
2717 ## size = [2 0]
2718 %!test test_sparse_slice ([2 0], 11, []);
2719 %!assert (set_slice (sparse (ones ([2 0])), 11, 1), sparse ([2 0]')) # sparse different from full
2720 %!assert (set_slice (sparse (ones ([2 0])), 11, 2), sparse ([0 2]')) # sparse different from full
2721 %!assert (set_slice (sparse (ones ([2 0])), 11, 3), sparse ([0 0; 2 0]')) # sparse different from full
2722 %!assert (set_slice (sparse (ones ([2 0])), 11, 4), sparse ([0 0; 0 2]')) # sparse different from full
2723 
2724 ## size = [0 2]
2725 %!test test_sparse_slice ([0 2], 11, []);
2726 %!assert (set_slice (sparse (ones ([0 2])), 11, 1), sparse ([2 0])) # sparse different from full
2727 %!test test_sparse_slice ([0 2], 11, 2);
2728 %!test test_sparse_slice ([0 2], 11, 3);
2729 %!test test_sparse_slice ([0 2], 11, 4);
2730 %!test test_sparse_slice ([0 2], 11, [4, 4]);
2731 
2732 ## size = [2 1]
2733 %!test test_sparse_slice ([2 1], 11, []);
2734 %!test test_sparse_slice ([2 1], 11, 1);
2735 %!test test_sparse_slice ([2 1], 11, 2);
2736 %!test test_sparse_slice ([2 1], 11, 3);
2737 %!test test_sparse_slice ([2 1], 11, 4);
2738 %!test test_sparse_slice ([2 1], 11, [4, 4]);
2739 
2740 ## size = [1 2]
2741 %!test test_sparse_slice ([1 2], 11, []);
2742 %!test test_sparse_slice ([1 2], 11, 1);
2743 %!test test_sparse_slice ([1 2], 11, 2);
2744 %!test test_sparse_slice ([1 2], 11, 3);
2745 %!test test_sparse_slice ([1 2], 11, 4);
2746 %!test test_sparse_slice ([1 2], 11, [4, 4]);
2747 
2748 ## size = [2 2]
2749 %!test test_sparse_slice ([2 2], 11, []);
2750 %!test test_sparse_slice ([2 2], 11, 1);
2751 %!test test_sparse_slice ([2 2], 11, 2);
2752 %!test test_sparse_slice ([2 2], 11, 3);
2753 %!test test_sparse_slice ([2 2], 11, 4);
2754 %!test test_sparse_slice ([2 2], 11, [4, 4]);
2755 # These 2 errors are the same as in the full case
2756 %!error id=Octave:invalid-resize set_slice (sparse (ones ([2 2])), 11, 5)
2757 %!error id=Octave:invalid-resize set_slice (sparse (ones ([2 2])), 11, 6)
2758 
2759 
2760 #### 2d indexing
2761 
2762 ## size = [2 0]
2763 %!test test_sparse_slice ([2 0], 21, []);
2764 %!test test_sparse_slice ([2 0], 21, 1);
2765 %!test test_sparse_slice ([2 0], 21, 2);
2766 %!test test_sparse_slice ([2 0], 21, [2,2]);
2767 %!assert (set_slice (sparse (ones ([2 0])), 21, 3), sparse (3,0))
2768 %!assert (set_slice (sparse (ones ([2 0])), 21, 4), sparse (4,0))
2769 %!test test_sparse_slice ([2 0], 22, []);
2770 %!test test_sparse_slice ([2 0], 22, 1);
2771 %!test test_sparse_slice ([2 0], 22, 2);
2772 %!test test_sparse_slice ([2 0], 22, [2,2]);
2773 %!assert (set_slice (sparse (ones ([2 0])), 22, 3), sparse ([0 0 2;0 0 2])) # sparse different from full
2774 %!assert (set_slice (sparse (ones ([2 0])), 22, 4), sparse ([0 0 0 2;0 0 0 2])) # sparse different from full
2775 
2776 ## size = [0 2]
2777 %!test test_sparse_slice ([0 2], 21, []);
2778 %!test test_sparse_slice ([0 2], 21, 1);
2779 %!test test_sparse_slice ([0 2], 21, 2);
2780 %!test test_sparse_slice ([0 2], 21, [2,2]);
2781 %!assert (set_slice (sparse (ones ([0 2])), 21, 3), sparse ([0 0;0 0;2 2])) # sparse different from full
2782 %!assert (set_slice (sparse (ones ([0 2])), 21, 4), sparse ([0 0;0 0;0 0;2 2])) # sparse different from full
2783 %!test test_sparse_slice ([0 2], 22, []);
2784 %!test test_sparse_slice ([0 2], 22, 1);
2785 %!test test_sparse_slice ([0 2], 22, 2);
2786 %!test test_sparse_slice ([0 2], 22, [2,2]);
2787 %!assert (set_slice (sparse (ones ([0 2])), 22, 3), sparse (0,3))
2788 %!assert (set_slice (sparse (ones ([0 2])), 22, 4), sparse (0,4))
2789 
2790 ## size = [2 1]
2791 %!test test_sparse_slice ([2 1], 21, []);
2792 %!test test_sparse_slice ([2 1], 21, 1);
2793 %!test test_sparse_slice ([2 1], 21, 2);
2794 %!test test_sparse_slice ([2 1], 21, [2,2]);
2795 %!test test_sparse_slice ([2 1], 21, 3);
2796 %!test test_sparse_slice ([2 1], 21, 4);
2797 %!test test_sparse_slice ([2 1], 22, []);
2798 %!test test_sparse_slice ([2 1], 22, 1);
2799 %!test test_sparse_slice ([2 1], 22, 2);
2800 %!test test_sparse_slice ([2 1], 22, [2,2]);
2801 %!test test_sparse_slice ([2 1], 22, 3);
2802 %!test test_sparse_slice ([2 1], 22, 4);
2803 
2804 ## size = [1 2]
2805 %!test test_sparse_slice ([1 2], 21, []);
2806 %!test test_sparse_slice ([1 2], 21, 1);
2807 %!test test_sparse_slice ([1 2], 21, 2);
2808 %!test test_sparse_slice ([1 2], 21, [2,2]);
2809 %!test test_sparse_slice ([1 2], 21, 3);
2810 %!test test_sparse_slice ([1 2], 21, 4);
2811 %!test test_sparse_slice ([1 2], 22, []);
2812 %!test test_sparse_slice ([1 2], 22, 1);
2813 %!test test_sparse_slice ([1 2], 22, 2);
2814 %!test test_sparse_slice ([1 2], 22, [2,2]);
2815 %!test test_sparse_slice ([1 2], 22, 3);
2816 %!test test_sparse_slice ([1 2], 22, 4);
2817 
2818 ## size = [2 2]
2819 %!test test_sparse_slice ([2 2], 21, []);
2820 %!test test_sparse_slice ([2 2], 21, 1);
2821 %!test test_sparse_slice ([2 2], 21, 2);
2822 %!test test_sparse_slice ([2 2], 21, [2,2]);
2823 %!test test_sparse_slice ([2 2], 21, 3);
2824 %!test test_sparse_slice ([2 2], 21, 4);
2825 %!test test_sparse_slice ([2 2], 22, []);
2826 %!test test_sparse_slice ([2 2], 22, 1);
2827 %!test test_sparse_slice ([2 2], 22, 2);
2828 %!test test_sparse_slice ([2 2], 22, [2,2]);
2829 %!test test_sparse_slice ([2 2], 22, 3);
2830 %!test test_sparse_slice ([2 2], 22, 4);
2831 
2832 bug #35570:
2833 
2834 %!assert (speye (3,1)(3:-1:1), sparse ([0; 0; 1]))
2835 
2836 ## Test removing columns (bug #36656)
2837 
2838 %!test
2839 %! s = sparse (magic (5));
2840 %! s(:,2:4) = [];
2841 %! assert (s, sparse (magic (5)(:, [1,5])));
2842 
2843 %!test
2844 %! s = sparse ([], [], [], 1, 1);
2845 %! s(1,:) = [];
2846 %! assert (s, sparse ([], [], [], 0, 1));
2847 
2848 ## Test (bug #37321)
2849 %!test a=sparse (0,0); assert (all (a) == sparse ([1]));
2850 %!test a=sparse (0,1); assert (all (a) == sparse ([1]));
2851 %!test a=sparse (1,0); assert (all (a) == sparse ([1]));
2852 %!test a=sparse (1,0); assert (all (a,2) == sparse ([1]));
2853 %!test a=sparse (1,0); assert (size (all (a,1)), [1 0]);
2854 %!test a=sparse (1,1);
2855 %! assert (all (a) == sparse ([0]));
2856 %! assert (size (all (a)), [1 1]);
2857 %!test a=sparse (2,1);
2858 %! assert (all (a) == sparse ([0]));
2859 %! assert (size (all (a)), [1 1]);
2860 %!test a=sparse (1,2);
2861 %! assert (all (a) == sparse ([0]));
2862 %! assert (size (all (a)), [1 1]);
2863 %!test a=sparse (2,2); assert (isequal (all (a), sparse ([0 0])));
2864 
2865 */
2866 
2867 template <class T>
2868 void
2869 Sparse<T>::print_info (std::ostream& os, const std::string& prefix) const
2870 {
2871  os << prefix << "rep address: " << rep << "\n"
2872  << prefix << "rep->nzmx: " << rep->nzmx << "\n"
2873  << prefix << "rep->nrows: " << rep->nrows << "\n"
2874  << prefix << "rep->ncols: " << rep->ncols << "\n"
2875  << prefix << "rep->data: " << static_cast<void *> (rep->d) << "\n"
2876  << prefix << "rep->ridx: " << static_cast<void *> (rep->r) << "\n"
2877  << prefix << "rep->cidx: " << static_cast<void *> (rep->c) << "\n"
2878  << prefix << "rep->count: " << rep->count << "\n";
2879 }
2880 
2881 #define INSTANTIATE_SPARSE(T, API) \
2882  template class API Sparse<T>;
2883