### 5.1 Multicomponent and complex arrays ¶

Multicomponent arrays have elements which are vectors. Examples of such arrays are vector fields, colour images (which contain, say, RGB tuples), and multispectral images. Complex-valued arrays can also be regarded as multicomponent arrays, since each element is a 2-tuple of real values.

Here are some examples of multicomponent arrays:

    // A 3-dimensional array; each element is a length 3 vector of float
    Array<TinyVector<float,3>,3> A;

    // A complex 2-dimensional array
    Array<complex<double>,2> B;

    // A 2-dimensional image containing RGB tuples
    struct RGB24 {
      unsigned char r, g, b;
    };

    Array<RGB24,2> C;

#### 5.1.1 Extracting components ¶

Blitz++ provides some special support for such arrays. The most important is the ability to extract a single component. For example:

    Array<TinyVector<float,3>,2> A(128,128);
    Array<float,2> B = A.extractComponent(float(), 1, 3);
    B = 0;

The call to `extractComponent` returns an array of floats; this array is a view of the second component of each element of A. The arguments of `extractComponent` are: (1) the type of the component (in this example, float); (2) the component number to extract (numbered 0, 1, ... N-1); and (3) the number of components in the array.

This is a little bit messy, so Blitz++ provides a handy shortcut using `operator[]`:

    Array<TinyVector<float,3>,2> A(128,128);
    A[1] = 0;

The number inside the square brackets is the component number. However, for this operation to work, Blitz++ has to already know how many components there are, and what type they are. It knows this already for `TinyVector` and `complex<T>`. If you use your own type, though, you will have to tell Blitz++ this information using the macro `BZ_DECLARE_MULTICOMPONENT_TYPE()`. This macro has three arguments:

    BZ_DECLARE_MULTICOMPONENT_TYPE(T_element, T_componentType, numComponents)

`T_element` is the element type of the array. `T_componentType` is the type of the components of that element. `numComponents` is the number of components in each element.

An example will clarify this. Suppose we wanted to make a colour image, stored in 24-bit HSV (hue-saturation-value) format. We can make a class `HSV24` which represents a single pixel:

    #include <blitz/array.h>

    using namespace blitz;

    class HSV24 {
    public:
        // These constants will makes the code below cleaner; we can
        // refer to the components by name, rather than number.

        static const int hue=0, saturation=1, value=2;

        HSV24() { }
        HSV24(int hue, int saturation, int value)
          : h_(hue), s_(saturation), v_(value)
        { }

        // Some other stuff here, obviously

    private:
        unsigned char h_, s_, v_;
    };

Right after the class declaration, we will invoke the macro `BZ_DECLARE_MULTICOMPONENT_TYPE` to tell Blitz++ about HSV24:

    // HSV24 has 3 components of type unsigned char
    BZ_DECLARE_MULTICOMPONENT_TYPE(HSV24, unsigned char, 3);

Now we can create HSV images and modify the individual components:

    int main()
    {
        Array<HSV24,2> A(128,128);   // A 128x128 HSV image
        ...

        // Extract a greyscale version of the image
        Array<unsigned char,2> A_greyscale = A[HSV24::value];

        // Bump up the saturation component to get a
        // pastel effect
        A[HSV24::saturation] *= 1.3;

        // Brighten up the middle of the image
        Range middle(32,96);
        A[HSV24::value](middle,middle) *= 1.2;
    }

#### 5.1.2 Special support for complex arrays ¶

Since complex arrays are used frequently, Blitz++ provides two special methods for getting the real and imaginary components:

    Array<complex<float>,2> A(32,32);

    real(A) = 1.0;
    imag(A) = 0.0;

The function `real(A)` returns an array view of the real component; `imag(A)` returns a view of the imaginary component.

Note: Blitz++ provides numerous math functions defined over complex-valued arrays, such as `conj`, `polar`, `arg`, `abs`, `cos`, `pow`, etc. See the section on math functions (Single-argument math functions) for details.

#### 5.1.3 Zipping together expressions ¶

Blitz++ provides a function `zip()` which lets you combine two or more expressions into a single component. For example, you can combine two real expressions into a complex expression, or three integer expressions into an HSV24 expression. The function has this syntax:

    resultexpr zip(expr1, expr2, T_element)
    resultexpr zip(expr1, expr2, expr3, T_element)         ** not available yet
    resultexpr zip(expr1, expr2, expr3, expr4, T_element)  ** not available yet

The types `resultexpr`, `expr1` and `expr2` are array expressions. The third argument is the type you want to create. For example:

    int N = 16;
    Array<complex<float>,1> A(N);
    Array<float,1> theta(N);

     ...

    A = zip(cos(theta), sin(theta), complex<float>());

The above line is equivalent to:

    for (int i=0; i < N; ++i)
       A[i] = complex<float>(cos(theta[i]), sin(theta[i]));