version bump cml to version 1.0.2
[chaz/yoink] / src / Moof / cml / core / dynamic_2D.h
1 /* -*- C++ -*- ------------------------------------------------------------
2
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
4
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
7
8 *-----------------------------------------------------------------------*/
9 /** @file
10 * @brief
11 */
12
13 #ifndef dynamic_2D_h
14 #define dynamic_2D_h
15
16 #include <memory>
17 #include <cml/core/common.h>
18 #include <cml/core/dynamic_1D.h>
19 #include <cml/dynamic.h>
20
21 namespace cml {
22
23 /** Dynamically-sized and allocated 2D array.
24 *
25 * @note The allocator should be an STL-compatible allocator.
26 *
27 * @internal The internal array type <em>must</em> have the proper copy
28 * semantics, otherwise copy construction will fail.
29 *
30 * @internal This class does not need a destructor.
31 */
32 template<typename Element, typename Layout, class Alloc>
33 class dynamic_2D
34 {
35 public:
36
37 /* Record the allocator type: */
38 typedef typename Alloc::template rebind<Element>::other allocator_type;
39
40 /* Record the generator: */
41 typedef dynamic<Alloc> generator_type;
42
43 /* Standard: */
44 typedef typename allocator_type::value_type value_type;
45 typedef typename allocator_type::pointer pointer;
46 typedef typename allocator_type::reference reference;
47 typedef typename allocator_type::const_reference const_reference;
48 typedef typename allocator_type::const_pointer const_pointer;
49
50 /* For matching by memory layout: */
51 typedef Layout layout;
52
53 /* For matching by memory type: */
54 typedef dynamic_memory_tag memory_tag;
55
56 /* For matching by size type: */
57 typedef dynamic_size_tag size_tag;
58
59 /* For matching by resizability: */
60 typedef resizable_tag resizing_tag;
61
62 /* For matching by dimensions: */
63 typedef twod_tag dimension_tag;
64
65 /* To simplify the matrix transpose operator: */
66 typedef dynamic_2D<typename cml::remove_const<Element>::type,
67 Layout,Alloc> transposed_type;
68
69 /* To simplify the matrix row and column operators: */
70 typedef dynamic_1D<Element,Alloc> row_array_type;
71 typedef dynamic_1D<Element,Alloc> col_array_type;
72
73
74 protected:
75
76 /** Construct a dynamic array with no size. */
77 dynamic_2D() : m_rows(0), m_cols(0), m_data(0), m_alloc() {}
78
79 /** Construct a dynamic matrix given the dimensions. */
80 explicit dynamic_2D(size_t rows, size_t cols)
81 : m_rows(0), m_cols(0), m_data(0), m_alloc()
82 {
83 this->resize(rows, cols);
84 }
85
86 /** Copy construct a dynamic matrix. */
87 dynamic_2D(const dynamic_2D& other)
88 : m_rows(0), m_cols(0), m_data(0), m_alloc()
89 {
90 this->copy(other);
91 }
92
93 ~dynamic_2D() {
94 this->destroy();
95 }
96
97
98 public:
99
100 enum { array_rows = -1, array_cols = -1 };
101
102
103 public:
104
105 /** Return the number of rows in the array. */
106 size_t rows() const { return m_rows; }
107
108 /** Return the number of cols in the array. */
109 size_t cols() const { return m_cols; }
110
111
112 public:
113
114 /** Access the given element of the matrix.
115 *
116 * @param row row of element.
117 * @param col column of element.
118 * @returns mutable reference.
119 */
120 reference operator()(size_t row, size_t col) {
121 return this->get_element(row, col, layout());
122 }
123
124 /** Access the given element of the matrix.
125 *
126 * @param row row of element.
127 * @param col column of element.
128 * @returns const reference.
129 */
130 const_reference operator()(size_t row, size_t col) const {
131 return this->get_element(row, col, layout());
132 }
133
134 /** Return access to the data as a raw pointer. */
135 pointer data() { return &m_data[0]; }
136
137 /** Return access to the data as a raw pointer. */
138 const_pointer data() const { return &m_data[0]; }
139
140
141 public:
142
143 /** Set the array dimensions. The previous contents are destroyed
144 * before reallocating the array. If the number of rows and columns
145 * isn't changing, nothing happens. Also, if either rows or cols is 0,
146 * the array is cleared.
147 *
148 * @warning This is not guaranteed to preserve the original data.
149 */
150 void resize(size_t rows, size_t cols) {
151
152 /* Nothing to do if the size isn't changing: */
153 if(rows == m_rows && cols == m_cols) return;
154
155 /* Destroy the current array contents: */
156 this->destroy();
157
158 /* Set the new size if non-zero: */
159 if(rows*cols > 0) {
160 value_type* data = m_alloc.allocate(rows*cols);
161 for(size_t i = 0; i < rows*cols; ++ i)
162 m_alloc.construct(&data[i], value_type());
163
164 /* Success, so save the new array and the dimensions: */
165 m_rows = rows;
166 m_cols = cols;
167 m_data = data;
168 }
169 }
170
171 /** Copy the other array. The previous contents are destroyed before
172 * reallocating the array. If other == *this, nothing happens. Also,
173 * if either other.rows() or other.cols() is 0, the array is cleared.
174 */
175 void copy(const dynamic_2D& other) {
176
177 /* Nothing to do if it's the same array: */
178 if(&other == this) return;
179
180 /* Destroy the current array contents: */
181 this->destroy();
182
183 /* Set the new size if non-zero: */
184 size_t rows = other.rows(), cols = other.cols();
185 if(rows*cols > 0) {
186 value_type* data = m_alloc.allocate(rows*cols);
187 for(size_t i = 0; i < rows*cols; ++ i)
188 m_alloc.construct(&data[i], other[i]);
189
190 /* Success, so save the new array and the dimensions: */
191 m_rows = rows;
192 m_cols = cols;
193 m_data = data;
194 }
195 }
196
197
198 protected:
199
200 reference get_element(size_t row, size_t col, row_major) {
201 return m_data[row*m_cols + col];
202 }
203
204 const_reference get_element(size_t row, size_t col, row_major) const {
205 return m_data[row*m_cols + col];
206 }
207
208 reference get_element(size_t row, size_t col, col_major) {
209 return m_data[col*m_rows + row];
210 }
211
212 const_reference get_element(size_t row, size_t col, col_major) const {
213 return m_data[col*m_rows + row];
214 }
215
216
217 protected:
218
219 /** Destroy the current contents of the array. */
220 void destroy() {
221 if(m_data) {
222 for(size_t i = 0; i < m_rows*m_cols; ++ i)
223 m_alloc.destroy(&m_data[i]);
224 m_alloc.deallocate(m_data, m_rows*m_cols);
225 m_rows = m_cols = 0;
226 m_data = 0;
227 }
228 }
229
230
231 protected:
232
233 /** Current array dimensions (may be 0,0). */
234 size_t m_rows, m_cols;
235
236 /** Array data (may be NULL). */
237 value_type* m_data;
238
239 /** Allocator for the array. */
240 allocator_type m_alloc;
241 };
242
243 } // namespace cml
244
245 #endif
246
247 // -------------------------------------------------------------------------
248 // vim:ft=cpp
This page took 0.041277 seconds and 4 git commands to generate.