Mercurial > hg > octave-nkf
changeset 4517:b4449b1193ac
[project @ 2003-09-20 02:06:06 by jwe]
author | jwe |
---|---|
date | Sat, 20 Sep 2003 02:06:07 +0000 |
parents | 34c934a1b08f |
children | 382cb0ed8c14 |
files | liboctave/Array-idx.h liboctave/Array.cc liboctave/Array.h liboctave/ChangeLog liboctave/Makefile.in |
diffstat | 5 files changed, 1748 insertions(+), 1798 deletions(-) [+] |
line wrap: on
line diff
deleted file mode 100644 --- a/liboctave/Array-idx.h +++ /dev/null @@ -1,1724 +0,0 @@ -// Template array classes -/* - -Copyright (C) 1996, 1997 John W. Eaton - -This file is part of Octave. - -Octave is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octave; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "Array-flags.h" -#include "Range.h" -#include "idx-vector.h" -#include "lo-error.h" - -template <class T> -void -Array<T>::clear_index (void) -{ - delete [] idx; - idx = 0; - idx_count = 0; -} - -template <class T> -void -Array<T>::set_index (const idx_vector& idx_arg) -{ - int nd = ndims (); - - if (! idx && nd > 0) - idx = new idx_vector [nd]; - - if (idx_count < nd) - { - idx[idx_count++] = idx_arg; - } - else - { - idx_vector *new_idx = new idx_vector [idx_count+1]; - - for (int i = 0; i < idx_count; i++) - new_idx[i] = idx[i]; - - new_idx[idx_count++] = idx_arg; - - delete [] idx; - - idx = new_idx; - } -} - -template <class T> -Array<T> -Array<T>::value (void) -{ - Array<T> retval; - - int n_idx = index_count (); - - if (n_idx == 2) - { - idx_vector *tmp = get_idx (); - - idx_vector idx_i = tmp[0]; - idx_vector idx_j = tmp[1]; - - retval = index (idx_i, idx_j); - } - else if (n_idx == 1) - { - retval = index (idx[0]); - } - else - (*current_liboctave_error_handler) - ("Array<T>::value: invalid number of indices specified"); - - clear_index (); - - return retval; -} - -template <class T> -Array<T> -Array<T>::index (idx_vector& idx_arg, int resize_ok, const T& rfv) const -{ - Array<T> retval; - - switch (ndims ()) - { - case 1: - retval = index1 (idx_arg, resize_ok, rfv); - break; - - case 2: - retval = index2 (idx_arg, resize_ok, rfv); - break; - - default: - { - Array<idx_vector> tmp (1, idx_arg); - - retval = index (tmp, resize_ok, rfv); - } - break; - } - - return retval; -} - -template <class T> -Array<T> -Array<T>::index1 (idx_vector& idx_arg, int resize_ok, const T& rfv) const -{ - Array<T> retval; - - int len = length (); - - int n = idx_arg.freeze (len, "vector", resize_ok); - - if (idx_arg) - { - if (idx_arg.is_colon_equiv (len)) - { - retval = *this; - } - else if (n == 0) - { - retval.resize_no_fill (0); - } - else if (len == 1 && n > 1 - && idx_arg.one_zero_only () - && idx_arg.ones_count () == n) - { - retval.resize (n, elem (0)); - } - else - { - retval.resize_no_fill (n); - - for (int i = 0; i < n; i++) - { - int ii = idx_arg.elem (i); - if (ii >= len) - retval.elem (i) = rfv; - else - retval.elem (i) = elem (ii); - } - } - } - - // idx_vector::freeze() printed an error message for us. - - return retval; -} - -template <class T> -Array<T> -Array<T>::index2 (idx_vector& idx_arg, int resize_ok, const T& rfv) const -{ - Array<T> retval; - - int nr = dim1 (); - int nc = dim2 (); - - int orig_len = nr * nc; - - int idx_orig_rows = idx_arg.orig_rows (); - int idx_orig_columns = idx_arg.orig_columns (); - - if (idx_arg.is_colon ()) - { - // Fast magic colon processing. - - int result_nr = nr * nc; - int result_nc = 1; - - retval = Array<T> (*this, dim_vector (result_nr, result_nc)); - } - else if (nr == 1 && nc == 1) - { - Array<T> tmp = Array<T>::index1 (idx_arg, resize_ok); - - if (tmp.length () != 0) - retval = Array<T> (tmp, dim_vector (idx_orig_rows, idx_orig_columns)); - else - retval = Array<T> (tmp, dim_vector (0, 0)); - } - else if (nr == 1 || nc == 1) - { - // If indexing a vector with a matrix, return value has same - // shape as the index. Otherwise, it has same orientation as - // indexed object. - - Array<T> tmp = index1 (idx_arg, resize_ok); - - int len = tmp.length (); - - if (len == 0) - { - if (idx_orig_rows == 0 || idx_orig_columns == 0) - retval = Array<T> (dim_vector (idx_orig_rows, idx_orig_columns)); - else if (nr == 1) - retval = Array<T> (dim_vector (1, 0)); - else - retval = Array<T> (dim_vector (0, 1)); - } - else - { - if (idx_orig_rows == 1 || idx_orig_columns == 1) - { - if (nr == 1) - retval = Array<T> (tmp, dim_vector (1, len)); - else - retval = Array<T> (tmp, dim_vector (len, 1)); - } - else - retval = Array<T> (tmp, dim_vector (idx_orig_rows, idx_orig_columns)); - } - } - else - { - if (liboctave_wfi_flag - && ! (idx_arg.one_zero_only () - && idx_orig_rows == nr - && idx_orig_columns == nc)) - (*current_liboctave_warning_handler) ("single index used for matrix"); - - // This code is only for indexing matrices. The vector - // cases are handled above. - - idx_arg.freeze (nr * nc, "matrix", resize_ok); - - if (idx_arg) - { - int result_nr = idx_orig_rows; - int result_nc = idx_orig_columns; - - if (idx_arg.one_zero_only ()) - { - result_nr = idx_arg.ones_count (); - result_nc = (result_nr > 0 ? 1 : 0); - } - - retval.resize_no_fill (result_nr, result_nc); - - int k = 0; - for (int j = 0; j < result_nc; j++) - { - for (int i = 0; i < result_nr; i++) - { - int ii = idx_arg.elem (k++); - if (ii >= orig_len) - retval.elem (i, j) = rfv; - else - { - int fr = ii % nr; - int fc = (ii - fr) / nr; - retval.elem (i, j) = elem (fr, fc); - } - } - } - } - // idx_vector::freeze() printed an error message for us. - } - - 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 -{ - Array<T> retval; - - int nr = dim1 (); - int nc = dim2 (); - - int n = idx_i.freeze (nr, "row", resize_ok); - int m = idx_j.freeze (nc, "column", resize_ok); - - if (idx_i && idx_j) - { - if (idx_i.orig_empty () || idx_j.orig_empty () || n == 0 || m == 0) - { - retval.resize_no_fill (n, m); - } - else if (idx_i.is_colon_equiv (nr) && idx_j.is_colon_equiv (nc)) - { - retval = *this; - } - else - { - retval.resize_no_fill (n, m); - - for (int j = 0; j < m; j++) - { - int jj = idx_j.elem (j); - for (int i = 0; i < n; i++) - { - int ii = idx_i.elem (i); - if (ii >= nr || jj >= nc) - retval.elem (i, j) = rfv; - else - retval.elem (i, j) = elem (ii, jj); - } - } - } - } - - // idx_vector::freeze() printed an error message for us. - - return retval; -} - -#include "ArrayN-inline.h" - -template <class T> -Array<T> -Array<T>::index (Array<idx_vector>& ra_idx, int resize_ok, const T& rfv) const -{ - Array<T> retval; - - int n_idx = ra_idx.length (); - - int n_dims = dimensions.length (); - - if (n_idx == n_dims) - { - dim_vector frozen_lengths = freeze (ra_idx, dimensions, resize_ok); - - if (frozen_lengths.length () == n_dims) - { - if (all_ok (ra_idx)) - { - 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)) - { - 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 - } - } - // 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"); - - return retval; -} - -template <class T> -void -Array<T>::maybe_delete_elements (idx_vector& idx_arg) -{ - switch (ndims ()) - { - case 1: - maybe_delete_elements_1 (idx_arg); - break; - - case 2: - maybe_delete_elements_2 (idx_arg); - break; - - default: - (*current_liboctave_error_handler) - ("Array<T>::maybe_delete_elements: invalid operation"); - break; - } -} - -template <class T> -void -Array<T>::maybe_delete_elements_1 (idx_vector& idx_arg) -{ - int len = length (); - - if (len == 0) - return; - - if (idx_arg.is_colon_equiv (len, 1)) - resize_no_fill (0); - else - { - int num_to_delete = idx_arg.length (len); - - if (num_to_delete != 0) - { - int new_len = len; - - int iidx = 0; - - for (int i = 0; i < len; i++) - if (i == idx_arg.elem (iidx)) - { - iidx++; - new_len--; - - if (iidx == num_to_delete) - break; - } - - if (new_len > 0) - { - T *new_data = new T [new_len]; - - int ii = 0; - iidx = 0; - for (int i = 0; i < len; i++) - { - if (iidx < num_to_delete && i == idx_arg.elem (iidx)) - iidx++; - else - { - new_data[ii] = elem (i); - ii++; - } - } - - if (--rep->count <= 0) - delete rep; - - rep = new typename Array<T>::ArrayRep (new_data, new_len); - - dimensions.resize (1); - dimensions(0) = new_len; - } - else - (*current_liboctave_error_handler) - ("A(idx) = []: index out of range"); - } - } -} - -template <class T> -void -Array<T>::maybe_delete_elements_2 (idx_vector& idx_arg) -{ - int nr = dim1 (); - int nc = dim2 (); - - if (nr == 0 && nc == 0) - return; - - int n; - if (nr == 1) - n = nc; - else if (nc == 1) - n = nr; - else - { - (*current_liboctave_error_handler) - ("A(idx) = []: expecting A to be row or column vector or scalar"); - - return; - } - - if (idx_arg.is_colon_equiv (n, 1)) - { - // Either A(:) = [] or A(idx) = [] with idx enumerating all - // elements, so we delete all elements and return [](0x0). To - // preserve the orientation of the vector, you have to use - // A(idx,:) = [] (delete rows) or A(:,idx) (delete columns). - - resize_no_fill (0, 0); - return; - } - - idx_arg.sort (true); - - int num_to_delete = idx_arg.length (n); - - if (num_to_delete != 0) - { - int new_n = n; - - int iidx = 0; - - for (int i = 0; i < n; i++) - if (i == idx_arg.elem (iidx)) - { - iidx++; - new_n--; - - if (iidx == num_to_delete) - break; - } - - if (new_n > 0) - { - T *new_data = new T [new_n]; - - int ii = 0; - iidx = 0; - for (int i = 0; i < n; i++) - { - if (iidx < num_to_delete && i == idx_arg.elem (iidx)) - iidx++; - else - { - if (nr == 1) - new_data[ii] = elem (0, i); - else - new_data[ii] = elem (i, 0); - - ii++; - } - } - - if (--(Array<T>::rep)->count <= 0) - delete Array<T>::rep; - - Array<T>::rep = new typename Array<T>::ArrayRep (new_data, new_n); - - dimensions.resize (2); - - if (nr == 1) - { - dimensions(0) = 1; - dimensions(1) = new_n; - } - else - { - dimensions(0) = new_n; - dimensions(1) = 1; - } - } - else - (*current_liboctave_error_handler) - ("A(idx) = []: index out of range"); - } -} - -template <class T> -void -Array<T>::maybe_delete_elements (idx_vector& idx_i, idx_vector& idx_j) -{ - int nr = dim1 (); - int nc = dim2 (); - - if (nr == 0 && nc == 0) - return; - - if (idx_i.is_colon ()) - { - if (idx_j.is_colon ()) - { - // A(:,:) -- We are deleting columns and rows, so the result - // is [](0x0). - - resize_no_fill (0, 0); - return; - } - - if (idx_j.is_colon_equiv (nc, 1)) - { - // A(:,j) -- We are deleting columns by enumerating them, - // If we enumerate all of them, we should have zero columns - // with the same number of rows that we started with. - - resize_no_fill (nr, 0); - return; - } - } - - if (idx_j.is_colon () && idx_i.is_colon_equiv (nr, 1)) - { - // A(i,:) -- We are deleting rows by enumerating them. If we - // enumerate all of them, we should have zero rows with the - // same number of columns that we started with. - - resize_no_fill (0, nc); - return; - } - - if (idx_i.is_colon_equiv (nr, 1)) - { - if (idx_j.is_colon_equiv (nc, 1)) - resize_no_fill (0, 0); - else - { - idx_j.sort (true); - - int num_to_delete = idx_j.length (nc); - - if (num_to_delete != 0) - { - if (nr == 1 && num_to_delete == nc) - resize_no_fill (0, 0); - else - { - int new_nc = nc; - - int iidx = 0; - - for (int j = 0; j < nc; j++) - if (j == idx_j.elem (iidx)) - { - iidx++; - new_nc--; - - if (iidx == num_to_delete) - break; - } - - if (new_nc > 0) - { - T *new_data = new T [nr * new_nc]; - - int jj = 0; - iidx = 0; - for (int j = 0; j < nc; j++) - { - if (iidx < num_to_delete && j == idx_j.elem (iidx)) - iidx++; - else - { - for (int i = 0; i < nr; i++) - new_data[nr*jj+i] = elem (i, j); - jj++; - } - } - - if (--(Array<T>::rep)->count <= 0) - delete Array<T>::rep; - - Array<T>::rep = new typename Array<T>::ArrayRep (new_data, nr * new_nc); - - dimensions.resize (2); - dimensions(1) = new_nc; - } - else - (*current_liboctave_error_handler) - ("A(idx) = []: index out of range"); - } - } - } - } - else if (idx_j.is_colon_equiv (nc, 1)) - { - if (idx_i.is_colon_equiv (nr, 1)) - resize_no_fill (0, 0); - else - { - idx_i.sort (true); - - int num_to_delete = idx_i.length (nr); - - if (num_to_delete != 0) - { - if (nc == 1 && num_to_delete == nr) - resize_no_fill (0, 0); - else - { - int new_nr = nr; - - int iidx = 0; - - for (int i = 0; i < nr; i++) - if (i == idx_i.elem (iidx)) - { - iidx++; - new_nr--; - - if (iidx == num_to_delete) - break; - } - - if (new_nr > 0) - { - T *new_data = new T [new_nr * nc]; - - int ii = 0; - iidx = 0; - for (int i = 0; i < nr; i++) - { - if (iidx < num_to_delete && i == idx_i.elem (iidx)) - iidx++; - else - { - for (int j = 0; j < nc; j++) - new_data[new_nr*j+ii] = elem (i, j); - ii++; - } - } - - if (--(Array<T>::rep)->count <= 0) - delete Array<T>::rep; - - Array<T>::rep = new typename Array<T>::ArrayRep (new_data, new_nr * nc); - - dimensions.resize (2); - dimensions(0) = new_nr; - } - else - (*current_liboctave_error_handler) - ("A(idx) = []: index out of range"); - } - } - } - } -} - -template <class T> -void -Array<T>::maybe_delete_elements (idx_vector&, idx_vector&, idx_vector&) -{ - assert (0); -} - -template <class T> -void -Array<T>::maybe_delete_elements (Array<idx_vector>& idx, const T& rfv) -{ - int n_idx = idx.length (); - - dim_vector lhs_dims = dims (); - - dim_vector idx_is_colon; - idx_is_colon.resize (n_idx); - - dim_vector idx_is_colon_equiv; - idx_is_colon_equiv.resize (n_idx); - - // Initialization of colon arrays. - - for (int i = 0; i < n_idx; i++) - { - idx_is_colon_equiv(i) = idx(i).is_colon_equiv (lhs_dims(i), 1); - - idx_is_colon(i) = idx(i).is_colon (); - } - - if (all_ones (idx_is_colon) || all_ones (idx_is_colon_equiv)) - { - // A(:,:,:) -- we are deleting elements in all dimensions, so - // the result is [](0x0x0). - - dim_vector zeros; - zeros.resize (n_idx); - - for (int i = 0; i < n_idx; i++) - zeros(i) = 0; - - resize (zeros, rfv); - } - - else if (num_ones (idx_is_colon) == n_idx - 1 - && num_ones (idx_is_colon_equiv) == n_idx) - { - // A(:,:,j) -- we are deleting elements in one dimension by - // enumerating them. - // - // If we enumerate all of the elements, we should have zero - // elements in that dimension with the same number of elements - // in the other dimensions that we started with. - - dim_vector temp_dims; - temp_dims.resize (n_idx); - - for (int i = 0; i < n_idx; i++) - { - if (idx_is_colon (i)) - temp_dims (i) = lhs_dims (i); - else - temp_dims (i) = 0; - } - - resize (temp_dims); - } - else if (num_ones (idx_is_colon) == n_idx - 1) - { - // We have colons in all indices except for one. - // This index tells us which slice to delete - - int non_col = 0; - - // Find the non-colon column. - - for (int i = 0; i < n_idx; i++) - { - if (! idx_is_colon (i)) - non_col = i; - } - - // The length of the non-colon dimension. - - int non_col_dim = lhs_dims (non_col); - - idx(non_col).sort (true); - - int num_to_delete = idx(non_col).length (lhs_dims (non_col)); - - if (num_to_delete > 0) - { - int temp = num_ones(lhs_dims); - - if (non_col_dim == 1) - temp--; - - if (temp == n_idx - 1 && num_to_delete == non_col_dim) - { - // We have A with (1x1x4), where A(1,:,1:4) - // Delete all (0x0x0) - - dim_vector zero_dims (n_idx, 0); - - resize (zero_dims, rfv); - } - else - { - // New length of non-colon dimension - // (calculated in the next for loop) - - int new_dim = non_col_dim; - - int iidx = 0; - - for (int j = 0; j < non_col_dim; j++) - if (j == idx(non_col).elem (iidx)) - { - iidx++; - - new_dim--; - - if (iidx == num_to_delete) - break; - } - - // Creating the new nd array after deletions. - - if (new_dim > 0) - { - // Calculate number of elements in new array. - - int num_new_elem=1; - - for (int i = 0; i < n_idx; i++) - { - if (i == non_col) - num_new_elem *= new_dim; - - else - num_new_elem *= lhs_dims(i); - } - - T *new_data = new T [num_new_elem]; - - Array<int> result_idx (lhs_dims.length (), 0); - - dim_vector lhs_inc; - lhs_inc.resize (lhs_dims.length ()); - - for (int i = 0; i < lhs_dims.length (); i++) - lhs_inc(i) = lhs_dims(i) + 1; - - dim_vector new_lhs_dim = lhs_dims; - - new_lhs_dim(non_col) = new_dim; - - int num_elem = 1; - - int numidx = 0; - - int n = length (); - - for (int i =0; i < lhs_dims.length (); i++) - if (i != non_col) - num_elem *= lhs_dims (i); - - num_elem *= idx(non_col).capacity (); - - for (int i = 0; i < n; i++) - { - if (numidx < num_elem - && is_in (result_idx(non_col), idx(non_col))) - numidx++; - - else - { - Array<int> temp_result_idx = result_idx; - - int num_lgt - = how_many_lgt (result_idx(non_col), idx(non_col)); - - temp_result_idx(non_col) -= num_lgt; - - int kidx - = ::compute_index (temp_result_idx, new_lhs_dim); - - new_data[kidx] = elem (result_idx); - } - - increment_index (result_idx, lhs_dims); - } - - if (--rep->count <= 0) - delete rep; - - rep = new typename Array<T>::ArrayRep (new_data, - num_new_elem); - - dimensions = new_lhs_dim; - } - } - } - } - else if (num_ones(idx_is_colon) < n_idx) - { - (*current_liboctave_error_handler) - ("A null assignment can have only one non-colon index."); - } -} - -// XXX FIXME XXX -- this is a mess. - -template <class LT, class RT> -int -assign (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv) -{ - int retval = 0; - - switch (lhs.ndims ()) - { - case 0: - { - if (lhs.index_count () < 3) - { - // kluge... - lhs.resize_no_fill (0, 0); - retval = assign2 (lhs, rhs, rfv); - } - else - retval = assignN (lhs, rhs, rfv); - } - break; - - case 1: - { - if (lhs.index_count () > 1) - retval = assignN (lhs, rhs, rfv); - else - retval = assign1 (lhs, rhs, rfv); - } - break; - - case 2: - { - if (lhs.index_count () > 2) - retval = assignN (lhs, rhs, rfv); - else - retval = assign2 (lhs, rhs, rfv); - } - break; - - default: - retval = assignN (lhs, rhs, rfv); - break; - } - - return retval; -} - -template <class LT, class RT> -int -assign1 (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv) -{ - int retval = 1; - - idx_vector *tmp = lhs.get_idx (); - - idx_vector lhs_idx = tmp[0]; - - int lhs_len = lhs.length (); - int rhs_len = rhs.length (); - - int n = lhs_idx.freeze (lhs_len, "vector", true, liboctave_wrore_flag); - - if (n != 0) - { - if (rhs_len == n || rhs_len == 1) - { - int max_idx = lhs_idx.max () + 1; - if (max_idx > lhs_len) - lhs.resize (max_idx, rfv); - } - - if (rhs_len == n) - { - for (int i = 0; i < n; i++) - { - int ii = lhs_idx.elem (i); - lhs.elem (ii) = rhs.elem (i); - } - } - else if (rhs_len == 1) - { - RT scalar = rhs.elem (0); - - for (int i = 0; i < n; i++) - { - int ii = lhs_idx.elem (i); - lhs.elem (ii) = scalar; - } - } - else - { - (*current_liboctave_error_handler) - ("A(I) = X: X must be a scalar or a vector with same length as I"); - - retval = 0; - } - } - else if (lhs_idx.is_colon ()) - { - if (lhs_len == 0) - { - lhs.resize_no_fill (rhs_len); - - for (int i = 0; i < rhs_len; i++) - lhs.elem (i) = rhs.elem (i); - } - else - (*current_liboctave_error_handler) - ("A(:) = X: A must be the same size as X"); - } - else if (! (rhs_len == 1 || rhs_len == 0)) - { - (*current_liboctave_error_handler) - ("A([]) = X: X must also be an empty matrix or a scalar"); - - retval = 0; - } - - lhs.clear_index (); - - return retval; -} - -#define MAYBE_RESIZE_LHS \ - do \ - { \ - int max_row_idx = idx_i_is_colon ? rhs_nr : idx_i.max () + 1; \ - int max_col_idx = idx_j_is_colon ? rhs_nc : idx_j.max () + 1; \ - \ - int new_nr = max_row_idx > lhs_nr ? max_row_idx : lhs_nr; \ - int new_nc = max_col_idx > lhs_nc ? max_col_idx : lhs_nc; \ - \ - lhs.resize_and_fill (new_nr, new_nc, rfv); \ - } \ - while (0) - -template <class LT, class RT> -int -assign2 (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv) -{ - int retval = 1; - - int n_idx = lhs.index_count (); - - int lhs_nr = lhs.rows (); - int lhs_nc = lhs.cols (); - - int rhs_nr = rhs.rows (); - int rhs_nc = rhs.cols (); - - idx_vector *tmp = lhs.get_idx (); - - idx_vector idx_i; - idx_vector idx_j; - - if (n_idx > 1) - idx_j = tmp[1]; - - if (n_idx > 0) - idx_i = tmp[0]; - - if (n_idx == 2) - { - int n = idx_i.freeze (lhs_nr, "row", true, liboctave_wrore_flag); - - int m = idx_j.freeze (lhs_nc, "column", true, liboctave_wrore_flag); - - int idx_i_is_colon = idx_i.is_colon (); - int idx_j_is_colon = idx_j.is_colon (); - - if (idx_i_is_colon) - n = lhs_nr > 0 ? lhs_nr : rhs_nr; - - if (idx_j_is_colon) - m = lhs_nc > 0 ? lhs_nc : rhs_nc; - - if (idx_i && idx_j) - { - if (rhs_nr == 0 && rhs_nc == 0) - { - lhs.maybe_delete_elements (idx_i, idx_j); - } - else - { - if (rhs_nr == 1 && rhs_nc == 1 && n > 0 && m > 0) - { - MAYBE_RESIZE_LHS; - - RT scalar = rhs.elem (0, 0); - - for (int j = 0; j < m; j++) - { - int jj = idx_j.elem (j); - for (int i = 0; i < n; i++) - { - int ii = idx_i.elem (i); - lhs.elem (ii, jj) = scalar; - } - } - } - else if (n == rhs_nr && m == rhs_nc) - { - if (n > 0 && m > 0) - { - MAYBE_RESIZE_LHS; - - for (int j = 0; j < m; j++) - { - int jj = idx_j.elem (j); - for (int i = 0; i < n; i++) - { - int ii = idx_i.elem (i); - lhs.elem (ii, jj) = rhs.elem (i, j); - } - } - } - } - else if (n == 0 && m == 0) - { - if (! ((rhs_nr == 1 && rhs_nc == 1) - || (rhs_nr == 0 && rhs_nc == 0))) - { - (*current_liboctave_error_handler) - ("A([], []) = X: X must be an empty matrix or a scalar"); - - retval = 0; - } - } - else - { - (*current_liboctave_error_handler) - ("A(I, J) = X: X must be a scalar or the number of elements in I must"); - (*current_liboctave_error_handler) - ("match the number of rows in X and the number of elements in J must"); - (*current_liboctave_error_handler) - ("match the number of columns in X"); - - retval = 0; - } - } - } - // idx_vector::freeze() printed an error message for us. - } - else if (n_idx == 1) - { - int lhs_is_empty = lhs_nr == 0 || lhs_nc == 0; - - if (lhs_is_empty || (lhs_nr == 1 && lhs_nc == 1)) - { - int lhs_len = lhs.length (); - - int n = idx_i.freeze (lhs_len, 0, true, liboctave_wrore_flag); - - if (idx_i) - { - if (rhs_nr == 0 && rhs_nc == 0) - { - if (n != 0 && (lhs_nr != 0 || lhs_nc != 0)) - lhs.maybe_delete_elements (idx_i); - } - else - { - if (liboctave_wfi_flag) - { - if (lhs_is_empty - && idx_i.is_colon () - && ! (rhs_nr == 1 || rhs_nc == 1)) - { - (*current_liboctave_warning_handler) - ("A(:) = X: X is not a vector or scalar"); - } - else - { - int idx_nr = idx_i.orig_rows (); - int idx_nc = idx_i.orig_columns (); - - if (! (rhs_nr == idx_nr && rhs_nc == idx_nc)) - (*current_liboctave_warning_handler) - ("A(I) = X: X does not have same shape as I"); - } - } - - if (assign1 ((Array<LT>&) lhs, (Array<RT>&) rhs, rfv)) - { - int len = lhs.length (); - - if (len > 0) - { - // The following behavior is much simplified - // over previous versions of Octave. It - // seems to be compatible with Matlab. - - lhs.dimensions = dim_vector (1, lhs.length ()); - } - else - lhs.dimensions = dim_vector (0, 0); - } - else - retval = 0; - } - } - // idx_vector::freeze() printed an error message for us. - } - else if (lhs_nr == 1) - { - idx_i.freeze (lhs_nc, "vector", true, liboctave_wrore_flag); - - if (idx_i) - { - if (rhs_nr == 0 && rhs_nc == 0) - lhs.maybe_delete_elements (idx_i); - else - { - if (assign1 ((Array<LT>&) lhs, (Array<RT>&) rhs, rfv)) - lhs.dimensions = dim_vector (1, lhs.length ()); - else - retval = 0; - } - } - // idx_vector::freeze() printed an error message for us. - } - else if (lhs_nc == 1) - { - idx_i.freeze (lhs_nr, "vector", true, liboctave_wrore_flag); - - if (idx_i) - { - if (rhs_nr == 0 && rhs_nc == 0) - lhs.maybe_delete_elements (idx_i); - else - { - if (assign1 ((Array<LT>&) lhs, (Array<RT>&) rhs, rfv)) - lhs.dimensions = dim_vector (lhs.length (), 1); - else - retval = 0; - } - } - // idx_vector::freeze() printed an error message for us. - } - else - { - if (liboctave_wfi_flag - && ! (idx_i.is_colon () - || (idx_i.one_zero_only () - && idx_i.orig_rows () == lhs_nr - && idx_i.orig_columns () == lhs_nc))) - (*current_liboctave_warning_handler) - ("single index used for matrix"); - - int len = idx_i.freeze (lhs_nr * lhs_nc, "matrix"); - - if (idx_i) - { - if (len == 0) - { - if (! ((rhs_nr == 1 && rhs_nc == 1) - || (rhs_nr == 0 && rhs_nc == 0))) - (*current_liboctave_error_handler) - ("A([]) = X: X must be an empty matrix or scalar"); - } - else if (len == rhs_nr * rhs_nc) - { - int k = 0; - for (int j = 0; j < rhs_nc; j++) - { - for (int i = 0; i < rhs_nr; i++) - { - int ii = idx_i.elem (k++); - int fr = ii % lhs_nr; - int fc = (ii - fr) / lhs_nr; - lhs.elem (fr, fc) = rhs.elem (i, j); - } - } - } - else if (rhs_nr == 1 && rhs_nc == 1 && len <= lhs_nr * lhs_nc) - { - RT scalar = rhs.elem (0, 0); - - for (int i = 0; i < len; i++) - { - int ii = idx_i.elem (i); - int fr = ii % lhs_nr; - int fc = (ii - fr) / lhs_nr; - lhs.elem (fr, fc) = scalar; - } - } - else - { - (*current_liboctave_error_handler) - ("A(I) = X: X must be a scalar or a matrix with the same size as I"); - - retval = 0; - } - } - // idx_vector::freeze() printed an error message for us. - } - } - else - { - (*current_liboctave_error_handler) - ("invalid number of indices for matrix expression"); - - retval = 0; - } - - lhs.clear_index (); - - return retval; -} - -#define MAYBE_RESIZE_ND_DIMS \ - do \ - { \ - if (n_idx >= lhs_dims.length () && ! rhs_is_empty) \ - { \ - Array<int> max_idx (n_idx); \ - dim_vector new_idx; \ - new_idx.resize (n_idx); \ - \ - for (int i = 0; i < n_idx; i++) \ - { \ - if (lhs_dims.length () == 0 || i >= lhs_dims.length ()) \ - new_idx(i) = idx(i).max () + 1; \ - else \ - { \ - if (i < rhs_dims.length ()) \ - max_idx(i) = idx(i).is_colon () ? rhs_dims(i) : idx(i).max () + 1; \ - else \ - max_idx(i) = idx(i).max () + 1; \ - \ - new_idx(i) = max_idx(i) > lhs_dims(i) ? max_idx(i) : lhs_dims(i); \ - } \ - } \ - \ - lhs.resize (new_idx, rfv); \ - lhs_dims = lhs.dims (); \ - } \ - } \ - while (0) - -template <class LT, class RT> -int -assignN (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv) -{ - int retval = 1; - - int n_idx = lhs.index_count (); - - dim_vector lhs_dims = lhs.dims (); - dim_vector rhs_dims = rhs.dims (); - - idx_vector *tmp = lhs.get_idx (); - - Array<idx_vector> idx = conv_to_array (tmp, n_idx); - - // This needs to be defined before MAYBE_RESIZE_ND_DIMS. - - bool rhs_is_empty = rhs_dims.length () == 0 ? true : any_zero_len (rhs_dims); - - // Maybe expand to more dimensions. - - MAYBE_RESIZE_ND_DIMS; - - Array<int> idx_is_colon (n_idx, 0); - Array<int> idx_is_colon_equiv (n_idx, 0); - - for (int i = 0; i < n_idx; i++) - { - idx_is_colon_equiv(i) = idx(i).is_colon_equiv (lhs_dims(i), 1); - - idx_is_colon(i) = idx(i).is_colon (); - } - - int resize_ok = 1; - - dim_vector frozen_len; - - if (n_idx == lhs_dims.length ()) - frozen_len = freeze (idx, lhs_dims, resize_ok); - - bool rhs_is_scalar = is_scalar (rhs_dims); - - bool idx_is_empty = any_zero_len (frozen_len); - - if (rhs_is_empty) - { - lhs.maybe_delete_elements (idx, rfv); - } - else if (rhs_is_scalar) - { - if (n_idx == 0) - (*current_liboctave_error_handler) - ("number of indices is zero."); - - else if (n_idx < lhs_dims.length ()) - { - // Number of indices is less than dimensions. - - 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."); - } - else - { - // Fewer indices than dimensions, no colons. - - bool resize = false; - - // Subtract one since the last idx do not tell us - // anything about dimensionality. - - for (int i = 0; i < idx.length () - 1; i++) - { - // Subtract one since idx counts from 0 while dims - // count from 1. - - if (idx(i).elem (0) + 1 > lhs_dims(i)) - resize = true; - } - - if (resize) - { - dim_vector new_dims; - new_dims.resize (lhs_dims.length ()); - - for (int i = 0; i < lhs_dims.length (); i++) - { - if (i < idx.length () - 1 - && idx(i).elem (0) + 1 > lhs_dims(i)) - new_dims(i) = idx(i).elem (0)+1; - else - new_dims(i) = lhs_dims(i); - } - - lhs.resize (new_dims, rfv); - - lhs_dims = lhs.dims (); - } - - Array<int> one_arg_temp (1, 0); - - RT scalar = rhs.elem (one_arg_temp); - - Array<int> int_arr = conv_to_int_array (idx); - - int numelem = get_scalar_idx (int_arr, lhs_dims); - - if (numelem > lhs.length () || numelem < 0) - (*current_liboctave_error_handler) - ("attempt to grow array along ambiguous dimension."); - else - lhs.Array<LT>::checkelem (numelem) = scalar; - } - } - else - { - // Scalar to matrix assignment with as many indices as lhs - // dimensions. - - int n = Array<LT>::get_size (frozen_len); - - Array<int> result_idx (lhs_dims.length (), 0); - - Array<int> elt_idx; - - RT scalar = rhs.elem (0); - - for (int i = 0; i < n; i++) - { - elt_idx = get_elt_idx (idx, result_idx); - - dim_vector lhs_inc; - lhs_inc.resize (lhs_dims.length ()); - - for (int i = 0; i < lhs_dims.length (); i++) - lhs_inc(i) = lhs_dims(i) + 1; - - if (index_in_bounds(elt_idx, lhs_inc)) - lhs.checkelem (elt_idx) = scalar; - else - lhs.checkelem (elt_idx) = rfv; - - increment_index (result_idx, frozen_len); - } - } - } - else if (rhs_dims.length () >= 2) - { - // RHS is matrix or higher dimension. - - // 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)) - { - (*current_liboctave_error_handler) - ("dimensions do not match in matrix assignment."); - } - else - { - bool dim_ok(true); - - int jj = 0; - - // Check that RHS dimensions are the same length as the - // corresponding LHS dimensions. - - for (int j = 0; j < idx_is_colon.length (); j++) - { - if (idx_is_colon(j) || idx_is_colon_equiv(j)) - { - if (rhs_dims(jj) < lhs_dims(j)) - { - dim_ok = false; - - break; - } - - jj++; - } - } - - if (! dim_ok) - (*current_liboctave_error_handler) - ("subscripted assignment dimension mismatch."); - else - { - dim_vector new_dims; - new_dims.resize (n_idx); - - bool resize = false; - - int ii = 0; - - // Update idx vectors. - - for (int i = 0; i < n_idx; i++) - { - if (idx(i).is_colon ()) - { - // Add appropriate idx_vector to idx(i) since - // index with : contains no indexes. - - frozen_len(i) = lhs_dims(i) > rhs_dims(ii) ? lhs_dims(i) : rhs_dims(ii); - - new_dims(i) = lhs_dims(i) > rhs_dims(ii) ? lhs_dims(i) : rhs_dims(ii); - - ii++; - - Range idxrange (1, frozen_len(i), 1); - - idx_vector idxv (idxrange); - - idx(i) = idxv; - } - else - { - new_dims(i) = lhs_dims(i) > idx(i).max () + 1 ? lhs_dims(i) : idx(i).max () + 1; - - if (frozen_len(i) > 1) - ii++; - } - if (new_dims(i) != lhs_dims(i)) - resize = true; - } - - // Resize LHS if dimensions have changed. - - if (resize) - { - lhs.resize (new_dims, rfv); - - lhs_dims = lhs.dims (); - } - - // Number of elements which need to be set. - - int n = Array<LT>::get_size (frozen_len); - - Array<int> result_idx (lhs_dims.length (), 0); - Array<int> elt_idx; - - Array<int> result_rhs_idx (rhs_dims.length (), 0); - - dim_vector frozen_rhs; - frozen_rhs.resize (rhs_dims.length()); - - for (int i = 0; i < rhs_dims.length (); i++) - frozen_rhs(i) = rhs_dims(i); - - dim_vector lhs_inc; - lhs_inc.resize (lhs_dims.length ()); - - for (int i = 0; i < lhs_dims.length (); i++) - lhs_inc(i) = lhs_dims(i) + 1; - - for (int i = 0; i < n; i++) - { - elt_idx = get_elt_idx (idx, result_idx); - - if (index_in_bounds (elt_idx, lhs_inc)) - { - int s = compute_index (result_rhs_idx,rhs_dims); - - lhs.checkelem (elt_idx) = rhs.elem (s); - - increment_index (result_rhs_idx, frozen_rhs); - } - else - lhs.checkelem (elt_idx) = rfv; - - increment_index (result_idx, frozen_len); - } - } - } - } - else if (idx_is_empty) - { - // Assignment to matrix with at least one empty index. - - if (! rhs_is_empty || ! rhs_is_scalar) - { - (*current_liboctave_error_handler) - ("A([], []) = X: X must be an empty matrix or a scalar"); - - retval = 0; - } - } - else if (lhs_dims.length () != rhs_dims.length ()) - { - (*current_liboctave_error_handler) - ("A(I) = X: X must be a scalar or a matrix with the same size as I"); - retval = 0; - } - - lhs.clear_index (); - - return retval; -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/
--- a/liboctave/Array.cc +++ b/liboctave/Array.cc @@ -34,7 +34,8 @@ #include <iostream> #include "Array.h" -#include "Array-idx.h" +#include "Array-flags.h" +#include "Range.h" #include "idx-vector.h" #include "lo-error.h" @@ -225,29 +226,6 @@ return retval; } -#if 0 - -template <class T> -int -Array<T>::compute_index (int i, int j) const -{ - int retval = -1; - - int n = dimensions.length (); - - if (n == 2) - retval = j*dimensions(0)+i; - else if (n == 1 && j == 0) - retval = i; - else - (*current_liboctave_error_handler) - ("Array<T>::compute_index: invalid ra_idxing operation"); - - return retval; -} - -#endif - template <class T> T Array<T>::range_error (const char *fcn, int n) const @@ -767,35 +745,6 @@ } template <class T> -void -Array<T>::maybe_delete_dims (void) -{ - int ndims = dimensions.length (); - - dim_vector new_dims (1, 1); - - bool delete_dims = true; - - for (int i = ndims - 1; i >= 0; i--) - { - if (delete_dims) - { - if (dimensions(i) != 1) - { - delete_dims = false; - - new_dims = dim_vector (i + 1, dimensions(i)); - } - } - else - new_dims(i) = dimensions(i); - } - - if (ndims != new_dims.length ()) - dimensions = new_dims; -} - -template <class T> Array<T> Array<T>::transpose (void) const { @@ -833,6 +782,1726 @@ template <class T> void +Array<T>::maybe_delete_dims (void) +{ + int ndims = dimensions.length (); + + dim_vector new_dims (1, 1); + + bool delete_dims = true; + + for (int i = ndims - 1; i >= 0; i--) + { + if (delete_dims) + { + if (dimensions(i) != 1) + { + delete_dims = false; + + new_dims = dim_vector (i + 1, dimensions(i)); + } + } + else + new_dims(i) = dimensions(i); + } + + if (ndims != new_dims.length ()) + dimensions = new_dims; +} + +template <class T> +void +Array<T>::clear_index (void) +{ + delete [] idx; + idx = 0; + idx_count = 0; +} + +template <class T> +void +Array<T>::set_index (const idx_vector& idx_arg) +{ + int nd = ndims (); + + if (! idx && nd > 0) + idx = new idx_vector [nd]; + + if (idx_count < nd) + { + idx[idx_count++] = idx_arg; + } + else + { + idx_vector *new_idx = new idx_vector [idx_count+1]; + + for (int i = 0; i < idx_count; i++) + new_idx[i] = idx[i]; + + new_idx[idx_count++] = idx_arg; + + delete [] idx; + + idx = new_idx; + } +} + +template <class T> +void +Array<T>::maybe_delete_elements (idx_vector& idx_arg) +{ + switch (ndims ()) + { + case 1: + maybe_delete_elements_1 (idx_arg); + break; + + case 2: + maybe_delete_elements_2 (idx_arg); + break; + + default: + (*current_liboctave_error_handler) + ("Array<T>::maybe_delete_elements: invalid operation"); + break; + } +} + +template <class T> +void +Array<T>::maybe_delete_elements_1 (idx_vector& idx_arg) +{ + int len = length (); + + if (len == 0) + return; + + if (idx_arg.is_colon_equiv (len, 1)) + resize_no_fill (0); + else + { + int num_to_delete = idx_arg.length (len); + + if (num_to_delete != 0) + { + int new_len = len; + + int iidx = 0; + + for (int i = 0; i < len; i++) + if (i == idx_arg.elem (iidx)) + { + iidx++; + new_len--; + + if (iidx == num_to_delete) + break; + } + + if (new_len > 0) + { + T *new_data = new T [new_len]; + + int ii = 0; + iidx = 0; + for (int i = 0; i < len; i++) + { + if (iidx < num_to_delete && i == idx_arg.elem (iidx)) + iidx++; + else + { + new_data[ii] = elem (i); + ii++; + } + } + + if (--rep->count <= 0) + delete rep; + + rep = new typename Array<T>::ArrayRep (new_data, new_len); + + dimensions.resize (1); + dimensions(0) = new_len; + } + else + (*current_liboctave_error_handler) + ("A(idx) = []: index out of range"); + } + } +} + +template <class T> +void +Array<T>::maybe_delete_elements_2 (idx_vector& idx_arg) +{ + int nr = dim1 (); + int nc = dim2 (); + + if (nr == 0 && nc == 0) + return; + + int n; + if (nr == 1) + n = nc; + else if (nc == 1) + n = nr; + else + { + (*current_liboctave_error_handler) + ("A(idx) = []: expecting A to be row or column vector or scalar"); + + return; + } + + if (idx_arg.is_colon_equiv (n, 1)) + { + // Either A(:) = [] or A(idx) = [] with idx enumerating all + // elements, so we delete all elements and return [](0x0). To + // preserve the orientation of the vector, you have to use + // A(idx,:) = [] (delete rows) or A(:,idx) (delete columns). + + resize_no_fill (0, 0); + return; + } + + idx_arg.sort (true); + + int num_to_delete = idx_arg.length (n); + + if (num_to_delete != 0) + { + int new_n = n; + + int iidx = 0; + + for (int i = 0; i < n; i++) + if (i == idx_arg.elem (iidx)) + { + iidx++; + new_n--; + + if (iidx == num_to_delete) + break; + } + + if (new_n > 0) + { + T *new_data = new T [new_n]; + + int ii = 0; + iidx = 0; + for (int i = 0; i < n; i++) + { + if (iidx < num_to_delete && i == idx_arg.elem (iidx)) + iidx++; + else + { + if (nr == 1) + new_data[ii] = elem (0, i); + else + new_data[ii] = elem (i, 0); + + ii++; + } + } + + if (--(Array<T>::rep)->count <= 0) + delete Array<T>::rep; + + Array<T>::rep = new typename Array<T>::ArrayRep (new_data, new_n); + + dimensions.resize (2); + + if (nr == 1) + { + dimensions(0) = 1; + dimensions(1) = new_n; + } + else + { + dimensions(0) = new_n; + dimensions(1) = 1; + } + } + else + (*current_liboctave_error_handler) + ("A(idx) = []: index out of range"); + } +} + +template <class T> +void +Array<T>::maybe_delete_elements (idx_vector& idx_i, idx_vector& idx_j) +{ + int nr = dim1 (); + int nc = dim2 (); + + if (nr == 0 && nc == 0) + return; + + if (idx_i.is_colon ()) + { + if (idx_j.is_colon ()) + { + // A(:,:) -- We are deleting columns and rows, so the result + // is [](0x0). + + resize_no_fill (0, 0); + return; + } + + if (idx_j.is_colon_equiv (nc, 1)) + { + // A(:,j) -- We are deleting columns by enumerating them, + // If we enumerate all of them, we should have zero columns + // with the same number of rows that we started with. + + resize_no_fill (nr, 0); + return; + } + } + + if (idx_j.is_colon () && idx_i.is_colon_equiv (nr, 1)) + { + // A(i,:) -- We are deleting rows by enumerating them. If we + // enumerate all of them, we should have zero rows with the + // same number of columns that we started with. + + resize_no_fill (0, nc); + return; + } + + if (idx_i.is_colon_equiv (nr, 1)) + { + if (idx_j.is_colon_equiv (nc, 1)) + resize_no_fill (0, 0); + else + { + idx_j.sort (true); + + int num_to_delete = idx_j.length (nc); + + if (num_to_delete != 0) + { + if (nr == 1 && num_to_delete == nc) + resize_no_fill (0, 0); + else + { + int new_nc = nc; + + int iidx = 0; + + for (int j = 0; j < nc; j++) + if (j == idx_j.elem (iidx)) + { + iidx++; + new_nc--; + + if (iidx == num_to_delete) + break; + } + + if (new_nc > 0) + { + T *new_data = new T [nr * new_nc]; + + int jj = 0; + iidx = 0; + for (int j = 0; j < nc; j++) + { + if (iidx < num_to_delete && j == idx_j.elem (iidx)) + iidx++; + else + { + for (int i = 0; i < nr; i++) + new_data[nr*jj+i] = elem (i, j); + jj++; + } + } + + if (--(Array<T>::rep)->count <= 0) + delete Array<T>::rep; + + Array<T>::rep = new typename Array<T>::ArrayRep (new_data, nr * new_nc); + + dimensions.resize (2); + dimensions(1) = new_nc; + } + else + (*current_liboctave_error_handler) + ("A(idx) = []: index out of range"); + } + } + } + } + else if (idx_j.is_colon_equiv (nc, 1)) + { + if (idx_i.is_colon_equiv (nr, 1)) + resize_no_fill (0, 0); + else + { + idx_i.sort (true); + + int num_to_delete = idx_i.length (nr); + + if (num_to_delete != 0) + { + if (nc == 1 && num_to_delete == nr) + resize_no_fill (0, 0); + else + { + int new_nr = nr; + + int iidx = 0; + + for (int i = 0; i < nr; i++) + if (i == idx_i.elem (iidx)) + { + iidx++; + new_nr--; + + if (iidx == num_to_delete) + break; + } + + if (new_nr > 0) + { + T *new_data = new T [new_nr * nc]; + + int ii = 0; + iidx = 0; + for (int i = 0; i < nr; i++) + { + if (iidx < num_to_delete && i == idx_i.elem (iidx)) + iidx++; + else + { + for (int j = 0; j < nc; j++) + new_data[new_nr*j+ii] = elem (i, j); + ii++; + } + } + + if (--(Array<T>::rep)->count <= 0) + delete Array<T>::rep; + + Array<T>::rep = new typename Array<T>::ArrayRep (new_data, new_nr * nc); + + dimensions.resize (2); + dimensions(0) = new_nr; + } + else + (*current_liboctave_error_handler) + ("A(idx) = []: index out of range"); + } + } + } + } +} + +template <class T> +void +Array<T>::maybe_delete_elements (idx_vector&, idx_vector&, idx_vector&) +{ + assert (0); +} + +template <class T> +void +Array<T>::maybe_delete_elements (Array<idx_vector>& idx, const T& rfv) +{ + int n_idx = idx.length (); + + dim_vector lhs_dims = dims (); + + dim_vector idx_is_colon; + idx_is_colon.resize (n_idx); + + dim_vector idx_is_colon_equiv; + idx_is_colon_equiv.resize (n_idx); + + // Initialization of colon arrays. + + for (int i = 0; i < n_idx; i++) + { + idx_is_colon_equiv(i) = idx(i).is_colon_equiv (lhs_dims(i), 1); + + idx_is_colon(i) = idx(i).is_colon (); + } + + if (all_ones (idx_is_colon) || all_ones (idx_is_colon_equiv)) + { + // A(:,:,:) -- we are deleting elements in all dimensions, so + // the result is [](0x0x0). + + dim_vector zeros; + zeros.resize (n_idx); + + for (int i = 0; i < n_idx; i++) + zeros(i) = 0; + + resize (zeros, rfv); + } + + else if (num_ones (idx_is_colon) == n_idx - 1 + && num_ones (idx_is_colon_equiv) == n_idx) + { + // A(:,:,j) -- we are deleting elements in one dimension by + // enumerating them. + // + // If we enumerate all of the elements, we should have zero + // elements in that dimension with the same number of elements + // in the other dimensions that we started with. + + dim_vector temp_dims; + temp_dims.resize (n_idx); + + for (int i = 0; i < n_idx; i++) + { + if (idx_is_colon (i)) + temp_dims (i) = lhs_dims (i); + else + temp_dims (i) = 0; + } + + resize (temp_dims); + } + else if (num_ones (idx_is_colon) == n_idx - 1) + { + // We have colons in all indices except for one. + // This index tells us which slice to delete + + int non_col = 0; + + // Find the non-colon column. + + for (int i = 0; i < n_idx; i++) + { + if (! idx_is_colon (i)) + non_col = i; + } + + // The length of the non-colon dimension. + + int non_col_dim = lhs_dims (non_col); + + idx(non_col).sort (true); + + int num_to_delete = idx(non_col).length (lhs_dims (non_col)); + + if (num_to_delete > 0) + { + int temp = num_ones(lhs_dims); + + if (non_col_dim == 1) + temp--; + + if (temp == n_idx - 1 && num_to_delete == non_col_dim) + { + // We have A with (1x1x4), where A(1,:,1:4) + // Delete all (0x0x0) + + dim_vector zero_dims (n_idx, 0); + + resize (zero_dims, rfv); + } + else + { + // New length of non-colon dimension + // (calculated in the next for loop) + + int new_dim = non_col_dim; + + int iidx = 0; + + for (int j = 0; j < non_col_dim; j++) + if (j == idx(non_col).elem (iidx)) + { + iidx++; + + new_dim--; + + if (iidx == num_to_delete) + break; + } + + // Creating the new nd array after deletions. + + if (new_dim > 0) + { + // Calculate number of elements in new array. + + int num_new_elem=1; + + for (int i = 0; i < n_idx; i++) + { + if (i == non_col) + num_new_elem *= new_dim; + + else + num_new_elem *= lhs_dims(i); + } + + T *new_data = new T [num_new_elem]; + + Array<int> result_idx (lhs_dims.length (), 0); + + dim_vector lhs_inc; + lhs_inc.resize (lhs_dims.length ()); + + for (int i = 0; i < lhs_dims.length (); i++) + lhs_inc(i) = lhs_dims(i) + 1; + + dim_vector new_lhs_dim = lhs_dims; + + new_lhs_dim(non_col) = new_dim; + + int num_elem = 1; + + int numidx = 0; + + int n = length (); + + for (int i =0; i < lhs_dims.length (); i++) + if (i != non_col) + num_elem *= lhs_dims (i); + + num_elem *= idx(non_col).capacity (); + + for (int i = 0; i < n; i++) + { + if (numidx < num_elem + && is_in (result_idx(non_col), idx(non_col))) + numidx++; + + else + { + Array<int> temp_result_idx = result_idx; + + int num_lgt + = how_many_lgt (result_idx(non_col), idx(non_col)); + + temp_result_idx(non_col) -= num_lgt; + + int kidx + = ::compute_index (temp_result_idx, new_lhs_dim); + + new_data[kidx] = elem (result_idx); + } + + increment_index (result_idx, lhs_dims); + } + + if (--rep->count <= 0) + delete rep; + + rep = new typename Array<T>::ArrayRep (new_data, + num_new_elem); + + dimensions = new_lhs_dim; + } + } + } + } + else if (num_ones(idx_is_colon) < n_idx) + { + (*current_liboctave_error_handler) + ("A null assignment can have only one non-colon index."); + } +} + +template <class T> +Array<T> +Array<T>::value (void) +{ + Array<T> retval; + + int n_idx = index_count (); + + if (n_idx == 2) + { + idx_vector *tmp = get_idx (); + + idx_vector idx_i = tmp[0]; + idx_vector idx_j = tmp[1]; + + retval = index (idx_i, idx_j); + } + else if (n_idx == 1) + { + retval = index (idx[0]); + } + else + (*current_liboctave_error_handler) + ("Array<T>::value: invalid number of indices specified"); + + clear_index (); + + return retval; +} + +template <class T> +Array<T> +Array<T>::index (idx_vector& idx_arg, int resize_ok, const T& rfv) const +{ + Array<T> retval; + + switch (ndims ()) + { + case 1: + retval = index1 (idx_arg, resize_ok, rfv); + break; + + case 2: + retval = index2 (idx_arg, resize_ok, rfv); + break; + + default: + { + Array<idx_vector> tmp (1, idx_arg); + + retval = index (tmp, resize_ok, rfv); + } + break; + } + + return retval; +} + +template <class T> +Array<T> +Array<T>::index1 (idx_vector& idx_arg, int resize_ok, const T& rfv) const +{ + Array<T> retval; + + int len = length (); + + int n = idx_arg.freeze (len, "vector", resize_ok); + + if (idx_arg) + { + if (idx_arg.is_colon_equiv (len)) + { + retval = *this; + } + else if (n == 0) + { + retval.resize_no_fill (0); + } + else if (len == 1 && n > 1 + && idx_arg.one_zero_only () + && idx_arg.ones_count () == n) + { + retval.resize (n, elem (0)); + } + else + { + retval.resize_no_fill (n); + + for (int i = 0; i < n; i++) + { + int ii = idx_arg.elem (i); + if (ii >= len) + retval.elem (i) = rfv; + else + retval.elem (i) = elem (ii); + } + } + } + + // idx_vector::freeze() printed an error message for us. + + return retval; +} + +template <class T> +Array<T> +Array<T>::index2 (idx_vector& idx_arg, int resize_ok, const T& rfv) const +{ + Array<T> retval; + + int nr = dim1 (); + int nc = dim2 (); + + int orig_len = nr * nc; + + int idx_orig_rows = idx_arg.orig_rows (); + int idx_orig_columns = idx_arg.orig_columns (); + + if (idx_arg.is_colon ()) + { + // Fast magic colon processing. + + int result_nr = nr * nc; + int result_nc = 1; + + retval = Array<T> (*this, dim_vector (result_nr, result_nc)); + } + else if (nr == 1 && nc == 1) + { + Array<T> tmp = Array<T>::index1 (idx_arg, resize_ok); + + if (tmp.length () != 0) + retval = Array<T> (tmp, dim_vector (idx_orig_rows, idx_orig_columns)); + else + retval = Array<T> (tmp, dim_vector (0, 0)); + } + else if (nr == 1 || nc == 1) + { + // If indexing a vector with a matrix, return value has same + // shape as the index. Otherwise, it has same orientation as + // indexed object. + + Array<T> tmp = index1 (idx_arg, resize_ok); + + int len = tmp.length (); + + if (len == 0) + { + if (idx_orig_rows == 0 || idx_orig_columns == 0) + retval = Array<T> (dim_vector (idx_orig_rows, idx_orig_columns)); + else if (nr == 1) + retval = Array<T> (dim_vector (1, 0)); + else + retval = Array<T> (dim_vector (0, 1)); + } + else + { + if (idx_orig_rows == 1 || idx_orig_columns == 1) + { + if (nr == 1) + retval = Array<T> (tmp, dim_vector (1, len)); + else + retval = Array<T> (tmp, dim_vector (len, 1)); + } + else + retval = Array<T> (tmp, dim_vector (idx_orig_rows, idx_orig_columns)); + } + } + else + { + if (liboctave_wfi_flag + && ! (idx_arg.one_zero_only () + && idx_orig_rows == nr + && idx_orig_columns == nc)) + (*current_liboctave_warning_handler) ("single index used for matrix"); + + // This code is only for indexing matrices. The vector + // cases are handled above. + + idx_arg.freeze (nr * nc, "matrix", resize_ok); + + if (idx_arg) + { + int result_nr = idx_orig_rows; + int result_nc = idx_orig_columns; + + if (idx_arg.one_zero_only ()) + { + result_nr = idx_arg.ones_count (); + result_nc = (result_nr > 0 ? 1 : 0); + } + + retval.resize_no_fill (result_nr, result_nc); + + int k = 0; + for (int j = 0; j < result_nc; j++) + { + for (int i = 0; i < result_nr; i++) + { + int ii = idx_arg.elem (k++); + if (ii >= orig_len) + retval.elem (i, j) = rfv; + else + { + int fr = ii % nr; + int fc = (ii - fr) / nr; + retval.elem (i, j) = elem (fr, fc); + } + } + } + } + // idx_vector::freeze() printed an error message for us. + } + + 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 +{ + Array<T> retval; + + int nr = dim1 (); + int nc = dim2 (); + + int n = idx_i.freeze (nr, "row", resize_ok); + int m = idx_j.freeze (nc, "column", resize_ok); + + if (idx_i && idx_j) + { + if (idx_i.orig_empty () || idx_j.orig_empty () || n == 0 || m == 0) + { + retval.resize_no_fill (n, m); + } + else if (idx_i.is_colon_equiv (nr) && idx_j.is_colon_equiv (nc)) + { + retval = *this; + } + else + { + retval.resize_no_fill (n, m); + + for (int j = 0; j < m; j++) + { + int jj = idx_j.elem (j); + for (int i = 0; i < n; i++) + { + int ii = idx_i.elem (i); + if (ii >= nr || jj >= nc) + retval.elem (i, j) = rfv; + else + retval.elem (i, j) = elem (ii, jj); + } + } + } + } + + // idx_vector::freeze() printed an error message for us. + + return retval; +} + +#include "ArrayN-inline.h" + +template <class T> +Array<T> +Array<T>::index (Array<idx_vector>& ra_idx, int resize_ok, const T& rfv) const +{ + Array<T> retval; + + int n_idx = ra_idx.length (); + + int n_dims = dimensions.length (); + + if (n_idx == n_dims) + { + dim_vector frozen_lengths = freeze (ra_idx, dimensions, resize_ok); + + if (frozen_lengths.length () == n_dims) + { + if (all_ok (ra_idx)) + { + 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)) + { + 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 + } + } + // 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"); + + return retval; +} + +// XXX FIXME XXX -- this is a mess. + +template <class LT, class RT> +int +assign (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv) +{ + int retval = 0; + + switch (lhs.ndims ()) + { + case 0: + { + if (lhs.index_count () < 3) + { + // kluge... + lhs.resize_no_fill (0, 0); + retval = assign2 (lhs, rhs, rfv); + } + else + retval = assignN (lhs, rhs, rfv); + } + break; + + case 1: + { + if (lhs.index_count () > 1) + retval = assignN (lhs, rhs, rfv); + else + retval = assign1 (lhs, rhs, rfv); + } + break; + + case 2: + { + if (lhs.index_count () > 2) + retval = assignN (lhs, rhs, rfv); + else + retval = assign2 (lhs, rhs, rfv); + } + break; + + default: + retval = assignN (lhs, rhs, rfv); + break; + } + + return retval; +} + +template <class LT, class RT> +int +assign1 (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv) +{ + int retval = 1; + + idx_vector *tmp = lhs.get_idx (); + + idx_vector lhs_idx = tmp[0]; + + int lhs_len = lhs.length (); + int rhs_len = rhs.length (); + + int n = lhs_idx.freeze (lhs_len, "vector", true, liboctave_wrore_flag); + + if (n != 0) + { + if (rhs_len == n || rhs_len == 1) + { + int max_idx = lhs_idx.max () + 1; + if (max_idx > lhs_len) + lhs.resize (max_idx, rfv); + } + + if (rhs_len == n) + { + for (int i = 0; i < n; i++) + { + int ii = lhs_idx.elem (i); + lhs.elem (ii) = rhs.elem (i); + } + } + else if (rhs_len == 1) + { + RT scalar = rhs.elem (0); + + for (int i = 0; i < n; i++) + { + int ii = lhs_idx.elem (i); + lhs.elem (ii) = scalar; + } + } + else + { + (*current_liboctave_error_handler) + ("A(I) = X: X must be a scalar or a vector with same length as I"); + + retval = 0; + } + } + else if (lhs_idx.is_colon ()) + { + if (lhs_len == 0) + { + lhs.resize_no_fill (rhs_len); + + for (int i = 0; i < rhs_len; i++) + lhs.elem (i) = rhs.elem (i); + } + else + (*current_liboctave_error_handler) + ("A(:) = X: A must be the same size as X"); + } + else if (! (rhs_len == 1 || rhs_len == 0)) + { + (*current_liboctave_error_handler) + ("A([]) = X: X must also be an empty matrix or a scalar"); + + retval = 0; + } + + lhs.clear_index (); + + return retval; +} + +#define MAYBE_RESIZE_LHS \ + do \ + { \ + int max_row_idx = idx_i_is_colon ? rhs_nr : idx_i.max () + 1; \ + int max_col_idx = idx_j_is_colon ? rhs_nc : idx_j.max () + 1; \ + \ + int new_nr = max_row_idx > lhs_nr ? max_row_idx : lhs_nr; \ + int new_nc = max_col_idx > lhs_nc ? max_col_idx : lhs_nc; \ + \ + lhs.resize_and_fill (new_nr, new_nc, rfv); \ + } \ + while (0) + +template <class LT, class RT> +int +assign2 (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv) +{ + int retval = 1; + + int n_idx = lhs.index_count (); + + int lhs_nr = lhs.rows (); + int lhs_nc = lhs.cols (); + + int rhs_nr = rhs.rows (); + int rhs_nc = rhs.cols (); + + idx_vector *tmp = lhs.get_idx (); + + idx_vector idx_i; + idx_vector idx_j; + + if (n_idx > 1) + idx_j = tmp[1]; + + if (n_idx > 0) + idx_i = tmp[0]; + + if (n_idx == 2) + { + int n = idx_i.freeze (lhs_nr, "row", true, liboctave_wrore_flag); + + int m = idx_j.freeze (lhs_nc, "column", true, liboctave_wrore_flag); + + int idx_i_is_colon = idx_i.is_colon (); + int idx_j_is_colon = idx_j.is_colon (); + + if (idx_i_is_colon) + n = lhs_nr > 0 ? lhs_nr : rhs_nr; + + if (idx_j_is_colon) + m = lhs_nc > 0 ? lhs_nc : rhs_nc; + + if (idx_i && idx_j) + { + if (rhs_nr == 0 && rhs_nc == 0) + { + lhs.maybe_delete_elements (idx_i, idx_j); + } + else + { + if (rhs_nr == 1 && rhs_nc == 1 && n > 0 && m > 0) + { + MAYBE_RESIZE_LHS; + + RT scalar = rhs.elem (0, 0); + + for (int j = 0; j < m; j++) + { + int jj = idx_j.elem (j); + for (int i = 0; i < n; i++) + { + int ii = idx_i.elem (i); + lhs.elem (ii, jj) = scalar; + } + } + } + else if (n == rhs_nr && m == rhs_nc) + { + if (n > 0 && m > 0) + { + MAYBE_RESIZE_LHS; + + for (int j = 0; j < m; j++) + { + int jj = idx_j.elem (j); + for (int i = 0; i < n; i++) + { + int ii = idx_i.elem (i); + lhs.elem (ii, jj) = rhs.elem (i, j); + } + } + } + } + else if (n == 0 && m == 0) + { + if (! ((rhs_nr == 1 && rhs_nc == 1) + || (rhs_nr == 0 && rhs_nc == 0))) + { + (*current_liboctave_error_handler) + ("A([], []) = X: X must be an empty matrix or a scalar"); + + retval = 0; + } + } + else + { + (*current_liboctave_error_handler) + ("A(I, J) = X: X must be a scalar or the number of elements in I must"); + (*current_liboctave_error_handler) + ("match the number of rows in X and the number of elements in J must"); + (*current_liboctave_error_handler) + ("match the number of columns in X"); + + retval = 0; + } + } + } + // idx_vector::freeze() printed an error message for us. + } + else if (n_idx == 1) + { + int lhs_is_empty = lhs_nr == 0 || lhs_nc == 0; + + if (lhs_is_empty || (lhs_nr == 1 && lhs_nc == 1)) + { + int lhs_len = lhs.length (); + + int n = idx_i.freeze (lhs_len, 0, true, liboctave_wrore_flag); + + if (idx_i) + { + if (rhs_nr == 0 && rhs_nc == 0) + { + if (n != 0 && (lhs_nr != 0 || lhs_nc != 0)) + lhs.maybe_delete_elements (idx_i); + } + else + { + if (liboctave_wfi_flag) + { + if (lhs_is_empty + && idx_i.is_colon () + && ! (rhs_nr == 1 || rhs_nc == 1)) + { + (*current_liboctave_warning_handler) + ("A(:) = X: X is not a vector or scalar"); + } + else + { + int idx_nr = idx_i.orig_rows (); + int idx_nc = idx_i.orig_columns (); + + if (! (rhs_nr == idx_nr && rhs_nc == idx_nc)) + (*current_liboctave_warning_handler) + ("A(I) = X: X does not have same shape as I"); + } + } + + if (assign1 ((Array<LT>&) lhs, (Array<RT>&) rhs, rfv)) + { + int len = lhs.length (); + + if (len > 0) + { + // The following behavior is much simplified + // over previous versions of Octave. It + // seems to be compatible with Matlab. + + lhs.dimensions = dim_vector (1, lhs.length ()); + } + else + lhs.dimensions = dim_vector (0, 0); + } + else + retval = 0; + } + } + // idx_vector::freeze() printed an error message for us. + } + else if (lhs_nr == 1) + { + idx_i.freeze (lhs_nc, "vector", true, liboctave_wrore_flag); + + if (idx_i) + { + if (rhs_nr == 0 && rhs_nc == 0) + lhs.maybe_delete_elements (idx_i); + else + { + if (assign1 ((Array<LT>&) lhs, (Array<RT>&) rhs, rfv)) + lhs.dimensions = dim_vector (1, lhs.length ()); + else + retval = 0; + } + } + // idx_vector::freeze() printed an error message for us. + } + else if (lhs_nc == 1) + { + idx_i.freeze (lhs_nr, "vector", true, liboctave_wrore_flag); + + if (idx_i) + { + if (rhs_nr == 0 && rhs_nc == 0) + lhs.maybe_delete_elements (idx_i); + else + { + if (assign1 ((Array<LT>&) lhs, (Array<RT>&) rhs, rfv)) + lhs.dimensions = dim_vector (lhs.length (), 1); + else + retval = 0; + } + } + // idx_vector::freeze() printed an error message for us. + } + else + { + if (liboctave_wfi_flag + && ! (idx_i.is_colon () + || (idx_i.one_zero_only () + && idx_i.orig_rows () == lhs_nr + && idx_i.orig_columns () == lhs_nc))) + (*current_liboctave_warning_handler) + ("single index used for matrix"); + + int len = idx_i.freeze (lhs_nr * lhs_nc, "matrix"); + + if (idx_i) + { + if (len == 0) + { + if (! ((rhs_nr == 1 && rhs_nc == 1) + || (rhs_nr == 0 && rhs_nc == 0))) + (*current_liboctave_error_handler) + ("A([]) = X: X must be an empty matrix or scalar"); + } + else if (len == rhs_nr * rhs_nc) + { + int k = 0; + for (int j = 0; j < rhs_nc; j++) + { + for (int i = 0; i < rhs_nr; i++) + { + int ii = idx_i.elem (k++); + int fr = ii % lhs_nr; + int fc = (ii - fr) / lhs_nr; + lhs.elem (fr, fc) = rhs.elem (i, j); + } + } + } + else if (rhs_nr == 1 && rhs_nc == 1 && len <= lhs_nr * lhs_nc) + { + RT scalar = rhs.elem (0, 0); + + for (int i = 0; i < len; i++) + { + int ii = idx_i.elem (i); + int fr = ii % lhs_nr; + int fc = (ii - fr) / lhs_nr; + lhs.elem (fr, fc) = scalar; + } + } + else + { + (*current_liboctave_error_handler) + ("A(I) = X: X must be a scalar or a matrix with the same size as I"); + + retval = 0; + } + } + // idx_vector::freeze() printed an error message for us. + } + } + else + { + (*current_liboctave_error_handler) + ("invalid number of indices for matrix expression"); + + retval = 0; + } + + lhs.clear_index (); + + return retval; +} + +#define MAYBE_RESIZE_ND_DIMS \ + do \ + { \ + if (n_idx >= lhs_dims.length () && ! rhs_is_empty) \ + { \ + Array<int> max_idx (n_idx); \ + dim_vector new_idx; \ + new_idx.resize (n_idx); \ + \ + for (int i = 0; i < n_idx; i++) \ + { \ + if (lhs_dims.length () == 0 || i >= lhs_dims.length ()) \ + new_idx(i) = idx(i).max () + 1; \ + else \ + { \ + if (i < rhs_dims.length ()) \ + max_idx(i) = idx(i).is_colon () ? rhs_dims(i) : idx(i).max () + 1; \ + else \ + max_idx(i) = idx(i).max () + 1; \ + \ + new_idx(i) = max_idx(i) > lhs_dims(i) ? max_idx(i) : lhs_dims(i); \ + } \ + } \ + \ + lhs.resize (new_idx, rfv); \ + lhs_dims = lhs.dims (); \ + } \ + } \ + while (0) + +template <class LT, class RT> +int +assignN (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv) +{ + int retval = 1; + + int n_idx = lhs.index_count (); + + dim_vector lhs_dims = lhs.dims (); + dim_vector rhs_dims = rhs.dims (); + + idx_vector *tmp = lhs.get_idx (); + + Array<idx_vector> idx = conv_to_array (tmp, n_idx); + + // This needs to be defined before MAYBE_RESIZE_ND_DIMS. + + bool rhs_is_empty = rhs_dims.length () == 0 ? true : any_zero_len (rhs_dims); + + // Maybe expand to more dimensions. + + MAYBE_RESIZE_ND_DIMS; + + Array<int> idx_is_colon (n_idx, 0); + Array<int> idx_is_colon_equiv (n_idx, 0); + + for (int i = 0; i < n_idx; i++) + { + idx_is_colon_equiv(i) = idx(i).is_colon_equiv (lhs_dims(i), 1); + + idx_is_colon(i) = idx(i).is_colon (); + } + + int resize_ok = 1; + + dim_vector frozen_len; + + if (n_idx == lhs_dims.length ()) + frozen_len = freeze (idx, lhs_dims, resize_ok); + + bool rhs_is_scalar = is_scalar (rhs_dims); + + bool idx_is_empty = any_zero_len (frozen_len); + + if (rhs_is_empty) + { + lhs.maybe_delete_elements (idx, rfv); + } + else if (rhs_is_scalar) + { + if (n_idx == 0) + (*current_liboctave_error_handler) + ("number of indices is zero."); + + else if (n_idx < lhs_dims.length ()) + { + // Number of indices is less than dimensions. + + 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."); + } + else + { + // Fewer indices than dimensions, no colons. + + bool resize = false; + + // Subtract one since the last idx do not tell us + // anything about dimensionality. + + for (int i = 0; i < idx.length () - 1; i++) + { + // Subtract one since idx counts from 0 while dims + // count from 1. + + if (idx(i).elem (0) + 1 > lhs_dims(i)) + resize = true; + } + + if (resize) + { + dim_vector new_dims; + new_dims.resize (lhs_dims.length ()); + + for (int i = 0; i < lhs_dims.length (); i++) + { + if (i < idx.length () - 1 + && idx(i).elem (0) + 1 > lhs_dims(i)) + new_dims(i) = idx(i).elem (0)+1; + else + new_dims(i) = lhs_dims(i); + } + + lhs.resize (new_dims, rfv); + + lhs_dims = lhs.dims (); + } + + Array<int> one_arg_temp (1, 0); + + RT scalar = rhs.elem (one_arg_temp); + + Array<int> int_arr = conv_to_int_array (idx); + + int numelem = get_scalar_idx (int_arr, lhs_dims); + + if (numelem > lhs.length () || numelem < 0) + (*current_liboctave_error_handler) + ("attempt to grow array along ambiguous dimension."); + else + lhs.Array<LT>::checkelem (numelem) = scalar; + } + } + else + { + // Scalar to matrix assignment with as many indices as lhs + // dimensions. + + int n = Array<LT>::get_size (frozen_len); + + Array<int> result_idx (lhs_dims.length (), 0); + + Array<int> elt_idx; + + RT scalar = rhs.elem (0); + + for (int i = 0; i < n; i++) + { + elt_idx = get_elt_idx (idx, result_idx); + + dim_vector lhs_inc; + lhs_inc.resize (lhs_dims.length ()); + + for (int i = 0; i < lhs_dims.length (); i++) + lhs_inc(i) = lhs_dims(i) + 1; + + if (index_in_bounds(elt_idx, lhs_inc)) + lhs.checkelem (elt_idx) = scalar; + else + lhs.checkelem (elt_idx) = rfv; + + increment_index (result_idx, frozen_len); + } + } + } + else if (rhs_dims.length () >= 2) + { + // RHS is matrix or higher dimension. + + // 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)) + { + (*current_liboctave_error_handler) + ("dimensions do not match in matrix assignment."); + } + else + { + bool dim_ok(true); + + int jj = 0; + + // Check that RHS dimensions are the same length as the + // corresponding LHS dimensions. + + for (int j = 0; j < idx_is_colon.length (); j++) + { + if (idx_is_colon(j) || idx_is_colon_equiv(j)) + { + if (rhs_dims(jj) < lhs_dims(j)) + { + dim_ok = false; + + break; + } + + jj++; + } + } + + if (! dim_ok) + (*current_liboctave_error_handler) + ("subscripted assignment dimension mismatch."); + else + { + dim_vector new_dims; + new_dims.resize (n_idx); + + bool resize = false; + + int ii = 0; + + // Update idx vectors. + + for (int i = 0; i < n_idx; i++) + { + if (idx(i).is_colon ()) + { + // Add appropriate idx_vector to idx(i) since + // index with : contains no indexes. + + frozen_len(i) = lhs_dims(i) > rhs_dims(ii) ? lhs_dims(i) : rhs_dims(ii); + + new_dims(i) = lhs_dims(i) > rhs_dims(ii) ? lhs_dims(i) : rhs_dims(ii); + + ii++; + + Range idxrange (1, frozen_len(i), 1); + + idx_vector idxv (idxrange); + + idx(i) = idxv; + } + else + { + new_dims(i) = lhs_dims(i) > idx(i).max () + 1 ? lhs_dims(i) : idx(i).max () + 1; + + if (frozen_len(i) > 1) + ii++; + } + if (new_dims(i) != lhs_dims(i)) + resize = true; + } + + // Resize LHS if dimensions have changed. + + if (resize) + { + lhs.resize (new_dims, rfv); + + lhs_dims = lhs.dims (); + } + + // Number of elements which need to be set. + + int n = Array<LT>::get_size (frozen_len); + + Array<int> result_idx (lhs_dims.length (), 0); + Array<int> elt_idx; + + Array<int> result_rhs_idx (rhs_dims.length (), 0); + + dim_vector frozen_rhs; + frozen_rhs.resize (rhs_dims.length()); + + for (int i = 0; i < rhs_dims.length (); i++) + frozen_rhs(i) = rhs_dims(i); + + dim_vector lhs_inc; + lhs_inc.resize (lhs_dims.length ()); + + for (int i = 0; i < lhs_dims.length (); i++) + lhs_inc(i) = lhs_dims(i) + 1; + + for (int i = 0; i < n; i++) + { + elt_idx = get_elt_idx (idx, result_idx); + + if (index_in_bounds (elt_idx, lhs_inc)) + { + int s = compute_index (result_rhs_idx,rhs_dims); + + lhs.checkelem (elt_idx) = rhs.elem (s); + + increment_index (result_rhs_idx, frozen_rhs); + } + else + lhs.checkelem (elt_idx) = rfv; + + increment_index (result_idx, frozen_len); + } + } + } + } + else if (idx_is_empty) + { + // Assignment to matrix with at least one empty index. + + if (! rhs_is_empty || ! rhs_is_scalar) + { + (*current_liboctave_error_handler) + ("A([], []) = X: X must be an empty matrix or a scalar"); + + retval = 0; + } + } + else if (lhs_dims.length () != rhs_dims.length ()) + { + (*current_liboctave_error_handler) + ("A(I) = X: X must be a scalar or a matrix with the same size as I"); + retval = 0; + } + + lhs.clear_index (); + + return retval; +} + +template <class T> +void Array<T>::print_info (std::ostream& os, const std::string& prefix) const { os << prefix << "rep address: " << rep << "\n"
--- a/liboctave/Array.h +++ b/liboctave/Array.h @@ -66,8 +66,6 @@ int len; int count; - ArrayRep& operator = (const ArrayRep& a); - ArrayRep (T *d, int l) : data (d), len (l), count (1) { } ArrayRep (void) : data (0), len (0), count (1) { } @@ -86,7 +84,7 @@ for (int i = 0; i < len; i++) data[i] = a.data[i]; } - + ~ArrayRep (void) { delete [] data; } int length (void) const { return len; } @@ -105,6 +103,12 @@ { octave_qsort (data, static_cast<size_t> (len), sizeof (T), compare); } + + private: + + // No assignment! + + ArrayRep& operator = (const ArrayRep& a); }; //-------------------------------------------------------------------- @@ -238,6 +242,8 @@ static int get_size (int r, int c, int p); static int get_size (const dim_vector& dims); + int compute_index (const Array<int>& ra_idx) const; + T range_error (const char *fcn, int n) const; T& range_error (const char *fcn, int n); @@ -388,8 +394,6 @@ T operator () (const Array<int>& ra_idx) const { return elem (ra_idx); } #endif - int compute_index (const Array<int>& ra_idx) const; - protected: void resize_no_fill (int n); @@ -444,6 +448,8 @@ int ndims (void) const { return dimensions.length (); } + void maybe_delete_dims (void); + void clear_index (void); void set_index (const idx_vector& i); @@ -464,8 +470,6 @@ void maybe_delete_elements (Array<idx_vector>& ra_idx, const T& rfv); - void maybe_delete_dims (void); - Array<T> value (void); Array<T> index (idx_vector& i, int resize_ok = 0, @@ -485,8 +489,6 @@ // static T resize_fill_value (void) { return T (); } - void print_info (std::ostream& os, const std::string& prefix) const; - template <class LT, class RT> friend int assign (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv); @@ -502,6 +504,8 @@ template <class LT, class RT> friend int assignN (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv); + + void print_info (std::ostream& os, const std::string& prefix) const; }; template <class LT, class RT>
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,5 +1,8 @@ 2003-09-19 John W. Eaton <jwe@bevo.che.wisc.edu> + * Array.cc: Merge Array-idx.h. + * Array-idx.h: Delete. + * chNDArray.h, chNDArray.cc, boolNDArray.h, boolNDArray.cc: New files. * Array.h, Array-idx.h, Array.cc: Fold all N-d functionality here.
--- a/liboctave/Makefile.in +++ b/liboctave/Makefile.in @@ -26,18 +26,16 @@ endif MATRIX_INC := Array.h Array2.h Array3.h ArrayN.h DiagArray2.h \ - Array-flags.h Array-idx.h \ - ArrayN-idx.h ArrayN-inlines.h MArray-defs.h MArray.h \ - MArray2.h MDiagArray2.h Matrix.h MArrayN.h base-lu.h \ - dim-vector.h mx-base.h mx-op-defs.h mx-ops.h mx-defs.h \ - mx-ext.h CColVector.h CDiagMatrix.h CMatrix.h CNDArray.h \ - CRowVector.h CmplxAEPBAL.h CmplxCHOL.h CmplxDET.h \ - CmplxHESS.h CmplxLU.h CmplxQR.h CmplxQRP.h CmplxSCHUR.h \ - CmplxSVD.h EIG.h boolMatrix.h boolNDArray.h chMatrix.h \ - chNDArray.h dColVector.h \ - dDiagMatrix.h dMatrix.h dNDArray.h dRowVector.h \ - dbleAEPBAL.h dbleCHOL.h dbleDET.h dbleHESS.h dbleLU.h dbleQR.h \ - dbleQRP.h dbleSCHUR.h dbleSVD.h + Array-flags.h ArrayN-idx.h ArrayN-inlines.h MArray-defs.h \ + MArray.h MArray2.h MDiagArray2.h Matrix.h MArrayN.h \ + base-lu.h dim-vector.h mx-base.h mx-op-defs.h mx-ops.h \ + mx-defs.h mx-ext.h CColVector.h CDiagMatrix.h CMatrix.h \ + CNDArray.h CRowVector.h CmplxAEPBAL.h CmplxCHOL.h \ + CmplxDET.h CmplxHESS.h CmplxLU.h CmplxQR.h CmplxQRP.h \ + CmplxSCHUR.h CmplxSVD.h EIG.h boolMatrix.h boolNDArray.h \ + chMatrix.h chNDArray.h dColVector.h dDiagMatrix.h dMatrix.h \ + dNDArray.h dRowVector.h dbleAEPBAL.h dbleCHOL.h dbleDET.h \ + dbleHESS.h dbleLU.h dbleQR.h dbleQRP.h dbleSCHUR.h dbleSVD.h MX_OP_INC := mx-cdm-cm.h mx-cdm-cs.h mx-cdm-dm.h mx-cdm-m.h \ mx-cdm-s.h mx-cm-cdm.h mx-cm-dm.h mx-cm-m.h mx-cm-s.h \