changeset 33555:a8346c5f6997

Fix 2-output form of sort() for dim > ndims() (bug #65712) Following fixes to allow `sort (A, dim)` for dim exceeding `ndims (A)`, including the case of dim = inf, this patch does the same for the 2-output calling form of sort(). * Array-base.cc: Create `sidx` early, rework early return conditions. * data.cc: Adapt the value of `dv(dim)` when dim exceeds the size of dv. Tweak input validation conditions to trap more conditions. Add BISTs.
author Arun Giridhar <arungiridhar@gmail.com>
date Thu, 09 May 2024 18:13:54 -0400
parents 4495e4a23aa6
children 4b0987b80bb7
files libinterp/corefcn/data.cc liboctave/array/Array-base.cc
diffstat 2 files changed, 22 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/data.cc	Wed May 08 14:58:32 2024 -0400
+++ b/libinterp/corefcn/data.cc	Thu May 09 18:13:54 2024 -0400
@@ -7120,15 +7120,13 @@
         }
       else
         {
-          // Forbid vector or array input
-          if (! args(1).is_scalar_type ())
+          // Require dim to be positive real scalar.
+          if (! args(1).is_scalar_type () || args(1).iscomplex ()
+              || args(1).double_value () <= 0)
             error ("sort: DIM must be a positive scalar integer");
 
           // Forbid fractional value input, also nan input.
           dim = args(1).strict_int_value ("sort: DIM must be a positive scalar integer") - 1;
-
-          if (dim < 0)
-            error ("sort: DIM must be a positive scalar integer");
         }
     }
 
@@ -7162,7 +7160,8 @@
       // NOTE: Can not change this to ovl() call because arg.sort changes sidx
       //       and objects are declared const in ovl prototype.
       retval(0) = arg.sort (sidx, dim, smode);
-      retval(1) = idx_vector (sidx, dv(dim));  // No checking, extent is known.
+      // Check for index dimension extent. Set to 1 for dimension >= ndims ()
+      retval(1) = idx_vector (sidx, (dim < arg.ndims ()) ? dv(dim) : 1);
     }
   else
     retval = ovl (arg.sort (dim, smode));
@@ -7394,11 +7393,20 @@
 %! A = [1 2; 3 4];
 %! assert (sort (A, 100), A)
 %! assert (sort (A, inf), A)
+%! [B, idx] = sort (A, 100);
+%! assert (B, A);
+%! assert (idx, ones (2))
+%! [B, idx] = sort (A, inf);
+%! assert (B, A);
+%! assert (idx, ones (2))
 
 %!error <Invalid call> sort ()
 %!error <Invalid call> sort (1, 2, 3, 4)
 %!error <MODE must be either "ascend" or "descend"> sort (1, "foobar")
 %!error <DIM must be a positive scalar integer> sort (1, [1 2 3])
+%!error <DIM must be a positive scalar integer> sort ([1 2; 3 4], -inf)
+%!error <DIM must be a positive scalar integer> sort ([1 2; 3 4], 0)
+%!error <DIM must be a positive scalar integer> sort ([1 2; 3 4], 1+i)
 %!error <DIM must be a positive scalar integer> sort ([1 2; 3 4], 1.234)
 %!error <DIM must be a positive scalar integer> sort ([1 2; 3 4], nan)
 %!error <DIM argument must precede MODE argument> sort (1, "ascend", 1)
--- a/liboctave/array/Array-base.cc	Wed May 08 14:58:32 2024 -0400
+++ b/liboctave/array/Array-base.cc	Thu May 09 18:13:54 2024 -0400
@@ -1922,19 +1922,18 @@
 Array<T, Alloc>::sort (Array<octave_idx_type>& sidx, int dim,
                        sortmode mode) const
 {
-  if (dim < 0 || dim >= ndims ())
+  if (dim < 0)
     (*current_liboctave_error_handler) ("sort: invalid dimension");
 
+  const dim_vector& dv = dims ();
+
+  sidx = Array<octave_idx_type> (dv);
+
+  if (numel () < 1 || dim >= ndims ())
+    return *this;
+
   Array<T, Alloc> m (dims ());
 
-  const dim_vector& dv = m.dims ();
-
-  if (m.numel () < 1)
-    {
-      sidx = Array<octave_idx_type> (dv);
-      return m;
-    }
-
   octave_idx_type ns = dv(dim);
   octave_idx_type iter = dv.numel () / ns;
   octave_idx_type stride = 1;
@@ -1947,7 +1946,6 @@
 
   octave_sort<T> lsort;
 
-  sidx = Array<octave_idx_type> (dv);
   octave_idx_type *vi = sidx.rwdata ();
 
   if (mode != UNSORTED)