changeset 10535:3f973f6c841c

improve sparse concatenation operator
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 20 Apr 2010 08:42:03 +0200
parents eb55e736060e
children 74cb77f0a163
files liboctave/Array.cc liboctave/ChangeLog liboctave/Sparse.cc src/ChangeLog src/pt-mat.cc
diffstat 5 files changed, 95 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/Array.cc	Mon Apr 19 20:57:41 2010 -0400
+++ b/liboctave/Array.cc	Tue Apr 20 08:42:03 2010 +0200
@@ -2602,6 +2602,9 @@
     (*current_liboctave_error_handler)
       ("cat: invalid dimension");
 
+  if (n == 1)
+    return array_list[0];
+
   dim_vector dv;
   for (octave_idx_type i = 0; i < n; i++)
     if (! dv.concat (array_list[i].dims (), dim))
--- a/liboctave/ChangeLog	Mon Apr 19 20:57:41 2010 -0400
+++ b/liboctave/ChangeLog	Tue Apr 20 08:42:03 2010 +0200
@@ -1,3 +1,8 @@
+2010-04-19  Jaroslav Hajek  <highegg@gmail.com>
+
+	* Array.cc (Array<T>::cat): Fast return for single array case.
+	* Sparse.cc (Sparse<T>::cat): Ditto.
+
 2010-04-19  Jaroslav Hajek  <highegg@gmail.com>
 
 	* Array.cc (Array<T>::cat): Miscellaneous fixes.
--- a/liboctave/Sparse.cc	Mon Apr 19 20:57:41 2010 -0400
+++ b/liboctave/Sparse.cc	Tue Apr 20 08:42:03 2010 +0200
@@ -2384,6 +2384,9 @@
   octave_idx_type total_nz = 0;
   if (dim == 0 || dim == 1)
     {
+      if (n == 1)
+        return sparse_list[0];
+
       for (octave_idx_type i = 0; i < n; i++)
         {
           if (! dv.concat (sparse_list[i].dims (), dim))
@@ -2392,6 +2395,9 @@
           total_nz += sparse_list[i].nnz ();
         }
     }
+  else
+    (*current_liboctave_error_handler)
+      ("cat: invalid dimension for sparse concatenation");
 
   Sparse<T> retval (dv, total_nz);
 
@@ -2443,8 +2449,7 @@
         break;
       }
     default:
-      (*current_liboctave_error_handler)
-        ("cat: invalid dimension for sparse concatenation");
+      assert (false);
     }
 
   return retval;
--- a/src/ChangeLog	Mon Apr 19 20:57:41 2010 -0400
+++ b/src/ChangeLog	Tue Apr 20 08:42:03 2010 +0200
@@ -1,3 +1,11 @@
+2010-04-20  Jaroslav Hajek  <highegg@gmail.com>
+
+	* pt-mat.cc (single_type_concat): New overloads. Make TYPE an explicit
+	template parameter. Try to forward some cases to Array<T>::cat and
+	Sparse<T>::cat.
+	(do_single_type_concat, do_single_type_concat_no_mutate): Don't
+	allocate the array here, let single_type_concat do it.
+
 2010-04-19  Jaroslav Hajek  <highegg@gmail.com>
 
 	* data.cc (single_type_concat, do_single_type_concat): Rewrite using
--- a/src/pt-mat.cc	Mon Apr 19 20:57:41 2010 -0400
+++ b/src/pt-mat.cc	Tue Apr 20 08:42:03 2010 +0200
@@ -724,9 +724,9 @@
                      "concatenation of different character string types may have unintended consequences");
 }
 
-template<class TYPE>
+template<class TYPE, class T>
 static void 
-single_type_concat (TYPE& result,
+single_type_concat (Array<T>& result,
                     tm_const& tmp)
 {
   octave_idx_type r = 0, c = 0;
@@ -761,14 +761,79 @@
     }
 }
 
+template<class TYPE, class T>
+static void 
+single_type_concat (Array<T>& result,
+                    const dim_vector& dv,
+                    tm_const& tmp)
+{
+  if (tmp.length () == 1)
+    {
+      // If possible, forward the operation to liboctave.
+      // Single row.
+      tm_row_const& row = tmp.front ();
+      octave_idx_type ncols = row.length (), i = 0;
+      OCTAVE_LOCAL_BUFFER (Array<T>, array_list, ncols);
+
+      for (tm_row_const::iterator q = row.begin ();
+           q != row.end () && ! error_state;
+           q++)
+        {
+          octave_quit ();
+
+          array_list[i++] = octave_value_extract<TYPE> (*q);
+        }
+
+      if (! error_state)
+        result = Array<T>::cat (1, ncols, array_list);
+    }
+  else
+    {
+      result = Array<T> (dv);
+      single_type_concat<TYPE> (result, tmp);
+    }
+}
+
+template<class TYPE, class T>
+static void 
+single_type_concat (Sparse<T>& result,
+                    const dim_vector&,
+                    tm_const& tmp)
+{
+  // Sparse matrices require preallocation for efficient indexing; besides,
+  // only horizontal concatenation can be efficiently handled by indexing.
+  // So we just cat all rows through liboctave, then cat the final column.
+  octave_idx_type nrows = tmp.length (), j = 0;
+  OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_row_list, nrows);
+  for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
+    {
+      tm_row_const row = *p;
+      octave_idx_type ncols = row.length (), i = 0;
+      OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_list, ncols);
+
+      for (tm_row_const::iterator q = row.begin ();
+           q != row.end () && ! error_state;
+           q++)
+        {
+          octave_quit ();
+
+          sparse_list[i++] = octave_value_extract<TYPE> (*q);
+        }
+
+      sparse_row_list[j++] = Sparse<T>::cat (1, ncols, sparse_list);
+    }
+
+  result = Sparse<T>::cat (0, nrows, sparse_row_list);
+}
+
 template<class TYPE>
 static octave_value 
 do_single_type_concat (const dim_vector& dv,
                        tm_const& tmp)
 {
-  TYPE result (dv);
+  TYPE result;
 
-  single_type_concat (result, tmp);
+  single_type_concat<TYPE> (result, dv, tmp);
 
   return result;
 }
@@ -778,9 +843,9 @@
 do_single_type_concat_no_mutate (const dim_vector& dv,
                                  tm_const& tmp)
 {
-  TYPE result (dv);
+  TYPE result;
 
-  single_type_concat (result, tmp);
+  single_type_concat<TYPE> (result, dv, tmp);
 
   return new OV_TYPE (result);
 }
@@ -915,7 +980,7 @@
 
           charNDArray result (dv, Vstring_fill_char);
 
-          single_type_concat (result, tmp);
+          single_type_concat<charNDArray> (result, tmp);
 
           retval = octave_value (result, type);
         }