]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <sect1 id="MultiArray"><title>MultiArray Concept</title> |
2 | ||
3 | ||
4 | <para>The MultiArray | |
5 | concept defines an interface to hierarchically nested | |
6 | containers. It specifies operations for accessing elements, | |
7 | traversing containers, and creating views | |
8 | of array data. | |
9 | MultiArray defines | |
10 | a flexible memory model that accomodates | |
11 | a variety of data layouts. | |
12 | </para> | |
13 | ||
14 | <para> | |
15 | At each level (or dimension) of a MultiArray's | |
16 | container hierarchy lie a set of ordered containers, each of which | |
17 | contains the same number and type of values. The depth of this | |
18 | container hierarchy is the MultiArray's <emphasis>dimensionality</emphasis>. | |
19 | MultiArray is recursively defined; the | |
20 | containers at each level of the container hierarchy model | |
21 | MultiArray as well. While each dimension of a MultiArray | |
22 | has its own size, the list of sizes for all dimensions | |
23 | defines the <emphasis>shape</emphasis> of the entire MultiArray. | |
24 | At the base of this hierarchy lie 1-dimensional | |
25 | MultiArrays. Their values are the contained | |
26 | objects of interest and not part of the container hierarchy. These are | |
27 | the MultiArray's elements. | |
28 | </para> | |
29 | ||
30 | ||
31 | <para> | |
32 | Like other container concepts, MultiArray exports | |
33 | iterators to traverse its values. In addition, values can be | |
34 | addressed directly using the familiar bracket notation. | |
35 | </para> | |
36 | ||
37 | <para> | |
38 | MultiArray also specifies | |
39 | routines for creating | |
40 | specialized views. A <emphasis>view</emphasis> lets you treat a | |
41 | subset of the underlying | |
42 | elements in a MultiArray as though it were a separate | |
43 | MultiArray. Since a view refers to the same underlying elements, | |
44 | changes made to a view's elements will be reflected in the original | |
45 | MultiArray. For | |
46 | example, given a 3-dimensional "cube" of elements, a 2-dimensional | |
47 | slice can be viewed as if it were an independent | |
48 | MultiArray. | |
49 | ||
50 | Views are created using <literal>index_gen</literal> and | |
51 | <literal>index_range</literal> objects. | |
52 | <literal>index_range</literal>s denote elements from a certain | |
53 | dimension that are to be included in a | |
54 | view. <literal>index_gen</literal> aggregates range data and performs | |
55 | bookkeeping to determine the view type to be returned. | |
56 | ||
57 | MultiArray's <literal>operator[]</literal> | |
58 | must be passed the result | |
59 | of <literal>N</literal> chained calls to | |
60 | <literal>index_gen::operator[]</literal>, i.e. | |
61 | ||
62 | <programlisting>indices[a0][a1]...[aN]; | |
63 | </programlisting> | |
64 | ||
65 | where <literal>N</literal> is the | |
66 | MultiArray's dimensionality and | |
67 | <literal>indices</literal> an object of type <literal>index_gen</literal>. | |
68 | ||
69 | The view type is dependent upon the number of degenerate dimensions | |
70 | specified to <literal>index_gen</literal>. A degenerate dimension | |
71 | occurs when a single-index is specified to | |
72 | <literal>index_gen</literal> for a certain dimension. For example, if | |
73 | <literal>indices</literal> is an object of type | |
74 | <literal>index_gen</literal>, then the following example: | |
75 | ||
76 | <programlisting>indices[index_range(0,5)][2][index_range(0,4)]; | |
77 | </programlisting> | |
78 | ||
79 | has a degenerate second dimension. The view generated from the above | |
80 | specification will have 2 dimensions with shape <literal>5 x 4</literal>. | |
81 | If the "<literal>2</literal>" above were replaced with | |
82 | another <literal>index_range</literal> object, for example: | |
83 | ||
84 | <programlisting>indices[index_range(0,5)][index_range(0,2)][index_range(0,4)]; | |
85 | </programlisting> | |
86 | ||
87 | then the view would have 3 dimensions.</para> | |
88 | ||
89 | <para> | |
90 | MultiArray exports | |
91 | information regarding the memory | |
92 | layout of its contained elements. Its memory model for elements is | |
93 | completely defined by 4 properties: the origin, shape, index bases, | |
94 | and strides. The origin is the address in memory of the element | |
95 | accessed as <literal>a[0][0]...[0]</literal>, where | |
96 | <literal>a</literal> is a MultiArray. The shape is a list of numbers | |
97 | specifying the size of containers at each dimension. For example, the | |
98 | first extent is the size of the outermost container, the second extent | |
99 | is the size of its subcontainers, and so on. The index bases are a | |
100 | list of signed values specifying the index of the first value in a | |
101 | container. All containers at the same dimension share the same index | |
102 | base. Note that since positive index bases are | |
103 | possible, the origin need not exist in order to determine the location | |
104 | in memory of the MultiArray's elements. | |
105 | The strides determine how index values are mapped to memory offsets. | |
106 | They accomodate a | |
107 | number of possible element layouts. For example, the elements of a 2 | |
108 | dimensional array can be stored by row (i.e., the elements of each row | |
109 | are stored contiguously) or by column (i.e., the elements of each | |
110 | column are stored contiguously). | |
111 | </para> | |
112 | ||
113 | <para> | |
114 | Two concept checking classes for the MultiArray concepts | |
115 | (<literal>ConstMultiArrayConcept</literal> and | |
116 | <literal>MutableMultiArrayConcept</literal>) are in the namespace | |
117 | <literal>boost::multi_array_concepts</literal> in | |
118 | <literal><boost/multi_array/concept_checks.hpp></literal>. | |
119 | </para> | |
120 | ||
121 | ||
122 | <sect2><title>Notation</title> | |
123 | <para>What follows are the descriptions of symbols that will be used | |
124 | to describe the MultiArray interface.</para> | |
125 | <table> | |
126 | <title>Notation</title> | |
127 | <tgroup cols="2"> | |
128 | <tbody> | |
129 | <row> | |
130 | <entry><literal>A</literal></entry> | |
131 | <entry>A type that is a model of MultiArray | |
132 | </entry> | |
133 | </row> | |
134 | <row> | |
135 | <entry><literal>a,b</literal></entry> | |
136 | <entry>Objects of type <literal>A</literal></entry> | |
137 | </row> | |
138 | <row> | |
139 | <entry><literal>NumDims</literal></entry> | |
140 | <entry>The numeric dimension parameter associated with | |
141 | <literal>A</literal>.</entry> | |
142 | </row> | |
143 | <row> | |
144 | <entry><literal>Dims</literal></entry> | |
145 | <entry>Some numeric dimension parameter such that | |
146 | <literal>0<Dims<NumDims</literal>. | |
147 | </entry> | |
148 | </row> | |
149 | <row> | |
150 | <entry><literal>indices</literal></entry> | |
151 | <entry>An object created by some number of chained calls | |
152 | to <literal>index_gen::operator[](index_range)</literal>.</entry> | |
153 | </row> | |
154 | <row> | |
155 | <entry><literal>index_list</literal></entry> | |
156 | <entry>An object whose type models | |
157 | <ulink url="../../utility/Collection.html">Collection</ulink> | |
158 | </entry> | |
159 | </row> | |
160 | <row> | |
161 | <entry><literal>idx</literal></entry> | |
162 | <entry>A signed integral value.</entry> | |
163 | </row> | |
164 | <row> | |
165 | <entry><literal>tmp</literal></entry> | |
166 | <entry>An object of type | |
167 | <literal>boost::array<index,NumDims></literal></entry> | |
168 | </row> | |
169 | </tbody> | |
170 | </tgroup> | |
171 | </table> | |
172 | </sect2> | |
173 | ||
174 | <sect2><title>Associated Types</title> | |
175 | <para> | |
176 | </para> | |
177 | <table><title>Associated Types</title> | |
178 | <tgroup cols="2"> | |
179 | ||
180 | <thead> | |
181 | <row> | |
182 | <entry>Type</entry> | |
183 | <entry>Description</entry> | |
184 | </row> | |
185 | </thead> | |
186 | ||
187 | <tbody> | |
188 | ||
189 | <row> | |
190 | <entry><literal>value_type</literal></entry> | |
191 | ||
192 | <entry>This is the value type of the container. | |
193 | If <literal>NumDims == 1</literal>, then this is | |
194 | <literal>element</literal>. Otherwise, this is the value type of the | |
195 | immediately nested containers. | |
196 | </entry> | |
197 | </row> | |
198 | ||
199 | <row> | |
200 | <entry> | |
201 | <literal>reference</literal> | |
202 | </entry> | |
203 | ||
204 | <entry> | |
205 | This is the reference type of the contained value. | |
206 | If <literal>NumDims == 1</literal>, then this is | |
207 | <literal>element&</literal>. Otherwise, this is the same type as | |
208 | <literal>template subarray<NumDims-1>::type</literal>. | |
209 | </entry> | |
210 | </row> | |
211 | ||
212 | <row> | |
213 | <entry> | |
214 | <literal>const_reference</literal> | |
215 | </entry> | |
216 | <entry> | |
217 | This is the const reference type of the contained value. | |
218 | If <literal>NumDims == 1</literal>, then this is | |
219 | <literal>const element&</literal>. Otherwise, this is the same | |
220 | type as | |
221 | <literal>template const_subarray<NumDims-1>::type</literal>. | |
222 | </entry> | |
223 | </row> | |
224 | ||
225 | <row> | |
226 | <entry> | |
227 | <literal>size_type</literal> | |
228 | </entry> | |
229 | <entry> | |
230 | This is an unsigned integral type. It is primarily used to specify array shape. | |
231 | </entry> | |
232 | </row> | |
233 | ||
234 | ||
235 | <row> | |
236 | <entry> | |
237 | <literal>difference_type</literal> | |
238 | </entry> | |
239 | <entry> | |
240 | This is a signed integral type used to represent the distance between two | |
241 | iterators. It is the same type as | |
242 | <literal>std::iterator_traits<iterator>::difference_type</literal>. | |
243 | </entry> | |
244 | </row> | |
245 | ||
246 | <row> | |
247 | <entry><literal>iterator</literal></entry> | |
248 | <entry> | |
249 | This is an iterator over the values of <literal>A</literal>. | |
250 | If <literal>NumDims == 1</literal>, then it models | |
251 | <ulink url="http://www.boost.org/doc/html/RandomAccessIterator.html"> | |
252 | <literal>Random Access Iterator</literal></ulink>. | |
253 | Otherwise it models | |
254 | <ulink url="./iterator_categories.html#concept_RandomAccessTraversalIterator"> | |
255 | Random Access Traversal Iterator</ulink>, | |
256 | <ulink url="./iterator_categories.html#concept_ReadableIterator"> | |
257 | Readable Iterator</ulink>, | |
258 | <ulink url="./iterator_categories.html#concept_WritableIterator"> | |
259 | Writable Iterator</ulink>, and | |
260 | <ulink url="http://www.boost.org/doc/html/OutputIterator.html"> | |
261 | <literal>Output Iterator</literal></ulink>. | |
262 | </entry> | |
263 | </row> | |
264 | ||
265 | <row> | |
266 | <entry> | |
267 | <literal>const_iterator</literal> | |
268 | </entry> | |
269 | <entry> | |
270 | This is the const iterator over the values of <literal>A</literal>. | |
271 | </entry> | |
272 | </row> | |
273 | <row> | |
274 | ||
275 | <entry> | |
276 | <literal>reverse_iterator</literal> | |
277 | </entry> | |
278 | <entry> | |
279 | This is the reversed iterator, used to iterate backwards over the values of | |
280 | <literal>A</literal>. | |
281 | </entry> | |
282 | </row> | |
283 | ||
284 | <row> | |
285 | <entry> | |
286 | <literal>const_reverse_iterator</literal> | |
287 | </entry> | |
288 | <entry> | |
289 | This is the reversed const iterator. | |
290 | <literal>A</literal>. | |
291 | </entry> | |
292 | </row> | |
293 | <row> | |
294 | ||
295 | <entry> | |
296 | <literal>element</literal> | |
297 | </entry> | |
298 | <entry> | |
299 | This is the type of objects stored at the base of the | |
300 | hierarchy of MultiArrays. It is the same as | |
301 | <literal>template subarray<1>::value_type</literal> | |
302 | </entry> | |
303 | </row> | |
304 | ||
305 | <row> | |
306 | <entry> | |
307 | <literal>index</literal> | |
308 | </entry> | |
309 | <entry> | |
310 | This is a signed integral type used for indexing into <literal>A</literal>. It | |
311 | is also used to represent strides and index bases. | |
312 | </entry> | |
313 | </row> | |
314 | ||
315 | <row> | |
316 | <entry> | |
317 | <literal>index_gen</literal> | |
318 | </entry> | |
319 | <entry> | |
320 | This type is used to create a tuple of <literal>index_range</literal>s | |
321 | passed to <literal>operator[]</literal> to create | |
322 | an <literal>array_view<Dims>::type</literal> object. | |
323 | </entry> | |
324 | </row> | |
325 | ||
326 | <row> | |
327 | <entry> | |
328 | <literal>index_range</literal> | |
329 | </entry> | |
330 | <entry> | |
331 | This type specifies a range of indices over some dimension of a | |
332 | MultiArray. This range will be visible through an | |
333 | <literal>array_view<Dims>::type</literal> object. | |
334 | </entry> | |
335 | </row> | |
336 | ||
337 | <row> | |
338 | <entry> | |
339 | <literal>template subarray<Dims>::type</literal> | |
340 | </entry> | |
341 | <entry> | |
342 | This is subarray type with <literal>Dims</literal> dimensions. | |
343 | It is the reference type of the <literal>(NumDims - Dims)</literal> | |
344 | dimension of <literal>A</literal> and also models | |
345 | MultiArray. | |
346 | </entry> | |
347 | </row> | |
348 | ||
349 | <row> | |
350 | <entry> | |
351 | <literal>template const_subarray<Dims>::type</literal> | |
352 | </entry> | |
353 | <entry> | |
354 | This is the const subarray type. | |
355 | </entry> | |
356 | </row> | |
357 | ||
358 | <row> | |
359 | <entry> | |
360 | <literal>template array_view<Dims>::type</literal> | |
361 | </entry> | |
362 | <entry> | |
363 | This is the view type with <literal>Dims</literal> dimensions. It is | |
364 | returned by calling <literal>operator[](<literal>indices</literal>)</literal>. | |
365 | It models MultiArray. | |
366 | </entry> | |
367 | </row> | |
368 | ||
369 | <row> | |
370 | <entry> | |
371 | <literal>template | |
372 | const_array_view<Dims>::type</literal> | |
373 | </entry> | |
374 | <entry> | |
375 | This is the const view type with <literal>Dims</literal> dimensions. | |
376 | </entry> | |
377 | </row> | |
378 | ||
379 | </tbody> | |
380 | </tgroup> | |
381 | </table> | |
382 | ||
383 | </sect2> | |
384 | ||
385 | ||
386 | <sect2><title>Valid expressions</title> | |
387 | ||
388 | <table><title>Valid Expressions</title> | |
389 | <tgroup cols="3"> | |
390 | <thead> | |
391 | <row> | |
392 | <entry>Expression</entry> | |
393 | <entry>Return type</entry> | |
394 | <entry>Semantics</entry> | |
395 | </row> | |
396 | </thead> | |
397 | <tbody> | |
398 | <row> | |
399 | <entry><literal>A::dimensionality</literal></entry> | |
400 | <entry><literal>size_type</literal></entry> | |
401 | <entry>This compile-time constant represents the number of | |
402 | dimensions of the array (note that | |
403 | <literal>A::dimensionality == NumDims</literal>).</entry> | |
404 | </row> | |
405 | <row> | |
406 | <entry><literal>a.shape()</literal></entry> | |
407 | <entry><literal>const size_type*</literal></entry> | |
408 | <entry> | |
409 | This returns a list of <literal>NumDims</literal> elements specifying the | |
410 | extent of each array dimension. | |
411 | </entry> | |
412 | </row> | |
413 | ||
414 | <row> | |
415 | <entry><literal>a.strides()</literal></entry> | |
416 | <entry><literal>const index*</literal></entry> | |
417 | <entry> | |
418 | This returns a list of <literal>NumDims</literal> elements specifying the | |
419 | stride associated with each array dimension. When accessing values, | |
420 | strides is used to calculate an element's location in memory. | |
421 | </entry> | |
422 | </row> | |
423 | ||
424 | <row> | |
425 | <entry><literal>a.index_bases()</literal></entry> | |
426 | <entry><literal>const index*</literal></entry> | |
427 | <entry> | |
428 | This returns a list of <literal>NumDims</literal> elements specifying the | |
429 | numeric index of the first element for each array dimension. | |
430 | </entry> | |
431 | </row> | |
432 | <row> | |
433 | <entry><literal>a.origin()</literal></entry> | |
434 | <entry> | |
435 | <literal>element*</literal> if <literal>a</literal> is mutable, | |
436 | <literal>const element*</literal> otherwise. | |
437 | </entry> | |
438 | <entry> | |
439 | This returns the address of the element accessed by the expression | |
440 | <literal>a[0][0]...[0].</literal>. If the index bases are positive, | |
441 | this element won't exist, but the address can still be used to locate | |
442 | a valid element given its indices. | |
443 | </entry> | |
444 | </row> | |
445 | <row> | |
446 | <entry><literal>a.num_dimensions()</literal></entry> | |
447 | <entry><literal>size_type</literal></entry> | |
448 | <entry>This returns the number of dimensions of the array | |
449 | (note that <literal>a.num_dimensions() == NumDims</literal>).</entry> | |
450 | </row> | |
451 | ||
452 | <row> | |
453 | <entry><literal>a.num_elements()</literal></entry> | |
454 | <entry><literal>size_type</literal></entry> | |
455 | <entry>This returns the number of elements contained | |
456 | in the array. It is equivalent to the following code: | |
457 | <programlisting> | |
458 | std::accumulate(a.shape(),a.shape+a.num_dimensions(), | |
459 | size_type(1),std::multiplies<size_type>()); | |
460 | </programlisting> | |
461 | </entry> | |
462 | </row> | |
463 | ||
464 | <row> | |
465 | <entry><literal>a.size()</literal></entry> | |
466 | <entry><literal>size_type</literal></entry> | |
467 | <entry> | |
468 | This returns the number of values contained in | |
469 | <literal>a</literal>. It is equivalent to <literal>a.shape()[0];</literal> | |
470 | </entry> | |
471 | </row> | |
472 | <row> | |
473 | <entry><literal>a(index_list)</literal></entry> | |
474 | <entry> | |
475 | <literal>element&</literal>; if <literal>a</literal> is mutable, | |
476 | <literal>const element&</literal> otherwise. | |
477 | </entry> | |
478 | <entry> | |
479 | This expression accesses a specific element of | |
480 | <literal>a</literal>.<literal>index_list</literal> is the unique set | |
481 | of indices that address the element returned. It is | |
482 | equivalent to the following code (disregarding intermediate temporaries): | |
483 | <programlisting> | |
484 | // multiply indices by strides | |
485 | std::transform(index_list.begin(), index_list.end(), | |
486 | a.strides(), tmp.begin(), std::multiplies<index>()), | |
487 | ||
488 | // add the sum of the products to the origin | |
489 | *std::accumulate(tmp.begin(), tmp.end(), a.origin()); | |
490 | </programlisting> | |
491 | </entry> | |
492 | </row> | |
493 | ||
494 | <row> | |
495 | <entry><literal>a.begin()</literal></entry> | |
496 | <entry> | |
497 | <literal>iterator</literal> if <literal>a</literal> is mutable, | |
498 | <literal>const_iterator</literal> otherwise. | |
499 | </entry> | |
500 | <entry>This returns an iterator pointing to the beginning of | |
501 | <literal>a</literal>.</entry> | |
502 | </row> | |
503 | ||
504 | <row> | |
505 | <entry><literal>a.end()</literal></entry> | |
506 | <entry> | |
507 | <literal>iterator</literal> if <literal>a</literal> is mutable, | |
508 | <literal>const_iterator</literal> otherwise. | |
509 | </entry> | |
510 | <entry>This returns an iterator pointing to the end of | |
511 | <literal>a</literal>.</entry> | |
512 | </row> | |
513 | ||
514 | <row> | |
515 | <entry><literal>a.rbegin()</literal></entry> | |
516 | <entry> | |
517 | <literal>reverse_iterator</literal> if <literal>a</literal> is mutable, | |
518 | <literal>const_reverse_iterator</literal> otherwise. | |
519 | </entry> | |
520 | <entry>This returns a reverse iterator pointing to the | |
521 | beginning of <literal>a</literal> reversed. | |
522 | </entry> | |
523 | </row> | |
524 | ||
525 | <row> | |
526 | <entry><literal>a.rend()</literal></entry> | |
527 | <entry> | |
528 | <literal>reverse_iterator</literal> if <literal>a</literal> is mutable, | |
529 | <literal>const_reverse_iterator</literal> otherwise. | |
530 | </entry> | |
531 | <entry> | |
532 | This returns a reverse iterator pointing to the end of <literal>a</literal> | |
533 | reversed. | |
534 | </entry> | |
535 | </row> | |
536 | <row> | |
537 | <entry><literal>a[idx]</literal></entry> | |
538 | <entry> | |
539 | <literal>reference</literal> if <literal>a</literal> is mutable, | |
540 | <literal>const_reference</literal> otherwise. | |
541 | </entry> | |
542 | <entry> | |
543 | This returns a reference type that is bound to the index | |
544 | <literal>idx</literal> value of <literal>a</literal>. Note that if | |
545 | <literal>i</literal> is the index base for this dimension, the above | |
546 | expression returns the <literal>(idx-i)</literal>th element (counting | |
547 | from zero). The expression is equivalent to | |
548 | <literal>*(a.begin()+idx-a.index_bases()[0]);</literal>. | |
549 | </entry> | |
550 | </row> | |
551 | ||
552 | <row> | |
553 | <entry><literal>a[indices]</literal></entry> | |
554 | <entry> | |
555 | <literal>array_view<Dims>::type</literal> if | |
556 | <literal>a</literal> is mutable, | |
557 | <literal>const_array_view<Dims>::type</literal> otherwise. | |
558 | </entry> | |
559 | <entry> | |
560 | This expression generates a view of the array determined by the | |
561 | <literal>index_range</literal> and <literal>index</literal> values | |
562 | used to construct <literal>indices</literal>. | |
563 | </entry> | |
564 | </row> | |
565 | <row> | |
566 | <entry><literal>a == b</literal></entry> | |
567 | <entry>bool</entry> | |
568 | <entry>This performs a lexicographical comparison of the | |
569 | values of <literal>a</literal> and <literal>b</literal>. The element | |
570 | type must model <ulink url="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</ulink> for this | |
571 | expression to be valid.</entry> | |
572 | </row> | |
573 | <row> | |
574 | <entry><literal>a < b</literal></entry> | |
575 | <entry>bool</entry> | |
576 | <entry>This performs a lexicographical comparison of the | |
577 | values of <literal>a</literal> and <literal>b</literal>. The element | |
578 | type must model <ulink url="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</ulink> for this | |
579 | expression to be valid.</entry> | |
580 | </row> | |
581 | <row> | |
582 | <entry><literal>a <= b</literal></entry> | |
583 | <entry>bool</entry> | |
584 | <entry>This performs a lexicographical comparison of the | |
585 | values of <literal>a</literal> and <literal>b</literal>. The element | |
586 | type must model <ulink url="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</ulink> and | |
587 | <ulink url="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</ulink> for this | |
588 | expression to be valid.</entry> | |
589 | </row> | |
590 | <row> | |
591 | <entry><literal>a > b</literal></entry> | |
592 | <entry>bool</entry> | |
593 | <entry>This performs a lexicographical comparison of the | |
594 | values of <literal>a</literal> and <literal>b</literal>. The element | |
595 | type must model <ulink url="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</ulink> and | |
596 | <ulink url="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</ulink> for this | |
597 | expression to be valid.</entry> | |
598 | </row> | |
599 | <row> | |
600 | <entry><literal>a >= b</literal></entry> | |
601 | <entry>bool</entry> | |
602 | <entry>This performs a lexicographical comparison of the | |
603 | values of <literal>a</literal> and <literal>b</literal>. The element | |
604 | type must model <ulink url="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</ulink> for this | |
605 | expression to be valid.</entry> | |
606 | </row> | |
607 | </tbody> | |
608 | </tgroup> | |
609 | </table> | |
610 | </sect2> | |
611 | ||
612 | ||
613 | <sect2><title>Complexity guarantees</title> | |
614 | ||
615 | <literal>begin()</literal> and <literal>end()</literal> execute in amortized | |
616 | constant time. | |
617 | <literal>size()</literal> executes in at most linear time in the | |
618 | MultiArray's size. | |
619 | </sect2> | |
620 | ||
621 | <sect2> | |
622 | <title>Invariants</title> | |
623 | <table><title>Invariants</title> | |
624 | <tgroup cols="2"> | |
625 | <tbody> | |
626 | <row> | |
627 | <entry>Valid range</entry> | |
628 | <entry><literal>[a.begin(),a.end())</literal> is a valid range. | |
629 | </entry> | |
630 | </row> | |
631 | ||
632 | <row> | |
633 | <entry>Range size</entry> | |
634 | <entry> | |
635 | <literal>a.size() == std::distance(a.begin(),a.end());</literal>. | |
636 | </entry> | |
637 | </row> | |
638 | ||
639 | <row> | |
640 | <entry>Completeness</entry> | |
641 | <entry> | |
642 | Iteration through the range | |
643 | <literal>[a.begin(),a.end())</literal> will traverse across every | |
644 | <literal>value_type</literal> of <literal>a</literal>. | |
645 | </entry> | |
646 | </row> | |
647 | <row> | |
648 | <entry>Accessor Equivalence</entry> | |
649 | <entry> | |
650 | Calling <literal>a[a1][a2]...[aN]</literal> where <literal>N==NumDims</literal> | |
651 | yields the same result as calling | |
652 | <literal>a(index_list)</literal>, where <literal>index_list</literal> | |
653 | is a <ulink url="../../utility/Collection.html">Collection</ulink> containing the values <literal>a1...aN</literal>. | |
654 | </entry> | |
655 | </row> | |
656 | </tbody> | |
657 | </tgroup> | |
658 | </table> | |
659 | </sect2> | |
660 | ||
661 | <sect2 id="view_types"> | |
662 | <title>Associated Types for Views</title> | |
663 | <para>The following MultiArray associated | |
664 | types define the interface for creating views of existing | |
665 | MultiArrays. Their interfaces and roles in the | |
666 | concept are described below.</para> | |
667 | ||
668 | <sect3 id="index_range"> | |
669 | <title><literal>index_range</literal></title> | |
670 | ||
671 | <para><literal>index_range</literal> objects represent half-open | |
672 | strided intervals. They are aggregated (using an | |
673 | <literal>index_gen</literal> object) and passed to | |
674 | a MultiArray's <literal>operator[]</literal> | |
675 | to create an array view. When creating a view, | |
676 | each <literal>index_range</literal> denotes a range of | |
677 | valid indices along one dimension of a MultiArray. | |
678 | Elements that are accessed through the set of ranges specified will be | |
679 | included in the constructed view. In some cases, an | |
680 | <literal>index_range</literal> is created without specifying start | |
681 | or finish values. In those cases, the object is interpreted to | |
682 | start at the beginning of a MultiArray dimension | |
683 | and end at its end.</para> | |
684 | ||
685 | <para> | |
686 | <literal>index_range</literal> objects can be constructed and modified | |
687 | several ways in order to allow convenient and clear expression of a | |
688 | range of indices. To specify ranges, <literal>index_range</literal> | |
689 | supports a set of constructors, mutating member functions, and a novel | |
690 | specification involving inequality operators. Using inequality | |
691 | operators, a half open range [5,10) can be specified as follows: | |
692 | <programlisting>5 <= index_range() < 10;</programlisting> or | |
693 | <programlisting>4 < index_range() <= 9;</programlisting> and so on. | |
694 | ||
695 | The following describes the | |
696 | <literal>index_range</literal> interface. | |
697 | </para> | |
698 | ||
699 | <table> | |
700 | <title>Notation</title> | |
701 | <tgroup cols="2"> | |
702 | <tbody> | |
703 | <row> | |
704 | <entry><literal>i</literal></entry> | |
705 | <entry>An object of type <literal>index_range</literal>.</entry> | |
706 | </row> | |
707 | <row> | |
708 | <entry><literal>idx,idx1,idx2,idx3</literal></entry> | |
709 | <entry>Objects of type <literal>index</literal>.</entry> | |
710 | </row> | |
711 | </tbody> | |
712 | </tgroup> | |
713 | </table> | |
714 | ||
715 | <table><title>Associated Types</title> | |
716 | <tgroup cols="2"> | |
717 | <thead> | |
718 | <row> | |
719 | <entry>Type</entry> | |
720 | <entry>Description</entry> | |
721 | </row> | |
722 | </thead> | |
723 | <tbody> | |
724 | <row> | |
725 | <entry><literal>index</literal></entry> | |
726 | <entry>This is a signed integral type. It is used to | |
727 | specify the start, finish, and stride values.</entry> | |
728 | </row> | |
729 | <row> | |
730 | <entry><literal>size_type</literal></entry> | |
731 | <entry>This is an unsigned integral type. It is used to | |
732 | report the size of the range an <literal>index_range</literal> | |
733 | represents.</entry> | |
734 | </row> | |
735 | </tbody> | |
736 | </tgroup> | |
737 | </table> | |
738 | ||
739 | ||
740 | <table><title>Valid Expressions</title> | |
741 | <tgroup cols="3"> | |
742 | <thead> | |
743 | <row> | |
744 | <entry>Expression</entry> | |
745 | <entry>Return type</entry> | |
746 | <entry>Semantics</entry> | |
747 | </row> | |
748 | </thead> | |
749 | <tbody> | |
750 | <row> | |
751 | <entry><literal>index_range(idx1,idx2,idx3)</literal></entry> | |
752 | <entry><literal>index_range</literal></entry> | |
753 | <entry>This constructs an <literal>index_range</literal> | |
754 | representing the interval <literal>[idx1,idx2)</literal> | |
755 | with stride <literal>idx3</literal>.</entry> | |
756 | </row> | |
757 | <row> | |
758 | <entry><literal>index_range(idx1,idx2)</literal></entry> | |
759 | <entry><literal>index_range</literal></entry> | |
760 | <entry>This constructs an <literal>index_range</literal> | |
761 | representing the interval <literal>[idx1,idx2)</literal> | |
762 | with unit stride. It is equivalent to | |
763 | <literal>index_range(idx1,idx2,1)</literal>.</entry> | |
764 | </row> | |
765 | <row> | |
766 | <entry><literal>index_range()</literal></entry> | |
767 | <entry><literal>index_range</literal></entry> | |
768 | <entry>This construct an <literal>index_range</literal> | |
769 | with unspecified start and finish values.</entry> | |
770 | </row> | |
771 | <row> | |
772 | <entry><literal>i.start(idx1)</literal></entry> | |
773 | <entry><literal>index&</literal></entry> | |
774 | <entry>This sets the start index of <literal>i</literal> to | |
775 | <literal>idx</literal>.</entry> | |
776 | </row> | |
777 | <row> | |
778 | <entry><literal>i.finish(idx)</literal></entry> | |
779 | <entry><literal>index&</literal></entry> | |
780 | <entry>This sets the finish index of <literal>i</literal> to | |
781 | <literal>idx</literal>.</entry> | |
782 | </row> | |
783 | <row> | |
784 | <entry><literal>i.stride(idx)</literal></entry> | |
785 | <entry><literal>index&</literal></entry> | |
786 | <entry>This sets the stride length of <literal>i</literal> to | |
787 | <literal>idx</literal>.</entry> | |
788 | </row> | |
789 | <row> | |
790 | <entry><literal>i.start()</literal></entry> | |
791 | <entry><literal>index</literal></entry> | |
792 | <entry>This returns the start index of <literal>i</literal>.</entry> | |
793 | </row> | |
794 | <row> | |
795 | <entry><literal>i.finish()</literal></entry> | |
796 | <entry><literal>index</literal></entry> | |
797 | <entry>This returns the finish index of <literal>i</literal>.</entry> | |
798 | </row> | |
799 | <row> | |
800 | <entry><literal>i.stride()</literal></entry> | |
801 | <entry><literal>index</literal></entry> | |
802 | <entry>This returns the stride length of <literal>i</literal>.</entry> | |
803 | </row> | |
804 | <row> | |
805 | <entry><literal>i.get_start(idx)</literal></entry> | |
806 | <entry><literal>index</literal></entry> | |
807 | <entry>If <literal>i</literal> specifies a start | |
808 | value, this is equivalent to <literal>i.start()</literal>. Otherwise it | |
809 | returns <literal>idx</literal>.</entry> | |
810 | </row> | |
811 | <row> | |
812 | <entry><literal>i.get_finish(idx)</literal></entry> | |
813 | <entry><literal>index</literal></entry> | |
814 | <entry>If <literal>i</literal> specifies a finish | |
815 | value, this is equivalent to <literal>i.finish()</literal>. Otherwise it | |
816 | returns <literal>idx</literal>.</entry> | |
817 | </row> | |
818 | <row> | |
819 | <entry><literal>i.size(idx)</literal></entry> | |
820 | <entry><literal>size_type</literal></entry> | |
821 | <entry>If <literal>i</literal> specifies a both finish and | |
822 | start values, this is equivalent to | |
823 | <literal>(i.finish()-i.start())/i.stride()</literal>. Otherwise it | |
824 | returns <literal>idx</literal>.</entry> | |
825 | </row> | |
826 | <row> | |
827 | <entry><literal>i < idx</literal></entry> | |
828 | <entry><literal>index</literal></entry> | |
829 | <entry>This is another syntax for specifying the finish | |
830 | value. This notation does not include | |
831 | <literal>idx</literal> in the range of valid indices. It is equivalent to | |
832 | <literal>index_range(r.start(), idx, r.stride())</literal></entry> | |
833 | </row> | |
834 | <row> | |
835 | <entry><literal>i <= idx</literal></entry> | |
836 | <entry><literal>index</literal></entry> | |
837 | <entry>This is another syntax for specifying the finish | |
838 | value. This notation includes | |
839 | <literal>idx</literal> in the range of valid indices. It is equivalent to | |
840 | <literal>index_range(r.start(), idx + 1, r.stride())</literal></entry> | |
841 | </row> | |
842 | <row> | |
843 | <entry><literal>idx < i</literal></entry> | |
844 | <entry><literal>index</literal></entry> | |
845 | <entry>This is another syntax for specifying the start | |
846 | value. This notation does not include | |
847 | <literal>idx</literal> in the range of valid indices. It is equivalent to | |
848 | <literal>index_range(idx + 1, i.finish(), i.stride())</literal>.</entry> | |
849 | </row> | |
850 | <row> | |
851 | <entry><literal>idx <= i</literal></entry> | |
852 | <entry><literal>index</literal></entry> | |
853 | <entry>This is another syntax for specifying the start | |
854 | value. This notation includes | |
855 | <literal>idx1</literal> in the range of valid indices. It is equivalent to | |
856 | <literal>index_range(idx, i.finish(), i.stride())</literal>.</entry> | |
857 | </row> | |
858 | <row> | |
859 | <entry><literal>i + idx</literal></entry> | |
860 | <entry><literal>index</literal></entry> | |
861 | <entry>This expression shifts the start and finish values | |
862 | of <literal>i</literal> up by <literal>idx</literal>. It is equivalent to | |
863 | <literal>index_range(r.start()+idx1, r.finish()+idx, r.stride())</literal></entry> | |
864 | </row> | |
865 | <row> | |
866 | <entry><literal>i - idx</literal></entry> | |
867 | <entry><literal>index</literal></entry> | |
868 | <entry>This expression shifts the start and finish values | |
869 | of <literal>i</literal> up by <literal>idx</literal>. It is equivalent to | |
870 | <literal>index_range(r.start()-idx1, r.finish()-idx, r.stride())</literal></entry> | |
871 | </row> | |
872 | </tbody> | |
873 | </tgroup> | |
874 | </table> | |
875 | </sect3> | |
876 | ||
877 | <sect3 id="index_gen"> | |
878 | <title><literal>index_gen</literal></title> | |
879 | <para> <literal>index_gen</literal> aggregates | |
880 | <literal>index_range</literal> objects in order to specify view | |
881 | parameters. Chained calls to <literal>operator[]</literal> store | |
882 | range and dimension information used to | |
883 | instantiate a new view into a MultiArray. | |
884 | </para> | |
885 | <table> | |
886 | <title>Notation</title> | |
887 | <tgroup cols="2"> | |
888 | <tbody> | |
889 | <row> | |
890 | <entry><literal>Dims,Ranges</literal></entry> | |
891 | <entry>Unsigned integral values.</entry> | |
892 | </row> | |
893 | <row> | |
894 | <entry><literal>x</literal></entry> | |
895 | <entry>An object of type | |
896 | <literal>template gen_type<Dims,Ranges>::type</literal>.</entry> | |
897 | </row> | |
898 | <row> | |
899 | <entry><literal>i</literal></entry> | |
900 | <entry>An object of type | |
901 | <literal>index_range</literal>.</entry> | |
902 | </row> | |
903 | <row> | |
904 | <entry><literal>idx</literal></entry> | |
905 | <entry>Objects of type <literal>index</literal>.</entry> | |
906 | </row> | |
907 | </tbody> | |
908 | </tgroup> | |
909 | </table> | |
910 | ||
911 | <table><title>Associated Types</title> | |
912 | <tgroup cols="2"> | |
913 | <thead> | |
914 | <row> | |
915 | <entry>Type</entry> | |
916 | <entry>Description</entry> | |
917 | </row> | |
918 | </thead> | |
919 | <tbody> | |
920 | <row> | |
921 | <entry><literal>index</literal></entry> | |
922 | <entry>This is a signed integral type. It is used to | |
923 | specify degenerate dimensions.</entry> | |
924 | </row> | |
925 | <row> | |
926 | <entry><literal>size_type</literal></entry> | |
927 | <entry>This is an unsigned integral type. It is used to | |
928 | report the size of the range an <literal>index_range</literal> | |
929 | represents.</entry> | |
930 | </row> | |
931 | <row> | |
932 | <entry> | |
933 | <literal>template gen_type::<Dims,Ranges>::type</literal></entry> | |
934 | <entry>This type generator names the result of | |
935 | <literal>Dims</literal> chained calls to | |
936 | <literal>index_gen::operator[]</literal>. The | |
937 | <literal>Ranges</literal> parameter is determined by the number of | |
938 | degenerate ranges specified (i.e. calls to | |
939 | <literal>operator[](index)</literal>). Note that | |
940 | <classname>index_gen</classname> and | |
941 | <classname>gen_type<0,0>::type</classname> are the same type.</entry> | |
942 | </row> | |
943 | </tbody> | |
944 | </tgroup> | |
945 | </table> | |
946 | ||
947 | ||
948 | ||
949 | ||
950 | <table><title>Valid Expressions</title> | |
951 | <tgroup cols="3"> | |
952 | <thead> | |
953 | <row> | |
954 | <entry>Expression</entry> | |
955 | <entry>Return type</entry> | |
956 | <entry>Semantics</entry> | |
957 | </row> | |
958 | </thead> | |
959 | <tbody> | |
960 | <row> | |
961 | <entry><literal>index_gen()</literal></entry> | |
962 | <entry><literal>gen_type<0,0>::type</literal></entry> | |
963 | <entry>This constructs an <literal>index_gen</literal> | |
964 | object. This object can then be used to generate tuples of | |
965 | <literal>index_range</literal> values.</entry> | |
966 | </row> | |
967 | ||
968 | <row> | |
969 | <entry><literal>x[i]</literal></entry> | |
970 | <entry><literal>gen_type<Dims+1,Ranges+1>::type</literal> | |
971 | </entry> | |
972 | <entry>Returns a new object containing all previous | |
973 | <classname>index_range</classname> objects in addition to | |
974 | <literal>i.</literal> Chained calls to | |
975 | <function>operator[]</function> are the means by which | |
976 | <classname>index_range</classname> objects are aggregated.</entry> | |
977 | </row> | |
978 | <row> | |
979 | <entry><literal>x[idx]</literal></entry> | |
980 | <entry><literal>gen_type<Dims,Ranges+1>::type</literal> | |
981 | </entry> | |
982 | <entry>Returns a new object containing all previous | |
983 | <classname>index_range</classname> objects in addition to a degenerate | |
984 | range, <literal>index_range(idx,idx).</literal> Note that this is NOT | |
985 | equivalent to <literal>x[index_range(idx,idx)].</literal>, which will | |
986 | return an object of type | |
987 | <literal>gen_type<Dims+1,Ranges+1>::type</literal>. | |
988 | </entry> | |
989 | </row> | |
990 | </tbody> | |
991 | </tgroup> | |
992 | </table> | |
993 | </sect3> | |
994 | ||
995 | </sect2> | |
996 | ||
997 | <sect2> | |
998 | <title>Models</title> | |
999 | ||
1000 | <itemizedlist> | |
1001 | <listitem> <literal>multi_array</literal> </listitem> | |
1002 | <listitem> <literal>multi_array_ref</literal> </listitem> | |
1003 | <listitem> <literal>const_multi_array_ref</literal> </listitem> | |
1004 | <listitem> | |
1005 | <literal>template array_view<Dims>::type</literal> | |
1006 | </listitem> | |
1007 | <listitem> | |
1008 | <literal>template const_array_view<Dims>::type</literal> | |
1009 | </listitem> | |
1010 | <listitem> | |
1011 | <literal>template subarray<Dims>::type</literal> | |
1012 | </listitem> | |
1013 | <listitem> | |
1014 | <literal>template const_subarray<Dims>::type</literal> | |
1015 | </listitem> | |
1016 | </itemizedlist> | |
1017 | </sect2> | |
1018 | ||
1019 | </sect1> |