Next: Index placeholders, Up: Array Expressions [Contents][Index]
A commonly asked question about Blitz++ is what order it uses to evaluate array expressions. For example, in code such as
A(Range(2,10)) = A(Range(1,9))
does the expression get evaluated at indices 1, 2, ..., 9 or at 9, 8, ...,
1? This makes a big difference to the result: in one case, the array will
be shifted to the right by one element; in the other case, most of the array
elements will be set to the value in A(1)
.
Blitz always selects the traversal order it thinks will be fastest. For 1D arrays, this means it will go from beginning to the end of the array in memory (see notes below). For multidimensional arrays, it will do one of two things:
Because the traversal order is not always predictable, it is safest to put the result in a new array if you are doing a stencil-style expression. Blitz guarantees this will always work correctly. If you try to put the result in one of the operands, you have to guess correctly which traversal order blitz will choose. This is easy for the 1D case, but hard for the multidimensional case.
Some special notes about 1D array traversals:
An expression can contain any mix of these operands:
int
, float
, double
,
long double
, or complex<T>
A+(B+C)
)
Subarrays may be used in an expression. For example, this code example performs a 5-point average on a two-dimensional array:
Array<float,2> A(64,64), B(64,64); // ... Range I(1,62), J(1,62); A(I,J) = (B(I,J) + B(I+1,J) + B(I-1,J) + B(I,J+1) + B(I,J-1)) / 5;
Arrays with different storage formats (for example, C-style and Fortran-style) can be mixed in the same expression. Blitz++ will handle the different storage formats automatically. However:
These binary operators are supported:
+ - * / % > < >= <= == != && || ^ & |
Caution: operator <<
and >>
are reserved for use in input/output.
If you need a bit-shift operation on arrays, you may define one yourself;
see User et.
These unary operators are supported:
- ~ !
The operators > < >= <= == != && || !
result in a bool-valued
expression.
All operators are applied elementwise.
You can only use operators which are well-defined for the number type stored
in the arrays. For example, bitwise XOR (^
) is meaningful for
integers, so this code is all right:
Array<int,3> A, B, C; // ... A = B ^ C;
Bitwise XOR is not meaningful on floating point types, so this code will generate a compiler error:
Array<float,1> A, B, C; // ... C = B ^ C;
Here’s the compiler error generated by KAI C++ for the above code:
"../../blitz/ops.h", line 85: error: expression must have integral or enum type BZ_DEFINE_OP(BitwiseXor,^); ^ detected during: instantiation of "blitz::BitwiseXor<float, float>::T_numtype blitz::BitwiseXor<float, float>::apply(float, float)" at line 210 of "../../blitz/arrayexpr.h" instantiation of ... . .
If you are creating arrays using a type you have created yourself, you will
need to overload whatever operators you want to use on arrays. For example,
if I create a class Polynomial
, and want to write code such as:
Array<Polynomial,2> A, B, C; // ... C = A * B;
I would have to provide operator*
for Polynomial
by
implementing
Polynomial Polynomial::operator*(Polynomial);)
or
Polynomial operator*(Polynomial, Polynomial);)
These assignment operators are supported:
= += -= *= /= %= ^= &= |= >>= <<=
An array object should appear on the left side of the operator. The right side can be:
T_numtype
Next: Index placeholders, Up: Array Expressions [Contents][Index]