]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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. The <tt>extent_gen</tt> type | |
259 | is defined in the <tt>multi_array_types</tt> namespace and as a | |
260 | member of every array type, but by default, the library constructs a | |
261 | global <tt>extent_gen</tt> object <tt>boost::extents</tt>. In case of | |
262 | concern about memory used by these objects, defining | |
263 | <tt>BOOST_MULTI_ARRAY_NO_GENERATORS</tt> before including the library | |
264 | header inhibits its construction. | |
265 | ||
266 | <h3>Example</h3> | |
267 | <blockquote> | |
268 | <pre> | |
269 | typedef boost::multi_array<double, 3> array_type; | |
270 | array_type A(boost::extents[3][4][2]); | |
271 | </pre> | |
272 | </blockquote> | |
273 | ||
274 | <a name="sec_access"></a> | |
275 | <h2>Accessing Elements</h2> | |
276 | The Boost.MultiArray components provide two ways of accessing | |
277 | specific elements within a container. The first uses the traditional | |
278 | C array notation, provided by <tt>operator[]</tt>. | |
279 | <h3>Example</h3> | |
280 | <blockquote> | |
281 | <pre> | |
282 | typedef boost::multi_array<double, 3> array_type; | |
283 | array_type A(boost::extents[3][4][2]); | |
284 | A[0][0][0] = 3.14; | |
285 | assert(A[0][0][0] == 3.14); | |
286 | </pre> | |
287 | </blockquote> | |
288 | ||
289 | <p> The second method involves passing a | |
290 | <a href="../../utility/Collection.html"> | |
291 | Collection</a> of indices to <tt>operator()</tt>. N indices will be retrieved | |
292 | from the Collection for the N dimensions of the container. | |
293 | <h3>Example</h3> | |
294 | <blockquote> | |
295 | <pre> | |
296 | typedef boost::multi_array<double, 3> array_type; | |
297 | array_type A(boost::extents[3][4][2]); | |
298 | boost::array<array_type::index,3> idx = {{0,0,0}}; | |
299 | A(idx) = 3.14; | |
300 | assert(A(idx) == 3.14); | |
301 | </pre> | |
302 | </blockquote> | |
303 | This can be useful for writing dimension-independent code, and under | |
304 | some compilers may yield higher performance than <tt>operator[].</tt> | |
305 | ||
306 | <p> | |
307 | By default, both of the above element access methods perform range | |
308 | checking. If a supplied index is out of the range defined for an | |
309 | array, an assertion will abort the program. To disable range | |
310 | checking (for performance reasons in production releases), define | |
311 | the <tt>BOOST_DISABLE_ASSERTS</tt> preprocessor macro prior to | |
312 | including multi_array.hpp in your application. | |
313 | ||
314 | <a name="sec_views"></a> | |
315 | <h2>Creating Views</h2> | |
316 | Boost.MultiArray provides the facilities for creating a sub-view of an | |
317 | already existing array component. It allows you to create a sub-view that | |
318 | retains the same number of dimensions as the original array or one | |
319 | that has less dimensions than the original as well. | |
320 | ||
321 | <p>Sub-view creation occurs by placing a call to operator[], passing | |
322 | it an <tt>index_gen</tt> type. The <tt>index_gen</tt> is populated by | |
323 | passing <tt>index_range</tt> objects to its <tt>operator[]</tt>. | |
324 | The <tt>index_range</tt> and <tt>index_gen</tt> types are defined in | |
325 | the <tt>multi_array_types</tt> namespace and as nested members of | |
326 | every array type. Similar to <tt>boost::extents</tt>, the library by | |
327 | default constructs the object <tt>boost::indices</tt>. You can | |
328 | suppress this object by | |
329 | defining <tt>BOOST_MULTI_ARRAY_NO_GENERATORS</tt> before including the | |
330 | library header. A simple sub-view creation example follows. | |
331 | ||
332 | <h3>Example</h3> | |
333 | <blockquote> | |
334 | <pre> | |
335 | // myarray = 2 x 3 x 4 | |
336 | ||
337 | // | |
338 | // array_view dims: [base,bound) (dimension striding default = 1) | |
339 | // dim 0: [0,2) | |
340 | // dim 1: [1,3) | |
341 | // dim 2: [0,4) (strided by 2), | |
342 | // | |
343 | ||
344 | typedef boost::multi_array_types::index_range range; | |
345 | // OR typedef array_type::index_range range; | |
346 | array_type::array_view<3>::type myview = | |
347 | myarray[ boost::indices[range(0,2)][range(1,3)][range(0,4,2)] ]; | |
348 | ||
349 | for (array_type::index i = 0; i != 2; ++i) | |
350 | for (array_type::index j = 0; j != 2; ++j) | |
351 | for (array_type::index k = 0; k != 2; ++k) | |
352 | assert(myview[i][j][k] == myarray[i][j+1][k*2]); | |
353 | </pre> | |
354 | </blockquote> | |
355 | ||
356 | ||
357 | <p>By passing an integral value to the index_gen, one may create a | |
358 | subview with fewer dimensions than the original array component (also | |
359 | called slicing). | |
360 | <h3>Example</h3> | |
361 | <blockquote> | |
362 | <pre> | |
363 | // myarray = 2 x 3 x 4 | |
364 | ||
365 | // | |
366 | // array_view dims: | |
367 | // [base,stride,bound) | |
368 | // [0,1,2), 1, [0,2,4) | |
369 | // | |
370 | ||
371 | typedef boost::multi_array_types::index_range range; | |
372 | array_type::index_gen indices; | |
373 | array_type::array_view<2>::type myview = | |
374 | myarray[ indices[range(0,2)][1][range(0,4,2)] ]; | |
375 | ||
376 | for (array_type::index i = 0; i != 2; ++i) | |
377 | for (array_type::index j = 0; j != 2; ++j) | |
378 | assert(myview[i][j] == myarray[i][1][j*2]); | |
379 | </pre> | |
380 | </blockquote> | |
381 | ||
382 | <h3>More on <tt>index_range</tt></h3> | |
383 | The <tt>index_range</tt> type provides several methods of specifying | |
384 | ranges for subview generation. Here are a few range instantiations | |
385 | that specify the same range. | |
386 | <h3>Example</h3> | |
387 | <blockquote> | |
388 | <pre> | |
389 | // [base,stride,bound) | |
390 | // [0,2,4) | |
391 | ||
392 | typedef boost::multi_array_types::index_range range; | |
393 | range a_range; | |
394 | a_range = range(0,4,2); | |
395 | a_range = range().start(0).finish(4).stride(2); | |
396 | a_range = range().start(0).stride(2).finish(4); | |
397 | a_range = 0 <= range().stride(2) < 4; | |
398 | a_range = 0 <= range().stride(2) <= 3; | |
399 | </pre> | |
400 | </blockquote> | |
401 | ||
402 | An <tt>index_range</tt> object passed to a slicing operation will | |
403 | inherit its start and/or finish value from the array being sliced if | |
404 | you do not supply one. This conveniently prevents you from having to | |
405 | know the bounds of the array dimension in certain cases. For example, | |
406 | the default-constructed range will take the full extent of the | |
407 | dimension it is used to specify. | |
408 | ||
409 | <h3>Example</h3> | |
410 | <blockquote> | |
411 | <pre> | |
412 | typedef boost::multi_array_types::index_range range; | |
413 | range a_range; | |
414 | ||
415 | // All elements in this dimension | |
416 | a_range = range(); | |
417 | ||
418 | // indices i where 3 <= i | |
419 | a_range = range().start(3) | |
420 | a_range = 3 <= range(); | |
421 | a_range = 2 < range(); | |
422 | ||
423 | // indices i where i < 7 | |
424 | a_range = range().finish(7) | |
425 | a_range = range() < 7; | |
426 | a_range = range() <= 6; | |
427 | </pre> | |
428 | </blockquote> | |
429 | ||
430 | The following example slicing operations exhibit some of the | |
431 | alternatives shown above | |
432 | <blockquote> | |
433 | <pre> | |
434 | // take all of dimension 1 | |
435 | // take i < 5 for dimension 2 | |
436 | // take 4 <= j <= 7 for dimension 3 with stride 2 | |
437 | myarray[ boost::indices[range()][range() < 5 ][4 <= range().stride(2) <= 7] ]; | |
438 | </pre> | |
439 | </blockquote> | |
440 | ||
441 | <a name="sec_storage"></a> | |
442 | <h2>Storage Ordering</h2> | |
443 | Each array class provides constructors that accept a storage ordering | |
444 | parameter. This is most | |
445 | useful when interfacing with legacy codes that require an ordering | |
446 | different from standard C, such as FORTRAN. The possibilities are | |
447 | <tt>c_storage_order</tt>, <tt>fortran_storage_order</tt>, and | |
448 | <tt>general_storage_order</tt>. | |
449 | ||
450 | <p><tt>c_storage_order</tt>, which is the default, will store elements | |
451 | in memory in the same order as a C array would, that is, the | |
452 | dimensions are stored from last to first. | |
453 | ||
454 | <p><tt>fortran_storage_order</tt> will store elements in memory in the same order | |
455 | as FORTRAN would: from the first dimension to | |
456 | the last. Note that with use of this parameter, the array | |
457 | indices will remain zero-based. | |
458 | <h3>Example</h3> | |
459 | <blockquote> | |
460 | <pre> | |
461 | typedef boost::multi_array<double,3> array_type; | |
462 | array_type A(boost::extents[3][4][2],boost::fortran_storage_order()); | |
463 | call_fortran_function(A.data()); | |
464 | </pre> | |
465 | </blockquote> | |
466 | ||
467 | <p><tt>general_storage_order</tt> allows one to customize both the order in | |
468 | which dimensions are stored in memory and whether dimensions are | |
469 | stored in ascending or descending order. | |
470 | <h3>Example</h3> | |
471 | <blockquote> | |
472 | <pre> | |
473 | typedef boost::general_storage_order<3> storage; | |
474 | typedef boost::multi_array<int,3> array_type; | |
475 | ||
476 | // Store last dimension, then first, then middle | |
477 | array_type::size_type ordering[] = {2,0,1}; | |
478 | ||
479 | // Store the first dimension(dimension 0) in descending order | |
480 | bool ascending[] = {false,true,true}; | |
481 | ||
482 | array_type A(extents[3][4][2],storage(ordering,ascending)); | |
483 | </pre> | |
484 | </blockquote> | |
485 | ||
486 | ||
487 | <a name="sec_base"></a> | |
488 | <h2>Setting The Array Base</h2> | |
489 | In some situations, it may be inconvenient or awkward to use an | |
490 | array that is zero-based. | |
491 | the Boost.MultiArray components provide two facilities for changing the | |
492 | bases of an array. One may specify a pair of range values, with | |
493 | the <tt>extent_range</tt> type, to | |
494 | the <tt>extent_gen</tt> constructor in order to set the base value. | |
495 | ||
496 | <h3>Example</h3> | |
497 | <blockquote> | |
498 | <pre> | |
499 | typedef boost::multi_array<double, 3> array_type; | |
500 | typedef boost::multi_array_types::extent_range range; | |
501 | // OR typedef array_type::extent_range range; | |
502 | ||
503 | array_type::extent_gen extents; | |
504 | ||
505 | // dimension 0: 0-based | |
506 | // dimension 1: 1-based | |
507 | // dimension 2: -1 - based | |
508 | array_type A(extents[2][range(1,4)][range(-1,3)]); | |
509 | </pre> | |
510 | </blockquote> | |
511 | ||
512 | <p> | |
513 | An alternative is to first construct the array normally then | |
514 | reset the bases. To set all bases to the same value, use the | |
515 | <tt>reindex</tt> member function, passing it a single new index value. | |
516 | <h3>Example</h3> | |
517 | <blockquote> | |
518 | <pre> | |
519 | typedef boost::multi_array<double, 3> array_type; | |
520 | ||
521 | array_type::extent_gen extents; | |
522 | ||
523 | array_type A(extents[2][3][4]); | |
524 | // change to 1-based | |
525 | A.reindex(1) | |
526 | </pre> | |
527 | </blockquote> | |
528 | ||
529 | <p> | |
530 | An alternative is to set each base separately using the | |
531 | <tt>reindex</tt> member function, passing it a Collection of index bases. | |
532 | <h3>Example</h3> | |
533 | <blockquote> | |
534 | <pre> | |
535 | typedef boost::multi_array<double, 3> array_type; | |
536 | ||
537 | array_type::extent_gen extents; | |
538 | ||
539 | // dimension 0: 0-based | |
540 | // dimension 1: 1-based | |
541 | // dimension 2: (-1)-based | |
542 | array_type A(extents[2][3][4]); | |
543 | boost::array<array_type::index,ndims> bases = {{0, 1, -1}}; | |
544 | A.reindex(bases); | |
545 | </pre> | |
546 | </blockquote> | |
547 | ||
548 | ||
549 | <a name="sec_reshape"></a> | |
550 | <h2>Changing an Array's Shape</h2> | |
551 | The Boost.MultiArray arrays provide a reshape operation. While the | |
552 | number of dimensions must remain the same, the shape of the array may | |
553 | change so long as the total number of | |
554 | elements contained remains the same. | |
555 | <h3>Example</h3> | |
556 | <blockquote> | |
557 | <pre> | |
558 | typedef boost::multi_array<double, 3> array_type; | |
559 | ||
560 | array_type::extent_gen extents; | |
561 | array_type A(extents[2][3][4]); | |
562 | boost::array<array_type::index,ndims> dims = {{4, 3, 2}}; | |
563 | A.reshape(dims); | |
564 | </pre> | |
565 | </blockquote> | |
566 | ||
567 | <p> | |
568 | Note that reshaping an array does not affect the indexing. | |
569 | ||
570 | <a name="sec_resize"></a> | |
571 | <h2>Resizing an Array</h2> | |
572 | ||
573 | The <tt>boost::multi_array</tt> class provides an element-preserving | |
574 | resize operation. The number of dimensions must remain the same, but | |
575 | the extent of each dimension may be increased and decreased as | |
576 | desired. When an array is made strictly larger, the existing elements | |
577 | will be preserved by copying them into the new underlying memory and | |
578 | subsequently destructing the elements in the old underlying memory. | |
579 | Any new elements in the array are default constructed. However, if | |
580 | the new array size shrinks some of the dimensions, some elements will | |
581 | no longer be available. | |
582 | ||
583 | <h3>Example</h3> | |
584 | <blockquote> | |
585 | <pre> | |
586 | typedef boost::multi_array<int, 3> array_type; | |
587 | ||
588 | array_type::extent_gen extents; | |
589 | array_type A(extents[3][3][3]); | |
590 | A[0][0][0] = 4; | |
591 | A[2][2][2] = 5; | |
592 | A.resize(extents[2][3][4]); | |
593 | assert(A[0][0][0] == 4); | |
594 | // A[2][2][2] is no longer valid. | |
595 | </pre> | |
596 | </blockquote> | |
597 | ||
598 | ||
599 | <a name="sec_concepts"></a> | |
600 | <h2>MultiArray Concept</h2> | |
601 | Boost.MultiArray defines and uses the | |
602 | <a href="./reference.html#MultiArray">MultiArray</a> | |
603 | concept. It specifies an interface for N-dimensional containers. | |
604 | ||
605 | <a name="sec_testcases"></a> | |
606 | <h2>Test Cases</h2> | |
607 | Boost.MultiArray comes with a suite of test cases meant to exercise | |
608 | the features and semantics of the library. A description of the test | |
609 | cases can be found <a href="./test_cases.html">here</a>. | |
610 | ||
611 | <a name="sec_related"></a> | |
612 | <h2>Related Work</h2> | |
613 | ||
614 | <a href="../../array/index.html">boost::array</a> | |
615 | and <a href="http://www.sgi.com/tech/stl/Vector.html">std::vector</a> are | |
616 | one-dimensional containers of user data. Both manage their own | |
617 | memory. <tt>std::valarray</tt> is a low-level | |
618 | C++ Standard Library component | |
619 | meant to provide portable high performance for numerical applications. | |
620 | <a href="http://www.oonumerics.org/blitz/">Blitz++</a> is | |
621 | an array library developed by Todd | |
622 | Veldhuizen. It uses | |
623 | advanced C++ techniques to provide near-Fortran performance for | |
624 | array-based numerical applications. | |
625 | <b>array_traits</b> is a beta library, formerly distributed with | |
626 | Boost, that provides a means to create iterators over native C++ | |
627 | arrays. | |
628 | ||
629 | This library is analogous to | |
630 | <a href="../../array/index.html">boost::array</a> in that it augments C style N-dimensional | |
631 | arrays, as <tt>boost::array</tt> does for C one-dimensional arrays. | |
632 | ||
633 | ||
634 | <a name="sec_credits"></a> | |
635 | <h2>Credits</h2> | |
636 | <ul> | |
637 | ||
638 | <li><a href="mailto:garcia@osl.iu.edu">Ronald Garcia</a> | |
639 | is the primary author of the library. | |
640 | ||
641 | <li><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a> | |
642 | helped with the library and provided a sounding board for ideas, | |
643 | advice, and assistance porting to Microsoft Visual C++. | |
644 | ||
645 | <li><a href="mailto:gbavestrelli@yahoo.com">Giovanni Bavestrelli</a> | |
646 | provided an early implementation of an | |
647 | N-dimensional array which inspired feedback from the | |
648 | <a href="http://www.boost.org/">Boost</a> mailing list | |
649 | members. Some design decisions in this work were based upon this | |
650 | implementation and the comments it elicited. | |
651 | ||
652 | <li><a href="mailto:tveldhui@acm.org">Todd Veldhuizen</a> wrote | |
653 | <a href="http://oonumerics.org/blitz/">Blitz++</a>, which | |
654 | inspired some aspects of this design. In addition, he supplied | |
655 | feedback on the design and implementation of the library. | |
656 | ||
657 | <li><a href="mailto:jewillco@osl.iu.edu">Jeremiah Willcock</a> | |
658 | provided feedback on the implementation and design of the | |
659 | library and some suggestions for features. | |
660 | ||
661 | <li><a href="mailto:bdawes@acm.org">Beman Dawes</a> | |
662 | helped immensely with porting the library to Microsoft Windows | |
663 | compilers. | |
664 | </ul> | |
665 | ||
666 | <hr> | |
667 | ||
668 | <address> | |
669 | <a href="mailto:garcia@.cs.indiana.edu">Ronald Garcia</a> | |
670 | </address> | |
671 | <!-- Created: Fri Jun 29 10:53:07 EST 2001 --> | |
672 | <!-- hhmts start -->Last modified: Tue Feb 7 17:15:50 EST 2006 <!-- hhmts end --> | |
673 | ||
674 | </body> | |
675 | </html> |