Mercurial > hg > octave-lojdl
changeset 9329:67fc970dad7d
improve indexed assignment using indexed numel
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 10 Jun 2009 11:31:58 +0200 |
parents | 0307f5e5568c |
children | e903c92d2f02 |
files | ChangeLog src/ChangeLog src/data.cc src/ov-base.cc src/ov-base.h src/ov-class.cc src/ov-class.h src/ov.cc src/ov.h src/pt-idx.cc |
diffstat | 10 files changed, 222 insertions(+), 184 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-06-11 Jaroslav Hajek <highegg@gmail.com> + + * example/@polynomial/numel.m: New method. + 2009-05-22 Benjamin Lindner <lindnerb@users.sourceforge.net> * mkoctfile.cc.in: mask MSVC specific linker flags for mex output
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2009-06-10 Jaroslav Hajek <highegg@gmail.com> + + * ov-base.cc (octave_base_value::numel (const octave_value_list&), + octave_base_value::size): New virtual methods. + * ov-base.h: Declare them. + * ov.h (octave_value::numel (const octave_value_list&)): New method. + (octave_value::size): Forward to octave_base_value. + * ov-class.cc (octave_class::numel (const octave_value_list&), + octave_base_value::size): New method overrides. + * ov-class.h: Declare them. + * pt-idx.cc (tree_index_expression::lvalue): Rewrite. + * data.cc (Fnumel): Allow indexed query. + 2009-06-10 John W. Eaton <jwe@octave.org> * pt-fcn-handle.cc (tree_anon_fcn_handle::dup): Don't convert to
--- a/src/data.cc +++ b/src/data.cc @@ -2334,18 +2334,14 @@ @end deftypefn") { octave_value retval; - - if (args.length () == 1) + octave_idx_type nargin = args.length (); + + if (nargin >= 1) { - int numel = args(0).numel (); + octave_idx_type numel = args(0).numel (args.slice (1, nargin-1)); if (! error_state) - { - if (numel < 0) - numel = 0; - retval = numel; - } } else print_usage ();
--- a/src/ov-base.cc +++ b/src/ov-base.cc @@ -76,6 +76,41 @@ return octave_value (); } +Matrix +octave_base_value::size (void) +{ + const dim_vector dv = dims (); + Matrix mdv (1, dv.length ()); + for (octave_idx_type i = 0; i < dv.length (); i++) + mdv(i) = dv(i); + return mdv; +} + +octave_idx_type +octave_base_value::numel (const octave_value_list& idx) +{ + octave_idx_type retval; + + octave_idx_type len = idx.length (); + + if (len == 0) + retval = numel (); + else + { + const dim_vector dv = dims ().redim (len); + retval = 1; + for (octave_idx_type i = 0; i < len; i++) + { + if (idx(i).is_magic_colon ()) + retval *= dv(i); + else + retval *= idx(i).numel (); + } + } + + return retval; +} + octave_value octave_base_value::subsref (const std::string&, const std::list<octave_value_list>&)
--- a/src/ov-base.h +++ b/src/ov-base.h @@ -151,6 +151,10 @@ virtual void maybe_economize (void) { } + virtual Matrix size (void); + + virtual octave_idx_type numel (const octave_value_list&); + virtual octave_value subsref (const std::string& type, const std::list<octave_value_list>& idx);
--- a/src/ov-class.cc +++ b/src/ov-class.cc @@ -29,6 +29,7 @@ #include "Array-util.h" #include "byte-swap.h" #include "oct-locbuf.h" +#include "lo-mappers.h" #include "Cell.h" #include "defun.h" @@ -275,6 +276,90 @@ return (fcn && fcn->name () == "builtin"); } +Matrix +octave_class::size (void) +{ + Matrix retval (1, 2, 1.0); + octave_value meth = symbol_table::find_method ("size", class_name ()); + + if (meth.is_defined ()) + { + count++; + octave_value_list args (1, octave_value (this)); + + octave_value_list lv = feval (meth.function_value (), args, 1); + if (lv.length () == 1 && lv(0).is_matrix_type () && lv(0).dims ().is_vector ()) + retval = lv(0).matrix_value (); + else + error ("@%s/size: invalid return value"); + } + + return retval; +} + +octave_idx_type +octave_class::numel (const octave_value_list& idx) +{ + octave_idx_type retval = -1; + const std::string cn = class_name (); + + octave_value meth = symbol_table::find_method ("numel", cn); + + if (meth.is_defined ()) + { + octave_value_list args (idx.length () + 1, octave_value ()); + + count++; + args(0) = octave_value (this); + + for (octave_idx_type i = 0; i < idx.length (); i++) + args(i+1) = idx(i); + + octave_value_list lv = feval (meth.function_value (), args, 1); + if (lv.length () == 1 && lv(0).is_scalar_type ()) + retval = lv(0).idx_type_value (true); + else + error ("@%s/numel: invalid return value", cn.c_str ()); + } + else + { + // If method is not found, calculate using size (). + const Matrix mdv = size (); + octave_idx_type nmdv = mdv.numel (); + dim_vector dv; dv.resize (std::max (nmdv, 2)); + for (octave_idx_type i = 0; i < nmdv && !error_state; i++) + { + if (mdv(i) == xround (mdv(i)) && xfinite (mdv(i)) && mdv(i) >= 0) + dv(i) = mdv(i); + else + error ("@%s/numel: expected nonnegative integers from @%s/size", + cn.c_str (), cn.c_str ()); + } + + if (! error_state) + { + octave_idx_type len = idx.length (); + if (len == 0) + retval = dv.numel (); + else + { + dv = dv.redim (len); + retval = 1; + for (octave_idx_type i = 0; i < len; i++) + { + if (idx(i).is_magic_colon ()) + retval *= dv(i); + else + retval *= idx(i).numel (); + } + } + } + + } + + return retval; +} + octave_value_list octave_class::subsref (const std::string& type, const std::list<octave_value_list>& idx,
--- a/src/ov-class.h +++ b/src/ov-class.h @@ -72,6 +72,10 @@ Cell dotref (const octave_value_list& idx); + Matrix size (void); + + octave_idx_type numel (const octave_value_list&); + octave_value subsref (const std::string& type, const std::list<octave_value_list>& idx) {
--- a/src/ov.cc +++ b/src/ov.cc @@ -1246,21 +1246,6 @@ return retval; } -Matrix -octave_value::size (void) const -{ - dim_vector dv = dims (); - - int n_dims = dv.length (); - - Matrix retval (1, n_dims); - - while (n_dims--) - retval(n_dims) = dv(n_dims); - - return retval; -} - bool octave_value::is_equal (const octave_value& test) const {
--- a/src/ov.h +++ b/src/ov.h @@ -354,6 +354,13 @@ octave_base_value *try_narrowing_conversion (void) { return rep->try_narrowing_conversion (); } + // Close to dims (), but can be overloaded for classes. + Matrix size (void) + { return rep->size (); } + + octave_idx_type numel (const octave_value_list& idx) + { return rep->numel (idx); } + octave_value single_subsref (const std::string& type, const octave_value_list& idx); @@ -424,8 +431,6 @@ octave_idx_type capacity (void) const { return rep->capacity (); } - Matrix size (void) const; - size_t byte_size (void) const { return rep->byte_size (); }
--- a/src/pt-idx.cc +++ b/src/pt-idx.cc @@ -409,6 +409,7 @@ octave_lvalue retval; std::list<octave_value_list> idx; + std::string tmp_type; int n = args.size (); @@ -420,16 +421,13 @@ if (! error_state) { - // I think it is OK to have a copy here. - const octave_value *tro = retval.object (); - octave_value first_retval_object; + octave_value tmp; if (tro) - first_retval_object = *tro; + tmp = *tro; - octave_value tmp = first_retval_object; octave_idx_type tmpi = 0; std::list<octave_value_list> tmpidx; @@ -437,45 +435,14 @@ { if (retval.numel () != 1) gripe_indexed_cs_list (); - - if (i > 0) + else if (tmpi < i) { - tree_argument_list *al = *p_args; - - if (al && al->has_magic_end ()) - { - // We have an expression like - // - // x{end}.a(end) - // - // and we are looking at the argument list that - // contains the second (or third, etc.) "end" token, - // so we must evaluate everything up to the point of - // that argument list so we pass the appropriate - // value to the built-in __end__ function. + tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true); + tmpidx.clear (); + } - if (tmp.is_defined ()) - { - if (tmpi < i) - { - tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true); - - tmpi = i; - tmpidx.clear (); - } - } - else - gripe_invalid_inquiry_subscript (); - - if (tmp.is_undefined ()) - gripe_invalid_inquiry_subscript (); - else if (tmp.is_cs_list ()) - gripe_indexed_cs_list (); - - if (error_state) - break; - } - } + if (error_state) + break; switch (type[i]) { @@ -483,8 +450,19 @@ { octave_value_list tidx = make_value_list (*p_args, *p_arg_nm, &tmp); + idx.push_back (tidx); - tmpidx.push_back (tidx); + + if (i < n - 1) + { + if (type[i+1] == '.') + { + tmpidx.push_back (tidx); + tmpi = i+1; + } + else + error ("() must be followed by . or close the index chain"); + } } break; @@ -493,60 +471,27 @@ octave_value_list tidx = make_value_list (*p_args, *p_arg_nm, &tmp); - if (! tidx.all_scalars ()) - { - octave_idx_type nel = 1; - - octave_idx_type nidx = tidx.length (); - - // Possible cs-list. - bool has_magic_colon = tidx.has_magic_colon (); - dim_vector dims; - - if (has_magic_colon) - { - if (tmp.is_defined ()) - { - if (tmpi < i) - { - tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true); - tmpi = i; - tmpidx.clear (); - } + if (tmp.is_undefined ()) + { + if (tidx.has_magic_colon ()) + gripe_invalid_inquiry_subscript (); + else + tmp = Cell (); + } + else if (tmp.is_zero_by_zero () + && (tmp.is_matrix_type () || tmp.is_string ())) + { + tmp = Cell (); + } - if (tmp.is_undefined ()) - gripe_invalid_inquiry_subscript (); - else if (tmp.is_cs_list ()) - gripe_indexed_cs_list (); - - dims = (nidx == 1) ? dim_vector (tmp.numel (), 1) : tmp.dims (); - } - else - gripe_invalid_inquiry_subscript (); - - if (error_state) - break; - } - - for (octave_idx_type j = 0; j < nidx; j++) - { - octave_value val = tidx(j); - - if (val.is_magic_colon ()) - nel *= dims (j); - else - nel *= val.numel (); - } - - retval.numel (nel); - } + retval.numel (tmp.numel (tidx)); if (error_state) break; idx.push_back (tidx); tmpidx.push_back (tidx); - + tmpi = i; } break; @@ -556,90 +501,49 @@ if (error_state) break; + bool autoconv = (tmp.is_zero_by_zero () + && (tmp.is_matrix_type () || tmp.is_string () + || tmp.is_cell ())); + if (i > 0 && type [i-1] == '(') { - // Possible cs-list. - - octave_value_list xidx = idx.back (); - - if (! xidx.all_scalars ()) - { - octave_idx_type nel = 1; - - octave_idx_type nidx = xidx.length (); - - // Possible cs-list. - bool has_magic_colon = xidx.has_magic_colon (); - dim_vector dims; + octave_value_list pidx = idx.back (); - if (has_magic_colon) - { - // Evaluate everything up to the point preceding the last paren. - if (tmp.is_defined ()) - { - if (tmpi < i-1) - { - tmpidx.pop_back (); - tmp = tmp.subsref (type.substr (tmpi, i-1 - tmpi), tmpidx, true); - tmpi = i - 1; - tmpidx.clear (); - tmpidx.push_back (xidx); - } - - if (tmp.is_undefined ()) - gripe_invalid_inquiry_subscript (); - else if (tmp.is_cs_list ()) - gripe_indexed_cs_list (); + if (tmp.is_undefined ()) + { + if (pidx.has_magic_colon ()) + gripe_invalid_inquiry_subscript (); + else + tmp = Octave_map (); + } + else if (autoconv) + tmp = Octave_map (); - dims = (nidx == 1) ? dim_vector (tmp.numel (), 1) : tmp.dims (); - } - else - gripe_invalid_inquiry_subscript (); - - if (error_state) - break; - } + retval.numel (tmp.numel (pidx)); - for (octave_idx_type j = 0; j < nidx; j++) - { - octave_value val = xidx(j); - - if (val.is_magic_colon ()) - nel *= dims (j); - else - nel *= val.numel (); - } - - retval.numel (nel); - } + tmpi = i-1; + tmpidx.push_back (tidx); } else { - // A plain struct component can also yield a list reference. - if (tmp.is_defined () && tmpi < i) - tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true); - - tmpi = i; - tmpidx.clear (); + if (tmp.is_undefined () || autoconv) + { + tmpi = i+1; + tmp = octave_value (); + } + else + { + retval.numel (tmp.numel (octave_value_list ())); - if (tmp.is_cs_list ()) - gripe_indexed_cs_list (); - else if (tmp.is_map ()) - retval.numel (tmp.numel ()); - else - tmp = Octave_map (); - - if (error_state) - break; - + tmpi = i; + tmpidx.push_back (tidx); + } } if (error_state) break; idx.push_back (tidx); - tmpidx.push_back (tidx); - } break; @@ -647,6 +551,9 @@ panic_impossible (); } + if (idx.back ().empty ()) + error ("invalid empty index list"); + if (error_state) break;