home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
octa21fs.zip
/
octave
/
octave-2.1.23
/
liboctave
/
Array2-idx.h
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-15
|
14KB
|
697 lines
// 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)
{
idx_vector *tmp = get_idx ();
idx_vector idx = tmp[0];
return index (idx);
}
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) const
{
Array2<T> retval;
int nr = d1;
int nc = d2;
if (nr == 1 && nc == 1)
{
Array<T> tmp = Array<T>::index (idx);
int len = tmp.length ();
if (len == 0)
retval = Array2<T> (0, 0);
else
{
if (liboctave_pcv_flag)
retval = Array2<T> (tmp, len, 1);
else
retval = Array2<T> (tmp, 1, len);
}
}
else if (nr == 1 || nc == 1)
{
int result_is_column_vector = (nc == 1 || idx.is_colon ());
Array<T> tmp = Array<T>::index (idx);
int len = tmp.length ();
if (len == 0)
retval = Array2<T> (0, 0);
else
{
if (result_is_column_vector)
retval = Array2<T> (tmp, len, 1);
else
retval = Array2<T> (tmp, 1, len);
}
}
else if (liboctave_dfi_flag || idx.is_colon ())
{
// This code is only for indexing matrices. The vector
// cases are handled above.
idx.freeze (nr * nc, "matrix");
if (idx)
{
int result_nr = idx.orig_rows ();
int result_nc = idx.orig_columns ();
if (idx.is_colon ())
{
result_nr = nr * nc;
result_nc = result_nr ? 1 : 0;
}
else if (idx.one_zero_only ())
{
result_nr = idx.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.elem (k++);
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.
}
else
(*current_liboctave_error_handler)
("single index only valid for row or column vector");
return retval;
}
template <class T>
Array2<T>
Array2<T>::index (idx_vector& idx_i, idx_vector& idx_j) const
{
Array2<T> retval;
int nr = d1;
int nc = d2;
int n = idx_i.freeze (nr, "row");
int m = idx_j.freeze (nc, "column");
if (idx_i && idx_j)
{
if (idx_i.orig_empty () || idx_j.orig_empty ())
{
retval.resize (n, m);
}
else if (n == 0)
{
if (m == 0)
retval.resize (0, 0);
else if (idx_j.is_colon_equiv (nc, 1))
retval.resize (0, nc);
else if (idx_i.is_colon_equiv (nr, 1))
retval.resize (0, m);
else
(*current_liboctave_error_handler) ("invalid row index = 0");
}
else if (m == 0)
{
if (n == 0)
retval.resize (0, 0);
else if (idx_i.is_colon_equiv (nr, 1))
retval.resize (nr, 0);
else if (idx_j.is_colon_equiv (nc, 1))
retval.resize (n, 0);
else
(*current_liboctave_error_handler) ("invalid column index = 0");
}
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);
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_i, idx_vector& idx_j)
{
int nr = d1;
int nc = d2;
if (nr == 0 && nc == 0)
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 idx = 0;
for (int j = 0; j < nc; j++)
if (j == idx_j.elem (idx))
{
idx++;
new_nc--;
if (idx == num_to_delete)
break;
}
if (new_nc > 0)
{
T *new_data = new T [nr * new_nc];
int jj = 0;
idx = 0;
for (int j = 0; j < nc; j++)
{
if (idx < num_to_delete && j == idx_j.elem (idx))
idx++;
else
{
for (int i = 0; i < nr; i++)
new_data[nr*jj+i] = elem (i, j);
jj++;
}
}
if (--rep->count <= 0)
delete rep;
rep = new 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 idx = 0;
for (int i = 0; i < nr; i++)
if (i == idx_i.elem (idx))
{
idx++;
new_nr--;
if (idx == num_to_delete)
break;
}
if (new_nr > 0)
{
T *new_data = new T [new_nr * nc];
int ii = 0;
idx = 0;
for (int i = 0; i < nr; i++)
{
if (idx < num_to_delete && i == idx_i.elem (idx))
idx++;
else
{
for (int j = 0; j < nc; j++)
new_data[new_nr*j+ii] = elem (i, j);
ii++;
}
}
if (--rep->count <= 0)
delete rep;
rep = new 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 \
{ \
if (liboctave_rre_flag) \
{ \
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, 0.0); \
} \
} \
while (0)
template <class LT, class RT>
int
assign (Array2<LT>& lhs, const Array2<RT>& rhs)
{
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 ();
if (n_idx == 2)
{
idx_vector *tmp = lhs.get_idx ();
idx_vector idx_i = tmp[0];
idx_vector idx_j = tmp[1];
int n = idx_i.freeze (lhs_nr, "row", liboctave_rre_flag);
int m = idx_j.freeze (lhs_nc, "column", liboctave_rre_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)
{
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))
{
idx_vector *tmp = lhs.get_idx ();
idx_vector idx = tmp[0];
int lhs_len = lhs.length ();
int n = idx.freeze (lhs_len, 0, liboctave_rre_flag);
if (idx)
{
if (rhs_nr == 0 && rhs_nc == 0)
{
if (n != 0 && (lhs_nr != 0 || lhs_nc != 0))
{
idx_vector tmp (':');
lhs.maybe_delete_elements (idx, tmp);
}
}
else if (! liboctave_dfi_flag && lhs_is_empty
&& idx.is_colon ()
&& ! (rhs_nr == 1 || rhs_nc == 1))
{
(*current_liboctave_error_handler)
("A(:) = X: X must be a vector");
}
else
{
if (assign ((Array<LT>&) lhs, (Array<RT>&) rhs))
{
int len = lhs.length ();
if (len > 0)
{
int idx_nr = idx.orig_rows ();
int idx_nc = idx.orig_columns ();
// lhs_is_empty now means that lhs was
// *originally* empty, and lhs_len is the
// *original* length of the lhs.
if (liboctave_dfi_flag
|| (idx_nr == 1 && idx_nc == 1)
|| (rhs_nr == 1 && rhs_nc == 1 && lhs_len == 1))
{
if (liboctave_pcv_flag)
{
lhs.d1 = lhs.length ();
lhs.d2 = 1;
}
else
{
lhs.d1 = 1;
lhs.d2 = lhs.length ();
}
}
else if (lhs_is_empty && idx.is_colon ())
{
lhs.d1 = rhs.d1;
lhs.d2 = rhs.d2;
}
else if (rhs_nr == 1
&& (idx_nr == 1 || lhs_len == 1))
{
lhs.d1 = 1;
lhs.d2 = lhs.length ();
}
else if (rhs_nc == 1
&& (idx_nc == 1 || lhs_len == 1))
{
lhs.d1 = lhs.length ();
lhs.d2 = 1;
}
else if (idx_nr == 0 && idx_nc == 0)
{
if (! ((rhs.d1 == 1 && rhs.d2 == 1)
|| (rhs.d1 == 0 && rhs.d2 == 0)))
(*current_liboctave_error_handler)
("A([]) = X: X must be an empty matrix or scalar");
}
else
(*current_liboctave_error_handler)
("A(I) = X: X must be a scalar or a matrix with the same size as I");
}
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_vector *tmp = lhs.get_idx ();
idx_vector idx = tmp[0];
idx.freeze (lhs_nc, "vector", liboctave_rre_flag);
if (idx)
{
if (rhs_nr == 0 && rhs_nc == 0)
{
idx_vector tmp (':');
lhs.maybe_delete_elements (tmp, idx);
}
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_vector *tmp = lhs.get_idx ();
idx_vector idx = tmp[0];
idx.freeze (lhs_nr, "vector", liboctave_rre_flag);
if (idx)
{
if (rhs_nr == 0 && rhs_nc == 0)
{
idx_vector tmp (':');
lhs.maybe_delete_elements (idx, tmp);
}
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_dfi_flag)
{
idx_vector *tmp = lhs.get_idx ();
idx_vector idx = tmp[0];
int len = idx.freeze (lhs_nr * lhs_nc, "matrix");
if (idx)
{
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.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.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)
("single index only valid for row or column vector");
retval = 0;
}
}
else
{
(*current_liboctave_error_handler)
("invalid number of indices for matrix expression");
retval = 0;
}
lhs.clear_index ();
return retval;
}
/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/