Mercurial > hg > octave-lojdl
changeset 10645:8645b7087859
abstract scalar index checking off Array<T> (prep for struct optimizations)
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Thu, 20 May 2010 15:10:34 +0200 |
parents | 45b72e631cb5 |
children | 6c50b56824aa |
files | liboctave/Array-util.cc liboctave/Array-util.h liboctave/Array.cc liboctave/Array.h liboctave/ChangeLog liboctave/dim-vector.h |
diffstat | 6 files changed, 124 insertions(+), 99 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/Array-util.cc +++ b/liboctave/Array-util.cc @@ -174,29 +174,60 @@ return retval; } -octave_idx_type +octave_idx_type +compute_index (octave_idx_type n, const dim_vector& dims) +{ + if (n < 0) + gripe_invalid_index (); + if (n >= dims.numel ()) + gripe_index_out_of_range (1, 1, n+1, dims.numel ()); + + return n; +} + +octave_idx_type +compute_index (octave_idx_type i, octave_idx_type j, const dim_vector& dims) +{ + if (i < 0 || j < 0) + gripe_invalid_index (); + if (i >= dims(0)) + gripe_index_out_of_range (2, 1, i+1, dims(0)); + if (j >= dims.numel (1)) + gripe_index_out_of_range (2, 2, j+1, dims.numel (1)); + + return j*dims(0) + i; +} + +octave_idx_type +compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k, + const dim_vector& dims) +{ + if (i < 0 || j < 0 || k < 0) + gripe_invalid_index (); + if (i >= dims(0)) + gripe_index_out_of_range (3, 1, i+1, dims(0)); + if (j >= dims(1)) + gripe_index_out_of_range (3, 2, j+1, dims(1)); + if (k >= dims.numel (2)) + gripe_index_out_of_range (3, 3, k+1, dims.numel (2)); + + return (k*dims(1) + j)*dims(0) + i; +} + +octave_idx_type compute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims) { - octave_idx_type retval = -1; - - int n = dims.length (); - - if (n > 0 && n == ra_idx.length ()) + int nd = ra_idx.length (); + const dim_vector dv = dims.redim (nd); + for (int d = 0; d < nd; d++) { - retval = ra_idx(--n); + if (ra_idx(d) < 0) + gripe_invalid_index (); + if (ra_idx(d) >= dv(d)) + gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d)); + } - while (--n >= 0) - { - retval *= dims(n); - - retval += ra_idx(n); - } - } - else - (*current_liboctave_error_handler) - ("ArrayN<T>::compute_index: invalid ra_idxing operation"); - - return retval; + return dv.compute_index (ra_idx.data ()); } Array<octave_idx_type>
--- a/liboctave/Array-util.h +++ b/liboctave/Array-util.h @@ -47,7 +47,20 @@ extern OCTAVE_API bool any_ones (const Array<octave_idx_type>& arr); -extern OCTAVE_API octave_idx_type compute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims); +// These four compute a linear index for given dimensions, throwing +// exceptions on invalid indices. +extern OCTAVE_API octave_idx_type +compute_index (octave_idx_type n, const dim_vector& dims); + +extern OCTAVE_API octave_idx_type +compute_index (octave_idx_type i, octave_idx_type j, const dim_vector& dims); + +extern OCTAVE_API octave_idx_type +compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k, + const dim_vector& dims); + +extern OCTAVE_API octave_idx_type +compute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims); extern OCTAVE_API Array<octave_idx_type> conv_to_int_array (const Array<idx_vector>& a);
--- a/liboctave/Array.cc +++ b/liboctave/Array.cc @@ -187,28 +187,30 @@ template <class T> octave_idx_type +Array<T>::compute_index (octave_idx_type i, octave_idx_type j) const +{ + return ::compute_index (i, j, dimensions); +} + +template <class T> +octave_idx_type +Array<T>::compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k) const +{ + return ::compute_index (i, j, k, dimensions); +} + +template <class T> +octave_idx_type Array<T>::compute_index (const Array<octave_idx_type>& ra_idx) const { - octave_idx_type retval = 0; - - int n = dimensions.length (), ni = ra_idx.length (); - - while (ni > n) - retval += ra_idx(--ni); - - while (ni > 0) - { - retval *= dimensions(--ni); - retval += ra_idx(ni); - } - - return retval; + return ::compute_index (ra_idx, dimensions); } template <class T> T& Array<T>::checkelem (octave_idx_type n) { + // Do checks directly to avoid recomputing slice_len. if (n < 0) gripe_invalid_index (); if (n >= slice_len) @@ -221,53 +223,28 @@ T& Array<T>::checkelem (octave_idx_type i, octave_idx_type j) { - if (i < 0 || j < 0) - gripe_invalid_index (); - if (i >= dim1 ()) - gripe_index_out_of_range (2, 1, i+1, dim1 ()); - if (j >= dimensions.numel (1)) - gripe_index_out_of_range (2, 2, j+1, dimensions.numel (1)); - - return elem (i, j); + return elem (compute_index (i, j)); } template <class T> T& Array<T>::checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k) { - if (i < 0 || j < 0 || k < 0) - gripe_invalid_index (); - if (i >= dim1 ()) - gripe_index_out_of_range (3, 1, i+1, dim1 ()); - if (j >= dim2 ()) - gripe_index_out_of_range (3, 2, j+1, dim2 ()); - if (k >= dimensions.numel (2)) - gripe_index_out_of_range (3, 3, k+1, dimensions.numel (2)); - - return elem (i, j, k); + return elem (compute_index (i, j, k)); } template <class T> T& Array<T>::checkelem (const Array<octave_idx_type>& ra_idx) { - int nd = ra_idx.length (); - const dim_vector dv = dimensions.redim (nd); - for (int d = 0; d < nd; d++) - { - if (ra_idx(d) < 0) - gripe_invalid_index (); - if (ra_idx(d) >= dv(d)) - gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d)); - } - - return elem (ra_idx); + return elem (compute_index (ra_idx)); } template <class T> typename Array<T>::crefT Array<T>::checkelem (octave_idx_type n) const { + // Do checks directly to avoid recomputing slice_len. if (n < 0) gripe_invalid_index (); if (n >= slice_len) @@ -280,47 +257,21 @@ typename Array<T>::crefT Array<T>::checkelem (octave_idx_type i, octave_idx_type j) const { - if (i < 0 || j < 0) - gripe_invalid_index (); - if (i >= dim1 ()) - gripe_index_out_of_range (2, 1, i+1, dim1 ()); - if (j >= dimensions.numel (1)) - gripe_index_out_of_range (2, 2, j+1, dimensions.numel (1)); - - return elem (i, j); + return elem (compute_index (i, j)); } template <class T> typename Array<T>::crefT Array<T>::checkelem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const { - if (i < 0 || j < 0 || k < 0) - gripe_invalid_index (); - if (i >= dim1 ()) - gripe_index_out_of_range (3, 1, i+1, dim1 ()); - if (j >= dim2 ()) - gripe_index_out_of_range (3, 2, j+1, dim2 ()); - if (k >= dimensions.numel (2)) - gripe_index_out_of_range (3, 3, k+1, dimensions.numel (2)); - - return elem (i, j, k); + return elem (compute_index (i, j, k)); } template <class T> typename Array<T>::crefT Array<T>::checkelem (const Array<octave_idx_type>& ra_idx) const { - int nd = ra_idx.length (); - const dim_vector dv = dimensions.redim (nd); - for (int d = 0; d < nd; d++) - { - if (ra_idx(d) < 0) - gripe_invalid_index (); - if (ra_idx(d) >= dv(d)) - gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d)); - } - - return elem (ra_idx); + return elem (compute_index (ra_idx)); } template <class T>
--- a/liboctave/Array.h +++ b/liboctave/Array.h @@ -336,6 +336,9 @@ octave_idx_type compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k) const; octave_idx_type compute_index (const Array<octave_idx_type>& ra_idx) const; + octave_idx_type compute_index_unchecked (const Array<octave_idx_type>& ra_idx) const + { return dimensions.compute_index (ra_idx.data (), ra_idx.length ()); } + // No checking, even for multiple references, ever. T& xelem (octave_idx_type n) { return slice_data [n]; } @@ -350,10 +353,10 @@ { return xelem (i, dim2()*k+j); } T& xelem (const Array<octave_idx_type>& ra_idx) - { return xelem (compute_index (ra_idx)); } + { return xelem (compute_index_unchecked (ra_idx)); } crefT xelem (const Array<octave_idx_type>& ra_idx) const - { return xelem (compute_index (ra_idx)); } + { return xelem (compute_index_unchecked (ra_idx)); } // FIXME -- would be nice to fix this so that we don't // unnecessarily force a copy, but that is not so easy, and I see no @@ -375,7 +378,7 @@ T& elem (octave_idx_type i, octave_idx_type j, octave_idx_type k) { return elem (i, dim2()*k+j); } T& elem (const Array<octave_idx_type>& ra_idx) - { return Array<T>::elem (compute_index (ra_idx)); } + { return Array<T>::elem (compute_index_unchecked (ra_idx)); } #if defined (BOUNDS_CHECKING) T& operator () (octave_idx_type n) { return checkelem (n); } @@ -401,7 +404,7 @@ crefT elem (octave_idx_type i, octave_idx_type j, octave_idx_type k) const { return xelem (i, j, k); } crefT elem (const Array<octave_idx_type>& ra_idx) const - { return Array<T>::xelem (compute_index (ra_idx)); } + { return Array<T>::xelem (compute_index_unchecked (ra_idx)); } #if defined (BOUNDS_CHECKING) crefT operator () (octave_idx_type n) const { return checkelem (n); }
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,19 @@ +2010-05-20 Jaroslav Hajek <highegg@gmail.com> + + * dim-vector.h (dim_vector::compute_index (const octave_idx_type *, + int)): New method overload. + (dim_vector::compute_index, dim_vector::cum_compute_index, + dim_vector::increment_index): Add missing const qualifiers. + + * Array-util.cc (compute_index (..., const dim_vector&)): Rewrite, + add new overloads. Move code from Array<T>::checkelem here. + * Array-util.h: Update decls. + * Array.h (Array<T>::compute_index): Forward to the above. + (Array<T>::compute_index_unchecked): New method. + (Array<T>::elem, Array<T>::xelem): Call it here. + + * Array.cc (Array<T>::checkelem): Use compute_index where suitable. + 2010-05-19 Jaroslav Hajek <highegg@gmail.com> * mx-inlines.cc (mx_inline_cumcount): Fix 2D version instantiation.
--- a/liboctave/dim-vector.h +++ b/liboctave/dim-vector.h @@ -612,7 +612,7 @@ // Compute a linear index from an index tuple. - octave_idx_type compute_index (const octave_idx_type *idx) + octave_idx_type compute_index (const octave_idx_type *idx) const { octave_idx_type k = 0; for (int i = length () - 1; i >= 0; i--) @@ -621,11 +621,22 @@ return k; } + // Ditto, but the tuple may be incomplete (nidx < length ()). + + octave_idx_type compute_index (const octave_idx_type *idx, int nidx) const + { + octave_idx_type k = 0; + for (int i = nidx - 1; i >= 0; i--) + k = k * rep[i] + idx[i]; + + return k; + } + // Increment a multi-dimensional index tuple, optionally starting // from an offset position and return the index of the last index // position that was changed, or length () if just cycled over. - int increment_index (octave_idx_type *idx, int start = 0) + int increment_index (octave_idx_type *idx, int start = 0) const { int i; for (i = start; i < length (); i++) @@ -655,7 +666,7 @@ // Compute a linear index from an index tuple. Dimensions are // required to be cumulative. - octave_idx_type cum_compute_index (const octave_idx_type *idx) + octave_idx_type cum_compute_index (const octave_idx_type *idx) const { octave_idx_type k = idx[0];