TooN Documentation

1.0.5

Introduction

The TooN library is a set of C++ header files which provide basic numerics facilities:

It provides classes for statically- (known at compile time) and dynamically- (unknown at compile time) sized vectors and matrices and it delegates advanced functions (like SVD or multiplication of large matrices) to LAPACK and BLAS (this means you will need libblas and liblapack).

The library makes substantial internal use of templates to achieve run-time speed efficiency whilst retaining a (reasonably) clear programming syntax. Because of this use of templates, you will need a recent compiler (for example it does not work with g++ before version 3.0). Programs that use it can also take a long time to compile with -O3 under g++. Currently the library only supports double precision vectors and matrices.

Why use this library?

(*) This is not always true (see Implementation, below)

How to get

The library can be obtained from savannah using anonymous cvs with the command:

cvs -z3 -d:pserver:anonymous@cvs.savannah.nongnu.org:/sources/toon co TooN

How to use

Compiler setup

Examples

Create two vectors and work out their inner (dot), outer and cross products
// Initialise the vectors
Vector<3> a;
a = 3,5,0;
Vector<3> b;
b = 4,1,3;
// Now work out the products
double dot = a*b;                            // Dot product
Matrix<3,3> outer = a.as_col() * b.as_row(); // Outer product
Vector<3> cross = a ^ b;                     // Cross product

cout << "a:" << endl << a << endl;
cout << "b:" << endl << b << endl;
cout << "Outer:" << endl << outer << endl;
cout << "Cross:" << endl << cross << endl;

Create a vector and a matrix and multiply the two together

// Initialise a vector
Vector<3> v;
v = 1,2,3;
// Initialise a matrix
double d[2][3] = {{2,4,5},{6,8,9}};
Matrix<2,3> M(d);
// Now perform calculations
Vector<2> v2 = M*v;  // OK - answer is a static 2D vector
Vector<> v3 = M*v;   // OK - vector is determined to be 2D at runtime
Vector<> v4 = v*M;   // Compile error - dimensions of matrix and vector incompatible

See the detailed documentation for Vector, Matrix and the various matrix decompositions for more examples.

Implementation

Static-sized vectors and matrices

One aspect that makes this library efficient is that when you declare a 3-vector, all you get are 3 doubles - there's no metadata. So sizeof(Vector<3>) is 24. This means that when you write Vector<3> v; the data for v is allocated on the stack and hence new/delete (malloc/free) overhead is avoided. However, for large vectors and matrices, this would be a Bad Thing since Vector<1000000> v; would result in an object of 8 megabytes being allocated on the stack. I don't know about you, but my whole stack is only that big. TooN gets around that problem by having a cutoff at which statically sized vectors are allocated on the heap. This is completely transparent to the programmer, the objects' behaviour is unchanged and you still get the type safety offered by statically sized vectors and matrices. The cutoff size at which the library changes the representation is defined in toon.h as the const int MaxStackSize in the class NUMERICS.

When you apply the subscript operator to a Matrix<3,3> and the function simply returns the apropriate hunk of memory as a vector reference (i.e. it basically does no work). This avoids copying and also allows the resulting vector to be used as an l-value. Similarly the transpose operation applied to a matrix returns the memory corresponding to the matrix as a reference to a matrix with the opposite layout which also means the transpose can be used as an l-value so M1 = M2.T(); and M1.T() = M2; do exactly the same thing.

Dynamic sized vectors and matrices

These are implemented in the obvious way using metadata with the rule that the object that allocated on the heap also deallocates. Other objects may reference the data (e.g. when you subscript a matrix and get a vector).

Return value optimisation vs Lazy evaluation

When you write v1 = M * v2; a naive implementation will compute M * v2 and store the result in a temporary object. It will then copy this temporary object into v1. A method often advanced to avoid this is to have M * v2 simply return an special object O which contains references to M and v2. When the compiler then resolves v1 = O, the special object computes M*v2 directly into v1. This approach is often called lazy evaluation and the special objects lazy vectors or lazy matrices. Stroustrup (The C++ programming language Chapter 22) refers to them as composition closure objects or compositors.

The killer is this: What if v1 is just another name for v2? i.e. you write something like v = M * v;. In this case the semantics have been broken because the values of v are being overwritten as the computation progresses and then the remainder of the computation is using the new values. In this library v1 in the expression could equally well alias part of M, thus you can't even solve the problem by having a clever check for aliasing between v1 and v2. This aliasing problem means that the only time the compiler can assume it's safe to omit the temporary is when v1 is being constructed (and thus cannot alias anything else) i.e. Vector<3> v1 = M * v2;.

TooN provides this optimisation by providing the compiler with the opportunity to use a return value optimisation. It does this by making M * v2 call a special constructor for Vector<3> with M and v2 as arguments. Since nothing is happening between the construction of the temporary and the copy construction of v1 from the temporary (which is then destroyed), the compiler is permitted to optimise the construction of the return value directly into v1.

Because a naive implemenation of this strategy would result in the vector and matrix classes having a very large number of constructors, these classes are provided with template constructors that take a standard form. The code that does this, declared in the header of class Vector is:

// constructor from 2-ary operator
template <class LHS, class RHS, class Op>
inline Vector(const LHS& lhs, const RHS& rhs, const Operator<Op>&){Op::eval(*this,lhs,rhs);}
The third argument of the constructor is a dummy, used to specify the construction method because you the standard doesn't allow you to supply template arguments when you call a constructor. Since the argument is unused, my compiler omits it (and I hope yours does too).

How it all really works

This documentation is generated from a cleaned-up version of the interface, hiding the implementation that allows all of the magic to work. If you want to know more and can understand idioms like:
template <int Size, class AllocZone>
class FixedVAccessor : public AllocZone {
   ...
};
and
template <int Size>
class Vector : public FixedVector<Size, FixedVAccessor<Size,typename SizeTraits<Size>::get_zone> > {
   ...
};
Then take a look at the source code ...
Generated on Mon Aug 18 17:16:26 2008 for TooN by  doxygen 1.4.7