Mercurial > hg > octave-shane
changeset 9986:672e1b49e01e
optimize indexing of ranges by single subscripts
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Tue, 15 Dec 2009 10:04:34 +0100 |
parents | 43a29eeda994 |
children | bb30843c4929 |
files | liboctave/ChangeLog liboctave/Range.cc liboctave/Range.h src/ChangeLog src/ov-range.cc |
diffstat | 5 files changed, 96 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,9 @@ +2009-12-15 Jaroslav Hajek <highegg@gmail.com> + + * Range.cc (Range::elem, Range::checkelem, Range::index): + New methods. + * Range.h: Declare them. + 2009-12-15 Jaroslav Hajek <highegg@gmail.com> * idx-vector.h (idx_vector::loop, idx_vector::bloop): Fix behavior for
--- a/liboctave/Range.cc +++ b/liboctave/Range.cc @@ -81,6 +81,57 @@ return cache; } +double +Range::checkelem (octave_idx_type i) const +{ + if (i < 0 || i >= rng_nelem) + (*current_liboctave_error_handler) ("Range::elem (%d): range error", i); + + return rng_base + rng_inc * i; +} + +struct _rangeidx_helper +{ + double *array, base, inc; + _rangeidx_helper (double *a, double b, double i) + : array (a), base (b), inc (i) { } + void operator () (octave_idx_type i) + { *array++ = base + i * inc; } +}; + +Array<double> +Range::index (const idx_vector& i) const +{ + Array<double> retval; + + octave_idx_type n = rng_nelem; + + if (i.is_colon ()) + { + retval = matrix_value ().reshape (dim_vector (rng_nelem, 1)); + } + else if (i.extent (n) != n) + { + (*current_liboctave_error_handler) + ("A(I): Index exceeds matrix dimension."); + } + else + { + dim_vector rd = i.orig_dimensions (); + octave_idx_type il = i.length (n); + + // taken from Array.cc. + + if (n != 1 && rd.is_vector ()) + rd = dim_vector (1, il); + + retval.clear (rd); + + i.loop (n, _rangeidx_helper (retval.fortran_vec (), rng_base, rng_inc)); + } + + return retval; +} // NOTE: max and min only return useful values if nelem > 0.
--- a/liboctave/Range.h +++ b/liboctave/Range.h @@ -77,6 +77,21 @@ sortmode is_sorted (sortmode mode = ASCENDING) const; + // Support for single-index subscripting, without generating matrix cache. + + double checkelem (octave_idx_type i) const; + + double elem (octave_idx_type i) const + { +#if defined (BOUNDS_CHECKING) + return checkelem (i); +#else + return rng_base + rng_inc * i; +#endif + } + + Array<double> index (const idx_vector& i) const; + void set_base (double b) { if (rng_base != b)
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2009-12-14 Jaroslav Hajek <highegg@gmail.com> + + * ov-range.cc (octave_range::do_index_op): Defer single subscript to + new Range methods. + 2009-12-14 Jaroslav Hajek <highegg@gmail.com> * symtab.cc (symbol_table::cleanup): New static method.
--- a/src/ov-range.cc +++ b/src/ov-range.cc @@ -118,19 +118,28 @@ octave_value octave_range::do_index_op (const octave_value_list& idx, bool resize_ok) { - // FIXME -- this doesn't solve the problem of - // - // a = 1:5; a(1, 1, 1) - // - // and similar constructions. Hmm... + if (idx.length () == 1 && ! resize_ok) + { + octave_value retval; - // FIXME -- using this constructor avoids possibly narrowing - // the range to a scalar value. Need a better solution to this - // problem. + // The range can handle a single subscript. + idx_vector i = idx(0).index_vector (); + if (! error_state) + { + if (i.is_scalar () && i(0) < range.nelem ()) + retval = range.elem (i(0)); + else + retval = range.index (i); + } - octave_value tmp (new octave_matrix (range.matrix_value ())); + return retval; + } + else + { + octave_value tmp (new octave_matrix (range.matrix_value ())); - return tmp.do_index_op (idx, resize_ok); + return tmp.do_index_op (idx, resize_ok); + } } double