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