]> git.lyx.org Git - lyx.git/blob - boost/boost/multi_array.hpp
LFUN_ESCAPE gets ReadOnly (fix bug 1142)
[lyx.git] / boost / boost / multi_array.hpp
1 // Copyright (C) 2002 Ronald Garcia
2 //
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.
8 //
9 // This software is provided "as is" without express or implied warranty, 
10 // and with no claim as to its suitability for any purpose.
11 //
12
13 //  See http://www.boost.org/libs/multi_array for documentation.
14
15 #ifndef BOOST_MULTI_ARRAY_RG071801_HPP
16 #define BOOST_MULTI_ARRAY_RG071801_HPP
17
18 //
19 // multi_array.hpp - contains the multi_array class template
20 // declaration and definition
21 //
22
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"
32 #include <algorithm>
33 #include <cstddef>
34 #include <functional>
35 #include <numeric>
36 #include <vector>
37
38
39
40 namespace boost {
41   namespace detail {
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);
48         }
49       };
50     } //namespace multi_array
51   } // namespace detail
52
53 template<typename T, std::size_t NumDims,
54   typename Allocator>
55 class multi_array : 
56   public multi_array_ref<T,NumDims>
57 {
58   typedef multi_array_ref<T,NumDims> super_type;
59 public: 
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;
74
75
76   template <std::size_t NDims>
77   struct const_array_view {
78     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
79   };
80
81   template <std::size_t NDims>
82   struct array_view {
83     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
84   };
85
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> >();
91     allocate_space();
92   }
93
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> >();
100     allocate_space();
101   }
102
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> >();
110     allocate_space();
111   }
112
113
114   explicit multi_array(const detail::multi_array
115                        ::extent_gen<NumDims>& ranges) :
116     super_type((T*)initial_base_,ranges) {
117
118     allocate_space();
119   }
120
121
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) {
126
127     allocate_space();
128   }
129
130
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) {
136
137     allocate_space();
138   }
139
140   multi_array(const multi_array& rhs) :
141   super_type(rhs), allocator_(rhs.allocator_) {
142     allocate_space();
143     boost::copy_n(rhs.base_,rhs.num_elements(),base_);
144   }
145
146   template <typename OPtr>
147   multi_array(const detail::multi_array::
148               const_sub_array<T,NumDims,OPtr>& rhs) :
149     super_type(rhs) {
150     allocate_space();
151     std::copy(rhs.begin(),rhs.end(),this->begin());
152   }
153
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) :
159     super_type(rhs) {
160     allocate_space();
161     std::copy(rhs.begin(),rhs.end(),this->begin());
162   }
163
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);
169     return *this;
170   }
171
172   multi_array& operator=(const multi_array& other) {
173     if (&other != this) {
174       super_type::operator=(other);
175     }
176     return *this;
177   }
178
179
180   multi_array& resize(const detail::multi_array
181                       ::extent_gen<NumDims>& ranges) {
182
183
184     // build a multi_array with the specs given
185     multi_array new_array(ranges);
186
187
188     // build a view of tmp with the minimum extents
189
190     // Get the minimum extents of the arrays.
191     boost::array<size_type,NumDims> min_extents;
192
193     const size_type& (*min)(const size_type&, const size_type&) =
194       std::min<size_type>;
195     std::transform(new_array.extent_list_.begin(),new_array.extent_list_.end(),
196                    this->extent_list_.begin(),
197                    min_extents.begin(),
198                    min);
199
200     
201     // typedef boost::array<index,NumDims> index_list;
202     // Build index_gen objects to create views with the same shape
203
204     // these need to be separate to handle non-zero index bases
205     typedef detail::multi_array::index_gen<NumDims,NumDims> index_gen;
206     index_gen old_idxes;
207     index_gen new_idxes;
208
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());
213
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());
218
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];
222
223     // Set the right portion of the new array
224     view_new = view_old;
225
226     using std::swap;
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_);
239
240     return *this;
241   }
242
243
244   ~multi_array() {
245     deallocate_space();
246   }
247
248 private:
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());
255   }
256
257   void deallocate_space() {
258     if(base_) {
259       for(T* i = base_; i != base_+allocated_elements_; ++i)
260         allocator_.destroy(i);
261       allocator_.deallocate(base_,allocated_elements_);
262     }
263   }    
264   
265   typedef boost::array<size_type,NumDims> size_list;
266   typedef boost::array<index,NumDims> index_list;
267
268   Allocator allocator_;
269   T* base_;
270   size_type allocated_elements_;
271   enum {initial_base_ = 0};
272 };
273
274 } // namespace boost
275
276 #endif // BOOST_MULTI_ARRAY_RG071801_HPP