Mercurial > hg > octave-lyh
changeset 8580:188d38a553c7
further indexing optimization touches
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Fri, 23 Jan 2009 13:13:39 +0100 |
parents | 7e0f36dfefbe |
children | 6adcafc70c32 |
files | liboctave/Array.cc liboctave/ChangeLog src/ChangeLog src/oct-obj.cc src/oct-obj.h src/ov-cell.cc src/ov-struct.cc src/ov-usr-fcn.cc src/pt-arg-list.cc src/pt-assign.cc src/pt-idx.cc src/symtab.cc |
diffstat | 12 files changed, 129 insertions(+), 110 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/Array.cc +++ b/liboctave/Array.cc @@ -1216,13 +1216,18 @@ // Try to resize first if necessary. if (nx != n) { - // A simple optimization. Things like A(1:N) = x will skip fill on - // resizing, if A is 0x0. + // Optimize case A = []; A(1:n) = X with A empty. if (rows () == 0 && columns () == 0 && ndims () == 2 - && rhl == 1 && i.is_colon_equiv (nx)) - *this = Array<T> (dim_vector (1, nx)); - else - resize_fill (nx, rfv); + && i.is_colon_equiv (nx)) + { + if (rhl == 1) + *this = Array<T> (dim_vector (1, nx), rhs(0)); + else + *this = Array<T> (rhs, dim_vector (1, nx)); + return; + } + + resize_fill (nx, rfv); n = numel (); } @@ -1284,6 +1289,17 @@ // Resize if requested. if (rdv != dv) { + // Optimize case A = []; A(1:m, 1:n) = X + if (dv.all_zero () && i.is_colon_equiv (rdv(0)) + && j.is_colon_equiv (rdv(1))) + { + if (isfill) + *this = Array<T> (rdv, rhs(0)); + else + *this = Array<T> (rhs, rdv); + return; + } + resize (rdv, rfv); dv = dimensions; }
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,10 @@ +2009-01-23 Jaroslav Hajek <highegg@gmail.com> + + * Array.cc (Array<T>::assign (const idx_vector&, const Array<T>&)): + Optimize assignment to an empty array. + (Array<T>::assign (const idx_vector&, const idx_vector&, const Array<T>&)): + Optimize assignment to an empty array. + 2009-01-22 Jaroslav Hajek <highegg@gmail.com> * Array2.h (Array2<T>::index): Declare resize_ok as bool.
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -4,10 +4,22 @@ New functions. * gripes.h: Declare them. * pt-idx.cc: Remove definitions of the above funcs. - * ov-cell.cc (octave_cell::subsasgn): Remove dead branch. - * ov-struct.cc (octave_struct::subsasgn): Remove dead branch. + * ov-cell.cc (octave_cell::subsref): Declare constants as const. + (octave_cell::subsasgn): Remove dead branch, declare constants as const. + (octave_cell::list_value): Optimize. + * ov-struct.cc + (octave_struct::subsref): Declare constants as const. + (octave_struct::subsasgn): Remove dead branch, declare constants as const. * ov-cs-list.cc (octave_cs_list::octave_cs_list (const Cell&)): Optimize. + * oct-obj.cc (octave_value_list::octave_value_list (const + std::list<octave_value_list>&)): New constructor. + * oct-obj.h: Declare it. + * pt-arg-list.cc (convert_to_const_vector): Optimize. + * symtab.cc (symbol_table::fcn_info::fcn_info_rep::find): Use const + reference to avoid redundant copy. + * ov-usr-fcn.cc (octave_user_function::bind_automatic_vars): Optimize. + (octave_user_function::octave_all_va_args): Optimize. 2009-01-22 Jaroslav Hajek <highegg@gmail.com>
--- a/src/oct-obj.cc +++ b/src/oct-obj.cc @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2009 VZLU Prague This file is part of Octave. @@ -29,6 +30,36 @@ #include "oct-obj.h" #include "Cell.h" +octave_value_list::octave_value_list (const std::list<octave_value_list>& lst) +{ + octave_idx_type n = 0, nel = 0; + + // Determine number. + for (std::list<octave_value_list>::const_iterator p = lst.begin (); + p != lst.end (); p++) + { + n++; + nel += p->length (); + } + + // Optimize single-element case + if (n == 1) + data = lst.front ().data; + else if (nel > 0) + { + data.resize (nel); + octave_idx_type k = 0; + for (std::list<octave_value_list>::const_iterator p = lst.begin (); + p != lst.end (); p++) + { + data.assign (idx_vector (k, k + p->length ()), p->data); + k += p->length (); + } + assert (k == nel); + } + +} + octave_allocator octave_value_list::allocator (sizeof (octave_value_list));
--- a/src/oct-obj.h +++ b/src/oct-obj.h @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2009 VZLU Prague This file is part of Octave. @@ -58,6 +59,9 @@ octave_value_list (const octave_value_list& obj) : data (obj.data), names (obj.names) { } + // Concatenation constructor. + octave_value_list (const std::list<octave_value_list>&); + ~octave_value_list (void) { } void *operator new (size_t size)
--- a/src/ov-cell.cc +++ b/src/ov-cell.cc @@ -136,7 +136,7 @@ if (! error_state) { - Cell tcell = tmp.cell_value (); + const Cell tcell = tmp.cell_value (); if (tcell.length () == 1) retval = tcell(0,0); @@ -231,12 +231,16 @@ if (tmpc.numel () == 1) { octave_value tmp = tmpc(0); + tmpc = Cell (); if (! tmp.is_defined () || tmp.is_zero_by_zero ()) - tmp = octave_value::empty_conv (type.substr (1), rhs); + { + tmp = octave_value::empty_conv (type.substr (1), rhs); + tmp.make_unique (); // probably a no-op. + } else - // optimization: ignore the copy still stored inside our array and in tmpc. - tmp.make_unique (2); + // optimization: ignore the copy still stored inside our array. + tmp.make_unique (1); if (! error_state) t_rhs = tmp.subsasgn (next_type, next_idx, rhs); @@ -356,29 +360,7 @@ octave_value_list octave_cell::list_value (void) const { - octave_value_list retval; - - octave_idx_type nr = rows (); - octave_idx_type nc = columns (); - - if (nr == 1 && nc > 0) - { - retval.resize (nc); - - for (octave_idx_type i = 0; i < nc; i++) - retval(i) = matrix(0,i); - } - else if (nc == 1 && nr > 0) - { - retval.resize (nr); - - for (octave_idx_type i = 0; i < nr; i++) - retval(i) = matrix(i,0); - } - else - error ("invalid conversion from cell array to list"); - - return retval; + return octave_value_list (matrix); } string_vector
--- a/src/ov-struct.cc +++ b/src/ov-struct.cc @@ -117,11 +117,11 @@ std::list<octave_value_list>::const_iterator p = idx.begin (); octave_value_list key_idx = *++p; - Cell tmp = dotref (key_idx); + const Cell tmp = dotref (key_idx); if (! error_state) { - Cell t = tmp.index (idx.front ()); + const Cell t = tmp.index (idx.front ()); retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true); @@ -140,7 +140,7 @@ { if (map.numel() > 0) { - Cell t = dotref (idx.front ()); + const Cell t = dotref (idx.front ()); retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true); } @@ -183,11 +183,11 @@ std::list<octave_value_list>::const_iterator p = idx.begin (); octave_value_list key_idx = *++p; - Cell tmp = dotref (key_idx, auto_add); + const Cell tmp = dotref (key_idx, auto_add); if (! error_state) { - Cell t = tmp.index (idx.front (), auto_add); + const Cell t = tmp.index (idx.front (), auto_add); retval = (t.length () == 1) ? t(0) : octave_value (t, true); @@ -206,7 +206,7 @@ { if (map.numel() > 0) { - Cell t = dotref (idx.front (), auto_add); + const Cell t = dotref (idx.front (), auto_add); retval = (t.length () == 1) ? t(0) : octave_value (t, true); } @@ -296,7 +296,6 @@ // cast map to const reference to avoid forced key insertion. Cell tmpc = cmap.contents (key).index (idx.front (), true); - tmpc.make_unique (); // FIXME: better code reuse? cf. octave_cell::subsasgn and the case below. if (! error_state) @@ -304,6 +303,7 @@ if (tmpc.numel () == 1) { octave_value tmp = tmpc(0); + tmpc = Cell (); if (! tmp.is_defined () || tmp.is_zero_by_zero ()) { @@ -311,8 +311,8 @@ tmp.make_unique (); // probably a no-op. } else - // optimization: ignore the copy still stored inside our map and in tmpc. - tmp.make_unique (2); + // optimization: ignore the copy still stored inside our map. + tmp.make_unique (1); if (! error_state) t_rhs = tmp.subsasgn (next_type, next_idx, rhs); @@ -340,10 +340,8 @@ std::string next_type = type.substr (1); - Cell tmpc1 = octave_value (); - Cell& tmpc = (map.contains (key)) ? map.contents (key) : tmpc1; - - tmpc.make_unique (); + Cell tmpc (1, 1); + if (map.contains (key)) tmpc = cmap.contents (key); // FIXME: better code reuse? if (! error_state) @@ -351,10 +349,11 @@ if (tmpc.numel () == 1) { octave_value tmp = tmpc(0); + tmpc = Cell (); if (! tmp.is_defined () || tmp.is_zero_by_zero ()) { - tmp = octave_value::empty_conv (type.substr (1), rhs); + tmp = octave_value::empty_conv (next_type, rhs); tmp.make_unique (); // probably a no-op. } else
--- a/src/ov-usr-fcn.cc +++ b/src/ov-usr-fcn.cc @@ -263,16 +263,10 @@ { octave_value_list retval; - int n = num_args_passed - num_named_args; + octave_idx_type n = num_args_passed - num_named_args; if (n > 0) - { - retval.resize (n); - - int k = 0; - for (int i = num_named_args; i < num_args_passed; i++) - retval(k++) = args_passed(i); - } + retval = args_passed.slice (num_named_args, n); return retval; } @@ -539,16 +533,7 @@ symbol_table::mark_hidden (".nargout."); if (takes_varargs ()) - { - int n = va_args.length (); - - Cell varargin (1, n); - - for (int i = 0; i < n; i++) - varargin(0,i) = va_args(i); - - symbol_table::varref ("varargin") = varargin; - } + symbol_table::varref ("varargin") = va_args.cell_value (); } DEFUN (nargin, args, ,
--- a/src/pt-arg-list.cc +++ b/src/pt-arg-list.cc @@ -174,12 +174,9 @@ int len = length (); - octave_value_list args; - int args_len = len; - args.resize (args_len); + std::list<octave_value_list> args; iterator p = begin (); - int j = 0; for (int k = 0; k < len; k++) { if (stash_object) @@ -200,33 +197,24 @@ if (error_state) { ::error ("evaluating argument list element number %d", k+1); - args = octave_value_list (); + args.clear (); break; } else { if (tmp.is_cs_list ()) - { - octave_value_list tl = tmp.list_value (); - int n = tl.length (); - args_len += n - 1; - args.resize (args_len); - for (int i = 0; i < n; i++) - args(j++) = tl(i); - } + args.push_back (tmp.list_value ()); else if (tmp.is_defined ()) - args(j++) = tmp; + args.push_back (tmp); } } else { - args(j++) = octave_value (); + args.push_back (octave_value ()); break; } } - args.resize (j); - if (stash_object) unwind_protect::run_frame ("convert_to_const_vector");
--- a/src/pt-assign.cc +++ b/src/pt-assign.cc @@ -217,7 +217,7 @@ { if (rhs_val.is_cs_list ()) { - octave_value_list lst = rhs_val.list_value (); + const octave_value_list lst = rhs_val.list_value (); if (! lst.empty ()) rhs_val = lst(0); @@ -315,7 +315,7 @@ { octave_value retval; - octave_value_list tmp = rvalue (1); + const octave_value_list tmp = rvalue (1); if (! tmp.empty ()) retval = tmp(0); @@ -359,7 +359,10 @@ p++) n_out += p->numel (); - octave_value_list rhs_val = rhs->rvalue (n_out); + // The following trick is used to keep rhs_val constant. + const octave_value_list rhs_val1 = rhs->rvalue (n_out); + const octave_value_list rhs_val = (rhs_val1.length () == 1 && rhs_val1(0).is_cs_list () + ? rhs_val1(0).list_value () : rhs_val1); if (error_state) return retval; @@ -378,18 +381,9 @@ octave_idx_type n = rhs_val.length (); - if (n == 1) - { - octave_value tmp = rhs_val(0); - - if (tmp.is_cs_list ()) - { - rhs_val = tmp.list_value (); - n = rhs_val.length (); - } - } - - retval.resize (n, octave_value ()); + // To avoid copying per elements and possible optimizations, we + // postpone joining the final values. + std::list<octave_value_list> retval_list; tree_argument_list::iterator q = lhs->begin (); @@ -409,17 +403,14 @@ { if (etype == octave_value::op_asn_eq) { - octave_value_list ovl (nel, octave_value ()); - - for (octave_idx_type j = 0; j < nel; j++) - ovl(j) = rhs_val(k+j); + // This won't do a copy. + octave_value_list ovl = rhs_val.slice (k, nel); ult.assign (etype, octave_value (ovl, true)); if (! error_state) { - for (octave_idx_type j = 0; j < nel; j++) - retval(k+j) = rhs_val(k+j); + retval_list.push_back (ovl); k += nel; } @@ -443,9 +434,9 @@ if (! error_state) { if (etype == octave_value::op_asn_eq) - retval(k) = rhs_val(k); + retval_list.push_back (rhs_val(k)); else - retval(k) = ult.value (); + retval_list.push_back (ult.value ()); k++; } @@ -476,6 +467,9 @@ break; } + + // Concatenate return values. + retval = retval_list; } }
--- a/src/pt-idx.cc +++ b/src/pt-idx.cc @@ -331,7 +331,7 @@ // that argument list so we can pass the appropriate // value to the built-in __end__ function. - octave_value_list tmp_list + const octave_value_list tmp_list = tmp.subsref (type.substr (tmpi, i - tmpi), idx, nargout); tmp = tmp_list(0); @@ -390,7 +390,7 @@ { octave_value retval; - octave_value_list tmp = rvalue (1); + const octave_value_list tmp = rvalue (1); if (! tmp.empty ()) retval = tmp(0);