📄 arrays-expr.texi
字号:
@end ifnottex@math{A} is a rank 3 tensor (a three dimensional array), @math{B} is a rank2 tensor (a two dimensional array), and @math{C} is a rank 1 tensor (a onedimensional array). The above expression sets @code{A(i,j,k) = B(i,j) * C(k)}.To implement this product using Blitz++, we'll need the arrays and someindex placeholders:@cindex index placeholders used for tensor notation@exampleArray<float,3> A(4,4,4);Array<float,2> B(4,4);Array<float,1> C(4);firstIndex i; // Alternately, could just saysecondIndex j; // using namespace blitz::tensor;thirdIndex k;@end exampleHere's the Blitz++ code which is equivalent to the tensor expression:@exampleA = B(i,j) * C(k);@end exampleThe index placeholder arguments tell an array how to map its dimensions ontothe dimensions of the destination array. For example, here's somereal-world tensor notation:@tex$$ C^{ijk} = A^{ij} x^{k} - A^{jk} y^{i} $$@end tex@html<pre> ijk ij k jk iC = A x - A y</pre>@end html@ifnottex@ifnothtml@example ijk ij k jk iC = A x - A y@end example@end ifnothtml@end ifnottexIn Blitz++, this would be coded as:@exampleusing namespace blitz::tensor;C = A(i,j) * x(k) - A(j,k) * y(i);@end exampleThis tensor expression can be visualized in the following way:@center @image{tensor1}@center Examples of array indexing, subarrays, and slicing.Here's an example which computes an outer product of two one-dimensionalarrays:@cindex outer product@cindex kronecker product@cindex tensor product@smallexample@include examples/outer.texi@end smallexampleAnd the output:@smallexample@include examples/outer.out@end smallexampleIndex placeholders can @emph{not} be used on the left-hand side of anexpression. If you need to reorder the indices, you must do this on theright-hand side.In real-world tensor notation, repeated indices imply a contraction (orsummation). For example, this tensor expression computes a matrix-matrixproduct:@tex$$ C^{ij} = A^{ik} B^{kj} $$@end tex@html<pre> ij ik kjC = A B</pre>@end html@ifnottex@ifnothtml@example ij ik kjC = A B@end example@end ifnothtml@end ifnottexThe repeated k index is interpreted as meaning@tex$$ c_{ij} = \sum_{k} a_{ik} b_{kj} $$@end tex@html<pre>c = sum of {a * b } over k ij ik kj</pre>@end html@ifnottex@ifnothtml@examplec = sum of @{a * b @} over k ij ik kj@end example@end ifnothtml@end ifnottex@cindex contraction@cindex tensor contractionIn Blitz++, repeated indices do @emph{not} imply contraction. If you wantto contract (sum along) an index, you must use the @code{sum()} function:@exampleArray<float,2> A, B, C; // ...firstIndex i;secondIndex j;thirdIndex k;C = sum(A(i,k) * B(k,j), k);@end exampleThe @code{sum()} function is an example of an @emph{array reduction},described in the next section.Index placeholders can be used in any order in an expression. This examplecomputes a kronecker product of a pair of two-dimensional arrays, andpermutes the indices along the way:@exampleArray<float,2> A, B; // ...Array<float,4> C; // ...fourthIndex l;C = A(l,j) * B(k,i);@end exampleThis is equivalent to the tensor notation@tex$$ C^{ijkl} = A^{lj} B^{ki} $$@end tex@html<pre> ijkl lj kiC = A B </pre>@end html@ifnottex@ifnothtml@example ijkl lj kiC = A B@end example@end ifnothtml@end ifnottexTensor-like notation can be mixed with other array notations:@exampleArray<float,2> A, B; // ...Array<double,4> C; // ...C = cos(A(l,j)) * sin(B(k,i)) + 1./(i+j+k+l);@end example@cindex tensor notation efficiency issuesAn important efficiency note about tensor-like notation: the right-hand sideof an expression is @emph{completely evaluated} for @emph{every} element inthe destination array. For example, in this code:@exampleArray<float,1> x(4), y(4);Array<float,2> A(4,4):A = cos(x(i)) * sin(y(j));@end exampleThe resulting implementation will look something like this:@examplefor (int n=0; n < 4; ++n) for (int m=0; m < 4; ++m) A(n,m) = cos(x(n)) * sin(y(m));@end exampleThe functions @code{cos} and @code{sin} will be invoked sixteen times each.It's possible that a good optimizing compiler could hoist the @code{cos}evaluation out of the inner loop, but don't hold your breath -- there's alot of complicated machinery behind the scenes to handle tensor notation,and most optimizing compilers are easily confused. In a situation like theabove, you are probably best off manually creating temporaries for@code{cos(x)} and @code{sin(y)} first.@section Array reductions@cindex Array reductions@cindex reductionsCurrently, Blitz++ arrays support two forms of reduction:@itemize @bullet@item Reductions which transform an array into a scalar (for example,summing the elements). These are referred to as @strong{completereductions}.@item Reducing an N dimensional array (or array expression) to an N-1dimensional array expression. These are called @strong{partial reductions}.@end itemize@cindex Array reductions complete@cindex complete reductions@cindex reductions complete@section Complete reductionsComplete reductions transform an array (or array expression) into a scalar. Here are some examples:@example Array<float,2> A(3,3);A = 0, 1, 2, 3, 4, 5, 6, 7, 8;cout << sum(A) << endl // 36 << min(A) << endl // 0 << count(A >= 4) << endl; // 5@end exampleHere are the available complete reductions:@table @code@item sum()@cindex @code{sum()} reductionSummation (may be promoted to a higher-precision type)@item product()@cindex @code{product()} reductionProduct @item mean()@cindex @code{mean()} reductionArithmetic mean (promoted to floating-point type if necessary) @item min()@cindex @code{min()} reductionMinimum value @item max()@cindex @code{max()} reductionMaximum value @item minIndex()@cindex @code{minIndex()} reductionIndex of the minimum value (@code{TinyVector<int,N_rank>})@item maxIndex()@cindex @code{maxIndex()} reductionIndex of the maximum value (@code{TinyVector<int,N_rank>})@item count()@cindex @code{count()} reductionCounts the number of times the expression is logical true (@code{int})@item any()@cindex @code{any()} reductionTrue if the expression is true anywhere (@code{bool})@item all()@cindex @code{all()} reductionTrue if the expression is true everywhere (@code{bool})@end table@strong{Note:} @code{minIndex()} and @code{maxIndex()} return TinyVectors, even when the rank of the array (or array expression) is 1.Reductions can be combined with @code{where} expressions (@ref{Where expr})to reduce over some part of an array. For example, @code{sum(where(A > 0,A, 0))} sums only the positive elements in an array.@section Partial Reductions@cindex Array reductions partial@cindex partial reductions@cindex reductions partialHere's an example which computes the sum of each row of a two-dimensionalarray:@exampleArray<float,2> A; // ...Array<float,1> rs; // ...firstIndex i;secondIndex j;rs = sum(A, j);@end exampleThe reduction @code{sum()} takes two arguments:@itemize @bullet@item The first argument is an array or array expression.@item The second argument is an index placeholder indicating thedimension over which the reduction is to occur. @end itemizeReductions have an @strong{important restriction}: It is currently onlypossible to reduce over the @emph{last} dimension of an array or arrayexpression. Reducing a dimension other than the last would require Blitz++to reorder the dimensions to fill the hole left behind. For example, inorder for this reduction to work:@exampleArray<float,3> A; // ...Array<float,2> B; // ...secondIndex j;// Reduce over dimension 2 of a 3-D array?B = sum(A, j);@end exampleBlitz++ would have to remap the dimensions so that the third dimensionbecame the second. It's not currently smart enough to do this.However, there is a simple workaround which solves some of the problemscreated by this limitation: you can do the reordering manually, prior to thereduction:@exampleB = sum(A(i,k,j), k);@end exampleWriting @code{A(i,k,j)} interchanges the second and third dimensions,permitting you to reduce over the second dimension. Here's a list of thereduction operations currently supported:@table @code@item sum() Summation@item product() Product @item mean() Arithmetic mean (promoted to floating-point type if necessary)@item min() Minimum value@item max() Maximum value@item minIndex() Index of the minimum value (int)@item maxIndex() Index of the maximum value (int)@item count() Counts the number of times the expression is logical true (int)@item any() True if the expression is true anywhere (bool)@item all() True if the expression is true everywhere (bool)@item first() First index at which the expression is logical true (int); if the expressionis logical true nowhere, then @code{tiny(int())} (INT_MIN) is returned.@item last() Last index at which the expression is logical true (int); if the expressionis logical true nowhere, then @code{huge(int())} (INT_MAX) is returned. @end tableThe reductions @code{any()}, @code{all()}, and @code{first()} haveshort-circuit semantics: the reduction will halt as soon as the answer isknown. For example, if you use @code{any()}, scanning of the expressionwill stop as soon as the first true value is encountered.To illustrate, here's an example:@exampleArray<int, 2> A(4,4);A = 3, 8, 0, 1, 1, -1, 9, 3, 2, -5, -1, 1, 4, 3, 4, 2;Array<float, 1> z;firstIndex i;secondIndex j;z = sum(A(j,i), j);@end exampleThe array @code{z} now contains the sum of @code{A} along each column:@example[ 10 5 12 7 ]@end exampleThis table shows what the result stored in @code{z} would be if@code{sum()} were replaced with other reductions:@examplesum [ 10 5 12 7 ]mean [ 2.5 1.25 3 1.75 ]min [ 1 -5 -1 1 ]minIndex [ 1 2 2 0 ]max [ 4 8 9 3 ]maxIndex [ 3 0 1 1 ]first((A < 0), j) [ -2147483648 1 2 -2147483648 ]product [ 24 120 0 6 ]count((A(j,i) > 0), j) [ 4 2 2 4 ]any(abs(A(j,i)) > 4, j) [ 0 1 1 0 ]all(A(j,i) > 0, j) [ 1 0 0 1 ]@end exampleNote: the odd numbers for first() are @code{tiny(int())} i.e.@: the smallestnumber representable by an int. The exact value is machine-dependent.@cindex Array reductions chaining@cindex partial reductions chaining@cindex reductions chainingThe result of a reduction is an array expression, so reductionscan be used as operands in an array expression:@exampleArray<int,3> A;Array<int,2> B;Array<int,1> C; // ...secondIndex j;thirdIndex k;B = sqrt(sum(sqr(A), k));// Do two reductions in a rowC = sum(sum(A, k), j);@end exampleNote that this is not allowed:@exampleArray<int,2> A;firstIndex i;secondIndex j;// Completely sum the array?int result = sum(sum(A, j), i);@end exampleYou cannot reduce an array to zero dimensions! Instead, use one of theglobal functions described in the previous section.@node Where expr@section where statements@cindex @code{where} statements@cindex functional if (@code{where})@cindex @code{if} (@code{where})Blitz++ provides the @code{where} function as an array expression version of the@code{( ? : )} operator. The syntax is:@examplewhere(array-expr1, array-expr2, array-expr3)@end exampleWherever @code{array-expr1} is true, @code{array-expr2} is returned. Where@code{array-expr1} is false, @code{array-expr3} is returned. For example,suppose we wanted to sum the squares of only the positive elements of anarray. This can be implemented using a where function:@exampledouble posSquareSum = sum(where(A > 0, pow2(A), 0));@end example
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -