management of hypermatrix in repmat.
[scilab.git] / scilab / modules / elementary_functions / macros / repmat.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) - 2011 -  INRIA, Serge Steer
3 // This file must be used under the terms of the CeCILL.
4 // This source file is licensed as described in the file COPYING, which
5 // you should have received as part of this distribution.  The terms
6 // are also available at
7 // http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
8 function B = repmat(A,varargin)
9     //ajouter test sur les type des elements de varargin
10     rhs = argn(2);
11     if rhs < 2 then
12         error(msprintf(_("%s: Wrong number of input arguments: at least %d expected.\n"), "repmat", 2))
13     end
14
15     narg=size(varargin);
16
17     // Test varargin
18     if narg==1 then
19         // Scalar of vector needed
20         if typeof(varargin(1)) <> "constant" then
21             error(msprintf(_("%s: Wrong type for input argument #%d: A real scalar or vector expected.\n"), "repmat", 2))
22         end
23         if size(varargin(1),'*')<>1 & isempty(find(size(varargin(1))==1)) then
24             error(msprintf(_("%s: Wrong size for input argument #%d: A real scalar or vector expected.\n"), "repmat", 2))
25         end
26     else
27         for i=1:narg
28             if typeof(varargin(i)) <> "constant" then
29                 error(msprintf(_("%s: Wrong type for input argument #%d: A real scalar expected.\n"), "repmat", i+1))
30             end
31             if size(varargin(i),"*")<>1 then
32                 error(msprintf(_("%s: Wrong size for input argument #%d: A real scalar expected.\n"), "repmat", i+1))
33             end
34         end
35     end
36
37     if type(A)>10 then
38         if typeof(A)=="rational" then
39             B=rlist(repmat(A.num,varargin(:)),repmat(A.den,varargin(:)),A.dt)
40             return
41         else
42             execstr('B=%'+typeof(A)+"_repmat(A,varargin(:))")
43             return
44         end
45     end
46
47     if narg==1 then
48         if size(varargin(1),'*')==1 then
49             siz=list(varargin(1),varargin(1))
50         else //convert array into list
51             tmp=varargin(1)
52             siz=list();
53             for i=1:size(tmp,'*'),siz(i)=tmp(i); end
54         end
55     else
56         siz=list();
57         for i=1:narg
58             siz(i)=varargin(i)
59         end
60     end
61
62     nd=size(siz)
63     if or(type(A)==[5 6]) then //sparse matrices
64         if nd>2 then
65             error(msprintf(_("%s: Wrong number of output matrix dimensions required: %d expected for sparse matrices.\n"), "repmat", 2))
66         end
67     end
68
69     for i=size(siz):-1:3
70         if siz(i)>1 then break,end
71         nd=nd-1
72     end
73     sizA=size(A)
74     nda=size(sizA,'*')
75
76     if and(sizA==1) then //scalar case
77
78         //this case can also be handled by the general one but in a less
79         //efficient way
80         if nd<=2 then
81             B=A(ones(siz(1:nd)))
82         else
83             s=1;for k=1:nd;s=s*siz(k),end
84             B=matrix(A(ones(s,1)),siz(1:nd))
85         end
86     else //general case
87         if nda<nd then
88             sizA(nda+1:nd)=1;
89         elseif  nda>nd then
90             for k=nd+1:nda
91                 siz(k)=1
92             end
93             nd=nda
94         end
95         I=list();
96         for i=1:nd
97             ind=matrix(1:sizA(i),-1,1);
98             ind=ind(:,ones(1,siz(i)));
99             I(i)=ind;
100         end
101
102         if nda > 2 | (size(varargin(1),"*") <> 1 & size(varargin(1)) <3) then // Works if A is hypermat but not for int8,int16 matrix
103             B=A(I(:));
104         else // Works for int8, int16... matrix but not for hypermat
105             if rhs ==2 then
106                 if size(varargin(1),"*") <> 1 then // case repmat(A,size)
107                     varargin_temp=varargin;
108                     if size(varargin(1),1) <> 1 & size(varargin(1),2) == 1 then
109                         for i=1:size(varargin(1),1)
110                             varargin(i)=varargin_temp(1)(i);
111                         end
112                     elseif size(varargin(1),2) <> 1 & size(varargin(1),1) == 1 then
113                         for i=1:size(varargin(1),2)
114                             varargin(i)=varargin_temp(1)(i);
115                         end
116                     else
117                         error(msprintf(_("%s: Wrong size for input argument #%d: a vector expected.\n"),"repmat",2));
118                     end
119                 end
120             end
121             res=A(I(1),I(2));
122             A_base=matrix(res,size(res,1)*size(res,2),1);
123             dims=[size(A,1)*varargin(1)];
124             for i=2:size(varargin) //compute dims
125                 dims_1=[size(A,i)*varargin(i)];
126                 dims=[dims, dims_1];
127             end
128             nb=1;
129             flag=0;
130             for i=3:size(varargin)
131                 nb=nb*varargin(i);
132                 if varargin(i)~=1 then // dims[2 2 1 1]=>dims[2 2]
133                     flag=1;
134                 end
135             end
136             if size(varargin) ==1 then // dims[2] => dims[2 2]
137                 varargin(2) = varargin(1);
138             end
139             if flag == 0 then
140                 B=matrix(A_base,varargin(1)*size(A,1), varargin(2)*size(A,2));
141             else
142                 J1=[1:size(A_base,1)];
143                 J=J1;
144                 for k=1:nb-1
145                     J=[J,J1];
146                 end
147                 J=J';
148                 A_final=A_base(J);
149                 B=matrix(A_final, dims);
150             end
151         end
152     end
153 endfunction
154