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


3.6 Index placeholders

Blitz++ provides objects called index placeholders which represent array indices. They can be used directly in expressions.

There is a distinct index placeholder type associated with each dimension of an array. The types are called firstIndex, secondIndex, thirdIndex, ..., tenthIndex, eleventhIndex. Here’s an example of using an index placeholder:

Array<float,1> A(10);
firstIndex i;
A = i;

This generates code which is similar to:

for (int i=0; i < A.length(); ++i)
    A(i) = i;

Here’s an example which fills an array with a sampled sine wave:

Array<float,1> A(16);
firstIndex i;

A = sin(2 * M_PI * i / 16.);

If your destination array has rank greater than 1, you may use multiple index placeholders:

// Fill a two-dimensional array with a radially
// symmetric, decaying sinusoid

// Create the array
int N = 64;           
Array<float,2> F(N,N);

// Some parameters
float midpoint = (N-1)/2.;
int cycles = 3;
float omega = 2.0 * M_PI * cycles / double(N);
float tau = - 10.0 / N;

// Index placeholders
firstIndex i;
secondIndex j;

// Fill the array
F = cos(omega * sqrt(pow2(i-midpoint) + pow2(j-midpoint)))
    * exp(tau * sqrt(pow2(i-midpoint) + pow2(j-midpoint)));

Here’s a plot of the resulting array:

sinsoid
Array filled using an index placeholder expression.

You can use index placeholder expressions in up to 11 dimensions. Here’s a three dimensional example:

// Fill a three-dimensional array with a Gaussian function
Array<float,3> A(16,16,16);
firstIndex i;
secondIndex j;
thirdIndex k;
float midpoint = 15/2.;
float c = - 1/3.0;
A = exp(c * (sqr(i-midpoint) + sqr(j-midpoint) 
    + sqr(k-midpoint)));

You can mix array operands and index placeholders:

Array<int,1> A(5), B(5);
firstIndex i;

A = 0, 1, 1, 0, 2;
B = i * A;          // Results in [ 0, 1, 2, 0, 8 ]

For your convenience, there is a namespace within blitz called tensor which declares all the index placeholders:

namespace blitz {
  namespace tensor {
    firstIndex i;
    secondIndex j;
    thirdIndex k;
     ...
    eleventhIndex t;
  }
}

So instead of declaring your own index placeholder objects, you can just say

namespace blitz::tensor;

when you would like to use them. Alternately, you can just preface all the index placeholders with tensor::, for example:

A = sin(2 * M_PI * tensor::i / 16.);

This will make your code more readable, since it is immediately clear that i is an index placeholder, rather than a scalar value.

3.7 Type promotion

When operands of different numeric types are used in an expression, the result gets promoted according to the usual C-style type promotion. For example, the result of adding an Array<int> to an Arrray<float> will be promoted to float. Generally, the result is promoted to whichever type has greater precision.

Type promotion for user-defined types

The rules for type promotion of user-defined types (or types from another library) are a bit complicated. Here’s how a pair of operand types are promoted:

If you wish to alter the default type promotion rules above, you have two choices:

Note that you can do these specializations in your own header files (you don’t have to edit promote.h or ops.h).

Manual casts

There are some inconvenient aspects of C-style type promotion. For example, when you divide two integers in C, the result gets truncated. The same problem occurs when dividing two integer arrays in Blitz++:

Array<int,1> A(4), B(4);
Array<float,1> C(4);

A = 1, 2, 3, 5;
B = 2, 2, 2, 7;

C = A / B;      // Result:  [ 0  1  1  0 ]

The usual solution to this problem is to cast one of the operands to a floating type. For this purpose, Blitz++ provides a function cast(expr,type) which will cast the result of expr as type:

C = A / cast(B, float());   // Result: [ 0.5  1  1.5  0.714 ]

The first argument to cast() is an array or expression. The second argument is a dummy object of the type to which you want to cast. Once compilers support templates more thoroughly, it will be possible to use this cast syntax:

C = A / cast<float>(B);

But this is not yet supported.


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