Mercurial > octave
changeset 21256:a93fa1b0796e stable
Avoid overflow while reshaping large sparse matrices (bug #42850).
* Sparse.cc (reshape): track quotient and remainder of (i*old_nr)
divided by new_nr, instead of evaluating i*old_nr explicitly.
author | Lachlan Andrew <lachlanbis@gmail.com> |
---|---|
date | Sat, 16 Jan 2016 14:03:45 +1100 |
parents | 6209f428426c |
children | af8118df8292 8990b8c4f00a |
files | liboctave/array/Sparse.cc |
diffstat | 1 files changed, 28 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/array/Sparse.cc Sat Jan 09 20:40:49 2016 +1100 +++ b/liboctave/array/Sparse.cc Sat Jan 16 14:03:45 2016 +1100 @@ -842,22 +842,35 @@ octave_idx_type kk = 0; retval.xcidx (0) = 0; + // quotient and remainder of i * old_nr divided by new_nr + // Track them individually to avoid overflow (bug #42850). + octave_idx_type i_old_qu = 0; + octave_idx_type i_old_rm = static_cast<octave_idx_type> (-old_nr); for (octave_idx_type i = 0; i < old_nc; i++) - for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) - { - octave_idx_type tmp = i * old_nr + ridx (j); - if (tmp < 0) - (*current_liboctave_error_handler) - ("reshape: overflow in octave_idx_type prevents reshaping array"); - - octave_idx_type ii = tmp % new_nr; - octave_idx_type jj = (tmp - ii) / new_nr; - for (octave_idx_type k = kk; k < jj; k++) - retval.xcidx (k+1) = j; - kk = jj; - retval.xdata (j) = data (j); - retval.xridx (j) = ii; - } + { + i_old_rm += old_nr; + if (i_old_rm >= new_nr) + { + i_old_qu += i_old_rm / new_nr; + i_old_rm = i_old_rm % new_nr; + } + for (octave_idx_type j = cidx (i); j < cidx (i+1); j++) + { + octave_idx_type ii, jj; + ii = (i_old_rm + ridx (j)) % new_nr; + jj = i_old_qu + (i_old_rm + ridx (j)) / new_nr; + + // Original calculation subject to overflow + // ii = (i*old_nr + ridx (j)) % new_nr + // jj = (i*old_nr + ridx (j)) / new_nr + + for (octave_idx_type k = kk; k < jj; k++) + retval.xcidx (k+1) = j; + kk = jj; + retval.xdata (j) = data (j); + retval.xridx (j) = ii; + } + } for (octave_idx_type k = kk; k < new_nc; k++) retval.xcidx (k+1) = new_nnz; }