* Bug 15737 fixed: setdiff() dit not support complex numbers 58/20858/8
Samuel GOUGEON [Mon, 21 Jan 2019 07:03:38 +0000 (08:03 +0100)]
  http://bugzilla.scilab.org/15737

  + speed up: k is no longer computed when it is not requested.

Change-Id: I1dac082acb75ec9ce419eaa0822833566c32ac67

scilab/CHANGES.md
scilab/modules/elementary_functions/help/en_US/setoperations/setdiff.xml
scilab/modules/elementary_functions/help/ru_RU/setoperations/setdiff.xml
scilab/modules/elementary_functions/macros/setdiff.sci
scilab/modules/elementary_functions/tests/nonreg_tests/bug_15737.tst [new file with mode: 0644]

index f4a23f5..4898fd5 100644 (file)
@@ -143,6 +143,7 @@ Feature changes and additions
 * `gsort` can now perform multilevel sorting. This noticeably allows to sort completely complex numbers.
 * `factorial(n)` can be used now from n=171 up to n=10^14.
 * `intersect()` now supports complex numbers.
+* `setdiff()` now supports complex numbers.
 
 
 Help pages:
@@ -278,6 +279,7 @@ Bug Fixes
 * [#15534](http://bugzilla.scilab.org/show_bug.cgi?id=15534): Booleans and encoded integers could not be concatenated together.
 * [#15577](http://bugzilla.scilab.org/show_bug.cgi?id=15577): `edit` did not accept a line number as text, as with `edit linspace 21`.
 * [#15580](http://bugzilla.scilab.org/show_bug.cgi?id=15580): `det(sparse([],[]))` yielded an error.
+* [#15737](http://bugzilla.scilab.org/show_bug.cgi?id=15737): `setdiff` was wrong with complex numbers.
 * [#15981](http://bugzilla.scilab.org/show_bug.cgi?id=15981): `wavread()` kept the wav file open and locked when returning on errors. It weakly managed the input file name. It claimed for invalid data formats instead of unsupported ones, with poor information about the current format vs the supported ones. Several error messages refered to a wrong function.
 * [#15595](http://bugzilla.scilab.org/show_bug.cgi?id=15595): `unique()` was not able to return distinct values in their original order, without sorting them. A `keepOrder` option now allows it.
 * [#15668](http://bugzilla.scilab.org/show_bug.cgi?id=15668): `save(filename)` saved all predefined Scilab constants %e %pi etc.. (regression)
index b21758c..6df05ff 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) 2018 - Samuel GOUGEON
+ * Copyright (C) 2018 - 2019 - 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.
@@ -38,8 +38,8 @@
                 <term>a, b</term>
                 <listitem>
                     <para>
-                        vectors, matrices or hypermatrices of real numbers or encoded integers or
-                        strings. Both must have the same data types (and integer types).
+                        vectors, matrices or hypermatrices of real or complex numbers, or encoded
+                        integers, or strings. Both must have the same data types (and integer types).
                     </para>
                     <para>
                         If the option <literal>orien="r"</literal> is used, <literal>a</literal>
@@ -314,6 +314,12 @@ r, k
                     Option "r" | "c" added, including for hypermatrices.
                 </revdescription>
             </revision>
+            <revision>
+                <revnumber>6.1.0</revnumber>
+                <revdescription>
+                    Complex numbers are now accepted.
+                </revdescription>
+            </revision>
         </revhistory>
     </refsection>
 </refentry>
index fcdd524..742bc24 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) 2018 - Samuel GOUGEON
+ * Copyright (C) 2018 - 2019 - 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.
@@ -38,9 +38,9 @@
                 <term>a, b</term>
                 <listitem>
                     <para>
-                        векторы, матрицы или гиперматрицы вещественных чисел или кодированных
-                        целых чисел или строк. Оба должны иметь одинаковые типы данных (или типы
-                        целых чисел).
+                        векторы, матрицы или гиперматрицы действительных или комплексных чисел,
+                        или закодированные целые числа, или строки.
+                        Оба должны иметь одинаковые типы данных (или типы целых чисел).
                     </para>
                     <para>
                         Если используется опция <literal>orien="r"</literal>, то
@@ -56,7 +56,8 @@
                     направленная обработка:
                     <itemizedlist>
                         <listitem>
-                            <literal>"r"</literal>: строки из <literal>a</literal> ищутся среди строк в <literal>b</literal>.
+                            <literal>"r"</literal>: строки из <literal>a</literal> ищутся среди
+                            строк в <literal>b</literal>.
                         </listitem>
                         <listitem>
                             <literal>"c"</literal>: столбцы из <literal>a</literal> ищутся среди
         </para>
         <para>
             Формат результатов представлен в следующей таблице, в соответствии с формой
-            <literal>a</literal> и опцией <literal>orien</literal>. Во всех случаях, если все элементы <literal>a</literal> находятся в <literal>b</literal>, возвращается
+            <literal>a</literal> и опцией <literal>orien</literal>. Во всех случаях, если все
+            элементы <literal>a</literal> находятся в <literal>b</literal>, возвращается
             <literal>[]</literal> для <literal>v</literal> как для <literal>ka</literal>:
             <table>
                 <tr>
         </para>
         <para>
             <literal>v</literal> и <literal>ka</literal> становятся пустыми
-            <literal>[]</literal>, если <literal>a</literal> пуста (либо <literal>b</literal>), или все элементы <literal>a</literal> находятся в <literal>b</literal>.
+            <literal>[]</literal>, если <literal>a</literal> пуста (либо <literal>b</literal>),
+            или все элементы <literal>a</literal> находятся в <literal>b</literal>.
         </para>
     </refsection>
     <refsection>
@@ -305,6 +308,12 @@ r, k
                     Добавлены опции "r" | "c", включая гиперматрицы.
                 </revdescription>
             </revision>
+            <revision>
+                <revnumber>6.1.0</revnumber>
+                <revdescription>
+                    Теперь допускаются комплексные числа.
+                </revdescription>
+            </revision>
         </revhistory>
     </refsection>
 </refentry>
index 88fcb6d..0ddf120 100644 (file)
@@ -16,8 +16,9 @@ function [a, ka] = setdiff(a, b, orien)
 
     // History:
     // * 2018 - S. Gougeon : orien="r"|"c" added, including the hypermat case
+    // * 2019 - S. Gougeon : complex numbers supported
 
-    rhs = argn(2);
+    [lhs, rhs] = argn();
 
     // CHECKING INPUT ARGUMENTS
     // ========================
@@ -52,6 +53,7 @@ function [a, ka] = setdiff(a, b, orien)
 
     // PROCESSING
     // ==========
+    Complexes = (type(a)==1 && ~isreal(a)) | (type(b)==1 && ~isreal(b));
     // "r" or "c"
     // ----------
     if orien then
@@ -61,41 +63,84 @@ function [a, ka] = setdiff(a, b, orien)
         if ndims(b) > 2 then
             b = serialize_hypermat(b, orien)
         end
-        [a, ka] = unique(a, orien)
-        if isempty(b)
-            return
-        end
-        it = inttype(a)
-        b = unique(b, orien)
-        if orien==2
-            a = a.'
-            b = b.'
-        end
-        [c, kc] = gsort([[a iconvert(ones(a(:,1)),it)] ;
-                         [b iconvert(ones(b(:,1))*2,it)]], "lr","i")
-        k = find(or(c(1:$-1,1:$-1)~=c(2:$,1:$-1),"c") & c(1:$-1,$)==1)
-        if c($,$)==1
-            k = [k size(c,1)]
-        end
-        ka = ka(kc(k))
-        // a = a(ka,:) // in initial order
-        a = c(k,1:$-1)
-        if orien==2
-            ka = matrix(ka, 1, -1)
-            a = a.'
+        if lhs > 1
+            [a, ka] = unique(a, orien)
+            if isempty(b)
+                return
+            end
+            it = inttype(a)
+            b = unique(b, orien)
+            if orien==2
+                a = a.'
+                b = b.'
+            end
+            if Complexes
+                [c, kc] = gsort([[a iconvert(ones(a(:,1)),it)] ;
+                                 [b iconvert(ones(b(:,1))*2,it)]], ..
+                                "lr", ["i" "i"], list(abs, atan))
+            else
+                [c, kc] = gsort([[a iconvert(ones(a(:,1)),it)] ;
+                                 [b iconvert(ones(b(:,1))*2,it)]], "lr","i")
+            end
+            k = find(or(c(1:$-1,1:$-1)~=c(2:$,1:$-1),"c") & c(1:$-1,$)==1)
+            if c($,$)==1
+                k = [k size(c,1)]
+            end
+            ka = ka(kc(k))
+            // a = a(ka,:) // in initial order
+            a = c(k,1:$-1)
+            if orien==2
+                ka = matrix(ka, 1, -1)
+                a = a.'
+            end
+        else
+            a = unique(a, orien)
+            if isempty(b)
+                return
+            end
+            it = inttype(a)
+            b = unique(b, orien)
+            if orien==2
+                a = a.'
+                b = b.'
+            end
+            if Complexes
+                c = gsort([[a iconvert(ones(a(:,1)),it)] ;
+                           [b iconvert(ones(b(:,1))*2,it)]], ..
+                           "lr", ["i" "i"], list(abs, atan))
+            else
+                c = gsort([[a iconvert(ones(a(:,1)),it)] ;
+                           [b iconvert(ones(b(:,1))*2,it)]], "lr","i")
+            end
+            k = find(or(c(1:$-1,1:$-1)~=c(2:$,1:$-1),"c") & c(1:$-1,$)==1)
+            if c($,$)==1
+                k = [k size(c,1)]
+            end
+            // a = a(ka,:) // in initial order
+            a = c(k,1:$-1)
+            if orien==2
+                a = a.'
+            end
         end
+
     else
         // by element
         // ----------
-        [a,ka] = unique(a);
+        if lhs > 1
+            [a,ka] = unique(a);
+        else
+            a = unique(a);
+        end
         na = size(a,"*");
         if isempty(b)
             return
         end
-
         b = unique(b(:));
-
-        [x,k] = gsort([a(:); b], "g", "i");
+        if Complexes
+            [x,k] = gsort([a(:); b], "g", ["i" "i"], list(abs, atan));
+        else
+            [x,k] = gsort([a(:); b], "g", "i");
+        end
         d = find(x(2:$)==x(1:$-1));  //index of common entries in sorted table
         if d <> [] then
             k([d;d+1]) = [];
@@ -103,7 +148,9 @@ function [a, ka] = setdiff(a, b, orien)
 
         keep = find(k <= na);
         a = a(k(keep));
-        ka = ka(k(keep));
+        if lhs > 1
+            ka = ka(k(keep))
+        end
     end
 endfunction
 // ----------------------------------------------------------------------------
diff --git a/scilab/modules/elementary_functions/tests/nonreg_tests/bug_15737.tst b/scilab/modules/elementary_functions/tests/nonreg_tests/bug_15737.tst
new file mode 100644 (file)
index 0000000..6825e56
--- /dev/null
@@ -0,0 +1,20 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2020 - Samuel GOUGEON
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+
+// <-- Non-regression test for bug 15737 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/15737
+//
+// <-- Short Description -->
+// setdiff() was wrong for complex numbers.
+
+assert_checkequal(setdiff([1+%i 1-%i],1-%i), 1+%i);
+assert_checkequal(setdiff(1-%i, [1-%i 1+%i]), []);