diff liboctave/Array2-idx.h @ 1988:7b56630a1e05

[project @ 1996-03-02 00:33:22 by jwe] Initial revision
author jwe
date Sat, 02 Mar 1996 00:33:22 +0000
parents
children 1b57120c997b
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/liboctave/Array2-idx.h
@@ -0,0 +1,580 @@
+// Template array classes                              -*- C++ -*-
+/*
+
+Copyright (C) 1996 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 ();
+
+  int nr = d1;
+  int nc = d2;
+
+  if (n_idx == 2)
+    {
+      idx_vector *tmp = get_idx ();
+      idx_vector idx_i = tmp[0];
+      idx_vector idx_j = tmp[1];
+
+      int n = idx_i.freeze (nr, "row", liboctave_pzo_flag);
+      int m = idx_j.freeze (nc, "column", liboctave_pzo_flag);
+
+      if (idx_i && idx_j)
+	{
+	  if (n == 0)
+	    {
+	      if (m == 0 || idx_j.is_colon_equiv (nc, 1))
+		retval.resize (0, 0);
+	      else
+		(*current_liboctave_error_handler)
+		  ("invalid row index = 0");
+	    }
+	  else if (m == 0)
+	    {
+	      if (n == 0 || idx_i.is_colon_equiv (nr, 1))
+		retval.resize (0, 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.
+    }
+  else if (n_idx == 1)
+    {
+      if (nr == 1 && nc == 1)
+	{
+	  Array<T> tmp = Array<T>::value ();
+
+	  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);
+
+	  if (liboctave_dfi_flag)
+	    {
+	      idx_vector *tmp = get_idx ();
+	      idx_vector idx = tmp[0];
+
+	      if (idx.is_colon ())
+		result_is_column_vector = 1;
+	    }
+
+	  Array<T> tmp = Array<T>::value ();
+
+	  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)
+	{
+	  // This code is only for indexing matrices.  The vector
+	  // cases are handled above.
+
+	  idx_vector *tmp = get_idx ();
+	  idx_vector idx = tmp[0];
+
+	  idx.freeze (nr * nc, "matrix", liboctave_pzo_flag);
+
+	  if (idx)
+	    {
+	      int result_nr = idx.orig_rows ();
+	      int result_nc = idx.orig_columns ();
+
+	      if (idx.is_colon ())
+		{
+		  result_nr = nr * nc;
+		  result_nc = 1;
+		}
+	      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");
+    }
+  else
+    (*current_liboctave_error_handler)
+      ("invalid number of indices for matrix expression");
+
+  clear_index ();
+
+  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
+	{
+	  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 - num_to_delete;
+		  if (new_nc > 0)
+		    {
+		      T *new_data = new T [nr * new_nc];
+
+		      int jj = 0;
+		      int idx = 0;
+		      for (int j = 0; j < nc; j++)
+			{
+			  if (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 (nr, 1))
+    {
+      if (idx_i.is_colon_equiv (nc, 1))
+	resize (0, 0);
+      else
+	{
+	  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 - num_to_delete;
+		  if (new_nr > 0)
+		    {
+		      T *new_data = new T [new_nr * nc];
+
+		      int ii = 0;
+		      int idx = 0;
+		      for (int i = 0; i < nr; i++)
+			{
+			  if (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");
+		}
+	    }
+	}
+    }
+}
+
+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_pzo_flag,
+			    liboctave_rre_flag);
+
+      int m = idx_j.freeze (lhs_nc, "column", liboctave_pzo_flag,
+			    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 = rhs_nr;
+
+      if (idx_j_is_colon)
+	m = rhs_nc;
+
+      if (idx_i && idx_j)
+	{
+	  if (rhs_nr == 0 && rhs_nc == 0)
+	    {
+	      lhs.maybe_delete_elements (idx_i, idx_j);
+	    }
+	  else
+	    {
+	      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);
+		}
+
+	      if (n == rhs_nr && m == rhs_nc)
+		{
+		  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 (rhs_nr == 1 && rhs_nc == 1)
+		{
+		  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
+		{
+		  (*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)
+    {
+      if (lhs_nr == 0 || lhs_nc == 0
+	  || (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_pzo_flag,
+			      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 (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 ();
+
+			  if (liboctave_dfi_flag
+			      || (idx_nr == 1 && idx_nc == 1))
+			    {
+			      if (liboctave_pcv_flag)
+				{
+				  lhs.d1 = lhs.length ();
+				  lhs.d2 = 1;
+				}
+			      else
+				{
+				  lhs.d1 = 1;
+				  lhs.d2 = lhs.length ();
+				}
+			    }
+			  else if (idx_nr == 1 && rhs_nr == 1)
+			    {
+			      lhs.d1 = 1;
+			      lhs.d2 = lhs.length ();
+			    }
+			  else if (idx_nc == 1 && rhs_nc == 1)
+			    {
+			      lhs.d1 = lhs.length ();
+			      lhs.d2 = 1;
+			    }
+			  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_pzo_flag,
+		      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_pzo_flag,
+		      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",
+				liboctave_pzo_flag);
+
+	  if (idx)
+	    {
+	      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
+		{
+		  (*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++ ***
+;;; page-delimiter: "^/\\*" ***
+;;; End: ***
+*/