* Bug 15280 fixed: gsort(hypermat, dim>2, ..) enabled 37/21537/6
Samuel GOUGEON [Tue, 14 Jul 2020 17:53:34 +0000 (19:53 +0200)]
  http://bugzilla.scilab.org/15280

Change-Id: If6d6fd97bf6bffba9ecfd20b8732bd8dd1fb9e53

scilab/CHANGES.md
scilab/modules/elementary_functions/help/en_US/searchandsort/gsort.xml
scilab/modules/elementary_functions/help/ru_RU/searchandsort/gsort.xml
scilab/modules/elementary_functions/macros/%hm_gsort.sci
scilab/modules/elementary_functions/sci_gateway/cpp/sci_gsort.cpp
scilab/modules/elementary_functions/tests/unit_tests/gsort.tst
scilab/modules/elementary_functions/tests/unit_tests/gsort_hypermat_all_types.tst [new file with mode: 0644]

index dcba5ab..3e93c04 100644 (file)
@@ -192,7 +192,9 @@ Feature changes and additions
 * `function` replaces `mc` as the new overloading code for functions in Scilab language.
 
 6.1.1
-* `gsort` is fully enabled for sparse vectors and 2D matrices, in all `g, r, c, lr, lc` methods. It was formerly limited to real or complex vectors and only to the `g` mode. All boolean, real or complex vector or 2D matrices can now be sorted with any method. Multi-level sorting is enabled for all types of sparse input.
+* `gsort` is upgraded:
+  - It can now sort any sparse 2D matrix, in all `g, r, c, lr, lc` methods, including sparse booleans and in multi-level mode. It was formerly limited to sparse real or complex vectors and only to the `g` mode.
+  - Any hypermatrix can be sorted along a dimension > 2.
 * `unique` is enabled for any 2D sparse arrays, in simple, 'c' and 'r' modes.
 
 Help pages:
@@ -278,6 +280,7 @@ Bug Fixes
 * [#12532](https://bugzilla.scilab.org/12532): From `browsevar`, clicking on any function did not edit it with `edit`. The content of libraries could not be displayed either.
 * [#12889](https://bugzilla.scilab.org/12889): In the help browser, add a menu allowing to select the language of help pages, regardless of the language of the session.
 * [#14873](https://bugzilla.scilab.org/14873): `setfield` page: The output and the 6.0 history were documented only on the en_US version. The input was wrongly restricted to matrices, while any Scilab object is acceptable. The specific role of `setfield` for mlists was not really described nor illustrated. The example did not include any call to setfield.
+* [#15280](https://bugzilla.scilab.org/15280): `gsort` was unable to sort any hypermatrix along dimensions > "r"|"c".
 * [#15839](https://bugzilla.scilab.org/15839): `gsort`: the only sparse possible input were real or complex vectors, and only with the `g` method.
 * [#15842](https://bugzilla.scilab.org/15842): `unique` could not process 2D sparse matrices.
 * [#16106](https://bugzilla.scilab.org/16106): Xcos sciblk4 user-defined blocks did not handle opar and odstate/oz correctly.
index 632510e..1f64025 100644 (file)
             <varlistentry>
                 <term>method</term>
                 <listitem>
-                    A keyword: The sorting method:
+                    A keyword or index > 0: The sorting method:
                     <informaltable>
                         <tr valign="top">
-                            <th>'g'</th><td>:</td>
+                            <td><emphasis role="bold">'g'</emphasis></td><td>:</td>
                             <td>General sorting: All elements of <literal>A</literal> are sorted
                                 (default method).
                             </td>
                         </tr>
                         <tr valign="top">
-                            <th>'r'</th><td>:</td>
+                            <td style="white-space:nowrap">
+                                <emphasis role="bold">'r'</emphasis> or
+                                <emphasis role="bold">1</emphasis></td>
+                            <td>:</td>
                             <td>Rows of each column of <literal>A</literal> are sorted.</td>
                         </tr>
                         <tr valign="top">
-                            <th>'c'</th><td>:</td>
+                            <td style="white-space:nowrap">
+                                <emphasis role="bold">'c'</emphasis> or
+                                <emphasis role="bold">2</emphasis></td>
+                            <td>:</td>
                             <td>Columns of each row of <literal>A</literal> are sorted.</td>
                         </tr>
-                        <tr valign="top"><th>'lr'</th><td>:</td>
+                        <tr valign="top">
+                            <td><emphasis role="bold">3 ≤ m ≤ ndims(A)</emphasis></td>
+                            <td>:</td>
+                            <td>Elements of each vector along the dimension #m are sorted.</td>
+                        </tr>
+                        <tr valign="top"><td><emphasis role="bold">'lr'</emphasis></td><td>:</td>
                             <td>lexicographic sort of the rows of <literal>A</literal>:
                                 Sorts rows according to values in the first column. If a group of
                                 sorted rows have the same value in column #1, resorts the group
@@ -73,7 +84,7 @@
                                 Not applicable to hypermatrices.
                             </td>
                         </tr>
-                        <tr valign="top"><th>'lc'</th><td>:</td>
+                        <tr valign="top"><td><emphasis role="bold">'lc'</emphasis></td><td>:</td>
                             <td>lexicographic sort of the columns of <literal>A</literal>
                                 (not for hypermatrices).
                             </td>
@@ -582,6 +593,83 @@ P = evstr(P)
 ]]></screen>
         </para>
     </refsect3>
+
+    <refsect3>
+        <title>With an hypermatrix</title>
+        <para>
+            <emphasis role="bold">Sorting columns in each row:</emphasis>
+        </para>
+        <para>
+        <programlisting role="example"><![CDATA[
+h = matrix([9,7,9,0,2,9,4,2,0,9,5,8,5,2,0,0], [2,4,2])
+[s, k] = gsort(h, "c", "i")
+]]>     </programlisting>
+        <screen><![CDATA[
+--> h = matrix([9,7,9,0,2,9,4,2,0,9,5,8,5,2,0,0], [2,4,2])
+ h  =
+(:,:,1)
+   9.   9.   2.   4.
+   7.   0.   9.   2.
+(:,:,2)
+   0.   5.   5.   0.
+   9.   8.   2.   0.
+
+--> [s, k] = gsort(h, "c", "i")
+ s  =
+(:,:,1)
+   2.   4.   9.   9.
+   0.   2.   7.   9.
+(:,:,2)
+   0.   0.   5.   5.
+   0.   2.   8.   9.
+
+ k  =
+(:,:,1)
+   3.   4.   1.   2.
+   2.   4.   1.   3.
+(:,:,2)
+   1.   4.   2.   3.
+   4.   3.   2.   1.
+]]></screen>
+        </para>
+        <para>
+            <emphasis role="bold">Sorting values across pages:</emphasis>
+        </para>
+        <para>
+        <programlisting role="example"><![CDATA[
+h = matrix([9,7,9,0,2,9,4,2,0,9,5,8,5,2,0,0], [2,4,2])
+[s, k] = gsort(h, 3, "i")   // along the 3rd dimension = hypermat 'thickness'
+]]>     </programlisting>
+        <screen><![CDATA[
+--> h = matrix([9,7,9,0,2,9,4,2,0,9,5,8,5,2,0,0], [2,4,2])
+ h  =
+(:,:,1)
+   9.   9.   2.   4.
+   7.   0.   9.   2.
+(:,:,2)
+   0.   5.   5.   0.
+   9.   8.   2.   0.
+
+--> [s, k] = gsort(h, 3, "i")
+ s  =
+(:,:,1)
+   0.   5.   2.   0.
+   7.   0.   2.   0.
+(:,:,2)
+   9.   9.   5.   4.
+   9.   8.   9.   2.
+
+ k  =
+(:,:,1)
+   2.   2.   1.   2.
+   1.   1.   2.   2.
+(:,:,2)
+   1.   1.   2.   1.
+   2.   2.   1.   1.
+]]></screen>
+        </para>
+    </refsect3>
+
     </refsection>
     <refsection role="see also">
         <title>See also</title>
@@ -633,11 +721,17 @@ P = evstr(P)
             <revision>
                 <revnumber>6.1.1</revnumber>
                 <revremark>
-                    gsort() was formerly limited to real or complex vectors,
-                    and only to the `g` method. It is now fully enabled for sparse
-                    vectors and 2D matrices of booleans, real or complex numbers,
-                    in all `g, r, c, lr, lc` methods. Multi-level sorting is
-                    enabled for all types of sparse input.
+                    <itemizedlist>
+                        <listitem>
+                            For a sparse input, gsort() was limited to numerical vectors,
+                            and only to the `g` method. It is now fully enabled for vectors
+                            and 2D matrices of sparse booleans, real or complex numbers,
+                            in all `g, r, c, lr, lc` methods, including in multi-level mode.
+                        </listitem>
+                        <listitem>
+                            Sorting along a dimension > 2 is now possible.
+                        </listitem>
+                    </itemizedlist>
                 </revremark>
             </revision>
         </revhistory>
index 8a9b36f..a12b696 100644 (file)
@@ -40,7 +40,7 @@
                 <listitem>
                     Скаляр, вектор, матрица или гиперматрица логических значений, целых,
                     вещественных или комплексных чисел, или текстов. Разрежённые матрицы
-                    вещественных чисел, комплексных чисел или логических значений также могут 
+                    вещественных чисел, комплексных чисел или логических значений также могут
                     быть отсортированы.
                     <note>
                         Разрешена перегрузка необрабатываемых типов.
             <varlistentry>
                 <term>method</term>
                 <listitem>
-                    Ключевое слово: метод сортировки:
+                    Ключевое слово или индекс больше 0: метод сортировки:
                     <informaltable>
                         <tr valign="top">
                             <th>'g'</th><td>:</td>
                             <td>Общая сортировка: сортируются все элементы в <literal>A</literal>
-                                ( метод по умолчанию).
+                                (метод по умолчанию).
                             </td>
                         </tr>
                         <tr valign="top">
-                            <th>'r'</th><td>:</td>
+                            <td style="white-space:nowrap">
+                                <emphasis role="bold">'r'</emphasis> или
+                                <emphasis role="bold">1</emphasis></td>
+                            <td>:</td>
                             <td>Сортируются строки в каждом столбце в <literal>A</literal>.</td>
                         </tr>
                         <tr valign="top">
-                            <th>'c'</th><td>:</td>
+                            <td style="white-space:nowrap">
+                                <emphasis role="bold">'c'</emphasis> или
+                                <emphasis role="bold">2</emphasis></td>
+                            <td>:</td>
                             <td>Сортируются столбцы в каждой строке в <literal>A</literal>.</td>
                         </tr>
-                        <tr valign="top"><th>'lr'</th><td>:</td>
+                        <tr valign="top"><td><emphasis role="bold">'lr'</emphasis></td><td>:</td>
                             <td>
                                 лексикографическая сортировка строк в <literal>A</literal>:
                                 Сортируются строки в соответствии со значениями в первом столбце.
@@ -76,7 +82,7 @@
                                 значениями в столбце №2, и так далее. Не применимо к гиперматрицам.
                             </td>
                         </tr>
-                        <tr valign="top"><th>'lc'</th><td>:</td>
+                        <tr valign="top"><td><emphasis role="bold">'lc'</emphasis></td><td>:</td>
                             <td>
                                 лексикографическая сортировка столбцов в <literal>A</literal>
                                 (не для гиперматриц).
         </para>
         <para>
             <note>
-                Какой бы метод ни выбрали, <emphasis role="bold">алгоритм сохраняет относительный порядок элементов с равными значениями</emphasis>.
+                Какой бы метод ни выбрали, <emphasis role="bold">алгоритм сохраняет относительный
+                порядок элементов с равными значениями</emphasis>.
             </note>
         </para>
         <refsect3>
                     </listitem>
                     <listitem>
                         <emphasis>Сортировка матрицы <literal>P</literal> полиномов,
-                        сначала в порядке увеличения степени, затем в порядке уменьшения значения постоянного коэффициента 0-й степени</emphasis>:
+                        сначала в порядке увеличения степени, затем в порядке уменьшения значения
+                        постоянного коэффициента 0-й степени</emphasis>:
                         <screen>
 function c = get_coef(p, i)
     // i: степень возвращаемого коэффициента
@@ -597,6 +605,81 @@ P = evstr(P)
 ]]></screen>
         </para>
     </refsect3>
+    <refsect3>
+        <title>С гиперматрицей</title>
+        <para>
+            <emphasis role="bold">Сортировка столбцов в каждой строке:</emphasis>
+        </para>
+        <para>
+        <programlisting role="example"><![CDATA[
+h = matrix([9,7,9,0,2,9,4,2,0,9,5,8,5,2,0,0], [2,4,2])
+[s, k] = gsort(h, "c", "i")
+]]>     </programlisting>
+        <screen><![CDATA[
+--> h = matrix([9,7,9,0,2,9,4,2,0,9,5,8,5,2,0,0], [2,4,2])
+ h  =
+(:,:,1)
+   9.   9.   2.   4.
+   7.   0.   9.   2.
+(:,:,2)
+   0.   5.   5.   0.
+   9.   8.   2.   0.
+
+--> [s, k] = gsort(h, "c", "i")
+ s  =
+(:,:,1)
+   2.   4.   9.   9.
+   0.   2.   7.   9.
+(:,:,2)
+   0.   0.   5.   5.
+   0.   2.   8.   9.
+
+ k  =
+(:,:,1)
+   3.   4.   1.   2.
+   2.   4.   1.   3.
+(:,:,2)
+   1.   4.   2.   3.
+   4.   3.   2.   1.
+]]></screen>
+        </para>
+        <para>
+            <emphasis role="bold">Сортировка значений по страницам:</emphasis>
+        </para>
+        <para>
+        <programlisting role="example"><![CDATA[
+h = matrix([9,7,9,0,2,9,4,2,0,9,5,8,5,2,0,0], [2,4,2])
+[s, k] = gsort(h, 3, "i")   // по третьей размерности = 'толщина' гиперматрицы
+]]>     </programlisting>
+        <screen><![CDATA[
+--> h = matrix([9,7,9,0,2,9,4,2,0,9,5,8,5,2,0,0], [2,4,2])
+ h  =
+(:,:,1)
+   9.   9.   2.   4.
+   7.   0.   9.   2.
+(:,:,2)
+   0.   5.   5.   0.
+   9.   8.   2.   0.
+
+--> [s, k] = gsort(h, 3, "i")
+ s  =
+(:,:,1)
+   0.   5.   2.   0.
+   7.   0.   2.   0.
+(:,:,2)
+   9.   9.   5.   4.
+   9.   8.   9.   2.
+
+ k  =
+(:,:,1)
+   2.   2.   1.   2.
+   1.   1.   2.   2.
+(:,:,2)
+   1.   1.   2.   1.
+   2.   2.   1.   1.
+]]></screen>
+        </para>
+    </refsect3>
     </refsection>
     <refsection role="see also">
         <title>Смотрите также</title>
@@ -647,11 +730,18 @@ P = evstr(P)
             <revision>
                 <revnumber>6.1.1</revnumber>
                 <revremark>
-                    gsort() ранее была ограничена вещественными или комплексными
-                    векторами и только методом 'g'. Теперь она полностью способна
-                    к работе с разрежёнными векторами и двумерными матрицами логических,
-                    вещественных или комплексных чисел, всеми методами 'g, r, c, lr, lc'.
-                    Многоуровневая сортировка возможна для всех типов разрежённых входных данных.
+                    <itemizedlist>
+                        <listitem>
+                            Для разрежённого входа, gsort() ранее была ограничена вещественными или
+                            комплексными векторами и только методом 'g'. Теперь она полностью способна
+                            к работе с разрежёнными векторами и двумерными матрицами логических,
+                            вещественных или комплексных чисел, всеми методами 'g, r, c, lr, lc'.
+                            Многоуровневая сортировка возможна для всех типов разрежённых входных данных.
+                        </listitem>
+                        <listitem>
+                            Теперь возможна сортировка вдоль размерности более 2.
+                        </listitem>
+                    </itemizedlist>
                 </revremark>
             </revision>
         </revhistory>
index d7c5e7a..e323c8b 100644 (file)
@@ -11,7 +11,7 @@
 // along with this program.
 
 function [S, k] = %hm_gsort(A, method, varargin)
-    // method can be: 'g', 'r', 'c', 'lr', 'lc'
+    // method can be: 'g', 'r', 'c', 1, 2, .., ndims, 'lr', 'lc'
     // sortdir = varargin(1): "i", "d", or vector of "i" and "d"
     // criteria = varargin(2): list() of functions or builtin handles or :
     //
@@ -19,6 +19,7 @@ function [S, k] = %hm_gsort(A, method, varargin)
     //  decimal or complex numbers, polynomials, texts
 
     // INITIALIZATIONS
+    // ---------------
     lhs = argn(1)
     sizes = size(A)
     L = prod(sizes(3:$))
@@ -28,45 +29,67 @@ function [S, k] = %hm_gsort(A, method, varargin)
     end
 
     // CHECKING PARAMETERS
+    // -------------------
     // method: checked in the gateway
     if ~isdef("method","l")
         method = "g"
+    elseif method == "r"
+        method = 1
+    elseif method == "c"
+        method = 2
     end
     // sortdir, criteria: checked in each overload, since these ones
     //      can also be called directly by the gateway
 
+    // PREPROCESSING
+    // -------------
+    if type(method)==1 then
+        // We permute dims to make #1 the dim along which to sort
+        if method > 1
+            d = 1:ndims(A)
+            d([1 method]) = [method 1]
+            A = permute(A, d)
+        end
+        sA = size(A)
+        A = matrix(A, size(A,1), -1)
+    elseif or(method==["lr" "lc"])
+        // transform input hypermatrix to a hypermatrix of 3 dimensions
+        A = matrix(A, sizes(1), sizes(2), -1)
+        // init output variables
+        S = zeros(sizes(1), sizes(2), L)
+    end
+
+    // PROCESSING
+    // ==========
     // ONLY THE SORTED ARRAY IS EXPECTED (gsort is then faster)
+    // --------------------------------------------------------
     if(lhs == 1)
         if method == "g"
             S = gsort(A(:), method, varargin(:))
-            S = matrix(S, size(A))
-        else // 'r' 'c' 'lr' 'lc'
-            // transform input hypermatrix to a hypermatrix of 3 dimensions
-            mat = matrix(A,sizes(1), sizes(2), -1)
-
-            // init output variables
-            S = zeros(sizes(1), sizes(2), L)
 
+        elseif or(method==["lr" "lc"])
             // perform a 2D sort for each sheet
             for i = 1:L
-                S(:,:,i) = gsort(mat(:,:,i), method, varargin(:))
+                S(:,:,i) = gsort(A(:,:,i), method, varargin(:))
+            end
+
+        else    // sorting along a dimension
+            S = gsort(A, "r", varargin(:))
+            S = matrix(S, sA)
+            if method > 1
+                S = permute(S, d)
             end
         end
 
     // INDICES ARE ALSO EXPECTED
+    // -------------------------
     else
         if method == "g"
             [S, k] = gsort(A(:), method, varargin(:))
-            S = matrix(S, size(A))
             k = matrix(k, size(A))
-        else // 'r' 'c' 'lr' 'lc'
-            sizesInd = size(A)
 
-            // transform input hypermatrix to a hypermatrix of 3 dimensions
-            mat = matrix(A,sizes(1), sizes(2), -1)
-
-            // init output variables
-            S = zeros(sizes(1), sizes(2), L)
+        elseif or(method==["lr" "lc"])
+            sizesInd = sizes
             if method == "lc"
                 sizesInd(1) = 1
             elseif method == "lr"
@@ -76,11 +99,20 @@ function [S, k] = %hm_gsort(A, method, varargin)
 
             // perform a 2D sort for each sheet
             for i = 1:L
-                [S(:,:,i), k(:,:,i)] = gsort(mat(:,:,i), method, varargin(:))
+                [S(:,:,i), k(:,:,i)] = gsort(A(:,:,i), method, varargin(:))
             end
-
             // return the result with the good dimensions
             k = matrix(k, sizesInd)
+
+        else    // sorting along a dimension
+            [S, k] = gsort(A, "r", varargin(:))
+            S = matrix(S, sA)
+            k = matrix(k, sA)
+            if method > 1
+                S = permute(S, d)
+                k = permute(k, d)
+            end
+
         end
     end
     S = matrix(S, sizes)
index 5bd874a..20c4b31 100644 (file)
@@ -2,7 +2,7 @@
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2012 - DIGITEO - Cedric DELAMARRE
  * Copyright (C) 2012 - 2016 - Scilab Enterprises
- * Copyright (C) 2018 - Samuel GOUGEON
+ * Copyright (C) 2018 - 2020 - Samuel GOUGEON
  *
  * This file is hereby licensed under the terms of the GNU GPL v2.0,
  * pursuant to article 5.3.4 of the CeCILL v.2.1.
@@ -59,33 +59,66 @@ types::Function::ReturnValue sci_gsort(types::typed_list &in, int _iRetCount, ty
         return types::Function::Error;
     }
 
+    types::GenericType* pGTIn = in[0]->getAs<types::GenericType>();
+
     // Get the sorting method, always as argin#2 for all generic types
     // ----------------------
+    char* msg = _("%s: Argument #%d: 'g','r','c','lc','lr' or integer in [1, %d] expected.\n");
     std::wstring wstrProcess = L"g";
+    int iOrientation = 0;
+    int ndims = static_cast<int>(pGTIn->getDims());
+
     if (in.size() >= 2)
     {
-        if (in[1]->isString() == false)
+        if (in[1]->isDouble())
         {
-            Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "gsort", 2);
-            return types::Function::Error;
-        }
+            types::Double* pDbl = in[1]->getAs<types::Double>();
+
+            if (pDbl->isScalar() == false)
+            {
+                Scierror(999, _("%s: Argument #%d: Scalar (1 element) expected.\n"), "gsort", 2);
+                return types::Function::Error;
+            }
 
-        wstrProcess = in[1]->getAs<types::String>()->get(0);
+            iOrientation = static_cast<int>(pDbl->get(0));
 
-        if ( wstrProcess != L"c"  &&
-                wstrProcess != L"r"  &&
-                wstrProcess != L"g"  &&
-                wstrProcess != L"lc" &&
-                wstrProcess != L"lr")
+            if (iOrientation <= 0 || iOrientation > ndims)
+            {
+                Scierror(999, msg, "gsort", 2, ndims);
+                return types::Function::Error;
+            }
+            if ( iOrientation == 1 )
+            {
+                wstrProcess = L"r";
+            }
+            else if ( iOrientation == 2 )
+            {
+                wstrProcess = L"c";
+            }
+            // else: hypermat: overload called later
+        }
+        else if (in[1]->isString() == false)
         {
-            Scierror(999, _("%s: Argument #%d: Must be in the set {%s}.\n"), "gsort", 2, "'g','r','c','lc','lr'");
+            Scierror(999, msg, "gsort", 2, ndims);
             return types::Function::Error;
         }
+        else
+        {
+            wstrProcess = in[1]->getAs<types::String>()->get(0);
+
+            if ( wstrProcess != L"c"  &&
+                 wstrProcess != L"r"  &&
+                 wstrProcess != L"g"  &&
+                 wstrProcess != L"lc" &&
+                 wstrProcess != L"lr")
+            {
+                Scierror(999, msg, "gsort", 2, ndims);
+                return types::Function::Error;
+            }
+        }
     }
 
-    types::GenericType* pGTIn = in[0]->getAs<types::GenericType>();
-       
-    if (pGTIn->getDims() > 2)
+    if (ndims > 2)
     {
         // hypermatrix
         return Overload::call(L"%hm_gsort", in, _iRetCount, out);
index fd1a5d5..ee1cfb5 100644 (file)
@@ -342,19 +342,19 @@ Nrand = 100;
 vmax = 4;
 for itype = [1 2 4 8 11 12 14 18]
     a = iconvert(matrix(grand(1,"prm",(1:N*P)'),N,P), itype);
-    
+
     //-----Global sort --------------------------------
     [a1,ind] = gsort(a,"g");
     assert_checkequal(a1, iconvert(matrix(N * P:-1:1,N,P), itype));
     assert_checkequal(a1, matrix(a(ind),N,P));
-    
+
     for i = 1:Nrand
         b = iconvert(10 * rand(N,P,"u"), itype);
         [b1,ind] = gsort(b,"g");
         assert_checkequal(b1, matrix(b(ind),N,P));
         assert_checktrue(or(b1(1:$-1) - b1(2:$) >= 0));
     end
-    
+
     //increasing values
     [a1,ind] = gsort(a,"g","i");
     assert_checkequal(a1, iconvert(matrix(1:N*P,N,P), itype));
@@ -366,7 +366,7 @@ for itype = [1 2 4 8 11 12 14 18]
         assert_checkequal(b1, matrix(b(ind),N,P));
         assert_checktrue(or(b1(1:$-1) - b1(2:$) <= 0));
     end
-    
+
     //----sort each column of a ('r' means that the row indice is used for sorting)
     [a1,ind] = gsort(a,"r");
     nc = size(a,"c");
@@ -375,13 +375,13 @@ for itype = [1 2 4 8 11 12 14 18]
         test = [test, matrix(a(ind(:,i),i),N,1)];
     end
     assert_checkequal(a1, test);
-    
+
     test = [];
     for i =1:nc
         test = [test, gsort(a(:,i),"g")];
     end
     assert_checkequal(a1, test);
-    
+
     if itype < 10
         for i = 1:Nrand
             b = iconvert(10*rand(N,P,"u"), itype);
@@ -424,7 +424,7 @@ for itype = [1 2 4 8 11 12 14 18]
         test = [test; gsort(a(i,:),"g")];
     end
     assert_checkequal(a1, test);
-    
+
     if itype < 10
         for i = 1:Nrand
             b = iconvert(10 * rand(N,P,"u"), itype);
@@ -451,7 +451,7 @@ for itype = [1 2 4 8 11 12 14 18]
         test = [test; gsort(a(i,:),"g","i")];
     end
     assert_checkequal(a1, test);
-    
+
     //----sort the rows of a in lexicographic order
     //    i.e a(k,:) < a(l,:) if there's a number j
     //    such that a(k,j) < a(l,j) or a(k,p)=a(l,p) for p in [1,j-1];
@@ -464,12 +464,12 @@ for itype = [1 2 4 8 11 12 14 18]
     // a random permutation
     [ax,perm] = gsort(rand(1,N1,"u"));
     a = iconvert(alr(perm,:), itype);
-    
+
     [a1,ind] = gsort(a,"lr");
-    
+
     assert_checkequal(a1, iconvert(alr, itype));
     assert_checkequal(a1, matrix(a(ind,:),N1,P1));
-    
+
     [a2,ind2] = gsort(a*[100;10;1],"g");
     assert_checkequal(ind2, ind);
     ///////////////////////
@@ -480,15 +480,15 @@ for itype = [1 2 4 8 11 12 14 18]
         v = double(b1)*((vmax+1)^[P-1:-1:0])';
         assert_checktrue(or(v(2:$) - v(1:$-1) <= 0));
     end
-    
+
     // increasing
     [a1,ind] = gsort(a,"lr","i");
     assert_checkequal(a1, iconvert(alr(N1:-1:1,:), itype));
     assert_checkequal(a1, matrix(a(ind,:),N1,P1));
-    
+
     [a2,ind2] = gsort(a*[100;10;1],"g","i");
     assert_checkequal(ind2, ind);
-    
+
     for i = 1:Nrand
         b = int(vmax * rand(N,P,"u"));
         [b1,ind] = gsort(b,"lr","i");
@@ -496,21 +496,21 @@ for itype = [1 2 4 8 11 12 14 18]
         v = double(b1)*((vmax+1)^[P-1:-1:0])';
         assert_checktrue(or(v(2:$) - v(1:$-1) >= 0));
     end
-    
+
     //----sort the columns of a in lexicographic order
     N1 = 3; P1 = 4;
     alr = alr';
     // a random permutation
     [ax,perm] = gsort(rand(1,P1,"u"));
     a = iconvert(alr(:,perm), itype);
-    
+
     [a1,ind] = gsort(a,"lc");
     assert_checkequal(a1, iconvert(alr, itype));
     assert_checkequal(a1, matrix(a(:,ind),N1,P1));
-    
+
     [a2,ind2] = gsort([100,10,1]*a,"g");
     assert_checkequal(ind2, ind);
-    
+
     for i = 1:Nrand
         b = int(vmax*rand(N1,P1,"u"));
         [b1,ind] = gsort(b,"lc");
@@ -523,10 +523,10 @@ for itype = [1 2 4 8 11 12 14 18]
     [a1,ind] = gsort(a,"lc","i");
     assert_checkequal(a1, iconvert(alr(:,P1:-1:1), itype));
     assert_checkequal(a1, matrix(a(:,ind),N1,P1));
-    
+
     [a2,ind2] = gsort([100,10,1] * a,"g","i");
     assert_checkequal(ind2, ind);
-    
+
     for i = 1:Nrand
         b = int(vmax*rand(N,P,"u"));
         [b1,ind] = gsort(b,"lc","i");
@@ -534,7 +534,7 @@ for itype = [1 2 4 8 11 12 14 18]
         v = ((vmax+1)^[N-1:-1:0])*b1;
         assert_checktrue(or(v(2:$) - v(1:$-1) >= 0));
     end
-    
+
     a = iconvert([1,1,1,1,2,2,3,3,2,2,3,3,4,4,4,4,4,4,4,4,5,5,5,6,6,6,7,7,7,7,..
     8,8,8,8,9,9,9,9,9,9,9,7,9,10,10,10,10,11,11,11,12,13,13,13,13,14,14,12,12,..
     14,14,14,14,14,14,15,15,15,15,16,17,18;
@@ -549,7 +549,7 @@ for itype = [1 2 4 8 11 12 14 18]
     assert_checktrue(or(t(:,1) >= 0));      // int8: <= 0
     assert_checktrue(or(t(find(t(:,1)==0),2) >= 0));
     assert_checkequal(a(ind,:), b);
-    
+
     for k = 1:30
         p = grand(1,"prm",(1:size(a,1))');
         [b,ind] = gsort(a(p,:),"lr","i");
@@ -558,13 +558,13 @@ for itype = [1 2 4 8 11 12 14 18]
         assert_checktrue(or(t(find(t(:,1)==0),2) >= 0));
         assert_checkequal(a(p(ind),:), b);
     end
-    
+
     [b,ind] = gsort(a,"lr","d");
     t = b(1:$-1,:) - b(2:$,:);
     assert_checktrue(or(t(:,1) >= 0));      // int8: <= 0
     assert_checktrue(or(t(find(t(:,1)==0),2) >= 0));
     assert_checkequal(a(ind,:), b);
-    
+
     for k = 1:30
         p = grand(1,"prm",(1:size(a,1))');
         [b,ind] = gsort(a(p,:),"lr","d");
@@ -573,7 +573,7 @@ for itype = [1 2 4 8 11 12 14 18]
         assert_checktrue(or(t(find(t(:,1)==0),2) >= 0));
         assert_checkequal(a(p(ind),:), b);
     end
-    
+
     a = b;
     a([10 60],:) = a([60 10],:);
     [b,ind] = gsort(a,"lr","i");
@@ -581,7 +581,7 @@ for itype = [1 2 4 8 11 12 14 18]
     assert_checktrue(or(t(:,1) >= 0));      // int8: <= 0
     assert_checktrue(or(t(find(t(:,1)==0),2) >= 0));
     assert_checkequal(a(ind,:), b);
-    
+
     [b,ind] = gsort(a,"lr","d");
     t = b(1:$-1,:) - b(2:$,:);
     assert_checktrue(or(t(:,1) >= 0));      // int8: <= 0
@@ -686,65 +686,3 @@ assert_checkequal(gsort(a), []);
 assert_checkequal(s, []);
 assert_checkequal(k, []);
 
-//================================ hypermatrix ================================
-
-A = rand(6, 4, 2, 8);
-for o = ["d" "i"]
-    // 'g'
-    [hs hind]   = gsort(A, 'g', o);
-    [s ind]     = gsort(A(:), 'g', o);
-
-    assert_checkequal(hs(:), s);
-    assert_checkequal(hind(:), ind);
-
-    hs = gsort(A, 'g', o);
-    assert_checkequal(hs(:), s);
-
-    // 'c' 'r' 'lc' 'lr'
-    [hsc hindc]   = gsort(A, "c", o);
-    [hsr hindr]   = gsort(A, "r", o);
-    [hslc hindlc] = gsort(A, "lc", o);
-    [hslr hindlr] = gsort(A, "lr", o);
-
-    a       = matrix(A, 6, 4, 16); // 2 * 8 = 16
-    z = zeros(a);
-    [sc, indc, sr, indr, slc, slr] = (z, z, z, z, z, z);
-    indlc   = zeros(1, 4, 16);
-    indlr   = zeros(6, 1, 16);
-
-    for i = 1:16
-        [sc(:,:,i) indc(:,:,i)]   = gsort(a(:,:,i),"c", o);
-        [sr(:,:,i) indr(:,:,i)]   = gsort(a(:,:,i),"r", o);
-        [slc(:,:,i) indlc(:,:,i)] = gsort(a(:,:,i),"lc", o);
-        [slr(:,:,i) indlr(:,:,i)] = gsort(a(:,:,i),"lr", o);
-    end
-
-    sc      = matrix(sc, 6, 4, 2, 8);
-    indc    = matrix(indc, 6, 4, 2, 8);
-    sr      = matrix(sr, 6, 4, 2, 8);
-    indr    = matrix(indr, 6, 4, 2, 8);
-    slc     = matrix(slc, 6, 4, 2, 8);
-    indlc   = matrix(indlc, 1, 4, 2, 8);
-    slr     = matrix(slr, 6, 4, 2, 8);
-    indlr   = matrix(indlr, 6, 1, 2, 8);
-
-    assert_checkequal(hsc, sc);
-    assert_checkequal(hindc, indc);
-    assert_checkequal(hsr, sr);
-    assert_checkequal(hindr, indr);
-    assert_checkequal(hslc, slc);
-    assert_checkequal(hindlc, indlc);
-    assert_checkequal(hslr, slr);
-    assert_checkequal(hindlr, indlr);
-
-    // whitout indices
-    hsc  = gsort(A, "c", o);
-    hsr  = gsort(A, "r", o);
-    hslc = gsort(A, "lc", o);
-    hslr = gsort(A, "lr", o);
-
-    assert_checkequal(hsc, sc);
-    assert_checkequal(hsr, sr);
-    assert_checkequal(hslc, slc);
-    assert_checkequal(hslr, slr);
-end
diff --git a/scilab/modules/elementary_functions/tests/unit_tests/gsort_hypermat_all_types.tst b/scilab/modules/elementary_functions/tests/unit_tests/gsort_hypermat_all_types.tst
new file mode 100644 (file)
index 0000000..cbde9d4
--- /dev/null
@@ -0,0 +1,119 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) ????-2008 - INRIA
+// Copyright (C) ????-2008 - ENPC
+// Copyright (C) 2008 - DIGITEO - Allan CORNET
+// Copyright (C) 2012 - Scilab Enterprises - Adeline CARNIS
+// Copyright (C) 2018 - 2020 - Samuel GOUGEON
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+
+//================ Sorting hypermatrices (all data types) ======================
+
+A = rand(6, 4, 2, 8);
+for o = ["d" "i"]
+    // 'g'
+    [hs hind]   = gsort(A, 'g', o);
+    [s ind]     = gsort(A(:), 'g', o);
+
+    assert_checkequal(hs(:), s);
+    assert_checkequal(hind(:), ind);
+
+    hs = gsort(A, 'g', o);
+    assert_checkequal(hs(:), s);
+
+    // 'c' 'r' 'lc' 'lr'
+    [hsc hindc]   = gsort(A, "c", o);
+    [hsr hindr]   = gsort(A, "r", o);
+    [hslc hindlc] = gsort(A, "lc", o);
+    [hslr hindlr] = gsort(A, "lr", o);
+
+    a       = matrix(A, 6, 4, 16); // 2 * 8 = 16
+    z = zeros(a);
+    [sc, indc, sr, indr, slc, slr] = (z, z, z, z, z, z);
+    indlc   = zeros(1, 4, 16);
+    indlr   = zeros(6, 1, 16);
+
+    for i = 1:16
+        [sc(:,:,i) indc(:,:,i)]   = gsort(a(:,:,i),"c", o);
+        [sr(:,:,i) indr(:,:,i)]   = gsort(a(:,:,i),"r", o);
+        [slc(:,:,i) indlc(:,:,i)] = gsort(a(:,:,i),"lc", o);
+        [slr(:,:,i) indlr(:,:,i)] = gsort(a(:,:,i),"lr", o);
+    end
+
+    sc      = matrix(sc, 6, 4, 2, 8);
+    indc    = matrix(indc, 6, 4, 2, 8);
+    sr      = matrix(sr, 6, 4, 2, 8);
+    indr    = matrix(indr, 6, 4, 2, 8);
+    slc     = matrix(slc, 6, 4, 2, 8);
+    indlc   = matrix(indlc, 1, 4, 2, 8);
+    slr     = matrix(slr, 6, 4, 2, 8);
+    indlr   = matrix(indlr, 6, 1, 2, 8);
+
+    assert_checkequal(hsc, sc);
+    assert_checkequal(hindc, indc);
+    assert_checkequal(hsr, sr);
+    assert_checkequal(hindr, indr);
+    assert_checkequal(hslc, slc);
+    assert_checkequal(hindlc, indlc);
+    assert_checkequal(hslr, slr);
+    assert_checkequal(hindlr, indlr);
+
+    // whitout indices
+    hsc  = gsort(A, "c", o);
+    hsr  = gsort(A, "r", o);
+    hslc = gsort(A, "lc", o);
+    hslr = gsort(A, "lr", o);
+
+    assert_checkequal(hsc, sc);
+    assert_checkequal(hsr, sr);
+    assert_checkequal(hslc, slc);
+    assert_checkequal(hslr, slr);
+end
+
+// Sorting along a dim > 2
+// -----------------------
+H = grand(2,4,3,3,"uin",-9,9);
+function r = toBool(m), r = m < 0; endfunction
+for fun = list(toBool, int8, uint8, int16, uint32, int64, string)
+    h = fun(H);
+    for o = ["i" "d"]
+        // along dim = 1 (checking)
+        [sh, k] = gsort(h, 1, o);
+        for i2 = 1:size(h,2)
+            for j2 = 1:size(h,3)
+                for k2 = 1:size(h,4)
+                    [s, ks] = gsort(h(:,i2,j2,k2), "g", o);
+                    assert_checkequal(s, sh(:,i2,j2,k2));
+                    assert_checkequal(ks, k(:,i2,j2,k2));
+                end
+            end
+        end
+        // along dim = 3
+        [sh, k] = gsort(h, 3, o);
+        for i2 = 1:size(h,1)
+            for j2 = 1:size(h,2)
+                for k2 = 1:size(h,4)
+                    [s, ks] = gsort(h(i2,j2,:,k2), "g", o);
+                    assert_checkequal(s, sh(i2,j2,:,k2));
+                    assert_checkequal(ks, k(i2,j2,:,k2));
+                end
+            end
+        end
+        // along dim = 4
+        [sh, k] = gsort(h, 4, o);
+        for i2 = 1:size(h,1)
+            for j2 = 1:size(h,2)
+                for k2 = 1:size(h,3)
+                    [s, ks] = gsort(h(i2,j2,k2,:), "g", o);
+                    assert_checkequal(s, sh(i2,j2,k2,:));
+                    assert_checkequal(ks, k(i2,j2,k2,:));
+                end
+            end
+        end
+    end
+end