Mercurial > octave
changeset 27081:c0d8ce61c1c9 stable
Always reserve at least 1 element of storage for sparse matrices (bug #56232).
* Sparse.h (SparseRep (void), SparseRep (octave_idx_type n),
SparseRep (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz = 1)):
Rewrite constructors to always create valid d and r pointers with enough
memory for 1 value. Always initialize nzmx to at least 1.
* Sparse.cc (SparseRep::change_length): Check for nz == 0 and change value to 1
so that sparse array always maintains memory for at least one value.
* amd.cc (Famd): Re-write failing BIST test that now works.
* data.cc (Fnzmax): Document that nzmax will always return at least 1.
* sparse.cc (Fspalloc): Document that 1 element will always be allocated.
author | Rik <rik@octave.org> |
---|---|
date | Wed, 08 May 2019 15:18:32 -0700 |
parents | 227feb6e422a |
children | 9a5b6b929f75 47b81207cb32 |
files | libinterp/corefcn/data.cc libinterp/corefcn/sparse.cc libinterp/dldfcn/amd.cc liboctave/array/Sparse.cc liboctave/array/Sparse.h |
diffstat | 5 files changed, 28 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/data.cc Mon May 06 20:25:15 2019 -0700 +++ b/libinterp/corefcn/data.cc Wed May 08 15:18:32 2019 -0700 @@ -2813,9 +2813,12 @@ @deftypefn {} {@var{n} =} nzmax (@var{SM}) Return the amount of storage allocated to the sparse matrix @var{SM}. -Note that Octave tends to crop unused memory at the first opportunity +Programming Note: Octave tends to crop unused memory at the first opportunity for sparse objects. Thus, in general the value of @code{nzmax} will be the -same as @code{nnz} except for some cases of user-created sparse objects. +same as @code{nnz}, except for some cases of user-created sparse objects. + +Also, note that Octave always reserves storage for at least one value. Thus, +for empty matrices @code{nnz} will report 0, but @code{nzmax} will report 1. @seealso{nnz, spalloc, sparse} @end deftypefn */) {
--- a/libinterp/corefcn/sparse.cc Mon May 06 20:25:15 2019 -0700 +++ b/libinterp/corefcn/sparse.cc Wed May 08 15:18:32 2019 -0700 @@ -267,9 +267,9 @@ @b{and} that the following conditions are met: @itemize -@item the assignment does not decrease nnz (@var{S}). +@item the assignment does not decrease @code{nnz (@var{S})}. -@item after the assignment, nnz (@var{S}) does not exceed @var{nz}. +@item after the assignment, @code{nnz (@var{S})} does not exceed @var{nz}. @item no index is out of bounds. @end itemize @@ -281,6 +281,9 @@ The amount of pre-allocated memory for a given matrix may be queried using the function @code{nzmax}. + +Programming Note: Octave always reserves memory for at least one value, +even if @var{nz} is 0. @seealso{nzmax, sparse} @end deftypefn */) {
--- a/libinterp/dldfcn/amd.cc Mon May 06 20:25:15 2019 -0700 +++ b/libinterp/dldfcn/amd.cc Wed May 08 15:18:32 2019 -0700 @@ -182,7 +182,7 @@ %!shared A, A2, opts %! A = ones (20, 30); %! A2 = ones (30, 30); -%! + %!testif HAVE_AMD %! assert(amd (A2), [1:30]); %! opts.dense = 25; @@ -190,7 +190,9 @@ %! opts.aggressive = 1; %! assert(amd (A2, opts), [1:30]); +%!testif HAVE_AMD +%! assert (amd ([]), zeros (1,0)) + %!error <S must be a square matrix|was unavailable or disabled> amd (A) %!error amd (A2, 2) -%!error <matrix S is corrupted|was unavailable or disabled> amd ([]) */
--- a/liboctave/array/Sparse.cc Mon May 06 20:25:15 2019 -0700 +++ b/liboctave/array/Sparse.cc Wed May 08 15:18:32 2019 -0700 @@ -143,6 +143,9 @@ for (octave_idx_type j = ncols; j > 0 && c[j] > nz; j--) c[j] = nz; + // Always preserve space for 1 element. + nz = (nz > 0 ? nz : 1); + // Skip reallocation if we have less than 1/frac extra elements to discard. static const int frac = 5; if (nz > nzmx || nz < nzmx - nzmx/frac)
--- a/liboctave/array/Sparse.h Mon May 06 20:25:15 2019 -0700 +++ b/liboctave/array/Sparse.h Wed May 08 15:18:32 2019 -0700 @@ -68,20 +68,22 @@ octave::refcount<int> count; SparseRep (void) - : d (nullptr), r (nullptr), c (new octave_idx_type [1] {}), - nzmx (0), nrows (0), ncols (0), count (1) + : d (new T [1]), r (new octave_idx_type [1] {}), + c (new octave_idx_type [1] {}), + nzmx (1), nrows (0), ncols (0), count (1) { } SparseRep (octave_idx_type n) - : d (nullptr), r (nullptr), c (new octave_idx_type [n+1] {}), - nzmx (0), nrows (n), ncols (n), count (1) + : d (new T [1]), r (new octave_idx_type [1] {}), + c (new octave_idx_type [n+1] {}), + nzmx (1), nrows (n), ncols (n), count (1) { } - SparseRep (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz = 0) - : d (nz > 0 ? new T [nz] : nullptr), - r (nz > 0 ? new octave_idx_type [nz] {} : nullptr), - c (new octave_idx_type [nc+1] {}), nzmx (nz), nrows (nr), - ncols (nc), count (1) + SparseRep (octave_idx_type nr, octave_idx_type nc, octave_idx_type nz = 1) + : d (nz > 0 ? new T [nz] : new T [1]), + r (nz > 0 ? new octave_idx_type [nz] {} : new octave_idx_type [1] {}), + c (new octave_idx_type [nc+1] {}), + nzmx (nz > 0 ? nz : 1), nrows (nr), ncols (nc), count (1) { } SparseRep (const SparseRep& a)