changeset 4758:a308566c8b42

[project @ 2004-02-13 23:01:34 by jwe]
author jwe
date Fri, 13 Feb 2004 23:01:34 +0000
parents c48180a45d34
children 364bbf35dbfa
files liboctave/CNDArray.cc liboctave/CNDArray.h liboctave/ChangeLog liboctave/chNDArray.cc liboctave/chNDArray.h liboctave/dNDArray.cc liboctave/dNDArray.h liboctave/mx-inlines.cc src/ChangeLog src/data.cc src/ov-re-mat.cc src/ov-re-mat.h
diffstat 12 files changed, 337 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/CNDArray.cc	Fri Feb 13 22:13:52 2004 +0000
+++ b/liboctave/CNDArray.cc	Fri Feb 13 23:01:34 2004 +0000
@@ -231,6 +231,12 @@
   MX_ND_COMPLEX_OP_REDUCTION (+= elem (iter_idx), Complex (0, 0));
 }
 
+bool
+ComplexNDArray::cat (ComplexNDArray& cat_arr, int dim, int add_dim) const
+{
+  MX_ND_CAT;
+}
+
 NDArray
 ComplexNDArray::abs (void) const
 {
--- a/liboctave/CNDArray.h	Fri Feb 13 22:13:52 2004 +0000
+++ b/liboctave/CNDArray.h	Fri Feb 13 23:01:34 2004 +0000
@@ -87,6 +87,7 @@
   ComplexNDArray prod (int dim = -1) const;
   ComplexNDArray sum (int dim = -1) const;
   ComplexNDArray sumsq (int dim = -1) const;
+  bool cat (ComplexNDArray& cat_array, int dim, int add_dim) const;
 
   NDArray abs (void) const;
 
--- a/liboctave/ChangeLog	Fri Feb 13 22:13:52 2004 +0000
+++ b/liboctave/ChangeLog	Fri Feb 13 23:01:34 2004 +0000
@@ -1,3 +1,13 @@
+2004-02-13  Petter Risholm  <risholm@stud.ntnu.no>
+
+	* mx-inlines.cc (MX_ND_CAT): New macro.
+	* dNDArray.cc (NDArray::cat): New function.
+	* dNDArray.h: Provide decls.
+	* CNDArray.cc (complexNDArray::cat): New function.
+	* CNDArray.h: Provide decls.
+	* chNDArray.cc (charNDArray::cat): New function.
+	* chNDArray.h: Provide decls.
+
 2004-02-13  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* Array.cc (maybe_delete_elements_2): Allow X(n) = [] for 2-d X.
--- a/liboctave/chNDArray.cc	Fri Feb 13 22:13:52 2004 +0000
+++ b/liboctave/chNDArray.cc	Fri Feb 13 23:01:34 2004 +0000
@@ -48,6 +48,12 @@
   MX_ND_ANY_ALL_REDUCTION (MX_ND_ANY_EVAL (elem (iter_idx) != ' '), false);
 }
 
+bool
+charNDArray::cat (charNDArray& cat_arr, int dim, int add_dim) const
+{
+  MX_ND_CAT;  
+}
+
 charMatrix
 charNDArray::matrix_value (void) const
 {
--- a/liboctave/chNDArray.h	Fri Feb 13 22:13:52 2004 +0000
+++ b/liboctave/chNDArray.h	Fri Feb 13 23:01:34 2004 +0000
@@ -71,7 +71,8 @@
 
   boolNDArray all (int dim = -1) const;
   boolNDArray any (int dim = -1) const;
-
+  bool cat (charNDArray& cat_array, int dim, int add_dim) const;
+ 
   charMatrix matrix_value (void) const;
 
   charNDArray squeeze (void) const { return ArrayN<char>::squeeze (); }
--- a/liboctave/dNDArray.cc	Fri Feb 13 22:13:52 2004 +0000
+++ b/liboctave/dNDArray.cc	Fri Feb 13 23:01:34 2004 +0000
@@ -212,6 +212,12 @@
   MX_ND_REAL_OP_REDUCTION (+= elem (iter_idx), 0);
 }
 
+bool
+NDArray::cat (NDArray& cat_arr, int dim, int add_dim) const
+{
+  MX_ND_CAT;
+}
+
 NDArray
 real (const ComplexNDArray& a)
 {
--- a/liboctave/dNDArray.h	Fri Feb 13 22:13:52 2004 +0000
+++ b/liboctave/dNDArray.h	Fri Feb 13 23:01:34 2004 +0000
@@ -86,7 +86,8 @@
   NDArray prod (int dim = -1) const;
   NDArray sum (int dim = -1) const;  
   NDArray sumsq (int dim = -1) const;
- 
+  bool cat (NDArray& cat_array, int dim, int add_dim) const;
+     
   NDArray abs (void) const;
 
   friend NDArray real (const ComplexNDArray& a);
--- a/liboctave/mx-inlines.cc	Fri Feb 13 22:13:52 2004 +0000
+++ b/liboctave/mx-inlines.cc	Fri Feb 13 23:01:34 2004 +0000
@@ -607,6 +607,34 @@
 \
   return retval
 
+#define MX_ND_CAT \
+ bool retval = false;\
+ \
+  dim_vector dv = dims (); \
+ \
+   Array<int> ra_idx (dv.length (), 0); \
+ \
+   for (int i = 0; i < length (); i++) \
+     { \
+       if (i != 0) \
+	 increment_index (ra_idx, dv, 0); \
+ \
+       Array<int> ra_idx2 = ra_idx; \
+ \
+       if (dim >= ra_idx2.length ()) \
+	 { \
+	   ra_idx2.resize_and_fill (dim + 1, 0); \
+ \
+	   retval = true; \
+	 } \
+ \
+       ra_idx2.elem (dim) = ra_idx2.elem (dim) + add_dim; \
+ \
+       cat_arr.elem (ra_idx2) =  elem (ra_idx); \
+     } \
+ \
+   return retval
+
 #endif
 
 /*
--- a/src/ChangeLog	Fri Feb 13 22:13:52 2004 +0000
+++ b/src/ChangeLog	Fri Feb 13 23:01:34 2004 +0000
@@ -1,3 +1,9 @@
+2004-02-13  Petter Risholm  <risholm@stud.ntnu.no>
+
+	* data.cc (Fcat): New function.
+	* data.cc (do_cat): New function.
+	* data.cc (cat_add_dims): New function.
+
 2004-02-13  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* toplev.cc (main_loop): Call octave_parse, not yyparse.
--- a/src/data.cc	Fri Feb 13 22:13:52 2004 +0000
+++ b/src/data.cc	Fri Feb 13 23:01:34 2004 +0000
@@ -665,6 +665,260 @@
   DATA_REDUCTION (prod);
 }
 
+static bool
+cat_add_dims (dim_vector& dv_new, const dim_vector& dv_arg, int dim)
+{
+  // dv_arg is []
+  if (dv_arg.all_zero ())
+    return true;
+  
+  // dv_new is []
+  if (dv_new.all_zero ())
+    {
+      dv_new = dv_arg;
+      return true;
+    }
+  
+  int n_new  = dv_new.length ();
+  int n_args = dv_arg.length ();
+  
+  // Find the max and min value of n_new and n_args
+  int n_max = n_new > n_args ? n_new : n_args;
+  int n_min = n_new < n_args ? n_new : n_args;  
+
+  // The elements of the dimension vectors can only differ
+  // if the dim variable differs from the actual dimension
+  // they differ.
+  for (int i = 0; i < n_min; i++)
+    {
+      if (dv_new(i) != dv_arg(i) && dim != i)
+	{
+	  error ("cat: dimension mismatch");
+	  return false;
+	}
+    }
+  
+  // Ditto
+  for (int i = n_min; i < n_max; i++)
+    {
+      if (n_new > n_min)
+	{
+	  if (dv_new(i) != 1 && dim != i)
+	    {
+	      error ("cat: dimension mismatch");
+	      return false;
+	    }
+	}
+      else 
+	{
+	  if (dv_arg(i) != 1 && dim != i)
+	    {
+	      error ("cat: dimension mismatch");
+	      return false;
+	    }
+	}
+    }
+
+  // If we want to add the dimension vectors at a dimension
+  // larger than both, then we need to set n_max to this number
+  // so that we resize dv_new to the right dimension.
+  n_max = n_max > (dim + 1) ? n_max : (dim + 1);
+  
+  // Resize dv_new to new the appropriate dimensions.
+  if (n_max > n_new)
+    {
+      dv_new.resize (n_max);
+
+      for (int i = n_new; i < n_max; i++)
+	dv_new.elem (i) = 1;
+    }
+  
+  if (dim > n_args)
+    dv_new.elem (dim) = dv_new.elem (dim)++;
+  else
+    dv_new.elem (dim) += dv_arg(dim);
+
+  return true;
+}
+
+static octave_value
+do_cat (const octave_value_list& args)
+{
+  octave_value retval;
+
+  int dim = args(0).int_value () - 1;
+
+  if (error_state)
+    {
+      error ("cat: expecting first argument to be a integer");
+      return retval;
+    }
+
+  if (args.length () > 2 && (dim >= 0))
+    {      
+      dim_vector  dv = args(1).dims ();
+
+      // I need to look into these conversions
+      for (int i = 2; i < args.length (); i++)
+	{
+	  // add_dims constructs a dimension vector which 
+	  // holds the dimensions of the final array after
+	  // concatenation.
+	  if (! cat_add_dims (dv, args(i).dims (), dim))
+	    return retval; // Dimensions do not match
+	}
+
+      NDArray cat_re = NDArray (dv, 0);
+      ComplexNDArray cat_cx;
+      charNDArray cat_ch;
+
+      // The final array can be of three types.
+      // Here is a compatible chart
+      //     re cx ch
+      // --------------
+      // re |re cx ch
+      // cx |cx cx X
+      // ch |ch X  ch
+      // Where X means incompatible
+      enum types { REAL, COMPLEX, CHAR } t = REAL;      
+
+      // Variable which tells us how much we have extended
+      // the variable along the dim dimension.
+      int curr_add_dims = 0;
+
+      // Tells us wether the array we concatenated had less dimensions
+      // than dim, such that we only add one dimension to curr_add_dims.
+      bool extended_dims = false;
+      
+      // Start filling in values
+      for (int i = 1; i < args.length (); i++)
+	{
+	  octave_value tmp = args (i);
+
+	  dim_vector dv_arg = tmp.dims ();
+
+	  // This variable tells us wether the the new value is
+	  // has a number of dimension less than the final value.
+	  extended_dims = false;
+	  
+	  if (t == REAL)
+	    {
+	      if (tmp.is_complex_type ())
+		{
+		  cat_cx = ComplexNDArray (cat_re);
+		  
+		  extended_dims =
+		    tmp.complex_array_value ().cat (cat_cx, dim, curr_add_dims);
+		  
+		  t = COMPLEX;
+		}
+	      else if (tmp.is_string ())
+		{
+		  // This is a hack to be able to convert a dNDArray
+		  // to a chNDArray.
+		  cat_ch = charNDArray (octave_value (cat_re).char_array_value ());
+		  
+		  extended_dims =
+		    tmp.char_array_value ().cat (cat_ch, dim, curr_add_dims);
+		  
+		  t = CHAR;
+		}
+	      else
+		extended_dims = 
+		  tmp.array_value().cat (cat_re, dim, curr_add_dims);
+	    }
+	  else if (t == COMPLEX)
+	    {
+	      extended_dims = 
+		tmp.complex_array_value ().cat (cat_cx, dim, curr_add_dims);
+	    }
+	  else if (t == CHAR)
+	    {
+	      if (tmp.is_complex_type ())
+		{
+		  error ("cannot convert complex type to character type");
+		  return retval;
+		}
+	      else
+		extended_dims =
+		  tmp.char_array_value ().cat (cat_ch, dim, curr_add_dims);
+	    }
+	  
+	  if (error_state) return retval; // Wrong conversion in the last if statement
+
+	  // Keep track of how many dimensions have been added
+	  if (extended_dims)
+	    curr_add_dims++;
+	  else
+	    curr_add_dims += dv_arg (dim);
+	}
+
+      if (t == REAL)
+	retval = octave_value (cat_re);
+      else if (t == COMPLEX)
+	retval = octave_value (cat_cx);
+      else if (t == CHAR)
+	retval = octave_value (cat_ch);
+    }
+  else
+    print_usage ("cat");
+
+  return retval;
+}
+
+DEFUN (cat, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} cat (@var{dim}, @var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
+Return the concatenation of N-d array objects, @var{array1}, @var{array2}, @dots{}, @var{arrayN} along dimension @var{dim}.\n\
+\n\
+@example\n\
+@group\n\
+A = ones (2, 2);\n\
+B = zeros (2, 2);\n\
+cat (2, A, B)\n\
+@result{} ans =\n\
+\n\
+     1 1 0 0\n\
+     1 1 0 0\n\
+     1 1 0 0\n\
+     1 1 0 0\n\
+@end group\n\
+@end example\n\
+\n\
+Alternatively, we can concatenate @var{A} and @var{B} along the\n\
+second dimension the following way:\n\
+\n\
+@example\n\
+@group\n\
+[A, B].\n\
+@end group\n\
+@end example\n\
+\n\
+@var{dim} can be larger than the dimensions of the N-d array objects\n\
+and the result will thus have @var{dim} dimensions as the\n\
+following example shows:\n\
+@example\n\
+@group\n\
+cat (4, ones(2, 2), zeros (2, 2))\n\
+@result{} ans =\n\
+\n\
+   ans(:,:,1,1) =\n\
+\n\
+     1 1\n\
+     1 1\n\
+\n\
+   ans(:,:,1,2) =\n\
+     0 0\n\
+     0 0\n\
+@end group\n\
+@end example\n\
+\n\
+@seealso{horzcat and vertcat}\n\
+@end deftypefn")
+{
+  return do_cat (args);
+}
+
 static octave_value
 do_permute (const octave_value_list& args, bool inv, const std::string& fname)
 {
--- a/src/ov-re-mat.cc	Fri Feb 13 22:13:52 2004 +0000
+++ b/src/ov-re-mat.cc	Fri Feb 13 23:01:34 2004 +0000
@@ -145,6 +145,19 @@
   return ComplexNDArray (matrix);
 }
 
+charNDArray
+octave_matrix::char_array_value (bool) const
+{
+  charNDArray retval (dims ());
+
+  int nel = numel ();
+  
+  for (int i = 0; i < nel; i++)
+    retval.elem (i) = static_cast<char>(matrix.elem (i));
+
+  return retval;
+}
+  
 streamoff_array
 octave_matrix::streamoff_array_value (void) const
 {
--- a/src/ov-re-mat.h	Fri Feb 13 22:13:52 2004 +0000
+++ b/src/ov-re-mat.h	Fri Feb 13 23:01:34 2004 +0000
@@ -102,7 +102,9 @@
   ComplexMatrix complex_matrix_value (bool = false) const;
 
   ComplexNDArray complex_array_value (bool = false) const;
-
+   
+  charNDArray char_array_value (bool = false) const;
+  
   NDArray array_value (bool = false) const { return matrix; }
 
   streamoff_array streamoff_array_value (void) const;