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