Next: , Up: Array Expressions   [Contents][Index]


3.1 Expression evaluation order

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:

3.2 Expression operands

An expression can contain any mix of these operands:

3.3 Array operands

Using subarrays in an expression

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;

Mixing arrays with different storage formats

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:

3.4 Expression operators

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);)

3.5 Assignment operators

These assignment operators are supported:

= += -= *= /= %= ^= &= |= >>= <<=

An array object should appear on the left side of the operator. The right side can be:


Next: , Up: Array Expressions   [Contents][Index]