* Bug 15842 fixed: unique() + with 2D sparse 09/21509/8
Samuel GOUGEON [Tue, 23 Jun 2020 09:54:53 +0000 (11:54 +0200)]
  http://bugzilla.scilab.org/15842

  is required for https://codereview.scilab.org/21426
  and for upgrading other set functions.

Change-Id: Ibfd461b344029d452648a607a43cf3fef2460ef5

scilab/CHANGES.md
scilab/modules/elementary_functions/help/en_US/setoperations/unique.xml
scilab/modules/elementary_functions/help/fr_FR/setoperations/unique.xml
scilab/modules/elementary_functions/help/ja_JP/setoperations/unique.xml
scilab/modules/elementary_functions/help/pt_BR/setoperations/unique.xml
scilab/modules/elementary_functions/help/ru_RU/setoperations/unique.xml
scilab/modules/elementary_functions/macros/unique.sci
scilab/modules/elementary_functions/tests/unit_tests/unique_sparse.tst [new file with mode: 0644]

index 66aa23c..9eac4ad 100644 (file)
@@ -193,7 +193,7 @@ Feature changes and additions
 
 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.
-* `unique` is enabled for any 2D sparse arrays.
+* `unique` is enabled for any 2D sparse arrays, in simple, 'c' and 'r' modes.
 
 Help pages:
 -----------
index d6ac46f..18a7f63 100644 (file)
@@ -3,7 +3,7 @@
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2008 - INRIA
  * Copyright (C) 2012 - 2016 - Scilab Enterprises
- * Copyright (C) 2017 - 2019 - Samuel GOUGEON
+ * Copyright (C) 2017 - 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.
@@ -37,6 +37,7 @@
                 <term>M</term>
                 <listitem>
                     vector, matrix, or hypermatrix of booleans, numbers, or text.
+                    Numeric or boolean sparses are accepted.
                     <para/>
                 </listitem>
             </varlistentry>
@@ -66,6 +67,8 @@
                     </listitem>
                   </itemizedlist>
                   <para/>
+                  If <varname>M</varname> is sparse, then <varname>U</varname> is always sparse.
+                  <para/>
                 </listitem>
             </varlistentry>
             <varlistentry>
                         </listitem>
                     </itemizedlist>
                     <para/>
+                    <warning>
+                        <varname>ku</varname> is dense, even when <varname>M</varname> is sparse and the
+                        overall "*" mode is used.
+                    </warning>
                 </listitem>
             </varlistentry>
             <varlistentry>
@@ -374,7 +381,7 @@ unique(M, "c")
             <revision>
                 <revnumber>6.1.1</revnumber>
                 <revdescription>
-                    ku 3rd output implemented.
+                    ku 3rd output implemented. Sparse 2D matrices are now accepted.
                 </revdescription>
             </revision>
         </revhistory>
index 8c77997..38c806d 100644 (file)
@@ -39,6 +39,7 @@
                 <listitem>
                     <para>
                         vecteur, matrice, ou hypermatrice de booléens, de nombres, ou de textes.
+                        Les matrices numériques ou booléennes creuses sont acceptées.
                     </para>
                 </listitem>
             </varlistentry>
             <varlistentry>
                 <term>U</term>
                 <listitem>
-                    <para>
-                      <itemizedlist>
-                        <listitem>
-                            <para>
-                                Sans <varname>orient</varname>: vecteur d'éléments de
-                                <varname>M</varname> triés par ordre croissant.
-                                Si <varname>M</varname> est un vecteur ligne, <varname>U</varname>
-                                aussi. Dans tous les autres cas, <varname>U</varname> est un
-                                vecteur colonne.
-                            </para>
-                        </listitem>
-                        <listitem>
-                          Avec <varname>orient</varname>: Matrice de lignes ou de colonnes extraites
-                          de <varname>M</varname>, triées par ordre lexicographique croissant.
-                        </listitem>
-                      </itemizedlist>
-                    </para>
+                    <itemizedlist>
+                    <listitem>
+                        <para>
+                            Sans <varname>orient</varname>: vecteur d'éléments de
+                            <varname>M</varname> triés par ordre croissant.
+                            Si <varname>M</varname> est un vecteur ligne, <varname>U</varname>
+                            aussi. Dans tous les autres cas, <varname>U</varname> est un
+                            vecteur colonne.
+                        </para>
+                    </listitem>
+                    <listitem>
+                      Avec <varname>orient</varname>: Matrice de lignes ou de colonnes extraites
+                      de <varname>M</varname>, triées par ordre lexicographique croissant.
+                    </listitem>
+                </itemizedlist>
+                <para/>
+                <para>
+                    <varname>U</varname> est toujours creuse si en entrée <varname>M</varname> l'est.
+                </para>
                 </listitem>
             </varlistentry>
             <varlistentry>
                         </listitem>
                     </itemizedlist>
                     <para/>
+                    <warning>
+                        <varname>ku</varname> est dense, y compris lorsque <varname>M</varname> est
+                        creuse et que le mode simple "*" est utilisé.
+                    </warning>
                 </listitem>
             </varlistentry>
             <varlistentry>
@@ -387,7 +394,7 @@ unique(M, "c")
             <revision>
                 <revnumber>6.1.1</revnumber>
                 <revdescription>
-                    3ème résultat ku implémenté.
+                    3ème résultat ku implémenté. Les matrices creuses 2D sont désormais acceptées.
                 </revdescription>
             </revision>
         </revhistory>
index a89b38d..c1c3ddf 100644 (file)
@@ -38,6 +38,7 @@
                 <listitem>
                     <para>
                         vector, matrix, or hypermatrix of booleans, numbers, or strings.
+                        Numeric or boolean sparses are accepted.
                     </para>
                 </listitem>
             </varlistentry>
@@ -52,8 +53,7 @@
             <varlistentry>
                 <term>U</term>
                 <listitem>
-                    <para>
-                      <itemizedlist>
+                    <itemizedlist>
                         <listitem>
                             <para>
                               If <varname>orient</varname> is not used: Vector of extracted
                           If <varname>orient</varname> is used: Matrix of extracted
                           <varname>M</varname> rows or columns, sorted in lexicographic ascending order.
                         </listitem>
-                      </itemizedlist>
-                    </para>
+                    </itemizedlist>
+                    <para/>
+                    If <varname>M</varname> is sparse, then <varname>U</varname> is always sparse.
+                    <para/>
                 </listitem>
             </varlistentry>
             <varlistentry>
                         </listitem>
                     </itemizedlist>
                     <para/>
+                    <warning>
+                        <varname>ku</varname> is dense, even when <varname>M</varname> is sparse and the
+                        overall "*" mode is used.
+                    </warning>
                 </listitem>
             </varlistentry>
             <varlistentry>
@@ -380,7 +386,7 @@ unique(M, "c")
             <revision>
                 <revnumber>6.1.1</revnumber>
                 <revdescription>
-                    ku 3rd output implemented.
+                    ku 3rd output implemented. Sparse 2D matrices are now accepted.
                 </revdescription>
             </revision>
         </revhistory>
index b6f6eb9..9f4143e 100644 (file)
             <varlistentry>
                 <term>M</term>
                 <listitem>
-                    <para>Vetor, matriz ou hipermatriz de booleanos, números, ou texto.</para>
+                    <para>
+                        Vetor, matriz ou hipermatriz de booleanos, números, ou texto.
+                        Numeric or boolean sparses are accepted.
+                    </para>
                 </listitem>
             </varlistentry>
             <varlistentry>
@@ -68,6 +71,8 @@
                         </listitem>
                       </itemizedlist>
                     </para>
+                    If <varname>M</varname> is sparse, then <varname>U</varname> is always sparse.
+                    <para/>
                 </listitem>
             </varlistentry>
             <varlistentry>
                         </listitem>
                     </itemizedlist>
                     <para/>
+                    <warning>
+                        <varname>ku</varname> is dense, even when <varname>M</varname> is sparse and the
+                        overall "*" mode is used.
+                    </warning>
                 </listitem>
             </varlistentry>
             <varlistentry>
@@ -376,7 +385,7 @@ unique(M, "c")
             <revision>
                 <revnumber>6.1.1</revnumber>
                 <revdescription>
-                    ku 3rd output implemented.
+                    ku 3rd output implemented. Sparse 2D matrices are now accepted.
                 </revdescription>
             </revision>
         </revhistory>
index b76d217..189c19b 100644 (file)
@@ -38,6 +38,7 @@
                 <listitem>
                     <para>
                         вектор, матрица или гиперматрица логических значений, чисел или текстов.
+                        Принимаются числовые или логические разрежённые матрицы.
                     </para>
                 </listitem>
             </varlistentry>
@@ -70,6 +71,9 @@
                         </listitem>
                       </itemizedlist>
                     </para>
+                    <para>
+                        Если <varname>M</varname> является разрежённой, то <varname>U</varname> всегда разрежённая.
+                    </para>
                 </listitem>
             </varlistentry>
             <varlistentry>
@@ -82,7 +86,7 @@
                     </para>
                     <para>
                         <varname>km</varname> является строкой, если <varname>M</varname> является
-                        строкой или если используется <literal>orient="c"</literal>. В проитвном случае
+                        строкой или если используется <literal>orient="c"</literal>. В противном случае
                         это столбец.
                     </para>
                 </listitem>
                         </listitem>
                     </itemizedlist>
                     <para/>
+                    <warning>
+                        <varname>ku</varname> является плотной, даже когда <varname>M</varname>
+                        является разрежённой и используется всеобщий режим "*".
+                    </warning>
                 </listitem>
             </varlistentry>
             <varlistentry>
@@ -380,6 +388,7 @@ unique(M, "c")
                 <revnumber>6.1.1</revnumber>
                 <revdescription>
                   Реализован третий выходной аргумент <literal>ku</literal>.
+                  Теперь принимаются двумерные разрежённые матрицы.
                 </revdescription>
             </revision>
         </revhistory>
index 7d3361a..6591b51 100644 (file)
@@ -19,8 +19,11 @@ function [x, ki, ko, nb] = unique(x, varargin)
     //   - add uniqueNan option: http://bugzilla.scilab.org/15522
     //   - add keepOrder option: http://bugzilla.scilab.org/15795
     //   - add nb output option: http://bugzilla.scilab.org/8418
+    //
     // * 2020 - S. Gougeon :
+    //   - Complex numbers are now completely sorted, by magnitude, + by phase
     //   - add ku output indices: http://bugzilla.scilab.org/16337
+    //   - Sparse 2D matrices accepted: http://bugzilla.scilab.org/15842
 
     keepOrder = %f
     uniqueNan = %f
@@ -180,7 +183,7 @@ function [x, ki, ko, nb] = unique(x, varargin)
             else
                 x = gsort(x,"lr","i");
             end
-            x( find(and(x(2:$,:) == x(1:$-1,:),"c")),:) = [];
+            x(find(and(x(2:$,:) == x(1:$-1,:),"c")),:) = [];
         end
         if  orient==2 | orient=="c" then
             x = x.'
@@ -189,6 +192,7 @@ function [x, ki, ko, nb] = unique(x, varargin)
             nb = nb'
         end
     end
+    ko = full(ko)
 
     if uniqueNan
         x = uniqueProcessNan(x, newInf, "restoreNan")
@@ -247,7 +251,7 @@ function [x, newInf] = uniqueProcessNan(x, newInf, way)
             end
             r(r<>r) = %inf
             i(i<>i) = %inf
-            x = complex(r,i);
+            x = r + imult(i);
         end
 
     // Restoring  NaN
@@ -267,7 +271,7 @@ function [x, newInf] = uniqueProcessNan(x, newInf, way)
                 r(r==newInf) = %inf
                 i(i==newInf) = %inf
             end
-            x = complex(r, i)
+            x = r + imult(i)
         end
     end
 endfunction
diff --git a/scilab/modules/elementary_functions/tests/unit_tests/unique_sparse.tst b/scilab/modules/elementary_functions/tests/unit_tests/unique_sparse.tst
new file mode 100644 (file)
index 0000000..45839ee
--- /dev/null
@@ -0,0 +1,60 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2018 - 2020 - Samuel Gougeon
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+// unit test of unique() for real, complex and boolean SPARSE input
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+
+// ------------------------------------------------------------------
+// We assume that the result of unique(o,..) with a full o is correct.
+// They are tested elsewhere.
+// Here, we compare the result of full(unique(sparse(o),..)) with
+// the one got with unique(o,..).
+// ------------------------------------------------------------------
+esb = sparse(%t); esb(1) = [];
+m = int(sprand(3,20,0.5)*4);
+n = size(m,"*");
+k = grand(1,n/5,"uin",1,n);
+//m(k) = %nan;    // Requires fixing http://bugzilla.scilab.org/16472
+mc = m + imult(m(:,$:-1:1));
+b = m > 1;
+objects = list(..
+   sparse([]), sparse(0), sparse(-7), m(:)', m(:), m, .. // reals
+   sparse(1-%i), mc(:).', mc(:), mc, ..                  // complex
+   esb, sparse(%f), sparse(%t), b(:)', b(:), b);         // booleans
+
+options = list(list(), list("keepOrder"), list("uniqueNan"), list("keepOrder","uniqueNan"));
+for orien = list(list(), "r", "c")
+    for opt = options              // 3 x 4 x 16 x 9 = 1728 tests
+        for o = objects
+            u = unique(o, orien(:), opt(:));
+            fu = unique(full(o), orien(:), opt(:));
+            assert_checktrue(issparse(u));
+            assert_checkequal(full(u), fu);
+        
+            [u, ki, ku, nb] = unique(o, orien(:), opt(:));
+            [fu, fki, fku, fnb] = unique(full(o), orien(:), opt(:));
+
+            assert_checktrue(issparse(u));
+            assert_checkfalse(issparse(ki));
+            assert_checkfalse(issparse(ku));
+            assert_checkfalse(issparse(nb));
+            assert_checkequal(full(u), fu);
+            select orien
+            case list()
+                assert_checkequal(u, o(ki));
+                assert_checkequal(o, matrix(u(ku),size(o)));
+            case "r"
+                assert_checkequal(u, o(ki,:));
+                assert_checkequal(o, matrix(u(ku,:),size(o)));
+            case "c"
+                assert_checkequal(u, o(:,ki));
+                assert_checkequal(o, matrix(u(:,ku),size(o)));
+            end
+        end
+    end
+end