1 // Copyright (C) 2002 Ronald Garcia
3 // Permission to copy, use, sell and distribute this software is granted
4 // provided this copyright notice appears in all copies.
5 // Permission to modify the code and to distribute modified code is granted
6 // provided this copyright notice appears in all copies, and a notice
7 // that the code was modified is included with the copyright notice.
9 // This software is provided "as is" without express or implied warranty,
10 // and with no claim as to its suitability for any purpose.
13 // See http://www.boost.org/libs/multi_array for documentation.
15 #ifndef BOOST_MULTI_ARRAY_RG071801_HPP
16 #define BOOST_MULTI_ARRAY_RG071801_HPP
19 // multi_array.hpp - contains the multi_array class template
20 // declaration and definition
23 #include "boost/multi_array/base.hpp"
24 #include "boost/multi_array/collection_concept.hpp"
25 #include "boost/multi_array/copy_array.hpp"
26 #include "boost/multi_array/iterator.hpp"
27 #include "boost/multi_array/subarray.hpp"
28 #include "boost/multi_array/multi_array_ref.hpp"
29 #include "boost/multi_array/algorithm.hpp"
30 #include "boost/array.hpp"
31 #include "boost/type_traits.hpp"
42 namespace multi_array {
43 struct populate_index_ranges {
44 multi_array_types::index_range
45 operator()(multi_array_types::index base,
46 multi_array_types::size_type extent) {
47 return multi_array_types::index_range(base,base+extent);
50 } //namespace multi_array
53 template<typename T, std::size_t NumDims,
56 public multi_array_ref<T,NumDims>
58 typedef multi_array_ref<T,NumDims> super_type;
60 typedef typename super_type::value_type value_type;
61 typedef typename super_type::reference reference;
62 typedef typename super_type::const_reference const_reference;
63 typedef typename super_type::iterator iterator;
64 typedef typename super_type::const_iterator const_iterator;
65 typedef typename super_type::iter_base iter_base;
66 typedef typename super_type::const_iter_base const_iter_base;
67 typedef typename super_type::reverse_iterator reverse_iterator;
68 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
69 typedef typename super_type::element element;
70 typedef typename super_type::size_type size_type;
71 typedef typename super_type::difference_type difference_type;
72 typedef typename super_type::index index;
73 typedef typename super_type::extent_range extent_range;
76 template <std::size_t NDims>
77 struct const_array_view {
78 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
81 template <std::size_t NDims>
83 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
86 template <class ExtentList>
87 explicit multi_array(ExtentList const& extents) :
88 super_type((T*)initial_base_,extents) {
89 boost::function_requires<
90 detail::multi_array::CollectionConcept<ExtentList> >();
94 template <class ExtentList>
95 explicit multi_array(ExtentList const& extents,
96 const general_storage_order<NumDims>& so) :
97 super_type((T*)initial_base_,extents,so) {
98 boost::function_requires<
99 detail::multi_array::CollectionConcept<ExtentList> >();
103 template <class ExtentList>
104 explicit multi_array(ExtentList const& extents,
105 const general_storage_order<NumDims>& so,
106 Allocator const& alloc) :
107 super_type((T*)initial_base_,extents,so), allocator_(alloc) {
108 boost::function_requires<
109 detail::multi_array::CollectionConcept<ExtentList> >();
114 explicit multi_array(const detail::multi_array
115 ::extent_gen<NumDims>& ranges) :
116 super_type((T*)initial_base_,ranges) {
122 explicit multi_array(const detail::multi_array
123 ::extent_gen<NumDims>& ranges,
124 const general_storage_order<NumDims>& so) :
125 super_type((T*)initial_base_,ranges,so) {
131 explicit multi_array(const detail::multi_array
132 ::extent_gen<NumDims>& ranges,
133 const general_storage_order<NumDims>& so,
134 Allocator const& alloc) :
135 super_type((T*)initial_base_,ranges,so), allocator_(alloc) {
140 multi_array(const multi_array& rhs) :
141 super_type(rhs), allocator_(rhs.allocator_) {
143 boost::copy_n(rhs.base_,rhs.num_elements(),base_);
146 template <typename OPtr>
147 multi_array(const detail::multi_array::
148 const_sub_array<T,NumDims,OPtr>& rhs) :
151 std::copy(rhs.begin(),rhs.end(),this->begin());
154 // For some reason, gcc 2.95.2 doesn't pick the above template
155 // member function when passed a subarray, so i was forced to
156 // duplicate the functionality here...
157 multi_array(const detail::multi_array::
158 sub_array<T,NumDims>& rhs) :
161 std::copy(rhs.begin(),rhs.end(),this->begin());
164 // Since assignment is a deep copy, multi_array_ref
165 // contains all the necessary code.
166 template <typename ConstMultiArray>
167 multi_array& operator=(const ConstMultiArray& other) {
168 super_type::operator=(other);
172 multi_array& operator=(const multi_array& other) {
173 if (&other != this) {
174 super_type::operator=(other);
180 multi_array& resize(const detail::multi_array
181 ::extent_gen<NumDims>& ranges) {
184 // build a multi_array with the specs given
185 multi_array new_array(ranges);
188 // build a view of tmp with the minimum extents
190 // Get the minimum extents of the arrays.
191 boost::array<size_type,NumDims> min_extents;
193 const size_type& (*min)(const size_type&, const size_type&) =
195 std::transform(new_array.extent_list_.begin(),new_array.extent_list_.end(),
196 this->extent_list_.begin(),
201 // typedef boost::array<index,NumDims> index_list;
202 // Build index_gen objects to create views with the same shape
204 // these need to be separate to handle non-zero index bases
205 typedef detail::multi_array::index_gen<NumDims,NumDims> index_gen;
209 std::transform(new_array.index_base_list_.begin(),
210 new_array.index_base_list_.end(),
211 min_extents.begin(),old_idxes.ranges_.begin(),
212 detail::multi_array::populate_index_ranges());
214 std::transform(this->index_base_list_.begin(),
215 this->index_base_list_.end(),
216 min_extents.begin(),new_idxes.ranges_.begin(),
217 detail::multi_array::populate_index_ranges());
219 // Build same-shape views of the two arrays
220 typename multi_array::array_view<3>::type view_old = (*this)[old_idxes];
221 typename multi_array::array_view<3>::type view_new = new_array[new_idxes];
223 // Set the right portion of the new array
227 // Swap the internals of these arrays.
228 swap(this->super_type::base_,new_array.super_type::base_);
229 swap(this->storage_,new_array.storage_);
230 swap(this->extent_list_,new_array.extent_list_);
231 swap(this->stride_list_,new_array.stride_list_);
232 swap(this->index_base_list_,new_array.index_base_list_);
233 swap(this->origin_offset_,new_array.origin_offset_);
234 swap(this->directional_offset_,new_array.directional_offset_);
235 swap(this->num_elements_,new_array.num_elements_);
236 swap(this->allocator_,new_array.allocator_);
237 swap(this->base_,new_array.base_);
238 swap(this->allocated_elements_,new_array.allocated_elements_);
249 void allocate_space() {
250 typename Allocator::const_pointer no_hint=0;
251 base_ = allocator_.allocate(this->num_elements(),no_hint);
252 this->set_base_ptr(base_);
253 allocated_elements_ = this->num_elements();
254 std::uninitialized_fill_n(base_,allocated_elements_,T());
257 void deallocate_space() {
259 for(T* i = base_; i != base_+allocated_elements_; ++i)
260 allocator_.destroy(i);
261 allocator_.deallocate(base_,allocated_elements_);
265 typedef boost::array<size_type,NumDims> size_list;
266 typedef boost::array<index,NumDims> index_list;
268 Allocator allocator_;
270 size_type allocated_elements_;
271 enum {initial_base_ = 0};
276 #endif // BOOST_MULTI_ARRAY_RG071801_HPP