GNU Octave 11.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-2026 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}, @var{j}
112indices, the corresponding value in @var{S} will be the sum of the values at
113the repeated location. @xref{XREFaccumarray,,accumarray}, for an example of
114how to produce different behavior such as taking the minimum instead.
115
116If the option @qcode{"unique"} is given, and more than one value is specified
117at the same @var{i}, @var{j} indices, then only the last specified value will
118be used. For completeness, the option @qcode{"sum"} can be given and will
119be ignored as the default behavior is to sum values at repeated locations.
120
121@code{sparse (@var{m}, @var{n})} will create an empty @var{m}x@var{n} sparse
122matrix and is equivalent to @code{sparse ([], [], [], @var{m}, @var{n})}
123
124The optional final argument reserves space for @var{nzmax} values in the sparse
125array and is useful if the eventual number of nonzero values will be greater
126than the number of values in @var{sv} used during the initial construction of
127the array. @xref{XREFspalloc,,spalloc}, for more information and usage
128instructions.
129
130Example 1 (convert full matrix to sparse to save memory):
131
132@example
133@group
134x = full (diag (1:1000));
135sizeof (x)
136@xresult{} 8000000
137s = sparse (x);
138sizeof (xs)
139@xresult{} 24008
140@end group
141@end example
142
143Example 2 (sum at repeated indices):
144
145@example
146@group
147@var{i} = [1 1 2]; @var{j} = [1 1 2]; @var{sv} = [3 4 5];
148sparse (@var{i}, @var{j}, @var{sv}, 3, 4)
149@xresult{}
150 Compressed Column Sparse (rows = 3, cols = 4, nnz = 2 [17%])
151
152 (1, 1) -> 7
153 (2, 2) -> 5
154@end group
155@end example
156
157Example 3 ("unique" option):
158
159@example
160@group
161@var{i} = [1 1 2]; @var{j} = [1 1 2]; @var{sv} = [3 4 5];
162sparse (@var{i}, @var{j}, @var{sv}, 3, 4, "unique")
163@xresult{}
164 Compressed Column Sparse (rows = 3, cols = 4, nnz = 2 [17%])
165
166 (1, 1) -> 4
167 (2, 2) -> 5
168@end group
169@end example
170@seealso{full, accumarray, spalloc, spdiags, speye, spones, sprand, sprandn,
171sprandsym, spconvert, spfun}
172@end deftypefn */)
173{
174 int nargin = args.length ();
175
176 if (nargin == 0 || nargin > 6)
177 print_usage ();
178
179 octave_value retval;
180
181 if (nargin == 1)
182 {
183 octave_value arg = args(0);
184 if (arg.isfloat ())
185 {
186 if (arg.is_single_type ())
187 warning_with_id ("Octave:sparse:double-conversion",
188 "sparse: input array cast to double");
189 if (arg.iscomplex ())
190 retval = arg.sparse_complex_matrix_value ();
191 else
192 retval = arg.sparse_matrix_value ();
193 }
194 else if (arg.islogical ())
195 retval = arg.sparse_bool_matrix_value ();
196 else
197 err_wrong_type_arg ("sparse", arg);
198 }
199 else if (nargin == 2)
200 {
201 octave_idx_type m = args(0).strict_idx_type_value ("sparse: M must be a non-negative integer");
202 octave_idx_type n = args(1).strict_idx_type_value ("sparse: N must be a non-negative integer");
203
204 if (m < 0 || n < 0)
205 error ("sparse: dimensions M and N must be non-negative");
206
207 retval = SparseMatrix (m, n);
208 }
209 else if (nargin >= 3)
210 {
211 bool summation = true;
212 if (nargin > 3 && args(nargin-1).is_string ())
213 {
214 std::string opt = args(nargin-1).string_value ();
215 if (opt == "unique")
216 summation = false;
217 else if (opt == "sum" || opt == "summation")
218 summation = true;
219 else
220 error ("sparse: invalid option: %s", opt.c_str ());
221
222 nargin -= 1;
223 }
224
225 octave_idx_type m, n, nzmax;
226 m = n = nzmax = -1;
227 if (nargin == 6)
228 {
229 nzmax = args(5).idx_type_value ();
230 nargin--;
231 }
232
233 if (nargin == 5)
234 {
235 m = args(3).strict_idx_type_value ("sparse: M must be a non-negative integer");
236 n = args(4).strict_idx_type_value ("sparse: N must be a non-negative integer");
237
238 if (m < 0 || n < 0)
239 error ("sparse: dimensions M and N must be non-negative");
240 }
241
242 int argidx = 0; // index being checked when index_vector throws
243 try
244 {
245 idx_vector i = args(0).index_vector ();
246 argidx = 1;
247 idx_vector j = args(1).index_vector ();
248
249 octave_value arg = args(2); // temp var for code readability
250 if (arg.isfloat ())
251 {
252 if (arg.is_single_type ())
253 warning_with_id ("Octave:sparse:double-conversion",
254 "sparse: input array cast to double");
255 if (arg.iscomplex ())
257 i, j, m, n, summation, nzmax);
258 else
259 retval = SparseMatrix (arg.array_value (),
260 i, j, m, n, summation, nzmax);
261 }
262 else if (arg.islogical ())
263 retval = SparseBoolMatrix (arg.bool_array_value (),
264 i, j, m, n, summation, nzmax);
265 else
266 err_wrong_type_arg ("sparse", arg);
267 }
268 catch (index_exception& ie)
269 {
270 // Rethrow to allow more info to be reported later.
271 ie.set_pos_if_unset (2, argidx+1);
272 throw;
273 }
274 }
275
276 return retval;
277}
278
279/*
280## Tests for sparse constructor are in test/sparse.tst
281%!assert (1)
282*/
283
284DEFUN (spalloc, args, ,
285 doc: /* -*- texinfo -*-
286@deftypefn {} {@var{s} =} spalloc (@var{m}, @var{n}, @var{nz})
287Create an @var{m}-by-@var{n} sparse matrix with pre-allocated space for at
288most @var{nz} nonzero elements.
289
290This is useful for building a matrix incrementally by a sequence of indexed
291assignments. Subsequent indexed assignments after @code{spalloc} will reuse
292the pre-allocated memory, provided they are of one of the simple forms
293
294@itemize
295@item @code{@var{s}(I:J) = @var{x}}
296
297@item @code{@var{s}(:,I:J) = @var{x}}
298
299@item @code{@var{s}(K:L,I:J) = @var{x}}
300@end itemize
301
302@b{and} that the following conditions are met:
303
304@itemize
305@item the assignment does not decrease @code{nnz (@var{S})}.
306
307@item after the assignment, @code{nnz (@var{S})} does not exceed @var{nz}.
308
309@item no index is out of bounds.
310@end itemize
311
312Partial movement of data may still occur, but in general the assignment will
313be more memory and time efficient under these circumstances. In particular,
314it is possible to efficiently build a pre-allocated sparse matrix from a
315contiguous block of columns.
316
317The amount of pre-allocated memory for a given matrix may be queried using
318the function @code{nzmax}.
319
320Programming Note: Octave always reserves memory for at least one value,
321even if @var{nz} is 0.
322@seealso{nzmax, sparse}
323@end deftypefn */)
324{
325 int nargin = args.length ();
326
327 if (nargin < 2 || nargin > 3)
328 print_usage ();
329
330 octave_idx_type m = args(0).idx_type_value ();
331 octave_idx_type n = args(1).idx_type_value ();
332
333 octave_idx_type nz = 0;
334 if (nargin == 3)
335 nz = args(2).idx_type_value ();
336
337 if (m < 0 || n < 0 || nz < 0)
338 error ("spalloc: M, N, and NZ must be non-negative");
339
340 return ovl (SparseMatrix (dim_vector (m, n), nz));
341}
342
343/*
344%!assert (issparse (spalloc (1,1)))
345%!assert (spalloc (1,1), sparse (1,1))
346%!test
347%! s = spalloc (1,1,5);
348%! assert (s, sparse (1,1));
349%! assert (nzmax (s), 5);
350%!assert (spalloc (1,2), sparse (1,2))
351%!assert (spalloc (1,2,2), sparse (1,2))
352%!assert (spalloc (2,1), sparse (2,1))
353%!assert (spalloc (2,1,2), sparse (2,1))
354
355%!error spalloc ()
356%!error spalloc (1)
357%!error spalloc (1,2,3,4)
358%!error <M, N, and NZ must be non-negative> spalloc (-1, 1, 1)
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*/
362
363OCTAVE_END_NAMESPACE(octave)
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:92
void set_pos_if_unset(octave_idx_type nd_arg, octave_idx_type dim_arg)
bool isfloat() const
Definition ov.h:699
boolNDArray bool_array_value(bool warn=false) const
Definition ov.h:898
SparseMatrix sparse_matrix_value(bool frc_str_conv=false) const
Definition ov.h:907
ComplexNDArray complex_array_value(bool frc_str_conv=false) const
Definition ov.h:882
bool is_single_type() const
Definition ov.h:696
bool iscomplex() const
Definition ov.h:739
SparseBoolMatrix sparse_bool_matrix_value(bool warn=false) const
Definition ov.h:914
NDArray array_value(bool frc_str_conv=false) const
Definition ov.h:863
octave_idx_type length() const
SparseComplexMatrix sparse_complex_matrix_value(bool frc_str_conv=false) const
Definition ov.h:911
bool islogical() const
Definition ov.h:733
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:1098
void error(const char *fmt,...)
Definition error.cc:1008
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