Mercurial > octave
changeset 33024:1220b63eea0e bytecode-interpreter
maint: Merge default to bytecode-interpreter
author | Arun Giridhar <arungiridhar@gmail.com> |
---|---|
date | Wed, 14 Feb 2024 18:52:17 -0500 |
parents | 19973af3ac42 (current diff) 92a2e883af17 (diff) |
children | a71bde898ef9 |
files | libinterp/parse-tree/pt-eval.cc |
diffstat | 13 files changed, 312 insertions(+), 71 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.github/dependabot.yml Wed Feb 14 18:52:17 2024 -0500 @@ -0,0 +1,10 @@ +# Set update schedule for GitHub Actions + +version: 2 +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every week + interval: "weekly"
--- a/.github/workflows/codeql-analysis.yaml Sun Feb 11 09:40:35 2024 -0500 +++ b/.github/workflows/codeql-analysis.yaml Wed Feb 14 18:52:17 2024 -0500 @@ -51,7 +51,7 @@ - name: initialize CodeQL # Initialize the CodeQL tools for scanning. - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -63,7 +63,7 @@ run: make -C ./.build all -j2 V=1 - name: perform CodeQL analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 windows: @@ -171,7 +171,7 @@ - name: initialize CodeQL # Initialize the CodeQL tools for scanning. - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -185,4 +185,4 @@ run: make -C ./.build all -j8 V=1 - name: perform CodeQL analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3
--- a/doc/interpreter/expr.txi Sun Feb 11 09:40:35 2024 -0500 +++ b/doc/interpreter/expr.txi Wed Feb 14 18:52:17 2024 -0500 @@ -1233,6 +1233,7 @@ thing = "food" predicate = "good" message = [ "this " , thing , " is " , predicate ] +@result{} "this food is good" @end group @end example @@ -1264,9 +1265,9 @@ @example @group -octave:13> foo = 1 +>> foo = 1 foo = 1 -octave:13> foo = "bar" +>> foo = "bar" foo = bar @end group @end example @@ -1280,14 +1281,149 @@ @code{a} is a matrix with at least two columns, @example -@group a(:, 2) = 5 -@end group @end example @noindent sets all the elements in the second column of @code{a} to 5. +When an assignment sets the value of a vector, matrix, or array element at a +position or dimension outside of that variable's current size, the array size +will be increased to accommodate the new values: + +@example +@group +>> a = [1, 2, 3] +a = 1 2 3 +>> a(4) = 4 +a = 1 2 3 4 +>> a(2, :) = [5, 6, 7, 8] +a = + 1 2 3 4 + 5 6 7 8 +@end group +@end example + +Attempting to increase the size of an array such that the desired output size +is ambiguous will result in an error: + +@example +@group +>> a(9) = 10 +@print{} error: Invalid resizing operation or ambiguous assignment to an +out-of-bounds array element +@end group +@end example + +This is because adding the 9th element creates an ambiguity in the desired +array position for the value 10, each possibility requiring a different array +size expansion to accommodate the assignment. + +Assignments may be made with fewer specified elements than would be required to +fill the newly expanded array as long as the assignment is unambiguous. In +these cases the array will be automatically padded with @i{null} values: +@example +@group +>> a = [1, 2] +a = 1 2 +>> a(4) = 5 +a = 1 2 0 5 +>> a(3, :) = [6, 7, 8, 9] +a = + 1 2 0 5 + 0 0 0 0 + 6 7 8 9 +>> a(4, 5) = 10 +a = + 1 2 0 5 0 + 0 0 0 0 0 + 6 7 8 9 0 + 0 0 0 0 10 +@end group +@end example + +For all built-in types, the @i{null} value will be appropriate to that object +type. + +Numeric arrays: +@example +@group +>> a = int32 ([1, 2]) +a = 1, 2 +>> a(4) = 5 +a = 1 2 0 5 +@end group +@end example + +Logical arrays: +@example +@group +>> a = [true, false, true] +a = 1 0 1 +>> d(5) = true +d = 1 0 1 0 1 +@end group +@end example + +Character arrays: +@example +@group +>> a = "abc" +a = abc +>> a(5) = "d" +a = abcd +>> double (a) +ans = 97 98 99 0 100 +@end group +@end example + +Cell arrays: +@example +@group +>> e = @{1, "foo", [3, 4]@}; +>> e(5) = "bar" +e = +@{ + [1,1] = 1 + [1,2] = foo + [1,3] = + + 3 4 + + [1,4] = [](0x0) + [1,5] = bar +@} +@end group +@end example + +Struct arrays: +@example +@group +>> a = struct("foo",1,"bar",2); +>> a(3) = struct("foo",3,"bar",9) +a = + + 1x3 struct array containing the fields: + + foo + bar + +>> a.foo +ans = 1 +ans = [](0x0) +ans = 3 +>> a.bar +ans = 2 +ans = [](0x0) +ans = 9 +@end group +@end example + +Note that Octave currently is unable to concatenate arbitrary object types +into arrays. Such behavior must be explicitly defined within the object class +or attempts at concatenation will result in an error. +@xref{Object Oriented Programming} + Assigning an empty matrix @samp{[]} works in most cases to allow you to delete rows or columns of matrices and vectors. @xref{Empty Matrices}. For example, given a 4 by 5 matrix @var{A}, the assignment @@ -1306,6 +1442,28 @@ @noindent deletes the first, third, and fifth columns. +Deleting part of an array object will necessarily resize the object. When the +deletion allows for consistent size reduction across a dimension, e.g., one +element of a vector, or one row or column of a matrix, the size along that +dimension will be reduced while preserving dimensionality. If, however, +dimensionality cannot be maintained, the object will be reshaped into a vector +following column-wise element ordering: + +@example +@group +>> a = [1, 2, 3, 4; 5, 6, 7, 8] +a = + 1 2 3 4 + 5 6 7 8 +>> a(:, 3) = [] +a = + 1 2 4 + 5 6 8 +>> a(4) = [] +a = 1 5 2 4 8 +@end group +@end example + An assignment is an expression, so it has a value. Thus, @code{z = 1} as an expression has the value 1. One consequence of this is that you can write multiple assignments together:
--- a/libinterp/corefcn/data.cc Sun Feb 11 09:40:35 2024 -0500 +++ b/libinterp/corefcn/data.cc Wed Feb 14 18:52:17 2024 -0500 @@ -3818,7 +3818,7 @@ DEFUN (isempty, args, , doc: /* -*- texinfo -*- @deftypefn {} {@var{tf} =} isempty (@var{A}) -Return true if @var{A} is an empty matrix (any one of its dimensions is +Return true if @var{A} is an empty object (any one of its dimensions is zero). @seealso{isnull, isa} @end deftypefn */) @@ -3911,9 +3911,9 @@ @deftypefn {} {@var{tf} =} isvector (@var{x}) Return true if @var{x} is a vector. -A vector is a 2-D array where one of the dimensions is equal to 1 (either +A vector is a 2-D object where one of the dimensions is equal to 1 (either @nospell{1xN} or @nospell{Nx1}). As a consequence of this definition, a 1x1 -array (a scalar) is also a vector. +object (a scalar) is also a vector. @seealso{isscalar, ismatrix, iscolumn, isrow, size} @end deftypefn */) { @@ -3952,7 +3952,7 @@ @deftypefn {} {@var{tf} =} isrow (@var{x}) Return true if @var{x} is a row vector. -A row vector is a 2-D array for which @code{size (@var{x})} returns +A row vector is a 2-D object for which @code{size (@var{x})} returns @w{@code{[1, N]}} with non-negative N. @seealso{iscolumn, isscalar, isvector, ismatrix, size} @end deftypefn */) @@ -4001,7 +4001,7 @@ @deftypefn {} {@var{tf} =} iscolumn (@var{x}) Return true if @var{x} is a column vector. -A column vector is a 2-D array for which @code{size (@var{x})} returns +A column vector is a 2-D object for which @code{size (@var{x})} returns @w{@code{[N, 1]}} with non-negative N. @seealso{isrow, isscalar, isvector, ismatrix, size} @end deftypefn */)
--- a/libinterp/corefcn/debug.cc Sun Feb 11 09:40:35 2024 -0500 +++ b/libinterp/corefcn/debug.cc Wed Feb 14 18:52:17 2024 -0500 @@ -541,7 +541,7 @@ %!test %! if (isguirunning ()) %! orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file", -%! "0"); +%! "false"); %! endif %! unwind_protect %! dbclear all; # Clear out breakpoints before test
--- a/libinterp/corefcn/gsvd.cc Sun Feb 11 09:40:35 2024 -0500 +++ b/libinterp/corefcn/gsvd.cc Wed Feb 14 18:52:17 2024 -0500 @@ -283,17 +283,17 @@ %! assert (S0, S1, 20*eps); ## a few tests for gsvd.m -%!shared A, A0, B, B0, U, V, C, S, X +%!shared A0, B0 %! old_state = randn ("state"); %! restore_state = onCleanup (@() randn ("state", old_state)); -%! randn ("state", 40); # initialize generator to make behavior reproducible +%! randn ("state", 40); # initialize generator to make behavior reproducible %! A0 = randn (5, 3); %! B0 = diag ([1 2 4]); -%! A = A0; -%! B = B0; ## A (5x3) and B (3x3) are full rank %!test <48807> +%! A = A0; +%! B = B0; %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (3), 5*eps); %! assert (U*C*X', A, 10*eps); @@ -301,6 +301,8 @@ ## A: 5x3 full rank, B: 3x3 rank deficient %!test <48807> +%! A = A0; +%! B = B0; %! B(2, 2) = 0; %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (3), 5*eps); @@ -309,6 +311,7 @@ ## A: 5x3 rank deficient, B: 3x3 full rank %!test <48807> +%! A = A0; %! B = B0; %! A(:, 3) = 2*A(:, 1) - A(:, 2); %! [U, V, X, C, S] = gsvd (A, B); @@ -319,6 +322,8 @@ ## A and B are both rank deficient ## FIXME: LAPACK seems to be completely broken for this case %!#test <48807> +%! A = A0; +%! B = B0; %! B(:, 3) = 2*B(:, 1) - B(:, 2); %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (3), 5*eps); @@ -328,8 +333,7 @@ ## A (now 3x5) and B (now 5x5) are full rank %!test <48807> %! A = A0.'; -%! B0 = diag ([1 2 4 8 16]); -%! B = B0; +%! B = diag ([1 2 4 8 16]); %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (5), 5*eps); %! assert (U*C*X', A, 15*eps); @@ -337,6 +341,8 @@ ## A: 3x5 full rank, B: 5x5 rank deficient %!test <48807> +%! A = A0.'; +%! B = diag ([1 2 4 8 16]); %! B(2, 2) = 0; %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (5), 5*eps); @@ -345,7 +351,8 @@ ## A: 3x5 rank deficient, B: 5x5 full rank %!test <48807> -%! B = B0; +%! A = A0.'; +%! B = diag ([1 2 4 8 16]); %! A(3, :) = 2*A(1, :) - A(2, :); %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (5), 5*eps); @@ -367,11 +374,9 @@ %!test <48807> %! old_state = randn ("state"); %! restore_state = onCleanup (@() randn ("state", old_state)); -%! randn ("state", 12345); # initialize generator to make behavior reproducible -%! A0 = A0 + j* randn (5, 3); -%! B0 = diag ([1 2 4]) + j* diag ([4 -2 -1]); -%! A = A0; -%! B = B0; +%! randn ("state", 12345); # initialize generator to make behavior reproducible +%! A = A0 + j* randn (5, 3); +%! B = diag ([1 2 4]) + j* diag ([4 -2 -1]); %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (3), 5*eps); %! assert (U*C*X', A, 10*eps); @@ -379,6 +384,8 @@ ## A: 5x3 complex full rank, B: 3x3 complex rank deficient %!test <48807> +%! A = A0 + j* randn (5, 3); +%! B = diag ([1 2 4]) + j* diag ([4 -2 -1]); %! B(2, 2) = 0; %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (3), 5*eps); @@ -387,7 +394,8 @@ ## A: 5x3 complex rank deficient, B: 3x3 complex full rank %!test <48807> -%! B = B0; +%! A = A0 + j* randn (5, 3); +%! B = diag ([1 2 4]) + j* diag ([4 -2 -1]); %! A(:, 3) = 2*A(:, 1) - A(:, 2); %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (3), 5*eps); @@ -397,6 +405,8 @@ ## A (5x3) and B (3x3) are both complex rank deficient ## FIXME: LAPACK seems to be completely broken for this case %!#test <48807> +%! A = A0 + j* randn (5, 3); +%! B = diag ([1 2 4]) + j* diag ([4 -2 -1]); %! B(:, 3) = 2*B(:, 1) - B(:, 2); %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (3), 5*eps); @@ -407,8 +417,7 @@ ## now, A is 3x5 %!test <48807> %! A = A0.'; -%! B0 = diag ([1 2 4 8 16]) + j* diag ([-5 4 -3 2 -1]); -%! B = B0; +%! B = diag ([1 2 4 8 16]) + j* diag ([-5 4 -3 2 -1]); %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (5), 5*eps); %! assert (U*C*X', A, 25*eps); @@ -416,7 +425,8 @@ ## A: 3x5 complex full rank, B: 5x5 complex rank deficient %!test <48807> -%! B(2, 2) = 0; +%! A = A0.'; +%! B = diag ([1 0 4 8 16]) + j* diag ([-5 0 -3 2 -1]); %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (5), 5*eps); %! assert (U*C*X', A, 10*eps); @@ -424,7 +434,8 @@ ## A: 3x5 complex rank deficient, B: 5x5 complex full rank %!test <48807> -%! B = B0; +%! A = A0.'; +%! B = diag ([1 2 4 8 16]) + j* diag ([-5 4 -3 2 -1]); %! A(3, :) = 2*A(1, :) - A(2, :); %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (5), 5*eps); @@ -445,9 +456,11 @@ ## Test that single inputs produce single outputs %!test +%! A = A0.'; +%! B = diag ([1 2 4 8 16]) + j* diag ([-5 4 -3 2 -1]); %! s = gsvd (single (eye (5)), B); %! assert (class (s), "single"); -%! [U,V,X,C,S] = gsvd (single (eye(5)), B); +%! [U, V, X, C, S] = gsvd (single (eye(5)), B); %! assert (class (U), "single"); %! assert (class (V), "single"); %! assert (class (X), "single"); @@ -456,7 +469,7 @@ %! %! s = gsvd (A, single (eye (5))); %! assert (class (s), "single"); -%! [U,V,X,C,S] = gsvd (A, single (eye (5))); +%! [U, V, X, C, S] = gsvd (A, single (eye (5))); %! assert (class (U), "single"); %! assert (class (V), "single"); %! assert (class (X), "single");
--- a/libinterp/corefcn/perms.cc Sun Feb 11 09:40:35 2024 -0500 +++ b/libinterp/corefcn/perms.cc Wed Feb 14 18:52:17 2024 -0500 @@ -58,9 +58,9 @@ // preferrable and the comparison templates can be removed: // bool isequal; // if constexpr (std::is_same<T, octave_value>::value) -// isEqual = Ar[i].is_equal (Ar[j]); +// isequal = Ar[i].is_equal (Ar[j]); // else -// isEqual = (Ar[i] == Ar[j]); +// isequal = (Ar[i] == Ar[j]); template <typename T> bool is_equal_T (T a, T b) @@ -105,7 +105,7 @@ { for (octave_idx_type j = i + 1; j < m; j++) { - bool isequal = is_equal_T<T>(Ar[i], Ar[j]); + bool isequal = is_equal_T<T> (Ar[i], Ar[j]); if (myvidx[j] > myvidx[i] && isequal) { myvidx[j] = myvidx[i]; // not yet processed...
--- a/libinterp/dldfcn/__glpk__.cc Sun Feb 11 09:40:35 2024 -0500 +++ b/libinterp/dldfcn/__glpk__.cc Wed Feb 14 18:52:17 2024 -0500 @@ -167,7 +167,7 @@ break; } - glp_set_row_bnds (lp, i+1, typx, b[i], b[i]); + glp_set_row_bnds (lp, i+1, typx, typx == GLP_DB ? -b[i] : b[i], b[i]); }
--- a/libinterp/parse-tree/bp-table.cc Sun Feb 11 09:40:35 2024 -0500 +++ b/libinterp/parse-tree/bp-table.cc Wed Feb 14 18:52:17 2024 -0500 @@ -543,18 +543,28 @@ /* %!test -%! dbclear all; # Clear out breakpoints before test -%! dbstop help; -%! dbstop in ls; -%! dbstop help at 105; # 105 is a comment; code line is at 106 -%! dbstop in ls 123; # 123 is a comment; code line is at 126 -%! dbstop help 204 if a==5; -%! dbstop if error Octave:undefined-function; -%! s = dbstatus; -%! dbclear all; -%! assert ({s.bkpt(:).name}, {"help", "help", "help>do_contents", "ls", "ls"}); -%! assert ([s.bkpt(:).line], [56, 106, 208, 63, 126]); -%! assert (s.errs, {"Octave:undefined-function"}); +%! if (isguirunning ()) +%! orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file", +%! "false"); +%! endif +%! unwind_protect +%! dbclear all; # Clear out breakpoints before test +%! dbstop help; +%! dbstop in ls; +%! dbstop help at 105; # 105 is a comment; code line is at 106 +%! dbstop in ls 123; # 123 is a comment; code line is at 126 +%! dbstop help 204 if a==5; +%! dbstop if error Octave:undefined-function; +%! s = dbstatus; +%! dbclear all; +%! assert ({s.bkpt(:).name}, {"help", "help", "help>do_contents", "ls", "ls"}); +%! assert ([s.bkpt(:).line], [56, 106, 208, 63, 126]); +%! assert (s.errs, {"Octave:undefined-function"}); +%! unwind_protect_cleanup +%! if (isguirunning ()) +%! __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg); +%! endif +%! end_unwind_protect */ void
--- a/libinterp/parse-tree/pt-eval.cc Sun Feb 11 09:40:35 2024 -0500 +++ b/libinterp/parse-tree/pt-eval.cc Wed Feb 14 18:52:17 2024 -0500 @@ -3249,7 +3249,7 @@ if (rhs.ndims () > 2) arg = arg.reshape (dv); - if (nrows > 0 && steps > 0) + if (steps > 0) { octave_value_list idx; octave_idx_type iidx;
--- a/scripts/optimization/glpk.m Sun Feb 11 09:40:35 2024 -0500 +++ b/scripts/optimization/glpk.m Wed Feb 14 18:52:17 2024 -0500 @@ -652,6 +652,22 @@ %! assert (A(i,:) * xmin <= b(i)); %! endfor +%!testif HAVE_GLPK +%! sense = 1; +%! c = [-1, -1]'; +%! A = [1, 0; 0, 1]; +%! b = [1, 1]'; +%! ctype = ['D', 'D']'; +%! lb = [-1, -1]'; +%! ub = []; +%! vartype = ['I', 'I']'; +%! param.msglev = 0; +%! [xmin, fmin, errnum, extra] = glpk (c, A, b, lb, ub, ctype, vartype, ... +%! sense, param); +%! assert (fmin, c' * xmin); +%! for i = 1:2 +%! assert (A(i,:) * xmin <= b(i)); +%! endfor %!testif HAVE_GLPK %! sense = 1;
--- a/test/classdef-debug/test_classdef_breakpoints.tst Sun Feb 11 09:40:35 2024 -0500 +++ b/test/classdef-debug/test_classdef_breakpoints.tst Wed Feb 14 18:52:17 2024 -0500 @@ -10,22 +10,40 @@ %! endif %!endfunction -## Add breakpoints in different member functions using line numbers. %!test <*46451> -%! dbstop classdef_breakpoints 13 7 10; -%! assert_dbstatus ([7, 10, 13]); - -## Remove one breakpoint and confirm the others remain. -%!test <*46451> -%! dbclear classdef_breakpoints 10; -%! assert_dbstatus ([7, 13]); +%! if (isguirunning ()) +%! orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file", +%! "false"); +%! endif +%! unwind_protect +%! ## Add breakpoints in different member functions using line numbers. +%! dbstop classdef_breakpoints 13 7 10; +%! assert_dbstatus ([7, 10, 13]); +%! +%! ## Remove one breakpoint and confirm the others remain. +%! dbclear classdef_breakpoints 10; +%! assert_dbstatus ([7, 13]); +%! +%! ## Clear all breakpoints, none should be left. +%! dbclear classdef_breakpoints; +%! assert_dbstatus ([]); +%! unwind_protect_cleanup +%! if (isguirunning ()) +%! __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg); +%! endif +%! end_unwind_protect -## Add breakpoint in local function. %!test <46451> -%! dbstop classdef_breakpoints 19; -%! assert_dbstatus ([7, 13, 20]); - -## Clear all breakpoints, none should be left. -%!test <*46451> -%! dbclear classdef_breakpoints; -%! assert_dbstatus ([]); +%! if (isguirunning ()) +%! orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file", +%! "false"); +%! endif +%! unwind_protect +%! ## Add breakpoint in local function. +%! dbstop classdef_breakpoints 19; +%! assert_dbstatus ([7, 13, 20]); +%! unwind_protect_cleanup +%! if (isguirunning ()) +%! __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg); +%! endif +%! end_unwind_protect
--- a/test/for.tst Sun Feb 11 09:40:35 2024 -0500 +++ b/test/for.tst Wed Feb 14 18:52:17 2024 -0500 @@ -130,15 +130,15 @@ %! __printf_assert__ ("\n"); %! assert (__prog_output_assert__ ("1234")); -%!test <*50893> +%!test <*55622> %! cnt = 0; %! for k = zeros (0,3) %! cnt++; %! endfor -%! assert (cnt, 0); -%! assert (k, zeros (0,3)); +%! assert (cnt, 3); +%! assert (k, zeros (0,1)); -%!test <*50893> +%!test <*55622> %! cnt = 0; %! for k = zeros (3,0) %! cnt++; @@ -159,8 +159,24 @@ %! for k = cell (0,3) %! cnt++; %! endfor +%! assert (cnt, 3); +%! assert (k, cell (0,1)); + +%!test <*55622> +%! cnt = 0; +%! for k = zeros (1,2,3); +%! cnt++; +%! endfor +%! assert (cnt, 6); +%! assert (k, 0); + +%!test <*55622> +%! cnt = 0; +%! for k = zeros (1,2,0); +%! cnt++; +%! endfor %! assert (cnt, 0); -%! assert (k, cell (0,3)); +%! assert (k, zeros (1,0)); %!test <*45143> %! warning ("on", "Octave:infinite-loop", "local");