1 /* -*- C++ -*- ------------------------------------------------------------
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
8 *-----------------------------------------------------------------------*/
17 #include <cml/core/common.h>
18 #include <cml/core/dynamic_1D.h>
19 #include <cml/dynamic.h>
23 /** Dynamically-sized and allocated 2D array.
25 * @note The allocator should be an STL-compatible allocator.
27 * @internal The internal array type <em>must</em> have the proper copy
28 * semantics, otherwise copy construction will fail.
30 * @internal This class does not need a destructor.
32 template<typename Element
, typename Layout
, class Alloc
>
37 /* Record the allocator type: */
38 typedef typename
Alloc::template rebind
<Element
>::other allocator_type
;
40 /* Record the generator: */
41 typedef dynamic
<Alloc
> generator_type
;
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
;
50 /* For matching by memory layout: */
51 typedef Layout layout
;
53 /* For matching by memory type: */
54 typedef dynamic_memory_tag memory_tag
;
56 /* For matching by size type: */
57 typedef dynamic_size_tag size_tag
;
59 /* For matching by resizability: */
60 typedef resizable_tag resizing_tag
;
62 /* For matching by dimensions: */
63 typedef twod_tag dimension_tag
;
65 /* To simplify the matrix transpose operator: */
66 typedef dynamic_2D
<typename
cml::remove_const
<Element
>::type
,
67 Layout
,Alloc
> transposed_type
;
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
;
76 /** Construct a dynamic array with no size. */
77 dynamic_2D() : m_rows(0), m_cols(0), m_data(0), m_alloc() {}
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()
83 this->resize(rows
, cols
);
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()
100 enum { array_rows
= -1, array_cols
= -1 };
105 /** Return the number of rows in the array. */
106 size_t rows() const { return m_rows
; }
108 /** Return the number of cols in the array. */
109 size_t cols() const { return m_cols
; }
114 /** Access the given element of the matrix.
116 * @param row row of element.
117 * @param col column of element.
118 * @returns mutable reference.
120 reference
operator()(size_t row
, size_t col
) {
121 return this->get_element(row
, col
, layout());
124 /** Access the given element of the matrix.
126 * @param row row of element.
127 * @param col column of element.
128 * @returns const reference.
130 const_reference
operator()(size_t row
, size_t col
) const {
131 return this->get_element(row
, col
, layout());
134 /** Return access to the data as a raw pointer. */
135 pointer
data() { return &m_data
[0]; }
137 /** Return access to the data as a raw pointer. */
138 const_pointer
data() const { return &m_data
[0]; }
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.
148 * @warning This is not guaranteed to preserve the original data.
150 void resize(size_t rows
, size_t cols
) {
152 /* Nothing to do if the size isn't changing: */
153 if(rows
== m_rows
&& cols
== m_cols
) return;
155 /* Destroy the current array contents: */
158 /* Set the new size if non-zero: */
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());
164 /* Success, so save the new array and the dimensions: */
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.
175 void copy(const dynamic_2D
& other
) {
177 /* Nothing to do if it's the same array: */
178 if(&other
== this) return;
180 /* Destroy the current array contents: */
183 /* Set the new size if non-zero: */
184 size_t rows
= other
.rows(), cols
= other
.cols();
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
]);
190 /* Success, so save the new array and the dimensions: */
200 reference
get_element(size_t row
, size_t col
, row_major
) {
201 return m_data
[row
*m_cols
+ col
];
204 const_reference
get_element(size_t row
, size_t col
, row_major
) const {
205 return m_data
[row
*m_cols
+ col
];
208 reference
get_element(size_t row
, size_t col
, col_major
) {
209 return m_data
[col
*m_rows
+ row
];
212 const_reference
get_element(size_t row
, size_t col
, col_major
) const {
213 return m_data
[col
*m_rows
+ row
];
219 /** Destroy the current contents of the array. */
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
);
233 /** Current array dimensions (may be 0,0). */
234 size_t m_rows
, m_cols
;
236 /** Array data (may be NULL). */
239 /** Allocator for the array. */
240 allocator_type m_alloc
;
247 // -------------------------------------------------------------------------