A Valarray Tutorial

Any operation that works on the underlying type, also works on the valarray in the same way.

A valarray is simply an array of values. It is templated on its value type, so for example a stdext::valarray <float> is an array of floats and a stdext::valarray <long> is an array of long integers.

Before you start using valarrays, remember to #include <macvalarray.h> in your code to get the Altivec-optimized valarrays.

Construction

You can construct a valarray from a regular C array (or pointer):

float af1 [] = {0, 1, 2, 3};
stdext::valarray <float> vf1 (af1, 4); // construct from first 4 elements of a1

You can also construct a valarray with each element set to the same value:

stdext::valarray <float> vf1 (10, 3.0f); // construct with 10 repeats of 3.0f

Or you can construct a valarray with each element set to zero (really, the default-constructed value):

stdext::valarray <float> vf1 (10); // construct with 10 repeats of 0.0f

Accessing Elements

Once you’ve got a valarray, you can access it element by element, just like a regular C array:

float f1 = vf1 [0]; // set f1 to the zeroth element of v1
vf1 [0] = 2.0f; // set the zeroth element of v1 to 2.0f

But unlike their unsafe variants, a valarray knows its own size:

size_t len = vf1.size (); // set len to the size of v1

The valarray allows you to treat various subsets as if they were valarrays themselves.

Vector Operations

So far so good. But what’s really cool is that any operation that works on the underlying type, also works on the valarray in the same way. For example:

// do f1 = f2 * f3 + f4 for all the corresponding elements
vf1 = vf2 * vf3 + vf4;

That includes various transcendentals as well:

// do f1 = sin (f2) + cos (f3) for all the corresponding elements
vf1 = sin (vf2) + cos (vf3);

Mixing and matching with the underlying value type is possible too:

// do f1 = f2 * 2.0f - f3 for all the corresponding elements
vf1 = vf2 * 2.0f - vf3;

You can summarize the entire valarray using sum, min or max:

float f1 = vf1.sum (); // set f1 to the sum of all values
float f2 = vf1.min (); // set f2 to the minimum value
float f3 = vf1.max (); // set f3 to the maximum value

Subsetting

A powerful feature of the valarray allows you to treat various subsets of a valarray as if they were valarrays themselves. You use the different overloads of operator[] to do this.

For example, you can use a stdext::valarray <bool> as a mask: a value in the original array is selected if the corresponding value in the mask is true, or not selected if it is false:

bool b [] = {true, true, false, true, false, true};
stdext::valarray <bool> vb (b, 6);

// set v1 to elements 0, 1, 3 and 5 of v2
vf1 = vf2 [vb];

You can use a stdext::valarray <size_t> as an indirection: the original array is indexed by each value in the indirection, and that value is selected:

size_t l [] = {2, 4, 7, 8};
stdext::valarray <size_t> vl (sz, 4);

// set v1 to elements 2, 4, 7 and 8 of v2
vf1 = vf2 [vl];

A slice has a start index, a stride or increment in index and a length or count of indices to select. Slicing a valarray selects those elements in that sequence of indices.

// construct a slice start = 2, stride = 3 and length = 4
stdext::slice sl (2, 3, 4);

// set v1 to elements 2, 2+3, 2+3+3 and 2+3+3+3 of v2
vf1 = vf2 [sl];

Samples

With these building blocks, you can express some complicated concepts simply and succinctly.

For example, to calculate a dot product:

float f1 = (vf1 * vf2).sum ();

To select all the positive elements in a valarray:

stdext::valarray <float> vf1 = vf2 [vf2 >= 0.0f];
Mon, 29 Sep 2003. © Pixelglow Software.
» The Expression Express
Search
Download
Purchase
Discuss