changeset 9731:7b9cbaad68d6

extend Array<T>
author Jaroslav Hajek <highegg@gmail.com>
date Fri, 16 Oct 2009 10:28:26 +0200
parents dd4aa19c3053
children b4fdfee405b5
files liboctave/Array.cc liboctave/Array.h liboctave/ArrayN.h liboctave/ChangeLog src/ChangeLog src/DLD-FUNCTIONS/cellfun.cc
diffstat 6 files changed, 95 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/Array.cc	Thu Oct 15 10:13:07 2009 +0200
+++ b/liboctave/Array.cc	Fri Oct 16 10:28:26 2009 +0200
@@ -51,11 +51,19 @@
   : rep (a.rep), dimensions (dv), 
     slice_data (a.slice_data), slice_len (a.slice_len)
 {
+  if (dv.numel () != a.numel ())
+    {
+      std::string dimensions_str = dimensions.str ();
+      std::string new_dims_str = dv.str ();
+
+      (*current_liboctave_error_handler)
+        ("reshape: can't reshape %s array to %s array",
+         dimensions_str.c_str (), new_dims_str.c_str ());
+    }
+
+  // This goes here because if an exception is thrown by the above,
+  // destructor will be never called.
   rep->count++;
-
-  if (a.numel () < dv.numel ())
-    (*current_liboctave_error_handler)
-      ("Array::Array (const Array&, const dim_vector&): dimension mismatch");
 }
 
 template <class T>
@@ -414,30 +422,51 @@
   return foo;
 }
 
+
+template <class T>
+Array<T>
+Array<T>::column (octave_idx_type k) const
+{
+  octave_idx_type r = dimensions(0);
+#ifdef BOUNDS_CHECKING
+  if (k < 0 || k * r >= numel ())
+    range_error ("column", k);
+#endif
+
+  return Array<T> (*this, dim_vector (r, 1), k*r, k*r + r);
+}
+
 template <class T>
 Array<T>
-Array<T>::reshape (const dim_vector& new_dims) const
+Array<T>::page (octave_idx_type k) const
+{
+  octave_idx_type r = dimensions(0), c = dimensions (1), p = r*c;
+#ifdef BOUNDS_CHECKING
+  if (k < 0 || k * p >= numel ())
+    range_error ("page", k);
+#endif
+
+  return Array<T> (*this, dim_vector (r, c), k*p, k*p + p);
+}
+
+template <class T>
+Array<T>
+Array<T>::linearize (void) const
 {
-  Array<T> retval;
-
-  if (dimensions != new_dims)
-    {
-      if (dimensions.numel () == new_dims.numel ())
-	retval = Array<T> (*this, new_dims);
-      else
-	{
-	  std::string dimensions_str = dimensions.str ();
-	  std::string new_dims_str = new_dims.str ();
-
-	  (*current_liboctave_error_handler)
-	    ("reshape: can't reshape %s array to %s array",
-	     dimensions_str.c_str (), new_dims_str.c_str ());
-	}
-    }
-  else
-    retval = *this;
-
-  return retval;
+  octave_idx_type n = numel ();
+  return Array<T> (*this, dim_vector (n, 1), 0, n);
+}
+
+template <class T>
+Array<T>
+Array<T>::linear_slice (octave_idx_type lo, octave_idx_type up) const
+{
+#ifdef BOUNDS_CHECKING
+  if (lo < 0 || up > numel ())
+    range_error ("linear_slice", lo, up);
+#endif
+  if (up < lo) up = lo;
+  return Array<T> (*this, dim_vector (up - lo, 1), lo, up);
 }
 
 // Helper class for multi-d dimension permuting (generalized transpose).
--- a/liboctave/Array.h	Thu Oct 15 10:13:07 2009 +0200
+++ b/liboctave/Array.h	Fri Oct 16 10:28:26 2009 +0200
@@ -151,7 +151,7 @@
     {
       rep->count++;
       slice_data = a.slice_data + l;
-      slice_len = std::min (u, a.slice_len) - l;
+      slice_len = u - l;
     }
 
 private:
@@ -239,6 +239,7 @@
       fill (val);
     }
 
+  // Reshape constructor.
   Array (const Array<T>& a, const dim_vector& dv);
 
   ~Array (void)
@@ -455,7 +456,23 @@
   T operator () (const Array<octave_idx_type>& ra_idx) const { return elem (ra_idx); }
 #endif
 
-  Array<T> reshape (const dim_vector& new_dims) const;
+  // Fast extractors. All of these produce shallow copies.
+  // Warning: none of these do check bounds, unless BOUNDS_CHECKING is on!
+
+  // Extract column: A(:,k+1).
+  Array<T> column (octave_idx_type k) const;
+  // Extract page: A(:,:,k+1).
+  Array<T> page (octave_idx_type k) const;
+
+  // Give this array as a column vector: A(:).
+  Array<T> linearize (void) const;
+
+  // Extract a slice from this array as a column vector: A(:)(lo+1:up).
+  // Must be 0 <= lo && up <= numel. May be up < lo.
+  Array<T> linear_slice (octave_idx_type lo, octave_idx_type up) const;
+
+  Array<T> reshape (const dim_vector& new_dims) const
+    { return Array<T> (*this, new_dims); }
 
   Array<T> permute (const Array<octave_idx_type>& vec, bool inv = false) const;
   Array<T> ipermute (const Array<octave_idx_type>& vec) const
--- a/liboctave/ArrayN.h	Thu Oct 15 10:13:07 2009 +0200
+++ b/liboctave/ArrayN.h	Fri Oct 16 10:28:26 2009 +0200
@@ -84,6 +84,16 @@
       return *this;
     }
 
+  ArrayN<T> column (octave_idx_type k) const
+    { return Array<T>::column (k); }
+  ArrayN<T> page (octave_idx_type k) const
+    { return Array<T>::page (k); }
+
+  ArrayN<T> linearize (void) const
+    { return Array<T>::linearize (); }
+  ArrayN<T> linear_slice (octave_idx_type lo, octave_idx_type up) const
+    { return Array<T>::linear_slice (lo, up); }
+
   ArrayN<T> reshape (const dim_vector& new_dims) const
     { return Array<T>::reshape (new_dims); }
 
--- a/liboctave/ChangeLog	Thu Oct 15 10:13:07 2009 +0200
+++ b/liboctave/ChangeLog	Fri Oct 16 10:28:26 2009 +0200
@@ -1,3 +1,10 @@
+2009-10-16  Jaroslav Hajek  <highegg@gmail.com>
+
+	* Array.cc (Array<T>::column, Array<T>::page, Array<T>::linearize,
+	Array<T>::linear_slice): New methods.
+	* Array.h: Declare them
+	* ArrayN.h: Forward them.
+
 2009-10-14  Jaroslav Hajek  <highegg@gmail.com>
 
 	* oct-sort.cc (octave_sort<T>::nth_element): New overloaded method.
--- a/src/ChangeLog	Thu Oct 15 10:13:07 2009 +0200
+++ b/src/ChangeLog	Fri Oct 16 10:28:26 2009 +0200
@@ -1,3 +1,7 @@
+2009-10-16  Jaroslav Hajek  <highegg@gmail.com>
+
+	* DLD-FUNCTIONS/cellfun.cc (Fnum2cell): Use Array<T>::column here.
+
 2009-10-15  Jaroslav Hajek  <highegg@gmail.com>
 
 	* DLD-FUNCTIONS/lookup.cc (Flookup): Update docstring.
--- a/src/DLD-FUNCTIONS/cellfun.cc	Thu Oct 15 10:13:07 2009 +0200
+++ b/src/DLD-FUNCTIONS/cellfun.cc	Fri Oct 16 10:28:26 2009 +0200
@@ -993,8 +993,7 @@
       Cell retval (celldv);
       for (octave_idx_type i = 0; i < nelc; i++)
         {
-          NDA tmp (parray.index (idx_vector::colon, idx_vector (i)));
-          retval.xelem (i) = tmp.reshape (arraydv);
+          retval.xelem (i) = NDA (parray.column (i).reshape (arraydv));
         }
 
       return retval;