GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
sparse.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1998-2025 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
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
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License 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// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <cstdlib>
31#include <string>
32
33#include "variables.h"
34#include "utils.h"
35#include "pager.h"
36#include "defun.h"
37#include "errwarn.h"
38#include "quit.h"
39#include "unwind-prot.h"
40
41#include "ov-re-sparse.h"
42#include "ov-cx-sparse.h"
43#include "ov-bool-sparse.h"
44
46
47DEFUN (issparse, args, ,
48 doc: /* -*- texinfo -*-
49@deftypefn {} {@var{tf} =} issparse (@var{x})
50Return true if @var{x} is a sparse matrix.
51@seealso{ismatrix}
52@end deftypefn */)
53{
54 if (args.length () != 1)
55 print_usage ();
56
57 return ovl (args(0).issparse ());
58}
59
60/*
61%!assert (issparse (sparse (1)), true)
62%!assert (issparse (1), false)
63%!assert (issparse (sparse (false)), true)
64%!assert (issparse (true), false)
65%!test
66%! warning ("off", "Octave:sparse:double-conversion", "local");
67%! assert (issparse (sparse (single ([1 2]))), true);
68%!assert (issparse (single ([1, 2])), false)
69%!assert (issparse (sparse ([1+i, 2]')), true)
70%!assert (issparse ([1+i, 2]'), false)
71
72%!assert (issparse ([]), false)
73%!assert (issparse (sparse([])), true)
74%!assert (issparse ("test"), false)
75%!assert (issparse (struct ("one", {1})), false)
76%!assert (issparse (cell (1)), false)
77
78## Test input validation
79%!error issparse ()
80%!error issparse (1,2)
81*/
82
83DEFUN (sparse, args, ,
84 doc: /* -*- texinfo -*-
85@deftypefn {} {@var{S} =} sparse (@var{A})
86@deftypefnx {} {@var{S} =} sparse (@var{m}, @var{n})
87@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv})
88@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n})
89@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n}, "unique")
90@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n}, @var{nzmax})
91Create a sparse matrix from a full matrix @var{A} or row, column, value
92triplets.
93
94If @var{A} is a full matrix, convert it to a sparse matrix representation,
95removing all zero values in the process. The matrix @var{A} should be of type
96logical or double.
97
98If two inputs @var{m} (rows) and @var{n} (columns) are specified then create
99an empty sparse matrix with the specified dimensions.
100
101Given the integer index vectors @var{i} and @var{j}, and a 1-by-@code{nnz}
102vector of real or complex values @var{sv}, construct the sparse matrix
103@code{S(@var{i}(@var{k}),@var{j}(@var{k})) = @var{sv}(@var{k})} with overall
104dimensions @var{m} and @var{n}. If any of @var{i}, @var{j}, or @var{sv} are
105scalars, they are expanded to have a common size.
106
107If @var{m} or @var{n} are not specified then their values are derived from the
108maximum index in the vectors @var{i} and @var{j} as given by
109@w{@code{@var{m} = max (@var{i})}}, @w{@code{@var{n} = max (@var{j})}}.
110
111@strong{Note}: If multiple values are specified with the same @var{i},
112@var{j} indices, the corresponding value in @var{S} will be the sum of the
113values at the repeated location. @xref{XREFaccumarray,,@code{accumarray}}, for
114an example of how to produce different behavior such as taking the minimum
115instead.
116
117If the option @qcode{"unique"} is given, and more than one value is specified
118at the same @var{i}, @var{j} indices, then only the last specified value will
119be used. For completeness, the option @qcode{"sum"} can be given and will
120be ignored as the default behavior is to sum values at repeated locations.
121
122@code{sparse (@var{m}, @var{n})} will create an empty @var{m}x@var{n} sparse
123matrix and is equivalent to @code{sparse ([], [], [], @var{m}, @var{n})}
124
125The optional final argument reserves space for @var{nzmax} values in the sparse
126array and is useful if the eventual number of nonzero values will be greater
127than the number of values in @var{sv} used during the initial construction of
128the array. @xref{XREFspalloc,,@code{spalloc}}, for more information and usage
129instructions.
130
131Example 1 (convert full matrix to sparse to save memory):
132
133@example
134@group
135x = full (diag (1:1000));
136sizeof (x)
137@result{} 8000000
138s = sparse (x);
139sizeof (xs)
140@result{} 24008
141@end group
142@end example
143
144Example 2 (sum at repeated indices):
145
146@example
147@group
148@var{i} = [1 1 2]; @var{j} = [1 1 2]; @var{sv} = [3 4 5];
149sparse (@var{i}, @var{j}, @var{sv}, 3, 4)
150@result{}
151 Compressed Column Sparse (rows = 3, cols = 4, nnz = 2 [17%])
152
153 (1, 1) -> 7
154 (2, 2) -> 5
155@end group
156@end example
157
158Example 3 ("unique" option):
159
160@example
161@group
162@var{i} = [1 1 2]; @var{j} = [1 1 2]; @var{sv} = [3 4 5];
163sparse (@var{i}, @var{j}, @var{sv}, 3, 4, "unique")
164@result{}
165 Compressed Column Sparse (rows = 3, cols = 4, nnz = 2 [17%])
166
167 (1, 1) -> 4
168 (2, 2) -> 5
169@end group
170@end example
171@seealso{full, accumarray, spalloc, spdiags, speye, spones, sprand, sprandn,
172sprandsym, spconvert, spfun}
173@end deftypefn */)
174{
175 int nargin = args.length ();
176
177 if (nargin == 0 || nargin > 6)
178 print_usage ();
179
180 octave_value retval;
181
182 if (nargin == 1)
183 {
184 octave_value arg = args(0);
185 if (arg.isfloat ())
186 {
187 if (arg.is_single_type ())
188 warning_with_id ("Octave:sparse:double-conversion",
189 "sparse: input array cast to double");
190 if (arg.iscomplex ())
191 retval = arg.sparse_complex_matrix_value ();
192 else
193 retval = arg.sparse_matrix_value ();
194 }
195 else if (arg.islogical ())
196 retval = arg.sparse_bool_matrix_value ();
197 else
198 err_wrong_type_arg ("sparse", arg);
199 }
200 else if (nargin == 2)
201 {
202 octave_idx_type m = args(0).strict_idx_type_value ("sparse: M must be a non-negative integer");
203 octave_idx_type n = args(1).strict_idx_type_value ("sparse: N must be a non-negative integer");
204
205 if (m < 0 || n < 0)
206 error ("sparse: dimensions M and N must be non-negative");
207
208 retval = SparseMatrix (m, n);
209 }
210 else if (nargin >= 3)
211 {
212 bool summation = true;
213 if (nargin > 3 && args(nargin-1).is_string ())
214 {
215 std::string opt = args(nargin-1).string_value ();
216 if (opt == "unique")
217 summation = false;
218 else if (opt == "sum" || opt == "summation")
219 summation = true;
220 else
221 error ("sparse: invalid option: %s", opt.c_str ());
222
223 nargin -= 1;
224 }
225
226 octave_idx_type m, n, nzmax;
227 m = n = nzmax = -1;
228 if (nargin == 6)
229 {
230 nzmax = args(5).idx_type_value ();
231 nargin--;
232 }
233
234 if (nargin == 5)
235 {
236 m = args(3).strict_idx_type_value ("sparse: M must be a non-negative integer");
237 n = args(4).strict_idx_type_value ("sparse: N must be a non-negative integer");
238
239 if (m < 0 || n < 0)
240 error ("sparse: dimensions M and N must be non-negative");
241 }
242
243 int argidx = 0; // index being checked when index_vector throws
244 try
245 {
246 idx_vector i = args(0).index_vector ();
247 argidx = 1;
248 idx_vector j = args(1).index_vector ();
249
250 octave_value arg = args(2); // temp var for code readability
251 if (arg.isfloat ())
252 {
253 if (arg.is_single_type ())
254 warning_with_id ("Octave:sparse:double-conversion",
255 "sparse: input array cast to double");
256 if (arg.iscomplex ())
258 i, j, m, n, summation, nzmax);
259 else
260 retval = SparseMatrix (arg.array_value (),
261 i, j, m, n, summation, nzmax);
262 }
263 else if (arg.islogical ())
264 retval = SparseBoolMatrix (arg.bool_array_value (),
265 i, j, m, n, summation, nzmax);
266 else
267 err_wrong_type_arg ("sparse", arg);
268 }
269 catch (index_exception& ie)
270 {
271 // Rethrow to allow more info to be reported later.
272 ie.set_pos_if_unset (2, argidx+1);
273 throw;
274 }
275 }
276
277 return retval;
278}
279
280/*
281## Tests for sparse constructor are in test/sparse.tst
282%!assert (1)
283*/
284
285DEFUN (spalloc, args, ,
286 doc: /* -*- texinfo -*-
287@deftypefn {} {@var{s} =} spalloc (@var{m}, @var{n}, @var{nz})
288Create an @var{m}-by-@var{n} sparse matrix with pre-allocated space for at
289most @var{nz} nonzero elements.
290
291This is useful for building a matrix incrementally by a sequence of indexed
292assignments. Subsequent indexed assignments after @code{spalloc} will reuse
293the pre-allocated memory, provided they are of one of the simple forms
294
295@itemize
296@item @code{@var{s}(I:J) = @var{x}}
297
298@item @code{@var{s}(:,I:J) = @var{x}}
299
300@item @code{@var{s}(K:L,I:J) = @var{x}}
301@end itemize
302
303@b{and} that the following conditions are met:
304
305@itemize
306@item the assignment does not decrease @code{nnz (@var{S})}.
307
308@item after the assignment, @code{nnz (@var{S})} does not exceed @var{nz}.
309
310@item no index is out of bounds.
311@end itemize
312
313Partial movement of data may still occur, but in general the assignment will
314be more memory and time efficient under these circumstances. In particular,
315it is possible to efficiently build a pre-allocated sparse matrix from a
316contiguous block of columns.
317
318The amount of pre-allocated memory for a given matrix may be queried using
319the function @code{nzmax}.
320
321Programming Note: Octave always reserves memory for at least one value,
322even if @var{nz} is 0.
323@seealso{nzmax, sparse}
324@end deftypefn */)
325{
326 int nargin = args.length ();
327
328 if (nargin < 2 || nargin > 3)
329 print_usage ();
330
331 octave_idx_type m = args(0).idx_type_value ();
332 octave_idx_type n = args(1).idx_type_value ();
333
334 octave_idx_type nz = 0;
335 if (nargin == 3)
336 nz = args(2).idx_type_value ();
337
338 if (m < 0 || n < 0 || nz < 0)
339 error ("spalloc: M, N, and NZ must be non-negative");
340
341 return ovl (SparseMatrix (dim_vector (m, n), nz));
342}
343
344/*
345%!assert (issparse (spalloc (1,1)))
346%!assert (spalloc (1,1), sparse (1,1))
347%!test
348%! s = spalloc (1,1,5);
349%! assert (s, sparse (1,1));
350%! assert (nzmax (s), 5);
351%!assert (spalloc (1,2), sparse (1,2))
352%!assert (spalloc (1,2,2), sparse (1,2))
353%!assert (spalloc (2,1), sparse (2,1))
354%!assert (spalloc (2,1,2), sparse (2,1))
355
356%!error spalloc ()
357%!error spalloc (1)
358%!error spalloc (1,2,3,4)
359%!error <M, N, and NZ must be non-negative> spalloc (-1, 1, 1)
360%!error <M, N, and NZ must be non-negative> spalloc (1, -1, 1)
361%!error <M, N, and NZ must be non-negative> spalloc (1, 1, -1)
362*/
363
364OCTAVE_END_NAMESPACE(octave)
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:90
void set_pos_if_unset(octave_idx_type nd_arg, octave_idx_type dim_arg)
bool isfloat() const
Definition ov.h:701
boolNDArray bool_array_value(bool warn=false) const
Definition ov.h:900
SparseMatrix sparse_matrix_value(bool frc_str_conv=false) const
Definition ov.h:909
ComplexNDArray complex_array_value(bool frc_str_conv=false) const
Definition ov.h:884
bool is_single_type() const
Definition ov.h:698
bool iscomplex() const
Definition ov.h:741
SparseBoolMatrix sparse_bool_matrix_value(bool warn=false) const
Definition ov.h:916
NDArray array_value(bool frc_str_conv=false) const
Definition ov.h:865
octave_idx_type length() const
SparseComplexMatrix sparse_complex_matrix_value(bool frc_str_conv=false) const
Definition ov.h:913
bool islogical() const
Definition ov.h:735
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage()
Definition defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition defun.h:56
void warning_with_id(const char *id, const char *fmt,...)
Definition error.cc:1093
void error(const char *fmt,...)
Definition error.cc:1003
void err_wrong_type_arg(const char *name, const char *s)
Definition errwarn.cc:166
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition ovl.h:217