# HG changeset patch # User Jaroslav Hajek # Date 1271745723 -7200 # Node ID 3f973f6c841c44d9584b45dba8d6576b8477f580 # Parent eb55e736060e841dd1a251e50684ab6076e99ab3 improve sparse concatenation operator diff -r eb55e736060e -r 3f973f6c841c liboctave/Array.cc --- 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)) diff -r eb55e736060e -r 3f973f6c841c liboctave/ChangeLog --- 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 + + * Array.cc (Array::cat): Fast return for single array case. + * Sparse.cc (Sparse::cat): Ditto. + 2010-04-19 Jaroslav Hajek * Array.cc (Array::cat): Miscellaneous fixes. diff -r eb55e736060e -r 3f973f6c841c liboctave/Sparse.cc --- 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 retval (dv, total_nz); @@ -2443,8 +2449,7 @@ break; } default: - (*current_liboctave_error_handler) - ("cat: invalid dimension for sparse concatenation"); + assert (false); } return retval; diff -r eb55e736060e -r 3f973f6c841c src/ChangeLog --- 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 + + * pt-mat.cc (single_type_concat): New overloads. Make TYPE an explicit + template parameter. Try to forward some cases to Array::cat and + Sparse::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 * data.cc (single_type_concat, do_single_type_concat): Rewrite using diff -r eb55e736060e -r 3f973f6c841c src/pt-mat.cc --- 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 +template static void -single_type_concat (TYPE& result, +single_type_concat (Array& result, tm_const& tmp) { octave_idx_type r = 0, c = 0; @@ -761,14 +761,79 @@ } } +template +static void +single_type_concat (Array& 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, 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 (*q); + } + + if (! error_state) + result = Array::cat (1, ncols, array_list); + } + else + { + result = Array (dv); + single_type_concat (result, tmp); + } +} + +template +static void +single_type_concat (Sparse& 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, 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, 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 (*q); + } + + sparse_row_list[j++] = Sparse::cat (1, ncols, sparse_list); + } + + result = Sparse::cat (0, nrows, sparse_row_list); +} + template 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 (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 (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 (result, tmp); retval = octave_value (result, type); }