📄 arrays-indirect.texi
字号:
@cindex indirection@cindex Array indirection@strong{Indirection} is the ability to modify or access an array at a set ofselected index values. Blitz++ provides several forms of indirection: @itemize @bullet@item @strong{Using a list of array positions}: this approach is usefulif you need to modify an array at a set of scattered points.@item @strong{Cartesian-product indirection}: as an example, for atwo-dimensional array you might have a list @code{I} of rows and a list@code{J} of columns, and you want to modify the array at all (i,j) positionswhere i is in @code{I} and j is in @code{J}. This is a @strong{cartesianproduct} of the index sets @code{I} and @code{J}.@item @strong{Over a set of strips}: for efficiency, you can represent anarbitrarily-shaped subset of an array as a list of one-dimensional strips.This is a useful way of handling @strong{Regions Of Interest} (ROIs).@end itemize@center @image{indirect}@center Three styles of indirection. @footnote{From top to bottom: (1) using a list of array positions; (2) Cartesian-product indirection; (3) using a set of strips to represent an arbitrarily-shaped subset of an array.}@cindex STL, for indirectionIn all cases, Blitz++ expects a Standard Template Library container. Someuseful STL containers are @code{list<>}, @code{vector<>}, @code{deque<>} and@code{set<>}. Documentation of these classes is often provided with yourcompiler, or see also the good documentation at@uref{http://www.sgi.com/Technology/STL/}. STL containers are used becausethey are widely available and provide easier manipulation of ``sets'' thanBlitz++ arrays. For example, you can easily expand and merge sets which arestored in STL containers; doing this is not so easy with Blitz++ arrays,which are designed for numerical work.STL containers are generally included by writing@example#include <list> // for list<>#include <vector> // for vector<>#include <deque> // for deque<>#include <set> // for set<>@end example@cindex [] operator, for indirectionThe @code{[]} operator is overloaded on arrays so that the syntax@code{array[container]} provides an indirect view of the array. So far,this indirect view may only be used as an lvalue (i.e.@: on the left-hand sideof an assignment statement).The examples in the next sections are available in the Blitz++ distributionin @file{<examples/indirect.cpp>}.@section Indirection using lists of array positions@cindex Array indirection list of positions@cindex indirection list of positionsThe simplest kind of indirection uses a list of points. For one-dimensionalarrays, you can just use an STL container of integers. Example:@example Array<int,1> A(5), B(5); A = 0; B = 1, 2, 3, 4, 5; vector<int> I; I.push_back(2); I.push_back(4); I.push_back(1); A[I] = B;@end exampleAfter this code, the array A contains @code{[ 0 2 3 0 5 ]}.Note that arrays on the right-hand-side of the assignment must have the sameshape as the array on the left-hand-side (before indirection). In thestatement @code{A[I] = B}, A and B must have the same shape, not I and B.For multidimensional arrays, you can use an STL container of@code{TinyVector<int,N_rank>} objects. Example:@example Array<int,2> A(4,4), B(4,4); A = 0; B = 10*tensor::i + tensor::j; typedef TinyVector<int,2> coord; list<coord> I; I.push_back(coord(1,1)); I.push_back(coord(2,2)); A[I] = B;@end exampleAfter this code, the array A contains:@example 0 0 0 0 0 11 0 0 0 0 22 0 0 0 0 0@end example(The @code{tensor::i} notation is explained in the section on indexplaceholders @ref{Index placeholders}).@section Cartesian-product indirection@cindex Array indirection Cartesian-product@cindex indirection Cartesian-productThe Cartesian product of the sets I, J and K is the set of (i,j,k) tuplesfor which i is in I, j is in J, and k is in K. Blitz++ implements cartesian-product indirection using an @strong{adaptor}which takes a set of STL containers and iterates through their Cartesianproduct. Note that the cartesian product is never explicitly created. Youcreate the Cartesian-product adaptor by calling the function:@exampletemplate<class T_container>indexSet(T_container& c1, T_container& c2, ...)@end exampleThe returned adaptor can then be used in the @code{[]} operator of an arrayobject.Here is a two-dimensional example:@cindex rank-1 update@example Array<int,2> A(6,6), B(6,6); A = 0; B = 10*tensor::i + tensor::j; vector<int> I, J; I.push_back(1); I.push_back(2); I.push_back(4); J.push_back(0); J.push_back(2); J.push_back(5); A[indexSet(I,J)] = B;@end exampleAfter this code, the A array contains:@example 0 0 0 0 0 010 0 12 0 0 1520 0 22 0 0 25 0 0 0 0 0 040 0 42 0 0 45 0 0 0 0 0 0@end exampleAll the containers used in a cartesian product must be the same type (e.g.all @code{vector<int>} or all @code{set<TinyVector<int,2> >}), but they maybe different sizes. Singleton containers (containers containing a singlevalue) are fine.@section Indirection with lists of strips@cindex Array indirection list of strips@cindex indirection list of stripsYou can also do indirection with a container of one-dimensional@strong{strips}. This is useful when you want to manipulate somearbitrarily-shaped, well-connected subdomain of an array. By representingthe subdomain as a list of strips, you allow Blitz++ to operate on vectors,rather than scattered points; this is much more efficient.@findex RectDomain<N>Strips are represented by objects of type @code{RectDomain<N>}, where@code{N} is the dimensionality of the array. The @code{RectDomain<N>} classcan be used to represent any rectangular subdomain, but for indirection itis only used to represent strips.You create a strip by using this function:@findex strip()@exampleRectDomain<N> strip(TinyVector<int,N> start, int stripDimension, int ubound);@end exampleThe @code{start} parameter is where the strip starts; @code{stripDimension}is the dimension in which the strip runs; @code{ubound} is the last indexvalue for the strip. For example, to create a 2-dimensional strip from(2,5) to (2,9), one would write:@exampleTinyVector<int,2> start(2,5);RectDomain<2> myStrip = strip(start,secondDim,9);@end exampleHere is a more substantial example which creates a list of stripsrepresenting a circle subset of an array:@example const int N = 7; Array<int,2> A(N,N), B(N,N); typedef TinyVector<int,2> coord; A = 0; B = 1; double centre_i = (N-1)/2.0; double centre_j = (N-1)/2.0; double radius = 0.8 * N/2.0; // circle will contain a list of strips which represent a circular // subdomain. list<RectDomain<2> > circle; for (int i=0; i < N; ++i) @{ double jdist2 = pow2(radius) - pow2(i-centre_i); if (jdist2 < 0.0) continue; int jdist = int(sqrt(jdist2)); coord startPos(i, int(centre_j - jdist)); circle.push_back(strip(startPos, secondDim, int(centre_j + jdist))); @} // Set only those points in the circle subdomain to 1 A[circle] = B;@end exampleAfter this code, the A array contains:@example 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0@end example
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -