1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 // Copyright (C) 2012 - 2016 - Scilab Enterprises
4 // Copyright (C) 2018, 2019 - Samuel GOUGEON
6 // This file is hereby licensed under the terms of the GNU GPL v2.0,
7 // pursuant to article 5.3.4 of the CeCILL v.2.1.
8 // This file was originally licensed under the terms of the CeCILL v2.1,
9 // and continues to be available under such terms.
10 // For more information, see the COPYING file which you should have received
11 // along with this program.
13 function [x, ki, ko, nb] = unique(x, varargin)
14 // extract unique components of a vector
15 // varargin : orient=1|2|"r"|"c", "uniqueNan", "keepOrder"
18 // * 2019 - S. Gougeon :
19 // - add uniqueNan option: http://bugzilla.scilab.org/15522
20 // - add keepOrder option: http://bugzilla.scilab.org/15795
21 // - add nb output option: http://bugzilla.scilab.org/8418
26 newInf = [] // init Inf substitute in case of "uniqueNan" and or(x==%inf)
31 // CHECKING INPUT ARGUMENTS
32 // ------------------------
34 i = 2; // index of the current input argument
37 if typeof(a)=="string"
54 msg = _("%s: Argument #%d: Must be in the set {%s}.\n")
55 error(msprintf(msg, "unique", i, "1,2,""r"",""c"",""keepOrder"",""uniqueNan"""))
60 while size(in)>0 & i<5 then
62 if typeof(a)=="string"
71 msg = _("%s: Argument #%d: Must be in the set {%s}.\n")
72 error(msprintf(msg, "unique", i, """keepOrder"",""uniqueNan"""))
77 uniqueNan = uniqueNan & or(type(x)==[1 5])
80 if size(x, orient)==1 then
85 [x, newInf] = uniqueProcessNan(x, [], "removeNan")
87 getK = argn(1)>1 | keepOrder
93 return // ki, nb are already []. x is [] or sparse([])
96 // PROCESSING complex numbers
97 // --------------------------
98 if or(type(x)==[1 5]) then
104 x = [real(x(:)) imag(x(:))]
108 [x, ki, ko, nb] = unique(x,"r")
110 x = complex(x(:,1),x(:,2));
111 if sz(1)==1 // => put results in row
118 elseif orient=="r" | orient==1
119 x = [real(x) imag(x)]
123 [x, ki, ko, nb] = unique(x,"r")
125 x = complex(x(:,1:sz(2)), x(:,sz(2)+1:$));
126 elseif orient=="c" | orient==2
127 x = [real(x) ; imag(x)]
131 [x, ki, ko, nb] = unique(x,"c")
133 x = complex(x(1:sz(1),:), x(sz(1)+1:$,:));
136 x = uniqueProcessNan(x, newInf, "restoreNan")
139 [ki, kk] = gsort(ki,"g","i")
155 // PROCESSING text and other numerical types
156 // -----------------------------------------
159 [x,ki] = gsort(x,"g","i");
160 keq = x(2:$) == x(1:$-1);
162 nb = [0 find(~keq) size(x,"*")]
163 nb = nb(2:$) - nb(1:$-1)
166 if keq<>[] then keq = keq+1;end
169 if size(x,1)>1 | ndims(x)>2
175 x = gsort(x,"g","d");
177 x( find(x(2:$) == x(1:$-1)) ) = [];
179 elseif orient==1|orient=="r" then
181 [x,ki] = gsort(x,"lr","i");
182 keq = and(x(2:$,:) == x(1:$-1,:),"c")
184 nb = [0 find(~keq) size(x,1)]
185 nb = nb(2:$) - nb(1:$-1)
189 if keq<>[] then keq = keq+1;end
193 x = gsort(x,"lr","i");
194 x( find(and(x(2:$,:) == x(1:$-1,:),"c")),:) = [];
196 elseif orient==2|orient=="c" then
198 [x,ki] = gsort(x,"lc","i");
199 keq = and(x(:,2:$) == x(:,1:$-1),"r")
201 nb = [0 find(~keq) size(x,2)]
202 nb = nb(2:$) - nb(1:$-1)
205 if keq<>[] then keq = keq+1;end
209 x = gsort(x,"lc","i");
210 x(:, find(and(x(:,2:$) == x(:,1:$-1),"r")) ) = [];
214 x = uniqueProcessNan(x, newInf, "restoreNan")
217 [ki, kk] = gsort(ki,"g","i")
231 // -------------------------------------------------------------------
233 // To consider Nan mutually equal, we replace all of them with a "regular" substitute.
234 // Since Nan are sorted as > Inf, we must use anyway Inf as the Nan substitute.
235 // If the original array have already some Inf, we must priorly replace them with
236 // a decimal greater than the finite maximum of the array values.
237 // After processing, we restore Inf => Nan (, and maxNum => Inf).
239 function [x, newInf] = uniqueProcessNan(x, newInf, way)
241 if way=="removeNan" & or(isnan(x)) then
247 m = max([1 max(x(~b))])
271 elseif way=="restoreNan"