Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/multi_array/doc/user.html @ 20

Last change on this file since 20 was 12, checked in by landauf, 18 years ago

added boost

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