changeset 5784:70f7659d0fb9

[project @ 2006-05-03 05:55:56 by dbateman]
author dbateman
date Wed, 03 May 2006 05:57:16 +0000
parents 2a9089b47dc2
children 6b9cec830d72
files src/ChangeLog src/DLD-FUNCTIONS/cellfun.cc
diffstat 2 files changed, 228 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Wed May 03 00:02:22 2006 +0000
+++ b/src/ChangeLog	Wed May 03 05:57:16 2006 +0000
@@ -1,3 +1,7 @@
+2006-05-03  David Bateman  <dbateman@free.fr>
+
+	* DLD-FUNCTIONS/cellfun.cc (Fmat2cell): new function.
+
 2006-05-02  John W. Eaton  <jwe@octave.org>
 
 	* lex.l ({CCHAR}): Exit rawcommand mode if returning '\n' token.
--- a/src/DLD-FUNCTIONS/cellfun.cc	Wed May 03 00:02:22 2006 +0000
+++ b/src/DLD-FUNCTIONS/cellfun.cc	Wed May 03 05:57:16 2006 +0000
@@ -332,6 +332,230 @@
   return retval;
 }
 
+DEFUN_DLD (mat2cell, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{b} =} mat2cell (@var{a}, @var{m}, @var{n})\n\
+@deftypefnx {Loadable Function} {@var{b} =} mat2cell (@var{a}, @var{d1}, @var{d2}, @dots{})\n\
+@deftypefnx {Loadable Function} {@var{b} =} mat2cell (@var{a}, @var{r})\n\
+Converts the matrix @var{a} to a cell array If @var{a} is 2-D, then\n\
+it is required that @code{sum (@var{m}) == size (@var{a}, 1)} and\n\
+@code{sum (@var{n}) == size (@var{a}, 2)}. Similarly, if @var{a} is\n\
+a multi-dimensional and the number of dimensional arguments is equal\n\
+to the dimensions of @var{a}, then it is required that @code{sum (@var{di})\n\
+== size (@var{a}, i)}.\n\
+\n\
+Given a single dimensional argument @var{r}, the other dimensional\n\
+arguments are assumed to equal @code{size (@var{a},@var{i})}.\n\
+\n\
+An example of the use of mat2cell is\n\
+\n\
+@example\n\
+@group\n\
+mat2cell (reshape(1:16,4,4),[3,1],[3,1])\n\
+@result{} @{\n\
+  [1,1] =\n\
+\n\
+     1   5   9\n\
+     2   6  10\n\
+     3   7  11\n\
+\n\
+  [2,1] =\n\
+\n\
+     4   8  12\n\
+\n\
+  [1,2] =\n\
+\n\
+    13\n\
+    14\n\
+    15\n\
+\n\
+  [2,2] = 16\n\
+@}\n\
+@end group\n\
+@end example\n\
+@seealso{num2cell,cell2mat\n\
+@end deftypefn")
+{
+  int nargin = args.length();
+  octave_value retval;
+
+  if (nargin < 2)
+    usage ("mat2cell");
+  else
+    {
+      dim_vector dv = args(0).dims();
+      dim_vector new_dv;
+      new_dv.resize(dv.length());
+      
+      if (nargin > 2)
+	{
+	  octave_idx_type nmax = -1;
+
+	  if (nargin - 1 != dv.length())
+	    error ("mat2cell: Incorrect number of dimensions");
+	  else
+	    {
+	      for (octave_idx_type j = 0; j < dv.length(); j++)
+		{
+		  ColumnVector d = ColumnVector (args(j+1).vector_value 
+						 (false, true));
+
+		  if (d.length() < 1)
+		    {
+		      error ("mat2cell: dimension can not be empty");
+		      break;
+		    }
+		  else
+		    {
+		      if (nmax < d.length())
+			nmax = d.length();
+
+		      for (octave_idx_type i = 1; i < d.length(); i++)
+			{
+			  OCTAVE_QUIT;
+
+			  if (d(i) >= 0)
+			    d(i) += d(i-1);
+			  else
+			    {
+			      error ("mat2cell: invalid dimensional argument");
+			      break;
+			    }
+			}
+
+		      if (d(0) < 0)
+			error ("mat2cell: invalid dimensional argument");
+		      
+		      if (d(d.length() - 1) != dv(j))
+			error ("mat2cell: inconsistent dimensions");
+
+		      if (error_state)
+			break;
+
+		      new_dv(j) = d.length();
+		    }
+		}
+	    }
+
+	  if (! error_state)
+	    {
+	      // Construct a matrix with the index values
+	      Matrix dimargs(nmax, new_dv.length());
+	      for (octave_idx_type j = 0; j < new_dv.length(); j++)
+		{
+		  OCTAVE_QUIT;
+
+		  ColumnVector d = ColumnVector (args(j+1).vector_value 
+						 (false, true));
+
+		  dimargs(0,j) = d(0);
+		  for (octave_idx_type i = 1; i < d.length(); i++)
+		    dimargs(i,j) = dimargs(i-1,j) + d(i);
+		}
+
+
+	      octave_value_list lst (new_dv.length(), octave_value());
+	      Cell ret (new_dv);
+	      octave_idx_type nel = new_dv.numel();
+	      octave_idx_type ntot = 1;
+
+	      for (int j = 0; j < new_dv.length()-1; j++)
+		ntot *= new_dv(j);
+
+	      for (octave_idx_type i = 0; i <  nel; i++)
+		{
+		  octave_idx_type n = ntot;
+		  octave_idx_type ii = i;
+		  for (octave_idx_type j =  new_dv.length() - 1;  j >= 0; j--)
+		    {
+		      OCTAVE_QUIT;
+		  
+		      octave_idx_type idx = ii / n;
+		      lst (j) = Range((idx == 0 ? 1. : dimargs(idx-1,j)+1.),
+				      dimargs(idx,j));
+		      ii = ii % n;
+		      if (j != 0)
+			n /= new_dv(j-1);
+		    }
+		  ret(i) = args(0).do_index_op(lst, 0);
+		  if (error_state)
+		    break;
+		}
+	  
+	      if (!error_state)
+		retval = ret;
+	    }
+	}
+      else
+	{
+	  ColumnVector d = ColumnVector (args(1).vector_value 
+					 (false, true));
+
+	  double sumd = 0.;
+	  for (octave_idx_type i = 0; i < d.length(); i++)
+	    {
+	      OCTAVE_QUIT;
+
+	      if (d(i) >= 0)
+		sumd += d(i);
+	      else
+		{
+		  error ("mat2cell: invalid dimensional argument");
+		  break;
+		}
+	    }
+
+	  if (sumd != dv(0))
+	    error ("mat2cell: inconsistent dimensions");
+
+	  new_dv(0) = d.length();
+	  for (octave_idx_type i = 1; i < dv.length(); i++)
+	    new_dv(i) = 1;
+
+	  if (! error_state)
+	    {
+	      octave_value_list lst (new_dv.length(), octave_value());
+	      Cell ret (new_dv);
+
+	      for (octave_idx_type i = 1; i < new_dv.length(); i++)
+		lst (i) = Range (1., static_cast<double>(dv(i)));
+	      
+	      double idx = 0.;
+	      for (octave_idx_type i = 0; i <  new_dv(0); i++)
+		{
+		  OCTAVE_QUIT;
+
+		  lst(0) = Range(idx + 1., idx + d(i));
+		  ret(i) = args(0).do_index_op(lst, 0);
+		  idx += d(i);
+		  if (error_state)
+		    break;
+		}
+	  
+	      if (!error_state)
+		retval = ret;
+	    }
+	}
+    }
+
+  return retval;
+}
+
+/*
+
+%!test
+%! x = reshape(1:20,5,4);
+%! c = mat2cell(x,[3,2],[3,1]);
+%! assert(c,{[1,6,11;2,7,12;3,8,13],[16;17;18];[4,9,14;5,10,15],[19;20]})
+
+%!test
+%! x = 'abcdefghij';
+%! c = mat2cell(x,1,[0,4,2,0,4,0]);
+%! empty1by0str = resize('',1,0);
+%! assert(c,{empty1by0str,'abcd','ef',empty1by0str,'ghij',empty1by0str})
+
+*/
+	  
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***