Mercurial > hg > octave-jordi
changeset 4513:508238e65af7
[project @ 2003-09-19 21:40:57 by jwe]
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2003-09-19 John W. Eaton <jwe@bevo.che.wisc.edu> + + * configure.in (AH_BOTTOM): Don't define HEAVYWEIGHT_INDEXING here. + 2003-07-30 John W. Eaton <jwe@bevo.che.wisc.edu> * emacs/octave-mod.el (octave-variables): Delete
--- a/configure.in +++ b/configure.in @@ -22,7 +22,7 @@ ### 02111-1307, USA. AC_INIT -AC_REVISION($Revision: 1.431 $) +AC_REVISION($Revision: 1.432 $) AC_PREREQ(2.52) AC_CONFIG_SRCDIR([src/octave.cc]) AC_CONFIG_HEADER(config.h) @@ -1350,8 +1350,6 @@ #define X_CAST(T, E) (T) (E) -#define HEAVYWEIGHT_INDEXING 1 - #if defined(HAVE_F2C) && !defined(F77_FUNC) # define F77_FUNC(x,X) x ## _ # define F77_FUNC_(x,X) x ## __
--- a/liboctave/Array-C.cc +++ b/liboctave/Array-C.cc @@ -50,6 +50,8 @@ template class Array2<Complex>; +#if 0 + template int assign (Array2<Complex>&, const Array2<Complex>&); template int assign (Array2<Complex>&, const Array2<double>&); template int assign (Array2<Complex>&, const Array2<int>&); @@ -62,6 +64,15 @@ template int assign (Array2<Complex>&, const Array2<short>&, const Complex&); template int assign (Array2<Complex>&, const Array2<char>&, const Complex&); +#endif + +#include "ArrayN.h" +#include "ArrayN.cc" + +template class ArrayN<Complex>; + +template std::ostream& operator << (std::ostream&, const ArrayN<Complex>&); + #include "DiagArray2.h" #include "DiagArray2.cc"
--- a/liboctave/Array-b.cc +++ b/liboctave/Array-b.cc @@ -40,10 +40,21 @@ template class Array2<bool>; +#if 0 + template int assign (Array2<bool>&, const Array2<bool>&); template int assign (Array2<bool>&, const Array2<bool>&, const bool&); +#endif + +#include "ArrayN.h" +#include "ArrayN.cc" + +template class ArrayN<bool>; + +template std::ostream& operator << (std::ostream&, const ArrayN<bool>&); + #include "DiagArray2.h" #include "DiagArray2.cc"
--- a/liboctave/Array-ch.cc +++ b/liboctave/Array-ch.cc @@ -40,10 +40,21 @@ template class Array2<char>; +#if 0 + template int assign (Array2<char>&, const Array2<char>&); template int assign (Array2<char>&, const Array2<char>&, const char&); +#endif + +#include "ArrayN.h" +#include "ArrayN.cc" + +template class ArrayN<char>; + +template std::ostream& operator << (std::ostream&, const ArrayN<char>&); + #include "DiagArray2.h" #include "DiagArray2.cc"
--- a/liboctave/Array-d.cc +++ b/liboctave/Array-d.cc @@ -46,6 +46,8 @@ template class Array2<double>; +#if 0 + template int assign (Array2<double>&, const Array2<double>&); template int assign (Array2<double>&, const Array2<int>&); template int assign (Array2<double>&, const Array2<short>&); @@ -56,11 +58,15 @@ template int assign (Array2<double>&, const Array2<short>&, const double&); template int assign (Array2<double>&, const Array2<char>&, const double&); +#endif + #include "ArrayN.h" #include "ArrayN.cc" template class ArrayN<double>; +#if 0 + template int assign (ArrayN<double>&, const ArrayN<double>&); template int assign (ArrayN<double>&, const ArrayN<int>&); template int assign (ArrayN<double>&, const ArrayN<short>&); @@ -71,6 +77,8 @@ template int assign (ArrayN<double>&, const ArrayN<short>&, const double&); template int assign (ArrayN<double>&, const ArrayN<char>&, const double&); +#endif + template std::ostream& operator << (std::ostream&, const ArrayN<double>&); #include "DiagArray2.h"
--- a/liboctave/Array-flags.cc +++ b/liboctave/Array-flags.cc @@ -28,13 +28,9 @@ // These have to be defined somewhere, but only once. -#if defined (HEAVYWEIGHT_INDEXING) - bool liboctave_wfi_flag = false; bool liboctave_wrore_flag = false; -#endif - /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/liboctave/Array-i.cc +++ b/liboctave/Array-i.cc @@ -44,6 +44,8 @@ template class Array2<int>; +#if 0 + template int assign (Array2<int>&, const Array2<int>&); template int assign (Array2<int>&, const Array2<short>&); template int assign (Array2<int>&, const Array2<char>&); @@ -52,6 +54,8 @@ template int assign (Array2<int>&, const Array2<short>&, const int&); template int assign (Array2<int>&, const Array2<char>&, const int&); +#endif + #include "DiagArray2.h" #include "DiagArray2.cc"
--- a/liboctave/Array-idx.h +++ b/liboctave/Array-idx.h @@ -22,6 +22,7 @@ */ #include "Array-flags.h" +#include "Range.h" #include "idx-vector.h" #include "lo-error.h" @@ -38,19 +39,27 @@ void Array<T>::set_index (const idx_vector& idx_arg) { - if (! idx) - idx = new idx_vector [max_indices]; + int nd = ndims (); - if (idx_count < max_indices) + if (! idx && nd > 0) + idx = new idx_vector [nd]; + + if (idx_count < nd) { idx[idx_count++] = idx_arg; } else { - (*current_liboctave_error_handler) - ("invalid number of indices specified"); + idx_vector *new_idx = new idx_vector [idx_count+1]; + + for (int i = 0; i < idx_count; i++) + new_idx[i] = idx[i]; - clear_index (); + new_idx[idx_count++] = idx_arg; + + delete [] idx; + + idx = new_idx; } } @@ -60,7 +69,24 @@ { Array<T> retval; - retval = index (idx[0]); + 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 (); @@ -73,6 +99,34 @@ { 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); @@ -85,7 +139,7 @@ } else if (n == 0) { - retval.resize (0); + retval.resize_no_fill (0); } else if (len == 1 && n > 1 && idx_arg.one_zero_only () @@ -95,7 +149,7 @@ } else { - retval.resize (n); + retval.resize_no_fill (n); for (int i = 0; i < n; i++) { @@ -114,16 +168,280 @@ } 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 (0); + resize_no_fill (0); else { int num_to_delete = idx_arg.length (len); @@ -166,7 +484,8 @@ rep = new typename Array<T>::ArrayRep (new_data, new_len); - set_max_indices (1); + dimensions.resize (1); + dimensions(0) = new_len; } else (*current_liboctave_error_handler) @@ -175,13 +494,539 @@ } } -// ??? FIXME ??? -- this does not handle assignment of empty vectors -// to delete elements. Should it? +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 (); @@ -232,7 +1077,7 @@ { if (lhs_len == 0) { - lhs.resize (rhs_len); + lhs.resize_no_fill (rhs_len); for (int i = 0; i < rhs_len; i++) lhs.elem (i) = rhs.elem (i); @@ -245,7 +1090,625 @@ { (*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; }
--- a/liboctave/Array-s.cc +++ b/liboctave/Array-s.cc @@ -42,12 +42,16 @@ template class Array2<short>; +#if 0 + template int assign (Array2<short>&, const Array2<short>&); template int assign (Array2<short>&, const Array2<char>&); template int assign (Array2<short>&, const Array2<short>&, const short&); template int assign (Array2<short>&, const Array2<char>&, const short&); +#endif + #include "DiagArray2.h" #include "DiagArray2.cc"
--- a/liboctave/Array.cc +++ b/liboctave/Array.cc @@ -34,140 +34,220 @@ #include <iostream> #include "Array.h" - -#if defined (HEAVYWEIGHT_INDEXING) +#include "Array-idx.h" #include "idx-vector.h" -#include "Array-idx.h" -#endif - #include "lo-error.h" // One dimensional array class. Handles the reference counting for // all the derived classes. template <class T> -Array<T>::Array (int n, const T& val) -{ - rep = new typename Array<T>::ArrayRep (n); - - for (int i = 0; i < n; i++) - rep->data[i] = val; - -#ifdef HEAVYWEIGHT_INDEXING - max_indices = 1; - idx_count = 0; - idx = 0; -#endif -} - -template <class T> Array<T>::~Array (void) { if (--rep->count <= 0) delete rep; -#ifdef HEAVYWEIGHT_INDEXING delete [] idx; -#endif +} + +// A guess (should be quite conservative). +#define MALLOC_OVERHEAD 1024 + +template <class T> +int +Array<T>::get_size (int r, int c) +{ + // XXX KLUGE XXX + + // If an allocation of an array with r * c elements of type T + // would cause an overflow in the allocator when computing the + // size of the allocation, then return a value which, although + // not equivalent to the actual request, should be too large for + // most current hardware, but not so large to cause the + // allocator to barf on computing retval * sizeof (T). + + static int nl; + static double dl + = frexp (static_cast<double> + (INT_MAX - MALLOC_OVERHEAD) / sizeof (T), &nl); + + // This value should be an integer. If we return this value and + // things work the way we expect, we should be paying a visit to + // new_handler in no time flat. + static int max_items = static_cast<int> (ldexp (dl, nl)); + + int nr, nc; + double dr = frexp (static_cast<double> (r), &nr); + double dc = frexp (static_cast<double> (c), &nc); + + int nt = nr + nc; + double dt = dr * dc; + + if (dt <= 0.5) + { + nt--; + dt *= 2; + + if (dt <= 0.5) + nt--; + } + + return (nt < nl || (nt == nl && dt < dl)) ? r * c : max_items; } template <class T> -Array<T>& -Array<T>::operator = (const Array<T>& a) +int +Array<T>::get_size (int r, int c, int p) { - if (this != &a && rep != a.rep) + // XXX KLUGE XXX + + // If an allocation of an array with r * c * p elements of type T + // would cause an overflow in the allocator when computing the + // size of the allocation, then return a value which, although + // not equivalent to the actual request, should be too large for + // most current hardware, but not so large to cause the + // allocator to barf on computing retval * sizeof (T). + + static int nl; + static double dl + = frexp (static_cast<double> + (INT_MAX - MALLOC_OVERHEAD) / sizeof (T), &nl); + + // This value should be an integer. If we return this value and + // things work the way we expect, we should be paying a visit to + // new_handler in no time flat. + static int max_items = static_cast<int> (ldexp (dl, nl)); + + int nr, nc, np; + double dr = frexp (static_cast<double> (r), &nr); + double dc = frexp (static_cast<double> (c), &nc); + double dp = frexp (static_cast<double> (p), &np); + + int nt = nr + nc + np; + double dt = dr * dc * dp; + + if (dt <= 0.5) { - if (--rep->count <= 0) - delete rep; + nt--; + dt *= 2; - rep = a.rep; - rep->count++; + if (dt <= 0.5) + nt--; } -#ifdef HEAVYWEIGHT_INDEXING - idx_count = 0; - idx = 0; -#endif - - return *this; + return (nt < nl || (nt == nl && dt < dl)) ? r * c * p : max_items; } template <class T> -void -Array<T>::resize (int n) +int +Array<T>::get_size (const dim_vector& ra_idx) { - if (n < 0) + // XXX KLUGE XXX + + // If an allocation of an array with r * c elements of type T + // would cause an overflow in the allocator when computing the + // size of the allocation, then return a value which, although + // not equivalent to the actual request, should be too large for + // most current hardware, but not so large to cause the + // allocator to barf on computing retval * sizeof (T). + + static int nl; + static double dl + = frexp (static_cast<double> + (INT_MAX - MALLOC_OVERHEAD) / sizeof (T), &nl); + + // This value should be an integer. If we return this value and + // things work the way we expect, we should be paying a visit to + // new_handler in no time flat. + + static int max_items = static_cast<int> (ldexp (dl, nl)); + + int retval = max_items; + + int n = ra_idx.length (); + + int nt = 0; + double dt = 1; + + for (int i = 0; i < n; i++) { - (*current_liboctave_error_handler) ("can't resize to negative dimension"); - return; + int nra_idx; + double dra_idx = frexp (static_cast<double> (ra_idx(i)), &nra_idx); + + nt += nra_idx; + dt *= dra_idx; } - if (n == length ()) - return; - - typename Array<T>::ArrayRep *old_rep = rep; - const T *old_data = data (); - int old_len = length (); + if (dt <= 0.5) + { + nt--; + dt *= 2; - rep = new typename Array<T>::ArrayRep (n); - - if (old_data && old_len > 0) - { - int min_len = old_len < n ? old_len : n; - - for (int i = 0; i < min_len; i++) - xelem (i) = old_data[i]; + if (dt <= 0.5) + nt--; } - if (--old_rep->count <= 0) - delete old_rep; + if (nt < nl || (nt == nl && dt < dl)) + { + retval = 1; + + for (int i = 0; i < n; i++) + retval *= ra_idx(i); + } + + return retval; } +#undef MALLOC_OVERHEAD + template <class T> -void -Array<T>::resize (int n, const T& val) +int +Array<T>::compute_index (const Array<int>& ra_idx) const { - if (n < 0) + int retval = -1; + + int n = dimensions.length (); + + if (n > 0 && n == ra_idx.length ()) { - (*current_liboctave_error_handler) ("can't resize to negative dimension"); - return; - } - - if (n == length ()) - return; - - typename Array<T>::ArrayRep *old_rep = rep; - const T *old_data = data (); - int old_len = length (); + retval = ra_idx(--n); - rep = new typename Array<T>::ArrayRep (n); - - int min_len = old_len < n ? old_len : n; + while (--n >= 0) + { + retval *= dimensions(n); + retval += ra_idx(n); + } + } + else + (*current_liboctave_error_handler) + ("Array<T>::compute_index: invalid ra_idxing operation"); - if (old_data && old_len > 0) - { - for (int i = 0; i < min_len; i++) - xelem (i) = old_data[i]; - } - - for (int i = old_len; i < n; i++) - xelem (i) = val; - - if (--old_rep->count <= 0) - delete old_rep; + return retval; } +#if 0 + template <class T> -T * -Array<T>::fortran_vec (void) +int +Array<T>::compute_index (int i, int j) const { - if (rep->count > 1) - { - --rep->count; - rep = new typename Array<T>::ArrayRep (*rep); - } - return rep->data; + 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 @@ -186,6 +266,572 @@ } template <class T> +T +Array<T>::range_error (const char *fcn, int i, int j) const +{ + (*current_liboctave_error_handler) + ("%s (%d, %d): range error", fcn, i, j); + return T (); +} + +template <class T> +T& +Array<T>::range_error (const char *fcn, int i, int j) +{ + (*current_liboctave_error_handler) + ("%s (%d, %d): range error", fcn, i, j); + static T foo; + return foo; +} + +template <class T> +T +Array<T>::range_error (const char *fcn, int i, int j, int k) const +{ + (*current_liboctave_error_handler) + ("%s (%d, %d, %d): range error", fcn, i, j, k); + return T (); +} + +template <class T> +T& +Array<T>::range_error (const char *fcn, int i, int j, int k) +{ + (*current_liboctave_error_handler) + ("%s (%d, %d, %d): range error", fcn, i, j, k); + static T foo; + return foo; +} + +template <class T> +T +Array<T>::range_error (const char *fcn, const Array<int>& ra_idx) const +{ + // XXX FIXME XXX -- report index values too! + + (*current_liboctave_error_handler) ("range error in Array"); + + return T (); +} + +template <class T> +T& +Array<T>::range_error (const char *fcn, const Array<int>& ra_idx) +{ + // XXX FIXME XXX -- report index values too! + + (*current_liboctave_error_handler) ("range error in Array"); + + static T foo; + return foo; +} + +template <class T> +void +Array<T>::resize_no_fill (int n) +{ + if (n < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + + if (n == length ()) + return; + + typename Array<T>::ArrayRep *old_rep = rep; + const T *old_data = data (); + int old_len = length (); + + rep = new typename Array<T>::ArrayRep (n); + + dimensions = dim_vector (n); + + if (old_data && old_len > 0) + { + int min_len = old_len < n ? old_len : n; + + for (int i = 0; i < min_len; i++) + xelem (i) = old_data[i]; + } + + if (--old_rep->count <= 0) + delete old_rep; +} + +template <class T> +void +Array<T>::resize_no_fill (const dim_vector& dims) +{ + int n = dims.length (); + + for (int i = 0; i < n; i++) + { + if (dims(i) < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + } + + bool no_change = true; + + for (int i = 0; i < n; i++) + { + if (dims(i) != dimensions(i)) + { + no_change = false; + break; + } + } + + if (no_change) + return; + + int old_len = length (); + + typename Array<T>::ArrayRep *old_rep = rep; + const T *old_data = data (); + + rep = new typename Array<T>::ArrayRep (get_size (dims)); + + dim_vector old_dimensions = dimensions; + + dimensions = dims; + + Array<int> ra_idx (dimensions.length (), 0); + + for (int i = 0; i < old_len; i++) + { + if (index_in_bounds (ra_idx, dimensions)) + xelem (ra_idx) = old_data[i]; + + increment_index (ra_idx, dimensions); + } + + if (--old_rep->count <= 0) + delete old_rep; +} + +template <class T> +void +Array<T>::resize_no_fill (int r, int c) +{ + if (r < 0 || c < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + + if (r == dim1 () && c == dim2 ()) + return; + + typename Array<T>::ArrayRep *old_rep = Array<T>::rep; + const T *old_data = data (); + + int old_d1 = dim1 (); + int old_d2 = dim2 (); + int old_len = length (); + + rep = new typename Array<T>::ArrayRep (get_size (r, c)); + + dimensions = dim_vector (r, c); + + if (old_data && old_len > 0) + { + int min_r = old_d1 < r ? old_d1 : r; + int min_c = old_d2 < c ? old_d2 : c; + + for (int j = 0; j < min_c; j++) + for (int i = 0; i < min_r; i++) + xelem (i, j) = old_data[old_d1*j+i]; + } + + if (--old_rep->count <= 0) + delete old_rep; +} + +template <class T> +void +Array<T>::resize_no_fill (int r, int c, int p) +{ + if (r < 0 || c < 0 || p < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + + if (r == dim1 () && c == dim2 () && p == dim3 ()) + return; + + typename Array<T>::ArrayRep *old_rep = rep; + const T *old_data = data (); + + int old_d1 = dim1 (); + int old_d2 = dim2 (); + int old_d3 = dim3 (); + int old_len = length (); + + int ts = get_size (get_size (r, c), p); + + rep = new typename Array<T>::ArrayRep (ts); + + dimensions = dim_vector (r, c, p); + + if (old_data && old_len > 0) + { + int min_r = old_d1 < r ? old_d1 : r; + int min_c = old_d2 < c ? old_d2 : c; + int min_p = old_d3 < p ? old_d3 : p; + + for (int k = 0; k < min_p; k++) + for (int j = 0; j < min_c; j++) + for (int i = 0; i < min_r; i++) + xelem (i, j, k) = old_data[old_d1*(old_d2*k+j)+i]; + } + + if (--old_rep->count <= 0) + delete old_rep; +} + +template <class T> +void +Array<T>::resize_and_fill (int n, const T& val) +{ + if (n < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + + if (n == length ()) + return; + + typename Array<T>::ArrayRep *old_rep = rep; + const T *old_data = data (); + int old_len = length (); + + rep = new typename Array<T>::ArrayRep (n); + + dimensions = dim_vector (n); + + int min_len = old_len < n ? old_len : n; + + if (old_data && old_len > 0) + { + for (int i = 0; i < min_len; i++) + xelem (i) = old_data[i]; + } + + for (int i = old_len; i < n; i++) + xelem (i) = val; + + if (--old_rep->count <= 0) + delete old_rep; +} + +template <class T> +void +Array<T>::resize_and_fill (int r, int c, const T& val) +{ + if (r < 0 || c < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + + if (r == dim1 () && c == dim2 ()) + return; + + typename Array<T>::ArrayRep *old_rep = Array<T>::rep; + const T *old_data = data (); + + int old_d1 = dim1 (); + int old_d2 = dim2 (); + int old_len = length (); + + rep = new typename Array<T>::ArrayRep (get_size (r, c)); + + dimensions = dim_vector (r, c); + + int min_r = old_d1 < r ? old_d1 : r; + int min_c = old_d2 < c ? old_d2 : c; + + if (old_data && old_len > 0) + { + for (int j = 0; j < min_c; j++) + for (int i = 0; i < min_r; i++) + xelem (i, j) = old_data[old_d1*j+i]; + } + + for (int j = 0; j < min_c; j++) + for (int i = min_r; i < r; i++) + xelem (i, j) = val; + + for (int j = min_c; j < c; j++) + for (int i = 0; i < r; i++) + xelem (i, j) = val; + + if (--old_rep->count <= 0) + delete old_rep; +} + +template <class T> +void +Array<T>::resize_and_fill (int r, int c, int p, const T& val) +{ + if (r < 0 || c < 0 || p < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + + if (r == dim1 () && c == dim2 () && p == dim3 ()) + return; + + typename Array<T>::ArrayRep *old_rep = rep; + const T *old_data = data (); + + int old_d1 = dim1 (); + int old_d2 = dim2 (); + int old_d3 = dim3 (); + + int old_len = length (); + + int ts = get_size (get_size (r, c), p); + + rep = new typename Array<T>::ArrayRep (ts); + + dimensions = dim_vector (r, c, p); + + int min_r = old_d1 < r ? old_d1 : r; + int min_c = old_d2 < c ? old_d2 : c; + int min_p = old_d3 < p ? old_d3 : p; + + if (old_data && old_len > 0) + for (int k = 0; k < min_p; k++) + for (int j = 0; j < min_c; j++) + for (int i = 0; i < min_r; i++) + xelem (i, j, k) = old_data[old_d1*(old_d2*k+j)+i]; + + // XXX FIXME XXX -- if the copy constructor is expensive, this may + // win. Otherwise, it may make more sense to just copy the value + // everywhere when making the new ArrayRep. + + for (int k = 0; k < min_p; k++) + for (int j = min_c; j < c; j++) + for (int i = 0; i < min_r; i++) + xelem (i, j, k) = val; + + for (int k = 0; k < min_p; k++) + for (int j = 0; j < c; j++) + for (int i = min_r; i < r; i++) + xelem (i, j, k) = val; + + for (int k = min_p; k < p; k++) + for (int j = 0; j < c; j++) + for (int i = 0; i < r; i++) + xelem (i, j, k) = val; + + if (--old_rep->count <= 0) + delete old_rep; +} + +template <class T> +void +Array<T>::resize_and_fill (const dim_vector& dims, const T& val) +{ + int n = dims.length (); + + for (int i = 0; i < n; i++) + { + if (dims(i) < 0) + { + (*current_liboctave_error_handler) + ("can't resize to negative dimension"); + return; + } + } + + bool no_change = true; + + for (int i = 0; i < n; i++) + { + if (dims(i) != dimensions(i)) + { + no_change = false; + break; + } + } + + if (no_change) + return; + + typename Array<T>::ArrayRep *old_rep = rep; + const T *old_data = data (); + + int old_len = length (); + + int len = get_size (dims); + + rep = new typename Array<T>::ArrayRep (len); + + dim_vector old_dimensions = dimensions; + + dimensions = dims; + + Array<int> ra_idx (dimensions.length (), 0); + + // XXX FIXME XXX -- it is much simpler to fill the whole array + // first, but probably slower for large arrays, or if the assignment + // operator for the type T is expensive. OTOH, the logic for + // deciding whether an element needs the copied value or the filled + // value might be more expensive. + + for (int i = 0; i < len; i++) + rep->elem (i) = val; + + for (int i = 0; i < old_len; i++) + { + if (index_in_bounds (ra_idx, dimensions)) + xelem (ra_idx) = old_data[i]; + + increment_index (ra_idx, dimensions); + } + + if (--old_rep->count <= 0) + delete old_rep; +} + +template <class T> +Array<T>& +Array<T>::insert (const Array<T>& a, int r, int c) +{ + int a_rows = a.rows (); + int a_cols = a.cols (); + + if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ()) + { + (*current_liboctave_error_handler) ("range error for insert"); + return *this; + } + + for (int j = 0; j < a_cols; j++) + for (int i = 0; i < a_rows; i++) + elem (r+i, c+j) = a.elem (i, j); + + return *this; +} + +template <class T> +Array<T>& +Array<T>::insert (const Array<T>& a, const Array<int>& ra_idx) +{ + int n = ra_idx.length (); + + if (n == dimensions.length ()) + { + dim_vector a_dims = a.dims (); + + for (int i = 0; i < n; i++) + { + if (ra_idx(i) < 0 || ra_idx(i) + a_dims(i) > dimensions(i)) + { + (*current_liboctave_error_handler) + ("Array<T>::insert: range error for insert"); + return *this; + } + } + +#if 0 + // XXX FIXME XXX -- need to copy elements + + for (int j = 0; j < a_cols; j++) + for (int i = 0; i < a_rows; i++) + elem (r+i, c+j) = a.elem (i, j); +#endif + + } + else + (*current_liboctave_error_handler) + ("Array<T>::insert: invalid indexing operation"); + + return *this; +} + +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 +{ + int nr = dim1 (); + int nc = dim2 (); + + if (nr > 1 && nc > 1) + { + Array<T> result (dim_vector (nc, nr)); + + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + result.xelem (j, i) = xelem (i, j); + + return result; + } + else + { + // Fast transpose for vectors and empty matrices + return Array<T> (*this, dim_vector (nc, nr)); + } +} + +template <class T> +T * +Array<T>::fortran_vec (void) +{ + if (rep->count > 1) + { + --rep->count; + rep = new typename Array<T>::ArrayRep (*rep); + } + return rep->data; +} + +template <class T> void Array<T>::print_info (std::ostream& os, const std::string& prefix) const { @@ -193,6 +839,11 @@ << prefix << "rep->len: " << rep->len << "\n" << prefix << "rep->data: " << static_cast<void *> (rep->data) << "\n" << prefix << "rep->count: " << rep->count << "\n"; + + // 2D info: + // + // << prefix << "rows: " << rows () << "\n" + // << prefix << "cols: " << cols () << "\n"; } /*
--- a/liboctave/Array.h +++ b/liboctave/Array.h @@ -33,17 +33,11 @@ #include <iostream> +#include "dim-vector.h" #include "lo-utils.h" class idx_vector; -// For now, define this here if it is not already defined. Not doing -// this can result in bugs that are very hard to find. - -#ifndef HEAVYWEIGHT_INDEXING -#define HEAVYWEIGHT_INDEXING 1 -#endif - // One dimensional array class. Handles the reference counting for // all the derived classes. @@ -60,7 +54,9 @@ { protected: -// The real representation of all arrays. + //-------------------------------------------------------------------- + // The real representation of all arrays. + //-------------------------------------------------------------------- class ArrayRep { @@ -78,17 +74,29 @@ explicit ArrayRep (int n) : data (new T [n]), len (n), count (1) { } + explicit ArrayRep (int n, const T& val) + : data (new T [n]), len (n), count (1) + { + fill (val); + } + ArrayRep (const ArrayRep& a) : data (new T [a.len]), len (a.len), count (1) - { - for (int i = 0; i < len; i++) - data[i] = a.data[i]; - } + { + for (int i = 0; i < len; i++) + data[i] = a.data[i]; + } ~ArrayRep (void) { delete [] data; } int length (void) const { return len; } + void fill (const T& val) + { + for (int i = 0; i < len; i++) + data[i] = val; + } + T& elem (int n) { return data[n]; } T elem (int n) const { return data[n]; } @@ -99,6 +107,8 @@ } }; + //-------------------------------------------------------------------- + void make_unique (void) { if (rep->count > 1) @@ -108,80 +118,155 @@ } } -#ifdef HEAVYWEIGHT_INDEXING - idx_vector *idx; - int max_indices; - int idx_count; -#endif - -protected: + void make_unique (const T& val) + { + if (rep->count > 1) + { + --rep->count; + rep = new ArrayRep (rep->length (), val); + } + else + rep->fill (val); + } typename Array<T>::ArrayRep *rep; - Array (T *d, int l) - { - rep = new typename Array<T>::ArrayRep (d, l); + dim_vector dimensions; + + idx_vector *idx; + int idx_count; + + Array (T *d, int n) + : rep (new typename Array<T>::ArrayRep (d, n)), dimensions (n), + idx (0), idx_count (0) { } -#ifdef HEAVYWEIGHT_INDEXING - idx = 0; - max_indices = 1; - idx_count = 0; -#endif + Array (T *d, const dim_vector& dims) + : rep (new typename Array<T>::ArrayRep (d, get_size (dims))), + dimensions (dims), idx (0), idx_count (0) { } + +private: + + Array<T>::ArrayRep *nil_rep (void) const + { + static typename Array<T>::ArrayRep *nr + = new typename Array<T>::ArrayRep (); + + return nr; } public: Array (void) - { - rep = new typename Array<T>::ArrayRep (); - -#ifdef HEAVYWEIGHT_INDEXING - idx = 0; - max_indices = 1; - idx_count = 0; -#endif - } + : rep (nil_rep ()), dimensions (), + idx (0), idx_count (0) { rep->count++; } explicit Array (int n) - { - rep = new typename Array<T>::ArrayRep (n); + : rep (new typename Array<T>::ArrayRep (n)), dimensions (n), + idx (0), idx_count (0) { } -#ifdef HEAVYWEIGHT_INDEXING - idx = 0; - max_indices = 1; - idx_count = 0; -#endif + explicit Array (int n, const T& val) + : rep (new typename Array<T>::ArrayRep (n)), dimensions (n), + idx (0), idx_count (0) + { + fill (val); + } + + Array (const Array<T>& a) + : rep (a.rep), dimensions (a.dimensions), idx (0), idx_count (0) + { + rep->count++; } - Array (int n, const T& val); +public: + + Array (const dim_vector& dims) + : rep (new typename Array<T>::ArrayRep (get_size (dims))), + dimensions (dims), idx (0), idx_count (0) { } - Array (const Array<T>& a) + Array (const dim_vector& dims, const T& val) + : rep (new typename Array<T>::ArrayRep (get_size (dims))), + dimensions (dims), idx (0), idx_count (0) { - rep = a.rep; + fill (val); + } + + Array (const Array<T>& a, const dim_vector& dims) + : rep (a.rep), dimensions (dims), idx (0), idx_count (0) + { rep->count++; - -#ifdef HEAVYWEIGHT_INDEXING - max_indices = a.max_indices; - idx_count = 0; - idx = 0; -#endif } ~Array (void); - Array<T>& operator = (const Array<T>& a); + Array<T>& operator = (const Array<T>& a) + { + if (this != &a) + { + if (--rep->count <= 0) + delete rep; + + rep = a.rep; + rep->count++; + + dimensions = a.dimensions; + } + + idx_count = 0; + idx = 0; + + return *this; + } + + void fill (const T& val) { make_unique (val); } int capacity (void) const { return rep->length (); } - int length (void) const { return rep->length (); } + int length (void) const { return capacity (); } + int nelem (void) const { return capacity (); } + + int dim1 (void) const { return dimensions(0); } + int dim2 (void) const { return dimensions(1); } + int dim3 (void) const { return dimensions(2); } + + int rows (void) const { return dim1 (); } + int cols (void) const { return dim2 (); } + int columns (void) const { return dim2 (); } + int pages (void) const { return dim3 (); } + + dim_vector dims (void) const { return dimensions; } + + static int get_size (int r, int c); + static int get_size (int r, int c, int p); + static int get_size (const dim_vector& dims); T range_error (const char *fcn, int n) const; T& range_error (const char *fcn, int n); + T range_error (const char *fcn, int i, int j) const; + T& range_error (const char *fcn, int i, int j); + + T range_error (const char *fcn, int i, int j, int k) const; + T& range_error (const char *fcn, int i, int j, int k); + + T range_error (const char *fcn, const Array<int>& ra_idx) const; + T& range_error (const char *fcn, const Array<int>& ra_idx); + // No checking, even for multiple references, ever. T& xelem (int n) { return rep->elem (n); } T xelem (int n) const { return rep->elem (n); } + T& xelem (int i, int j) { return xelem (dim1()*j+i); } + T xelem (int i, int j) const { return xelem (dim1()*j+i); } + + T& xelem (int i, int j, int k) { return xelem (i, dim2()*k+j); } + T xelem (int i, int j, int k) const { return xelem (i, dim2()*k+j); } + + T& xelem (const Array<int>& ra_idx) + { return xelem (compute_index (ra_idx)); } + + T xelem (const Array<int>& ra_idx) const + { return xelem (compute_index (ra_idx)); } + // XXX FIXME XXX -- 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 // clean way to do it. @@ -197,16 +282,55 @@ } } + T& checkelem (int i, int j) + { + if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ()) + return range_error ("T& Array<T>::checkelem", i, j); + else + return elem (dim1()*j+i); + } + + T& checkelem (int i, int j, int k) + { + if (i < 0 || j < 0 || k < 0 || i >= dim1 () || j >= dim2 () || k >= dim3 ()) + return range_error ("T& Array<T>::checkelem", i, j, k); + else + return elem (i, dim2()*k+j); + } + + T& checkelem (const Array<int>& ra_idx) + { + int i = compute_index (ra_idx); + + if (i < 0) + return range_error ("T& Array<T>::checkelem", ra_idx); + else + return elem (i); + } + T& elem (int n) { make_unique (); return xelem (n); } + T& elem (int i, int j) { return elem (dim1()*j+i); } + + T& elem (int i, int j, int k) { return elem (i, dim2()*k+j); } + + T& elem (const Array<int>& ra_idx) + { return Array<T>::elem (compute_index (ra_idx)); } + #if defined (BOUNDS_CHECKING) T& operator () (int n) { return checkelem (n); } + T& operator () (int i, int j) { return checkelem (i, j); } + T& operator () (int i, int j, int k) { return checkelem (i, j, k); } + T& operator () (const Array<int>& ra_idx) { return checkelem (ra_idx); } #else T& operator () (int n) { return elem (n); } + T& operator () (int i, int j) { return elem (i, j); } + T& operator () (int i, int j, int k) { return elem (i, j, k); } + T& operator () (const Array<int>& ra_idx) { return elem (ra_idx); } #endif T checkelem (int n) const @@ -217,16 +341,91 @@ return xelem (n); } + T checkelem (int i, int j) const + { + if (i < 0 || j < 0 || i >= dim1 () || j >= dim2 ()) + return range_error ("T Array<T>::checkelem", i, j); + else + return elem (dim1()*j+i); + } + + T checkelem (int i, int j, int k) const + { + if (i < 0 || j < 0 || k < 0 || i >= dim1 () || j >= dim2 () || k >= dim3 ()) + return range_error ("T Array<T>::checkelem", i, j, k); + else + return Array<T>::elem (i, Array<T>::dim1()*k+j); + } + + T checkelem (const Array<int>& ra_idx) const + { + int i = compute_index (ra_idx); + + if (i < 0) + return range_error ("T Array<T>::checkelem", ra_idx); + else + return Array<T>::elem (i); + } + T elem (int n) const { return xelem (n); } + T elem (int i, int j) const { return elem (dim1()*j+i); } + + T elem (int i, int j, int k) const { return elem (i, dim2()*k+j); } + + T elem (const Array<int>& ra_idx) const + { return Array<T>::elem (compute_index (ra_idx)); } + #if defined (BOUNDS_CHECKING) T operator () (int n) const { return checkelem (n); } + T operator () (int i, int j) const { return checkelem (i, j); } + T operator () (int i, int j, int k) const { return checkelem (i, j, k); } + T operator () (const Array<int>& ra_idx) const { return checkelem (ra_idx); } #else T operator () (int n) const { return elem (n); } + T operator () (int i, int j) const { return elem (i, j); } + T operator () (int i, int j, int k) const { return elem (i, j, k); } + T operator () (const Array<int>& ra_idx) const { return elem (ra_idx); } #endif - void resize (int n); - void resize (int n, const T& val); + int compute_index (const Array<int>& ra_idx) const; + +protected: + + void resize_no_fill (int n); + + void resize_no_fill (int r, int c); + + void resize_no_fill (int r, int c, int p); + + void resize_no_fill (const dim_vector& dims); + + void resize_and_fill (int n, const T& val); + + void resize_and_fill (int r, int c, const T& val); + + void resize_and_fill (int r, int c, int p, const T& val); + + void resize_and_fill (const dim_vector& dims, const T& val); + +public: + + void resize (int n) { resize_no_fill (n); } + + // void resize (int n, const T& val) { resize_and_fill (n, val); } + + void resize (const dim_vector& dims) { resize_no_fill (dims); } + + void resize (const dim_vector& dims, const T& val) + { resize_and_fill (dims, val); } + + Array<T>& insert (const Array<T>& a, int r, int c); + + Array<T>& insert (const Array<T>& a, const Array<int>& dims); + + bool is_square (void) const { return (dim1 () == dim2 ()); } + + Array<T> transpose (void) const; const T *data (void) const { return rep->data; } @@ -243,9 +442,7 @@ return *this; } -#ifdef HEAVYWEIGHT_INDEXING - - void set_max_indices (int mi) { max_indices = mi; } + int ndims (void) const { return dimensions.length (); } void clear_index (void); @@ -257,28 +454,60 @@ void maybe_delete_elements (idx_vector& i); + void maybe_delete_elements_1 (idx_vector& i); + + void maybe_delete_elements_2 (idx_vector& i); + + void maybe_delete_elements (idx_vector& i, idx_vector& j); + + void maybe_delete_elements (idx_vector& i, idx_vector& j, idx_vector& k); + + 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, const T& rfv = resize_fill_value (T ())) const; -#endif + Array<T> index1 (idx_vector& i, int resize_ok = 0, + const T& rfv = resize_fill_value (T ())) const; + + Array<T> index2 (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; + + Array<T> index (Array<idx_vector>& ra_idx, int resize_ok = 0, + const T& rfv = resize_fill_value (T ())) const; // 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); + + template <class LT, class RT> + friend int + assign1 (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv); -template <class LT, class RT> -int -assign (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv); + template <class LT, class RT> + friend int + assign2 (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv); + template <class LT, class RT> + friend int + assignN (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv); +}; template <class LT, class RT> int assign (Array<LT>& lhs, const Array<RT>& rhs) { - // return assign (lhs, rhs, Array<LT>::resize_fill_value ()); return assign (lhs, rhs, resize_fill_value (LT ())); }
deleted file mode 100644 --- a/liboctave/Array2-idx.h +++ /dev/null @@ -1,783 +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 "idx-vector.h" -#include "lo-error.h" - -template <class T> -Array2<T> -Array2<T>::value (void) -{ - Array2<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]; - - return index (idx_i, idx_j); - } - else if (n_idx == 1) - { - return index (Array<T>::idx[0]); - } - else - (*current_liboctave_error_handler) - ("invalid number of indices for matrix expression"); - - clear_index (); - - return retval; -} - -template <class T> -Array2<T> -Array2<T>::index (idx_vector& idx_arg, int resize_ok, const T& rfv) const -{ - Array2<T> retval; - - int nr = d1; - int nc = d2; - - 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 = Array2<T> (*this, result_nr, result_nc); - } - else if (nr == 1 && nc == 1) - { - Array<T> tmp = Array<T>::index (idx_arg, resize_ok); - - if (tmp.length () != 0) - retval = Array2<T> (tmp, idx_orig_rows, idx_orig_columns); - else - retval = Array2<T> (tmp, 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 = Array<T>::index (idx_arg, resize_ok); - - int len = tmp.length (); - - if (len == 0) - { - if (idx_orig_rows == 0 || idx_orig_columns == 0) - retval = Array2<T> (idx_orig_rows, idx_orig_columns); - else if (nr == 1) - retval = Array2<T> (1, 0); - else - retval = Array2<T> (0, 1); - } - else - { - if (idx_orig_rows == 1 || idx_orig_columns == 1) - { - if (nr == 1) - retval = Array2<T> (tmp, 1, len); - else - retval = Array2<T> (tmp, len, 1); - } - else - retval = Array2<T> (tmp, 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 (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> -Array2<T> -Array2<T>::index (idx_vector& idx_i, idx_vector& idx_j, int resize_ok, - const T& rfv) const -{ - Array2<T> retval; - - int nr = d1; - int nc = d2; - - 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 (n, m); - } - else if (idx_i.is_colon_equiv (nr) && idx_j.is_colon_equiv (nc)) - { - retval = *this; - } - else - { - retval.resize (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; -} - -template <class T> -void -Array2<T>::maybe_delete_elements (idx_vector& idx_arg) -{ - int nr = d1; - int nc = d2; - - 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 (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); - - if (nr == 1) - { - d1 = 1; - d2 = new_n; - } - else - { - d1 = new_n; - d2 = 1; - } - - set_max_indices (2); - } - else - (*current_liboctave_error_handler) - ("A(idx) = []: index out of range"); - } -} - -template <class T> -void -Array2<T>::maybe_delete_elements (idx_vector& idx_i, idx_vector& idx_j) -{ - int nr = d1; - int nc = d2; - - 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 (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 (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 (0, nc); - return; - } - - if (idx_i.is_colon_equiv (nr, 1)) - { - if (idx_j.is_colon_equiv (nc, 1)) - resize (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 (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); - - d2 = new_nc; - - set_max_indices (2); - } - 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 (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 (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); - - d1 = new_nr; - - set_max_indices (2); - } - else - (*current_liboctave_error_handler) - ("A(idx) = []: index out of range"); - } - } - } - } -} - -#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 (new_nr, new_nc, rfv); \ - } \ - while (0) - -template <class LT, class RT> -int -assign (Array2<LT>& lhs, const Array2<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 (assign ((Array<LT>&) lhs, (Array<RT>&) rhs)) - { - 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.d1 = 1; - lhs.d2 = lhs.length (); - } - else - { - lhs.d1 = 0; - lhs.d2 = 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 (assign ((Array<LT>&) lhs, (Array<RT>&) rhs)) - lhs.d2 = 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 (assign ((Array<LT>&) lhs, (Array<RT>&) rhs)) - lhs.d1 = lhs.length (); - 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; -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/
deleted file mode 100644 --- a/liboctave/Array2.cc +++ /dev/null @@ -1,257 +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. - -*/ - -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <cassert> - -#include <iostream> - -#include "Array2.h" - -#if defined (HEAVYWEIGHT_INDEXING) -#include "idx-vector.h" -#include "Array2-idx.h" -#endif - -#include "lo-error.h" - -// Two dimensional array class. - -// A guess (should be quite conservative). -#define MALLOC_OVERHEAD 1024 - -template <class T> -int -Array2<T>::get_size (int r, int c) const -{ - // XXX KLUGE XXX - - // If an allocation of an array with r * c elements of type T - // would cause an overflow in the allocator when computing the - // size of the allocation, then return a value which, although - // not equivalent to the actual request, should be too large for - // most current hardware, but not so large to cause the - // allocator to barf on computing retval * sizeof (T). - - static int nl; - static double dl - = frexp (static_cast<double> - (INT_MAX - MALLOC_OVERHEAD) / sizeof (T), &nl); - - // This value should be an integer. If we return this value and - // things work the way we expect, we should be paying a visit to - // new_handler in no time flat. - static int max_items = static_cast<int> (ldexp (dl, nl)); - - int nr, nc; - double dr = frexp (static_cast<double> (r), &nr); - double dc = frexp (static_cast<double> (c), &nc); - - int nt = nr + nc; - double dt = dr * dc; - - if (dt <= 0.5) - { - nt--; - dt *= 2; - - if (dt <= 0.5) - nt--; - } - - return (nt < nl || (nt == nl && dt < dl)) ? r * c : max_items; -} - -#undef MALLOC_OVERHEAD - -template <class T> -T -Array2<T>::range_error (const char *fcn, int i, int j) const -{ - (*current_liboctave_error_handler) - ("%s (%d, %d): range error", fcn, i, j); - return T (); -} - -template <class T> -T& -Array2<T>::range_error (const char *fcn, int i, int j) -{ - (*current_liboctave_error_handler) - ("%s (%d, %d): range error", fcn, i, j); - static T foo; - return foo; -} - -template <class T> -void -Array2<T>::resize (int r, int c) -{ - if (r < 0 || c < 0) - { - (*current_liboctave_error_handler) - ("can't resize to negative dimension"); - return; - } - - if (r == dim1 () && c == dim2 ()) - return; - - typename Array<T>::ArrayRep *old_rep = Array<T>::rep; - const T *old_data = data (); - - int old_d1 = dim1 (); - int old_d2 = dim2 (); - int old_len = length (); - - Array<T>::rep = new typename Array<T>::ArrayRep (get_size (r, c)); - - d1 = r; - d2 = c; - - if (old_data && old_len > 0) - { - int min_r = old_d1 < r ? old_d1 : r; - int min_c = old_d2 < c ? old_d2 : c; - - for (int j = 0; j < min_c; j++) - for (int i = 0; i < min_r; i++) - xelem (i, j) = old_data[old_d1*j+i]; - } - - if (--old_rep->count <= 0) - delete old_rep; -} - -template <class T> -void -Array2<T>::resize (int r, int c, const T& val) -{ - if (r < 0 || c < 0) - { - (*current_liboctave_error_handler) - ("can't resize to negative dimension"); - return; - } - - if (r == dim1 () && c == dim2 ()) - return; - - typename Array<T>::ArrayRep *old_rep = Array<T>::rep; - const T *old_data = data (); - - int old_d1 = dim1 (); - int old_d2 = dim2 (); - int old_len = length (); - - Array<T>::rep = new typename Array<T>::ArrayRep (get_size (r, c)); - - d1 = r; - d2 = c; - - int min_r = old_d1 < r ? old_d1 : r; - int min_c = old_d2 < c ? old_d2 : c; - - if (old_data && old_len > 0) - { - for (int j = 0; j < min_c; j++) - for (int i = 0; i < min_r; i++) - xelem (i, j) = old_data[old_d1*j+i]; - } - - for (int j = 0; j < min_c; j++) - for (int i = min_r; i < r; i++) - xelem (i, j) = val; - - for (int j = min_c; j < c; j++) - for (int i = 0; i < r; i++) - xelem (i, j) = val; - - if (--old_rep->count <= 0) - delete old_rep; -} - -template <class T> -Array2<T>& -Array2<T>::insert (const Array2<T>& a, int r, int c) -{ - int a_rows = a.rows (); - int a_cols = a.cols (); - - if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ()) - { - (*current_liboctave_error_handler) ("range error for insert"); - return *this; - } - - for (int j = 0; j < a_cols; j++) - for (int i = 0; i < a_rows; i++) - elem (r+i, c+j) = a.elem (i, j); - - return *this; -} - -template <class T> -Array2<T> -Array2<T>::transpose (void) const -{ - if (d1 > 1 && d2 > 1) - { - Array2<T> result (d2, d1); - - for (int j = 0; j < d2; j++) - for (int i = 0; i < d1; i++) - result.xelem (j, i) = xelem (i, j); - - return result; - } - else - { - // Fast transpose for vectors and empty matrices - return Array2<T> (*this, d2, d1); - } -} - -template <class T> -void -Array2<T>::print_info (std::ostream& os, const std::string& prefix) const -{ - os << "\n" - << prefix << "rows: " << rows () << "\n" - << prefix << "cols: " << cols () << "\n"; - - Array<T>::print_info (os, prefix + " "); -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/
--- a/liboctave/Array2.h +++ b/liboctave/Array2.h @@ -46,58 +46,23 @@ { protected: - int get_size (int r, int c) const; + static int get_size (int r, int c) { return Array<T>::get_size (r, c); } - Array2 (T *d, int n, int m) : Array<T> (d, get_size (n, m)) - { - d1 = n; - d2 = m; - set_max_indices (2); - } + Array2 (T *d, int r, int c) : Array<T> (d, dim_vector (r, c)) { } public: - // These really need to be protected (and they will be in the - // future, so don't depend on them being here!), but they can't be - // until template friends work correctly in g++. - - int d1; - int d2; + Array2 (void) : Array<T> (dim_vector (0, 0)) { } - Array2 (void) : Array<T> () - { - d1 = 0; - d2 = 0; - set_max_indices (2); - } - - Array2 (int n, int m) : Array<T> (get_size (n, m)) - { - d1 = n; - d2 = m; - set_max_indices (2); - } + Array2 (int r, int c) : Array<T> (dim_vector (r, c)) { } - Array2 (int n, int m, const T& val) : Array<T> (get_size (n, m), val) - { - d1 = n; - d2 = m; - set_max_indices (2); - } + Array2 (int r, int c, const T& val) + : Array<T> (dim_vector (r, c), val) { } - Array2 (const Array2<T>& a) : Array<T> (a) - { - d1 = a.d1; - d2 = a.d2; - set_max_indices (2); - } + Array2 (const Array2<T>& a) : Array<T> (a, a.dims ()) { } - Array2 (const Array<T>& a, int n, int m) : Array<T> (a) - { - d1 = n; - d2 = m; - set_max_indices (2); - } + Array2 (const Array<T>& a, int r, int c) + : Array<T> (a, dim_vector (r, c)) { } ~Array2 (void) { } @@ -106,103 +71,44 @@ if (this != &a) { Array<T>::operator = (a); - d1 = a.d1; - d2 = a.d2; + + dimensions = a.dimensions; } return *this; } - int dim1 (void) const { return d1; } - int dim2 (void) const { return d2; } - - int rows (void) const { return d1; } - int cols (void) const { return d2; } - int columns (void) const { return d2; } - - T range_error (const char *fcn, int i, int j) const; - T& range_error (const char *fcn, int i, int j); + void resize (int r, int c) { resize_no_fill (r, c); } - // No checking of any kind, ever. - - T& xelem (int i, int j) { return Array<T>::xelem (d1*j+i); } - T xelem (int i, int j) const { return Array<T>::xelem (d1*j+i); } + void resize (int r, int c, const T& val) { resize_and_fill (r, c, val); } - // Note that the following element selection methods don't use - // xelem() because they need to make use of the code in - // Array<T>::elem() that checks the reference count. - - T& checkelem (int i, int j) + Array2<T>& insert (const Array2<T>& a, int r, int c) { - if (i < 0 || j < 0 || i >= d1 || j >= d2) - return range_error ("T& Array2<T>::checkelem", i, j); - else - return Array<T>::elem (d1*j+i); - } - - T& elem (int i, int j) { return Array<T>::elem (d1*j+i); } - -#if defined (BOUNDS_CHECKING) - T& operator () (int i, int j) { return checkelem (i, j); } -#else - T& operator () (int i, int j) { return elem (i, j); } -#endif - - T checkelem (int i, int j) const - { - if (i < 0 || j < 0 || i >= d1 || j >= d2) - return range_error ("T Array2<T>::checkelem", i, j); - else - return Array<T>::elem (d1*j+i); + Array<T>::insert (a, r, c); + return *this; } - T elem (int i, int j) const { return Array<T>::elem (d1*j+i); } - -#if defined (BOUNDS_CHECKING) - T operator () (int i, int j) const { return checkelem (i, j); } -#else - T operator () (int i, int j) const { return elem (i, j); } -#endif - - void resize (int n, int m); - void resize (int n, int m, const T& val); - - Array2<T>& insert (const Array2<T>& a, int r, int c); - - bool is_square (void) const { return (d1 == d2); } - - Array2<T> transpose (void) const; - -#ifdef HEAVYWEIGHT_INDEXING - - void maybe_delete_elements (idx_vector& i); - - void maybe_delete_elements (idx_vector& i, idx_vector& j); - - Array2<T> value (void); + Array2<T> transpose (void) const + { + Array<T> tmp = Array<T>::transpose (); + return Array2<T> (tmp, tmp.rows (), tmp.columns ()); + } Array2<T> index (idx_vector& i, int resize_ok = 0, - const T& rfv = resize_fill_value (T ())) const; + const T& rfv = resize_fill_value (T ())) const + { + Array<T> tmp = Array<T>::index (i, resize_ok, rfv); + return Array2<T> (tmp, tmp.rows (), tmp.columns ()); + } Array2<T> index (idx_vector& i, idx_vector& j, int resize_ok = 0, - const T& rfv = resize_fill_value (T ())) const; - -#endif - - void print_info (std::ostream& os, const std::string& prefix) const; + const T& rfv = resize_fill_value (T ())) const + { + Array<T> tmp = Array<T>::index (i, j, resize_ok, rfv); + return Array2<T> (tmp, tmp.rows (), tmp.columns ()); + } }; -template <class LT, class RT> -int -assign (Array2<LT>& lhs, const Array2<RT>& rhs, const LT& rfv); - -template <class LT, class RT> -int -assign (Array2<LT>& lhs, const Array2<RT>& rhs) -{ - return assign (lhs, rhs, resize_fill_value (LT ())); -} - #endif /*
deleted file mode 100644 --- a/liboctave/Array3-idx.h +++ /dev/null @@ -1,56 +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 "idx-vector.h" -#include "lo-error.h" - -template <class T> -void -Array3<T>::maybe_delete_elements (idx_vector&, idx_vector&, idx_vector&) -{ - assert (0); -} - -template <class T> -Array3<T> -Array3<T>::value (void) -{ - Array3<T> retval; - assert (0); - return retval; -} - -template <class LT, class RT> -int -assign (Array3<LT>&, const Array3<RT>&, const LT&) -{ - assert (0); - return 0; -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/
deleted file mode 100644 --- a/liboctave/Array3.cc +++ /dev/null @@ -1,161 +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. - -*/ - -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <cassert> - -#include <iostream> - -#include "Array3.h" - -#if defined (HEAVYWEIGHT_INDEXING) -#include "idx-vector.h" -#include "Array3-idx.h" -#endif - -#include "lo-error.h" - -// Three dimensional array class. - -template <class T> -void -Array3<T>::resize (int r, int c, int p) -{ - if (r < 0 || c < 0 || p < 0) - { - (*current_liboctave_error_handler) - ("can't resize to negative dimension"); - return; - } - - if (r == dim1 () && c == dim2 () && p == dim3 ()) - return; - - typename Array<T>::ArrayRep *old_rep = Array<T>::rep; - const T *old_data = data (); - - int old_d1 = dim1 (); - int old_d2 = dim2 (); - int old_d3 = dim3 (); - int old_len = length (); - - int ts = get_size (get_size (r, c), p); - - Array<T>::rep = new typename Array<T>::ArrayRep (ts); - - Array2<T>::d1 = r; - Array2<T>::d2 = c; - d3 = p; - - if (old_data && old_len > 0) - { - int min_r = old_d1 < r ? old_d1 : r; - int min_c = old_d2 < c ? old_d2 : c; - int min_p = old_d3 < p ? old_d3 : p; - - for (int k = 0; k < min_p; k++) - for (int j = 0; j < min_c; j++) - for (int i = 0; i < min_r; i++) - xelem (i, j, k) = old_data[old_d1*(old_d2*k+j)+i]; - } - - if (--old_rep->count <= 0) - delete old_rep; -} - -template <class T> -void -Array3<T>::resize (int r, int c, int p, const T& val) -{ - if (r < 0 || c < 0 || p < 0) - { - (*current_liboctave_error_handler) - ("can't resize to negative dimension"); - return; - } - - if (r == dim1 () && c == dim2 () && p == dim3 ()) - return; - - typename Array<T>::ArrayRep *old_rep = Array<T>::rep; - const T *old_data = data (); - - int old_d1 = dim1 (); - int old_d2 = dim2 (); - int old_d3 = dim3 (); - - int old_len = length (); - - int ts = get_size (get_size (r, c), p); - - Array<T>::rep = new typename Array<T>::ArrayRep (ts); - - Array2<T>::d1 = r; - Array2<T>::d2 = c; - d3 = p; - - int min_r = old_d1 < r ? old_d1 : r; - int min_c = old_d2 < c ? old_d2 : c; - int min_p = old_d3 < p ? old_d3 : p; - - if (old_data && old_len > 0) - for (int k = 0; k < min_p; k++) - for (int j = 0; j < min_c; j++) - for (int i = 0; i < min_r; i++) - xelem (i, j, k) = old_data[old_d1*(old_d2*k+j)+i]; - - // If the copy constructor is expensive, this may win. Otherwise, - // it may make more sense to just copy the value everywhere when - // making the new ArrayRep. - - for (int k = 0; k < min_p; k++) - for (int j = min_c; j < c; j++) - for (int i = 0; i < min_r; i++) - xelem (i, j, k) = val; - - for (int k = 0; k < min_p; k++) - for (int j = 0; j < c; j++) - for (int i = min_r; i < r; i++) - xelem (i, j, k) = val; - - for (int k = min_p; k < p; k++) - for (int j = 0; j < c; j++) - for (int i = 0; i < r; i++) - xelem (i, j, k) = val; - - if (--old_rep->count <= 0) - delete old_rep; -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/
--- a/liboctave/Array3.h +++ b/liboctave/Array3.h @@ -31,7 +31,7 @@ #include <cassert> #include <cstdlib> -#include "Array2.h" +#include "Array.h" #include "lo-error.h" class idx_vector; @@ -40,133 +40,50 @@ template <class T> class -Array3 : public Array2<T> +Array3 : public Array<T> { protected: - int d3; + static int get_size (int r, int c, int p) + { return Array<T>::get_size (r, c, p); } - Array3 (T *d, int n, int m, int k) : Array2<T> (d, n, get_size (m, k)) - { - Array2<T>::d2 = m; - d3 = k; - set_max_indices (3); - } + Array3 (T *d, int r, int c, int p) : Array<T> (d, dim_vector (r, c, p)) { } public: - Array3 (void) : Array2<T> () - { - Array2<T>::d2 = 0; - d3 = 0; - set_max_indices (3); - } + Array3 (void) : Array<T> (dim_vector (0, 0, 0)) { } - Array3 (int n, int m, int k) : Array2<T> (n, get_size (m, k)) - { - Array2<T>::d2 = m; - d3 = k; - set_max_indices (3); - } + Array3 (int r, int c, int p) : Array<T> (dim_vector (r, c, p)) { } - Array3 (int n, int m, int k, const T& val) : Array2<T> (n, m*k, val) - { - Array2<T>::d2 = m; - d3 = k; - set_max_indices (3); - } + Array3 (int r, int c, int p, const T& val) + : Array<T> (dim_vector (r, c, p), val) { } - Array3 (const Array3<T>& a) : Array2<T> (a) - { - Array2<T>::d2 = a.d2; - d3 = a.d3; - set_max_indices (3); - } + Array3 (const Array3<T>& a) + : Array<T> (a, a.dims ()) { } + + Array3 (const Array<T>& a, int r, int c, int p) + : Array<T> (a, dim_vector (r, c, p)) { } ~Array3 (void) { } Array3<T>& operator = (const Array3<T>& a) { - if (this != &a && Array<T>::rep != a.rep) + if (this != &a) { Array<T>::operator = (a); - Array2<T>::d1 = a.d1; - Array2<T>::d2 = a.d2; - d3 = a.d3; + + dimensions = a.dimensions; } return *this; } - int dim3 (void) const { return d3; } - - // No checking of any kind, ever. - - T& xelem (int i, int j, int k) { return Array2<T>::xelem (i, Array2<T>::d2*k+j); } - T xelem (int i, int j, int k) const { return Array2<T>::xelem (i, Array2<T>::d2*k+j); } - - // Note that the following element selection methods don't use - // xelem() because they need to make use of the code in - // Array<T>::elem() that checks the reference count. - - T& checkelem (int i, int j, int k) - { - if (i < 0 || j < 0 || k < 0 || i >= Array2<T>::d1 || j >= Array2<T>::d2 || k >= d3) - { - (*current_liboctave_error_handler) ("range error in Array3"); - static T foo; - return foo; - } - return Array2<T>::elem (i, Array2<T>::d2*k+j); - } - - T& elem (int i, int j, int k) { return Array2<T>::elem (i, Array2<T>::d2*k+j); } - -#if defined (BOUNDS_CHECKING) - T& operator () (int i, int j, int k) { return checkelem (i, j, k); } -#else - T& operator () (int i, int j, int k) { return elem (i, j, k); } -#endif + void resize (int r, int c, int p) { resize_no_fill (r, c, p); } - T checkelem (int i, int j, int k) const - { - if (i < 0 || j < 0 || k < 0 || i >= Array2<T>::d1 || j >= Array2<T>::d2 || k >= d3) - { - (*current_liboctave_error_handler) ("range error in Array3"); - return T (); - } - return Array2<T>::elem (i, Array2<T>::d1*k+j); - } - - T elem (int i, int j, int k) const { return Array2<T>::elem (i, Array2<T>::d2*k+j); } - -#if defined (BOUNDS_CHECKING) - T operator () (int i, int j, int k) const { return checkelem (i, j, k); } -#else - T operator () (int i, int j, int k) const { return elem (i, j, k); } -#endif - - void resize (int n, int m, int k); - void resize (int n, int m, int k, const T& val); - -#ifdef HEAVYWEIGHT_INDEXING - void maybe_delete_elements (idx_vector& i, idx_vector& j, idx_vector& k); - - Array3<T> value (void); -#endif + void resize (int r, int c, int p, const T& val) + { resize_and_fill (r, c, p, val); } }; -template <class LT, class RT> -int -assign (Array3<LT>& lhs, const Array3<RT>& rhs, const LT& rfv); - -template <class LT, class RT> -int -assign (Array3<LT>& lhs, const Array3<RT>& rhs) -{ - return assign (lhs, rhs, static_cast<LT> (0)); -} - #endif /*
--- a/liboctave/ArrayN-idx.h +++ b/liboctave/ArrayN-idx.h @@ -26,203 +26,7 @@ #include "idx-vector.h" #include "lo-error.h" -template <class T> -void -ArrayN<T>::maybe_delete_elements (Array<idx_vector>& idx, const T& rfv) -{ - int n_idx = idx.length (); - - Array<int> lhs_dims = dims (); - - Array<int> idx_is_colon (n_idx, 0); - Array<int> idx_is_colon_equiv (n_idx, 0); - - // 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). - - Array<int> zeros (n_idx, 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. - - Array<int> temp_dims (n_idx,0); - - 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) - - Array<int> 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); - Array<int> elt_idx; - - Array<int> lhs_inc (lhs_dims.length ()); - - for (int i = 0; i < lhs_dims.length (); i++) - lhs_inc(i) = lhs_dims(i) + 1; - - Array<int> 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 (--(Array<T>::rep)->count <= 0) - delete Array<T>::rep; - - Array<T>::rep = - new typename Array<T>::ArrayRep (new_data, num_new_elem); - - dimensions = new_lhs_dim; - - set_max_indices (new_lhs_dim.length ()); - } - } - } - } - else if (num_ones(idx_is_colon) < n_idx) - { - (*current_liboctave_error_handler) - ("A null assignment can have only one non-colon index."); - } -} +#if 0 template <class T> ArrayN<T> @@ -260,724 +64,8 @@ return retval; } -template <class T> -ArrayN<T> -ArrayN<T>::index (idx_vector& ra_idx, int resize_ok, const T& rfv) const -{ - ArrayN<T> retval; - assert (0); - return retval; -} - -static inline Array<int> -freeze (Array<idx_vector>& ra_idx, const Array<int>& dimensions, int resize_ok) -{ - Array<int> retval; - - int n = ra_idx.length (); - - assert (n == dimensions.length ()); - - retval.resize (n); - - for (int i = 0; i < n; i++) - retval(i) = ra_idx(i).freeze (dimensions(i), "XXX FIXME XXX", resize_ok); - - return retval; -} - -static inline bool -vector_equivalent (const Array<int>& ra_idx) -{ - int n = ra_idx.length (); - - bool found_first = false; - - for (int i = 0; i < n; i++) - { - if (ra_idx(i) != 1) - { - if (! found_first) - found_first = true; - else - return false; - } - } - - return true; -} - -static inline bool -equal_arrays (const Array<int> a, const Array<int> b) -{ - bool retval = true; - - if (a.length () != b.length ()) - retval = false; - else - { - for (int i = 0; i < a.length (); i++) - { - if (a(i) != b(i)) - retval = false; - } - } - - return retval; -} - -static inline bool -all_ok (const Array<idx_vector>& ra_idx) -{ - bool retval = true; - - int n = ra_idx.length (); - - for (int i = 0; i < n; i++) - { - if (! ra_idx(i)) - { - retval = false; - break; - } - } - - return retval; -} - -static inline bool -any_orig_empty (const Array<idx_vector>& ra_idx) -{ - bool retval = false; - - int n = ra_idx.length (); - - for (int i = 0; i < n; i++) - { - if (ra_idx(i).orig_empty ()) - { - retval = true; - break; - } - } - - return retval; -} - -static inline bool -any_zero_len (const Array<int>& frozen_lengths) -{ - bool retval = false; - - int n = frozen_lengths.length (); - - for (int i = 0; i < n; i++) - { - if (frozen_lengths(i) == 0) - { - retval = true; - break; - } - } - - return retval; -} - -static inline Array<int> -get_zero_len_size (const Array<int>& frozen_lengths, - const Array<int>& dimensions) -{ - Array<int> retval; - assert (0); - return retval; -} - -static inline bool -all_colon_equiv (const Array<idx_vector>& ra_idx, - const Array<int>& frozen_lengths) -{ - bool retval = true; - - int idx_n = ra_idx.length (); - - int n = frozen_lengths.length (); - - assert (idx_n == n); - - for (int i = 0; i < n; i++) - { - if (! ra_idx(i).is_colon_equiv (frozen_lengths(i))) - { - retval = false; - break; - } - } - - return retval; -} - -static inline bool -is_in (int num, const idx_vector& idx) -{ - int n = idx.capacity (); - - for (int i = 0; i < n; i++) - if (idx.elem (i) == num) - return true; - - return false; -} - -static inline int -how_many_lgt (const int num, idx_vector& idxv) -{ - int retval = 0; - - int n = idxv.capacity (); - - for (int i = 0; i < n; i++) - if (num > idxv.elem (i)) - retval++; - - return retval; -} - -static inline bool -all_ones (const Array<int> arr) -{ - bool retval = true; - - for (int i = 0; i < arr.length (); i++) - { - if (arr(i) != 1) - { - retval = false; - break; - } - } - - return retval; -} - -static Array<int> -get_elt_idx (const Array<idx_vector>& ra_idx, const Array<int>& result_idx) -{ - int n = ra_idx.length (); - - Array<int> retval (n); - - for (int i = 0; i < n; i++) - retval(i) = ra_idx(i).elem (result_idx(i)); - - return retval; -} - -template <class T> -ArrayN<T> -ArrayN<T>::index (Array<idx_vector>& ra_idx, int resize_ok, const T& rfv) const -{ - ArrayN<T> retval; - - int n_dims = dimensions.length (); - - Array<int> 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)) - { - Array<int> 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 - { -#if 0 - retval.resize (frozen_lengths); - - int n = Array<T>::get_size (frozen_lengths); - - Array<int> result_idx (n_dims, 0); - - for (int i = 0; i < n; i++) - { - Array<int> 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 - (*current_liboctave_error_handler) - ("invalid number of dimensions for N-dimensional array index"); - - return retval; -} - -#define MAYBE_RESIZE_ND_DIMS \ - do \ - { \ - if (n_idx >= lhs_dims.length () && ! rhs_is_empty) \ - { \ - Array<int> max_idx (n_idx); \ - Array<int> new_idx (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 -assign (ArrayN<LT>& lhs, const ArrayN<RT>& rhs, const LT& rfv) -{ - int retval = 1; - - int n_idx = lhs.index_count (); - - Array<int> lhs_dims = lhs.dims (); - Array<int> 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; - - Array<int> 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) - { - Array<int> new_dims (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 = ArrayN<LT>::get_size (frozen_len); - - Array<int> result_idx (lhs_dims.length (), 0); - - Array<int> elt_idx; - - Array<int> one_arg_temp(1,0); - RT scalar = rhs.elem (one_arg_temp); - - for (int i = 0; i < n; i++) - { - elt_idx = get_elt_idx (idx, result_idx); - - Array<int> lhs_inc(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 - { - Array<int> new_dims (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 = ArrayN<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); - Array<int> frozen_rhs (rhs_dims.length(), 0); - - for (int i = 0; i < rhs_dims.length (); i++) - frozen_rhs(i) = rhs_dims(i); - - Array<int> lhs_inc (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.Array<RT>::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; - } - - return retval; -} - -static inline int -get_scalar_idx (Array<int>& idx, Array<int>& dims) -{ - int retval (-1); - - int n = idx.length (); - - if (n > 0) - { - retval = idx(--n); - - while (--n >= 0) - { - retval *= dims (n); - - retval += idx(n); - } - } - return retval; -} - -static inline int -num_ones (const Array<int> ra_idx) -{ - int retval (0); - for (int i = 0; i < ra_idx.length (); i++) - { - if (ra_idx (i) == 1) - retval++; - } - return retval; -} - -static inline bool -is_scalar (const Array<int>& dim) -{ - bool retval = true; - - int n = dim.length (); - - if (n == 0) - { - retval = false; - } - else - { - for (int i = 0; i < n; i ++) - { - if (dim (i) != 1) - { - retval = false; - - break; - } - } - } - return retval; -} - -static inline bool -any_ones (const Array<int> arr) -{ - bool retval = false; - - for (int i = 0; i < arr.length (); i++) - { - if (arr (i) == 1) - { - retval = true; - - break; - } - } - return retval; -} - -static inline int -compute_index (const Array<int>& ra_idx, const Array<int>& dims) -{ - int retval = -1; - - int n = dims.length (); - - if (n > 0 && n == ra_idx.length ()) - { - retval = ra_idx(--n); - - 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; -} - -static inline Array<int> -conv_to_int_array (const Array<idx_vector>& a) -{ - Array<int> retval (a.length ()); - - for (int i = 0; i < a.length (); i++) - retval (i) = a(i).elem (0); - - return retval; -} - -static inline Array<idx_vector> -conv_to_array (const idx_vector *tmp, const int len) -{ - Array<idx_vector> retval (len); - - for (int i = 0; i < len; i++) - retval (i) = tmp[i]; - - return retval; -} /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/liboctave/ArrayN-inline.h +++ b/liboctave/ArrayN-inline.h @@ -21,8 +21,13 @@ */ +#ifndef octave_ArrayN_inline_h +#define octave_ArrayN_inline_h 1 + +#include "idx-vector.h" + static inline bool -index_in_bounds (const Array<int>& ra_idx, const Array<int>& dimensions) +index_in_bounds (const Array<int>& ra_idx, const dim_vector& dimensions) { bool retval = true; @@ -46,7 +51,7 @@ } static inline void -increment_index (Array<int>& ra_idx, const Array<int>& dimensions, +increment_index (Array<int>& ra_idx, const dim_vector& dimensions, int start_dimension = 0) { ra_idx(start_dimension)++; @@ -65,6 +70,334 @@ } } +static inline int +get_scalar_idx (Array<int>& idx, dim_vector& dims) +{ + int retval (-1); + + int n = idx.length (); + + if (n > 0) + { + retval = idx(--n); + + while (--n >= 0) + { + retval *= dims (n); + + retval += idx(n); + } + } + return retval; +} + +static inline int +num_ones (const Array<int>& ra_idx) +{ + int retval (0); + for (int i = 0; i < ra_idx.length (); i++) + { + if (ra_idx (i) == 1) + retval++; + } + return retval; +} + +static inline bool +is_scalar (const dim_vector& dim) +{ + bool retval = true; + + int n = dim.length (); + + if (n == 0) + { + retval = false; + } + else + { + for (int i = 0; i < n; i ++) + { + if (dim (i) != 1) + { + retval = false; + + break; + } + } + } + return retval; +} + +static inline bool +any_ones (const Array<int>& arr) +{ + bool retval = false; + + for (int i = 0; i < arr.length (); i++) + { + if (arr (i) == 1) + { + retval = true; + + break; + } + } + return retval; +} + +static inline int +compute_index (const Array<int>& ra_idx, const dim_vector& dims) +{ + int retval = -1; + + int n = dims.length (); + + if (n > 0 && n == ra_idx.length ()) + { + retval = ra_idx(--n); + + 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; +} + +static inline Array<int> +conv_to_int_array (const Array<idx_vector>& a) +{ + Array<int> retval (a.length ()); + + for (int i = 0; i < a.length (); i++) + retval (i) = a(i).elem (0); + + return retval; +} + +static inline Array<idx_vector> +conv_to_array (const idx_vector *tmp, const int len) +{ + Array<idx_vector> retval (len); + + for (int i = 0; i < len; i++) + retval (i) = tmp[i]; + + return retval; +} + +static inline dim_vector +freeze (Array<idx_vector>& ra_idx, const dim_vector& dimensions, int resize_ok) +{ + dim_vector retval; + + int n = ra_idx.length (); + + assert (n == dimensions.length ()); + + retval.resize (n); + + for (int i = 0; i < n; i++) + retval(i) = ra_idx(i).freeze (dimensions(i), "XXX FIXME XXX", resize_ok); + + return retval; +} + +static inline bool +vector_equivalent (const Array<int>& ra_idx) +{ + int n = ra_idx.length (); + + bool found_first = false; + + for (int i = 0; i < n; i++) + { + if (ra_idx(i) != 1) + { + if (! found_first) + found_first = true; + else + return false; + } + } + + return true; +} + +static inline bool +equal_arrays (const dim_vector& a, const dim_vector& b) +{ + bool retval = true; + + if (a.length () != b.length ()) + retval = false; + else + { + for (int i = 0; i < a.length (); i++) + { + if (a(i) != b(i)) + retval = false; + } + } + + return retval; +} + +static inline bool +all_ok (const Array<idx_vector>& ra_idx) +{ + bool retval = true; + + int n = ra_idx.length (); + + for (int i = 0; i < n; i++) + { + if (! ra_idx(i)) + { + retval = false; + break; + } + } + + return retval; +} + +static inline bool +any_orig_empty (const Array<idx_vector>& ra_idx) +{ + bool retval = false; + + int n = ra_idx.length (); + + for (int i = 0; i < n; i++) + { + if (ra_idx(i).orig_empty ()) + { + retval = true; + break; + } + } + + return retval; +} + +static inline bool +any_zero_len (const dim_vector& frozen_lengths) +{ + bool retval = false; + + int n = frozen_lengths.length (); + + for (int i = 0; i < n; i++) + { + if (frozen_lengths(i) == 0) + { + retval = true; + break; + } + } + + return retval; +} + +static inline dim_vector +get_zero_len_size (const dim_vector& frozen_lengths, + const dim_vector& dimensions) +{ + dim_vector retval; + assert (0); + return retval; +} + +static inline bool +all_colon_equiv (const Array<idx_vector>& ra_idx, + const dim_vector& frozen_lengths) +{ + bool retval = true; + + int idx_n = ra_idx.length (); + + int n = frozen_lengths.length (); + + assert (idx_n == n); + + for (int i = 0; i < n; i++) + { + if (! ra_idx(i).is_colon_equiv (frozen_lengths(i))) + { + retval = false; + break; + } + } + + return retval; +} + +static inline bool +is_in (int num, const idx_vector& idx) +{ + int n = idx.capacity (); + + for (int i = 0; i < n; i++) + if (idx.elem (i) == num) + return true; + + return false; +} + +static inline int +how_many_lgt (const int num, idx_vector& idxv) +{ + int retval = 0; + + int n = idxv.capacity (); + + for (int i = 0; i < n; i++) + if (num > idxv.elem (i)) + retval++; + + return retval; +} + +static inline bool +all_ones (const Array<int>& arr) +{ + bool retval = true; + + for (int i = 0; i < arr.length (); i++) + { + if (arr(i) != 1) + { + retval = false; + break; + } + } + + return retval; +} + +static Array<int> +get_elt_idx (const Array<idx_vector>& ra_idx, const Array<int>& result_idx) +{ + int n = ra_idx.length (); + + Array<int> retval (n); + + for (int i = 0; i < n; i++) + retval(i) = ra_idx(i).elem (result_idx(i)); + + return retval; +} + +#endif + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/liboctave/ArrayN.cc +++ b/liboctave/ArrayN.cc @@ -35,313 +35,17 @@ #include "ArrayN.h" #include "ArrayN-inline.h" - -#if defined (HEAVYWEIGHT_INDEXING) +#include "ArrayN-idx.h" #include "idx-vector.h" -#include "ArrayN-idx.h" -#endif - #include "lo-error.h" // N-dimensional array class. template <class T> -int -ArrayN<T>::compute_index (const Array<int>& ra_idx) const -{ - int retval = -1; - - int n = dimensions.length (); - - if (n > 0 && n == ra_idx.length ()) - { - retval = ra_idx(--n); - - while (--n >= 0) - { - retval *= dimensions(n); - retval += ra_idx(n); - } - } - else - (*current_liboctave_error_handler) - ("ArrayN<T>::compute_index: invalid ra_idxing operation"); - - return retval; -} - -// A guess (should be quite conservative). -#define MALLOC_OVERHEAD 1024 - -template <class T> -int -ArrayN<T>::get_size (const Array<int>& ra_idx) -{ - // XXX KLUGE XXX - - // If an allocation of an array with r * c elements of type T - // would cause an overflow in the allocator when computing the - // size of the allocation, then return a value which, although - // not equivalent to the actual request, should be too large for - // most current hardware, but not so large to cause the - // allocator to barf on computing retval * sizeof (T). - - static int nl; - static double dl - = frexp (static_cast<double> - (INT_MAX - MALLOC_OVERHEAD) / sizeof (T), &nl); - - // This value should be an integer. If we return this value and - // things work the way we expect, we should be paying a visit to - // new_handler in no time flat. - - static int max_items = static_cast<int> (ldexp (dl, nl)); - - int retval = max_items; - - int n = ra_idx.length (); - - int nt = 0; - double dt = 1; - - for (int i = 0; i < n; i++) - { - int nra_idx; - double dra_idx = frexp (static_cast<double> (ra_idx(i)), &nra_idx); - - nt += nra_idx; - dt *= dra_idx; - } - - if (dt <= 0.5) - { - nt--; - dt *= 2; - - if (dt <= 0.5) - nt--; - } - - if (nt < nl || (nt == nl && dt < dl)) - { - retval = 1; - - for (int i = 0; i < n; i++) - retval *= ra_idx(i); - } - - return retval; -} - -#undef MALLOC_OVERHEAD - -template <class T> -T -ArrayN<T>::range_error (const char *fcn, const Array<int>& ra_idx) const -{ - // XXX FIXME XXX -- report index values too! - - (*current_liboctave_error_handler) ("range error in ArrayN"); - - return T (); -} - -template <class T> -T& -ArrayN<T>::range_error (const char *fcn, const Array<int>& ra_idx) -{ - // XXX FIXME XXX -- report index values too! - - (*current_liboctave_error_handler) ("range error in ArrayN"); - - static T foo; - return foo; -} - -template <class T> -void -ArrayN<T>::resize (const Array<int>& dims) -{ - int n = dims.length (); - - for (int i = 0; i < n; i++) - { - if (dims(i) < 0) - { - (*current_liboctave_error_handler) - ("can't resize to negative dimension"); - return; - } - } - - bool no_change = true; - - for (int i = 0; i < n; i++) - { - if (dims(i) != dimensions(i)) - { - no_change = false; - break; - } - } - - if (no_change) - return; - - int old_len = length (); - - typename Array<T>::ArrayRep *old_rep = Array<T>::rep; - const T *old_data = data (); - - Array<T>::rep = new typename Array<T>::ArrayRep (get_size (dims)); - - Array<int> old_dimensions = dimensions; - - dimensions = dims; - - Array<int> ra_idx (dimensions.length (), 0); - - for (int i = 0; i < old_len; i++) - { - if (index_in_bounds (ra_idx, dimensions)) - xelem (ra_idx) = old_data[i]; - - increment_index (ra_idx, dimensions); - } - - if (--old_rep->count <= 0) - delete old_rep; -} - -template <class T> -void -ArrayN<T>::resize (const Array<int>& dims, const T& val) -{ - int n = dims.length (); - - for (int i = 0; i < n; i++) - { - if (dims(i) < 0) - { - (*current_liboctave_error_handler) - ("can't resize to negative dimension"); - return; - } - } - - bool no_change = true; - - for (int i = 0; i < n; i++) - { - if (dims(i) != dimensions(i)) - { - no_change = false; - break; - } - } - - if (no_change) - return; - - typename Array<T>::ArrayRep *old_rep = Array<T>::rep; - const T *old_data = data (); - - int old_len = length (); - - int len = get_size (dims); - - Array<T>::rep = new typename Array<T>::ArrayRep (len); - - Array<int> old_dimensions = dimensions; - - dimensions = dims; - - Array<int> ra_idx (dimensions.length (), 0); - - for (int i = 0; i < len; i++) - Array<T>::rep->elem (i) = val; - - for (int i = 0; i < old_len; i++) - { - if (index_in_bounds (ra_idx, dimensions)) - xelem (ra_idx) = old_data[i]; - - increment_index (ra_idx, dimensions); - } - - if (--old_rep->count <= 0) - delete old_rep; -} - -template <class T> -ArrayN<T>& -ArrayN<T>::insert (const ArrayN<T>& a, const Array<int>& ra_idx) -{ - int n = ra_idx.length (); - - if (n == dimensions.length ()) - { - Array<int> a_dims = a.dims (); - - for (int i = 0; i < n; i++) - { - if (ra_idx(i) < 0 || ra_idx(i) + a_dims(i) > dimensions(i)) - { - (*current_liboctave_error_handler) - ("ArrayN<T>::insert: range error for insert"); - return *this; - } - } - -#if 0 - // XXX FIXME XXX -- need to copy elements - - for (int j = 0; j < a_cols; j++) - for (int i = 0; i < a_rows; i++) - elem (r+i, c+j) = a.elem (i, j); -#endif - - } - else - (*current_liboctave_error_handler) - ("ArrayN<T>::insert: invalid indexing operation"); - - return *this; -} - -template <class T> -void -ArrayN<T>::maybe_delete_dims (void) -{ - int ndims = dimensions.length (); - Array<int> 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 = Array<int> (i + 1, dimensions(i)); - } - } - else - { - new_dims(i) = dimensions(i); - } - } - - if (ndims != new_dims.length ()) - dimensions = new_dims; -} - -template <class T> std::ostream& operator << (std::ostream& os, const ArrayN<T>& a) { - Array<int> a_dims = a.dimensions; + dim_vector a_dims = a.dims (); int n_dims = a_dims.length (); @@ -363,7 +67,7 @@ { os << "data:"; - Array<int> ra_idx (n_dims,0); + Array<int> ra_idx (n_dims, 0); // Number of times the first 2d-array is to be displayed.
--- a/liboctave/ArrayN.h +++ b/liboctave/ArrayN.h @@ -36,7 +36,7 @@ #include <cstdlib> #include "Array.h" -#include "dMatrix.h" +#include "Array2.h" #include "lo-error.h" class idx_vector; @@ -49,175 +49,74 @@ { protected: + static int get_size (const dim_vector& dims) + { return Array<T>::get_size (dims); } - ArrayN (T *d, const Array<int>& dims) : Array<T> (d, get_size (dims)) - { - dimensions = dims; - set_max_indices (dimensions.length ()); - } + ArrayN (T *d, const dim_vector& dims) : Array<T> (d, dims) { } public: - static int get_size (const Array<int>& dims); - // These really need to be protected (and they will be in the // future, so don't depend on them being here!), but they can't be // until template friends work correctly in g++. - Array<int> dimensions; - ArrayN (void) : Array<T> () { } - ArrayN (const Array<int>& dims) : Array<T> (get_size (dims)) - { - dimensions = dims; - set_max_indices (dimensions.length ()); - } + ArrayN (const dim_vector& dims) : Array<T> (dims) { } - ArrayN (const Array<int>& dims, const T& val) - : Array<T> (get_size (dims), val) - { - dimensions = dims; - set_max_indices (dimensions.length ()); - } - - ArrayN (const ArrayN<T>& a) : Array<T> (a) - { - dimensions = a.dimensions; - set_max_indices (dimensions.length ()); - } + ArrayN (const dim_vector& dims, const T& val) + : Array<T> (dims) { fill (val); } - ArrayN (const Array<T>& a, const Array<int>& dims) : Array<T> (a) - { - dimensions = dims; - set_max_indices (dimensions.length ()); - } - - // New constructor which takes a Matrix as an argument. This should - // be moved to a subclass of ArrayN (NDArray) once we add a double - // instantiation of ArrayN. + ArrayN (const Array2<T>& a) : Array<T> (a, a.dims ()) { } - ArrayN (const Matrix& m) : Array<T> (m) - { - set_max_indices (2); - - Array<int> dim (2); + ArrayN (const ArrayN<T>& a) : Array<T> (a, a.dims ()) { } - dim(0) = m.dim1 (); - dim(1) = m.dim2 (); - - dimensions = dim; - } + ArrayN (const Array<T>& a, const dim_vector& dims) : Array<T> (a, dims) { } ~ArrayN (void) { } ArrayN<T>& operator = (const ArrayN<T>& a) { - if (this != &a && Array<T>::rep != a.rep) - { - Array<T>::operator = (a); - dimensions = a.dimensions; - } + if (this != &a) + Array<T>::operator = (a); return *this; } - int compute_index (const Array<int>& ra_idx) const; - - Array<int> dims (void) const { return dimensions; } - - T range_error (const char *fcn, const Array<int>& ra_idx) const; - T& range_error (const char *fcn, const Array<int>& ra_idx); - - // No checking of any kind, ever. - - T& xelem (const Array<int>& ra_idx) - { return Array<T>::xelem (compute_index (ra_idx)); } - - T xelem (const Array<int>& ra_idx) const - { return Array<T>::xelem (compute_index (ra_idx)); } + void resize (const dim_vector& dims) + { Array<T>resize_no_fill (dims); } - // Note that the following element selection methods don't use - // xelem() because they need to make use of the code in - // Array<T>::elem() that checks the reference count. - - T& checkelem (const Array<int>& ra_idx) - { - int i = compute_index (ra_idx); + void resize (const dim_vector& dims, const T& val) + { Array<T>::resize (dims, val); } - if (i < 0) - return range_error ("ArrayN<T>::checkelem", ra_idx); - else - return Array<T>::elem (i); - } - - T& elem (const Array<int>& ra_idx) + ArrayN<T>& insert (const ArrayN<T>& a, const dim_vector& dims) { - int i = compute_index (ra_idx); - - return Array<T>::elem (i); + Array<T>::insert (a, dims); + return *this; } -#if defined (BOUNDS_CHECKING) - T& operator () (const Array<int>& ra_idx) { return checkelem (ra_idx); } -#else - T& operator () (const Array<int>& ra_idx) { return elem (ra_idx); } -#endif - - T checkelem (const Array<int>& ra_idx) const + ArrayN<T> index (idx_vector& i, int resize_ok = 0, + const T& rfv = resize_fill_value (T ())) const { - int i = compute_index (ra_idx); - - if (i < 0) - return range_error ("ArrayN<T>::checkelem", ra_idx); - else - return Array<T>::elem (i); - } - - T elem (const Array<int>& ra_idx) const - { - int i = compute_index (ra_idx); - - return Array<T>::elem (i); + Array<T> tmp = Array<T>::index (i, resize_ok, rfv); + return ArrayN<T> (tmp, tmp.dims ()); } -#if defined (BOUNDS_CHECKING) - T operator () (const Array<int>& ra_idx) const { return checkelem (ra_idx); } -#else - T operator () (const Array<int>& ra_idx) const { return elem (ra_idx); } -#endif - - void resize (const Array<int>& dims); - void resize (const Array<int>& dims, const T& val); - - ArrayN<T>& insert (const ArrayN<T>& a, const Array<int>& dims); - -#ifdef HEAVYWEIGHT_INDEXING - void maybe_delete_elements (Array<idx_vector>& ra_idx, const T& rfv); - - ArrayN<T> value (void); - - ArrayN<T> index (idx_vector& ra_idx, int resize_ok = 0, - const T& rfv = resize_fill_value (T ())) const; + ArrayN<T> index (idx_vector& i, idx_vector& j, int resize_ok = 0, + const T& rfv = resize_fill_value (T ())) const + { + Array<T> tmp = Array<T>::index (i, j, resize_ok, rfv); + return ArrayN<T> (tmp, tmp.dims ()); + } ArrayN<T> index (Array<idx_vector>& ra_idx, int resize_ok = 0, - const T& rfv = resize_fill_value (T ())) const; - - void maybe_delete_dims (void); -#endif + const T& rfv = resize_fill_value (T ())) const + { + Array<T> tmp = Array<T>::index (ra_idx, resize_ok, rfv); + return ArrayN<T> (tmp, tmp.dims ()); + } }; -template <class LT, class RT> -int -assign (ArrayN<LT>& lhs, const ArrayN<RT>& rhs, const LT& rfv); - -template <class LT, class RT> -int -assign (ArrayN<LT>& lhs, const ArrayN<RT>& rhs) -{ - return assign (lhs, rhs, resize_fill_value (LT ())); -} - template <class T> std::ostream& operator << (std::ostream&, const ArrayN<T>&);
--- a/liboctave/CDiagMatrix.cc +++ b/liboctave/CDiagMatrix.cc @@ -545,7 +545,8 @@ } } else - std::cerr << "diag: requested diagonal out of range\n"; + (*current_liboctave_error_handler) + ("diag: requested diagonal out of range"); return d; }
--- a/liboctave/CMatrix.cc +++ b/liboctave/CMatrix.cc @@ -2691,7 +2691,8 @@ } } else - std::cerr << "diag: requested diagonal out of range\n"; + (*current_liboctave_error_handler) + ("diag: requested diagonal out of range"); return d; }
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,45 @@ +2003-09-19 John W. Eaton <jwe@bevo.che.wisc.edu> + + * Array.h, Array-idx.h, Array.cc: Fold all N-d functionality here. + Turn inheritance hierarchy upside down (2-d and 3-d arrays are now + just special cases of the general purpose N-d Array object). + + * dim-vector.h: New file. Use dim_vector objects instead of + ints or Array<int> objects to represent the size of Array + objects. + + * MArray-defs.h (INSTANTIATE_MARRAYN_FRIENDS): New macro. + + * Array2-idx.h, Array3-idx.h, Array2.cc, Array3.cc: Delete. + + * mx-base.h: Include NDArray header files. + + * MArray-C.cc, MArray-d.cc: Also instantiate ArrayN objects. + + * Array-C.cc, Array-b.cc, Array-ch.cc, Array-d.cc, Array-i.cc, + Array-s.cc: Also instantiate ArrayN objects. + Don't instantiate assign funcitons for Array2 objects. + + * CDiagMatrix.cc (ComplexDiagMatrix::diag): Signal error with + liboctave_error_handler, not cerr. + * CMatrix.cc (ComplexMatrix::diag): Likewise. + * dDiagMatrix.cc (DiagMatrix::diag): Likewise. + * dMatrix.cc (Matrix::diag): Likewise. + + * Array-flags.cc, Array.cc, Array.h, Array2.h, Array3.h, ArrayN.h: + Omit checks for HEAVYWEIGHT_INDEXING. + +2003-09-12 John W. Eaton <jwe@bevo.che.wisc.edu> + + * mx-base.h: Include CNDarray.h. Include dNDArray.h, not NDArray.h. + + * CNDARray.h, CNDArray.cc: New files. + * Makefile.in: Add them to the appropriate lists. + + * dNDArray.h: Rename from NDArray.h. + * dNDArray.cc: Rename from NDArray.cc. + * Makefile.in: Rename them here too. + 2003-09-10 Petter Risholm <risholm@stud.ntnu.no> * mx-base.h: Include NDArray.h, not ArrayN.h.
--- a/liboctave/DiagArray2.cc +++ b/liboctave/DiagArray2.cc @@ -53,7 +53,7 @@ DiagArray2<T>::checkelem (int r, int c) { static T foo (0); - if (r < 0 || c < 0 || r >= nr || c >= nc) + if (r < 0 || c < 0 || r >= dim1 () || c >= dim2 ()) { (*current_liboctave_error_handler) ("range error in DiagArray2"); return foo; @@ -66,7 +66,7 @@ DiagArray2<T>::operator () (int r, int c) { static T foo (0); - if (r < 0 || c < 0 || r >= nr || c >= nc) + if (r < 0 || c < 0 || r >= dim1 () || c >= dim2 ()) { (*current_liboctave_error_handler) ("range error in DiagArray2"); return foo; @@ -86,7 +86,7 @@ T DiagArray2<T>::checkelem (int r, int c) const { - if (r < 0 || c < 0 || r >= nr || c >= nc) + if (r < 0 || c < 0 || r >= dim1 () || c >= dim2 ()) { (*current_liboctave_error_handler) ("range error in DiagArray2"); return T (); @@ -98,7 +98,7 @@ T DiagArray2<T>::operator () (int r, int c) const { - if (r < 0 || c < 0 || r >= nr || c >= nc) + if (r < 0 || c < 0 || r >= dim1 () || c >= dim2 ()) { (*current_liboctave_error_handler) ("range error in DiagArray2"); return T (); @@ -142,8 +142,7 @@ Array<T>::rep = new typename Array<T>::ArrayRep (new_len); - nr = r; - nc = c; + dimensions = dim_vector (r, c); if (old_data && old_len > 0) { @@ -178,8 +177,7 @@ Array<T>::rep = new typename Array<T>::ArrayRep (new_len); - nr = r; - nc = c; + dimensions = dim_vector (r, c); int min_len = old_len < new_len ? old_len : new_len;
--- a/liboctave/DiagArray2.h +++ b/liboctave/DiagArray2.h @@ -110,51 +110,28 @@ protected: - int nr; - int nc; - DiagArray2 (T *d, int r, int c) : Array<T> (d, r < c ? r : c) - { - nr = r; - nc = c; - set_max_indices (2); - } + { dimensions = dim_vector (r, c); } public: - DiagArray2 (void) : Array<T> () - { - nr = 0; - nc = 0; - set_max_indices (2); - } + DiagArray2 (void) : Array<T> (dim_vector (0, 0)) { } DiagArray2 (int r, int c) : Array<T> (r < c ? r : c) - { - nr = r; - nc = c; - set_max_indices (2); - } + { dimensions = dim_vector (r, c); } - DiagArray2 (int r, int c, const T& val) : Array<T> (r < c ? r : c, val) + DiagArray2 (int r, int c, const T& val) : Array<T> (r < c ? r : c) { - nr = r; - nc = c; - set_max_indices (2); + dimensions = dim_vector (r, c); + + fill (val); } DiagArray2 (const Array<T>& a) : Array<T> (a) - { - nr = nc = a.length (); - set_max_indices (2); - } + { dimensions = dim_vector (a.length (), a.length ()); } DiagArray2 (const DiagArray2<T>& a) : Array<T> (a) - { - nr = a.nr; - nc = a.nc; - set_max_indices (2); - } + { dimensions = a.dims (); } ~DiagArray2 (void) { } @@ -163,8 +140,7 @@ if (this != &a) { Array<T>::operator = (a); - nr = a.nr; - nc = a.nc; + dimensions = a.dims (); } return *this; @@ -173,6 +149,9 @@ #if 0 operator Array2<T> () const { + int nr = dim1 (); + int nc = dim2 (); + Array2<T> retval (nr, nc, T (0)); int len = nr < nc ? nr : nc; @@ -184,13 +163,6 @@ } #endif - int dim1 (void) const { return nr; } - int dim2 (void) const { return nc; } - - int rows (void) const { return nr; } - int cols (void) const { return nc; } - int columns (void) const { return nc; } - #if 1 Proxy elem (int r, int c) { @@ -199,7 +171,7 @@ Proxy checkelem (int r, int c) { - if (r < 0 || c < 0 || r >= nr || c >= nc) + if (r < 0 || c < 0 || r >= dim1 () || c >= dim2 ()) { (*current_liboctave_error_handler) ("range error in DiagArray2"); return Proxy (0, r, c); @@ -210,7 +182,7 @@ Proxy operator () (int r, int c) { - if (r < 0 || c < 0 || r >= nr || c >= nc) + if (r < 0 || c < 0 || r >= dim1 () || c >= dim2 ()) { (*current_liboctave_error_handler) ("range error in DiagArray2"); return Proxy (0, r, c);
--- a/liboctave/MArray-C.cc +++ b/liboctave/MArray-C.cc @@ -42,6 +42,13 @@ INSTANTIATE_MARRAY2_FRIENDS (Complex) +#include "MArrayN.h" +#include "MArrayN.cc" + +template class MArrayN<Complex>; + +INSTANTIATE_MARRAYN_FRIENDS (Complex) + #include "MDiagArray2.h" #include "MDiagArray2.cc"
--- a/liboctave/MArray-d.cc +++ b/liboctave/MArray-d.cc @@ -40,6 +40,13 @@ INSTANTIATE_MARRAY2_FRIENDS (double) +#include "MArrayN.h" +#include "MArrayN.cc" + +template class MArrayN<double>; + +INSTANTIATE_MARRAYN_FRIENDS (double) + #include "MDiagArray2.h" #include "MDiagArray2.cc"
--- a/liboctave/MArray-defs.h +++ b/liboctave/MArray-defs.h @@ -262,14 +262,21 @@ MARRAY_UNOP_DEFS (MArray, T) \ MARRAY_BINOP_DEFS (MArray, T) -// Instantiate all the MArray friends for MArray element type T. +// Instantiate all the MArray2 friends for MArray2 element type T. #define INSTANTIATE_MARRAY2_FRIENDS(T) \ MARRAY_OP_ASSIGN_DEFS (MArray2, T, T) \ MARRAY_OP_ASSIGN_DEFS (MArray2, T, MArray2<T>) \ MARRAY_UNOP_DEFS (MArray2, T) \ MARRAY_BINOP_DEFS (MArray2, T) -// Instantiate all the MArray friends for MArray element type T. +// Instantiate all the MArrayN friends for MArrayN element type T. +#define INSTANTIATE_MARRAYN_FRIENDS(T) \ + MARRAY_OP_ASSIGN_DEFS (MArrayN, T, T) /* \ + MARRAY_OP_ASSIGN_DEFS (MArray2, T, MArray2<T>) \ + MARRAY_UNOP_DEFS (MArray2, T) \ + MARRAY_BINOP_DEFS (MArray2, T) */ + +// Instantiate all the MDiagArray2 friends for MDiagArray2 element type T. #define INSTANTIATE_MDIAGARRAY2_FRIENDS(T) \ MARRAY_OP_ASSIGN_DEFS (MDiagArray2, T, MDiagArray2<T>) \ MARRAY_UNOP_DEFS (MDiagArray2, T) \
--- a/liboctave/MArrayN.cc +++ b/liboctave/MArrayN.cc @@ -34,12 +34,10 @@ #include "MArray-defs.h" -// Two dimensional array with math ops. +// N-dimensional array with math ops. // Element by element MArrayN by scalar ops. - -#if 0 template <class T> MArrayN<T>& operator += (MArrayN<T>& a, const T& s) @@ -56,7 +54,7 @@ return a; } - +#if 0 #define MARRAYN_NDS_OP(OP) \ template <class T> \ MArrayN<T> \ @@ -100,8 +98,8 @@ MArrayN<T> \ FCN (const MArrayN<T>& a, const MArrayN<T>& b) \ { \ -Array<int> a_dims = a.dims (); \ -Array<int> b_dims = b.dims (); \ +dim_vector a_dims = a.dims (); \ +dim_vector b_dims = b.dims (); \ int dims_ok = 1; \ int any_dims_zero = 0; \ if (a_dims.length () != b_dims.length ()) \
--- a/liboctave/MArrayN.h +++ b/liboctave/MArrayN.h @@ -29,43 +29,39 @@ #define octave_MArrayN_h 1 #include "ArrayN.h" -// Two dimensional array with math ops. +#include "MArray2.h" +#include "dim-vector.h" + +// N-dimensional array with math ops. // But first, some preprocessor abuse... #include "MArray-defs.h" -class Matrix; - MARRAY_OPS_FORWARD_DECLS (MArrayN) template <class T> class MArrayN : public ArrayN<T> { - protected: +protected: - MArrayN (T *d, const Array<int>& dims) : ArrayN<T> (d, dims) - { } + MArrayN (T *d, const dim_vector& dims) : ArrayN<T> (d, dims) { } - public: +public: MArrayN (void) : ArrayN<T> () {} - MArrayN (const Array<int>& dims) : ArrayN<T> (dims) - { } + MArrayN (const dim_vector& dims) : ArrayN<T> (dims) { } - MArrayN (const Array<int>& dims, const T& val) - : ArrayN<T> (dims, val) { } + MArrayN (const dim_vector& dims, const T& val) : ArrayN<T> (dims, val) { } + + MArrayN (const Array2<T>& a) : ArrayN<T> (a) { } MArrayN (const ArrayN<T>& a) : ArrayN<T> (a) { } - //MArrayN (const Array<T>& a) : ArrayN<T> (a) { } - MArrayN (const MArrayN<T>& a) : ArrayN<T> (a) { } - MArrayN (const Matrix& m) : ArrayN<T> (m) { } - ~MArrayN (void) { } MArrayN<T>& operator = (const MArrayN<T>& a) @@ -73,10 +69,15 @@ ArrayN<T>::operator = (a); return *this; } - }; extern void -gripe_nonconformant (const char *op, Array<int>& op1_dims, Array<int>& op2_dims); +gripe_nonconformant (const char *op, dim_vector& op1_dims, dim_vector& op2_dims); #endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
--- a/liboctave/MDiagArray2.h +++ b/liboctave/MDiagArray2.h @@ -71,9 +71,12 @@ operator MArray2<T> () const { - MArray2<T> retval (DiagArray2<T>::nr, DiagArray2<T>::nc, T (0)); + int nr = DiagArray2<T>::dim1 (); + int nc = DiagArray2<T>::dim2 (); - int len = DiagArray2<T>::nr < DiagArray2<T>::nc ? DiagArray2<T>::nr : DiagArray2<T>::nc; + MArray2<T> retval (nr, nc, T (0)); + + int len = nr < nc ? nr : nc; for (int i = 0; i < len; i++) retval.xelem (i, i) = xelem (i, i);
--- a/liboctave/Makefile.in +++ b/liboctave/Makefile.in @@ -26,15 +26,17 @@ endif MATRIX_INC := Array.h Array2.h Array3.h ArrayN.h DiagArray2.h \ - Array-flags.h Array-idx.h Array2-idx.h Array3-idx.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 NDArray.h \ - base-lu.h mx-base.h mx-op-defs.h mx-ops.h mx-defs.h mx-ext.h \ - CColVector.h CDiagMatrix.h CMatrix.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 chMatrix.h \ - dColVector.h dDiagMatrix.h dMatrix.h dRowVector.h dbleAEPBAL.h \ - dbleCHOL.h dbleDET.h dbleHESS.h dbleLU.h dbleQR.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 \ @@ -72,7 +74,7 @@ $(MX_OP_INC) \ $(VX_OP_INC) -TEMPLATE_SRC := Array.cc Array2.cc Array3.cc ArrayN.cc DiagArray2.cc \ +TEMPLATE_SRC := Array.cc ArrayN.cc DiagArray2.cc \ MArray.cc MArray2.cc MDiagArray2.cc base-lu.cc TI_SRC := Array-C.cc Array-b.cc Array-ch.cc Array-i.cc Array-d.cc \ @@ -80,12 +82,13 @@ MArray-C.cc MArray-ch.cc MArray-i.cc MArray-d.cc MArray-s.cc MATRIX_SRC := Array-flags.cc CColVector.cc CDiagMatrix.cc CMatrix.cc \ - CRowVector.cc CmplxAEPBAL.cc CmplxCHOL.cc CmplxDET.cc \ - CmplxHESS.cc CmplxLU.cc CmplxQR.cc CmplxQRP.cc CmplxSCHUR.cc \ - CmplxSVD.cc EIG.cc MArray-misc.cc MArrayN.cc NDArray.cc \ - boolMatrix.cc chMatrix.cc \ - dColVector.cc dDiagMatrix.cc dMatrix.cc dRowVector.cc \ - dbleAEPBAL.cc dbleCHOL.cc dbleDET.cc dbleHESS.cc dbleLU.cc \ + CNDArray.cc CRowVector.cc CmplxAEPBAL.cc CmplxCHOL.cc \ + CmplxDET.cc CmplxHESS.cc CmplxLU.cc CmplxQR.cc CmplxQRP.cc \ + CmplxSCHUR.cc CmplxSVD.cc EIG.cc MArray-misc.cc MArrayN.cc \ + boolMatrix.cc boolNDArray.cc chMatrix.cc chNDArray.cc \ + dColVector.cc dDiagMatrix.cc \ + dMatrix.cc dNDArray.cc dRowVector.cc dbleAEPBAL.cc \ + dbleCHOL.cc dbleDET.cc dbleHESS.cc dbleLU.cc \ dbleQR.cc dbleQRP.cc dbleSCHUR.cc dbleSVD.cc MX_OP_SRC := mx-cdm-cm.cc mx-cdm-cs.cc mx-cdm-dm.cc mx-cdm-m.cc \
--- a/liboctave/dDiagMatrix.cc +++ b/liboctave/dDiagMatrix.cc @@ -391,7 +391,8 @@ } } else - std::cerr << "diag: requested diagonal out of range\n"; + (*current_liboctave_error_handler) + ("diag: requested diagonal out of range"); return d; }
--- a/liboctave/dMatrix.cc +++ b/liboctave/dMatrix.cc @@ -2208,7 +2208,8 @@ } } else - std::cerr << "diag: requested diagonal out of range\n"; + (*current_liboctave_error_handler) + ("diag: requested diagonal out of range"); return d; }
--- a/liboctave/dNDArray.cc +++ b/liboctave/dNDArray.cc @@ -1,4 +1,4 @@ -//N-D Array manipulations. +// N-D Array manipulations. /* Copyright (C) 1996, 1997 John W. Eaton @@ -29,10 +29,47 @@ #include <config.h> #endif -#include "NDArray.h" +#include "dNDArray.h" #include "mx-base.h" +#include "lo-error.h" #include "lo-ieee.h" +// XXX FIXME XXX -- this is not quite the right thing. + +boolMatrix +NDArray::all (int dim) const +{ + boolMatrix retval; + + if (dimensions.length () == 2) + { + Matrix tmp = matrix_value (); + retval = tmp.all (dim); + } + else + (*current_liboctave_error_handler) + ("all is not yet implemented for N-d Arrays"); + + return retval; +} + +boolMatrix +NDArray::any (int dim) const +{ + boolMatrix retval; + + if (dimensions.length () == 2) + { + Matrix tmp = matrix_value (); + retval = tmp.any (dim); + } + else + (*current_liboctave_error_handler) + ("any is not yet implemented for N-d Arrays"); + + return retval; +} + bool NDArray::any_element_is_negative (bool neg_zero) const { @@ -82,3 +119,35 @@ return true; } + +Matrix +NDArray::matrix_value (void) const +{ + Matrix retval; + + int nd = ndims (); + + switch (nd) + { + case 1: + retval = Matrix (Array2<double> (*this, dimensions(0), 1)); + break; + + case 2: + retval = Matrix (Array2<double> (*this, dimensions(0), dimensions(1))); + break; + + default: + (*current_liboctave_error_handler) + ("invalid converstion of NDArray to Matrix"); + break; + } + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
--- a/liboctave/dNDArray.h +++ b/liboctave/dNDArray.h @@ -20,15 +20,15 @@ */ -#if !defined (octave_NDArray_int_h) -#define octave_NDArray_int_h 1 +#if !defined (octave_NDArray_h) +#define octave_NDArray_h 1 #if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) #pragma interface #endif #include "MArrayN.h" -//#include "mx-base.h" +#include "dMatrix.h" #include "mx-defs.h" #include "mx-op-defs.h" @@ -36,32 +36,38 @@ #include "data-conv.h" #include "mach-info.h" -class NDArray : public MArrayN<double> +class +NDArray : public MArrayN<double> { - public: +public: NDArray (void) : MArrayN<double> () { } - NDArray (Array<int>& dims) : MArrayN<double> (dims) { } + NDArray (dim_vector& dims) : MArrayN<double> (dims) { } - NDArray (Array<int>& dims, double val) : MArrayN<double> (dims, val) { } + NDArray (dim_vector& dims, double val) : MArrayN<double> (dims, val) { } - NDArray (const NDArray& a): MArrayN<double> (a) { } + NDArray (const NDArray& a) : MArrayN<double> (a) { } + + NDArray (const Matrix& a) : MArrayN<double> (a) { } NDArray (const MArrayN<double>& a) : MArrayN<double> (a) { } - NDArray (const Matrix& m) : MArrayN<double> (m) { } - NDArray (const ArrayN<double>& a) : MArrayN<double> (a) { } - //NDArray (const Array<double>& a) : MArrayN<double> (a) { } - NDArray& operator = (const NDArray& a) { MArrayN<double>::operator = (a); return *this; } + // XXX FIXME XXX -- this is not quite the right thing. + + boolMatrix all (int dim = -1) const; + boolMatrix any (int dim = -1) const; + + Matrix matrix_value (void) const; + // i/o // friend std::ostream& operator << (std::ostream& os, const NDArray& a); @@ -72,11 +78,17 @@ bool any_element_is_negative (bool = false) const; bool all_integers (double& max_val, double& min_val) const; - private: +private: - NDArray (double *d, Array<int>& dims) : MArrayN<double> (d, dims) { } + NDArray (double *d, dim_vector& dims) : MArrayN<double> (d, dims) { } }; MARRAY_FORWARD_DEFS (MArrayN, NDArray, double) #endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
new file mode 100644 --- /dev/null +++ b/liboctave/dim-vector.h @@ -0,0 +1,134 @@ +/* + +Copyright (C) 2003 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. + +*/ + +#if !defined (octave_dim_vector_h) +#define octave_dim_vector_h 1 + +#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) +#pragma interface +#endif + +#include <cassert> + +class +dim_vector +{ +public: + + dim_vector (void) : ndims (0), dims (0) { } + + dim_vector (int n) : ndims (1), dims (new int [1]) { dims[0] = n; } + + dim_vector (int r, int c) + : ndims (2), dims (new int [2]) { dims[0] = r; dims[1] = c; } + + dim_vector (int r, int c, int p) + : ndims (3), dims (new int [3]) { dims[0] = r; dims[1] = c; dims[2] = p; } + + dim_vector (const dim_vector& dv) + : ndims (dv.ndims) + { + if (dv.dims) + { + dims = new int [ndims]; + + for (int i = 0; i < ndims; i++) + dims[i] = dv.dims[i]; + } + else + dims = 0; + } + + dim_vector& operator = (const dim_vector& dv) + { + if (&dv != this) + { + ndims = dv.ndims; + + if (dv.dims) + { + dims = new int [ndims]; + + for (int i = 0; i < ndims; i++) + dims[i] = dv.dims[i]; + } + } + + return *this; + } + + ~dim_vector (void) { delete [] dims; } + + int length (void) const { return ndims; } + + int& elem (int i) + { + if (i >= ndims) + resize (i+1); + + return dims[i]; + } + + int elem (int i) const { return i < ndims ? dims[i] : -1; } + + int& operator () (int i) { return elem (i); } + + int operator () (int i) const { return elem (i); } + + void resize (int n) + { + if (n > ndims) + { + int *new_dims = new int [n]; + + for (int i = 0; i < ndims; i++) + new_dims[i] = dims[i]; + + for (int i = ndims; i < n; i++) + new_dims[i] = 0; + + delete [] dims; + + dims = new_dims; + + ndims = n; + } + else + ndims = n; + } + +private: + + int rows; + int cols; + int ndims; + int *dims; +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ +
--- a/liboctave/mx-base.h +++ b/liboctave/mx-base.h @@ -45,9 +45,12 @@ #include "dDiagMatrix.h" #include "CDiagMatrix.h" -// N-dimensional Array classes. +// N-d Array classes. -#include "NDArray.h" +#include "boolNDArray.h" +#include "chNDArray.h" +#include "dNDArray.h" +#include "CNDArray.h" #endif
--- a/src/Cell.cc +++ b/src/Cell.cc @@ -28,22 +28,78 @@ #include <config.h> #endif +#include "idx-vector.h" + #include "Cell.h" Cell::Cell (const string_vector& sv) - : Array2<octave_value> () + : ArrayN<octave_value> () { int n = sv.length (); if (n > 0) { - resize (n, 1); + resize_no_fill (n, 1); for (int i = 0; i < n; i++) elem(i,0) = sv[i]; } } +Cell +Cell::index (const octave_value_list& idx, bool resize_ok) const +{ + Cell retval; + + int n = idx.length (); + + switch (n) + { + case 1: + { + idx_vector i = idx(0).index_vector (); + + retval = index (i, resize_ok); + } + break; + + case 2: + { + idx_vector i = idx(0).index_vector (); + idx_vector j = idx(1).index_vector (); + + retval = index (i, j, resize_ok); + } + break; + + default: + { + Array<idx_vector> iv (n); + + for (int i = 0; i < n; i++) + iv(i) = idx(i).index_vector (); + + retval = index (iv, resize_ok); + } + break; + } + + return retval; +} + +Cell& +Cell::assign (const octave_value_list& idx, const Cell& rhs, + const octave_value& fill_val) + +{ + for (int i = 0; i < idx.length (); i++) + set_index (idx(i).index_vector ()); + + ::assign (*this, rhs, fill_val); + + return *this; +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/Cell.h +++ b/src/Cell.h @@ -29,36 +29,70 @@ #include <string> -#include "Array2.h" +#include "ArrayN.h" #include "oct-alloc.h" #include "str-vec.h" #include "oct-obj.h" class -Cell : public Array2<octave_value> +Cell : public ArrayN<octave_value> { public: Cell (void) - : Array2<octave_value> () { } + : ArrayN<octave_value> () { } Cell (const octave_value& val) - : Array2<octave_value> (1, 1, val) { } + : ArrayN<octave_value> (dim_vector (1, 1), val) { } + + Cell (const octave_value_list& ovl) + : ArrayN<octave_value> (dim_vector (ovl.length (), 1)) + { + for (int i = 0; i < ovl.length (); i++) + elem (i) = ovl (i); + } Cell (int n, int m, const octave_value& val = resize_fill_value ()) - : Array2<octave_value> (n, m, val) { } + : ArrayN<octave_value> (dim_vector (n, m), val) { } - Cell (const Array2<octave_value>& c) - : Array2<octave_value> (c) { } + Cell (const ArrayN<octave_value>& c) + : ArrayN<octave_value> (c) { } Cell (const Array<octave_value>& c, int nr, int nc) - : Array2<octave_value> (c, nr, nc) { } + : ArrayN<octave_value> (c, dim_vector (nr, nc)) { } Cell (const string_vector& sv); Cell (const Cell& c) - : Array2<octave_value> (c) { } + : ArrayN<octave_value> (c) { } + + Cell index (const octave_value_list& idx, bool resize_ok = false) const; + + Cell index (idx_vector& i, int resize_ok = 0, + const octave_value& rfv = resize_fill_value ()) const + { return ArrayN<octave_value>::index (i, resize_ok, rfv); } + + Cell index (idx_vector& i, idx_vector& j, int resize_ok = 0, + const octave_value& rfv = resize_fill_value ()) const + { return ArrayN<octave_value>::index (i, j, resize_ok, rfv); } + + Cell index (Array<idx_vector>& ra_idx, int resize_ok = 0, + const octave_value& rfv = resize_fill_value ()) const + { return ArrayN<octave_value>::index (ra_idx, resize_ok, rfv); } + + Cell& assign (const octave_value_list& idx, const Cell& rhs, + const octave_value& fill_val = octave_value ()); + + octave_value& operator () (int i) { return elem_internal (i); } + + octave_value operator () (int i) const { return elem_internal (i); } + + octave_value& operator () (int i, int j) + { return ArrayN<octave_value>::operator () (i, j); } + + octave_value operator () (int i, int j) const + { return ArrayN<octave_value>::operator () (i, j); } // XXX FIXME XXX boolMatrix all (int dim = 0) const { return boolMatrix (); } @@ -70,6 +104,28 @@ bool is_true (void) const { return false; } static octave_value resize_fill_value (void) { return Matrix (); } + +private: + + // XXX FIXME XXX -- we need to do something intelligent if there is + // more than one dimension, but for now this is all we need... + + void maybe_resize (int n) + { + if (n >= rows ()) + resize (dim_vector (n + 1, 1), octave_value ()); + } + + octave_value& elem_internal (int n) + { + maybe_resize (n); + return elem (n); + } + + octave_value elem_internal (int n) const + { + return elem (n); + } }; #endif
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,43 @@ +2003-09-19 John W. Eaton <jwe@bevo.che.wisc.edu> + + * ov.h (octave_value::dim_vector): New function. + + * ov.h, ov.cc (octave_value::octave_value (const Cell&)): + New arg, is_cs_list. + (octave_value::octave_value (const NDArray&)): + Create octave_matrix object, not octave_double_nd_array object. + (octave_value::octave_value (const ComplexNDArray&), + octave_value::octave_value (const boolNDArray&), + octave_value (const charNDArray&, bool)): New constructors. + + * ov.h, ov.cc (octave_value::nil_rep): New function. + (octave_value::octave_value (void)): Use it to initialize empty + octave_value objects. + + * ov-list.h, ov-list.cc (octave_list::octave_list (const Cell&)): + New constructor. + * ov-cs-list.h (octave_cs_list::octave_cs_list (const Cell&)): + Likewise. + + * data.cc (Fsize): Handle N-d objects. + + * pr-output.cc (octave_print_internal): New versions for NDArray, + ComplexNDArray, boolNDArray, and charNDArray objects. + * pr-output.h: Provide decls. + + * ov-re-nd-array.h, ov-re-nd-array.cc: Delete. + + * Cell.h, Cell.cc, ov-base-mat.h, ov-base-mat.cc, ov-bool-mat.h, + ov-bool-mat.cc, ov-ch-mat.h, ov-ch-mat.cc, ov-cx-mat.h, + ov-cx-mat.cc, ov-re-mat.h, ov-re-mat.cc, ov-str-mat.h, + ov-str-mat.cc: Now N-dimensional. + + * oct-map.h, oct-map.cc: Now based on Cell ojects instead of + octave_value_list objects. Change all uses. + + * TEMPLATE-INST/Array-tc.cc: Also instantiate ArrayN objects. + Don't instantiate assign funcitons for Array2 objects. + 2003-09-11 John W. Eaton <jwe@bevo.che.wisc.edu> * pt-plot.cc (symbols_of_pt_plot): Default for automatic replot is
--- a/src/Makefile.in +++ b/src/Makefile.in @@ -71,7 +71,7 @@ ov-colon.h ov-base.h ov-base-mat.h ov-base-scalar.h \ ov-str-mat.h ov-bool-mat.h ov-bool.h ov-file.h ov-cell.h ov.h \ ov-fcn.h ov-builtin.h ov-dld-fcn.h ov-mapper.h ov-usr-fcn.h \ - ov-base-nd-array.h ov-re-nd-array.h ov-fcn-handle.h ov-typeinfo.h + ov-fcn-handle.h ov-typeinfo.h PT_INCLUDES := pt.h pt-all.h pt-arg-list.h pt-assign.h pt-binop.h \ pt-bp.h pt-cell.h pt-check.h pt-cmd.h pt-colon.h pt-const.h \ @@ -99,9 +99,8 @@ op-cs-s.cc op-fil-b.cc op-fil-bm.cc op-fil-cm.cc \ op-fil-cs.cc op-fil-m.cc op-fil-s.cc op-fil-lis.cc \ op-fil-rec.cc op-fil-str.cc op-list.cc op-m-cm.cc \ - op-m-cs.cc op-m-m.cc op-m-nd.cc op-m-s.cc op-nd-m.cc \ - op-nd-nd.cc op-nd-s.cc op-range.cc op-s-cm.cc \ - op-s-cs.cc op-s-m.cc op-s-nd.cc op-s-s.cc op-str-m.cc \ + op-m-cs.cc op-m-m.cc op-m-s.cc op-range.cc op-s-cm.cc \ + op-s-cs.cc op-s-m.cc op-s-s.cc op-str-m.cc \ op-str-s.cc op-str-str.cc OP_SRC := $(addprefix OPERATORS/, $(OP_XSRC)) @@ -112,8 +111,7 @@ ov-complex.cc ov-str-mat.cc ov-struct.cc ov-va-args.cc \ ov-colon.cc ov-bool-mat.cc ov-bool.cc ov-file.cc ov-cell.cc \ ov.cc ov-fcn.cc ov-builtin.cc ov-dld-fcn.cc ov-mapper.cc \ - ov-usr-fcn.cc ov-base-nd-array.cc ov-re-nd-array.cc \ - ov-fcn-handle.cc ov-typeinfo.cc + ov-usr-fcn.cc ov-fcn-handle.cc ov-typeinfo.cc PT_SRC := pt.cc pt-arg-list.cc pt-assign.cc pt-bp.cc pt-binop.cc \ pt-cell.cc pt-check.cc pt-cmd.cc pt-colon.cc pt-const.cc \
--- a/src/TEMPLATE-INST/Array-tc.cc +++ b/src/TEMPLATE-INST/Array-tc.cc @@ -34,6 +34,9 @@ #include "Array2.h" #include "Array2.cc" +#include "ArrayN.h" +#include "ArrayN.cc" + #include "DiagArray2.h" #include "DiagArray2.cc" @@ -57,11 +60,17 @@ template class Array2<octave_value>; +#if 0 + template int assign (Array2<octave_value>&, const Array2<octave_value>&); template int assign (Array2<octave_value>&, const Array2<octave_value>&, const octave_value&); +#endif + +template class ArrayN<octave_value>; + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/data.cc +++ b/src/data.cc @@ -726,22 +726,25 @@ int nargin = args.length (); - if (nargin == 1 && nargout < 3) + if (nargin == 1) { - int nr = args(0).rows (); - int nc = args(0).columns (); + dim_vector dimensions = args(0).dims (); + + int ndims = dimensions.length (); - if (nargout == 0 || nargout == 1) + Matrix m (1, ndims); + + if (nargout > 1) { - Matrix m (1, 2); - m (0, 0) = nr; - m (0, 1) = nc; - retval(0) = m; + while (ndims--) + retval(ndims) = dimensions(ndims); } - else if (nargout == 2) + else { - retval(1) = nc; - retval(0) = nr; + for (int i = 0; i < ndims; i++) + m(0, i) = dimensions(i); + + retval(0) = m; } } else if (nargin == 2 && nargout < 2) @@ -931,7 +934,7 @@ int ndim = 0; int type = 0; - Array<int> dims; + dim_vector dims; // Check for type information.
--- a/src/load-save.cc +++ b/src/load-save.cc @@ -4387,7 +4387,7 @@ for (Octave_map::iterator i = m.begin (); i != m.end (); i++) { // write the data of each element - octave_value_list elts = m.contents (i); + Cell elts = m.contents (i); for (int j = 0; j < len; j++) {
--- a/src/oct-map.cc +++ b/src/oct-map.cc @@ -34,12 +34,12 @@ #include "oct-map.h" #include "utils.h" -octave_value_list +Cell Octave_map::operator [] (const std::string& key) const { const_iterator p = seek (key); - return p != end () ? p->second : octave_value_list (); + return p != end () ? p->second : Cell (); } string_vector @@ -94,7 +94,7 @@ } Octave_map& -Octave_map::assign (const idx_vector& idx, const Octave_map& rhs) +Octave_map::assign (const octave_value_list& idx, const Octave_map& rhs) { string_vector t_keys = empty () ? rhs.keys () : equiv_keys (*this, rhs); @@ -106,7 +106,7 @@ { std::string key = t_keys[i]; - octave_value_list t_rhs = rhs[key]; + Cell t_rhs = rhs[key]; assign (idx, key, t_rhs); @@ -121,10 +121,10 @@ } Octave_map& -Octave_map::assign (const idx_vector& idx, const std::string& key, - const octave_value_list& rhs) +Octave_map::assign (const octave_value_list& idx, const std::string& key, + const Cell& rhs) { - octave_value_list tmp = map[key]; + Cell tmp = map[key]; octave_value fill_value = Matrix (); @@ -155,13 +155,13 @@ } Octave_map& -Octave_map::assign (const std::string& key, const octave_value_list& rhs) +Octave_map::assign (const std::string& key, const Cell& rhs) { if (empty ()) map[key] = rhs; else { - octave_value_list tmp = contents (begin ()); + Cell tmp = contents (begin ()); if (tmp.length () == rhs.length ()) map[key] = rhs; @@ -173,13 +173,13 @@ } Octave_map -Octave_map::index (idx_vector& idx) +Octave_map::index (const octave_value_list& idx) { Octave_map retval; for (iterator p = begin (); p != end (); p++) { - octave_value_list tmp = contents(p).index (idx); + Cell tmp = contents(p).index (idx); if (error_state) break;
--- a/src/oct-map.h +++ b/src/oct-map.h @@ -29,6 +29,7 @@ #include <map> +#include "Cell.h" #include "oct-obj.h" class string_vector; @@ -38,15 +39,21 @@ { public: - typedef std::map<std::string, octave_value_list>::iterator iterator; - typedef std::map<std::string, octave_value_list>::const_iterator const_iterator; + typedef std::map<std::string, Cell>::iterator iterator; + typedef std::map<std::string, Cell>::const_iterator const_iterator; Octave_map (void) : map (), array_len (0) { } Octave_map (const std::string& key, const octave_value& value) : map (), array_len (1) { - map[key] = octave_value_list (value); + map[key] = Cell (value); + } + + Octave_map (const std::string& key, const Cell& vals) + : map (), array_len (vals.length ()) + { + map[key] = vals; } Octave_map (const std::string& key, const octave_value_list& val_list) @@ -75,9 +82,9 @@ int empty (void) const { return map.empty (); } - octave_value_list& operator [] (const std::string& key) { return map[key]; } + Cell& operator [] (const std::string& key) { return map[key]; } - octave_value_list operator [] (const std::string& key) const; + Cell operator [] (const std::string& key) const; void del (const std::string& key) { @@ -94,10 +101,10 @@ std::string key (const_iterator p) const { return p->first; } - octave_value_list& contents (const_iterator p) + Cell& contents (const_iterator p) { return operator [] (key(p)); } - octave_value_list contents (const_iterator p) const + Cell contents (const_iterator p) const { return operator [] (key(p)); } const_iterator seek (const std::string& key) const { return map.find (key); } @@ -115,19 +122,19 @@ int array_length (void) const; - Octave_map& assign (const idx_vector& idx, const Octave_map& rhs); + Octave_map& assign (const octave_value_list& idx, const Octave_map& rhs); - Octave_map& assign (const idx_vector& idx, const std::string& key, - const octave_value_list& rhs); + Octave_map& assign (const octave_value_list& idx, const std::string& key, + const Cell& rhs); - Octave_map& assign (const std::string& key, const octave_value_list& rhs); + Octave_map& assign (const std::string& key, const Cell& rhs); - Octave_map index (idx_vector& idx); + Octave_map index (const octave_value_list& idx); private: // The map of names to values. - std::map<std::string, octave_value_list> map; + std::map<std::string, Cell> map; // The current size of this struct array; mutable int array_len;
--- a/src/ov-base-mat.cc +++ b/src/ov-base-mat.cc @@ -144,10 +144,13 @@ default: { - std::string n = type_name (); + Array<idx_vector> idx_vec (len); - error ("invalid number of indices (%d) for %s value", - len, n.c_str ()); + for (int i = 0; i < len; i++) + idx_vec(i) = idx(i).index_vector (); + + retval = MT (matrix.index (idx_vec, resize_ok, + MT::resize_fill_value ())); } break; } @@ -161,35 +164,10 @@ { int len = idx.length (); - switch (len) - { - case 2: - { - idx_vector i = idx (0).index_vector (); - idx_vector j = idx (1).index_vector (); - - matrix.set_index (i); - matrix.set_index (j); - - ::assign (matrix, rhs, MT::resize_fill_value ()); - } - break; + for (int i = 0; i < len; i++) + matrix.set_index (idx(i).index_vector ()); - case 1: - { - idx_vector i = idx (0).index_vector (); - - matrix.set_index (i); - - ::assign (matrix, rhs, MT::resize_fill_value ()); - } - break; - - default: - error ("invalid number of indices (%d) for indexed assignment", - len); - break; - } + ::assign (matrix, rhs, MT::resize_fill_value ()); } template <class MT>
--- a/src/ov-base-mat.h +++ b/src/ov-base-mat.h @@ -91,13 +91,16 @@ int rows (void) const { return matrix.rows (); } int columns (void) const { return matrix.columns (); } + dim_vector dims (void) const { return matrix.dims (); } + + // XXX FIXME XXX int length (void) const - { - int r = rows (); - int c = columns (); + { + int r = rows (); + int c = columns (); - return (r == 0 || c == 0) ? 0 : ((r > c) ? r : c); - } + return (r == 0 || c == 0) ? 0 : ((r > c) ? r : c); + } octave_value all (int dim = 0) const { return matrix.all (dim); } octave_value any (int dim = 0) const { return matrix.any (dim); }
--- a/src/ov-base.h +++ b/src/ov-base.h @@ -96,6 +96,8 @@ int columns (void) const { return -1; } + dim_vector dims (void) const { return dim_vector (rows (), columns ()); } + int length (void) const { return -1; } bool is_defined (void) const { return false; }
--- a/src/ov-bool-mat.cc +++ b/src/ov-bool-mat.cc @@ -44,7 +44,7 @@ #include "ov-re-mat.h" #include "pr-output.h" -template class octave_base_matrix<boolMatrix>; +template class octave_base_matrix<boolNDArray>; DEFINE_OCTAVE_ALLOCATOR (octave_bool_matrix); @@ -69,11 +69,16 @@ { octave_value *retval = 0; - int nr = matrix.rows (); - int nc = matrix.cols (); + if (matrix.ndims () == 2) + { + boolMatrix bm = matrix.matrix_value (); - if (nr == 1 && nc == 1) - retval = new octave_bool (matrix (0, 0)); + int nr = bm.rows (); + int nc = bm.cols (); + + if (nr == 1 && nc == 1) + retval = new octave_bool (bm (0, 0)); + } return retval; }
--- a/src/ov-bool-mat.h +++ b/src/ov-bool-mat.h @@ -48,21 +48,24 @@ // Character matrix values. class -octave_bool_matrix : public octave_base_matrix<boolMatrix> +octave_bool_matrix : public octave_base_matrix<boolNDArray> { public: octave_bool_matrix (void) - : octave_base_matrix<boolMatrix> () { } + : octave_base_matrix<boolNDArray> () { } + + octave_bool_matrix (const boolNDArray& bnda) + : octave_base_matrix<boolNDArray> (bnda) { } octave_bool_matrix (const boolMatrix& bm) - : octave_base_matrix<boolMatrix> (bm) { } + : octave_base_matrix<boolNDArray> (bm) { } octave_bool_matrix (const Array2<bool>& a) - : octave_base_matrix<boolMatrix> (a) { } + : octave_base_matrix<boolNDArray> (a) { } octave_bool_matrix (const octave_bool_matrix& bm) - : octave_base_matrix<boolMatrix> (bm) { } + : octave_base_matrix<boolNDArray> (bm) { } ~octave_bool_matrix (void) { } @@ -73,7 +76,9 @@ octave_value *try_narrowing_conversion (void); - idx_vector index_vector (void) const { return idx_vector (matrix); } + // XXX FIXME XXX + idx_vector index_vector (void) const + { return idx_vector (matrix.matrix_value ()); } bool is_bool_matrix (void) const { return true; } @@ -88,15 +93,16 @@ double scalar_value (bool frc_str_conv = false) const { return double_value (frc_str_conv); } - Matrix matrix_value (bool = false) const { return Matrix (matrix); } + Matrix matrix_value (bool = false) const + { return Matrix (matrix.matrix_value ()); } Complex complex_value (bool = false) const; ComplexMatrix complex_matrix_value (bool = false) const - { return ComplexMatrix (matrix); } + { return ComplexMatrix (matrix.matrix_value ( )); } boolMatrix bool_matrix_value (void) const - { return matrix; } + { return matrix.matrix_value (); } octave_value convert_to_str_internal (bool pad, bool force) const;
--- a/src/ov-cell.cc +++ b/src/ov-cell.cc @@ -327,47 +327,66 @@ void octave_cell::print_raw (std::ostream& os, bool) const { - int nr = rows (); - int nc = columns (); + int ndims = matrix.ndims (); + + if (ndims == 2) + { + int nr = rows (); + int nc = columns (); + + if (nr > 0 && nc > 0) + { + indent (os); + os << "{"; + newline (os); + + increment_indent_level (); + + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + OCTAVE_QUIT; + + OSSTREAM buf; + buf << "[" << i+1 << "," << j+1 << "]" << OSSTREAM_ENDS; - if (nr > 0 && nc > 0) + octave_value val = matrix(i,j); + + val.print_with_name (os, OSSTREAM_STR (buf)); + + OSSTREAM_FREEZE (buf); + } + } + + decrement_indent_level (); + + indent (os); + os << "}"; + newline (os); + } + else + { + os << "{}"; + if (nr > 0 || nc > 0) + os << "(" << nr << "x" << nc << ")"; + os << "\n"; + } + } + else { indent (os); os << "{"; - newline (os); - - increment_indent_level (); - - for (int j = 0; j < nc; j++) + dim_vector dv = matrix.dims (); + for (int i = 0; i < ndims; i++) { - for (int i = 0; i < nr; i++) - { - OCTAVE_QUIT; - - OSSTREAM buf; - buf << "[" << i+1 << "," << j+1 << "]" << OSSTREAM_ENDS; - - octave_value val = matrix(i,j); - - val.print_with_name (os, OSSTREAM_STR (buf)); - - OSSTREAM_FREEZE (buf); - } + if (i > 0) + os << "x"; + os << dv(i); } - - decrement_indent_level (); - - indent (os); - os << "}"; + os << " Cell Array}"; newline (os); } - else - { - os << "{}"; - if (nr > 0 || nc > 0) - os << "(" << nr << "x" << nc << ")"; - os << "\n"; - } } bool
--- a/src/ov-ch-mat.cc +++ b/src/ov-ch-mat.cc @@ -40,7 +40,7 @@ #include "gripes.h" #include "pr-output.h" -template class octave_base_matrix<charMatrix>; +template class octave_base_matrix<charNDArray>; DEFINE_OCTAVE_ALLOCATOR (octave_char_matrix);
--- a/src/ov-ch-mat.h +++ b/src/ov-ch-mat.h @@ -38,6 +38,7 @@ #include "error.h" #include "ov-base.h" + #include "ov-base-mat.h" #include "ov-typeinfo.h" @@ -49,30 +50,33 @@ // Character matrix values. class -octave_char_matrix : public octave_base_matrix<charMatrix> +octave_char_matrix : public octave_base_matrix<charNDArray> { public: octave_char_matrix (void) - : octave_base_matrix<charMatrix> () { } + : octave_base_matrix<charNDArray> () { } octave_char_matrix (const charMatrix& chm, bool = false) - : octave_base_matrix<charMatrix> (chm) { } + : octave_base_matrix<charNDArray> (chm) { } + + octave_char_matrix (const charNDArray& chm, bool = false) + : octave_base_matrix<charNDArray> (chm) { } octave_char_matrix (char c) - : octave_base_matrix<charMatrix> (c) { } + : octave_base_matrix<charNDArray> (c) { } octave_char_matrix (const char *s) - : octave_base_matrix<charMatrix> (s) { } + : octave_base_matrix<charNDArray> (s) { } octave_char_matrix (const std::string& s) - : octave_base_matrix<charMatrix> (s) { } + : octave_base_matrix<charNDArray> (s) { } octave_char_matrix (const string_vector& s) - : octave_base_matrix<charMatrix> (s) { } + : octave_base_matrix<charNDArray> (s) { } octave_char_matrix (const octave_char_matrix& chm) - : octave_base_matrix<charMatrix> (chm) { } + : octave_base_matrix<charNDArray> (chm) { } ~octave_char_matrix (void) { } @@ -91,18 +95,19 @@ double scalar_value (bool frc_str_conv = false) const { return double_value (frc_str_conv); } - Matrix matrix_value (bool = false) const { return Matrix (matrix); } + Matrix matrix_value (bool = false) const + { return Matrix (matrix.matrix_value ()); } Complex complex_value (bool = false) const; ComplexMatrix complex_matrix_value (bool = false) const - { return ComplexMatrix (matrix); } + { return ComplexMatrix (matrix.matrix_value ()); } charMatrix char_matrix_value (bool = false) const - { return matrix; } + { return matrix.matrix_value (); } octave_value convert_to_str_internal (bool, bool) const - { return octave_value (matrix, true); } + { return octave_value (matrix.matrix_value (), true); } protected:
--- a/src/ov-cs-list.h +++ b/src/ov-cs-list.h @@ -56,6 +56,9 @@ octave_cs_list (const octave_value_list& l) : octave_list (l) { } + octave_cs_list (const Cell& c) + : octave_list (c) { } + octave_cs_list (const octave_cs_list& l) : octave_list (l) { }
--- a/src/ov-cx-mat.cc +++ b/src/ov-cx-mat.cc @@ -45,7 +45,7 @@ #include "ov-scalar.h" #include "pr-output.h" -template class octave_base_matrix<ComplexMatrix>; +template class octave_base_matrix<ComplexNDArray>; DEFINE_OCTAVE_ALLOCATOR (octave_complex_matrix); @@ -56,22 +56,27 @@ { octave_value *retval = 0; - int nr = matrix.rows (); - int nc = matrix.cols (); + if (matrix.ndims () == 2) + { + ComplexMatrix cm = matrix.matrix_value (); - if (nr == 1 && nc == 1) - { - Complex c = matrix (0, 0); + int nr = cm.rows (); + int nc = cm.cols (); + + if (nr == 1 && nc == 1) + { + Complex c = matrix (0, 0); - if (imag (c) == 0.0) - retval = new octave_scalar (std::real (c)); - else - retval = new octave_complex (c); + if (imag (c) == 0.0) + retval = new octave_scalar (std::real (c)); + else + retval = new octave_complex (c); + } + else if (nr == 0 || nc == 0) + retval = new octave_matrix (Matrix (nr, nc)); + else if (cm.all_elements_are_real ()) + retval = new octave_matrix (::real (cm)); } - else if (nr == 0 || nc == 0) - retval = new octave_matrix (Matrix (nr, nc)); - else if (matrix.all_elements_are_real ()) - retval = new octave_matrix (::real (matrix)); return retval; } @@ -80,7 +85,7 @@ octave_complex_matrix::assign (const octave_value_list& idx, const ComplexMatrix& rhs) { - octave_base_matrix<ComplexMatrix>::assign (idx, rhs); + octave_base_matrix<ComplexNDArray>::assign (idx, rhs); } void @@ -89,35 +94,10 @@ { int len = idx.length (); - switch (len) - { - case 2: - { - idx_vector i = idx (0).index_vector (); - idx_vector j = idx (1).index_vector (); - - matrix.set_index (i); - matrix.set_index (j); - - ::assign (matrix, rhs); - } - break; + for (int i = 0; i < len; i++) + matrix.set_index (idx(i).index_vector ()); - case 1: - { - idx_vector i = idx (0).index_vector (); - - matrix.set_index (i); - - ::assign (matrix, rhs); - } - break; - - default: - error ("invalid number of indices (%d) for indexed matrix assignment", - len); - break; - } + ::assign (matrix, rhs); } bool @@ -158,7 +138,7 @@ if (! force_conversion && Vwarn_imag_to_real) gripe_implicit_conversion ("complex matrix", "real matrix"); - retval = ::real (matrix); + retval = ::real (matrix.matrix_value ()); return retval; } @@ -188,7 +168,7 @@ ComplexMatrix octave_complex_matrix::complex_matrix_value (bool) const { - return matrix; + return matrix.matrix_value (); } /*
--- a/src/ov-cx-mat.h +++ b/src/ov-cx-mat.h @@ -49,27 +49,30 @@ // Complex matrix values. class -octave_complex_matrix : public octave_base_matrix<ComplexMatrix> +octave_complex_matrix : public octave_base_matrix<ComplexNDArray> { public: octave_complex_matrix (void) - : octave_base_matrix<ComplexMatrix> () { } + : octave_base_matrix<ComplexNDArray> () { } + + octave_complex_matrix (const ComplexNDArray& m) + : octave_base_matrix<ComplexNDArray> (m) { } octave_complex_matrix (const ComplexMatrix& m) - : octave_base_matrix<ComplexMatrix> (m) { } + : octave_base_matrix<ComplexNDArray> (m) { } octave_complex_matrix (const ComplexDiagMatrix& d) - : octave_base_matrix<ComplexMatrix> (ComplexMatrix (d)) { } + : octave_base_matrix<ComplexNDArray> (ComplexMatrix (d)) { } octave_complex_matrix (const ComplexRowVector& v) - : octave_base_matrix<ComplexMatrix> (ComplexMatrix (v)) { } + : octave_base_matrix<ComplexNDArray> (ComplexMatrix (v)) { } octave_complex_matrix (const ComplexColumnVector& v) - : octave_base_matrix<ComplexMatrix> (ComplexMatrix (v)) { } + : octave_base_matrix<ComplexNDArray> (ComplexMatrix (v)) { } octave_complex_matrix (const octave_complex_matrix& cm) - : octave_base_matrix<ComplexMatrix> (cm) { } + : octave_base_matrix<ComplexNDArray> (cm) { } ~octave_complex_matrix (void) { }
--- a/src/ov-list.cc +++ b/src/ov-list.cc @@ -33,6 +33,7 @@ #include "lo-sstream.h" #include "lo-utils.h" +#include "Cell.h" #include "defun.h" #include "error.h" #include "ov-list.h" @@ -42,6 +43,17 @@ DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_list, "list"); +octave_list::octave_list (const Cell& c) + : octave_base_value (), lst () +{ + int n = c.length (); + + lst.resize (n); + + for (int i = 0; i < n; i++) + lst(i) = c(i); +} + octave_value octave_list::subsref (const std::string& type, const std::list<octave_value_list>& idx)
--- a/src/ov-list.h +++ b/src/ov-list.h @@ -56,6 +56,8 @@ octave_list (const octave_value_list& l) : octave_base_value (), lst (l) { } + octave_list (const Cell& c); + octave_list (const octave_list& l) : octave_base_value (), lst (l.lst) { }
--- a/src/ov-re-mat.cc +++ b/src/ov-re-mat.cc @@ -53,7 +53,7 @@ #define UCHAR_MAX 255 #endif -template class octave_base_matrix<Matrix>; +template class octave_base_matrix<NDArray>; DEFINE_OCTAVE_ALLOCATOR (octave_matrix); @@ -64,11 +64,8 @@ { octave_value *retval = 0; - int nr = matrix.rows (); - int nc = matrix.cols (); - - if (nr == 1 && nc == 1) - retval = new octave_scalar (matrix (0, 0)); + if (matrix.nelem () == 1) + retval = new octave_scalar (matrix (0)); return retval; } @@ -100,6 +97,14 @@ return retval; } +// XXX FIXME XXX + +Matrix +octave_matrix::matrix_value (bool) const +{ + return matrix.matrix_value (); +} + Complex octave_matrix::complex_value (bool) const { @@ -122,6 +127,14 @@ return retval; } +// XXX FIXME XXX + +ComplexMatrix +octave_matrix::complex_matrix_value (bool) const +{ + return ComplexMatrix (matrix.matrix_value ()); +} + octave_value octave_matrix::convert_to_str_internal (bool, bool) const {
--- a/src/ov-re-mat.h +++ b/src/ov-re-mat.h @@ -49,27 +49,30 @@ // Real matrix values. class -octave_matrix : public octave_base_matrix<Matrix> +octave_matrix : public octave_base_matrix<NDArray> { public: octave_matrix (void) - : octave_base_matrix<Matrix> () { } + : octave_base_matrix<NDArray> () { } octave_matrix (const Matrix& m) - : octave_base_matrix<Matrix> (m) { } + : octave_base_matrix<NDArray> (m) { } + + octave_matrix (const NDArray& nda) + : octave_base_matrix<NDArray> (nda) { } octave_matrix (const DiagMatrix& d) - : octave_base_matrix<Matrix> (Matrix (d)) { } + : octave_base_matrix<NDArray> (Matrix (d)) { } octave_matrix (const RowVector& v) - : octave_base_matrix<Matrix> (Matrix (v)) { } + : octave_base_matrix<NDArray> (Matrix (v)) { } octave_matrix (const ColumnVector& v) - : octave_base_matrix<Matrix> (Matrix (v)) { } + : octave_base_matrix<NDArray> (Matrix (v)) { } octave_matrix (const octave_matrix& m) - : octave_base_matrix<Matrix> (m) { } + : octave_base_matrix<NDArray> (m) { } ~octave_matrix (void) { } @@ -78,7 +81,8 @@ octave_value *try_narrowing_conversion (void); - idx_vector index_vector (void) const { return idx_vector (matrix); } + // XXX FIXME XXX + idx_vector index_vector (void) const { return idx_vector (matrix_value ()); } bool is_real_matrix (void) const { return true; } @@ -91,15 +95,14 @@ double scalar_value (bool frc_str_conv = false) const { return double_value (frc_str_conv); } - Matrix matrix_value (bool = false) const { return matrix; } + Matrix matrix_value (bool = false) const; Complex complex_value (bool = false) const; - ComplexMatrix complex_matrix_value (bool = false) const - { return ComplexMatrix (matrix); } + ComplexMatrix complex_matrix_value (bool = false) const; NDArray double_nd_array_value (bool = false) const - { return NDArray (matrix); } + { return matrix; } void increment (void) { matrix += 1.0; }
deleted file mode 100644 --- a/src/ov-re-nd-array.cc +++ /dev/null @@ -1,203 +0,0 @@ -/* - -Copyright (C) 2000 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. - -*/ - -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma implementation -#endif - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <iostream> - -#include "lo-ieee.h" -#include "lo-utils.h" -#include "mx-base.h" - -#include "gripes.h" -#include "oct-obj.h" -#include "oct-lvalue.h" -#include "ops.h" -#include "ov-base.h" -#include "ov-scalar.h" -#include "ov-re-mat.h" -#include "ov-base-nd-array.h" -#include "ov-base-nd-array.cc" -#include "ov-re-nd-array.h" -#include "pr-output.h" -#include "variables.h" - -template class octave_base_nd_array<NDArray>; - -DEFINE_OCTAVE_ALLOCATOR (octave_double_nd_array); - -DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_double_nd_array, - "double-nd-array"); - -octave_value * -octave_double_nd_array::try_narrowing_conversion (void) -{ - octave_value *retval = 0; - - array.maybe_delete_dims (); - - int n_dims = array.dims ().length (); - Array<int> dims = array.dims(); - - // Scalar - if (n_dims == 1 && dims(0) == 1) - { - retval = new octave_scalar (array(Array<int> (1,0))); - } - - // Matrix - if (n_dims == 2 || n_dims == 1) - { - retval = new octave_matrix (matrix_value ()); - } - - - - return retval; -} - -void -octave_double_nd_array::assign (const octave_value_list& idx, - const NDArray& rhs) -{ - int len = idx.length (); - - if ( len < 0) - { - error ("invalid number of indices (%d) for indexed matrix assignment", - len); - return; - } - - // XXX FIXME XXX -- where should this go? - array.set_max_indices (len); - - array.clear_index (); - - - for (int i = 0; i < len; i++) - { - idx_vector temp = idx(i).index_vector (); - array.set_index(temp); - } - - ::assign (array, rhs); - - // When subclasses of ArrayN are constructed, add an extra arguemnt - // resize_fill_value () -} - -bool -octave_double_nd_array::valid_as_scalar_index (void) const -{ - // XXX FIXME XXX - return false; -} - -double -octave_double_nd_array::double_value (bool) const -{ - double retval = lo_ieee_nan_value (); - - // XXX FIXME XXX - - gripe_invalid_conversion ("real nd-array", "real scalar"); - - return retval; -} - - -Matrix -octave_double_nd_array::matrix_value (bool ) const -{ - Array<int> ra_idx (array.dimensions.length (), 0); - - return convert_slice_to_matrix (ra_idx); -} - -Matrix -octave_double_nd_array::convert_slice_to_matrix (const Array<int>& ra_idx) const -{ - int n_dims = array.dimensions.length (); - - assert(ra_idx.length () == n_dims); - - Array<int> idx (ra_idx); - Matrix retval; - - if (n_dims > 1) - { - int d1 = array.dimensions(0); - int d2 = array.dimensions(1); - - retval = Matrix (d1, d2); - - for (int i = 0; i < d1; i++) - { - idx(0) = i; - for (int j = 0; j < d2; j++) - { - idx(1) = j; - retval(i,j) = array.elem (idx); - } - } - } - else if (n_dims == 1) - { - int d1 = array.dimensions(0); - int d2 = 1; - - retval = Matrix (d1, d2); - - for (int i = 0; i < d1; i++) - { - idx(0) = i; - retval(i, 0) = array.elem (idx); - } - - } - return retval; -} - -Complex -octave_double_nd_array::complex_value (bool) const -{ - double tmp = lo_ieee_nan_value (); - - Complex retval (tmp, tmp); - - gripe_invalid_conversion ("real matrix", "complex scalar"); - - return retval; -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/
deleted file mode 100644 --- a/src/ov-re-nd-array.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - -Copyright (C) 2000 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. - -*/ - -#if !defined (octave_re_nd_array_h) -#define octave_re_nd_array_h 1 - -#if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) -#pragma interface -#endif - -#include <cstdlib> - -#include <iostream> -#include <string> - -#include "mx-base.h" -#include "oct-alloc.h" - -#include "error.h" -#include "ov-base.h" -#include "ov-base-nd-array.h" -#include "ov-typeinfo.h" - -class octave_value_list; - -// Real N-dimensional array values. - -class -octave_double_nd_array : public octave_base_nd_array<NDArray> -{ -public: - - octave_double_nd_array (void) - : octave_base_nd_array<NDArray> () { } - - octave_double_nd_array (const NDArray& a) - : octave_base_nd_array<NDArray> (a) { } - - octave_double_nd_array (const octave_double_nd_array& a) - : octave_base_nd_array<NDArray> (a) { } - - ~octave_double_nd_array (void) { } - - octave_value *clone (void) const - { return new octave_double_nd_array (*this); } - - octave_value *empty_clone (void) const - { return new octave_double_nd_array (); } - - octave_value *try_narrowing_conversion (void); - - void assign (const octave_value_list& idx, const NDArray& rhs); - - // Need to implement idx_vector (NDArray) for this one. - // - // idx_vector index_vector (void) const { return idx_vector (array); } - - bool is_real_nd_array (void) const { return true; } - - bool is_real_matrix (void) const { return false; } - - bool is_real_type (void) const { return true; } - - bool valid_as_scalar_index (void) const; - - double double_value (bool = false) const; - - NDArray double_nd_array_value (bool = false) const { return array; } - - double scalar_value (bool frc_str_conv = false) const - { return double_value (frc_str_conv); } - - Matrix matrix_value (bool = false) const; - - Complex complex_value (bool = false) const; - - ComplexMatrix complex_matrix_value (bool = false) const - { return ComplexMatrix (matrix_value ()); } - - Matrix convert_slice_to_matrix (const Array<int>& ra_idx) const; - -private: - - DECLARE_OCTAVE_ALLOCATOR - - DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA -}; - -#endif - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/
--- a/src/ov-scalar.h +++ b/src/ov-scalar.h @@ -90,8 +90,10 @@ { return Matrix (1, 1, scalar); } NDArray double_nd_array_value (bool = false) const - { Array<int> temp (1, 1); - return NDArray (temp, double_value ()); } + { + dim_vector temp (1, 1); + return NDArray (temp, double_value ()); + } Complex complex_value (bool = false) const { return scalar; }
--- a/src/ov-str-mat.cc +++ b/src/ov-str-mat.cc @@ -76,7 +76,7 @@ idx_vector i = idx (0).index_vector (); idx_vector j = idx (1).index_vector (); - retval = octave_value (charMatrix (matrix.index (i, j, resize_ok)), + retval = octave_value (charNDArray (matrix.index (i, j, resize_ok)), true); } break; @@ -85,12 +85,21 @@ { idx_vector i = idx (0).index_vector (); - retval = octave_value (charMatrix (matrix.index (i, resize_ok)), true); + retval = octave_value (charNDArray (matrix.index (i, resize_ok)), + true); } break; default: - error ("invalid number of indices (%d) for matrix value", len); + { + Array<idx_vector> idx_vec (len); + + for (int i = 0; i < len; i++) + idx_vec(i) = idx(i).index_vector (); + + retval = octave_value (charNDArray (matrix.index (idx_vec, resize_ok)), + true); + } break; } @@ -108,35 +117,10 @@ if (tmp.rows () == 1 && tmp.columns () == 0) tmp.resize (0, 0); - switch (len) - { - case 2: - { - idx_vector i = idx (0).index_vector (); - idx_vector j = idx (1).index_vector (); - - matrix.set_index (i); - matrix.set_index (j); - - ::assign (matrix, tmp, Vstring_fill_char); - } - break; + for (int i = 0; i < len; i++) + matrix.set_index (idx(i).index_vector ()); - case 1: - { - idx_vector i = idx (0).index_vector (); - - matrix.set_index (i); - - ::assign (matrix, tmp, Vstring_fill_char); - } - break; - - default: - error ("invalid number of indices (%d) for indexed matrix assignment", - len); - break; - } + ::assign (matrix, tmp, Vstring_fill_char); } bool @@ -155,7 +139,7 @@ if (! force_string_conv && Vwarn_str_to_num) gripe_implicit_conversion ("string", "real matrix"); - retval = Matrix (matrix); + retval = Matrix (matrix.matrix_value ()); return retval; } @@ -163,12 +147,21 @@ string_vector octave_char_matrix_str::all_strings (bool, bool) const { - int n = matrix.rows (); + string_vector retval; + + if (matrix.ndims () == 2) + { + charMatrix chm = matrix.matrix_value (); + + int n = chm.rows (); - string_vector retval (n); + retval.resize (n); - for (int i = 0; i < n; i++) - retval[i] = matrix.row_as_string (i, true); + for (int i = 0; i < n; i++) + retval[i] = chm.row_as_string (i, true); + } + else + error ("invalid conversion of charNDArray to string_vector"); return retval; } @@ -176,7 +169,18 @@ std::string octave_char_matrix_str::string_value (bool) const { - return matrix.row_as_string (0); // XXX FIXME??? XXX + std::string retval; + + if (matrix.ndims () == 2) + { + charMatrix chm = matrix.matrix_value (); + + retval = chm.row_as_string (0); // XXX FIXME??? XXX + } + else + error ("invalid conversion of charNDArray to string"); + + return retval; } void
--- a/src/ov-str-mat.h +++ b/src/ov-str-mat.h @@ -59,6 +59,9 @@ octave_char_matrix_str (const charMatrix& chm) : octave_char_matrix (chm) { } + octave_char_matrix_str (const charNDArray& chm) + : octave_char_matrix (chm) { } + octave_char_matrix_str (char c) : octave_char_matrix (c) { }
--- a/src/ov-struct.cc +++ b/src/ov-struct.cc @@ -44,10 +44,10 @@ DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_struct, "struct"); -octave_value_list +Cell octave_struct::dotref (const octave_value_list& idx) { - octave_value_list retval; + Cell retval; assert (idx.length () == 1); @@ -63,11 +63,13 @@ return retval; } +#if 0 static void gripe_invalid_index (void) { error ("invalid index for structure array"); } +#endif static void gripe_invalid_index_for_assignment (void) @@ -104,46 +106,28 @@ std::list<octave_value_list>::const_iterator p = idx.begin (); octave_value_list key_idx = *++p; - octave_value_list tmp = dotref (key_idx); + Cell tmp = dotref (key_idx); if (! error_state) { - octave_value_list t_idx = idx.front (); + Cell t = tmp.index (idx.front ()); - if (t_idx.length () == 1) - { - idx_vector i = t_idx(0).index_vector (); - octave_value_list t = tmp.index (i); + retval = (t.length () == 1) ? t(0) : octave_value (t, true); - retval = (t.length () == 1) ? t(0) : octave_value (t, true); - - // We handled two index elements, so tell - // next_subsref to skip both of them. + // We handled two index elements, so tell + // next_subsref to skip both of them. - skip++; - } - else - gripe_invalid_index (); + skip++; } } else - { - octave_value_list t_idx = idx.front (); - - if (t_idx.length () == 1) - { - idx_vector i = t_idx(0).index_vector (); - retval = map.index (i); - } - else - gripe_invalid_index (); - } + retval = map.index (idx.front ()); } break; case '.': { - octave_value_list t = dotref (idx.front ()); + Cell t = dotref (idx.front ()); retval = (t.length () == 1) ? t(0) : octave_value (t, true); } @@ -164,7 +148,7 @@ } octave_value -octave_struct::numeric_conv (const octave_value_list& val, +octave_struct::numeric_conv (const Cell& val, const std::string& type) { octave_value retval; @@ -204,48 +188,39 @@ std::list<octave_value_list>::const_iterator p = idx.begin (); octave_value_list t_idx = *p; - if (t_idx.length () == 1) - { - octave_value_list key_idx = *++p; + octave_value_list key_idx = *++p; + + assert (key_idx.length () == 1); - assert (key_idx.length () == 1); + std::string key = key_idx(0).string_value (); - std::string key = key_idx(0).string_value (); - - octave_value u; + octave_value u; - if (! map.contains (key)) - u = octave_value::empty_conv (type.substr (2), rhs); - else - { - octave_value_list map_val = map[key]; + if (! map.contains (key)) + u = octave_value::empty_conv (type.substr (2), rhs); + else + { + Cell map_val = map[key]; - octave_value_list t_idx = idx.front (); - - idx_vector i = t_idx(0).index_vector (); + Cell map_elt = map_val.index (idx.front (), true); - octave_value_list map_elt = map_val.index (i, true); + u = numeric_conv (map_elt, type.substr (2)); + } - u = numeric_conv (map_elt, type.substr (2)); - } - - if (! error_state) - { - std::list<octave_value_list> next_idx (idx); + if (! error_state) + { + std::list<octave_value_list> next_idx (idx); - // We handled two index elements, so subsasgn to - // needs to skip both of them. - - next_idx.erase (next_idx.begin ()); - next_idx.erase (next_idx.begin ()); + // We handled two index elements, so subsasgn to + // needs to skip both of them. - u.make_unique (); + next_idx.erase (next_idx.begin ()); + next_idx.erase (next_idx.begin ()); - t_rhs = u.subsasgn (type.substr (2), next_idx, rhs); - } + u.make_unique (); + + t_rhs = u.subsasgn (type.substr (2), next_idx, rhs); } - else - gripe_invalid_index_for_assignment (); } else gripe_invalid_index_for_assignment (); @@ -266,7 +241,7 @@ u = octave_value::empty_conv (type.substr (1), rhs); else { - octave_value_list map_val = map[key]; + Cell map_val = map[key]; u = numeric_conv (map_val, type.substr (1)); } @@ -310,47 +285,31 @@ if (! error_state) { - octave_value_list t_idx = idx.front (); - - if (t_idx.length () == 1) - { - idx_vector i = t_idx(0).index_vector (); - - map.assign (i, key, t_rhs); + map.assign (idx.front (), key, t_rhs); - if (! error_state) - retval = octave_value (this, count + 1); - else - gripe_failed_assignment (); - } + if (! error_state) + retval = octave_value (this, count + 1); else - gripe_invalid_index_for_assignment (); + gripe_failed_assignment (); } else gripe_failed_assignment (); } else { - octave_value_list t_idx = idx.front (); + Octave_map rhs_map = t_rhs.map_value (); - if (t_idx.length () == 1) + if (! error_state) { - idx_vector i = t_idx(0).index_vector (); - - Octave_map rhs_map = t_rhs.map_value (); + map.assign (idx.front (), rhs_map); if (! error_state) - { - map.assign (i, rhs_map); - - if (! error_state) - retval = octave_value (this, count + 1); - else - gripe_failed_assignment (); - } + retval = octave_value (this, count + 1); else - error ("invalid structure assignment"); + gripe_failed_assignment (); } + else + error ("invalid structure assignment"); } } break; @@ -420,7 +379,7 @@ for (Octave_map::const_iterator p = map.begin (); p != map.end (); p++) { std::string key = map.key (p); - octave_value_list val = map.contents (p); + Cell val = map.contents (p); octave_value tmp = (n == 1) ? val(0) : octave_value (val, true);
--- a/src/ov-struct.h +++ b/src/ov-struct.h @@ -67,7 +67,7 @@ octave_value *clone (void) const { return new octave_struct (*this); } octave_value *empty_clone (void) const { return new octave_struct (); } - octave_value_list dotref (const octave_value_list& idx); + Cell dotref (const octave_value_list& idx); octave_value subsref (const std::string& type, const std::list<octave_value_list>& idx); @@ -80,7 +80,7 @@ return octave_value_list (); } - static octave_value numeric_conv (const octave_value_list& val, + static octave_value numeric_conv (const Cell& val, const std::string& type); octave_value subsasgn (const std::string& type,
--- a/src/ov.cc +++ b/src/ov.cc @@ -323,10 +323,17 @@ return retval; } +octave_value * +octave_value::nil_rep (void) const +{ + static octave_base_value *nr = new octave_base_value (); + return nr; +} + octave_value::octave_value (void) - : rep (new octave_base_value ()) + : rep (nil_rep ()) { - rep->count = 1; + rep->count++; } octave_value::octave_value (short int i) @@ -393,11 +400,15 @@ rep->count = 1; } -octave_value::octave_value (const Cell& c) - : rep (new octave_cell (c)) +octave_value::octave_value (const Cell& c, bool is_cs_list) + : rep (0) { + if (is_cs_list) + rep = new octave_cs_list (c); + else + rep = new octave_cell (c); + rep->count = 1; - maybe_mutate (); } octave_value::octave_value (const Matrix& m) @@ -408,7 +419,7 @@ } octave_value::octave_value (const NDArray& a) - : rep (new octave_double_nd_array (a)) + : rep (new octave_matrix (a)) { rep->count = 1; maybe_mutate (); @@ -449,14 +460,12 @@ maybe_mutate (); } -#if 0 -octave_value::octave_value (const ArrayN<Complex>& a) - : rep (new octave_complex_nd_array (a)) +octave_value::octave_value (const ComplexNDArray& a) + : rep (new octave_complex_matrix (a)) { rep->count = 1; maybe_mutate (); } -#endif octave_value::octave_value (const ComplexDiagMatrix& d) : rep (new octave_complex_matrix (d)) @@ -492,6 +501,13 @@ maybe_mutate (); } +octave_value::octave_value (const boolNDArray& bnda) + : rep (new octave_bool_matrix (bnda)) +{ + rep->count = 1; + maybe_mutate (); +} + octave_value::octave_value (char c) : rep (new octave_char_matrix_str (c)) { @@ -521,13 +537,19 @@ } octave_value::octave_value (const charMatrix& chm, bool is_string) - : rep (0) + : rep (is_string + ? new octave_char_matrix_str (chm) + : new octave_char_matrix (chm)) { - if (is_string) - rep = new octave_char_matrix_str (chm); - else - rep = new octave_char_matrix (chm); + rep->count = 1; + maybe_mutate (); +} +octave_value::octave_value (const charNDArray& chm, bool is_string) + : rep (is_string + ? new octave_char_matrix_str (chm) + : new octave_char_matrix (chm)) +{ rep->count = 1; maybe_mutate (); } @@ -571,10 +593,8 @@ } octave_value::octave_value (const octave_value_list& l, bool is_cs_list) - : rep (0) + : rep (is_cs_list ? new octave_cs_list (l) : new octave_list (l)) { - rep = is_cs_list ? new octave_cs_list (l) : new octave_list (l); - rep->count = 1; } @@ -1751,7 +1771,6 @@ octave_scalar::register_type (); octave_complex::register_type (); octave_matrix::register_type (); - octave_double_nd_array::register_type (); octave_complex_matrix::register_type (); octave_range::register_type (); octave_bool::register_type ();
--- a/src/ov.h +++ b/src/ov.h @@ -182,25 +182,28 @@ octave_value (octave_time t); octave_value (double d); - octave_value (const Cell& m); + octave_value (const Cell& m, bool is_cs_list = false); octave_value (const Matrix& m); - octave_value (const NDArray& m); + octave_value (const NDArray& nda); octave_value (const DiagMatrix& d); octave_value (const RowVector& v); octave_value (const ColumnVector& v); octave_value (const Complex& C); octave_value (const ComplexMatrix& m); + octave_value (const ComplexNDArray& cnda); octave_value (const ArrayN<Complex>& m); octave_value (const ComplexDiagMatrix& d); octave_value (const ComplexRowVector& v); octave_value (const ComplexColumnVector& v); octave_value (bool b); octave_value (const boolMatrix& bm); + octave_value (const boolNDArray& bnda); octave_value (char c); octave_value (const char *s); octave_value (const std::string& s); octave_value (const string_vector& s); octave_value (const charMatrix& chm, bool is_string = false); + octave_value (const charNDArray& chnda, bool is_string = false); octave_value (double base, double limit, double inc); octave_value (const Range& r); octave_value (const Octave_map& m); @@ -315,6 +318,9 @@ virtual int columns (void) const { return rep->columns (); } + virtual dim_vector dims (void) const + { return rep->dims (); } + virtual int length (void) const { return rep->length (); } @@ -636,6 +642,8 @@ binary_op op_eq_to_binary_op (assign_op op); DECLARE_OCTAVE_ALLOCATOR + + octave_value *nil_rep (void) const; }; #define OV_UNOP_FN(name) \
--- a/src/pr-output.cc +++ b/src/pr-output.cc @@ -1485,6 +1485,24 @@ } } +void +octave_print_internal (std::ostream& os, const NDArray& nda, + bool pr_as_read_syntax, int extra_indent) +{ + switch (nda.ndims ()) + { + case 1: + case 2: + octave_print_internal (os, nda.matrix_value (), + pr_as_read_syntax, extra_indent); + break; + + default: + os << nda; + break; + } +} + static inline void pr_plus_format (std::ostream& os, const Complex& c) { @@ -1661,6 +1679,24 @@ } void +octave_print_internal (std::ostream& os, const ComplexNDArray& nda, + bool pr_as_read_syntax, int extra_indent) +{ + switch (nda.ndims ()) + { + case 1: + case 2: + octave_print_internal (os, nda.matrix_value (), + pr_as_read_syntax, extra_indent); + break; + + default: + os << nda; + break; + } +} + +void octave_print_internal (std::ostream& os, const Range& r, bool pr_as_read_syntax, int extra_indent) { @@ -1777,6 +1813,25 @@ } void +octave_print_internal (std::ostream& os, const boolNDArray& nda, + bool pr_as_read_syntax, + int extra_indent) +{ + switch (nda.ndims ()) + { + case 1: + case 2: + octave_print_internal (os, nda.matrix_value (), + pr_as_read_syntax, extra_indent); + break; + + default: + os << nda; + break; + } +} + +void octave_print_internal (std::ostream& os, const charMatrix& chm, bool pr_as_read_syntax, int /* extra_indent XXX FIXME XXX */, @@ -1823,6 +1878,25 @@ } } +void +octave_print_internal (std::ostream& os, const charNDArray& nda, + bool pr_as_read_syntax, int extra_indent, + bool pr_as_string) +{ + switch (nda.ndims ()) + { + case 1: + case 2: + octave_print_internal (os, nda.matrix_value (), + pr_as_read_syntax, extra_indent, pr_as_string); + break; + + default: + os << nda; + break; + } +} + extern void octave_print_internal (std::ostream&, const Cell&, bool, int, bool) {
--- a/src/pr-output.h +++ b/src/pr-output.h @@ -28,10 +28,14 @@ #include "oct-cmplx.h" class ComplexMatrix; +class ComplexNDArray; class Matrix; +class NDArray; class Range; class boolMatrix; +class boolNDArray; class charMatrix; +class charNDArray; class Cell; extern void @@ -44,6 +48,11 @@ int extra_indent = 0); extern void +octave_print_internal (std::ostream& os, const NDArray& nda, + bool pr_as_read_syntax = false, + int extra_indent = 0); + +extern void octave_print_internal (std::ostream& os, const Complex& c, bool pr_as_read_syntax = false); @@ -53,6 +62,11 @@ int extra_indent = 0); extern void +octave_print_internal (std::ostream& os, const ComplexNDArray& nda, + bool pr_as_read_syntax = false, + int extra_indent = 0); + +extern void octave_print_internal (std::ostream& os, const Range& r, bool pr_as_read_syntax = false, int extra_indent = 0); @@ -63,12 +77,23 @@ int extra_indent = 0); extern void +octave_print_internal (std::ostream& os, const boolNDArray& m, + bool pr_as_read_syntax = false, + int extra_indent = 0); + +extern void octave_print_internal (std::ostream& os, const charMatrix& chm, bool pr_as_read_syntax = false, int extra_indent = 0, bool pr_as_string = false); extern void +octave_print_internal (std::ostream& os, const charNDArray& chm, + bool pr_as_read_syntax = false, + int extra_indent = 0, + bool pr_as_string = false); + +extern void octave_print_internal (std::ostream& os, const Cell& cell, bool pr_as_read_syntax = false, int extra_indent = 0,
--- a/src/pt-loop.cc +++ b/src/pt-loop.cc @@ -379,7 +379,7 @@ { MAYBE_DO_BREAKPOINT; - octave_value_list val_lst = tmp_val.contents (p); + Cell val_lst = tmp_val.contents (p); octave_value val = (val_lst.length () == 1) ? val_lst(0) : octave_value (val_lst); @@ -490,7 +490,7 @@ { octave_value key = tmp_val.key (q); - octave_value_list val_lst = tmp_val.contents (q); + Cell val_lst = tmp_val.contents (q); int n = tmp_val.array_length ();
--- a/src/utils.cc +++ b/src/utils.cc @@ -766,7 +766,7 @@ } void -check_dimensions (Array<int>& dim, const char *warnfor) +check_dimensions (dim_vector& dim, const char *warnfor) { bool neg = false; @@ -788,7 +788,7 @@ void get_dimensions (const octave_value& a, const char *warn_for, - Array<int>& dim) + dim_vector& dim) { if (a.is_scalar_type ()) {
--- a/src/utils.h +++ b/src/utils.h @@ -67,11 +67,11 @@ extern int check_preference (const std::string& var); extern void -check_dimensions (Array<int>& dim, const char *warnfor); +check_dimensions (dim_vector& dim, const char *warnfor); extern void get_dimensions (const octave_value& a, const char *warn_for, - Array<int>& dim); + dim_vector& dim); extern void get_dimensions (const octave_value& a, const octave_value& b,
--- a/test/octave.test/matrix/matrix.exp +++ b/test/octave.test/matrix/matrix.exp @@ -196,7 +196,6 @@ set test ones-2 set prog_output "^ans = 1"; -setup_xfail *-*-* do_test ones-2.m set test zeros-1 @@ -205,7 +204,6 @@ set test zeros-2 set prog_output "^ans = 1" -setup_xfail *-*-* do_test zeros-2.m set test rand-1