e22ed9bb1333202973bc60238cc0a7cd5908675c
[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 //
4 // This file must be used under the terms of the CeCILL.
5 // This source file is licensed as described in the file COPYING, which
6 // you should have received as part of this distribution.  The terms
7 // are also available at
8 // http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
9
10 function y = permute(x, dims)
11
12     // This function returns an array y which results of the x permutation
13     // Input :
14     // -x a (multi-dimensionnnal) array of cells, or doubles or strings, ...
15     // -dims a vector which contains the permutation order
16     // Output :
17     // -y the result of the x permutation
18
19     // Verify input arguments number
20     if argn(2) <> 2 then
21         error(msprintf(gettext("%s: Wrong number of input argument(s): %d expected.\n"), "permute", 2));
22     end
23
24     // Verify if the size of dims corresponds to dimension of x
25     if ndims(dims) <> 2 then
26         error(msprintf(gettext("%s: Wrong size for argument #%d: Vector expected.\n"), "permute", 2));
27
28     elseif or(gsort(dims,"c","i") <> (1:prod(size(dims)))) then
29         error(msprintf(gettext("%s: Wrong size for input argument #%d.\n"), "permute", 2));
30
31     elseif prod(size(dims)) < ndims(x) then
32         error(msprintf(gettext("%s: Wrong size for input argument #%d: At least the size of input argument #%d expected.\n"), "permute", 2, 1));
33     end
34
35     // Case x is empty
36     if isempty(x) then
37         y = x
38         return
39     end
40
41     // xsize vector contains the size of x
42     xsize = size(x)
43     // ysize vector contains the new size of x after the permutation
44     ind1 = find(dims<=ndims(x))
45     ind2 = find(dims>ndims(x))
46     ysize(ind1) = xsize(dims(ind1))
47     ysize(ind2) = 1
48     dims = dims(ind1)
49
50     // Delete the last dimensions of ysize which are equal to 1, ex : [2,3,1,4,1,1,1] -> [2,3,1,4]
51     i = prod(size(ysize))
52     while i>2 & ysize(i)==1 & i>max(ind1)
53         ysize(i) = []
54         i = i-1
55     end
56
57     // index vector contains all indices of x
58     index = zeros(1, prod(xsize)*length(xsize)); // Preallocate index
59     m = 1; // Iterator on index
60     for k=1:size(xsize,"*")
61         for j=1:size(x,"*")/prod(xsize(1:k))
62             for l=1:xsize(k)
63                 temp = ones(1, prod(xsize(1:k-1)))*l;
64                 index(1, m:m+size(temp,"*")-1) = temp;
65                 m = m+size(temp, "*"); // Pad m with the size of the vector we just computed
66             end
67         end
68     end
69     index = matrix(index, size(x, "*"), size(xsize, "*"))
70
71     // prodxsize is a vector, its ith component contains the prod of the first to the (ith-1) entries of xsize, its first component is always equal to one
72     prodxsize = ones(size(xsize, "*"), 1)
73     for i=2:size(xsize,"*")
74         prodxsize(i) = prod(xsize(1:i-1))
75     end
76     prodysize = ones(size(xsize, "*"), 1)
77     for i=2:size(ysize,"*")
78         prodysize(i) = prod(ysize(1:i-1))
79     end
80
81     // newindex contains the indices of x dimensions permutation
82     for j=1:size(index,1)
83         indexj = index(j, :)
84         newindexj = ones(1:prod(size(ysize)))
85         newindexj(ind1) = indexj(dims)
86         indexj(2:$) = indexj(2:$)-1
87         newindexj(2:$) = newindexj(2:$)-1
88         if typeof(x) == "ce" then // Case x is a cell array
89             y(newindexj*prodysize).entries = x(indexj*prodxsize).entries
90         else
91             y(newindexj*prodysize) = x(indexj*prodxsize)
92         end
93     end
94
95     y = matrix(y, ysize)
96
97 endfunction