5.1: Multicomponent and complex arrays |
Here are some examples of multicomponent arrays:
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:
The call to This is a little bit messy, so Blitz++ provides a handy shortcut
using 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
Array<TinyVector<float,3>,2> A(128,128);
Array<float,2> B = A.extractComponent(float(), 1, 3);
B = 0;
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.
operator[]
:
Array<TinyVector<float,3>,2> A(128,128);
A[1] = 0;
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:
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:
The function Note: Blitz++ provides numerous math functions defined
over complex-valued arrays, such as
Array<complex<float>,2> A(32,32);
real(A) = 1.0;
imag(A) = 0.0;
real(A)
returns an array view of the
real component; imag(A)
returns a view of the imaginary
component.
conj
, polar
, arg
, abs
, cos
, pow
, etc.
See the section on math functions
(3.8) for details.
5.1.3: Zipping together expressions |
Blitz++ provides a function The types The above line is equivalent to:
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
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>());
for (int i=0; i < N; ++i)
A[i] = complex<float>(cos(theta[i]), sin(theta[i]));
5.2: Creating arrays of a user type |
You can use the Array
class with types you have created yourself,
or types from another library. If you want to do arithmetic on the
array, whatever operators you use on the arrays have to be defined
on the underlying type.
For example, here's a simple class for doing fixed point computations in the interval [0,1]:
#include <blitz/numinquire.h> // for huge() class FixedPoint { public: // The type to use for the mantissa typedef unsigned int T_mantissa; FixedPoint() { } explicit FixedPoint(T_mantissa mantissa) { mantissa_ = mantissa; } FixedPoint(double value) { assert((value >= 0.0) && (value <= 1.0)); mantissa_ = value * huge(T_mantissa()); } FixedPoint operator+(FixedPoint x) { return FixedPoint(mantissa_ + x.mantissa_); } double value() const { return mantissa_ / double(huge(T_mantissa())); } private: T_mantissa mantissa_; }; ostream& operator<<(ostream& os, const FixedPoint& a) { os << a.value(); return os; } |
The function huge(T)
returns the largest representable value
for type T; in the example above, it's equal to UINT_MAX
.
The FixedPoint
class declares three useful operations: conversion
from double
, addition, and outputing to an ostream
. We can
use all of these operations on an Array<FixedPoint>
object:
#include <blitz/array.h> using namespace blitz; int main() { // Create an array using the FixedPoint class: Array<FixedPoint, 2> A(4,4), B(4,4); A = 0.5, 0.3, 0.8, 0.2, 0.1, 0.3, 0.2, 0.9, 0.0, 1.0, 0.7, 0.4, 0.2, 0.3, 0.8, 0.4; B = A + 0.05; cout << "B = " << B << endl; return 0; } |
Note that the array A
is initialized using a comma-delimited list
of double
; this makes use of the constructor FixedPoint(double)
.
The assignment B = A + 0.05
uses
FixedPoint::operator+(FixedPoint)
, with an implicit conversion
from double
to FixedPoint
. Formatting the array B
onto
the standard output stream is done using the output operator
defined for FixedPoint
.
Here's the program output:
B = 4 x 4 0.55 0.35 0.85 0.25 0.15 0.35 0.25 0.95 0.05 0.05 0.75 0.45 0.25 0.35 0.85 0.45 |