]> Dogcows Code - chaz/yoink/blobdiff - src/Moof/cml/core/dynamic_2D.h
version bump cml to version 1.0.2
[chaz/yoink] / src / Moof / cml / core / dynamic_2D.h
index c6ea38693f5b6152ee21c349f3ee16d8e2c6c067..374c53942745f72c7d1541380b84579e25cd3e9e 100644 (file)
@@ -13,7 +13,7 @@ Boost Software License, v1.0 (see cml/LICENSE for details).
 #ifndef dynamic_2D_h
 #define dynamic_2D_h
 
-#include <vector>
+#include <memory>
 #include <cml/core/common.h>
 #include <cml/core/dynamic_1D.h>
 #include <cml/dynamic.h>
@@ -40,15 +40,12 @@ class dynamic_2D
     /* Record the generator: */
     typedef dynamic<Alloc> generator_type;
 
-    /* Array implementation: */
-    typedef std::vector<Element,allocator_type> array_impl;
-
     /* Standard: */
-    typedef typename array_impl::value_type value_type;
-    typedef typename array_impl::pointer pointer; 
-    typedef typename array_impl::reference reference; 
-    typedef typename array_impl::const_reference const_reference; 
-    typedef typename array_impl::const_pointer const_pointer; 
+    typedef typename allocator_type::value_type value_type;
+    typedef typename allocator_type::pointer pointer; 
+    typedef typename allocator_type::reference reference; 
+    typedef typename allocator_type::const_reference const_reference; 
+    typedef typename allocator_type::const_pointer const_pointer; 
 
     /* For matching by memory layout: */
     typedef Layout layout;
@@ -66,7 +63,8 @@ class dynamic_2D
     typedef twod_tag dimension_tag;
 
     /* To simplify the matrix transpose operator: */
-    typedef dynamic_2D<Element,Layout,Alloc> transposed_type;
+    typedef dynamic_2D<typename cml::remove_const<Element>::type,
+            Layout,Alloc> transposed_type;
 
     /* To simplify the matrix row and column operators: */
     typedef dynamic_1D<Element,Alloc> row_array_type;
@@ -76,19 +74,25 @@ class dynamic_2D
   protected:
 
     /** Construct a dynamic array with no size. */
-    dynamic_2D() {}
+    dynamic_2D() : m_rows(0), m_cols(0), m_data(0), m_alloc() {}
 
-    /** Construct a dynamic matrix given the dimensions.
-     *
-     * This constructor is guaranteed to throw only if the allocator throws.
-     * If the array implementation guarantees that the array data structure is
-     * not modified after an exception, then this constructor is
-     * exception-safe.
-     *
-     * @throws only if the allocator throws during an allocation.
-     */
+    /** Construct a dynamic matrix given the dimensions. */
     explicit dynamic_2D(size_t rows, size_t cols) 
-        : m_rows(rows), m_cols(cols), m_data(rows*cols) {}
+        : m_rows(0), m_cols(0), m_data(0), m_alloc()
+               {
+         this->resize(rows, cols);
+       }
+
+    /** Copy construct a dynamic matrix. */
+    dynamic_2D(const dynamic_2D& other)
+        : m_rows(0), m_cols(0), m_data(0), m_alloc()
+               {
+         this->copy(other);
+       }
+
+    ~dynamic_2D() {
+      this->destroy();
+    }
 
 
   public:
@@ -114,7 +118,7 @@ class dynamic_2D
      * @returns mutable reference.
      */
     reference operator()(size_t row, size_t col) {
-        return get_element(row, col, layout());
+        return this->get_element(row, col, layout());
     }
 
     /** Access the given element of the matrix.
@@ -124,7 +128,7 @@ class dynamic_2D
      * @returns const reference.
      */
     const_reference operator()(size_t row, size_t col) const {
-        return get_element(row, col, layout());
+        return this->get_element(row, col, layout());
     }
 
     /** Return access to the data as a raw pointer. */
@@ -136,12 +140,58 @@ class dynamic_2D
 
   public:
 
-    /** Resize the array.
+    /** Set the array dimensions.  The previous contents are destroyed
+     * before reallocating the array.  If the number of rows and columns
+     * isn't changing, nothing happens.  Also, if either rows or cols is 0,
+     * the array is cleared.
      *
      * @warning This is not guaranteed to preserve the original data.
      */
     void resize(size_t rows, size_t cols) {
-        m_data.resize(rows*cols); m_rows = rows; m_cols = cols;
+
+      /* Nothing to do if the size isn't changing: */
+      if(rows == m_rows && cols == m_cols) return;
+
+      /* Destroy the current array contents: */
+      this->destroy();
+
+      /* Set the new size if non-zero: */
+      if(rows*cols > 0) {
+       value_type* data = m_alloc.allocate(rows*cols);
+       for(size_t i = 0; i < rows*cols; ++ i)
+         m_alloc.construct(&data[i], value_type());
+
+       /* Success, so save the new array and the dimensions: */
+       m_rows = rows;
+       m_cols = cols;
+       m_data = data;
+      }
+    }
+
+    /** Copy the other array.  The previous contents are destroyed before
+     * reallocating the array.  If other == *this, nothing happens.  Also,
+     * if either other.rows() or other.cols() is 0, the array is cleared.
+     */
+    void copy(const dynamic_2D& other) {
+
+      /* Nothing to do if it's the same array: */
+      if(&other == this) return;
+
+      /* Destroy the current array contents: */
+      this->destroy();
+
+      /* Set the new size if non-zero: */
+      size_t rows = other.rows(), cols = other.cols();
+      if(rows*cols > 0) {
+       value_type* data = m_alloc.allocate(rows*cols);
+       for(size_t i = 0; i < rows*cols; ++ i)
+         m_alloc.construct(&data[i], other[i]);
+
+       /* Success, so save the new array and the dimensions: */
+       m_rows = rows;
+       m_cols = cols;
+       m_data = data;
+      }
     }
 
 
@@ -166,8 +216,28 @@ class dynamic_2D
 
   protected:
 
+    /** Destroy the current contents of the array. */
+    void destroy() {
+      if(m_data) {
+       for(size_t i = 0; i < m_rows*m_cols; ++ i)
+         m_alloc.destroy(&m_data[i]);
+       m_alloc.deallocate(m_data, m_rows*m_cols);
+       m_rows = m_cols = 0;
+       m_data = 0;
+      }
+    }
+
+
+  protected:
+
+    /** Current array dimensions (may be 0,0). */
     size_t                      m_rows, m_cols;
-    array_impl                  m_data;
+
+    /** Array data (may be NULL). */
+    value_type*                        m_data;
+
+    /** Allocator for the array. */
+    allocator_type             m_alloc;
 };
 
 } // namespace cml
This page took 0.020863 seconds and 4 git commands to generate.