1<sect1 id="MultiArray"><title>MultiArray Concept</title> 2 3 4<para>The MultiArray 5concept defines an interface to hierarchically nested 6containers. It specifies operations for accessing elements, 7traversing containers, and creating views 8of array data. 9MultiArray defines 10a flexible memory model that accomodates 11a variety of data layouts. 12</para> 13 14<para> 15At each level (or dimension) of a MultiArray's 16container hierarchy lie a set of ordered containers, each of which 17contains the same number and type of values. The depth of this 18container hierarchy is the MultiArray's <emphasis>dimensionality</emphasis>. 19MultiArray is recursively defined; the 20containers at each level of the container hierarchy model 21MultiArray as well. While each dimension of a MultiArray 22has its own size, the list of sizes for all dimensions 23defines the <emphasis>shape</emphasis> of the entire MultiArray. 24At the base of this hierarchy lie 1-dimensional 25MultiArrays. Their values are the contained 26objects of interest and not part of the container hierarchy. These are 27the MultiArray's elements. 28</para> 29 30 31<para> 32Like other container concepts, MultiArray exports 33iterators to traverse its values. In addition, values can be 34addressed directly using the familiar bracket notation. 35</para> 36 37<para> 38MultiArray also specifies 39routines for creating 40specialized views. A <emphasis>view</emphasis> lets you treat a 41subset of the underlying 42elements in a MultiArray as though it were a separate 43MultiArray. Since a view refers to the same underlying elements, 44changes made to a view's elements will be reflected in the original 45MultiArray. For 46example, given a 3-dimensional "cube" of elements, a 2-dimensional 47slice can be viewed as if it were an independent 48MultiArray. 49 50Views 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 53dimension that are to be included in a 54view. <literal>index_gen</literal> aggregates range data and performs 55bookkeeping to determine the view type to be returned. 56 57MultiArray's <literal>operator[]</literal> 58 must be passed the result 59of <literal>N</literal> chained calls to 60<literal>index_gen::operator[]</literal>, i.e. 61 62<programlisting>indices[a0][a1]...[aN]; 63</programlisting> 64 65where <literal>N</literal> is the 66MultiArray's dimensionality and 67<literal>indices</literal> an object of type <literal>index_gen</literal>. 68 69The view type is dependent upon the number of degenerate dimensions 70specified to <literal>index_gen</literal>. A degenerate dimension 71occurs 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 79has a degenerate second dimension. The view generated from the above 80specification will have 2 dimensions with shape <literal>5 x 4</literal>. 81If the "<literal>2</literal>" above were replaced with 82another <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 87then the view would have 3 dimensions.</para> 88 89<para> 90MultiArray exports 91information regarding the memory 92layout of its contained elements. Its memory model for elements is 93completely defined by 4 properties: the origin, shape, index bases, 94and strides. The origin is the address in memory of the element 95accessed as <literal>a[0][0]...[0]</literal>, where 96<literal>a</literal> is a MultiArray. The shape is a list of numbers 97specifying the size of containers at each dimension. For example, the 98first extent is the size of the outermost container, the second extent 99is the size of its subcontainers, and so on. The index bases are a 100list of signed values specifying the index of the first value in a 101container. All containers at the same dimension share the same index 102base. Note that since positive index bases are 103possible, the origin need not exist in order to determine the location 104in memory of the MultiArray's elements. 105 The strides determine how index values are mapped to memory offsets. 106They accomodate a 107number of possible element layouts. For example, the elements of a 2 108dimensional array can be stored by row (i.e., the elements of each row 109are stored contiguously) or by column (i.e., the elements of each 110column are stored contiguously). 111</para> 112 113<para> 114Two 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 124to 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 152to <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 195immediately nested containers. 196</entry> 197</row> 198 199<row> 200<entry> 201<literal>reference</literal> 202</entry> 203 204<entry> 205This is the reference type of the contained value. 206If <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> 217This is the const reference type of the contained value. 218If <literal>NumDims == 1</literal>, then this is 219<literal>const element&</literal>. Otherwise, this is the same 220type 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> 230This 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> 240This is a signed integral type used to represent the distance between two 241iterators. 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> 249This is an iterator over the values of <literal>A</literal>. 250If <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>. 253Otherwise it models 254<ulink url="./iterator_categories.html#concept_RandomAccessTraversalIterator"> 255Random Access Traversal Iterator</ulink>, 256<ulink url="./iterator_categories.html#concept_ReadableIterator"> 257Readable Iterator</ulink>, 258<ulink url="./iterator_categories.html#concept_WritableIterator"> 259Writable 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> 270This 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> 279This 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> 289This 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> 299This is the type of objects stored at the base of the 300hierarchy 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> 310This is a signed integral type used for indexing into <literal>A</literal>. It 311is 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> 320This type is used to create a tuple of <literal>index_range</literal>s 321passed to <literal>operator[]</literal> to create 322an <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> 331This type specifies a range of indices over some dimension of a 332MultiArray. 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> 342This is subarray type with <literal>Dims</literal> dimensions. 343It is the reference type of the <literal>(NumDims - Dims)</literal> 344dimension of <literal>A</literal> and also models 345MultiArray. 346</entry> 347</row> 348 349<row> 350<entry> 351<literal>template const_subarray<Dims>::type</literal> 352</entry> 353<entry> 354This 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> 363This is the view type with <literal>Dims</literal> dimensions. It is 364returned by calling <literal>operator[](<literal>indices</literal>)</literal>. 365It models MultiArray. 366</entry> 367</row> 368 369<row> 370<entry> 371<literal>template 372const_array_view<Dims>::type</literal> 373</entry> 374<entry> 375This 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 402dimensions 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> 409This returns a list of <literal>NumDims</literal> elements specifying the 410extent 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> 418This returns a list of <literal>NumDims</literal> elements specifying the 419stride associated with each array dimension. When accessing values, 420strides 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> 428This returns a list of <literal>NumDims</literal> elements specifying the 429numeric 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> 439This returns the address of the element accessed by the expression 440<literal>a[0][0]...[0].</literal>. If the index bases are positive, 441this element won't exist, but the address can still be used to locate 442a 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 456in the array. It is equivalent to the following code: 457<programlisting> 458std::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> 468This 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> 479This expression accesses a specific element of 480<literal>a</literal>.<literal>index_list</literal> is the unique set 481of indices that address the element returned. It is 482equivalent 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 521beginning 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> 532This returns a reverse iterator pointing to the end of <literal>a</literal> 533reversed. 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> 543This 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 546expression returns the <literal>(idx-i)</literal>th element (counting 547from 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> 560This 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 569values of <literal>a</literal> and <literal>b</literal>. The element 570type must model <ulink url="https://www.boost.org/sgi/stl/EqualityComparable.html">EqualityComparable</ulink> for this 571expression 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 577values of <literal>a</literal> and <literal>b</literal>. The element 578type must model <ulink url="https://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</ulink> for this 579expression 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 585values of <literal>a</literal> and <literal>b</literal>. The element 586type must model <ulink url="https://www.boost.org/sgi/stl/EqualityComparable.html">EqualityComparable</ulink> and 587<ulink url="https://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</ulink> for this 588expression 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 594values of <literal>a</literal> and <literal>b</literal>. The element 595type must model <ulink url="https://www.boost.org/sgi/stl/EqualityComparable.html">EqualityComparable</ulink> and 596<ulink url="https://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</ulink> for this 597expression 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 603values of <literal>a</literal> and <literal>b</literal>. The element 604type must model <ulink url="https://www.boost.org/sgi/stl/LessThanComparable.html">LessThanComparable</ulink> for this 605expression 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 616constant time. 617<literal>size()</literal> executes in at most linear time in the 618MultiArray'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> 642Iteration 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> 650Calling <literal>a[a1][a2]...[aN]</literal> where <literal>N==NumDims</literal> 651yields the same result as calling 652<literal>a(index_list)</literal>, where <literal>index_list</literal> 653is 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 664types define the interface for creating views of existing 665MultiArrays. Their interfaces and roles in the 666concept 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 672strided intervals. They are aggregated (using an 673<literal>index_gen</literal> object) and passed to 674a MultiArray's <literal>operator[]</literal> 675to create an array view. When creating a view, 676each <literal>index_range</literal> denotes a range of 677valid indices along one dimension of a MultiArray. 678Elements that are accessed through the set of ranges specified will be 679included in the constructed view. In some cases, an 680<literal>index_range</literal> is created without specifying start 681or finish values. In those cases, the object is interpreted to 682start at the beginning of a MultiArray dimension 683and end at its end.</para> 684 685<para> 686<literal>index_range</literal> objects can be constructed and modified 687several ways in order to allow convenient and clear expression of a 688range of indices. To specify ranges, <literal>index_range</literal> 689supports a set of constructors, mutating member functions, and a novel 690specification involving inequality operators. Using inequality 691operators, 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 695The 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 727specify 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 732report the size of the range an <literal>index_range</literal> 733represents.</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> 769with 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 808value, this is equivalent to <literal>i.start()</literal>. Otherwise it 809returns <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 815value, this is equivalent to <literal>i.finish()</literal>. Otherwise it 816returns <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 822start values, this is equivalent to 823<literal>(i.finish()-i.start())/i.stride()</literal>. Otherwise it 824returns <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 830value. 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 838value. 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 846value. 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 854value. 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 862of <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 869of <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 881parameters. Chained calls to <literal>operator[]</literal> store 882range and dimension information used to 883instantiate 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 923specify 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 928report the size of the range an <literal>index_range</literal> 929represents.</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 938degenerate 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> 964object. 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 984range, <literal>index_range(idx,idx).</literal> Note that this is NOT 985equivalent to <literal>x[index_range(idx,idx)].</literal>, which will 986return 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> 1020