• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<?xml version="1.0" encoding="utf-8"?>
2<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
3  "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
4 <!ENTITY concepts SYSTEM "MultiArray.xml">
5 <!ENTITY multi_array SYSTEM "multi_array.xml">
6 <!ENTITY multi_array_ref SYSTEM "multi_array_ref.xml">
7 <!ENTITY const_multi_array_ref SYSTEM "const_multi_array_ref.xml">
8]>
9<library name="MultiArray" dirname="multi_array" id="multi_array"
10   xmlns:xi="http://www.w3.org/2001/XInclude"
11   last-revision="$Date$">
12  <libraryinfo>
13    <author>
14      <firstname>Ronald</firstname>
15      <surname>Garcia</surname>
16      <affiliation>
17	<orgname>Indiana University</orgname>
18	<orgdiv>Open Systems Lab</orgdiv>
19      </affiliation>
20    </author>
21    <orgname>BOOST</orgname>
22    <copyright>
23      <year>2002</year>
24      <holder>The Trustees of Indiana University</holder>
25    </copyright>
26       <librarypurpose>Multidimensional containers and adaptors for
27       arrays of contiguous data</librarypurpose>
28       <librarycategory name="category:math"/>
29       <librarycategory name="category:containers"/>
30  </libraryinfo>
31
32<title>Boost.MultiArray Reference Manual</title>
33
34
35<para>Boost.MultiArray is composed of several components.
36The MultiArray concept defines a generic interface to multidimensional
37containers.
38<literal>multi_array</literal> is a general purpose container class
39that models MultiArray. <literal>multi_array_ref</literal>
40and <literal>const_multi_array_ref</literal> are adapter
41classes. Using them,
42you can manipulate any block of contiguous data as though it were a
43<literal>multi_array</literal>.
44<literal>const_multi_array_ref</literal> differs from
45<literal>multi_array_ref</literal> in that its elements cannot
46be modified through its interface. Finally, several auxiliary classes are used
47to create and specialize arrays and some global objects are defined as
48part of the library interface.</para>
49
50<sect1 id="synopsis">
51<title>Library Synopsis</title>
52    <para>To use Boost.MultiArray, you must include the header
53<filename>boost/multi_array.hpp</filename> in your source. This file
54brings the following declarations into scope:</para>
55<programlisting>
56<![CDATA[namespace boost {
57
58  namespace multi_array_types {
59    typedef *unspecified* index;
60    typedef *unspecified* size_type;
61    typedef *unspecified* difference_type;
62    typedef *unspecified* index_range;
63    typedef *unspecified* extent_range;
64    typedef *unspecified* index_gen;
65    typedef *unspecified* extent_gen;
66  }
67
68  template <typename ValueType,
69            std::size_t NumDims,
70            typename Allocator = std::allocator<ValueType> >
71  class multi_array;
72
73  template <typename ValueType,
74            std::size_t NumDims>
75  class multi_array_ref;
76
77  template <typename ValueType,
78            std::size_t NumDims>
79  class const_multi_array_ref;
80
81  multi_array_types::extent_gen extents;
82  multi_array_types::index_gen  indices;
83
84  template <typename Array, int N> class subarray_gen;
85  template <typename Array, int N> class const_subarray_gen;
86  template <typename Array, int N> class array_view_gen;
87  template <typename Array, int N> class const_array_view_gen;
88
89  class c_storage_order;
90  class fortran_storage_order;
91  template <std::size_t NumDims> class general_storage_order;
92
93}]]>
94</programlisting>
95</sect1>
96
97&concepts;
98
99<sect1 id="array_types">
100<title>Array Components</title>
101<para>
102Boost.MultiArray defines an array class,
103<literal>multi_array</literal>, and two adapter classes,
104<literal>multi_array_ref</literal> and
105<literal>const_multi_array_ref</literal>. The three classes model
106MultiArray and so they share a lot of functionality.
107<literal>multi_array_ref</literal> differs from
108<literal>multi_array</literal> in that the
109<literal>multi_array</literal> manages its own memory, while
110<literal>multi_array_ref</literal> is passed a block of memory that it
111expects to be externally managed.
112<literal>const_multi_array_ref</literal> differs from
113<literal>multi_array_ref</literal> in that the underlying elements it
114adapts cannot be modified through its interface, though some array
115properties, including the array shape and index bases, can be altered.
116Functionality the classes have in common is described
117below.
118</para>
119
120<formalpara>
121<title>Note: Preconditions, Effects, and Implementation</title>
122<para>
123Throughout the following sections, small pieces of C++ code are
124used to specify constraints such as preconditions, effects, and
125postconditions.  These do not necessarily describe the underlying
126implementation of array components; rather, they describe the
127expected input to and
128behavior of the specified operations.  Failure to meet
129preconditions results in undefined behavior. Not all effects
130(i.e. copy constructors, etc.) must be mimicked exactly.  The code
131snippets for effects intend to capture the essence of the described
132operation.
133</para>
134</formalpara>
135
136<formalpara>
137<title>Queries</title>
138
139<variablelist>
140<varlistentry>
141<term><programlisting>element* data();
142const element* data() const;</programlisting></term>
143<listitem>
144<para>This returns a pointer to the beginning of the
145contiguous block that contains the array's data. If all dimensions of
146the array are 0-indexed and stored in ascending order, this is
147equivalent to <literal>origin()</literal>. Note that
148<literal>const_multi_array_ref</literal> only provides the const
149version of this function.
150</para>
151</listitem>
152</varlistentry>
153
154<varlistentry>
155<term><programlisting>element* origin();
156const element* origin() const;</programlisting></term>
157<listitem>
158<para>This returns the origin element of the
159<literal>multi_array</literal>. Note that
160<literal>const_multi_array_ref</literal> only provides the const
161version of this function. (Required by MultiArray)
162</para>
163</listitem>
164</varlistentry>
165
166<varlistentry>
167<term><function>const index* index_bases();</function></term>
168<listitem>
169<para>This returns the index bases for the
170<literal>multi_array</literal>. (Required by MultiArray)
171</para>
172</listitem>
173</varlistentry>
174
175<varlistentry>
176<term><function>const index* strides();</function></term>
177<listitem>
178<para>This returns the strides for the
179<literal>multi_array</literal>. (Required by MultiArray)
180</para>
181</listitem>
182</varlistentry>
183
184<varlistentry>
185<term><function>const size_type* shape();</function></term>
186<listitem>
187<para>This returns the shape of the
188<literal>multi_array</literal>. (Required by MultiArray)
189</para>
190</listitem>
191</varlistentry>
192</variablelist>
193
194</formalpara>
195
196<formalpara>
197<title>Comparators</title>
198<variablelist>
199<varlistentry>
200<term><programlisting><![CDATA[
201bool operator==(const *array-type*& rhs);
202bool operator!=(const *array-type*& rhs);
203bool operator<(const *array-type*& rhs);
204bool operator>(const *array-type*& rhs);
205bool operator>=(const *array-type*& rhs);
206bool operator<=(const *array-type*& rhs);]]></programlisting></term>
207
208<listitem>
209<para>Each comparator executes a lexicographical compare over
210the value types of the two arrays.
211(Required by MultiArray)
212</para>
213<formalpara>
214<title>Preconditions</title>
215<para><literal>element</literal> must support the
216comparator corresponding to that called on
217<literal>multi_array</literal>.</para>
218</formalpara>
219
220<formalpara>
221<title>Complexity</title>
222<para>O(<literal>num_elements()</literal>).</para>
223</formalpara>
224
225</listitem>
226</varlistentry>
227
228</variablelist>
229</formalpara>
230
231<formalpara>
232<title>Modifiers</title>
233
234<variablelist>
235
236<varlistentry>
237<term>
238<programlisting>
239<![CDATA[
240template <typename SizeList>
241void reshape(const SizeList& sizes)
242]]>
243</programlisting>
244</term>
245
246<listitem>
247<para>This changes the shape of the <literal>multi_array</literal>.  The
248number of elements and the index bases remain the same, but the number
249of values at each level of the nested container hierarchy may
250change.</para>
251
252<formalpara><title><literal>SizeList</literal> Requirements</title>
253<para><literal>SizeList</literal> must model
254<ulink url="../../utility/Collection.html">Collection</ulink>.</para>
255</formalpara>
256
257<formalpara><title>Preconditions</title>
258<para>
259<programlisting>
260<![CDATA[std::accumulate(sizes.begin(),sizes.end(),size_type(1),std::times<size_type>()) == this->num_elements();
261sizes.size() == NumDims;]]>
262</programlisting></para>
263</formalpara>
264
265
266<formalpara><title>Postconditions</title>
267<para>
268<literal>std::equal(sizes.begin(),sizes.end(),this->shape) == true;</literal>
269</para>
270</formalpara>
271</listitem>
272</varlistentry>
273
274<varlistentry>
275<term>
276<programlisting>
277<![CDATA[
278template <typename BaseList>
279void reindex(const BaseList& values);
280]]>
281</programlisting>
282</term>
283<listitem>
284<para>This changes the index bases of the <literal>multi_array</literal> to
285correspond to the the values in <literal>values</literal>.</para>
286
287<formalpara>
288<title><literal>BaseList</literal> Requirements</title>
289<para><literal>BaseList</literal> must model
290<ulink url="../../utility/Collection.html">Collection</ulink>.</para>
291</formalpara>
292
293<formalpara>
294<title>Preconditions</title>
295<para><literal>values.size() == NumDims;</literal></para>
296</formalpara>
297
298
299<formalpara>
300<title>Postconditions</title>
301<para><literal>std::equal(values.begin(),values.end(),this->index_bases());
302</literal></para>
303</formalpara>
304</listitem>
305</varlistentry>
306
307<varlistentry>
308<term>
309<programlisting>
310<![CDATA[
311void reindex(index value);
312]]>
313</programlisting>
314</term>
315<listitem>
316<para>This changes the index bases of all dimensions of the
317<literal>multi_array</literal> to <literal>value</literal>.</para>
318
319<formalpara>
320<title>Postconditions</title>
321<para>
322<programlisting>
323<![CDATA[
324std::count_if(this->index_bases(),this->index_bases()+this->num_dimensions(),
325              std::bind_2nd(std::equal_to<index>(),value)) ==
326              this->num_dimensions();
327]]>
328</programlisting>
329</para>
330</formalpara>
331</listitem>
332</varlistentry>
333
334</variablelist>
335</formalpara>
336
337&multi_array;
338&multi_array_ref;
339&const_multi_array_ref;
340
341</sect1>
342
343
344<sect1 id="auxiliary">
345    <title>Auxiliary Components</title>
346
347<sect2 id="multi_array_types">
348<title><literal>multi_array_types</literal></title>
349
350<programlisting>
351<![CDATA[namespace multi_array_types {
352  typedef *unspecified* index;
353  typedef *unspecified* size_type;
354  typedef *unspecified* difference_type;
355  typedef *unspecified* index_range;
356  typedef *unspecified* extent_range;
357  typedef *unspecified* index_gen;
358  typedef *unspecified* extent_gen;
359}]]>
360</programlisting>
361
362<para>Namespace <literal>multi_array_types</literal> defines types
363associated with <literal>multi_array</literal>,
364<literal>multi_array_ref</literal>, and
365<literal>const_multi_array_ref</literal> that are not
366dependent upon template parameters.  These types find common use with
367all Boost.Multiarray components.  They are defined
368in a namespace from which they can be accessed conveniently.
369With the exception of <literal>extent_gen</literal> and
370<literal>extent_range</literal>, these types fulfill the roles of the
371same name required by MultiArray and are described in its
372concept definition.  <literal>extent_gen</literal> and
373<literal>extent_range</literal> are described below.
374</para>
375</sect2>
376
377
378<sect2 id="extent_range">
379    <title><classname>extent_range</classname></title>
380
381<para><classname>extent_range</classname> objects define half open
382intervals.  They provide shape and index base information to
383<literal>multi_array</literal>, <literal>multi_array_ref</literal>,
384 and <literal>const_multi_array_ref</literal> constructors.
385<classname>extent_range</classname>s are passed in
386aggregate to an array constructor (see
387<classname>extent_gen</classname> for more details).
388</para>
389
390<formalpara>
391	<title>Synopsis</title>
392<programlisting><![CDATA[
393class extent_range {
394public:
395  typedef multi_array_types::index      index;
396  typedef multi_array_types::size_type  size_type;
397
398  // Structors
399  extent_range(index start, index finish);
400  extent_range(index finish);
401  ~extent_range();
402
403  // Queries
404  index start();
405  index finish();
406  size_type size();
407};]]></programlisting>
408</formalpara>
409
410      <formalpara>
411	<title>Model Of</title>
412	<para>DefaultConstructible,CopyConstructible</para>
413      </formalpara>
414
415<formalpara><title>Methods and Types</title>
416<variablelist>
417<varlistentry>
418<term><function>extent_range(index start, index finish)</function></term>
419<listitem>
420<para>  This constructor defines the half open interval
421<literal>[start,finish)</literal>. The expression
422<literal>finish</literal> must be greater than <literal>start</literal>.
423</para>
424</listitem>
425</varlistentry>
426
427<varlistentry><term><function>extent_range(index finish)</function></term>
428<listitem>
429<para>This constructor defines the half open interval
430<literal>[0,finish)</literal>. The value of <literal>finish</literal>
431must be positive.</para>
432</listitem>
433</varlistentry>
434
435<varlistentry><term><function>index start()</function></term>
436<listitem>
437<para>This function returns the first index represented by the range</para>
438</listitem>
439</varlistentry>
440
441<varlistentry><term><function>index finish()</function></term>
442<listitem>
443<para>This function returns the upper boundary value of the half-open
444interval.  Note that the range does not include this value.</para>
445</listitem>
446</varlistentry>
447
448<varlistentry>
449<term><function>size_type size()</function></term>
450<listitem>
451<para>This function returns the size of the specified range. It is
452equivalent to <literal>finish()-start()</literal>.</para>
453</listitem>
454</varlistentry>
455
456</variablelist>
457</formalpara>
458</sect2>
459
460<sect2 id="extent_gen">
461    <title><classname>extent_gen</classname></title>
462    <para>The <classname>extent_gen</classname> class defines an
463interface for aggregating array shape and indexing information to be
464passed to a <literal>multi_array</literal>,
465<literal>multi_array_ref</literal>, or <literal>const_multi_array_ref</literal>
466constructor. Its interface mimics
467 the syntax used to declare built-in array types
468in C++. For example, while a 3-dimensional array of
469<classname>int</classname> values in C++ would be
470declared as:
471<programlisting>int A[3][4][5],</programlisting>
472a similar <classname>multi_array</classname> would be declared:
473<programlisting>multi_array&lt;int,3&gt; A(extents[3][4][5]).</programlisting>
474</para>
475
476<formalpara><title>Synopsis</title>
477<programlisting><![CDATA[
478template <std::size_t NumRanges>
479class *implementation_defined* {
480public:
481  typedef multi_array_types::index index;
482  typedef multi_array_types::size_type size_type;
483
484  template <std::size_t NumRanges> class gen_type;
485
486  gen_type<NumRanges+1>::type  operator[](const range& a_range) const;
487  gen_type<NumRanges+1>::type  operator[](index idx) const;
488};
489
490typedef *implementation_defined*<0> extent_gen;
491]]></programlisting>
492</formalpara>
493
494<formalpara><title>Methods and Types</title>
495<variablelist>
496<varlistentry>
497<term><function>template gen_type&lt;Ranges&gt;::type</function></term>
498<listitem>
499<para>This type generator is used to specify the result of
500<literal>Ranges</literal> chained calls to
501<literal>extent_gen::operator[].</literal> The types
502<classname>extent_gen</classname> and
503<classname>gen_type&lt;0&gt;::type</classname> are the same.</para>
504</listitem>
505</varlistentry>
506
507<varlistentry>
508<term><function>gen_type&lt;NumRanges+1&gt;::type
509operator[](const extent_range&amp; a_range) const;</function></term>
510<listitem>
511<para>This function returns a new object containing all previous
512<classname>extent_range</classname> objects in addition to
513<literal>a_range.</literal> <classname>extent_range</classname>
514objects are aggregated by chained calls to
515<function>operator[]</function>.</para>
516</listitem>
517</varlistentry>
518
519<varlistentry>
520<term><function>gen_type&lt;NumRanges+1&gt;::type
521operator[](index idx) const;</function></term>
522<listitem>
523<para>This function returns a new object containing all previous
524<classname>extent_range</classname> objects in addition to
525<literal>extent_range(0,idx).</literal> This function gives the array
526constructors a similar syntax to traditional C multidimensional array
527declaration.</para>
528</listitem>
529</varlistentry>
530
531</variablelist>
532</formalpara>
533</sect2>
534
535<sect2>
536    <title>Global Objects</title>
537    <para>For syntactic convenience, Boost.MultiArray defines two
538global objects as part of its
539interface.  These objects play the role of object generators;
540expressions involving them create other objects of interest.
541</para>
542
543    <para> Under some circumstances, the two global objects may be
544considered excessive overhead.  Their construction can be prevented by
545defining the preprocessor symbol
546<literal>BOOST_MULTI_ARRAY_NO_GENERATORS</literal> before including
547<filename>boost/multi_array.hpp.</filename></para>
548
549<sect3 id="extents">
550<title><literal>extents</literal></title>
551
552<programlisting>
553<![CDATA[namespace boost {
554  multi_array_base::extent_gen extents;
555}]]>
556</programlisting>
557
558    <para>Boost.MultiArray's array classes use the
559<literal>extents</literal> global object to specify
560array shape during their construction.
561For example,
562a 3 by 3 by 3 <classname>multi_array</classname> is constructed as follows:
563<programlisting>multi_array&lt;int,3&gt; A(extents[3][3][3]);</programlisting>
564The same array could also be created by explicitly declaring an <literal>extent_gen</literal>
565object locally,, but the global object makes this declaration unnecessary.
566</para>
567</sect3>
568
569<sect3 id="indices">
570<title><literal>indices</literal></title>
571
572<programlisting>
573<![CDATA[namespace boost {
574  multi_array_base::index_gen  indices;
575}]]>
576</programlisting>
577
578      <para>The MultiArray concept specifies an
579<literal>index_gen</literal> associated type that is used to
580create views.
581<literal>indices</literal> is a global object that serves the role of
582<literal>index_gen</literal> for all array components provided by this
583library and their associated subarrays and views.
584</para>
585<para>For example, using the <literal>indices</literal> object,
586a view of an array <literal>A</literal> is constructed as follows:
587<programlisting>
588A[indices[index_range(0,5)][2][index_range(2,4)]];
589</programlisting>
590</para>
591</sect3>
592</sect2>
593
594<sect2 id="generators">
595<title>View and SubArray Generators</title>
596<para>
597Boost.MultiArray provides traits classes, <literal>subarray_gen</literal>,
598<literal>const_subarray_gen</literal>,
599<literal>array_view_gen</literal>,
600and <literal>const_array_view_gen</literal>, for naming of
601array associated types within function templates.
602In general this is no more convenient to use than the nested
603type generators, but the library author found that some C++ compilers do not
604properly handle templates nested within function template parameter types.
605These generators constitute a workaround for this deficit.
606The following code snippet illustrates
607the correspondence between the <literal>array_view_gen</literal>
608traits class and the <literal>array_view</literal> type associated to
609an array:
610
611<programlisting>
612template &lt;typename Array&gt;
613void my_function() {
614  typedef typename Array::template array_view&lt;3&gt;::type view1_t;
615  typedef typename boost::array_view_gen&lt;Array,3&gt;::type view2_t;
616  // ...
617}
618</programlisting>
619
620In the above example, <literal>view1_t</literal> and
621<literal>view2_t</literal> have the same type.
622</para>
623</sect2>
624
625
626<sect2 id="memory_layout">
627<title>Memory Layout Specifiers</title>
628<para>
629While a multidimensional array represents a hierarchy of containers of
630elements, at some point the elements must be laid out in
631memory.  As a result, a single multidimensional array
632can be represented in memory more than one way.
633</para>
634
635<para>For example, consider the two dimensional array shown below in
636matrix notation:
637
638<graphic fileref="matrix.gif"/>
639
640Here is how the above array is expressed in C++:
641<programlisting>
642int a[3][4] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
643</programlisting>
644This is an example of row-major storage, where elements of each row
645are stored contiguously.
646
647While C++ transparently handles accessing elements of an array, you
648can also manage the array and its indexing manually.  One way that
649this may be expressed in memory is as follows:
650<programlisting>
651int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
652int s[] = { 4, 1 };
653</programlisting>
654
655With the latter declaration of <literal>a</literal> and
656strides <literal>s</literal>, element <literal>a(i,j)</literal>
657of the array can be
658accessed using the expression
659<programlisting>*a+i*s[0]+j*s[1]</programlisting>.
660</para>
661
662<para>The same two dimensional array could be laid out by column as follows:
663
664<programlisting>
665int a[] = { 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11 };
666int s[] = { 3, 1 };
667</programlisting>
668Notice that the strides here are different. As a result,
669The expression given above to access values will work with this pair
670of data and strides as well.
671</para>
672
673<para>In addition to dimension order, it is also possible to
674store any dimension in descending order. For example, returning to the
675first example, the first dimension of the example array, the
676rows,  could be stored in
677reverse, resulting in the following:
678
679<programlisting>
680int data[] = { 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3 };
681int *a = data + 8;
682int s[] = { -4, 1 };
683</programlisting>
684
685Note that in this example <literal>a</literal> must be explicitly set
686to the origin. In the previous examples, the
687first element stored in memory was the origin; here this is no longer
688the case.
689</para>
690
691<para>
692Alternatively, the second dimension, or the columns, could be reversed
693and the rows stored in ascending order:
694
695<programlisting>
696int data[] = { 3, 2, 1, 0,  7, 6, 5, 4, 11, 10, 9, 8 };
697int *a = data + 3;
698int s[] = { 4, -1 };
699</programlisting>
700</para>
701
702<para>
703Finally, both dimensions could be stored in descending order:
704
705<programlisting>
706int data[] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
707int *a = data + 11;
708int s[] = { -4, -1 };
709</programlisting>
710<literal>
711</literal>
712</para>
713
714<para>
715All of the above arrays are equivalent. The expression
716given above for <literal>a(i,j)</literal> will yield the same value
717regardless of the memory layout.
718
719Boost.MultiArray arrays can be created with customized storage
720parameters as described above. Thus, existing data can be adapted
721(with <literal>multi_array_ref</literal> or
722<literal>const_multi_array_ref</literal>) as suited to the array
723abstraction.  A common usage of this feature would be to wrap arrays
724that must interoperate with Fortran routines so they can be
725manipulated naturally at both the C++ and Fortran levels. The
726following sections describe the Boost.MultiArray components used to
727specify memory layout.
728</para>
729
730<sect3 id="c_storage_order">
731<title><literal>c_storage_order</literal></title>
732<programlisting>
733<![CDATA[class c_storage_order {
734  c_storage_order();
735};]]>
736</programlisting>
737
738<para><literal>c_storage_order</literal> is used to specify that an
739array should store its elements using the same layout as that used by
740primitive C++ multidimensional arrays, that is, from last dimension
741to first. This is the default storage order for the arrays provided by
742this library.</para>
743</sect3>
744
745<sect3 id="fortran_storage_order">
746<title><literal>fortran_storage_order</literal></title>
747<programlisting>
748<![CDATA[class fortran_storage_order {
749  fortran_storage_order();
750};]]>
751</programlisting>
752
753<para><literal>fortran_storage_order</literal> is used to specify that
754an array should store its elements using the same memory layout as a
755Fortran multidimensional array would, that is, from first dimension to
756last.</para>
757</sect3>
758
759<sect3 id="general_storage_order">
760<title><literal>general_storage_order</literal></title>
761<programlisting>
762<![CDATA[template <std::size_t NumDims>
763class general_storage_order {
764
765  template <typename OrderingIter, typename AscendingIter>
766  general_storage_order(OrderingIter ordering, AscendingIter ascending);
767};]]>
768</programlisting>
769
770<para><literal>general_storage_order</literal> allows the user to
771specify an arbitrary memory layout for the contents of an array.  The
772constructed object is passed to the array constructor in order to
773specify storage order.</para>
774
775<para>
776<literal>OrderingIter</literal> and <literal>AscendingIter</literal>
777must model the <literal>InputIterator</literal> concept.  Both
778iterators must refer to a range of <literal>NumDims</literal>
779elements.  <literal>AscendingIter</literal> points to objects
780convertible to <literal>bool</literal>.  A value of
781<literal>true</literal> means that a dimension is stored in ascending
782order while <literal>false</literal> means that a dimension is stored
783in descending order.  <literal>OrderingIter</literal> specifies the
784order in which dimensions are stored.
785</para>
786
787</sect3>
788</sect2>
789
790<sect2 id="range_checking">
791<title>Range Checking</title>
792<para>
793By default, the array access methods <literal>operator()</literal> and
794<literal>operator[]</literal> perform range
795checking.  If a supplied index is out of the range defined for an
796array, an assertion will abort the program.  To disable range
797checking (for performance reasons in production releases), define
798the <literal>BOOST_DISABLE_ASSERTS</literal> preprocessor macro prior to
799including multi_array.hpp in an application.
800</para>
801
802</sect2>
803</sect1>
804
805
806</library>
807