1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
---|
2 | "http://www.w3.org/TR/html4/loose.dtd"> |
---|
3 | <html> |
---|
4 | <!-- |
---|
5 | == Copyright 2002 The Trustees of Indiana University. |
---|
6 | |
---|
7 | == Use, modification and distribution is subject to the Boost Software |
---|
8 | == License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
9 | == http://www.boost.org/LICENSE_1_0.txt) |
---|
10 | |
---|
11 | == Boost.MultiArray Library |
---|
12 | == Authors: Ronald Garcia |
---|
13 | == Jeremy Siek |
---|
14 | == Andrew Lumsdaine |
---|
15 | == See http://www.boost.org/libs/multi_array for documentation. |
---|
16 | --> |
---|
17 | <head> |
---|
18 | <title>The Boost Multidimensional Array Library (Boost.MultiArray)</title> |
---|
19 | </head> |
---|
20 | |
---|
21 | <body> |
---|
22 | |
---|
23 | <h1> |
---|
24 | <img src="../../../boost.png" alt="boost logo" |
---|
25 | width="277" align="middle" height="86"> |
---|
26 | <br>The Boost Multidimensional Array Library |
---|
27 | <br>(Boost.MultiArray) |
---|
28 | </h1> |
---|
29 | |
---|
30 | <h2>Synopsis</h2> |
---|
31 | |
---|
32 | <p> |
---|
33 | The Boost Multidimensional Array Library provides a class template for |
---|
34 | multidimensional arrays, as well as semantically equivalent |
---|
35 | adaptors for arrays of contiguous data. The classes in this library |
---|
36 | implement a common interface, formalized as a generic programming |
---|
37 | concept. The interface design is in line with the precedent set by the |
---|
38 | C++ Standard Library containers. Boost MultiArray is a more efficient |
---|
39 | and convenient way to express N-dimensional arrays than existing |
---|
40 | alternatives (especially the |
---|
41 | <tt>std::vector<std::vector<...>></tt> formulation |
---|
42 | of N-dimensional arrays). The arrays provided by the library may be |
---|
43 | accessed using the familiar syntax of native C++ arrays. Additional |
---|
44 | features, such as resizing, reshaping, and creating views are |
---|
45 | available (and described below). |
---|
46 | |
---|
47 | |
---|
48 | <h2>Table of Contents</h2> |
---|
49 | |
---|
50 | <ol> |
---|
51 | <li><a href="#sec_introduction">Introduction</a> |
---|
52 | |
---|
53 | <li><a href="#sec_example">Short Example</a> |
---|
54 | |
---|
55 | <li><a href="#sec_components">MultiArray Components</a> |
---|
56 | |
---|
57 | <li><a href="#sec_assignment">Construction and Assignment</a> |
---|
58 | |
---|
59 | <li><a href="#sec_generators">Array View and Subarray Type Generators</a> |
---|
60 | |
---|
61 | <li><a href="#sec_dimensions">Specifying Array Dimensions</a> |
---|
62 | |
---|
63 | <li><a href="#sec_access">Accessing Elements</a> |
---|
64 | |
---|
65 | <li><a href="#sec_views">Creating Views</a> |
---|
66 | |
---|
67 | <li><a href="#sec_storage">Storage Ordering</a> |
---|
68 | |
---|
69 | <li><a href="#sec_base">Setting the Array Base</a> |
---|
70 | |
---|
71 | <li><a href="#sec_reshape">Changing an Array's Shape</a> |
---|
72 | |
---|
73 | <li><a href="#sec_resize">Resizing an Array</a> |
---|
74 | |
---|
75 | <li><a href="#sec_concepts">MultiArray Concept</a> |
---|
76 | |
---|
77 | <li><a href="#sec_testcases">Test Cases</a> |
---|
78 | |
---|
79 | <li><a href="#sec_related">Related Work</a> |
---|
80 | <li><a href="#sec_credits">Credits</a> |
---|
81 | </ol> |
---|
82 | |
---|
83 | |
---|
84 | <a name="sec_introduction"></a> |
---|
85 | <h2>Introduction</h2> |
---|
86 | |
---|
87 | <p> |
---|
88 | The C++ standard library provides several generic containers, but it |
---|
89 | does not provide any multidimensional array types. The |
---|
90 | <tt>std::vector</tt> class template can be used to implement |
---|
91 | N-dimensional arrays, for example expressing a 2-dimensional array of |
---|
92 | <tt>double</tt> elements using the type |
---|
93 | <tt>std::vector<std::vector<double>></tt>, but the |
---|
94 | resulting interface is unwieldy and the memory overhead can be quite |
---|
95 | high. Native C++ arrays (i.e. <tt>int arr[2][2][2];</tt>) do not |
---|
96 | immediately interoperate well with the C++ Standard Library, and they |
---|
97 | also lose information at function call boundaries (specifically the |
---|
98 | extent of the last dimension). Finally, a dynamically allocated |
---|
99 | contiguous block of elements can be treated as an array, though this |
---|
100 | method requires manual bookkeeping that is error prone and obfuscates |
---|
101 | the intent of the programmer. |
---|
102 | </p> |
---|
103 | |
---|
104 | <p> |
---|
105 | The Boost MultiArray library enhances the C++ standard containers with |
---|
106 | versatile multi-dimensional array abstractions. It includes a general |
---|
107 | array class template and native array adaptors that support idiomatic |
---|
108 | array operations and interoperate with C++ Standard Library containers |
---|
109 | and algorithms. The arrays share a common interface, expressed as a |
---|
110 | generic programming in terms of which generic array algorithms can be |
---|
111 | implemented. |
---|
112 | </p> |
---|
113 | |
---|
114 | <p> |
---|
115 | This document is meant to provide an introductory tutorial and user's |
---|
116 | guide for the most basic and common usage patterns of MultiArray |
---|
117 | components. The <a href="./reference.html">reference manual</a> |
---|
118 | provides more complete and formal documentation of library features. |
---|
119 | </p> |
---|
120 | |
---|
121 | <a name="sec_example"></a> |
---|
122 | <h2>Short Example</h2> |
---|
123 | What follows is a brief example of the use of <tt>multi_array</tt>: |
---|
124 | |
---|
125 | <blockquote> |
---|
126 | <pre> |
---|
127 | #include "boost/multi_array.hpp" |
---|
128 | #include <cassert> |
---|
129 | |
---|
130 | int |
---|
131 | main () { |
---|
132 | // Create a 3D array that is 3 x 4 x 2 |
---|
133 | typedef boost::multi_array<double, 3> array_type; |
---|
134 | typedef array_type::index index; |
---|
135 | array_type A(boost::extents[3][4][2]); |
---|
136 | |
---|
137 | // Assign values to the elements |
---|
138 | int values = 0; |
---|
139 | for(index i = 0; i != 3; ++i) |
---|
140 | for(index j = 0; j != 4; ++j) |
---|
141 | for(index k = 0; k != 2; ++k) |
---|
142 | A[i][j][k] = values++; |
---|
143 | |
---|
144 | // Verify values |
---|
145 | int verify = 0; |
---|
146 | for(index i = 0; i != 3; ++i) |
---|
147 | for(index j = 0; j != 4; ++j) |
---|
148 | for(index k = 0; k != 2; ++k) |
---|
149 | assert(A[i][j][k] == verify++); |
---|
150 | |
---|
151 | return 0; |
---|
152 | } |
---|
153 | </pre> |
---|
154 | </blockquote> |
---|
155 | |
---|
156 | <a name="sec_components"></a> |
---|
157 | <h2>MultiArray Components</h2> |
---|
158 | |
---|
159 | Boost.MultiArray's implementation (boost/multi_array.hpp) provides three user-level class templates: |
---|
160 | |
---|
161 | <ol> |
---|
162 | <li><a href="./reference.html#multi_array"><tt>multi_array</tt></a>, |
---|
163 | |
---|
164 | <li><a href="./reference.html#multi_array_ref"><tt>multi_array_ref</tt></a>, and |
---|
165 | |
---|
166 | <li><a href="./reference.html#const_multi_array_ref"><tt>const_multi_array_ref</tt></a> |
---|
167 | </ol> |
---|
168 | |
---|
169 | <tt>multi_array</tt> is a container template. When instantiated, it |
---|
170 | allocates space for the number of elements corresponding to the |
---|
171 | dimensions specified at construction time. A <tt>multi_array</tt> may |
---|
172 | also be default constructed and resized as needed. |
---|
173 | |
---|
174 | <p> |
---|
175 | <tt>multi_array_ref</tt> adapts an existing array of data to provide |
---|
176 | the <tt>multi_array</tt> interface. <tt>multi_array_ref</tt> does not own the |
---|
177 | data passed to it. |
---|
178 | |
---|
179 | <p> |
---|
180 | <tt>const_multi_array_ref</tt> is similar to <tt>multi_array_ref</tt> |
---|
181 | but guarantees that the contents of the array are immutable. It can |
---|
182 | thus wrap pointers of type <i>T const*</i>. |
---|
183 | |
---|
184 | <p> |
---|
185 | The three components exhibit very similar behavior. Aside from |
---|
186 | constructor parameters, <tt>multi_array</tt> and |
---|
187 | <tt>multi_array_ref</tt> export the same interface. |
---|
188 | <tt>const_multi_array_ref</tt> provides only the constness-preserving |
---|
189 | portions of the <tt>multi_array_ref</tt> interface. |
---|
190 | |
---|
191 | <a name="sec_assignment"></a> |
---|
192 | <h2>Construction and Assignment</h2> |
---|
193 | <p>Each of the array types - |
---|
194 | <a href="./reference.html#multi_array"><tt>multi_array</tt></a>, |
---|
195 | <a href="./reference.html#multi_array_ref"><tt>multi_array_ref</tt></a>, and |
---|
196 | <a href="./reference.html#const_multi_array_ref"><tt>const_multi_array_ref</tt></a> - |
---|
197 | provides a specialized set of constructors. For further information, |
---|
198 | consult their reference pages. |
---|
199 | |
---|
200 | <p>All of the non-const array types in this library provide assignment |
---|
201 | operators<tt>operator=()</tt>. Each of the array types <tt>multi_array</tt>, |
---|
202 | <tt>multi_array_ref</tt>, <tt>subarray</tt>, and |
---|
203 | <tt>array_view</tt> can be assigned from any |
---|
204 | of the others, so long as their shapes match. The |
---|
205 | const variants, <tt>const_multi_array_ref</tt>, |
---|
206 | <tt>const_subarray</tt>, and <tt>const_array_view</tt>, can be the |
---|
207 | source of a copy to an array with matching shape. |
---|
208 | Assignment results in a deep (element by element) copy of the data |
---|
209 | contained within an array. |
---|
210 | |
---|
211 | <a name="sec_generators"></a> |
---|
212 | <h2>Array View and Subarray Type Generators</h2> |
---|
213 | In some situations, the use of nested generators for array_view and |
---|
214 | subarray types is inconvenient. For example, inside a |
---|
215 | function template parameterized upon array type, the extra |
---|
216 | "template" keywords can be obfuscating. More likely though, some |
---|
217 | compilers cannot handle templates nested within template parameters. |
---|
218 | For this reason the type generators, <tt>subarray_gen</tt>, |
---|
219 | <tt>const_subarray_gen</tt>, <tt>array_view_gen</tt>, and |
---|
220 | <tt>const_array_view_gen</tt> are provided. Thus, the two typedefs |
---|
221 | in the following example result in the same type: |
---|
222 | <blockquote> |
---|
223 | <pre> |
---|
224 | template <typename Array> |
---|
225 | void my_function() { |
---|
226 | typedef typename Array::template array_view<3>::type view1_t; |
---|
227 | typedef typename boost::array_view_gen<Array,3>::type view2_t; |
---|
228 | // ... |
---|
229 | } |
---|
230 | </pre> |
---|
231 | </blockquote> |
---|
232 | |
---|
233 | <a name="sec_dimensions"></a> |
---|
234 | <h2>Specifying Array Dimensions</h2> |
---|
235 | When creating most of the Boost.MultiArray components, it is necessary |
---|
236 | to specify both the number of dimensions and the extent of each |
---|
237 | (<tt>boost::multi_array</tt> also provides a default constructor). |
---|
238 | Though the number of dimensions is always specified as a template |
---|
239 | parameter, two separate mechanisms have been provided to specify the |
---|
240 | extent of each. |
---|
241 | <p>The first method involves passing a |
---|
242 | <a href="../../utility/Collection.html"> |
---|
243 | Collection</a> of extents to a |
---|
244 | constructor, most commonly a <tt>boost::array</tt>. The constructor |
---|
245 | will retrieve the beginning iterator from the container and retrieve N |
---|
246 | elements, corresponding to extents for the N dimensions. This is |
---|
247 | useful for writing dimension-independent code. |
---|
248 | <h3>Example</h3> |
---|
249 | <blockquote> |
---|
250 | <pre> |
---|
251 | typedef boost::multi_array<double, 3> array_type; |
---|
252 | boost::array<array_type::index, 3> shape = {{ 3, 4, 2 }}; |
---|
253 | array_type A(shape); |
---|
254 | </pre> |
---|
255 | </blockquote> |
---|
256 | |
---|
257 | <p>The second method involves passing the constructor an <tt>extent_gen</tt> |
---|
258 | object, specifying the matrix dimensions. By default, the library constructs a |
---|
259 | global <tt>extent_gen</tt> object <tt>boost::extents</tt>. In case of |
---|
260 | concern about memory used by these objects, defining |
---|
261 | <tt>BOOST_MULTI_ARRAY_NO_GENERATORS</tt> before including the library |
---|
262 | header inhibits its construction. |
---|
263 | |
---|
264 | <h3>Example</h3> |
---|
265 | <blockquote> |
---|
266 | <pre> |
---|
267 | typedef boost::multi_array<double, 3> array_type; |
---|
268 | array_type A(boost::extents[3][4][2]); |
---|
269 | </pre> |
---|
270 | </blockquote> |
---|
271 | |
---|
272 | <a name="sec_access"></a> |
---|
273 | <h2>Accessing Elements</h2> |
---|
274 | The Boost.MultiArray components provide two ways of accessing |
---|
275 | specific elements within a container. The first uses the traditional |
---|
276 | C array notation, provided by <tt>operator[]</tt>. |
---|
277 | <h3>Example</h3> |
---|
278 | <blockquote> |
---|
279 | <pre> |
---|
280 | typedef boost::multi_array<double, 3> array_type; |
---|
281 | array_type A(boost::extents[3][4][2]); |
---|
282 | A[0][0][0] = 3.14; |
---|
283 | assert(A[0][0][0] == 3.14); |
---|
284 | </pre> |
---|
285 | </blockquote> |
---|
286 | |
---|
287 | <p> The second method involves passing a |
---|
288 | <a href="../../utility/Collection.html"> |
---|
289 | Collection</a> of indices to <tt>operator()</tt>. N indices will be retrieved |
---|
290 | from the Collection for the N dimensions of the container. |
---|
291 | <h3>Example</h3> |
---|
292 | <blockquote> |
---|
293 | <pre> |
---|
294 | typedef boost::multi_array<double, 3> array_type; |
---|
295 | array_type A(boost::extents[3][4][2]); |
---|
296 | boost::array<array_type::index,3> idx = {{0,0,0}}; |
---|
297 | A(idx) = 3.14; |
---|
298 | assert(A(idx) == 3.14); |
---|
299 | </pre> |
---|
300 | </blockquote> |
---|
301 | This can be useful for writing dimension-independent code, and under |
---|
302 | some compilers may yield higher performance than <tt>operator[].</tt> |
---|
303 | |
---|
304 | <p> |
---|
305 | By default, both of the above element access methods perform range |
---|
306 | checking. If a supplied index is out of the range defined for an |
---|
307 | array, an assertion will abort the program. To disable range |
---|
308 | checking (for performance reasons in production releases), define |
---|
309 | the <tt>BOOST_DISABLE_ASSERTS</tt> preprocessor macro prior to |
---|
310 | including multi_array.hpp in your application. |
---|
311 | |
---|
312 | <a name="sec_views"></a> |
---|
313 | <h2>Creating Views</h2> |
---|
314 | Boost.MultiArray provides the facilities for creating a sub-view of an |
---|
315 | already existing array component. It allows you to create a sub-view that |
---|
316 | retains the same number of dimensions as the original array or one |
---|
317 | that has less dimensions than the original as well. |
---|
318 | |
---|
319 | <p>Sub-view creation occurs by placing a call to operator[], passing it |
---|
320 | an <tt>index_gen</tt> type. The <tt>index_gen</tt> is populated by |
---|
321 | passing <tt>index_range</tt> objects to its <tt>operator[]</tt>. |
---|
322 | Similar to <tt>boost::extents</tt>, the library by default constructs |
---|
323 | the object <tt>boost::indices</tt>. You can suppress this object |
---|
324 | by defining <tt>BOOST_MULTI_ARRAY_NO_GENERATORS</tt> before |
---|
325 | including the library header. A simple sub-view creation example follows. |
---|
326 | <h3>Example</h3> |
---|
327 | <blockquote> |
---|
328 | <pre> |
---|
329 | // myarray = 2 x 3 x 4 |
---|
330 | |
---|
331 | // |
---|
332 | // array_view dims: [base,bound) (dimension striding default = 1) |
---|
333 | // dim 0: [0,2) |
---|
334 | // dim 1: [1,3) |
---|
335 | // dim 2: [0,4) (strided by 2), |
---|
336 | // |
---|
337 | |
---|
338 | typedef array_type::index_range range; |
---|
339 | array_type::array_view<3>::type myview = |
---|
340 | myarray[ boost::indices[range(0,2)][range(1,3)][range(0,4,2)] ]; |
---|
341 | |
---|
342 | for (array_type::index i = 0; i != 2; ++i) |
---|
343 | for (array_type::index j = 0; j != 2; ++j) |
---|
344 | for (array_type::index k = 0; k != 2; ++k) |
---|
345 | assert(myview[i][j][k] == myarray[i][j+1][k*2]); |
---|
346 | </pre> |
---|
347 | </blockquote> |
---|
348 | |
---|
349 | |
---|
350 | <p>By passing an integral value to the index_gen, one may create a |
---|
351 | subview with fewer dimensions than the original array component (also |
---|
352 | called slicing). |
---|
353 | <h3>Example</h3> |
---|
354 | <blockquote> |
---|
355 | <pre> |
---|
356 | // myarray = 2 x 3 x 4 |
---|
357 | |
---|
358 | // |
---|
359 | // array_view dims: |
---|
360 | // [base,stride,bound) |
---|
361 | // [0,1,2), 1, [0,2,4) |
---|
362 | // |
---|
363 | |
---|
364 | typedef array_type::index_range range; |
---|
365 | array_type::index_gen indices; |
---|
366 | array_type::array_view<2>::type myview = |
---|
367 | myarray[ indices[range(0,2)][1][range(0,4,2)] ]; |
---|
368 | |
---|
369 | for (array_type::index i = 0; i != 2; ++i) |
---|
370 | for (array_type::index j = 0; j != 2; ++j) |
---|
371 | assert(myview[i][j] == myarray[i][1][j*2]); |
---|
372 | </pre> |
---|
373 | </blockquote> |
---|
374 | |
---|
375 | <h3>More on <tt>index_range</tt></h3> |
---|
376 | The <tt>index_range</tt> type provides several methods of specifying |
---|
377 | ranges for subview generation. Here are a few range instantiations |
---|
378 | that specify the same range. |
---|
379 | <h3>Example</h3> |
---|
380 | <blockquote> |
---|
381 | <pre> |
---|
382 | // [base,stride,bound) |
---|
383 | // [0,2,4) |
---|
384 | |
---|
385 | typedef array_type::index_range range; |
---|
386 | range a_range; |
---|
387 | a_range = range(0,4,2); |
---|
388 | a_range = range().start(0).finish(4).stride(2); |
---|
389 | a_range = range().start(0).stride(2).finish(4); |
---|
390 | a_range = 0 <= range().stride(2) < 4; |
---|
391 | a_range = 0 <= range().stride(2) <= 3; |
---|
392 | </pre> |
---|
393 | </blockquote> |
---|
394 | |
---|
395 | An <tt>index_range</tt> object passed to a slicing operation will |
---|
396 | inherit its start and/or finish value from the array being sliced if |
---|
397 | you do not supply one. This conveniently prevents you from having to |
---|
398 | know the bounds of the array dimension in certain cases. For example, |
---|
399 | the default-constructed range will take the full extent of the |
---|
400 | dimension it is used to specify. |
---|
401 | |
---|
402 | <h3>Example</h3> |
---|
403 | <blockquote> |
---|
404 | <pre> |
---|
405 | typedef array_type::index_range range; |
---|
406 | range a_range; |
---|
407 | |
---|
408 | // All elements in this dimension |
---|
409 | a_range = range(); |
---|
410 | |
---|
411 | // indices i where 3 <= i |
---|
412 | a_range = range().start(3) |
---|
413 | a_range = 3 <= range(); |
---|
414 | a_range = 2 < range(); |
---|
415 | |
---|
416 | // indices i where i < 7 |
---|
417 | a_range = range().finish(7) |
---|
418 | a_range = range() < 7; |
---|
419 | a_range = range() <= 6; |
---|
420 | </pre> |
---|
421 | </blockquote> |
---|
422 | |
---|
423 | The following example slicing operations exhibit some of the |
---|
424 | alternatives shown above |
---|
425 | <blockquote> |
---|
426 | <pre> |
---|
427 | // take all of dimension 1 |
---|
428 | // take i < 5 for dimension 2 |
---|
429 | // take 4 <= j <= 7 for dimension 3 with stride 2 |
---|
430 | myarray[ boost::indices[range()][range() < 5 ][4 <= range().stride(2) <= 7] ]; |
---|
431 | </pre> |
---|
432 | </blockquote> |
---|
433 | |
---|
434 | <a name="sec_storage"></a> |
---|
435 | <h2>Storage Ordering</h2> |
---|
436 | Each array class provides constructors that accept a storage ordering |
---|
437 | parameter. This is most |
---|
438 | useful when interfacing with legacy codes that require an ordering |
---|
439 | different from standard C, such as FORTRAN. The possibilities are |
---|
440 | <tt>c_storage_order</tt>, <tt>fortran_storage_order</tt>, and |
---|
441 | <tt>general_storage_order</tt>. |
---|
442 | |
---|
443 | <p><tt>c_storage_order</tt>, which is the default, will store elements |
---|
444 | in memory in the same order as a C array would, that is, the |
---|
445 | dimensions are stored from last to first. |
---|
446 | |
---|
447 | <p><tt>fortran_storage_order</tt> will store elements in memory in the same order |
---|
448 | as FORTRAN would: from the first dimension to |
---|
449 | the last. Note that with use of this parameter, the array |
---|
450 | indices will remain zero-based. |
---|
451 | <h3>Example</h3> |
---|
452 | <blockquote> |
---|
453 | <pre> |
---|
454 | typedef boost::multi_array<double,3> array_type; |
---|
455 | array_type A(boost::extents[3][4][2],boost::fortran_storage_order); |
---|
456 | call_fortran_function(A.data()); |
---|
457 | </pre> |
---|
458 | </blockquote> |
---|
459 | |
---|
460 | <p><tt>general_storage_order</tt> allows one to customize both the order in |
---|
461 | which dimensions are stored in memory and whether dimensions are |
---|
462 | stored in ascending or descending order. |
---|
463 | <h3>Example</h3> |
---|
464 | <blockquote> |
---|
465 | <pre> |
---|
466 | typedef boost::general_storage_order<3> storage; |
---|
467 | typedef boost::multi_array<int,3> array_type; |
---|
468 | |
---|
469 | // Store last dimension, then first, then middle |
---|
470 | array_type::size_type ordering[] = {2,0,1}; |
---|
471 | |
---|
472 | // Store the first dimension(dimension 0) in descending order |
---|
473 | bool ascending[] = {false,true,true}; |
---|
474 | |
---|
475 | array_type A(extents[3][4][2],storage(ordering,ascending)); |
---|
476 | </pre> |
---|
477 | </blockquote> |
---|
478 | |
---|
479 | |
---|
480 | <a name="sec_base"></a> |
---|
481 | <h2>Setting The Array Base</h2> |
---|
482 | In some situations, it may be inconvenient or awkward to use an |
---|
483 | array that is zero-based. |
---|
484 | the Boost.MultiArray components provide two facilities for changing the |
---|
485 | bases of an array. One may specify a pair of range values to |
---|
486 | the extent_gen constructor in order to set the base value. |
---|
487 | <h3>Example</h3> |
---|
488 | <blockquote> |
---|
489 | <pre> |
---|
490 | typedef boost::multi_array<double, 3> array_type; |
---|
491 | typedef array_type::extent_range range; |
---|
492 | |
---|
493 | array_type::extent_gen extents; |
---|
494 | |
---|
495 | // dimension 0: 0-based |
---|
496 | // dimension 1: 1-based |
---|
497 | // dimension 2: -1 - based |
---|
498 | array_type A(extents[2][range(1,4)][range(-1,3)]); |
---|
499 | </pre> |
---|
500 | </blockquote> |
---|
501 | |
---|
502 | <p> |
---|
503 | An alternative is to first construct the array normally then |
---|
504 | reset the bases. To set all bases to the same value, use the |
---|
505 | <tt>reindex</tt> member function, passing it a single new index value. |
---|
506 | <h3>Example</h3> |
---|
507 | <blockquote> |
---|
508 | <pre> |
---|
509 | typedef boost::multi_array<double, 3> array_type; |
---|
510 | typedef array_type::extent_range range; |
---|
511 | |
---|
512 | array_type::extent_gen extents; |
---|
513 | |
---|
514 | array_type A(extents[2][3][4]); |
---|
515 | // change to 1-based |
---|
516 | A.reindex(1) |
---|
517 | </pre> |
---|
518 | </blockquote> |
---|
519 | |
---|
520 | <p> |
---|
521 | An alternative is to set each base separately using the |
---|
522 | <tt>reindex</tt> member function, passing it a Collection of index bases. |
---|
523 | <h3>Example</h3> |
---|
524 | <blockquote> |
---|
525 | <pre> |
---|
526 | typedef boost::multi_array<double, 3> array_type; |
---|
527 | typedef array_type::extent_range range; |
---|
528 | |
---|
529 | array_type::extent_gen extents; |
---|
530 | |
---|
531 | // dimension 0: 0-based |
---|
532 | // dimension 1: 1-based |
---|
533 | // dimension 2: (-1)-based |
---|
534 | array_type A(extents[2][3][4]); |
---|
535 | boost::array<array_type::index,ndims> bases = {{0, 1, -1}}; |
---|
536 | A.reindex(bases); |
---|
537 | </pre> |
---|
538 | </blockquote> |
---|
539 | |
---|
540 | |
---|
541 | <a name="sec_reshape"></a> |
---|
542 | <h2>Changing an Array's Shape</h2> |
---|
543 | The Boost.MultiArray arrays provide a reshape operation. While the |
---|
544 | number of dimensions must remain the same, the shape of the array may |
---|
545 | change so long as the total number of |
---|
546 | elements contained remains the same. |
---|
547 | <h3>Example</h3> |
---|
548 | <blockquote> |
---|
549 | <pre> |
---|
550 | typedef boost::multi_array<double, 3> array_type; |
---|
551 | typedef array_type::extent_range range; |
---|
552 | |
---|
553 | array_type::extent_gen extents; |
---|
554 | array_type A(extents[2][3][4]); |
---|
555 | boost::array<array_type::index,ndims> dims = {{4, 3, 2}}; |
---|
556 | A.reshape(dims); |
---|
557 | </pre> |
---|
558 | </blockquote> |
---|
559 | |
---|
560 | <p> |
---|
561 | Note that reshaping an array does not affect the indexing. |
---|
562 | |
---|
563 | <a name="sec_resize"></a> |
---|
564 | <h2>Resizing an Array</h2> |
---|
565 | |
---|
566 | The <tt>boost::multi_array</tt> class provides an element-preserving |
---|
567 | resize operation. The number of dimensions must remain the same, but |
---|
568 | the extent of each dimension may be increased and decreased as |
---|
569 | desired. When an array is made strictly larger, the existing elements |
---|
570 | will be preserved by copying them into the new underlying memory and |
---|
571 | subsequently destructing the elements in the old underlying memory. |
---|
572 | Any new elements in the array are default constructed. However, if |
---|
573 | the new array size shrinks some of the dimensions, some elements will |
---|
574 | no longer be available. |
---|
575 | |
---|
576 | <h3>Example</h3> |
---|
577 | <blockquote> |
---|
578 | <pre> |
---|
579 | typedef boost::multi_array<int, 3> array_type; |
---|
580 | typedef array_type::extent_range range; |
---|
581 | |
---|
582 | array_type::extent_gen extents; |
---|
583 | array_type A(extents[3][3][3]); |
---|
584 | A[0][0][0] = 4; |
---|
585 | A[2][2][2] = 5; |
---|
586 | A.resize(extents[2][3][4]); |
---|
587 | assert(A[0][0][0] == 4); |
---|
588 | // A[2][2][2] is no longer valid. |
---|
589 | </pre> |
---|
590 | </blockquote> |
---|
591 | |
---|
592 | |
---|
593 | <a name="sec_concepts"></a> |
---|
594 | <h2>MultiArray Concept</h2> |
---|
595 | Boost.MultiArray defines and uses the |
---|
596 | <a href="./reference.html#MultiArray">MultiArray</a> |
---|
597 | concept. It specifies an interface for N-dimensional containers. |
---|
598 | |
---|
599 | <a name="sec_testcases"></a> |
---|
600 | <h2>Test Cases</h2> |
---|
601 | Boost.MultiArray comes with a suite of test cases meant to exercise |
---|
602 | the features and semantics of the library. A description of the test |
---|
603 | cases can be found <a href="./test_cases.html">here</a>. |
---|
604 | |
---|
605 | <a name="sec_related"></a> |
---|
606 | <h2>Related Work</h2> |
---|
607 | |
---|
608 | <a href="../../array/index.html">boost::array</a> |
---|
609 | and <a href="http://www.sgi.com/tech/stl/Vector.html">std::vector</a> are |
---|
610 | one-dimensional containers of user data. Both manage their own |
---|
611 | memory. <tt>std::valarray</tt> is a low-level |
---|
612 | C++ Standard Library component |
---|
613 | meant to provide portable high performance for numerical applications. |
---|
614 | <a href="http://www.oonumerics.org/blitz/">Blitz++</a> is |
---|
615 | an array library developed by Todd |
---|
616 | Veldhuizen. It uses |
---|
617 | advanced C++ techniques to provide near-Fortran performance for |
---|
618 | array-based numerical applications. |
---|
619 | <b>array_traits</b> is a beta library, formerly distributed with |
---|
620 | Boost, that provides a means to create iterators over native C++ |
---|
621 | arrays. |
---|
622 | |
---|
623 | This library is analogous to |
---|
624 | <a href="../../array/index.html">boost::array</a> in that it augments C style N-dimensional |
---|
625 | arrays, as <tt>boost::array</tt> does for C one-dimensional arrays. |
---|
626 | |
---|
627 | |
---|
628 | <a name="sec_credits"></a> |
---|
629 | <h2>Credits</h2> |
---|
630 | <ul> |
---|
631 | |
---|
632 | <li><a href="mailto:garcia@osl.iu.edu">Ronald Garcia</a> |
---|
633 | is the primary author of the library. |
---|
634 | |
---|
635 | <li><a href="../../../people/jeremy_siek.htm">Jeremy Siek</a> |
---|
636 | helped with the library and provided a sounding board for ideas, |
---|
637 | advice, and assistance porting to Microsoft Visual C++. |
---|
638 | |
---|
639 | <li><a href="mailto:gbavestrelli@yahoo.com">Giovanni Bavestrelli</a> |
---|
640 | provided an early implementation of an |
---|
641 | N-dimensional array which inspired feedback from the |
---|
642 | <a href="http://www.boost.org/">Boost</a> mailing list |
---|
643 | members. Some design decisions in this work were based upon this |
---|
644 | implementation and the comments it elicited. |
---|
645 | |
---|
646 | <li><a href="mailto:tveldhui@acm.org">Todd Veldhuizen</a> wrote |
---|
647 | <a href="http://oonumerics.org/blitz/">Blitz++</a>, which |
---|
648 | inspired some aspects of this design. In addition, he supplied |
---|
649 | feedback on the design and implementation of the library. |
---|
650 | |
---|
651 | <li><a href="mailto:jewillco@osl.iu.edu">Jeremiah Willcock</a> |
---|
652 | provided feedback on the implementation and design of the |
---|
653 | library and some suggestions for features. |
---|
654 | |
---|
655 | <li><a href="mailto:bdawes@acm.org">Beman Dawes</a> |
---|
656 | helped immensely with porting the library to Microsoft Windows |
---|
657 | compilers. |
---|
658 | </ul> |
---|
659 | |
---|
660 | <hr> |
---|
661 | |
---|
662 | <address> |
---|
663 | <a href="mailto:garcia@.cs.indiana.edu">Ronald Garcia</a> |
---|
664 | </address> |
---|
665 | <!-- Created: Fri Jun 29 10:53:07 EST 2001 --> |
---|
666 | <!-- hhmts start -->Last modified: Tue Feb 7 17:15:50 EST 2006 <!-- hhmts end --> |
---|
667 | |
---|
668 | </body> |
---|
669 | </html> |
---|