Copyright © 2002 The Trustees of Indiana University
Table of Contents
Kertxin Wireless Charger Stand,4 in 1 Wireless Charging Station Dock with USB for Apple Watch iWatch 5 4 3 2 1, Airpods,iPhone 11 11 Pro X Xs XR Max 8 Plus 8,Samsung Galaxy S9 S8 4.2 out of 5 stars 326.
- Universal 360 Rotating Flexible Long Arm lazy Phone Holder Clamp Lazy Bed Tablet Car Selfie Mount Bracket for iPhone x 7 Xiaomi. For iPhone 4S / 5 / 5G / 5C / 5S / 6 6S Plus / 7 7S Plus holder. 1 x Flexible Cellphone Stand Holder.
- Multi-docks PORTA-DOCK’S LATEST INNOVATION. A true innovation, Porta-Dock’s Multi-Dock combines the strength and stability of Porta-Dock’s Roll-In dock with the ability to use posts or our revolutionary new leveling system. Enjoy superior stability without sacrificing ease of installation and removal.
- Multi Dock – Sectional Dock. Category: Dock Brand: Porta-Dock Item Condition: New. The latest innovation from Porta-Dock combines strength and stability with a.
- Search all available properties including Single Family, Condos, Multi-Family, Commercial, Land, Rentals, Apartment, Income, Auction, Villa, Townhouse, Boat Dock via the MLS in Palmetto, FL - brought to you by La Rosa Realty, Orlando.
- Library Synopsis
- MultiArray Concept
- Notation
- Associated Types
- Valid expressions
- Complexity guarantees
- Invariants
- Associated Types for Views
- Models
- Array Components
multi_array
multi_array_ref
const_multi_array_ref
- Auxiliary Components
multi_array_types
extent_range
extent_gen
- Global Objects
- View and SubArray Generators
- Memory Layout Specifiers
- Range Checking
Boost.MultiArray is composed of several components.The MultiArray concept defines a generic interface to multidimensionalcontainers.
multi_array
is a general purpose container classthat models MultiArray. multi_array_ref
and const_multi_array_ref
are adapterclasses. Using them, you can manipulate any block of contiguous data as though it were amulti_array
.const_multi_array_ref
differs frommulti_array_ref
in that its elements cannotbe modified through its interface. Finally, several auxiliary classes are usedto create and specialize arrays and some global objects are defined aspart of the library interface.To use Boost.MultiArray, you must include the header
boost/multi_array.hpp
in your source. This filebrings the following declarations into scope:The MultiArrayconcept defines an interface to hierarchically nestedcontainers. It specifies operations for accessing elements,traversing containers, and creating viewsof array data.MultiArray definesa flexible memory model that accomodatesa variety of data layouts.
At each level (or dimension) of a MultiArray'scontainer hierarchy lie a set of ordered containers, each of whichcontains the same number and type of values. The depth of thiscontainer hierarchy is the MultiArray's dimensionality. MultiArray is recursively defined; thecontainers at each level of the container hierarchy modelMultiArray as well. While each dimension of a MultiArrayhas its own size, the list of sizes for all dimensions defines the shape of the entire MultiArray.At the base of this hierarchy lie 1-dimensionalMultiArrays. Their values are the containedobjects of interest and not part of the container hierarchy. These arethe MultiArray's elements.
Like other container concepts, MultiArray exportsiterators to traverse its values. In addition, values can beaddressed directly using the familiar bracket notation.
MultiArray also specifiesroutines for creatingspecialized views. A view lets you treat a subset of the underlyingelements in a MultiArray as though it were a separateMultiArray. Since a view refers to the same underlying elements,changes made to a view's elements will be reflected in the originalMultiArray. Forexample, given a 3-dimensional 'cube' of elements, a 2-dimensionalslice can be viewed as if it were an independentMultiArray.Views are created using
index_gen
andindex_range
objects.index_range
s denote elements from a certaindimension that are to be included in aview. index_gen
aggregates range data and performsbookkeeping to determine the view type to be returned.MultiArray's operator[]
must be passed the resultof N
chained calls to index_gen::operator[]
, i.e.where
N
is the MultiArray's dimensionality andindices
an object of type index_gen
.The view type is dependent upon the number of degenerate dimensionsspecified to index_gen
. A degenerate dimensionoccurs when a single-index is specified toindex_gen
for a certain dimension. For example, ifindices
is an object of typeindex_gen
, then the following example:has a degenerate second dimension. The view generated from the abovespecification will have 2 dimensions with shape
5 x 4
.If the '2
' above were replaced withanother index_range
object, for example:then the view would have 3 dimensions.
MultiArray exportsinformation regarding the memorylayout of its contained elements. Its memory model for elements iscompletely defined by 4 properties: the origin, shape, index bases,and strides. The origin is the address in memory of the elementaccessed as
a[0][0]..[0]
, wherea
is a MultiArray. The shape is a list of numbersspecifying the size of containers at each dimension. For example, thefirst extent is the size of the outermost container, the second extentis the size of its subcontainers, and so on. The index bases are alist of signed values specifying the index of the first value in acontainer. All containers at the same dimension share the same indexbase. Note that since positive index bases arepossible, the origin need not exist in order to determine the locationin memory of the MultiArray's elements. The strides determine how index values are mapped to memory offsets. They accomodate anumber of possible element layouts. For example, the elements of a 2dimensional array can be stored by row (i.e., the elements of each roware stored contiguously) or by column (i.e., the elements of eachcolumn are stored contiguously).Two concept checking classes for the MultiArray concepts(
ConstMultiArrayConcept
andMutableMultiArrayConcept
) are in the namespaceboost::multi_array_concepts
in<boost/multi_array/concept_checks.hpp>
.What follows are the descriptions of symbols that will be usedto describe the MultiArray interface.
Table 1. Notation
A | A type that is a model of MultiArray |
a,b | Objects of type A |
NumDims | The numeric dimension parameter associated withA . |
Dims | Some numeric dimension parameter such that 0<Dims<NumDims . |
indices | An object created by some number of chained callsto index_gen::operator[](index_range) . |
index_list | An object whose type modelsCollection |
idx | A signed integral value. |
tmp | An object of type boost::array<index,NumDims> |
Table 2. Associated Types
Type | Description |
---|---|
value_type | This is the value type of the container. If NumDims 1 , then this iselement . Otherwise, this is the value type of theimmediately nested containers. |
reference | This is the reference type of the contained value. If NumDims 1 , then this is element& . Otherwise, this is the same type astemplate subarray<NumDims-1>::type . |
const_reference | This is the const reference type of the contained value.If NumDims 1 , then this is const element& . Otherwise, this is the sametype astemplate const_subarray<NumDims-1>::type . |
size_type | This is an unsigned integral type. It is primarily used to specify array shape. |
difference_type | This is a signed integral type used to represent the distance between twoiterators. It is the same type asstd::iterator_traits<iterator>::difference_type . |
iterator | This is an iterator over the values of A .If NumDims 1 , then it models Random Access Iterator . Otherwise it models Random Access Traversal Iterator,Readable Iterator,Writable Iterator, and Output Iterator . |
const_iterator | This is the const iterator over the values of A . |
reverse_iterator | This is the reversed iterator, used to iterate backwards over the values of A . |
const_reverse_iterator | This is the reversed const iterator.A . |
element | This is the type of objects stored at the base of thehierarchy of MultiArrays. It is the same astemplate subarray<1>::value_type |
index | This is a signed integral type used for indexing into A . It is also used to represent strides and index bases. |
index_gen | This type is used to create a tuple of index_range s passed to operator[] to createan array_view<Dims>::type object. |
index_range | This type specifies a range of indices over some dimension of aMultiArray. This range will be visible through an array_view<Dims>::type object. |
template subarray<Dims>::type | This is subarray type with Dims dimensions.It is the reference type of the (NumDims - Dims) dimension of A and also modelsMultiArray. |
template const_subarray<Dims>::type | This is the const subarray type. |
template array_view<Dims>::type | This is the view type with Dims dimensions. It isreturned by calling operator[]( .It models MultiArray. |
templateconst_array_view<Dims>::type | This is the const view type with Dims dimensions. |
Table 3. Valid Expressions
Expression | Return type | Semantics |
---|---|---|
A::dimensionality | size_type | This compile-time constant represents the number ofdimensions of the array (note that A::dimensionality NumDims ). |
a.shape() | const size_type* | This returns a list of NumDims elements specifying theextent of each array dimension. |
a.strides() | const index* | This returns a list of NumDims elements specifying thestride associated with each array dimension. When accessing values,strides is used to calculate an element's location in memory. |
a.index_bases() | const index* | This returns a list of NumDims elements specifying thenumeric index of the first element for each array dimension. |
a.origin() | element* if a is mutable,const element* otherwise. | This returns the address of the element accessed by the expressiona[0][0]..[0]. . If the index bases are positive,this element won't exist, but the address can still be used to locatea valid element given its indices. |
a.num_dimensions() | size_type | This returns the number of dimensions of the array(note that a.num_dimensions() NumDims ). |
a.num_elements() | size_type | This returns the number of elements containedin the array. It is equivalent to the following code: |
a.size() | size_type | This returns the number of values contained ina . It is equivalent to a.shape()[0]; |
a(index_list) | element& ; if a is mutable,const element& otherwise. | This expression accesses a specific element ofa .index_list is the unique setof indices that address the element returned. It is equivalent to the following code (disregarding intermediate temporaries): |
a.begin() | iterator if a is mutable,const_iterator otherwise. | This returns an iterator pointing to the beginning ofa . |
a.end() | iterator if a is mutable,const_iterator otherwise. | This returns an iterator pointing to the end ofa . |
a.rbegin() | reverse_iterator if a is mutable, const_reverse_iterator otherwise. | This returns a reverse iterator pointing to thebeginning of a reversed. |
a.rend() | reverse_iterator if a is mutable, const_reverse_iterator otherwise. | This returns a reverse iterator pointing to the end of a reversed. |
a[idx] | reference if a is mutable,const_reference otherwise. | This returns a reference type that is bound to the indexidx value of a . Note that ifi is the index base for this dimension, the aboveexpression returns the (idx-i) th element (countingfrom zero). The expression is equivalent to*(a.begin()+idx-a.index_bases()[0]); . |
a[indices] | array_view<Dims>::type ifa is mutable,const_array_view<Dims>::type otherwise. | This expression generates a view of the array determined by theindex_range and index values used to construct indices . |
a b | bool | This performs a lexicographical comparison of thevalues of a and b . The elementtype must model EqualityComparable for thisexpression to be valid. |
a < b | bool | This performs a lexicographical comparison of thevalues of a and b . The elementtype must model LessThanComparable for thisexpression to be valid. |
a <= b | bool | This performs a lexicographical comparison of thevalues of a and b . The elementtype must model EqualityComparable andLessThanComparable for thisexpression to be valid. |
a > b | bool | This performs a lexicographical comparison of thevalues of a and b . The elementtype must model EqualityComparable and LessThanComparable for thisexpression to be valid. |
a >= b | bool | This performs a lexicographical comparison of thevalues of a and b . The elementtype must model LessThanComparable for thisexpression to be valid. |
begin()
and end()
execute in amortizedconstant time.size()
executes in at most linear time in the MultiArray's size. Table 4. Invariants
Valid range | [a.begin(),a.end()) is a valid range. |
Range size | a.size() std::distance(a.begin(),a.end()); . |
Completeness | Iteration through the range [a.begin(),a.end()) will traverse across everyvalue_type of a . |
Accessor Equivalence | Calling a[a1][a2]..[aN] where NNumDims yields the same result as calling a(index_list) , where index_list is a Collection containing the values a1..aN . |
The following MultiArray associated types define the interface for creating views of existingMultiArrays. Their interfaces and roles in theconcept are described below.
index_range
objects represent half-openstrided intervals. They are aggregated (using anindex_gen
object) and passed to a MultiArray's operator[]
to create an array view. When creating a view, each index_range
denotes a range ofvalid indices along one dimension of a MultiArray.Elements that are accessed through the set of ranges specified will be included in the constructed view. In some cases, anindex_range
is created without specifying startor finish values. In those cases, the object is interpreted tostart at the beginning of a MultiArray dimensionand end at its end.index_range
objects can be constructed and modified several ways in order to allow convenient and clear expression of arange of indices. To specify ranges, index_range
supports a set of constructors, mutating member functions, and a novel specification involving inequality operators. Using inequalityoperators, a half open range [5,10) can be specified as follows: or
and so on.The following describes the
index_range
interface.Table 5. Notation
i | An object of type index_range . |
idx,idx1,idx2,idx3 | Objects of type index . |
Table 6. Associated Types
Type | Description |
---|---|
index | This is a signed integral type. It is used tospecify the start, finish, and stride values. |
size_type | This is an unsigned integral type. It is used toreport the size of the range an index_range represents. |
Table 7. Valid Expressions
Expression | Return type | Semantics |
---|---|---|
index_range(idx1,idx2,idx3) | index_range | This constructs an index_range representing the interval [idx1,idx2) with stride idx3 . |
index_range(idx1,idx2) | index_range | This constructs an index_range representing the interval [idx1,idx2) with unit stride. It is equivalent to index_range(idx1,idx2,1) . |
index_range() | index_range | This construct an index_range with unspecified start and finish values. |
i.start(idx1) | index& | This sets the start index of i to idx . |
i.finish(idx) | index& | This sets the finish index of i to idx . |
i.stride(idx) | index& | This sets the stride length of i to idx . |
i.start() | index | This returns the start index of i . |
i.finish() | index | This returns the finish index of i . |
i.stride() | index | This returns the stride length of i . |
i.get_start(idx) | index | If i specifies a startvalue, this is equivalent to i.start() . Otherwise itreturns idx . |
i.get_finish(idx) | index | If i specifies a finishvalue, this is equivalent to i.finish() . Otherwise itreturns idx . |
i.size(idx) | size_type | If i specifies a both finish andstart values, this is equivalent to(i.finish()-i.start())/i.stride() . Otherwise itreturns idx . |
i < idx | index | This is another syntax for specifying the finishvalue. This notation does not include idx in the range of valid indices. It is equivalent to index_range(r.start(), idx, r.stride()) |
i <= idx | index | This is another syntax for specifying the finishvalue. This notation includes idx in the range of valid indices. It is equivalent to index_range(r.start(), idx + 1, r.stride()) |
idx < i | index | This is another syntax for specifying the startvalue. This notation does not include idx in the range of valid indices. It is equivalent to index_range(idx + 1, i.finish(), i.stride()) . |
idx <= i | index | This is another syntax for specifying the startvalue. This notation includesidx1 in the range of valid indices. It is equivalent to index_range(idx, i.finish(), i.stride()) . |
i + idx | index | This expression shifts the start and finish valuesof i up by idx . It is equivalent to index_range(r.start()+idx1, r.finish()+idx, r.stride()) |
i - idx | index | This expression shifts the start and finish valuesof i up by idx . It is equivalent to index_range(r.start()-idx1, r.finish()-idx, r.stride()) |
index_gen
aggregates index_range
objects in order to specify viewparameters. Chained calls to operator[]
storerange and dimension information used to instantiate a new view into a MultiArray.Table 8. Notation
Dims,Ranges | Unsigned integral values. |
x | An object of type template gen_type<Dims,Ranges>::type . |
i | An object of type index_range . |
idx | Objects of type index . |
Table 9. Associated Types
Type | Description |
---|---|
index | This is a signed integral type. It is used tospecify degenerate dimensions. |
size_type | This is an unsigned integral type. It is used toreport the size of the range an index_range represents. |
template gen_type::<Dims,Ranges>::type | This type generator names the result of Dims chained calls toindex_gen::operator[] . TheRanges parameter is determined by the number ofdegenerate ranges specified (i.e. calls tooperator[](index) ). Note that index_gen andgen_type<0,0>::type are the same type. |
Table 10. Valid Expressions
Expression | Return type | Semantics |
---|---|---|
index_gen() | gen_type<0,0>::type | This constructs an index_gen object. This object can then be used to generate tuples ofindex_range values. |
x[i] | gen_type<Dims+1,Ranges+1>::type | Returns a new object containing all previousindex_range objects in addition toi. Chained calls tooperator[] are the means by whichindex_range objects are aggregated. |
x[idx] | gen_type<Dims,Ranges+1>::type | Returns a new object containing all previousindex_range objects in addition to a degeneraterange, index_range(idx,idx). Note that this is NOTequivalent to x[index_range(idx,idx)]. , which willreturn an object of typegen_type<Dims+1,Ranges+1>::type . |
multi_array
multi_array_ref
const_multi_array_ref
template array_view<Dims>::type
template const_array_view<Dims>::type
template subarray<Dims>::type
template const_subarray<Dims>::type
Boost.MultiArray defines an array class,
multi_array
, and two adapter classes,multi_array_ref
and const_multi_array_ref
. The three classes model MultiArray and so they share a lot of functionality.multi_array_ref
differs frommulti_array
in that themulti_array
manages its own memory, whilemulti_array_ref
is passed a block of memory that itexpects to be externally managed.const_multi_array_ref
differs frommulti_array_ref
in that the underlying elements itadapts cannot be modified through its interface, though some arrayproperties, including the array shape and index bases, can be altered.Functionality the classes have in common is describedbelow.Note: Preconditions, Effects, and Implementation. Throughout the following sections, small pieces of C++ code areused to specify constraints such as preconditions, effects, andpostconditions. These do not necessarily describe the underlyingimplementation of array components; rather, they describe the expected input to andbehavior of the specified operations. Failure to meetpreconditions results in undefined behavior. Not all effects(i.e. Templates for pages – design 6 0 3 x 5. copy constructors, etc.) must be mimicked exactly. The codesnippets for effects intend to capture the essence of the describedoperation.
Queries.
This returns a pointer to the beginning of thecontiguous block that contains the array's data. If all dimensions ofthe array are 0-indexed and stored in ascending order, this is equivalent to
origin()
. Note thatconst_multi_array_ref
only provides the constversion of this function.This returns the origin element of the
multi_array
. Note thatconst_multi_array_ref
only provides the constversion of this function. (Required by MultiArray)const index* index_bases();
This returns the index bases for the
multi_array
. (Required by MultiArray)const index* strides();
This returns the strides for the
multi_array
. (Required by MultiArray)const size_type* shape();
This returns the shape of the
multi_array
. (Required by MultiArray)Comparators.
Each comparator executes a lexicographical compare overthe value types of the two arrays.(Required by MultiArray)
Preconditions. Msecure password manager 3 5 5 download free.
element
must support thecomparator corresponding to that called onmulti_array
.Complexity. O(
num_elements()
).Modifiers.
This changes the shape of the
multi_array
. Thenumber of elements and the index bases remain the same, but the numberof values at each level of the nested container hierarchy maychange.SizeList
Requirements. SizeList
must modelCollection.Preconditions.
Postconditions.
std::equal(sizes.begin(),sizes.end(),this->shape) true;
This changes the index bases of the
multi_array
tocorrespond to the the values in values
.BaseList
Requirements. BaseList
must modelCollection.Preconditions.
values.size() NumDims;
Postconditions.
std::equal(values.begin(),values.end(),this->index_bases());
This changes the index bases of all dimensions of the
multi_array
to value
.Pixelmator pro 1 3 15. Postconditions.
multi_array
is a multi-dimensional container thatsupports random access iteration. Its number of dimensions isfixed at compile time, but its shape and the number of elements itcontains are specified during its construction. The number of elementswill remain fixed for the duration of amulti_array
's lifetime, but the shape of the container canbe changed. A multi_array
manages its data elementsusing a replaceable allocator.Model Of. MultiArray,CopyConstructible. Depending on the element type, it may also model EqualityComparable and LessThanComparable.
Synopsis.
Constructors.
This constructs a
multi_array
using the specifiedparameters. sizes
specifies the shape of theconstructed multi_array
. store
specifies the storage order or layout in memory of the arraydimensions. alloc
is used toallocate the contained elements.ExtentList
Requirements. ExtentList
must model Collection.Preconditions.
sizes.size() NumDims;
This constructs a
multi_array
using the specified parameters. ranges
specifies the shape andindex bases of the constructed multi_array. It is the result of NumDims
chained calls to extent_gen::operator[]
. store
specifies the storage order or layout in memory of the arraydimensions. alloc
is the allocator used toallocate the memory used to store multi_array
elements.These constructors all constructs a
multi_array
and perform a deep copy of x
. Complexity. This performs O(
x.num_elements()
) calls toelement
's copy constructor.This constructs a
multi_array
whose shape is (0,..,0) and contains no elements.Note on Constructors. The
multi_array
construction expressions,and
are equivalent.
Modifiers.
This performs an element-wise copy of
x
into the current multi_array
.Array
Requirements. Array
must model MultiArray. Preconditions.
Postconditions.
Complexity. The assignment operators perform O(
x.num_elements()
) calls to element
's copy constructor.This copies the elements in the range
[begin,end)
into the array. It is equivalent to std::copy(begin,end,this->data())
.Preconditions.
std::distance(begin,end) this->num_elements();
Complexity. The
assign
member function performsO(this->num_elements()
) calls toValueType
's copy constructor.This function resizes an array to the shape specified by
extents
, which is either a generated list ofextents or a model of the Collection
concept. Thecontents of the array are preserved whenever possible; if the newarray size is smaller, then some data will be lost. Any new elementscreated by resizing the array are initialized with theelement
default constructor.Queries.
This query returns the storage order object associated with the
multi_array
in question. It can be used to construct a new array with the same storage order.multi_array_ref
is a multi-dimensional containeradaptor. It provides the MultiArray interface over any contiguousblock of elements. multi_array_ref
exports thesame interface as multi_array
, with the exceptionof the constructors.Model Of.
multi_array_ref
models MultiArray,CopyConstructible.and depending on the element type, it may also modelEqualityComparable and LessThanComparable. Detailed descriptions are provided here only for operations that arenot described in the multi_array
reference.Synopsis.
Constructors.
This constructs a
multi_array_ref
using the specifiedparameters. sizes
specifies the shape of theconstructed multi_array_ref
. store
specifies the storage order or layout in memory of the arraydimensions. alloc
is used toallocate the contained elements.ExtentList
Requirements. ExtentList
must model Collection.Preconditions.
sizes.size() NumDims;
This constructs a
multi_array_ref
using the specified parameters. ranges
specifies the shape andindex bases of the constructed multi_array_ref. It is the result of NumDims
chained calls to extent_gen::operator[]
. store
specifies the storage order or layout in memory of the arraydimensions. This constructs a shallow copy of
x
.Complexity. Constant time (for contrast, compare this tothe
multi_array
class copy constructor.Modifiers.
This performs an element-wise copy of
x
into the current multi_array_ref
.Array
Requirements. Array
must model MultiArray. Preconditions.
Postconditions.
Complexity. The assignment operators perform O(
x.num_elements()
) calls to element
's copy constructor.const_multi_array_ref
is a multi-dimensional containeradaptor. It provides the MultiArray interface over any contiguousblock of elements. const_multi_array_ref
exports thesame interface as multi_array
, with the exceptionof the constructors.Model Of.
const_multi_array_ref
modelsMultiArray,CopyConstructible.and depending on the element type, it may also modelEqualityComparable and LessThanComparable. Detailed descriptions are provided here only for operations that arenot described in the multi_array
reference.Synopsis.
Constructors.
This constructs a
const_multi_array_ref
using the specifiedparameters. sizes
specifies the shape of theconstructed const_multi_array_ref
. store
specifies the storage order or layout in memory of the arraydimensions.ExtentList
Requirements. ExtentList
must model Collection.Preconditions.
sizes.size() NumDims;
Effects. This constructs a
const_multi_array_ref
using the specified parameters. ranges
specifies the shape andindex bases of the constructed const_multi_array_ref. It is the result of NumDims
chained calls to extent_gen::operator[]
. store
specifies the storage order or layout in memory of the arraydimensions. Effects. This constructs a shallow copy of
x
.Namespace
multi_array_types
defines typesassociated with multi_array
,multi_array_ref
, andconst_multi_array_ref
that are notdependent upon template parameters. These types find common use withall Boost.Multiarray components. They are definedin a namespace from which they can be accessed conveniently.With the exception of extent_gen
and extent_range
, these types fulfill the roles of thesame name required by MultiArray and are described in itsconcept definition. extent_gen
andextent_range
are described below.extent_range
objects define half openintervals. They provide shape and index base information tomulti_array
, multi_array_ref
, and const_multi_array_ref
constructors.extent_range
s are passed inaggregate to an array constructor (seeextent_gen
for more details).Synopsis.
Model Of. DefaultConstructible,CopyConstructible
Methods and Types.
extent_range(index start, index finish)
This constructor defines the half open interval
[start,finish)
. The expressionfinish
must be greater than start
.extent_range(index finish)
This constructor defines the half open interval
[0,finish)
. The value of finish
must be positive.index start()
This function returns the first index represented by the range
index finish()
This function returns the upper boundary value of the half-openinterval. Note that the range does not include this value.
size_type size()
This function returns the size of the specified range. It isequivalent to
finish()-start()
.The
extent_gen
class defines aninterface for aggregating array shape and indexing information to bepassed to a multi_array
, multi_array_ref
, or const_multi_array_ref
constructor. Its interface mimics the syntax used to declare built-in array typesin C++. For example, while a 3-dimensional array of int
values in C++ would bedeclared as:a similar
multi_array
would be declared:Synopsis.
Methods and Types.
template gen_type<Ranges>::type
This type generator is used to specify the result of
Ranges
chained calls toextent_gen::operator[].
The typesextent_gen
andgen_type<0>::type
are the same.gen_type<NumRanges+1>::type operator[](const extent_range& a_range) const;
This function returns a new object containing all previous
extent_range
objects in addition toa_range.
extent_range
objects are aggregated by chained calls tooperator[]
.gen_type<NumRanges+1>::typeoperator[](index idx) const;
This function returns a new object containing all previous
extent_range
objects in addition toextent_range(0,idx).
This function gives the arrayconstructors a similar syntax to traditional C multidimensional arraydeclaration.For syntactic convenience, Boost.MultiArray defines two global objects as part of itsinterface. These objects play the role of object generators;expressions involving them create other objects of interest.
Under some circumstances, the two global objects may beconsidered excessive overhead. Their construction can be prevented bydefining the preprocessor symbol
BOOST_MULTI_ARRAY_NO_GENERATORS
before includingboost/multi_array.hpp.
Boost.MultiArray's array classes use the
extents
global object to specify array shape during their construction. For example,a 3 by 3 by 3 multi_array
is constructed as follows:The same array could also be created by explicitly declaring an
extent_gen
object locally, but the global object makes this declaration unnecessary. The MultiArray concept specifies an
index_gen
associated type that is used tocreate views.indices
is a global object that serves the role ofindex_gen
for all array components provided by thislibrary and their associated subarrays and views. For example, using the
indices
object,a view of an array A
is constructed as follows:Boost.MultiArray provides traits classes,
subarray_gen
,const_subarray_gen
,array_view_gen
,and const_array_view_gen
, for naming ofarray associated types within function templates. In general this is no more convenient to use than the nested type generators, but the library author found that some C++ compilers do not properly handle templates nested within function template parameter types. These generators constitute a workaround for this deficit. The following code snippet illustratesthe correspondence between the array_view_gen
traits class and the array_view
type associated toan array:In the above example,
view1_t
andview2_t
have the same type.While a multidimensional array represents a hierarchy of containers ofelements, at some point the elements must be laid out inmemory. As a result, a single multidimensional array can be represented in memory more than one way.
For example, consider the two dimensional array shown below inmatrix notation:
Here is how the above array is expressed in C++:
This is an example of row-major storage, where elements of each roware stored contiguously. While C++ transparently handles accessing elements of an array, youcan also manage the array and its indexing manually. One way that this may be expressed in memory is as follows:
With the latter declaration of
a
and strides s
, element a(i,j)
of the array can beaccessed using the expression .
The same two dimensional array could be laid out by column as follows:
Notice that the strides here are different. As a result,The expression given above to access values will work with this pairof data and strides as well.
In addition to dimension order, it is also possible tostore any dimension in descending order. For example, returning to the first example, the first dimension of the example array, the rows, could be stored in reverse, resulting in the following:
Note that in this example
a
must be explicitly setto the origin. In the previous examples, thefirst element stored in memory was the origin; here this is no longerthe case. Alternatively, the second dimension, or the columns, could be reversedand the rows stored in ascending order:
Finally, both dimensions could be stored in descending order:
All of the above arrays are equivalent. The expressiongiven above for
a(i,j)
will yield the same valueregardless of the memory layout.Boost.MultiArray arrays can be created with customized storageparameters as described above. Thus, existing data can be adapted(with multi_array_ref
orconst_multi_array_ref
) as suited to the arrayabstraction. A common usage of this feature would be to wrap arraysthat must interoperate with Fortran routines so they can bemanipulated naturally at both the C++ and Fortran levels. Thefollowing sections describe the Boost.MultiArray components used tospecify memory layout.c_storage_order
is used to specify that anarray should store its elements using the same layout as that used byprimitive C++ multidimensional arrays, that is, from last dimensionto first. This is the default storage order for the arrays provided bythis library.fortran_storage_order
is used to specify thatan array should store its elements using the same memory layout as aFortran multidimensional array would, that is, from first dimension tolast.general_storage_order
allows the user tospecify an arbitrary memory layout for the contents of an array. Theconstructed object is passed to the array constructor in order tospecify storage order.OrderingIter
and AscendingIter
must model the InputIterator
concept. Bothiterators must refer to a range of NumDims
elements. AscendingIter
points to objectsconvertible to bool
. A value oftrue
means that a dimension is stored in ascendingorder while false
means that a dimension is storedin descending order. OrderingIter
specifies theorder in which dimensions are stored.By default, the array access methods
operator()
andoperator[]
perform rangechecking. If a supplied index is out of the range defined for anarray, an assertion will abort the program. To disable rangechecking (for performance reasons in production releases), definethe BOOST_DISABLE_ASSERTS
preprocessor macro prior toincluding multi_array.hpp in an application...one of the most highly regarded and expertly designed C++ library projects in the world.— Herb Sutter and Andrei Alexandrescu, C++ Coding Standards
Contents
- Performance tests
- Results for 1 ordered index
- Results for 1 sequenced index
- Results for 2 ordered indices
- Results for 1 ordered index + 1 sequenced index
- Results for 3 ordered indices
- Results for 2 ordered indices + 1 sequenced index
Introduction
Boost.MultiIndex helps the programmer to avoid the manual construction of cumbersomecompositions of containers when multi-indexing capabilities are needed. Furthermore,it does so in an efficient manner, both in terms of space and time consumption. Thespace savings stem from the compact representation of the underlying data structures,requiring a single node per element. As for time efficiency, Boost.MultiIndexintensively uses metaprogramming techniques producing very tight implementationsof member functions which take care of the elementary operations for each index:for
multi_index_container
s with two or more indices, the running timecan be reduced to half as long as with manual simulations involving severalSTL containers.Manual simulation of a multi_index_container
The section on emulationof standard containers with
multi_index_container
shows the equivalencebetween single-index multi_index_container
s and some STL containers. Let us nowconcentrate on the problem of simulating a multi_index_container
with twoor more indices with a suitable combination of standard containers.Consider the following instantiation of
multi_index_container
:indexed_t
maintains two internal indices on elements of typeint
. In order to simulate this data structure resorting only tostandard STL containers, one can use on a first approach the following types:where
deletion, on the other hand, necessitates a logarithmic search, whereasmanual_t1
is the 'base' container that holdsthe actual elements, and manual_t2
stores pointers toelements of manual_t1
. This scheme turns out to be quiteinefficient, though: while insertion into the data structure is simple enough:indexed_t
deletes in constant time:The right approach consists of feeding the second container not withraw pointers, but with elements of type
manual_t1::iterator
:Now, insertion and deletion can be performed with complexity boundsequivalent to those of
indexed_t
:The construction can be extended in a straightworward manner tohandle more than two indices. In what follows, we will compareinstantiations of
multi_index_container
against this sort ofmanual simulations.Spatial efficiency
The gain in space consumption of
multi_index_container
withrespect to its manual simulations is amenable to a very simpletheoretical analysis. For simplicity, we will ignore alignmentissues (which in general play in favor of multi_index_container
.)Nodes of a
multi_index_container
with N indices hold the valueof the element plus N headers containing linking information foreach index. Thus the node size isSI = e + h0 + ··· + hN-1, where
e = size of the element,
hi = size of the i-th header.
On the other hand, the manual simulation allocates N nodes perelement, the first holding the elements themselves and the reststoring iterators to the 'base' container. In practice, an iteratormerely holds a raw pointer to the node it is associated to, so its sizeis independent of the type of the elements. Summing all contributions,the space allocated per element in a manual simulation is
SM = (e + h0) +(p + h1) + ··· +(p + hN-1) = SI + (N-1)p, where
p = size of a pointer.
The relative amount of memory taken up by
multi_index_container
with respect to its manual simulation is justSI / SM, which can be expressedthen as:SI / SM =SI / (SI + (N-1)p).
The formula shows that
multi_index_container
is more efficientwith regard to memory consumption as the number of indices grow. An implicitassumption has been made that headers of multi_index_container
index nodes are the same size that their analogues in STL containers; but thereis a particular case in which this is often not the case: ordered indices use aspatial optimizationtechnique which is not present in many implementations ofstd::set
, giving an additional advantage tomulti_index_container
s of one system word per ordered index. Taking this fact into account, the former formula can be adjusted to:SI / SM =SI / (SI + (N-1)p + Ow),
where O is the number of ordered indices of the container, and wis the system word size (typically 4 bytes on 32-bit architectures.)
These considerations have overlooked an aspect of the greatest practicalimportance: the fact that
multi_index_container
allocates a singlenode per element, compared to the many nodes of different sizesbuilt by manual simulations, diminishes memory fragmentation, whichcan show up in more usable memory available and better performance.Time efficiency
From the point of view of computational complexity (i.e. big-Ocharacterization),
multi_index_container
and its corresponding manualsimulations are equivalent: inserting an element intoa multi_index_container
reduces to a simple combination ofelementary insertion operations on each of the indices, andsimilarly for deletion. Hence, the most we can expect is a reduction(or increase) of execution time by a roughly constant factor. As wewill see later, the reduction can be very significative formulti_index_container
s with two or more indices.In the special case of
multi_index_container
s with only one index,resulting performance will roughly match that of the STL equivalent containers:tests show that there is at most a negligible degradation with respect to STL,and even in some cases a small improvement.Performance tests
See source code used for measurements.
In order to assess the efficiency of
multi_index_container
, the followingbasic algorithmhas been measured for different instantiations of
multi_index_container
at values of n 1,000, 10,000 and 100,000,and its execution time compared with that of the equivalent algorithmfor the corresponding manual simulation of the data structure based onSTL containers. The table below describes the test environments used.Compiler | Settings | OS and CPU |
---|---|---|
GCC 3.4.5 (mingw special) | -O3 | Windows 2000 Pro on P4 1.5 GHz, 256 MB RAM |
Intel C++ 7.1 | default release settings | Windows 2000 Pro on P4 1.5 GHz, 256 MB RAM |
Microsoft Visual C++ 8.0 | default release settings, _SECURE_SCL=0 | Windows XP on P4 Xeon 3.2 GHz, 1 GB RAM |
The relative memory consumption (i.e. the amount of memory allocatedby a
multi_index_container
with respect to its manual simulation)is determined by dividing the size of a multi_index_container
nodeby the sum of node sizes of all the containers integrating thesimulating data structure.Results for 1 ordered index
The following instantiation of
multi_index_container
was tested:which is functionally equivalent to
std::set<int>
.Memory consumption
GCC 3.4.5 | ICC 7.1 | MSVC 8.0 |
---|---|---|
80% | 80% | 80% |
multi_index_container
with 1ordered index.The reduction in memory usage is accounted for by the optimization technique implementedin Boost.MultiIndex ordered indices, as explained above.
Execution time
Fig. 1: Performance of multi_index_container
with 1 ordered index.
Somewhat surprisingly,
multi_index_container
performs slightlybetter than std::set
. A very likely explanation for this behavioris that the lower memory consumption of multi_index_container
results in a higher processor cache hit rate.The improvement is smallest for GCC, presumably because the worse quality ofthis compiler's optimizer masks the cache-related benefits.Results for 1 sequenced index
The following instantiation of
multi_index_container
was tested:which is functionally equivalent to
std::list<int>
.Memory consumption
GCC 3.4.5 | ICC 7.1 | MSVC 8.0 |
---|---|---|
100% | 100% | 100% |
multi_index_container
with 1sequenced index.The figures confirm that in this case
multi_index_container
nodes are thesame size than those of its std::list
counterpart.Execution time
Fig. 2: Performance of multi_index_container
with 1 sequenced index.
multi_index_container
does not attain the performanceof its STL counterpart, although the figures are close. Again, the worst resultsare those of GCC, with a degradation of up to 7%, while ICC and MSVC do notexceed a mere 5%.Results for 2 ordered indices
Multi Dock 1 1 57 =
The following instantiation of
multi_index_container
was tested:Memory consumption
GCC 3.4.5 | ICC 7.1 | MSVC 8.0 |
---|---|---|
70% | 70% | 70% |
multi_index_container
with 2ordered indices.These results concinde with the theoretical formula forSI = 28, N = O = 2 and p = w = 4.
Execution time
Fig. 3: Performance of multi_index_container
with 2 ordered indices.
The experimental results confirm our hypothesis that
multi_index_container
provides an improvement on execution time by an approximately constant factor,which in this case lies around 60%. There is no obvious explanation for theincreased advantage of multi_index_container
in MSVC forn=105.Results for 1 ordered index + 1 sequenced index
The following instantiation of
multi_index_container
was tested:Memory consumption
GCC 3.4.5 | ICC 7.1 | MSVC 8.0 |
---|---|---|
75% | 75% | 75% |
multi_index_container
with 1ordered index + 1 sequenced index.These results concinde with the theoretical formula forSI = 24, N = 2, O = 1 and p = w = 4.
Multi Dock 1 1 57 Inches
Execution time
Fig. 4: Performance of multi_index_container
with 1 ordered index+ 1 sequenced index.
For n=103 and n=104, the resultsare in agreement with our theoretical analysis, showing a constant factorimprovement of 50-65% with respect to the STL-based manual simulation.Curiously enough, this speedup gets even higher whenn=105 for two of the compilers, namely GCC and ICC.In order to rule out spurious results, the testshave been run many times, yielding similar outcoumes. Both test environmentsare deployed on the same machine, which points to some OS-related reason forthis phenomenon.
Results for 3 ordered indices
The following instantiation of
multi_index_container
was tested:Memory consumption
Multi Dock 1 1 57 Kg
GCC 3.4.5 | ICC 7.1 | MSVC 8.0 |
---|---|---|
66.7% | 66.7% | 66.7% |
multi_index_container
with 3ordered indices.These results concinde with the theoretical formula forSI = 40, N = O = 3 and p = w = 4.
Execution time
Fig. 5: Performance of multi_index_container
with 3 ordered indices.
Execution time for this case is between 45% and 55% lower than achieved withan STL-based manual simulation of the same data structure.
Results for 2 ordered indices + 1 sequenced index
The following instantiation of
multi_index_container
was tested:Memory consumption
GCC 3.4.5 | ICC 7.1 | MSVC 8.0 |
---|---|---|
69.2% | 69.2% | 69.2% |
multi_index_container
with 2ordered indices + 1 sequenced index.These results concinde with the theoretical formula forSI = 36, N = 3, O = 2 and p = w = 4.
Execution time
Fig. 6: Performance of multi_index_container
with 2 ordered indices+ 1 sequenced index.
In accordance to the expectations, execution time is improved by a fairly constantfactor, which ranges from 45% to 55%.
Conclusions
Multi Dock 1 1 57 Mph
We have shown that
multi_index_container
outperforms, both in space andtime efficiency, equivalent data structures obtained from the manualcombination of STL containers. This improvement gets larger when the numberof indices increase.In the special case of replacing standard containers with single-indexed
multi_index_container
s, the performance of Boost.MultiIndexis comparable with that of the tested STL implementations, and can even yieldsome improvements both in space consumption and execution time.Revised May 9th 2006
© Copyright 2003-2006 Joaquín M López Muñoz.Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)