changeset 8113:38a797766a2a

Special case single type conacation in Fcat. Rework cell2mat to take advantage
author David Bateman <dbateman@free.fr>
date Wed, 17 Sep 2008 17:31:24 -0400
parents 31e86163b752
children cbbea37b95e8
files src/data.cc src/pt-mat.h
diffstat 2 files changed, 171 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/src/data.cc	Wed Sep 17 16:04:27 2008 -0400
+++ b/src/data.cc	Wed Sep 17 17:31:24 2008 -0400
@@ -1763,6 +1763,51 @@
     } \
  while (0)
 
+#define SINGLE_TYPE_CONCAT(TYPE, EXTRACTOR) \
+  do \
+    { \
+      int dv_len = dv.length (); \
+      Array<octave_idx_type> ra_idx (dv_len > 1 ? dv_len : 2, 0); \
+      \
+      for (int j = 1; j < n_args; j++) \
+	{ \
+	  OCTAVE_QUIT; \
+	  \
+	  TYPE ra = args(j).EXTRACTOR ();	\
+	  \
+	  if (! error_state) \
+	    { \
+	      result.insert (ra, ra_idx); \
+	      \
+	      if (error_state) \
+	        return retval; \
+	      \
+	      dim_vector dv_tmp = args (j).dims (); \
+	      \
+	      if (dim >= dv_len) \
+	        { \
+		  if (j > 1) \
+		    error ("%s: indexing error", fname.c_str ()); \
+		  break; \
+		} \
+	      else \
+		ra_idx (dim) += (dim < dv_tmp.length () ? dv_tmp (dim) : 1); \
+	    } \
+	} \
+    } \
+ while (0)
+
+#define DO_SINGLE_TYPE_CONCAT(TYPE, EXTRACTOR) \
+  do \
+    { \
+      TYPE result (dv); \
+      \
+      SINGLE_TYPE_CONCAT(TYPE, EXTRACTOR); \
+      \
+      retval = result; \
+    } \
+ while (0)
+
 static octave_value
 do_cat (const octave_value_list& args, std::string fname)
 {
@@ -1806,69 +1851,146 @@
 		  error ("cat: dimension mismatch");
 		  return retval;
 		}
+	      
+	      result_type = 
+		get_concat_class (result_type, args(i).class_name ());
+
+	      if (all_sq_strings_p && ! args(i).is_sq_string ())
+		all_sq_strings_p = false;
+	      if (all_dq_strings_p && ! args(i).is_dq_string ())
+		all_dq_strings_p = false;
+	      if (all_real_p && ! args(i).is_real_type ())
+		all_real_p = false;
+	      if (!any_sparse_p && args(i).is_sparse_type ())
+		any_sparse_p = true;
 	    }
 
-	  // The lines below might seem crazy, since we take a copy
-	  // of the first argument, resize it to be empty and then resize
-	  // it to be full. This is done since it means that there is no
-	  // recopying of data, as would happen if we used a single resize.
-	  // It should be noted that resize operation is also significantly 
-	  // slower than the do_cat_op function, so it makes sense to have an
-	  // empty matrix and copy all data.
-	  //
-	  // We might also start with a empty octave_value using
-	  //   tmp = octave_value_typeinfo::lookup_type (args(1).type_name());
-	  // and then directly resize. However, for some types there might be
-	  // some additional setup needed, and so this should be avoided.
-
-	  octave_value tmp = args (1);
-	  tmp = tmp.resize (dim_vector (0,0)).resize (dv);
-
-	  if (error_state)
-	    return retval;
-
-	  int dv_len = dv.length ();
-	  Array<octave_idx_type> ra_idx (dv_len, 0);
-
-	  for (int j = 1; j < n_args; j++)
+	  if (result_type == "double")
+	    {
+	      if (any_sparse_p)
+		{	    
+		  if (all_real_p)
+		    DO_SINGLE_TYPE_CONCAT (SparseMatrix, sparse_matrix_value);
+		  else
+		    DO_SINGLE_TYPE_CONCAT (SparseComplexMatrix, sparse_complex_matrix_value);
+		}
+	      else
+		{
+		  if (all_real_p)
+		    DO_SINGLE_TYPE_CONCAT (NDArray, array_value);
+		  else
+		    DO_SINGLE_TYPE_CONCAT (ComplexNDArray, complex_array_value);
+		}
+	    }
+	  else if (result_type == "single")
+	    {
+	      if (all_real_p)
+		DO_SINGLE_TYPE_CONCAT (FloatNDArray, float_array_value);
+	      else
+		DO_SINGLE_TYPE_CONCAT (FloatComplexNDArray, 
+				       float_complex_array_value);
+	    }
+	  else if (result_type == "char")
+	    {
+	      char type = all_dq_strings_p ? '"' : '\'';
+
+	      maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p);
+
+	      charNDArray result (dv, Vstring_fill_char);
+
+	      SINGLE_TYPE_CONCAT (charNDArray, char_array_value);
+
+	      retval = octave_value (result, true, type);
+	    }
+	  else if (result_type == "logical")
 	    {
-	      // Can't fast return here to skip empty matrices as something
-	      // like cat(1,[],single([])) must return an empty matrix of
-	      // the right type.
-	      tmp = do_cat_op (tmp, args (j), ra_idx);
+	      if (any_sparse_p)
+		DO_SINGLE_TYPE_CONCAT (SparseBoolMatrix, sparse_bool_matrix_value);
+	      else
+		DO_SINGLE_TYPE_CONCAT (boolNDArray, bool_array_value);
+	    }
+	  else if (result_type == "int8")
+	    DO_SINGLE_TYPE_CONCAT (int8NDArray, int8_array_value);
+	  else if (result_type == "int16")
+	    DO_SINGLE_TYPE_CONCAT (int16NDArray, int16_array_value);
+	  else if (result_type == "int32")
+	    DO_SINGLE_TYPE_CONCAT (int32NDArray, int32_array_value);
+	  else if (result_type == "int64")
+	    DO_SINGLE_TYPE_CONCAT (int64NDArray, int64_array_value);
+	  else if (result_type == "uint8")
+	    DO_SINGLE_TYPE_CONCAT (uint8NDArray, uint8_array_value);
+	  else if (result_type == "uint16")
+	    DO_SINGLE_TYPE_CONCAT (uint16NDArray, uint16_array_value);
+	  else if (result_type == "uint32")
+	    DO_SINGLE_TYPE_CONCAT (uint32NDArray, uint32_array_value);
+	  else if (result_type == "uint64")
+	    DO_SINGLE_TYPE_CONCAT (uint64NDArray, uint64_array_value);
+	  else
+	    {
+	      // The lines below might seem crazy, since we take a copy
+	      // of the first argument, resize it to be empty and then resize
+	      // it to be full. This is done since it means that there is no
+	      // recopying of data, as would happen if we used a single resize.
+	      // It should be noted that resize operation is also significantly 
+	      // slower than the do_cat_op function, so it makes sense to have
+	      // an empty matrix and copy all data.
+	      //
+	      // We might also start with a empty octave_value using
+	      //   tmp = octave_value_typeinfo::lookup_type 
+	      //                                (args(1).type_name());
+	      // and then directly resize. However, for some types there might
+	      // be some additional setup needed, and so this should be avoided.
+
+	      octave_value tmp = args (1);
+	      tmp = tmp.resize (dim_vector (0,0)).resize (dv);
 
 	      if (error_state)
 		return retval;
 
-	      dim_vector dv_tmp = args (j).dims ();
-
-	      if (dim >= dv_len)
+	      int dv_len = dv.length ();
+	      Array<octave_idx_type> ra_idx (dv_len, 0);
+
+	      for (int j = 1; j < n_args; j++)
 		{
-		  if (j > 1)
-		    error ("%s: indexing error", fname.c_str ());
-		  break;
+		  // Can't fast return here to skip empty matrices as something
+		  // like cat(1,[],single([])) must return an empty matrix of
+		  // the right type.
+		  tmp = do_cat_op (tmp, args (j), ra_idx);
+
+		  if (error_state)
+		    return retval;
+
+		  dim_vector dv_tmp = args (j).dims ();
+
+		  if (dim >= dv_len)
+		    {
+		      if (j > 1)
+			error ("%s: indexing error", fname.c_str ());
+		      break;
+		    }
+		  else
+		    ra_idx (dim) += (dim < dv_tmp.length () ? 
+				     dv_tmp (dim) : 1);
 		}
-	      else
-		ra_idx (dim) += (dim < dv_tmp.length () ? 
-				 dv_tmp (dim) : 1);
+	      retval = tmp;
 	    }
 
-	  // Reshape, chopping trailing singleton dimensions
-	  dv.chop_trailing_singletons ();
-	  tmp = tmp.reshape (dv);
-
-	  retval = tmp;
+	  if (! error_state)
+	    {
+	      // Reshape, chopping trailing singleton dimensions
+	      dv.chop_trailing_singletons ();
+	      retval = retval.reshape (dv);
+	    }
 	}
       else
 	error ("%s: invalid dimension argument", fname.c_str ());
     }
   else
     print_usage ();
- 
+
   return retval;
 }
 
-
 DEFUN (horzcat, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} horzcat (@var{array1}, @var{array2}, @dots{}, @var{arrayN})\n\
--- a/src/pt-mat.h	Wed Sep 17 16:04:27 2008 -0400
+++ b/src/pt-mat.h	Wed Sep 17 17:31:24 2008 -0400
@@ -87,6 +87,12 @@
 extern void
 maybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p);
 
+extern std::string 
+get_concat_class (const std::string& c1, const std::string& c2);
+
+extern void
+maybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p);
+
 #endif
 
 /*