1function p = uperm(a)
2% Return all unique permutations of possibly-repeating array elements
3% =========================================================================
4% Copyright (C) 2014 Bruno Luong <brunoluong@yahoo.com>
5% Copyright (C) 2020 Dynare Team
6%
7% This file is part of Dynare.
8%
9% Dynare is free software: you can redistribute it and/or modify
10% it under the terms of the GNU General Public License as published by
11% the Free Software Foundation, either version 3 of the License, or
12% (at your option) any later version.
13%
14% Dynare is distributed in the hope that it will be useful,
15% but WITHOUT ANY WARRANTY; without even the implied warranty of
16% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17% GNU General Public License for more details.
18%
19% You should have received a copy of the GNU General Public License
20% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
21% =========================================================================
22% Original author: Bruno Luong <brunoluong@yahoo.com>, April 20, 2014
23% https://groups.google.com/d/msg/comp.soft-sys.matlab/yQKVPTYrv6Q/gw1MzNd9sYkJ
24% https://stackoverflow.com/a/42810388
25
26[u, ~, J] = unique(a);
27p = u(up(J, length(a)));
28
29function p = up(J, n)
30ktab = histc(J,1:max(J));
31l = n;
32p = zeros(1, n);
33s = 1;
34for i=1:length(ktab)
35    k = ktab(i);
36    c = nchoosek(1:l, k);
37    m = size(c,1);
38    [t, ~] = find(~p.');
39    t = reshape(t, [], s);
40    c = t(c,:)';
41    s = s*m;
42    r = repmat((1:s)',[1 k]);
43    q = accumarray([r(:) c(:)], i, [s n]);
44    p = repmat(p, [m 1]) + q;
45    l = l - k;
46end
47end
48
49end % uperm