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 /*
2 
3 Copyright (C) 2004-2013 David Bateman
4 Copyright (C) 1998-2004 Andy Adler
5 Copyright (C) 2010 VZLU Prague
6 
7 This file is part of Octave.
8 
9 Octave is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <cstdlib>
30 #include <string>
31 
32 #include "variables.h"
33 #include "utils.h"
34 #include "pager.h"
35 #include "defun.h"
36 #include "gripes.h"
37 #include "quit.h"
38 #include "unwind-prot.h"
39 
40 #include "ov-re-sparse.h"
41 #include "ov-cx-sparse.h"
42 #include "ov-bool-sparse.h"
43 
44 DEFUN (issparse, args, ,
45  "-*- texinfo -*-\n\
46 @deftypefn {Built-in Function} {} issparse (@var{x})\n\
47 Return true if @var{x} is a sparse matrix.\n\
48 @seealso{ismatrix}\n\
49 @end deftypefn")
50 {
51  if (args.length () != 1)
52  {
53  print_usage ();
54  return octave_value ();
55  }
56  else
57  return octave_value (args(0).is_sparse_type ());
58 }
59 
60 DEFUN (sparse, args, ,
61  "-*- texinfo -*-\n\
62 @deftypefn {Built-in Function} {@var{s} =} sparse (@var{a})\n\
63 @deftypefnx {Built-in Function} {@var{s} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n}, @var{nzmax})\n\
64 @deftypefnx {Built-in Function} {@var{s} =} sparse (@var{i}, @var{j}, @var{sv})\n\
65 @deftypefnx {Built-in Function} {@var{s} =} sparse (@var{i}, @var{j}, @var{s}, @var{m}, @var{n}, \"unique\")\n\
66 @deftypefnx {Built-in Function} {@var{s} =} sparse (@var{m}, @var{n})\n\
67 Create a sparse matrix from the full matrix or row, column, value triplets.\n\
68 If @var{a} is a full matrix, convert it to a sparse matrix representation,\n\
69 removing all zero values in the process.\n\
70 \n\
71 Given the integer index vectors @var{i} and @var{j}, a 1-by-@code{nnz} vector\n\
72 of real of complex values @var{sv}, overall dimensions @var{m} and @var{n}\n\
73 of the sparse matrix. The argument @code{nzmax} is ignored but accepted for\n\
74 compatibility with @sc{matlab}. If @var{m} or @var{n} are not specified\n\
75 their values are derived from the maximum index in the vectors @var{i} and\n\
76 @var{j} as given by @code{@var{m} = max (@var{i})},\n\
77 @code{@var{n} = max (@var{j})}.\n\
78 \n\
79 @strong{Note}: if multiple values are specified with the same\n\
80 @var{i}, @var{j} indices, the corresponding values in @var{s} will\n\
81 be added. See @code{accumarray} for an example of how to produce different\n\
82 behavior, such as taking the minimum instead.\n\
83 \n\
84 The following are all equivalent:\n\
85 \n\
86 @example\n\
87 @group\n\
88 s = sparse (i, j, s, m, n)\n\
89 s = sparse (i, j, s, m, n, \"summation\")\n\
90 s = sparse (i, j, s, m, n, \"sum\")\n\
91 @end group\n\
92 @end example\n\
93 \n\
94 Given the option @qcode{\"unique\"}, if more than two values are specified\n\
95 for the same @var{i}, @var{j} indices, the last specified value will be\n\
96 used.\n\
97 \n\
98 @code{sparse (@var{m}, @var{n})} is equivalent to\n\
99 @code{sparse ([], [], [], @var{m}, @var{n}, 0)}\n\
100 \n\
101 If any of @var{sv}, @var{i} or @var{j} are scalars, they are expanded\n\
102 to have a common size.\n\
103 @seealso{full, accumarray}\n\
104 @end deftypefn")
105 {
106  octave_value retval;
107  int nargin = args.length ();
108 
109  // Temporarily disable sparse_auto_mutate if set (it's obsolete anyway).
110  unwind_protect frame;
112  Vsparse_auto_mutate = false;
113 
114  if (nargin == 1)
115  {
116  octave_value arg = args (0);
117  if (arg.is_bool_type ())
118  retval = arg.sparse_bool_matrix_value ();
119  else if (arg.is_complex_type ())
120  retval = arg.sparse_complex_matrix_value ();
121  else if (arg.is_numeric_type ())
122  retval = arg.sparse_matrix_value ();
123  else
124  gripe_wrong_type_arg ("sparse", arg);
125  }
126  else if (nargin == 2)
127  {
128  octave_idx_type m = 0, n = 0;
129  if (args(0).is_scalar_type () && args(1).is_scalar_type ())
130  {
131  m = args(0).idx_type_value ();
132  n = args(1).idx_type_value ();
133  }
134  else
135  error ("sparse: dimensions M,N must be scalar");
136 
137  if (! error_state)
138  {
139  if (m >= 0 && n >= 0)
140  retval = SparseMatrix (m, n);
141  else
142  error ("sparse: dimensions M,N must be positive or zero");
143  }
144  }
145  else if (nargin >= 3)
146  {
147  bool summation = true;
148  if (nargin > 3 && args(nargin-1).is_string ())
149  {
150  std::string opt = args(nargin-1).string_value ();
151  if (opt == "unique")
152  summation = false;
153  else if (opt == "sum" || opt == "summation")
154  summation = true;
155  else
156  error ("sparse: invalid option: %s", opt.c_str ());
157 
158  nargin -= 1;
159  }
160 
161  if (! error_state)
162  {
163  octave_idx_type m = -1, n = -1, nzmax = -1;
164  if (nargin == 6)
165  {
166  nzmax = args(5).idx_type_value ();
167  nargin --;
168  }
169 
170  if (nargin == 5)
171  {
172  if (args(3).is_scalar_type () && args(4).is_scalar_type ())
173  {
174  m = args(3).idx_type_value ();
175  n = args(4).idx_type_value ();
176  }
177  else
178  error ("sparse: expecting scalar dimensions");
179 
180 
181  if (! error_state && (m < 0 || n < 0))
182  error ("sparse: dimensions must be non-negative");
183  }
184  else if (nargin != 3)
185  print_usage ();
186 
187  if (! error_state)
188  {
189  idx_vector i = args(0).index_vector ();
190  idx_vector j = args(1).index_vector ();
191 
192  if (args(2).is_bool_type ())
193  retval = SparseBoolMatrix (args(2).bool_array_value (), i, j,
194  m, n, summation, nzmax);
195  else if (args(2).is_complex_type ())
196  retval = SparseComplexMatrix (args(2).complex_array_value (),
197  i, j, m, n, summation, nzmax);
198  else if (args(2).is_numeric_type ())
199  retval = SparseMatrix (args(2).array_value (), i, j,
200  m, n, summation, nzmax);
201  else
202  gripe_wrong_type_arg ("sparse", args(2));
203  }
204 
205  }
206  }
207 
208  return retval;
209 }
210 
211 DEFUN (spalloc, args, ,
212  "-*- texinfo -*-\n\
213 @deftypefn {Built-in Function} {@var{s} =} spalloc (@var{m}, @var{n}, @var{nz})\n\
214 Create an @var{m}-by-@var{n} sparse matrix with pre-allocated space for at\n\
215 most @var{nz} nonzero elements. This is useful for building the matrix\n\
216 incrementally by a sequence of indexed assignments. Subsequent indexed\n\
217 assignments will reuse the pre-allocated memory, provided they are of one of\n\
218 the simple forms\n\
219 \n\
220 @itemize\n\
221 @item @code{@var{s}(I:J) = @var{x}}\n\
222 \n\
223 @item @code{@var{s}(:,I:J) = @var{x}}\n\
224 \n\
225 @item @code{@var{s}(K:L,I:J) = @var{x}}\n\
226 @end itemize\n\
227 \n\
228 @b{and} that the following conditions are met:\n\
229 \n\
230 @itemize\n\
231 @item the assignment does not decrease nnz (@var{S}).\n\
232 \n\
233 @item after the assignment, nnz (@var{S}) does not exceed @var{nz}.\n\
234 \n\
235 @item no index is out of bounds.\n\
236 @end itemize\n\
237 \n\
238 Partial movement of data may still occur, but in general the assignment will\n\
239 be more memory and time-efficient under these circumstances. In particular,\n\
240 it is possible to efficiently build a pre-allocated sparse matrix from\n\
241 contiguous block of columns.\n\
242 \n\
243 The amount of pre-allocated memory for a given matrix may be queried using\n\
244 the function @code{nzmax}.\n\
245 @seealso{nzmax, sparse}\n\
246 @end deftypefn")
247 {
248  octave_value retval;
249  int nargin = args.length ();
250 
251  if (nargin == 2 || nargin == 3)
252  {
253  octave_idx_type m = args(0).idx_type_value ();
254  octave_idx_type n = args(1).idx_type_value ();
255  octave_idx_type nz = 0;
256  if (nargin == 3)
257  nz = args(2).idx_type_value ();
258  if (error_state)
259  ;
260  else if (m >= 0 && n >= 0 && nz >= 0)
261  retval = SparseMatrix (dim_vector (m, n), nz);
262  else
263  error ("spalloc: M,N,NZ must be non-negative");
264  }
265  else
266  print_usage ();
267 
268  return retval;
269 }