# HG changeset patch # User Jaroslav Hajek # Date 1261947413 -3600 # Node ID f349847c45414dc36f13b8496954f6293d351ba8 # Parent 691b4ba324250288402df8e7e1e65699834eb67a optimize cellfun (@subsref, args, {subs}, uniformoutput, true) case diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2009-12-27 Jaroslav Hajek + + * ov.cc (decode_subscripts): Move to utils.cc. + * utils.cc (decode_subscripts): New func. + * utils.h: Declare it. + * DLD-FUNCTIONS/cellfun.cc (Fcellfun): Optimize the + `cellfun (@subsref, args, {subs}, "uniformoutput", true)' case. + 2009-12-26 Jaroslav Hajek * gripes.cc (gripe_nonbraced_cs_list_assignment): New function. diff --git a/src/DLD-FUNCTIONS/cellfun.cc b/src/DLD-FUNCTIONS/cellfun.cc --- a/src/DLD-FUNCTIONS/cellfun.cc +++ b/src/DLD-FUNCTIONS/cellfun.cc @@ -380,6 +380,32 @@ else error ("not enough arguments for `isclass'"); } + else if (name == "subsref" && nargin == 5 && nargout == 1 + && args(2).numel () == 1 && args(2).is_cell () + && args(3).is_string () + && args(3).xtoupper ().string_value () == "uniformoutput" + && args(4).bool_value () && ! error_state) + { + // This optimizes the case of applying the same index expression to + // multiple values. We decode the subscript just once. uniformoutput must + // be requested as well. + + const Cell tmpc = args(2).cell_value (); + octave_value subs = tmpc(0); + + std::string type; + std::list idx; + decode_subscripts ("subsref", subs, type, idx); + + if (! error_state) + { + Cell result (f_args.dims ()); + for (octave_idx_type count = 0; count < k && ! error_state; count++) + result(count) = f_args.elem (count).subsref (type, idx); + + retval(0) = result; + } + } else { if (! valid_identifier (name)) diff --git a/src/ov.cc b/src/ov.cc --- a/src/ov.cc +++ b/src/ov.cc @@ -2700,77 +2700,6 @@ return retval; } -static void -decode_subscripts (const char* name, const octave_value& arg, - std::string& type_string, - std::list& idx) -{ - Octave_map m = arg.map_value (); - - if (! error_state - && m.nfields () == 2 && m.contains ("type") && m.contains ("subs")) - { - Cell& type = m.contents ("type"); - Cell& subs = m.contents ("subs"); - - type_string = std::string (type.length(), '\0'); - - for (int k = 0; k < type.length (); k++) - { - std::string item = type(k).string_value (); - - if (! error_state) - { - if (item == "{}") - type_string[k] = '{'; - else if (item == "()") - type_string[k] = '('; - else if (item == ".") - type_string[k] = '.'; - else - { - error("%s: invalid indexing type `%s'", name, item.c_str ()); - return; - } - } - else - { - error ("%s: expecting type(%d) to be a character string", - name, k+1); - return; - } - - octave_value_list idx_item; - - if (subs(k).is_string ()) - idx_item(0) = subs(k); - else if (subs(k).is_cell ()) - { - Cell subs_cell = subs(k).cell_value (); - - for (int n = 0; n < subs_cell.length (); n++) - { - if (subs_cell(n).is_string () - && subs_cell(n).string_value () == ":") - idx_item(n) = octave_value(octave_value::magic_colon_t); - else - idx_item(n) = subs_cell(n); - } - } - else - { - error ("%s: expecting subs(%d) to be a character string or cell array", - name, k+1); - return; - } - - idx.push_back (idx_item); - } - } - else - error ("%s: second argument must be a structure with fields `type' and `subs'", name); -} - DEFUN (subsref, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} subsref (@var{val}, @var{idx})\n\ diff --git a/src/utils.cc b/src/utils.cc --- a/src/utils.cc +++ b/src/utils.cc @@ -1045,6 +1045,77 @@ return retval; } +void +decode_subscripts (const char* name, const octave_value& arg, + std::string& type_string, + std::list& idx) +{ + Octave_map m = arg.map_value (); + + if (! error_state + && m.nfields () == 2 && m.contains ("type") && m.contains ("subs")) + { + Cell& type = m.contents ("type"); + Cell& subs = m.contents ("subs"); + + type_string = std::string (type.length(), '\0'); + + for (int k = 0; k < type.length (); k++) + { + std::string item = type(k).string_value (); + + if (! error_state) + { + if (item == "{}") + type_string[k] = '{'; + else if (item == "()") + type_string[k] = '('; + else if (item == ".") + type_string[k] = '.'; + else + { + error("%s: invalid indexing type `%s'", name, item.c_str ()); + return; + } + } + else + { + error ("%s: expecting type(%d) to be a character string", + name, k+1); + return; + } + + octave_value_list idx_item; + + if (subs(k).is_string ()) + idx_item(0) = subs(k); + else if (subs(k).is_cell ()) + { + Cell subs_cell = subs(k).cell_value (); + + for (int n = 0; n < subs_cell.length (); n++) + { + if (subs_cell(n).is_string () + && subs_cell(n).string_value () == ":") + idx_item(n) = octave_value(octave_value::magic_colon_t); + else + idx_item(n) = subs_cell(n); + } + } + else + { + error ("%s: expecting subs(%d) to be a character string or cell array", + name, k+1); + return; + } + + idx.push_back (idx_item); + } + } + else + error ("%s: second argument must be a structure with fields `type' and `subs'", name); +} + Matrix identity_matrix (octave_idx_type nr, octave_idx_type nc) { diff --git a/src/utils.h b/src/utils.h --- a/src/utils.h +++ b/src/utils.h @@ -28,6 +28,7 @@ #include #include +#include #include "dMatrix.h" #include "lo-utils.h" @@ -95,7 +96,10 @@ extern OCTINTERP_API octave_idx_type dims_to_numel (const dim_vector& dims, const octave_value_list& idx); - +extern OCTINTERP_API void +decode_subscripts (const char* name, const octave_value& arg, + std::string& type_string, + std::list& idx); extern OCTINTERP_API Matrix identity_matrix (octave_idx_type nr, octave_idx_type nc);