]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/multi_array/doc/user.html
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / multi_array / doc / user.html
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&lt;std::vector&lt;...&gt;&gt;</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&lt;std::vector&lt;double&gt;&gt;</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 &lt;cassert&gt;
129
130 int
131 main () {
132 // Create a 3D array that is 3 x 4 x 2
133 typedef boost::multi_array&lt;double, 3&gt; 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 &lt;typename Array&gt;
225 void my_function() {
226 typedef typename Array::template array_view&lt;3&gt;::type view1_t;
227 typedef typename boost::array_view_gen&lt;Array,3&gt;::type view2_t;
228 // ...
229 }
230 </pre>
231 </blockquote>
232
233 <a name="sec_dimensions"></a>
234 <h2>Specifying Array Dimensions</h2>
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&lt;double, 3&gt; array_type;
252 boost::array&lt;array_type::index, 3&gt; 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&lt;double, 3&gt; 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&lt;double, 3&gt; 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&lt;double, 3&gt; array_type;
297 array_type A(boost::extents[3][4][2]);
298 boost::array&lt;array_type::index,3&gt; 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&lt;3&gt;::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&lt;2&gt;::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 &lt;= range().stride(2) &lt; 4;
398 a_range = 0 &lt;= range().stride(2) &lt;= 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 &lt;= i
419 a_range = range().start(3)
420 a_range = 3 &lt;= range();
421 a_range = 2 &lt; range();
422
423 // indices i where i &lt; 7
424 a_range = range().finish(7)
425 a_range = range() &lt; 7;
426 a_range = range() &lt;= 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 &lt; 5 for dimension 2
436 // take 4 &lt;= j &lt;= 7 for dimension 3 with stride 2
437 myarray[ boost::indices[range()][range() &lt; 5 ][4 &lt;= range().stride(2) &lt;= 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&lt;double,3&gt; 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&lt;3&gt; storage;
474 typedef boost::multi_array&lt;int,3&gt; 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&lt;double, 3&gt; 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&lt;double, 3&gt; 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&lt;double, 3&gt; 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&lt;array_type::index,ndims&gt; 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&lt;double, 3&gt; array_type;
559
560 array_type::extent_gen extents;
561 array_type A(extents[2][3][4]);
562 boost::array&lt;array_type::index,ndims&gt; 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&lt;int, 3&gt; 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>