Mercurial > hg > octave-nkf
changeset 4530:e8d87fefd144
[project @ 2003-10-07 04:02:04 by jwe]
author | jwe |
---|---|
date | Tue, 07 Oct 2003 04:02:04 +0000 |
parents | 78954aeaf321 |
children | b570d7825fb9 |
files | liboctave/Array.cc liboctave/Array.h liboctave/ArrayN-inline.h liboctave/ChangeLog |
diffstat | 4 files changed, 374 insertions(+), 75 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/Array.cc +++ b/liboctave/Array.cc @@ -805,7 +805,7 @@ else new_dims(i) = dimensions(i); } - + if (ndims != new_dims.length ()) dimensions = new_dims; } @@ -1292,7 +1292,7 @@ if (num_to_delete > 0) { - int temp = num_ones(lhs_dims); + int temp = num_ones (lhs_dims); if (non_col_dim == 1) temp--; @@ -1344,7 +1344,7 @@ } T *new_data = new T [num_new_elem]; - + Array<int> result_idx (lhs_dims.length (), 0); dim_vector lhs_inc; @@ -1404,10 +1404,10 @@ } } } - else if (num_ones(idx_is_colon) < n_idx) + else if (num_ones (idx_is_colon) < n_idx) { (*current_liboctave_error_handler) - ("A null assignment can have only one non-colon index."); + ("A null assignment can have only one non-colon index"); } } @@ -1458,11 +1458,7 @@ break; default: - { - Array<idx_vector> tmp (1, idx_arg); - - retval = index (tmp, resize_ok, rfv); - } + retval = indexN (idx_arg, resize_ok, rfv); break; } @@ -1630,6 +1626,184 @@ template <class T> Array<T> +Array<T>::indexN (idx_vector& ra_idx, int resize_ok, const T& rfv) const +{ + Array<T> retval; + + int n_dims = dims ().length (); + + int orig_len = number_of_elements (dims ()); + + Array<int> idx_orig_dimsXXX = ra_idx.orig_dimensions (); + + dim_vector idx_orig_dims; + + idx_orig_dims.resize(idx_orig_dimsXXX.length()); + + for (int i = 0; i < idx_orig_dimsXXX.length(); i++) + idx_orig_dims(i) = idx_orig_dimsXXX(i); + + + if (ra_idx.is_colon ()) + { + dim_vector idx(orig_len); + + retval = Array<T> (*this, idx); + + } + else if (length () == 1) + { + // Only one element in array. + + Array<T> tmp = Array<T>::index (ra_idx, resize_ok); + + if (tmp.length () != 0) + retval = Array<T> (tmp, idx_orig_dims); + else + { + dim_vector d; + retval = Array<T> (tmp, d); + } + } + else if (vector_equivalent (dims ())) + { + // We're getting elements from a vector equivalent i.e. (1x4x1). + + Array<T> tmp = Array<T>::index (ra_idx, resize_ok); + + int len = tmp.length (); + + if (len == 0) + { + if (any_zero_len (idx_orig_dims)) + retval = Array<T> (idx_orig_dims); + else + { + dim_vector new_dims; + new_dims.resize (n_dims); + + for (int i = 0; i < n_dims; i++) + { + if ((dims ())(i) == 1) + new_dims(i) = 1; + } + + retval = Array<T> (new_dims); + } + } + else + { + if (vector_equivalent(idx_orig_dims)) + { + // Array<int> index (n_dims, len); + dim_vector new_dims; + + new_dims.resize (n_dims); + + for (int i = 0; i < n_dims; i++) + { + if ((dims ())(i) == 1) + new_dims(i) = 1; + } + + retval = Array<T> (tmp, new_dims); + } + else + retval = Array<T> (tmp, idx_orig_dims); + + (*current_liboctave_error_handler) + ("I do not know what to do here yet!"); + } + } + else if (liboctave_wfi_flag || + (ra_idx.one_zero_only () && equal_arrays (idx_orig_dims, dims ()))) + { + // This code is only for indexing nd-arrays. The vector + // cases are handled above. + + ra_idx.freeze (orig_len, "nd-array", resize_ok); + + if (ra_idx) + { + dim_vector result_dims (idx_orig_dims); + + if (ra_idx.one_zero_only ()) + { + for (int i = 0; i < result_dims.length(); i++) + { + if (i == 0) + result_dims(i) = ra_idx.ones_count (); + else if (result_dims(0) > 0) + result_dims(i) = 1; + else + result_dims(i) = 0; + } + } + + retval.resize (result_dims); + + int n = number_of_elements (result_dims); + + int r_dims = result_dims.length (); + + Array<int> index (r_dims, 0); + + int k = 0; + + for (int i = 0; i < n; i++) + { + int ii = ra_idx.elem (k++); + + if (ii >= orig_len) + retval.elem (index) = rfv; + else + { + Array<int> temp = get_ra_idx (ii, dims ()); + + retval.elem (index) = elem (temp); + } + if (i != n - 1) + increment_index (index, result_dims); + } + } + } + else if (ra_idx.capacity () == 1) + { + // i.e. A(8) for A(3x3x3) + + ra_idx.freeze (orig_len, "nd-array", resize_ok); + + if (ra_idx) + { + int r_idx = ra_idx(0); + + Array<int> idx = get_ra_idx (r_idx, dims ()); + + dim_vector new_dims (1); + new_dims(0)=1; + + // This shouldn't be needed. + + Array<int> e (idx.length ()); + + for (int i = 0; i < idx.length();i++) + e(i) = idx(i); + + // Should be able to call elem (idx). + + retval = Array<T> (new_dims, elem (e)); + } + } + else + (*current_liboctave_error_handler) + ("single index only valid for row or column vector. ra_idx.cap () = &d", + ra_idx.capacity ()); + + return retval; +} + +template <class T> +Array<T> Array<T>::index (idx_vector& idx_i, idx_vector& idx_j, int resize_ok, const T& rfv) const { @@ -1681,76 +1855,75 @@ Array<T> Array<T>::index (Array<idx_vector>& ra_idx, int resize_ok, const T& rfv) const { + // This function handles all calls with more than one idx. + // For (3x3x3), the call can be A(2,5), A(2,:,:), A(3,2,3) etc. + Array<T> retval; - int n_idx = ra_idx.length (); - int n_dims = dimensions.length (); - if (n_idx == n_dims) + if (n_dims < ra_idx.length ()) { - dim_vector frozen_lengths = freeze (ra_idx, dimensions, resize_ok); - - if (frozen_lengths.length () == n_dims) + (*current_liboctave_error_handler) + ("index exceeds N-d array dimensions"); + + return retval; + } + + dim_vector frozen_lengths = short_freeze (ra_idx, dimensions, resize_ok); + + if (frozen_lengths.length () <= n_dims) + { + if (all_ok (ra_idx)) { - if (all_ok (ra_idx)) + if (any_orig_empty (ra_idx)) + { + retval.resize (frozen_lengths); + } + else if (any_zero_len (frozen_lengths)) { - if (any_orig_empty (ra_idx)) - { - retval.resize (frozen_lengths); - } - else if (any_zero_len (frozen_lengths)) - { - dim_vector new_size = get_zero_len_size (frozen_lengths, - dimensions); - - retval.resize (new_size); - } - else if (all_colon_equiv (ra_idx, frozen_lengths)) + dim_vector new_size = + get_zero_len_size (frozen_lengths, dimensions); + + retval.resize (new_size); + } + else if (all_colon_equiv (ra_idx, dimensions) + && frozen_lengths.length () == n_dims) + { + retval = *this; + } + else + { + retval.resize (frozen_lengths); + + int n = number_of_elements (frozen_lengths); + + Array<int> result_idx (ra_idx.length (), 0); + + dim_vector this_dims = dims (); + + for (int i = 0; i < n; i++) { - retval = *this; - } - else - { - (*current_liboctave_error_handler) ("not implemented"); -#if 0 - retval.resize (frozen_lengths); - - int n = Array<T>::get_size (frozen_lengths); - - dim_vector result_idx (n_dims, 0); - - for (int i = 0; i < n; i++) - { - dim_vector elt_idx = get_elt_idx (result_idx); - - if (elt_idx > orig_len) - retval.elem (result_idx) = rfv; - else - retval.elem (result_idx) = elem (elt_idx); - - increment_index (result_idx, frozen_lengths); - } -#endif + Array<int> elt_idx = get_elt_idx (ra_idx, result_idx); + + int numelem_result = + get_scalar_idx (result_idx, frozen_lengths); + + int numelem_elt = get_scalar_idx (elt_idx, this_dims); + + if (numelem_result > length () || numelem_result < 0 + || numelem_elt > length () || numelem_elt < 0) + (*current_liboctave_error_handler) + ("attempt to grow array along ambiguous dimension"); + else + retval.Array<T>::checkelem (numelem_result) = Array<T>::checkelem (numelem_elt); + + increment_index (result_idx, frozen_lengths); + } } - // idx_vector::freeze() printed an error message for us. } } - else if (n_idx == 1) - { - if (ra_idx(0).is_colon ()) - { - // Fast magic colon processing. - - int result_nr = Array<int>::get_size (dimensions); - int result_nc = 1; - - retval = Array<T> (*this, dim_vector (result_nr, result_nc)); - } - else - (*current_liboctave_error_handler) ("not implemented"); - } else (*current_liboctave_error_handler) ("invalid number of dimensions for N-dimensional array index"); @@ -2252,7 +2425,7 @@ { if (n_idx == 0) (*current_liboctave_error_handler) - ("number of indices is zero."); + ("number of indices is zero"); else if (n_idx < lhs_dims.length ()) { @@ -2261,7 +2434,7 @@ if (any_ones (idx_is_colon)|| any_ones (idx_is_colon_equiv)) { (*current_liboctave_error_handler) - ("number of indices is less than number of dimensions, one or more indices are colons."); + ("number of indices is less than number of dimensions, one or more indices are colons"); } else { @@ -2310,7 +2483,7 @@ if (numelem > lhs.length () || numelem < 0) (*current_liboctave_error_handler) - ("attempt to grow array along ambiguous dimension."); + ("attempt to grow array along ambiguous dimension"); else lhs.Array<LT>::checkelem (numelem) = scalar; } @@ -2354,14 +2527,15 @@ // Subtracting number of dimensions of length 1 will catch // cases where: A(2,1,2)=3 A(:,1,:)=[2,3;4,5] - if (rhs_dims.length () != num_ones(idx_is_colon_equiv) - num_ones(lhs_dims)) + if (rhs_dims.length () + != num_ones (idx_is_colon_equiv) - num_ones (lhs_dims)) { (*current_liboctave_error_handler) - ("dimensions do not match in matrix assignment."); + ("dimensions do not match in matrix assignment"); } else { - bool dim_ok(true); + bool dim_ok = true; int jj = 0; @@ -2385,7 +2559,7 @@ if (! dim_ok) (*current_liboctave_error_handler) - ("subscripted assignment dimension mismatch."); + ("subscripted assignment dimension mismatch"); else { dim_vector new_dims;
--- a/liboctave/Array.h +++ b/liboctave/Array.h @@ -495,6 +495,9 @@ Array<T> index2 (idx_vector& i, int resize_ok = 0, const T& rfv = resize_fill_value (T ())) const; + Array<T> indexN (idx_vector& i, int resize_ok = 0, + const T& rfv = resize_fill_value (T ())) const; + Array<T> index (idx_vector& i, idx_vector& j, int resize_ok = 0, const T& rfv = resize_fill_value (T ())) const;
--- a/liboctave/ArrayN-inline.h +++ b/liboctave/ArrayN-inline.h @@ -396,6 +396,117 @@ return retval; } +static inline int +number_of_elements (const dim_vector ra_idx) +{ + int retval = 1; + + int n = ra_idx.length (); + + if (n == 0) + retval = 0; + + for (int i = 0; i < n; i++) + retval *= ra_idx(i); + + return retval; +} + +static inline Array<int> +get_ra_idx (int idx, const dim_vector& dims) +{ + Array<int> retval; + + int n_dims = dims.length (); + + retval.resize (n_dims); + + for (int i = 0; i < n_dims; i++) + retval(i) = 0; + + assert (idx > 0 || idx < number_of_elements (dims)); + + for (int i = 0; i < idx; i++) + increment_index (retval, dims); + + // XXX FIXME XXX -- the solution using increment_index is not + // efficient. + +#if 0 + int var = 1; + for (int i = 0; i < n_dims; i++) + { + std::cout << "idx: " << idx << ", var: " << var << ", dims(" << i << "): " << dims(i) <<"\n"; + retval(i) = ((int)floor(((idx) / (double)var))) % dims(i); + idx -= var * retval(i); + var = dims(i); + } +#endif + + return retval; +} + +static inline dim_vector +short_freeze (Array<idx_vector>& ra_idx, const dim_vector& dimensions, + int resize_ok) +{ + dim_vector retval; + + int n = ra_idx.length (); + + int n_dims = dimensions.length (); + + if (n == n_dims) + { + retval = freeze (ra_idx, dimensions, resize_ok); + } + else if (n < n_dims) + { + retval.resize (n); + + for (int i = 0; i < n - 1; i++) + retval(i) = ra_idx(i).freeze (dimensions(i), "dimension", resize_ok); + + int size_left = 1; + + for (int i = n - 1; i < n_dims; i++) + size_left *= dimensions(i); + + if (ra_idx(n-1).is_colon()) + { + retval(n-1) = size_left; + } + else + { + int last_ra_idx = ra_idx(n-1)(0); + + if (last_ra_idx < dimensions(n - 1)) + { + retval(n - 1) = ra_idx(n - 1).freeze (dimensions(n-1), + "dimension", resize_ok); + } + else + { + if (size_left <= last_ra_idx) + { + // Make it larger than it should be to get an error + // later. + + retval.resize(n_dims + 1); + + (*current_liboctave_error_handler) + ("index exceeds N-d array dimensions"); + } + else + { + retval(n-1) = 1; + } + } + } + } + + return retval; +} #endif /*
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,14 @@ +2003-10-06 Petter Risholm <risholm@stud.ntnu.no> + + * Array.cc (ArrayN<T>::indexN): New definition. + * Array.h (Array<T>::indexN): Provide decl. + * Array.cc (ArrayN<T>::index (idx_vector&, int, const T&): + Call indexN if more than 2 indices. + (ArrayN<T>::index (Array<idx_vector>&, int, const T&)): + Make it (mostly) work. + * ArrayN-inline.h (number_of_elements, get_ra_idx, short_freeze): + New functions. + 2003-10-02 John W. Eaton <jwe@bevo.che.wisc.edu> * cmd-edit.cc (do_readline): Pass eof to octave_fgetl.