X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmoof%2Fcml%2Fcore%2Fdynamic_2D.h;fp=src%2Fmoof%2Fcml%2Fcore%2Fdynamic_2D.h;h=374c53942745f72c7d1541380b84579e25cd3e9e;hb=831f04d4bc19a390415ac0bbac4331c7a65509bc;hp=0000000000000000000000000000000000000000;hpb=299af4f2047e767e5d79501c26444473bda64c64;p=chaz%2Fyoink diff --git a/src/moof/cml/core/dynamic_2D.h b/src/moof/cml/core/dynamic_2D.h new file mode 100644 index 0000000..374c539 --- /dev/null +++ b/src/moof/cml/core/dynamic_2D.h @@ -0,0 +1,248 @@ +/* -*- C++ -*- ------------------------------------------------------------ + +Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/ + +The Configurable Math Library (CML) is distributed under the terms of the +Boost Software License, v1.0 (see cml/LICENSE for details). + + *-----------------------------------------------------------------------*/ +/** @file + * @brief + */ + +#ifndef dynamic_2D_h +#define dynamic_2D_h + +#include +#include +#include +#include + +namespace cml { + +/** Dynamically-sized and allocated 2D array. + * + * @note The allocator should be an STL-compatible allocator. + * + * @internal The internal array type must have the proper copy + * semantics, otherwise copy construction will fail. + * + * @internal This class does not need a destructor. + */ +template +class dynamic_2D +{ + public: + + /* Record the allocator type: */ + typedef typename Alloc::template rebind::other allocator_type; + + /* Record the generator: */ + typedef dynamic generator_type; + + /* Standard: */ + 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; + + /* For matching by memory type: */ + typedef dynamic_memory_tag memory_tag; + + /* For matching by size type: */ + typedef dynamic_size_tag size_tag; + + /* For matching by resizability: */ + typedef resizable_tag resizing_tag; + + /* For matching by dimensions: */ + typedef twod_tag dimension_tag; + + /* To simplify the matrix transpose operator: */ + typedef dynamic_2D::type, + Layout,Alloc> transposed_type; + + /* To simplify the matrix row and column operators: */ + typedef dynamic_1D row_array_type; + typedef dynamic_1D col_array_type; + + + protected: + + /** Construct a dynamic array with no size. */ + dynamic_2D() : m_rows(0), m_cols(0), m_data(0), m_alloc() {} + + /** Construct a dynamic matrix given the dimensions. */ + explicit dynamic_2D(size_t rows, size_t 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: + + enum { array_rows = -1, array_cols = -1 }; + + + public: + + /** Return the number of rows in the array. */ + size_t rows() const { return m_rows; } + + /** Return the number of cols in the array. */ + size_t cols() const { return m_cols; } + + + public: + + /** Access the given element of the matrix. + * + * @param row row of element. + * @param col column of element. + * @returns mutable reference. + */ + reference operator()(size_t row, size_t col) { + return this->get_element(row, col, layout()); + } + + /** Access the given element of the matrix. + * + * @param row row of element. + * @param col column of element. + * @returns const reference. + */ + const_reference operator()(size_t row, size_t col) const { + return this->get_element(row, col, layout()); + } + + /** Return access to the data as a raw pointer. */ + pointer data() { return &m_data[0]; } + + /** Return access to the data as a raw pointer. */ + const_pointer data() const { return &m_data[0]; } + + + public: + + /** 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) { + + /* 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; + } + } + + + protected: + + reference get_element(size_t row, size_t col, row_major) { + return m_data[row*m_cols + col]; + } + + const_reference get_element(size_t row, size_t col, row_major) const { + return m_data[row*m_cols + col]; + } + + reference get_element(size_t row, size_t col, col_major) { + return m_data[col*m_rows + row]; + } + + const_reference get_element(size_t row, size_t col, col_major) const { + return m_data[col*m_rows + row]; + } + + + 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 data (may be NULL). */ + value_type* m_data; + + /** Allocator for the array. */ + allocator_type m_alloc; +}; + +} // namespace cml + +#endif + +// ------------------------------------------------------------------------- +// vim:ft=cpp