1 // Copyright 2002 The Trustees of Indiana University.
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 // Boost.MultiArray Library
8 // Authors: Ronald Garcia
11 // See http://www.boost.org/libs/multi_array for documentation.
13 #ifndef BOOST_MULTI_ARRAY_RG071801_HPP
14 #define BOOST_MULTI_ARRAY_RG071801_HPP
17 // multi_array.hpp - contains the multi_array class template
18 // declaration and definition
21 #include "boost/multi_array/base.hpp"
22 #include "boost/multi_array/collection_concept.hpp"
23 #include "boost/multi_array/copy_array.hpp"
24 #include "boost/multi_array/iterator.hpp"
25 #include "boost/multi_array/subarray.hpp"
26 #include "boost/multi_array/multi_array_ref.hpp"
27 #include "boost/multi_array/algorithm.hpp"
28 #include "boost/array.hpp"
29 #include "boost/type_traits.hpp"
40 namespace multi_array {
41 struct populate_index_ranges {
42 multi_array_types::index_range
43 operator()(multi_array_types::index base,
44 multi_array_types::size_type extent) {
45 return multi_array_types::index_range(base,base+extent);
48 } //namespace multi_array
51 template<typename T, std::size_t NumDims,
54 public multi_array_ref<T,NumDims>
56 typedef multi_array_ref<T,NumDims> super_type;
58 typedef typename super_type::value_type value_type;
59 typedef typename super_type::reference reference;
60 typedef typename super_type::const_reference const_reference;
61 typedef typename super_type::iterator iterator;
62 typedef typename super_type::const_iterator const_iterator;
63 typedef typename super_type::reverse_iterator reverse_iterator;
64 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
65 typedef typename super_type::element element;
66 typedef typename super_type::size_type size_type;
67 typedef typename super_type::difference_type difference_type;
68 typedef typename super_type::index index;
69 typedef typename super_type::extent_range extent_range;
72 template <std::size_t NDims>
73 struct const_array_view {
74 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
77 template <std::size_t NDims>
79 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
82 explicit multi_array() :
83 super_type((T*)initial_base_) {
87 template <class ExtentList>
89 ExtentList const& extents
90 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
91 , typename detail::multi_array::disable_non_sub_array<ExtentList>::type* = 0
94 super_type((T*)initial_base_,extents) {
95 boost::function_requires<
96 detail::multi_array::CollectionConcept<ExtentList> >();
100 template <class ExtentList>
101 explicit multi_array(ExtentList const& extents,
102 const general_storage_order<NumDims>& so) :
103 super_type((T*)initial_base_,extents,so) {
104 boost::function_requires<
105 detail::multi_array::CollectionConcept<ExtentList> >();
109 template <class ExtentList>
110 explicit multi_array(ExtentList const& extents,
111 const general_storage_order<NumDims>& so,
112 Allocator const& alloc) :
113 super_type((T*)initial_base_,extents,so), allocator_(alloc) {
114 boost::function_requires<
115 detail::multi_array::CollectionConcept<ExtentList> >();
120 explicit multi_array(const detail::multi_array
121 ::extent_gen<NumDims>& ranges) :
122 super_type((T*)initial_base_,ranges) {
128 explicit multi_array(const detail::multi_array
129 ::extent_gen<NumDims>& ranges,
130 const general_storage_order<NumDims>& so) :
131 super_type((T*)initial_base_,ranges,so) {
137 explicit multi_array(const detail::multi_array
138 ::extent_gen<NumDims>& ranges,
139 const general_storage_order<NumDims>& so,
140 Allocator const& alloc) :
141 super_type((T*)initial_base_,ranges,so), allocator_(alloc) {
146 multi_array(const multi_array& rhs) :
147 super_type(rhs), allocator_(rhs.allocator_) {
149 boost::copy_n(rhs.base_,rhs.num_elements(),base_);
152 template <typename OPtr>
153 multi_array(const detail::multi_array::
154 const_sub_array<T,NumDims,OPtr>& rhs) :
157 std::copy(rhs.begin(),rhs.end(),this->begin());
160 // For some reason, gcc 2.95.2 doesn't pick the above template
161 // member function when passed a subarray, so i was forced to
162 // duplicate the functionality here...
163 multi_array(const detail::multi_array::
164 sub_array<T,NumDims>& rhs) :
167 std::copy(rhs.begin(),rhs.end(),this->begin());
170 // Since assignment is a deep copy, multi_array_ref
171 // contains all the necessary code.
172 template <typename ConstMultiArray>
173 multi_array& operator=(const ConstMultiArray& other) {
174 super_type::operator=(other);
178 multi_array& operator=(const multi_array& other) {
179 if (&other != this) {
180 super_type::operator=(other);
186 multi_array& resize(const detail::multi_array
187 ::extent_gen<NumDims>& ranges) {
190 // build a multi_array with the specs given
191 multi_array new_array(ranges);
194 // build a view of tmp with the minimum extents
196 // Get the minimum extents of the arrays.
197 boost::array<size_type,NumDims> min_extents;
199 const size_type& (*min)(const size_type&, const size_type&) =
201 std::transform(new_array.extent_list_.begin(),new_array.extent_list_.end(),
202 this->extent_list_.begin(),
207 // typedef boost::array<index,NumDims> index_list;
208 // Build index_gen objects to create views with the same shape
210 // these need to be separate to handle non-zero index bases
211 typedef detail::multi_array::index_gen<NumDims,NumDims> index_gen;
215 std::transform(new_array.index_base_list_.begin(),
216 new_array.index_base_list_.end(),
217 min_extents.begin(),old_idxes.ranges_.begin(),
218 detail::multi_array::populate_index_ranges());
220 std::transform(this->index_base_list_.begin(),
221 this->index_base_list_.end(),
222 min_extents.begin(),new_idxes.ranges_.begin(),
223 detail::multi_array::populate_index_ranges());
225 // Build same-shape views of the two arrays
227 multi_array::BOOST_NESTED_TEMPLATE array_view<NumDims>::type view_old = (*this)[old_idxes];
229 multi_array::BOOST_NESTED_TEMPLATE array_view<NumDims>::type view_new = new_array[new_idxes];
231 // Set the right portion of the new array
235 // Swap the internals of these arrays.
236 swap(this->super_type::base_,new_array.super_type::base_);
237 swap(this->storage_,new_array.storage_);
238 swap(this->extent_list_,new_array.extent_list_);
239 swap(this->stride_list_,new_array.stride_list_);
240 swap(this->index_base_list_,new_array.index_base_list_);
241 swap(this->origin_offset_,new_array.origin_offset_);
242 swap(this->directional_offset_,new_array.directional_offset_);
243 swap(this->num_elements_,new_array.num_elements_);
244 swap(this->allocator_,new_array.allocator_);
245 swap(this->base_,new_array.base_);
246 swap(this->allocated_elements_,new_array.allocated_elements_);
257 void allocate_space() {
258 typename Allocator::const_pointer no_hint=0;
259 base_ = allocator_.allocate(this->num_elements(),no_hint);
260 this->set_base_ptr(base_);
261 allocated_elements_ = this->num_elements();
262 std::uninitialized_fill_n(base_,allocated_elements_,T());
265 void deallocate_space() {
267 for(T* i = base_; i != base_+allocated_elements_; ++i)
268 allocator_.destroy(i);
269 allocator_.deallocate(base_,allocated_elements_);
273 typedef boost::array<size_type,NumDims> size_list;
274 typedef boost::array<index,NumDims> index_list;
276 Allocator allocator_;
278 size_type allocated_elements_;
279 enum {initial_base_ = 0};
284 #endif // BOOST_MULTI_ARRAY_RG071801_HPP