* Bug 8297 fixed: cat() slowness was crippling. Rewritten
[scilab.git] / scilab / modules / elementary_functions / macros / cat.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 //
3 // Copyright (C) 2017 - Samuel GOUGEON : cat() rewritten: http://bugzilla.scilab.org/8297
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
12 function  y = cat(dim, varargin)
13     // dim: scalar = dimension # along which input arrays are stacked
14     // varargin: input arrays: matrices, hypermatrices, cells arrays, struct
15     //           arrays, custom mlists,.. For custom arrays, [,] and [;] may be
16     //           not defined. Must be all of the same sizes, except along dim.
17     // y : concatenated array
18
19     rhs = argn(2);
20     if rhs < 2 then
21         msg = gettext("%s: Wrong number of input argument(s): %d expected.\n")
22         error(msprintf(msg,"cat", 1));
23     end
24
25     // dim must be a positive real
26     if type(dim)==1 & dim>=0 & size(dim,"*")==1
27         dim = max(1,round(dim));
28     else
29         msg = gettext("%s: Wrong type for input argument #%d: A positive real expected.\n");
30         error(msprintf(msg, "cat", 1));
31     end
32
33     // CHECK INPUT ARRAYS
34     //  - empty arrays are ignored
35     for i = size(varargin):-1:1
36         if isempty(varargin(i)) then
37             varargin(i) = null();
38         end
39     end
40     // - cat(m,[]), cat(m)  => []
41     if isempty(varargin) then
42         y = [];
43         return
44     end
45     // - if just one input argument to concatenate, then return this argument
46     if size(varargin) == 1 then
47         y = varargin(1);
48         return
49     end
50     //  - they must all have the same sizes (except along dim)
51     v = varargin(1);
52     S = size(v);
53     if length(S) < dim then
54         S = [S ones(1, dim-length(S))];
55     end
56     S(dim) = -1;
57     for i = 2:size(varargin)
58         s = size(varargin(i));
59         s(dim) = -1;
60         s(find(s==0)) = 1;
61         if ~and(s==S)
62             msg = gettext("%s: Wrong size for input arguments: Same size expected.\n");
63             error(msprintf(msg, "cat"));
64         end
65     end
66     // They must be all of the same type: cell, struct, or other
67     T = typeof(v)
68     for i = 2:size(varargin)
69         v = varargin(i)
70         if typeof(v)~=T
71             msg = gettext("%s: Wrong type for input arguments: Same types expected.\n");
72             error(msprintf(msg, "cat"));
73         end
74     end
75
76     // PROCESSING
77     // ----------
78     y = varargin(1);
79     [vcat, hcat] = (%t, %t);
80     if type(y)>10
81         t = typeof(y, "overload");
82         if ~or(t==["ce" "st"])
83             [vcat, hcat] = (isdef("%"+t+"_f_"+t,"n"), isdef("%"+t+"_c_"+t,"n"));
84         end
85     end
86     if dim==1 & vcat then
87         for i = 2:length(varargin)
88             y = [y ; varargin(i)];
89         end
90     elseif dim==2 & hcat
91         for i = 2:length(varargin)
92             y = [y, varargin(i)];
93         end
94     else
95         nd = max(ndims(y),dim);
96         st = emptystr(1,nd) + ":";
97         st(dim) = "%d:%d";
98         st = strcat(st,",");
99         Cmd = "y("+st+") = varargin(i);"
100         sy = size(y,dim);
101         for i = 2:length(varargin)
102             s = size(varargin(i), dim);
103             cmd = msprintf(Cmd,sy+1,sy+s);
104             execstr(cmd);
105             sy = sy + s;
106         end
107     end
108 endfunction