changeset 10122:9d1a14e12431

Update docs and add tests for container functions
author Thorsten Meyer <thorsten.meyier@gmx.de>
date Sun, 17 Jan 2010 13:31:42 +0100
parents b5cc666da6ca
children 8590f3c51868
files doc/ChangeLog doc/interpreter/container.txi scripts/ChangeLog scripts/general/celldisp.m scripts/general/structfun.m scripts/miscellaneous/getfield.m scripts/miscellaneous/orderfields.m scripts/miscellaneous/setfield.m scripts/miscellaneous/substruct.m src/ChangeLog src/DLD-FUNCTIONS/cellfun.cc src/ov-cell.cc src/ov-struct.cc
diffstat 13 files changed, 294 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/doc/ChangeLog	Sat Jan 16 07:59:52 2010 +0100
+++ b/doc/ChangeLog	Sun Jan 17 13:31:42 2010 +0100
@@ -1,3 +1,8 @@
+2010-01-17  Thorsten Meyer  <thorsten.meyier@gmx.de>
+
+	* interpreter/container.txi (Creating Cell Arrays): Add
+	docstring for cellslices function.
+
 2010-01-09  John W. Eaton  <jwe@octave.org>
 
 	* interpreter/munge-texi.cc: Avoid C-style casts.
--- a/doc/interpreter/container.txi	Sat Jan 16 07:59:52 2010 +0100
+++ b/doc/interpreter/container.txi	Sun Jan 17 13:31:42 2010 +0100
@@ -628,12 +628,14 @@
 
 As an alternative to creating empty cell arrays, and then filling them, it
 is possible to convert numerical arrays into cell arrays using the
-@code{num2cell} and @code{mat2cell} functions.
+@code{num2cell}, @code{mat2cell} and @code{cellslices} functions.
 
 @DOCSTRING(num2cell)
 
 @DOCSTRING(mat2cell)
 
+@DOCSTRING(cellslices)
+
 @node Indexing Cell Arrays
 @subsection Indexing Cell Arrays
 
--- a/scripts/ChangeLog	Sat Jan 16 07:59:52 2010 +0100
+++ b/scripts/ChangeLog	Sun Jan 17 13:31:42 2010 +0100
@@ -1,3 +1,11 @@
+2010-01-17  Thorsten Meyer  <thorsten.meyier@gmx.de>
+
+	* general/celldisp.m: Add example, add demo.
+
+	* general/structfun.m, miscellaneous/getfield.m,
+	miscellaneous/orderfields.m, miscellaneous/setfield.m,
+	miscellaneous/substruct.m: Update documentation string. 
+
 2010-01-16  David Bateman  <dbateman@free.fr>
 
 	* plot/__go_draw_axes__.m (next_marker):  New function to find a
--- a/scripts/general/celldisp.m	Sat Jan 16 07:59:52 2010 +0100
+++ b/scripts/general/celldisp.m	Sun Jan 17 13:31:42 2010 +0100
@@ -20,7 +20,24 @@
 ## @deftypefn {Function File} {} celldisp (@var{c}, @var{name})
 ## Recursively display the contents of a cell array.  By default the values
 ## are displayed with the name of the variable @var{c}.  However, this name
-## can be replaced with the variable @var{name}.
+## can be replaced with the variable @var{name}.  For example:
+## 
+## @example
+## @group
+## c = @{1, 2, @{31, 32@}@};
+## celldisp(c, "b")
+##      @result{}
+##         b@{1@} = 
+##          1
+##         b@{2@} = 
+##          2
+##         b@{3@}@{1@} = 
+##          31
+##         b@{3@}@{2@} = 
+##          32
+## @end group
+## @end example
+##
 ## @seealso{disp}
 ## @end deftypefn
 
@@ -60,3 +77,7 @@
     s = sprintf("%i", i);
   endif
 endfunction
+
+%!demo
+%! c = {1, 2, {31, 32}};
+%! celldisp(c, "b") 
\ No newline at end of file
--- a/scripts/general/structfun.m	Sat Jan 16 07:59:52 2010 +0100
+++ b/scripts/general/structfun.m	Sun Jan 17 13:31:42 2010 +0100
@@ -18,7 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} structfun (@var{func}, @var{s})
-## @deftypefnx {Function File} {[@var{a}, @var{b}] =} structfun (@dots{})
+## @deftypefnx {Function File} {[@var{a}, @dots{}] =} structfun (@dots{})
 ## @deftypefnx {Function File} {} structfun (@dots{}, "ErrorHandler", @var{errfunc})
 ## @deftypefnx {Function File} {} structfun (@dots{}, "UniformOutput", @var{val})
 ## 
@@ -35,7 +35,7 @@
 ##
 ## If the parameter "UniformOutput" is set to true (the default), then the function
 ## must return a single element which will be concatenated into the
-## return value.  If "UniformOutput" is false, the outputs placed in a structure
+## return value.  If "UniformOutput" is false, the outputs are placed into a structure
 ## with the same fieldnames as the input structure.
 ## 
 ## @example
@@ -44,10 +44,15 @@
 ## s.name2 = "Jill Jones"; 
 ## structfun (@@(x) regexp (x, '(\w+)$', "matches")@{1@}, s, 
 ##            "UniformOutput", false)
+##     @result{}
+##    @{
+##      name1 = Smith
+##      name2 = Jones
+##    @} 
 ## @end group
 ## @end example
 ## 
-## Given the parameter "ErrorHandler", then @var{errfunc} defines a function to
+## Given the parameter "ErrorHandler", @var{errfunc} defines a function to
 ## call in case @var{func} generates an error.  The form of the function is
 ## 
 ## @example
@@ -58,7 +63,9 @@
 ## @var{func}, given by @var{se}.  This is a structure with the elements
 ## "identifier", "message" and "index", giving respectively the error
 ## identifier, the error message, and the index into the input arguments
-## of the element that caused the error.
+## of the element that caused the error.  For an example on how to use
+## an error handler, @pxref{doc-cellfun, @code{cellfun}}. 
+##
 ## @seealso{cellfun, arrayfun}
 ## @end deftypefn
 
--- a/scripts/miscellaneous/getfield.m	Sat Jan 16 07:59:52 2010 +0100
+++ b/scripts/miscellaneous/getfield.m	Sun Jan 17 13:31:42 2010 +0100
@@ -19,13 +19,13 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {[@var{v1}, @dots{}] =} getfield (@var{s}, @var{key}, @dots{}) 
-## Extract fields from a structure.  For example
+## Extract a field from a structure (or a nested structure).  For example
 ##
 ## @example
 ## @group
 ## ss(1,2).fd(3).b = 5;
 ## getfield (ss, @{1,2@}, "fd", @{3@}, "b")
-## @result{} ans = 5
+##      @result{} ans = 5
 ## @end group
 ## @end example
 ##
@@ -36,6 +36,8 @@
 ## @group
 ## i1 = @{1,2@}; i2 = "fd"; i3 = @{3@}; i4= "b";
 ## ss(i1@{:@}).(i2)(i3@{:@}).(i4)
+##      @result{} ans = 5
+## 
 ## @end group
 ## @end example
 ## @seealso{setfield, rmfield, isfield, isstruct, fieldnames, struct}
--- a/scripts/miscellaneous/orderfields.m	Sat Jan 16 07:59:52 2010 +0100
+++ b/scripts/miscellaneous/orderfields.m	Sun Jan 17 13:31:42 2010 +0100
@@ -17,15 +17,70 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{t}, @var{p}] =} orderfields (@var{s1}, @var{s2})
-## Return a struct with fields arranged alphabetically or as specified
-## by @var{s2} and a corresponding permutation vector.
+## @deftypefn {Function File} {[@var{t}, @var{p}] =} orderfields (@var{s1}[, @var{s2}])
+## Return a copy of @var{s1} with fields arranged alphabetically or
+## as specified by @var{s2}.
 ##
 ## Given one struct, arrange field names in @var{s1} alphabetically.
 ##
-## Given two structs, arrange field names in @var{s1} as they appear
-## in @var{s2}.  The second argument may also specify the order in
-## a permutation vector or a cell array of strings.
+## If the second argument is a struct, arrange field names in @var{s1}
+## as they appear in @var{s2}.  The second argument may also specify the
+## order in a permutation vector or a cell array of strings containing
+## the fieldnames of @var{s1} in the desired order.
+##
+## The optional second output argument @var{p} is assigned the permutation vector
+## which converts the original name order into the new name order.
+##
+## Examples:
+##
+## @example
+## @group
+## s = struct("d", 4, "b", 2, "a", 1, "c", 3);
+## t1 = orderfields(s)
+##      @result{} t1 = 
+##         @{
+##           a =  1
+##           b =  2
+##           c =  3
+##           d =  4
+##         @}
+## @end group
+## @group
+## t = struct("d", @{@}, "c", @{@}, "b", "a", @{@});
+## t2 = orderfields(s, t)
+##      @result{} t2 =
+##         @{
+##           d =  4
+##           c =  3
+##           b =  2
+##           a =  1
+##         @}
+## @end group
+## @group
+## t3 = orderfields(s, [3, 2, 4, 1]);
+##      @result{} t3 =
+##         @{
+##           a =  1
+##           b =  2
+##           c =  3
+##           d =  4
+##         @}
+## @end group
+## @group
+## [t4, p] = orderfields(s, @{"d", "c", "b", "a"@})
+##      @result{} t4 = @{
+##           d =  4
+##           c =  3
+##           b =  2
+##           a =  1
+##         @}
+##      p =
+##         1
+##         4
+##         2
+##         3
+## @end group
+## @end example
 ##
 ## @seealso{getfield, rmfield, isfield, isstruct, fieldnames, struct}
 ## @end deftypefn
@@ -113,9 +168,10 @@
 %! assert (a(2).foo, 5)
 %! assert (a(2).bar, 6)
 %!test
-%! a(2) = orderfields (b, [2 1]);
+%! [a(2), p] = orderfields (b, [2 1]);
 %! assert (a(2).foo, 5)
 %! assert (a(2).bar, 6)
+%! assert (p, [2; 1]);
 %!test
 %! a(2) = orderfields (b, fieldnames (a));
 %! assert (a(2).foo, 5)
--- a/scripts/miscellaneous/setfield.m	Sat Jan 16 07:59:52 2010 +0100
+++ b/scripts/miscellaneous/setfield.m	Sun Jan 17 13:31:42 2010 +0100
@@ -19,23 +19,24 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {[@var{k1}, @dots{}, @var{v1}] =} setfield (@var{s}, @var{k1}, @var{v1}, @dots{})
-## Set field members in a structure.
+## Set a field member in a (nested) structure array.  For example:
 ##
 ## @example
 ## @group
 ## oo(1,1).f0 = 1;
 ## oo = setfield (oo, @{1,2@}, "fd", @{3@}, "b", 6);
 ## oo(1,2).fd(3).b == 6
-## @result{} ans = 1
+##      @result{} ans = 1
 ## @end group
 ## @end example
 ##
-## Note that this function could be written
+## Note that the same result as in the above example could be achieved by:
 ##
 ## @example
 ## @group
 ## i1 = @{1,2@}; i2 = "fd"; i3 = @{3@}; i4 = "b";
-## oo(i1@{:@}).(i2)(i3@{:@}).(i4) == 6;
+## oo(i1@{:@}).(i2)(i3@{:@}).(i4) == 6
+##      @result{} ans = 1
 ## @end group
 ## @end example
 ## @seealso{getfield, rmfield, isfield, isstruct, fieldnames, struct}
--- a/scripts/miscellaneous/substruct.m	Sat Jan 16 07:59:52 2010 +0100
+++ b/scripts/miscellaneous/substruct.m	Sun Jan 17 13:31:42 2010 +0100
@@ -19,7 +19,27 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} substruct (@var{type}, @var{subs}, @dots{})
 ## Create a subscript structure for use with @code{subsref} or
-## @code{subsasgn}.
+## @code{subsasgn}. For example:
+##
+## @example
+## @group
+## idx = substruct("()", @{3, ":"@})
+##      @result{}
+##        idx =
+##        @{
+##          type = ()
+##          subs =
+##          @{
+##            [1,1] =  3
+##            [1,2] = :
+##          @}
+##        @}
+## x = [1, 2, 3; 4, 5, 6; 7, 8, 9];
+## subsref(x, idx)
+##      @result{} ans = 
+##         7  8  9
+## @end group
+## @end example
 ## @seealso{subsref, subsasgn}
 ## @end deftypefn
 
--- a/src/ChangeLog	Sat Jan 16 07:59:52 2010 +0100
+++ b/src/ChangeLog	Sun Jan 17 13:31:42 2010 +0100
@@ -1,3 +1,12 @@
+2010-01-17  Thorsten Meyer  <thorsten.meyier@gmx.de>
+
+	* ov-cell.cc (Fstruct2cell): Add example, add test.
+	* DLD-FUNCTIONS/cellfun.cc (Fcellfun, Fnum2cell), ov-struct.cc
+	(Fisstruct): Fix docstring.
+	* DLD-FUNCTIONS/cellfun.cc (Fcellslices, Fisfield, Ffieldnames,
+	Frmfield): Add test.
+        * ov-struct.cc (Fcell2struct): Fix docstring, add test.
+
 2010-01-16  David Bateman  <dbateman@free.fr>
 
 	* graphics.h.in (line::properties, surface::properties,
--- a/src/DLD-FUNCTIONS/cellfun.cc	Sat Jan 16 07:59:52 2010 +0100
+++ b/src/DLD-FUNCTIONS/cellfun.cc	Sun Jan 17 13:31:42 2010 +0100
@@ -230,7 +230,7 @@
 @deftypefnx {Loadable Function} {} cellfun (\"isclass\", @var{c}, @var{class})\n\
 @deftypefnx {Loadable Function} {} cellfun (@var{func}, @var{c})\n\
 @deftypefnx {Loadable Function} {} cellfun (@var{func}, @var{c}, @var{d})\n\
-@deftypefnx {Loadable Function} {[@var{a}, @var{b}] =} cellfun (@dots{})\n\
+@deftypefnx {Loadable Function} {[@var{a}, @dots{}] =} cellfun (@dots{})\n\
 @deftypefnx {Loadable Function} {} cellfun (@dots{}, 'ErrorHandler', @var{errfunc})\n\
 @deftypefnx {Loadable Function} {} cellfun (@dots{}, 'UniformOutput', @var{val})\n\
 \n\
@@ -268,19 +268,37 @@
 @example\n\
 @group\n\
 cellfun (@@atan2, @{1, 0@}, @{0, 1@})\n\
-@result{}ans = [1.57080   0.00000]\n\
+     @result{}ans = [1.57080   0.00000]\n\
 @end group\n\
 @end example\n\
 \n\
-Note that the default output argument is an array of the same size as the\n\
+The number of output arguments of @code{cellfun} matches the number of output\n\
+arguments of the function.  The outputs of the function will be collected into the\n\
+output arguments of @code{cellfun} like this:\n\
+\n\
+@example\n\
+@group\n\
+function [a, b] = twoouts (x)\n\
+  a = x;\n\
+  b = x*x;\n\
+endfunction\n\
+[aa, bb] = cellfun(@@twoouts, @{1, 2, 3@})\n\
+     @result{}\n\
+        aa = \n\
+           1 2 3\n\
+        bb =\n\
+           1 4 9\n\
+@end group\n\
+@end example\n\
+Note that per default the output argument(s) are arrays of the same size as the\n\
 input arguments.\n\
 Input arguments that are singleton (1x1) cells will be automatically expanded\n\
 to the size of the other arguments.\n\
 \n\
 If the parameter 'UniformOutput' is set to true (the default), then the function\n\
-must return a single element which will be concatenated into the\n\
-return value.  If 'UniformOutput' is false, the outputs are concatenated in\n\
-a cell array.  For example\n\
+must return scalars which will be concatenated into the\n\
+return array(s).  If 'UniformOutput' is false, the outputs are concatenated into\n\
+a cell array (or cell arrays).  For example\n\
 \n\
 @example\n\
 @group\n\
@@ -1084,7 +1102,31 @@
 @deftypefnx {Loadable Function} {@var{c} =} num2cell (@var{m}, @var{dim})\n\
 Convert the matrix @var{m} to a cell array.  If @var{dim} is defined, the\n\
 value @var{c} is of dimension 1 in this dimension and the elements of\n\
-@var{m} are placed in slices in @var{c}.\n\
+@var{m} are placed into @var{c} in slices.  For example:\n\
+\n\
+@example\n\
+@group\n\
+num2cell([1,2;3,4])\n\
+     @result{} ans =\n\
+        @{\n\
+          [1,1] =  1\n\
+          [2,1] =  3\n\
+          [1,2] =  2\n\
+          [2,2] =  4\n\
+        @}\n\
+num2cell([1,2;3,4],1)\n\
+     @result{} ans =\n\
+        @{\n\
+          [1,1] =\n\
+             1\n\
+             3\n\
+          [1,2] =\n\
+             2\n\
+             4\n\
+        @}\n\
+@end group\n\
+@end example\n\
+\n\
 @seealso{mat2cell}\n\
 @end deftypefn") 
 {
@@ -1538,7 +1580,14 @@
 
   return retval;
 }
-	  
+
+/*
+%!test
+%! m = [1, 2, 3, 4; 5, 6, 7, 8; 9, 10, 11, 12];
+%! c = cellslices (m, [1, 2], [2, 3]);
+%! assert (c, {[1, 2; 5, 6; 9, 10], [2, 3; 6, 7; 10, 11]});
+*/
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/ov-cell.cc	Sat Jan 16 07:59:52 2010 +0100
+++ b/src/ov-cell.cc	Sun Jan 17 13:31:42 2010 +0100
@@ -1339,7 +1339,30 @@
 Create a new cell array from the objects stored in the struct object.\n\
 If @var{f} is the number of fields in the structure, the resulting\n\
 cell array will have a dimension vector corresponding to\n\
-@code{[@var{F} size(@var{S})]}.\n\
+@code{[@var{F} size(@var{S})]}. For example:\n\
+\n\
+@example\n\
+@group\n\
+  s = struct('name', @{'Peter', 'Hannah', 'Robert'@}, 'age', @{23, 16, 3@});\n\
+  c = struct2cell(s)\n\
+     @result{} c = @{1x1x3 Cell Array@}\n\
+  c(1,1,:)(:)\n\
+     @result{} ans =\n\
+        @{\n\
+          [1,1] = Peter\n\
+          [2,1] = Hannah\n\
+          [3,1] = Robert\n\
+        @}\n\
+  c(2,1,:)(:)\n\
+     @result{} ans =\n\
+        @{\n\
+          [1,1] = 23\n\
+          [2,1] = 16\n\
+          [3,1] = 3\n\
+        @}\n\
+@end group\n\
+@end example\n\
+\n\
 @seealso{cell2struct, fieldnames}\n\
 @end deftypefn")
 {
@@ -1402,6 +1425,18 @@
   return retval;
 }
 
+/*
+%!test
+%!  keys = cellstr (char (floor (rand (11,10)*24+65)))';
+%!  vals = cellfun(@(x) mat2cell(rand (19,1), ones (19,1), 1), ...
+%!           mat2cell([1:11]', ones(11,1), 1), "uniformoutput", false)';
+%!  s = struct ([keys; vals]{:});
+%!  t = cell2struct ([vals{:}], keys, 2);
+%!  assert (s, t);
+%!  assert (struct2cell (s), [vals{:}]');
+%!  assert (fieldnames (s), keys');
+*/
+
 mxArray *
 octave_cell::as_mxArray (void) const
 {
--- a/src/ov-struct.cc	Sat Jan 16 07:59:52 2010 +0100
+++ b/src/ov-struct.cc	Sun Jan 17 13:31:42 2010 +0100
@@ -837,7 +837,8 @@
 DEFUN (isstruct, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} isstruct (@var{expr})\n\
-Return 1 if the value of the expression @var{expr} is a structure.\n\
+Return 1 if the value of the expression @var{expr} is a structure\n\
+(or a structure array).\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -886,6 +887,13 @@
   return retval;
 }
 
+/*
+%!# test preservation of fieldname order
+%!test
+%!  x(3).d=1; x(2).a=2; x(1).b=3; x(2).c=3;
+%!  assert(fieldnames(x), {"d"; "a"; "b"; "c"});
+*/
+
 DEFUN (isfield, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} isfield (@var{expr}, @var{name})\n\
@@ -940,6 +948,18 @@
   return retval;
 }
 
+/*
+%!# test isfield
+%!test
+%!  x(3).d=1; x(2).a=2; x(1).b=3; x(2).c=3;
+%!  assert (isfield (x, "b"));
+%!assert( isfield( struct("a", "1"), "a"));
+%!assert( isfield( {1}, "c"), logical (0));
+%!assert( isfield( struct("a", "1"), 10), logical (0));
+%!assert( isfield( struct("a", "b"), "a "), logical (0));
+
+*/
+
 // Check that the dimensions of the input arguments are correct.
 
 static bool
@@ -1014,11 +1034,11 @@
                    185, 170, 168@},\n\
                  @{'Name','Height'@}, 1);\n\
 A(1)\n\
-@result{} ans =\n\
-      @{\n\
-        Height = 185\n\
-        Name   = Peter\n\
-      @}\n\
+     @result{} ans =\n\
+        @{\n\
+          Name   = Peter\n\
+          Height = 185\n\
+        @}\n\
 \n\
 @end group\n\
 @end example\n\
@@ -1187,14 +1207,27 @@
   return retval;
 }
 
+/*
+%!# test cell2struct versus struct2cell
+%!test
+%!  keys = cellstr (char (floor (rand (100,10)*24+65)))';
+%!  vals = mat2cell(rand (100,1), ones (100,1), 1)';
+%!  s = struct ([keys; vals]{:});
+%!  t = cell2struct (vals, keys, 2);
+%!  assert (s, t);
+%!  assert (struct2cell (s), vals');
+%!  assert (fieldnames (s), keys');
+*/
+
+
 // So we can call Fcellstr directly.
 extern octave_value_list Fcellstr (const octave_value_list& args, int);
 
 DEFUN (rmfield, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} rmfield (@var{s}, @var{f})\n\
-Remove field @var{f} from the structure @var{s}.  If @var{f} is a\n\
-cell array of character strings or a character array, remove the\n\
+Return a copy of the structure (array) @var{s} with the field @var{f} removed.\n\
+If @var{f} is a cell array of strings or a character array, remove the\n\
 named fields.\n\
 @seealso{cellstr, iscellstr, setfield}\n\
 @end deftypefn")
@@ -1238,6 +1271,15 @@
   return retval;
 }
 
+/*
+%!# test rmfield
+%!test
+%!  x(3).d=1; x(2).a=2; x(1).b=3; x(2).c=3; x(6).f="abc123";
+%!  y = rmfield (x, {"a", "f"});
+%!  assert (fieldnames (y), {"d"; "b"; "c"});
+%!  assert (size (y), [1, 6]);
+*/
+
 bool
 octave_struct::save_ascii (std::ostream& os)
 {