changeset 32312:66a8907102c5 stable

correctly load all-zero sparse matrices from text files (bug #64696) Since changeset c0d8ce61c1c9, sparse arrays have reserved at least one element of storage so nzmax is always greater than 0. That causes trouble for the read_sparse_matrix function which only reads a set of triplets (ROW, COL, VAL) from the input stream and assumes that the sparse array that it receives and fills with values has been initialized with exactly the correct amount of storage to hold all the values in the file (it assumes that nnz is the same as nzmax). But that's not the case for sparse arrays created with nnz equal to 0 and read_sparse_matrix attempts to read an element when it should not. We can't avoid the problem by calling Sparse<T>::nnz in read_sparse_matrix because it returns zero for a newly allocated sparse array and won't be correct until the values are stored in the array. Instead, we have to skip reading array elements in the load_ascii function if NZ is zero. * ov-base-sparse.cc (octave_base_sparse<T>::load_ascii): Skip input of matrix elements if NNZ is zero. New test.
author John W. Eaton <jwe@octave.org>
date Tue, 19 Sep 2023 14:00:19 -0400
parents 68f3ec939f92
children 091d5c1ec4ef ccca7e42adcb
files libinterp/octave-value/ov-base-sparse.cc
diffstat 1 files changed, 22 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-base-sparse.cc	Thu Sep 14 14:13:10 2023 -0400
+++ b/libinterp/octave-value/ov-base-sparse.cc	Tue Sep 19 14:00:19 2023 -0400
@@ -429,16 +429,35 @@
 
   T tmp (nr, nc, nz);
 
-  is >> tmp;
+  if (nz > 0)
+    {
+      is >> tmp;
 
-  if (! is)
-    error ("load: failed to load matrix constant");
+      if (! is)
+        error ("load: failed to load matrix constant");
+    }
 
   matrix = tmp;
 
   return true;
 }
 
+/*
+%!test <64696>
+%! A = B = sparse (1, 2);
+%! assert (nnz (A), 0);
+%! assert (nnz (B), 0);
+%! txt_file = [tempname(), ".dat"];
+%! unwind_protect
+%! save (txt_file, "A", "B");
+%!   s = load (txt_file);
+%! unwind_protect_cleanup
+%!   unlink (txt_file);
+%! end_unwind_protect
+%! assert (s.A, A);
+%! assert (s.B, B);
+*/
+
 template <typename T>
 octave_value
 octave_base_sparse<T>::fast_elem_extract (octave_idx_type n) const