* Bug #13409 fixed - permute(x, dims) failed when dims was greater than the dimension...
[scilab.git] / scilab / modules / elementary_functions / macros / permute.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) INRIA - Farid BELAHCENE
3 // Copyright (C) 2013 - Samuel GOUGEON : processing rewritten, fixing http://bugzilla.scilab.org/5205
4 //
5 // This file must be used under the terms of the CeCILL.
6 // This source file is licensed as described in the file COPYING, which
7 // you should have received as part of this distribution.  The terms
8 // are also available at
9 // http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10
11 function y = permute(x, dims)
12
13     // This function returns an array y which results of the x permutation
14     // Input :
15     // -x a (multi-dimensionnnal) array of cells, or doubles or strings, ...
16     // -dims a vector which contains the permutation order
17     // Output :
18     // -y the result of the x permutation
19
20     // Verify input arguments number
21     if argn(2) <> 2 then
22         error(msprintf(gettext("%s: Wrong number of input argument(s): %d expected.\n"), "permute", 2));
23     end
24
25     // Verify if the size of dims corresponds to dimension of x
26     if ndims(dims) <> 2 then
27         error(msprintf(gettext("%s: Wrong size for argument #%d: Vector expected.\n"), "permute", 2));
28
29     elseif or(gsort(dims,"c","i") <> (1:prod(size(dims)))) then
30         error(msprintf(gettext("%s: Wrong value for input argument #%d: Must be a valid permutation vector.\n"), "permute", 2));
31
32     elseif prod(size(dims)) < ndims(x) then
33         error(msprintf(gettext("%s: Wrong size for input argument #%d: At least the size of input argument #%d expected.\n"), "permute", 2, 1));
34     end
35
36     // Case x is empty
37     if isempty(x) then
38         y = x
39         return
40     end
41
42     // ---------------- PROCESSING --------------------
43     // Existing indices
44     s = size(x)
45     p = size(x, "*")
46
47     // Treat extra dimensions for permutations as 1
48     s = [s ones(1, length(dims) - length(s))];
49
50     n = 1
51     for i = 1:length(s)
52         t = "x%d = ones(1,p/(prod(s(1:%d)))) .*. ((1:s(%d)) .*. ones(1,n)) ;"+..
53         " n = prod(s(1:%d))\n"
54         t = msprintf(t, i, i, i, i)
55         execstr(t)
56     end
57     xlist = strcat(msprintf("x%d\n",(1:length(s))'),",")
58     cstr = "sub2ind(s,"+ xlist +")"
59     execstr("LI = "+cstr)
60
61     // New indices
62     s = s(dims)
63     cstr = "sub2ind(s,"+ strcat(msprintf("x%d\n", dims(:)), ",")+")"
64     execstr("LI2 = "+cstr)
65
66     // Clearing intermediate memory used
67     execstr("clear "+strsubst(xlist, ",", " "))
68
69     // Permutation
70     if typeof(x) == "ce"
71         y = x
72         y.dims = int32(s)
73         y(LI2).entries = x(LI).entries
74     else
75         y(LI2) = x(LI)
76         y = matrix(y, s)
77     end
78
79 endfunction