changeset 33543:8f73f8534d42

Return early if sort dimension exceeds array dimension (bug #65712) It turn out that calling `sort (A, dim)` where dim is greater than `ndims (A)` was creating a larger temp array to accommodate dim, so `sort (A, 1e9)` was transiently using 8GB, while `sort (A, inf)` was causing either OOM or a segfault, depending on the compiler and its settings. This patch changes the internal code for array sorting so that when the sort dimension exceeds the array's dimensions, the array is returned unchanged. This is analogous to `all (true(3,3), 100)` and similar expressions. * Array-base.cc (in function `Array<T, Alloc>::sort (int, sortmode)`): Copy array and return early if sort dimension exceeds array dimension. * data.cc (in Fsort): Add BISTs.
author Arun Giridhar <arungiridhar@gmail.com>
date Wed, 08 May 2024 08:07:49 -0400
parents c7b92fa723cc
children 31bc9accbe6e
files libinterp/corefcn/data.cc liboctave/array/Array-base.cc
diffstat 2 files changed, 19 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/data.cc	Tue May 07 20:56:04 2024 -0400
+++ b/libinterp/corefcn/data.cc	Wed May 08 08:07:49 2024 -0400
@@ -7385,6 +7385,12 @@
 %! [v, i] = sort (a);
 %! assert (i, [1, 4, 2, 5, 3]);
 
+## Test sort dimension being very large
+%!test <*65712>
+%! A = [1 2; 3 4];
+%! assert (sort (A, 100), A)
+%! assert (sort (A, inf), A)
+
 %!error <Invalid call> sort ()
 %!error <Invalid call> sort (1, 2, 3, 4)
 %!error <MODE must be either "ascend" or "descend"> sort (1, "foobar")
--- a/liboctave/array/Array-base.cc	Tue May 07 20:56:04 2024 -0400
+++ b/liboctave/array/Array-base.cc	Wed May 08 08:07:49 2024 -0400
@@ -1814,7 +1814,19 @@
     return m;
 
   if (dim >= dv.ndims ())
-    dv.resize (dim+1, 1);
+    {
+      // The dimension to sort along exceeds the array's dimensions,
+      // ==> array is already trivially sorted in such higher dimensions,
+      // ==> copy and return.
+
+      T *v = m.rwdata ();
+      const T *ov = data ();
+
+      for (octave_idx_type i = 0; i < m.numel (); i++)
+        v[i] = ov[i];
+
+      return m;
+    }
 
   octave_idx_type ns = dv(dim);
   octave_idx_type iter = dv.numel () / ns;