diff liboctave/Array.h @ 4513:508238e65af7

[project @ 2003-09-19 21:40:57 by jwe]
author jwe
date Fri, 19 Sep 2003 21:41:21 +0000
parents af308ca1a354
children b4449b1193ac
line wrap: on
line diff
--- a/liboctave/Array.h	Sat Sep 13 07:53:55 2003 +0000
+++ b/liboctave/Array.h	Fri Sep 19 21:41:21 2003 +0000
@@ -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 ()));
 }