changeset 1559:1adb4798e5c1

[project @ 1995-10-12 07:22:26 by jwe] Initial revision
author jwe
date Thu, 12 Oct 1995 07:22:26 +0000
parents 297e084c3857
children 27a03373de41
files liboctave/Array-flags.cc liboctave/Array-idx.h
diffstat 2 files changed, 803 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/Array-flags.cc	Thu Oct 12 07:22:26 1995 +0000
@@ -0,0 +1,52 @@
+//                                                       -*- C++ -*-
+/*
+
+Copyright (C) 1993, 1994, 1995 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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "Array.h"
+
+// These have to be defined somewhere, but only once.
+
+#if defined (HEAVYWEIGHT_INDEXING)
+#if defined (OCTAVE_SOURCE)
+#include "user-prefs.h"
+int& dfi_flag = user_pref.do_fortran_indexing;
+int& pcv_flag = user_pref.prefer_column_vectors;
+int& pzo_flag = user_pref.prefer_zero_one_indexing;
+int& rre_flag = user_pref.resize_on_range_error;
+#else
+int dfi_flag = 0;
+int pcv_flag = 0;
+int pzo_flag = 0;
+int rre_flag = 0;
+#endif
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; page-delimiter: "^/\\*" ***
+;;; End: ***
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/Array-idx.h	Thu Oct 12 07:22:26 1995 +0000
@@ -0,0 +1,751 @@
+// Template array classes                              -*- C++ -*-
+/*
+
+Copyright (C) 1995 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 "idx-vector.h"
+#include "lo-error.h"
+
+#if defined (OCTAVE_SOURCE)
+extern int& dfi_flag;
+extern int& pcv_flag;
+extern int& pzo_flag;
+extern int& rre_flag;
+#else
+extern int dfi_flag;
+extern int pcv_flag;
+extern int pzo_flag;
+extern int rre_flag;
+#endif
+
+template <class T>
+void
+ArrayRep<T>::clear_index (void)
+{
+  delete [] idx;
+  idx = 0;
+  idx_count = 0;
+}
+
+template <class T>
+void
+ArrayRep<T>::set_index (const idx_vector& i)
+{
+  if (! idx)
+    idx = new idx_vector [max_indices];
+
+  if (idx_count < max_indices)
+    {
+      idx[idx_count++] = i;
+    }
+  else
+    {
+      (*current_liboctave_error_handler)
+	("invalid number of indices specified");
+      clear_index ();
+    }
+}
+
+template <class T>
+Array<T>
+Array<T>::value (void)
+{
+  Array<T> retval;
+
+  idx_vector *tmp = get_idx ();
+  idx_vector idx = tmp[0];
+
+  int len = length ();
+
+  int n = idx.freeze (len, "vector", pzo_flag);
+
+  if (idx)
+    {
+      if (idx.is_colon_equiv (len))
+	{
+	  retval = *this;
+	}
+      else if (n == 0)
+	{
+	  retval.resize (0);
+	}
+      else if (len == 1 && n > 1
+	       && idx.one_zero_only ()
+	       && idx.ones_count () == n)
+	{
+	  retval.resize (n, elem (0));
+	}
+      else
+	{
+	  retval.resize (n);
+
+	  for (int i = 0; i < n; i++)
+	    {
+	      int ii = idx.elem (i);
+	      retval.elem (i) = elem (ii);
+	    }
+	}
+    }
+  // idx_vector::freeze() printed an error message for us.
+
+  clear_index ();
+
+  return retval;
+}
+
+template <class T>
+void
+Array<T>::maybe_delete_elements (idx_vector& idx)
+{
+  int len = length ();
+
+  if (len == 0)
+    return;
+
+  if (idx.is_colon_equiv (len, 1))
+    resize (0);
+  else
+    {
+      int num_to_delete = idx.length (len);
+
+      if (num_to_delete != 0)
+	{
+	  int new_len = len - num_to_delete;
+	  if (new_len > 0)
+	    {
+	      T *new_data = new T [new_len];
+
+	      int ii = 0;
+	      int iidx = 0;
+	      for (int i = 0; i < len; i++)
+		{
+		  if (i == idx.elem (iidx))
+		    iidx++;
+		  else
+		    {
+		      new_data[ii] = elem (i);
+		      ii++;
+		    }
+		}
+
+	      if (--rep->count <= 0)
+		delete rep;
+
+	      rep = new ArrayRep<T> (new_data, new_len);
+	      rep->count = 1;
+	      set_max_indices (1);
+	    }
+	  else
+	    (*current_liboctave_error_handler)
+	      ("%s: %d: internal indexing error", __FILE__, __LINE__);
+	}
+    }
+}
+
+// ??? FIXME ??? -- this doesn't handle assignment of empty vectors
+// to delete elements.  Should it?
+
+template <class LT, class RT>
+int
+assign (Array<LT>& lhs, const Array<RT>& rhs)
+{
+  int retval = 1;
+
+  idx_vector *tmp = lhs.get_idx ();
+
+  idx_vector idx = tmp[0];
+
+  int lhs_len = lhs.length ();
+  int rhs_len = rhs.length ();
+
+  int n = idx.freeze (lhs_len, "vector", pzo_flag, rre_flag);
+
+  if (n != 0)
+    {
+      if (rre_flag)
+	{
+	  int max_idx = idx.max () + 1;
+	  if (max_idx > lhs_len)
+	    lhs.resize (max_idx, 0.0);
+	}
+
+      if (rhs_len == n)
+	{
+	  for (int i = 0; i < n; i++)
+	    {
+	      int ii = idx.elem (i);
+	      lhs.elem (ii) = rhs.elem (i);
+	    }
+	}
+      else if (rhs_len == 1)
+	{
+	  RT scalar = rhs.elem (0);
+
+	  for (int i = 0; i < n; i++)
+	    {
+	      int ii = idx.elem (i);
+	      lhs.elem (ii) = scalar;
+	    }
+	}
+      else
+	{
+	  (*current_liboctave_error_handler)
+	    ("A(I) = X: X must be a scalar or a vector with same length as I");
+
+	  retval = 0;
+	}
+    }
+  else
+    {
+      (*current_liboctave_error_handler)
+	("A([]) = X: X must also be an empty matrix");
+
+      retval = 0;
+    }
+
+  lhs.clear_index ();
+
+  return retval;
+}
+
+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", pzo_flag);
+      int m = idx_j.freeze (nc, "column", 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 (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 (dfi_flag)
+	    {
+	      idx_vector *tmp = get_idx ();
+	      idx_vector idx = tmp[0];
+
+	      result_is_column_vector = idx.is_colon ();
+	    }
+
+	  Array<T> tmp = Array<T>::value ();
+
+	  int len = tmp.length ();
+
+	  if (result_is_column_vector)
+	    retval = Array2<T> (tmp, len, 1);
+	  else
+	    retval = Array2<T> (tmp, 1, len);
+	}
+      else if (dfi_flag)
+	{
+	  idx_vector *tmp = get_idx ();
+	  idx_vector idx = tmp[0];
+
+	  idx.freeze (nr * nc, "matrix", 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<T> (new_data, nr * new_nc);
+		      rep->count = 1;
+		      d2 = new_nc;
+		      set_max_indices (2);
+		    }
+		  else
+		    (*current_liboctave_error_handler)
+		      ("%s: %d: internal indexing error", __FILE__, __LINE__);
+		}
+	    }
+	}
+    }
+  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<T> (new_data, new_nr * nc);
+		      rep->count = 1;
+		      d1 = new_nr;
+		      set_max_indices (2);
+		    }
+		  else
+		    (*current_liboctave_error_handler)
+		      ("%s: %d: internal indexing error", __FILE__, __LINE__);
+		}
+	    }
+	}
+    }
+}
+
+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", pzo_flag, rre_flag);
+      int m = idx_j.freeze (lhs_nc, "column", pzo_flag, rre_flag);
+
+      if (idx_i && idx_j)
+	{
+	  if (rhs_nr == 0 && rhs_nc == 0)
+	    {
+	      lhs.maybe_delete_elements (idx_i, idx_j);
+	    }
+	  else
+	    {
+	      if (rre_flag)
+		{
+		  int max_row_idx = idx_i.max () + 1;
+		  int max_col_idx = 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)
+		{
+		  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 (0, 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)
+    {
+      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, pzo_flag, 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)
+			{
+			  if (pcv_flag)
+			    {
+			      lhs.d1 = lhs.length ();
+			      lhs.d2 = 1;
+			    }
+			  else
+			    {
+			      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_vector *tmp = lhs.get_idx ();
+
+	  idx_vector idx = tmp[0];
+
+	  idx.freeze (lhs_nc, "vector", pzo_flag, 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", pzo_flag, 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 (dfi_flag)
+	{
+	  idx_vector *tmp = lhs.get_idx ();
+	  idx_vector idx = tmp[0];
+
+	  int len = idx.freeze (lhs_nr * lhs_nc, "matrix", 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;
+}
+
+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>&)
+{
+  assert (0);
+  return 0;
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; page-delimiter: "^/\\*" ***
+;;; End: ***
+*/