in a dynamical list set from Scinotes favorite and most recent directories.
* `size` can now be overloadable for tlist lists, as it already could for mlist lists.
* `gcd` now accepts `int64` and `uint64` integers. The input can now be any array instead of a row.
+* `cat` has been rewritten. It is now fast and can process heavy arrays at high dimensions.
Help pages:
### Bugs fixed in 6.0.1:
* [#4276](http://bugzilla.scilab.org/show_bug.cgi?id=4276): `strsubst` replaced the first occurence in regex mode.
* [#5278](http://bugzilla.scilab.org/show_bug.cgi?id=5278): obsolete `xset()` was still used in scripts, macros, tests and help pages.
+* [#8297](http://bugzilla.scilab.org/show_bug.cgi?id=8297): `cat` slowness was exponential, crippling, and made it useless.
* [#11756](http://bugzilla.scilab.org/show_bug.cgi?id=11756): In the categories of the ATOMS GUI, actually available modules might be not listed.
* [#12195](http://bugzilla.scilab.org/show_bug.cgi?id=12195): `generateBlockImage` sometimes changed the current graphic driver.
* [#12771](http://bugzilla.scilab.org/show_bug.cgi?id=12771): xcosPalGenerateAllIcons help example was broken.
// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) INRIA - Farid BELAHCENE
-// Copyright (C) DIGITEO - 2011 - Allan CORNET
//
-// Copyright (C) 2012 - 2016 - Scilab Enterprises
+// Copyright (C) 2017 - Samuel GOUGEON : cat() rewritten: http://bugzilla.scilab.org/8297
//
// This file is hereby licensed under the terms of the GNU GPL v2.0,
// pursuant to article 5.3.4 of the CeCILL v.2.1.
// For more information, see the COPYING file which you should have received
// along with this program.
-function y = cat(dims, varargin)
- //
- // CAT function concatenates the inputs arguments (included in varargin) according to dims
- // if dims=1 then concatenation is done according to the rows of the input arguments, if dims=2 then concatenation is done according to the columns of the input arguments,...
- // Output
- // -y : a (multi) array, the result of the concatenation
- // Input
- // -dims : a scalar, the dimension chosen for the concatenation
- // -varargin : scalars, matrices, hypermatrices to concatenate
- // F.B
-
+function y = cat(dim, varargin)
+ // dim: scalar = dimension # along which input arrays are stacked
+ // varargin: input arrays: matrices, hypermatrices, cells arrays, struct
+ // arrays, custom mlists,.. For custom arrays, [,] and [;] may be
+ // not defined. Must be all of the same sizes, except along dim.
+ // y : concatenated array
rhs = argn(2);
- if rhs < 1 then
- error(msprintf(gettext("%s: Wrong number of input argument(s): %d expected.\n"),"cat", 1));
+ if rhs < 2 then
+ msg = gettext("%s: Wrong number of input argument(s): %d expected.\n")
+ error(msprintf(msg,"cat", 1));
end
- // dims must be a positive real
- if type(dims)==1 & dims>=0 & size(dims,"*")==1
- dims = max(1,round(dims));
+ // dim must be a positive real
+ if type(dim)==1 & dim>=0 & size(dim,"*")==1
+ dim = max(1,round(dim));
else
- error(msprintf(gettext("%s: Wrong type for input argument #%d: A positive real expected.\n"),"cat",1));
- end
-
- // verify if dims value is superior to the dimension of the input arguments
- dimssupvar = %t;
- for i = 1:size(varargin)
- if ndims(varargin(i))>=dims then
- dimssupvar = %f;
- end
+ msg = gettext("%s: Wrong type for input argument #%d: A positive real expected.\n");
+ error(msprintf(msg, "cat", 1));
end
- // delete all empty input arguments
- for i = size(varargin):-1:2
+ // CHECK INPUT ARRAYS
+ // - empty arrays are ignored
+ for i = size(varargin):-1:1
if isempty(varargin(i)) then
varargin(i) = null();
end
end
-
- // if just one input argument to concatenate then return this argument
+ // - cat(m,[]), cat(m) => []
+ if isempty(varargin) then
+ y = [];
+ return
+ end
+ // - if just one input argument to concatenate, then return this argument
if size(varargin) == 1 then
y = varargin(1);
return
- elseif isempty(varargin(1)) then
- varargin(1) = null();
end
-
- // create 2 lists sizevar and sizevarless which contains (respectively) the size of all input arguments (sizevar(i) = size(varargin(i))), and the size of all input arguments excluding the size of the dimension number dims
- onedims = ones(1,dims);
- sizevarless = list();
- sizevar = list();
-
- for i=1:size(varargin)
- var = onedims;
- var(1:ndims(varargin(i))) = size(varargin(i));
- sizevar(i) = var;
- var(dims) = [];
- sizevarless(i) = var;
+ // - they must all have the same sizes (except along dim)
+ v = varargin(1);
+ S = size(v);
+ if length(S) < dim then
+ S = [S ones(1, dim-length(S))];
end
-
- for i=2:size(varargin)
- if or(sizevarless(i-1)<> sizevarless(i))
- error(msprintf(gettext("%s: Wrong size for input arguments: Same size expected.\n"),"cat"));
+ S(dim) = -1;
+ for i = 2:size(varargin)
+ s = size(varargin(i));
+ s(dim) = -1;
+ s(find(s==0)) = 1;
+ if ~and(s==S)
+ msg = gettext("%s: Wrong size for input arguments: Same size expected.\n");
+ error(msprintf(msg, "cat"));
end
end
-
- // case : input arguments are cells arrrays
- if typeof(varargin(1))=="ce"
- ytemp = cell();
- else // case : input arguments are arrays of doubles, strings, characters,...
- ytemp = [];
- end
-
- vartype = typeof(varargin(1));
-
- for j=2:size(varargin)
- if typeof(varargin(j)) ==vartype
- vartype = typeof(varargin(j));
- else
- error(msprintf(gettext("%s: Wrong type for input arguments: Same types expected.\n"),"cat"));
+ // They must be all of the same type: cell, struct, or other
+ T = typeof(v)
+ for i = 2:size(varargin)
+ v = varargin(i)
+ if typeof(v)~=T
+ msg = gettext("%s: Wrong type for input arguments: Same types expected.\n");
+ error(msprintf(msg, "cat"));
end
end
- // permorder is the order of the permutation
- permuteorder = 1:size(sizevarless(1),"*")+1;
- if ~dimssupvar then
- permuteorder(dims) = [];
- permuteorder = [dims permuteorder];
- end
-
- // permutevar is a list which contains the permuted input arguments arrays
- permutevar = list();
- for j=1:size(varargin)
- permutevar(j) = permute(varargin(j),permuteorder);
- end
-
- for i=1:prod(sizevarless(1))
- for j=1:size(varargin)
- permutevarj = permutevar(j);
- lj = size(varargin(j),"*")/prod(sizevarless(j));
- if typeof(permutevarj)=="ce" then
- for k=1+lj*(i-1):lj*i
- ytemp{size(ytemp,"*")+1} = permutevarj{k};
- end
- else
- ytemp= [ytemp (permutevarj(1+lj*(i-1):lj*i)).'];
- end
+ // PROCESSING
+ // ----------
+ y = varargin(1);
+ [vcat, hcat] = (%t, %t);
+ if type(y)>10
+ t = typeof(y, "overload");
+ if ~or(t==["ce" "st"])
+ [vcat, hcat] = (isdef("%"+t+"_f_"+t,"n"), isdef("%"+t+"_c_"+t,"n"));
end
end
- ytemp = matrix(ytemp,1,-1);
-
- sizevar = sizevar(1);
- prodxdims = prod(sizevar(1:dims));
- ny = prod(sizevar)/prodxdims;
- ydimsize = size(ytemp,2)/(prod(sizevarless(1)));
- prodxdimless = prod(sizevar(1:dims-1));
- ind = 1;
- for j=1:ydimsize-1
- ind = [ind 1+prodxdimless*j];
- end
- for i=0:ny-1
- index = [];
- for j=0:prodxdimless-1
- index = [index ind+j+i*(prodxdimless)*ydimsize];
+ if dim==1 & vcat then
+ for i = 2:length(varargin)
+ y = [y ; varargin(i)];
end
- if typeof(ytemp)=="ce"
- ceindex = (1:ydimsize*prodxdimless)+ydimsize*prodxdimless*(i);
- for k=1:size(index,"*")
- y{index(k)} = ytemp{ceindex(k)};
- end
- else
- y(index) = ytemp((1:ydimsize*prodxdimless)+ydimsize*prodxdimless*(i));
+ elseif dim==2 & hcat
+ for i = 2:length(varargin)
+ y = [y, varargin(i)];
end
- end
-
- // redimension of y
- ysize = sizevarless(1);
- if dimssupvar then
- ysize($+1) = size(varargin);
else
- if dims == size(sizevarless(1))+1
- ysize(dims) = size(ytemp,2)/prod(sizevarless(1));
- else
- ysize = [ysize(1:dims-1) size(ytemp,2)/prod(sizevarless(1)) ysize(dims:$)];
+ nd = max(ndims(y),dim);
+ st = emptystr(1,nd) + ":";
+ st(dim) = "%d:%d";
+ st = strcat(st,",");
+ Cmd = "y("+st+") = varargin(i);"
+ sy = size(y,dim);
+ for i = 2:length(varargin)
+ s = size(varargin(i), dim);
+ cmd = msprintf(Cmd,sy+1,sy+s);
+ execstr(cmd);
+ sy = sy + s;
end
end
- y = matrix(y,ysize);
-
endfunction
--- /dev/null
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2017 - Samuel GOUGEON
+//
+// This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 8297 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/8297
+//
+// <-- Short Description -->
+// After M = rand(m,m);
+// cat(3, M, M) spent time was exponential vs m (~12 days for m = 500)
+
+cat(1,1,1); // To load the function
+m = rand(250,250);
+tic();
+r = cat(3, m, m);
+tnew = toc();
+assert_checkequal(r(:,:,2), m);
+
+path = "SCI/modules/elementary_functions/tests/nonreg_tests/bug_8297_cat_old.sci";
+exec(path,-1);
+tic();
+r = cat_old(3, m, m);
+told = toc();
+assert_checktrue(told/tnew > 200);
--- /dev/null
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) INRIA - Farid BELAHCENE
+// Copyright (C) DIGITEO - 2011 - Allan CORNET
+//
+// Copyright (C) 2012 - 2016 - Scilab Enterprises
+//
+// This file is hereby licensed under the terms of the GNU GPL v2.0,
+// pursuant to article 5.3.4 of the CeCILL v.2.1.
+// This file was originally licensed under the terms of the CeCILL v2.1,
+// and continues to be available under such terms.
+// For more information, see the COPYING file which you should have received
+// along with this program.
+
+function y = cat_old(dims, varargin)
+ //
+ // CAT function concatenates the inputs arguments (included in varargin) according to dims
+ // if dims=1 then concatenation is done according to the rows of the input arguments, if dims=2 then concatenation is done according to the columns of the input arguments,...
+ // Output
+ // -y : a (multi) array, the result of the concatenation
+ // Input
+ // -dims : a scalar, the dimension chosen for the concatenation
+ // -varargin : scalars, matrices, hypermatrices to concatenate
+ // F.B
+
+ rhs = argn(2);
+ if rhs < 1 then
+ error(msprintf(gettext("%s: Wrong number of input argument(s): %d expected.\n"),"cat", 1));
+ end
+
+ // dims must be a positive real
+ if type(dims)==1 & dims>=0 & size(dims,"*")==1
+ dims = max(1,round(dims));
+ else
+ error(msprintf(gettext("%s: Wrong type for input argument #%d: A positive real expected.\n"),"cat",1));
+ end
+
+ // verify if dims value is superior to the dimension of the input arguments
+ dimssupvar = %t;
+ for i = 1:size(varargin)
+ if ndims(varargin(i))>=dims then
+ dimssupvar = %f;
+ end
+ end
+
+ // delete all empty input arguments
+ for i = size(varargin):-1:2
+ if isempty(varargin(i)) then
+ varargin(i) = null();
+ end
+ end
+
+ // if just one input argument to concatenate then return this argument
+ if size(varargin) == 1 then
+ y = varargin(1);
+ return
+ elseif isempty(varargin(1)) then
+ varargin(1) = null();
+ end
+
+ // create 2 lists sizevar and sizevarless which contains (respectively) the size of all input arguments (sizevar(i) = size(varargin(i))), and the size of all input arguments excluding the size of the dimension number dims
+ onedims = ones(1,dims);
+ sizevarless = list();
+ sizevar = list();
+
+ for i=1:size(varargin)
+ var = onedims;
+ var(1:ndims(varargin(i))) = size(varargin(i));
+ sizevar(i) = var;
+ var(dims) = [];
+ sizevarless(i) = var;
+ end
+
+ for i=2:size(varargin)
+ if or(sizevarless(i-1)<> sizevarless(i))
+ error(msprintf(gettext("%s: Wrong size for input arguments: Same size expected.\n"),"cat"));
+ end
+ end
+
+ // case : input arguments are cells arrrays
+ if typeof(varargin(1))=="ce"
+ ytemp = cell();
+ else // case : input arguments are arrays of doubles, strings, characters,...
+ ytemp = [];
+ end
+
+ vartype = typeof(varargin(1));
+
+ for j=2:size(varargin)
+ if typeof(varargin(j)) ==vartype
+ vartype = typeof(varargin(j));
+ else
+ error(msprintf(gettext("%s: Wrong type for input arguments: Same types expected.\n"),"cat"));
+ end
+ end
+
+ // permorder is the order of the permutation
+ permuteorder = 1:size(sizevarless(1),"*")+1;
+ if ~dimssupvar then
+ permuteorder(dims) = [];
+ permuteorder = [dims permuteorder];
+ end
+
+ // permutevar is a list which contains the permuted input arguments arrays
+ permutevar = list();
+ for j=1:size(varargin)
+ permutevar(j) = permute(varargin(j),permuteorder);
+ end
+
+ for i=1:prod(sizevarless(1))
+ for j=1:size(varargin)
+ permutevarj = permutevar(j);
+ lj = size(varargin(j),"*")/prod(sizevarless(j));
+ if typeof(permutevarj)=="ce" then
+ for k=1+lj*(i-1):lj*i
+ ytemp{size(ytemp,"*")+1} = permutevarj{k};
+ end
+ else
+ ytemp= [ytemp (permutevarj(1+lj*(i-1):lj*i)).'];
+ end
+ end
+ end
+ ytemp = matrix(ytemp,1,-1);
+
+ sizevar = sizevar(1);
+ prodxdims = prod(sizevar(1:dims));
+ ny = prod(sizevar)/prodxdims;
+ ydimsize = size(ytemp,2)/(prod(sizevarless(1)));
+ prodxdimless = prod(sizevar(1:dims-1));
+ ind = 1;
+ for j=1:ydimsize-1
+ ind = [ind 1+prodxdimless*j];
+ end
+ for i=0:ny-1
+ index = [];
+ for j=0:prodxdimless-1
+ index = [index ind+j+i*(prodxdimless)*ydimsize];
+ end
+ if typeof(ytemp)=="ce"
+ ceindex = (1:ydimsize*prodxdimless)+ydimsize*prodxdimless*(i);
+ for k=1:size(index,"*")
+ y{index(k)} = ytemp{ceindex(k)};
+ end
+ else
+ y(index) = ytemp((1:ydimsize*prodxdimless)+ydimsize*prodxdimless*(i));
+ end
+ end
+
+ // redimension of y
+ ysize = sizevarless(1);
+ if dimssupvar then
+ ysize($+1) = size(varargin);
+ else
+ if dims == size(sizevarless(1))+1
+ ysize(dims) = size(ytemp,2)/prod(sizevarless(1));
+ else
+ ysize = [ysize(1:dims-1) size(ytemp,2)/prod(sizevarless(1)) ysize(dims:$)];
+ end
+ end
+ y = matrix(y,ysize);
+
+endfunction
+++ /dev/null
-// =============================================================================
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) 2016 - Scilab Enterprises - Pierre-Aimé AGNEL
-//
-// This file is distributed under the same license as the Scilab package.
-// =============================================================================
-// Unit tests for cat.sci function
-// first example : concatenation according to the rows
-dims=1; A1=[1 2 3]; A2=[4 5 6 ; 7 8 9]; A3=[10 11 12];
-y=cat(dims, A1, A2, A3);
-res = [1 2 3; 4 5 6; 7 8 9; 10 11 12];
-assert_checkequal(y, res);,
-// second example : concatenation according to the columns
-dims=2; A1=[1 2 3]'; A2=[4 5;7 8;9 10];
-y=cat(dims, A1, A2)
- y =
- 1. 4. 5.
- 2. 7. 8.
- 3. 9. 10.
-res = [1 4 5; 2 7 8; 3 9 10];
-assert_checkequal(y, res);,
-// third example : concatenation according to the 3th dimension
-dims=3; A1=matrix(1:12,[2,2,3]); A2=[13 15;14 16]; A3=matrix(17:32,[2,2,4]);
-y=cat(dims, A1, A2, A3);
-res = matrix( [1:32], [2, 2, 8] );
-assert_checkequal(y, res);
// =============================================================================
// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
// Copyright (C) 2016 - Scilab Enterprises - Pierre-Aimé AGNEL
+// Copyright (C) 2017 - Samuel GOUGEON
//
// This file is distributed under the same license as the Scilab package.
// =============================================================================
+// <-- NO CHECK REF -->
+// <-- CLI SHELL MODE -->
+
// Unit tests for cat.sci function
+// ===============================
+
+assert_checkequal(cat(1,[]), []);
+assert_checkequal(cat(2,[]), []);
+assert_checkequal(cat(3,[]), []);
+m = rand(3,4,2);
+assert_checkequal(cat(1,m), m);
+assert_checkequal(cat(2,m), m);
+assert_checkequal(cat(3,m), m);
+
// first example : concatenation according to the rows
-dims=1; A1=[1 2 3]; A2=[4 5 6 ; 7 8 9]; A3=[10 11 12];
+dims = 1; A1=[1 2 3]; A2=[4 5 6 ; 7 8 9]; A3=[10 11 12];
y=cat(dims, A1, A2, A3);
res = [1 2 3; 4 5 6; 7 8 9; 10 11 12];
assert_checkequal(y, res);,
+y = cat(dims, A1<5, A2<5, A3<5);
+assert_checkequal(y, res<5);,
+y = cat(dims, uint8(A1), uint8(A2), uint8(A3));
+assert_checkequal(y, uint8(res));,
+y = cat(dims, string(A1), string(A2), string(A3));
+assert_checkequal(y, string(res));,
+A1 = makecell([1 3 2], %pi, %t, "hello", %s, list(-1,"3"), 1/(1-%s));
+y = cat(1,A1,A1);
+res = makecell([2 3 2], %pi, %t, "hello", ..
+ %pi, %t, "hello", ..
+ %s, list(-1,"3"), 1/(1-%s), ..
+ %s, list(-1,"3"), 1/(1-%s));
+assert_checkequal(y, res);
+
// second example : concatenation according to the columns
-dims=2; A1=[1 2 3]'; A2=[4 5;7 8;9 10];
-y=cat(dims, A1, A2)
+dims = 2; A1=[1 2 3]'; A2=[4 5;7 8;9 10];
+y = cat(dims, A1, A2);
res = [1 4 5; 2 7 8; 3 9 10];
assert_checkequal(y, res);,
+y = cat(dims, A1<5, A2<5);
+assert_checkequal(y, res<5);,
+y = cat(dims, uint8(A1), uint8(A2));
+assert_checkequal(y, uint8(res));,
+y = cat(dims, string(A1), string(A2));
+assert_checkequal(y, string(res));,
+A1 = makecell([2 2 2], %pi, %t, "hello", %s, list(-1,"3"), 1/(1-%s), "abc", %i);
+y = cat(dims, A1, A1);
+res = makecell([2 4 2], %pi, %t, %pi, %t, ..
+ "hello", %s, "hello", %s, ..
+ list(-1,"3"), 1/(1-%s), list(-1,"3"), 1/(1-%s), ..
+ "abc", %i, "abc", %i);
+assert_checkequal(y, res);
// third example : concatenation according to the 3th dimension
-dims=3; A1=matrix(1:12,[2,2,3]); A2=[13 15;14 16]; A3=matrix(17:32,[2,2,4]);
+dims = 3; A1=matrix(1:12,[2,2,3]); A2=[13 15;14 16]; A3=matrix(17:32,[2,2,4]);
y=cat(dims, A1, A2, A3);
res = matrix( [1:32], [2, 2, 8] );
-
assert_checkequal(y, res);
+y = cat(dims, A1<5, A2<5, A3<5);
+assert_checkequal(y, res<5);,
+y = cat(dims, uint8(A1), uint8(A2), uint8(A3));
+assert_checkequal(y, uint8(res));,
+y = cat(dims, string(A1), string(A2), string(A3));
+assert_checkequal(y, string(res));,
+A1 = makecell([2 2 2], %pi, %t, "hello", %s, list(-1,"3"), 1/(1-%s), "abc", %i);
+y = cat(dims, A1, A1(:,:,1));
+res = makecell([2 2 3], %pi, %t, ..
+ "hello", %s,..
+ list(-1,"3"), 1/(1-%s), ..
+ "abc", %i, ..
+ %pi, %t, ..
+ "hello", %s);
+assert_checkequal(y, res);
+