changeset 21257:af8118df8292

maint: merge stable to default.
author Rik <rik@octave.org>
date Sun, 14 Feb 2016 09:22:13 -0800
parents 076876f0a83a (current diff) a93fa1b0796e (diff)
children b248c28d9a7b
files liboctave/array/Sparse.cc
diffstat 1 files changed, 32 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/array/Sparse.cc	Fri Feb 12 18:07:07 2016 -0800
+++ b/liboctave/array/Sparse.cc	Sun Feb 14 09:22:13 2016 -0800
@@ -815,22 +815,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;
         }
@@ -2024,10 +2037,10 @@
                   if (new_nz > nz)
                     {
                       // Make room first.
-                      std::copy (data () + ui, data () + nz,
-                                 data () + li + rnz);
-                      std::copy (ridx () + ui, ridx () + nz,
-                                 ridx () + li + rnz);
+                      std::copy_backward (data () + ui, data () + nz,
+                                          data () + new_nz);
+                      std::copy_backward (ridx () + ui, ridx () + nz,
+                                          ridx () + new_nz);
                       mx_inline_add2 (nc - ub, cidx () + ub + 1, new_nz - nz);
                     }