# HG changeset patch # User David Bateman # Date 1337385561 -7200 # Node ID f2e72944847b9ec7cec586faa4c72ea91eb53881 # Parent 997e05334f71269f16017ceb06a52cf33feced18 Ensure sparse constructors have valid ridx and data indices even if they are zero matrices (bug #36104) diff --git a/liboctave/Sparse.cc b/liboctave/Sparse.cc --- a/liboctave/Sparse.cc +++ b/liboctave/Sparse.cc @@ -235,7 +235,7 @@ (*current_liboctave_error_handler) ("Sparse::Sparse (const dim_vector&): dimension mismatch"); else - rep = new typename Sparse::SparseRep (dv(0), dv(1)); + rep = new typename Sparse::SparseRep (dv(0), dv(1), 0); } template @@ -301,11 +301,10 @@ (*current_liboctave_error_handler) ("sparse: column index %d out of bound %d", r.extent (nc), nc); - rep = new SparseRep (nr, nc); + rep = new typename Sparse::SparseRep (nr, nc, (nzm > 0 ? nzm : 0)); dimensions = dim_vector (nr, nc); - octave_idx_type n = a.numel (), rl = r.length (nr), cl = c.length (nc); bool a_scalar = n == 1; if (a_scalar) @@ -324,6 +323,7 @@ if (n == 1 && a(0) != T ()) { change_capacity (nzm > 1 ? nzm : 1); + xcidx(0) = 0; xridx(0) = r(0); xdata(0) = a(0); for (octave_idx_type j = 0; j < nc; j++) @@ -352,6 +352,7 @@ new_nz += rd[i-1] != rd[i]; // Allocate result. change_capacity (nzm > new_nz ? nzm : new_nz); + xcidx (0) = 0; xcidx (1) = new_nz; octave_idx_type *rri = ridx (); T *rrd = data (); @@ -494,6 +495,7 @@ new_nz += rd[i-1] != rd[i]; // Allocate result. change_capacity (nzm > new_nz ? nzm : new_nz); + xcidx(0) = 0; xcidx(1) = new_nz; octave_idx_type *rri = ridx (); T *rrd = data (); # HG changeset patch # User John W. Eaton # Date 1340304125 14400 # Node ID 4663cc835c65873fe12b599bcab11ba4a8f5fb87 # Parent f2e72944847b9ec7cec586faa4c72ea91eb53881 Special-case removing rows or columns from empty sparse matrices * Sparse.cc (Sparse::delete_elements): Don't attempt to preserve elements if nnz = 0; simply reshape if number of rows or columns is zero. diff --git a/liboctave/Sparse.cc b/liboctave/Sparse.cc --- a/liboctave/Sparse.cc +++ b/liboctave/Sparse.cc @@ -1240,16 +1240,31 @@ gripe_del_index_out_of_range (false, idx_j.extent (nc), nc); else if (idx_j.is_cont_range (nc, lb, ub)) { - const Sparse tmp = *this; - octave_idx_type lbi = tmp.cidx(lb), ubi = tmp.cidx(ub), new_nz = nz - (ubi - lbi); - *this = Sparse (nr, nc - (ub - lb), new_nz); - copy_or_memcpy (lbi, tmp.data (), data ()); - copy_or_memcpy (lbi, tmp.ridx (), ridx ()); - copy_or_memcpy (nz - ubi, tmp.data () + ubi, xdata () + lbi); - copy_or_memcpy (nz - ubi, tmp.ridx () + ubi, xridx () + lbi); - copy_or_memcpy (lb, tmp.cidx () + 1, cidx () + 1); - mx_inline_sub (nc - ub, xcidx () + lb + 1, - tmp.cidx () + ub + 1, ubi - lbi); + if (lb == 0 && ub == nc) + { + // Delete all rows and columns. + *this = Sparse (nr, 0); + } + else if (nz == 0) + { + // No elements to preserve; adjust dimensions. + *this = Sparse (nr, nc - (ub - lb)); + } + else + { + const Sparse tmp = *this; + octave_idx_type lbi = tmp.cidx(lb), ubi = tmp.cidx(ub), + new_nz = nz - (ubi - lbi); + + *this = Sparse (nr, nc - (ub - lb), new_nz); + copy_or_memcpy (lbi, tmp.data (), data ()); + copy_or_memcpy (lbi, tmp.ridx (), ridx ()); + copy_or_memcpy (nz - ubi, tmp.data () + ubi, xdata () + lbi); + copy_or_memcpy (nz - ubi, tmp.ridx () + ubi, xridx () + lbi); + copy_or_memcpy (lb, tmp.cidx () + 1, cidx () + 1); + mx_inline_sub (nc - ub, xcidx () + lb + 1, + tmp.cidx () + ub + 1, ubi - lbi); + } } else *this = index (idx_i, idx_j.complement (nc)); @@ -1262,24 +1277,40 @@ gripe_del_index_out_of_range (false, idx_i.extent (nr), nr); else if (idx_i.is_cont_range (nr, lb, ub)) { - // This is more memory-efficient than the approach below. - const Sparse tmpl = index (idx_vector (0, lb), idx_j); - const Sparse tmpu = index (idx_vector (ub, nr), idx_j); - *this = Sparse (nr - (ub - lb), nc, tmpl.nnz () + tmpu.nnz ()); - for (octave_idx_type j = 0, k = 0; j < nc; j++) + if (lb == 0 && ub == nr) { - for (octave_idx_type i = tmpl.cidx(j); i < tmpl.cidx(j+1); i++) + // Delete all rows and columns. + *this = Sparse (0, nc); + } + else if (nz == 0) + { + // No elements to preserve; adjust dimensions. + *this = Sparse (nr - (ub - lb), nc); + } + else + { + // This is more memory-efficient than the approach below. + const Sparse tmpl = index (idx_vector (0, lb), idx_j); + const Sparse tmpu = index (idx_vector (ub, nr), idx_j); + *this = Sparse (nr - (ub - lb), nc, + tmpl.nnz () + tmpu.nnz ()); + for (octave_idx_type j = 0, k = 0; j < nc; j++) { - xdata(k) = tmpl.data(i); - xridx(k++) = tmpl.ridx(i); + for (octave_idx_type i = tmpl.cidx(j); i < tmpl.cidx(j+1); + i++) + { + xdata(k) = tmpl.data(i); + xridx(k++) = tmpl.ridx(i); + } + for (octave_idx_type i = tmpu.cidx(j); i < tmpu.cidx(j+1); + i++) + { + xdata(k) = tmpu.data(i); + xridx(k++) = tmpu.ridx(i) + lb; + } + + xcidx(j+1) = k; } - for (octave_idx_type i = tmpu.cidx(j); i < tmpu.cidx(j+1); i++) - { - xdata(k) = tmpu.data(i); - xridx(k++) = tmpu.ridx(i) + lb; - } - - xcidx(j+1) = k; } } else