/*
* $Id: usage.dox,v 1.14 2004/07/03 17:09:23 opetzold Exp $
*/
/**
\page usage Usage
Contents:
-# \ref include
-# \ref construct
-# \ref c_arrays
-# \ref compare
-# \ref pod
-# \ref stl
-# \ref matrix_access
-# \ref expr_print
\section include Include files
The Tiny %Vector and %Matrix template library has many include files spread
throughout the %tvmet include directory. As a user, you need only include
<%tvmet/Vector> for vector operations and/or
<%tvmet/Matrix> for matrix operations.
\par Example:
\code
#include
#include
using namespace tvmet;
\endcode
Simple, isn't it? Don't forget to use the namespace tvmet, but keep in mind
that using the using directive inside headers will pollute the namespace. If
you write this in a header file, the namespace for all subsequent header
files (those which include the one you're writing) will also be polluted.
(This is not a %tvmet specific phenomenon.) Therefore, write the using
statement in the C++ file.
\section construct Construction and Initializing
Due to the nature of
Expression Templates (ET) you can't write code like
\par Example:
\code
tvmet::Vector v1(1,2,3); // OK
tvmet::Vector v2 = v1; // not possible
\endcode
The operator= function assigns an expression to the Vector which means that
the object must be constructed before you may assign something to it. The
solution is to write this as:
\par Example:
\code
using namespace tvmet;
Vector v1(1,2,3);
Vector v2; // construct the Vector object at first
v2 = v1; // ... and assign the contents of v1 to v2
Vector v3(v1); // ... or simple use the copy constructor
std::cout << v3 << std::endl;
\endcode
since the object v2 needs to be constructed before the object's operator=()
can be called.
The same rule applies to the Matrix class. You can only assign vectors and
matrices of the same dimension or you will get a compile error. This also
applies to the argument list for the constructor of the classes.
Initializing can be done as shown above or by using a comma separated list:
\par Example:
\code
using namespace tvmet;
Matrix m1; // yes, non-square matrices are possible as well
m1 = 1, 4,
2, 5,
3, 6;
\endcode
Matrix element initialization always performed column wise! If the length
of the comma separated list is longer than the storage size, you will get
a compile time error. (tvmet is designed to prevent this -- it will prevent
you from accidentally overwriting memory which does not belong to the
matrix you are initializing.) You can use a comma separated list to
initialize vectors as well.
If you want a clean (zero-valued) vector or matrix you can simple write:
\par Example:
\code
using namespace tvmet;
Vector v4(0);
Matrix m2(0);
\endcode
All elements of v4 and m2 are initialized with zero (or whatever value you
provide at construction time). Keep in mind that the uninitialized %Matrix
and %Vector classes will have random data when the are created (since they
use a static array for internal storage) unless you initialize them!
Another way to initialize a vector or matrix follows:
\par Example:
\code
using namespace tvmet;
Vector v5(1,2,3);
Vector v6(v5);
Vector v7(v5+v6);
\endcode
This is useful for temporary results. The result will be immediately
assigned to the new vector elements using the expression passed to the
constructor.
Yet another way of initializing a vector or matrix is similar to the above.
We assign an expression to it:
\par Example:
\code
using namespace tvmet;
Matrix m3, m4, m5;
m3 = 1, 2, 3,
4, 5, 6,
7, 8, 9;
m4 = m3;
m5 = m3 + m4;
\endcode
If you have your data inside arrays you can use tvmet's iterator interface
to initialize a vector or matrix with it:
\par Example:
\code
T data[] = { 1,4,7,
2,5,8,
3,6,9 };
std::size_t sz = sizeof(data)/sizeof(T);
T* first = data;
T* last = data + sz;
tvmet::Matrix m(first, last);
\endcode
The data will be copied into the matrix itself. When the constructor has
finished, there will be no stored reference to the array pointer.
Starting with tvmet release 1.6.0 you can create an identity matrix
simply by using the function identity(). Note, we have to specify the
matrix type, since ADL can't work here.
\par Example:
\code
typedef Matrix matrix_type;
...
matrix_type E( identity() );
\endcode
\section c_arrays Use of C style Arrays with tvmet
Sometimes you have some data arranged in a C style array for matrices
and vectors. As with tvmet release 1.6.0 you can wrap an expression
around using the functions vector_ref(const T* mem) and
matrix_ref(const T* mem) where mem is the pointer to the C array.
The returned expressions (XprVector or XprMatrix) can be used
as usual like tvmet's vectors and matrices. This means, you
can use all mathematical functions on it.
\par Example:
\code
static float lhs[3][3] = {
{-1, 0, 1}, { 1, 0, 1}, {-1, 0, -1}
};
static float rhs[3][3] = {
{ 0, 1, 1}, { 0, 1, -1}, { 0, -1, 1}
};
...
typedef Matrix matrix_type;
matrix_type M( prod(matrix_ref(&lhs[0][0]),
matrix_ref(&rhs[0][0])) );
\endcode
This allows to initialize tvmet's vectors and matrices by
an alternative way as described at \ref construct.
\section compare Compare Vectors and Matrices
If you expect to find global comparison operators for comparing Vectors
and Matrices, you are right -- these are provided. But, the return
value probably isn't what you expect: a boolean value. Instead, the operator
returns an expression (e.g. XprVector<>). The contents of this expression
type is a element wise logical operation (depends on the given operator
like ==, <, >, etc...)! To get a boolean value you need to evaluate the
expression using all_elements() or any_elements(), as follows:
\par Example:
\code
using namespace tvmet;
using namespace std;
Vector v1, v2, bv;
v1 = 1,2,3;
v2 = 1,3,3;
bv = v1 == v2;
cout << bv << endl;
cout << "v1 == v2 is "
<< ( all_elements( v1 == v2 ) ? "true" : "false" )
<< endl;
\endcode
This gives
\par [continued]
\code
Vector[1, 0, 1]
v1 == v2 is false
\endcode
The reason for this is the element wise operation on all elements (for both
Vectors and Matrices). Comparing two vectors will result in a "boolean Vector"
expression. Using all_elements/any_elements evaluates the result into a
single boolean by repeatedly applying the comparison for each element.
An other example on comparing is shown below:
\par Example:
\code
if(all_elements(X == Y)) { cout << "matrices are identical" << endl; }
if(any_elements(X == Y)) { cout << "at least one element is equal" << endl; }
if(any_elements(X != Y)) { cout << "not all elements are equal" << endl; }
\endcode
%tvmet prior release 1.2.1 did have a boolean version eval for comparing.
The functional and semantic meaning were not clear at all. Therefore I
decided to remove it.
\sa \ref operators
\section pod Data Types like std::complex<>
As we can see above we can use POD (plain old data) types like double and
int as data type of a %Vector or %Matrix. However, we are not limited to
this - we can use e.g. std::complex<> as well:
\par Example:
\code
using namespace tvmet;
Vector,3> v1, v2;
Matrix,3,3> m1;
\endcode
And operate on these...
\par [continued]
\code
v1 = 1,2,3;
m1 = 1,4,7,
2,5,8,
3,6,9;
v2 = m1 * v1;
\endcode
Be careful. std::complex<> isn't tested well on regression tests.
\section stl STL support
Since version 0.2.0 %tvmet has supported an iterator interface conform to
the STL and since version 0.5.0 reverse STL iterators have been supported,
too.
With these, you can mix the %tvmet Vector and Matrix containers with the
STL algorithms.
For example, if you don't like %tvmet's ostream operator, you can create
your own implementation like this:
\par Example:
\code
tvmet::Vector v(1,2,3,4,5,6);
std::cout << v << std::endl;
std::cout << "The Vector is:" << std::endl;
std::copy(v.begin(), v.end(), std::ostream_iterator(std::cout, "\n"));
\endcode
Or, you create a random matrix and print it as shown here:
\par Example:
\code
tvmet::Matrix m;
std::generate(m.begin(), m.end(), rand);
std::cout << m << std::endl;
\endcode
\section matrix_access Matrix access by rows and columns
If you need a specific row or column of a given matrix you can get access to
it by using the functions row and col. They will return an XprVector.
Unfortunately, you do not get any write access to the vector elements - only
reading is permitted due to the expression template concept used here. For
write access, you have to use matrix indexing with the parentheses operator.
\par Example:
\code
using namespace tvmet;
typedef Matrix matrix_type;
typedef Vector matrix_rowvector;
typedef Vector matrix_colvector;
matrix_type M;
M = ....
matrix_rowvector row2 = row(M, 2);
matrix_colvector col3 = col(M, 3);
...
\endcode
\section expr_print Expression printing
Expression printing is a nice feature for debugging expressions. (For more
about expression templates and expression tree please have a look
here).
You can write out a simple matrix-vector multiplication of a vector
v1 and a matrix m1 of the dimension of 3 as follows:
\par Example:
\code
std::cout << m1 * v1 << std::endl;
\endcode
which will be expanded to:
\par [continued]
\code
XprVector<
XprMVProduct<
d, 3, 3, 3, 1, d, 1
>
3
>
\endcode
The "d" is a g++ placeholder for double. (This may vary from compiler to
compiler since it is an implementation detail of runtime type information
[rtti] determined by the compiler's manufacturer). The purpose of this
feature is to check the right evaluation of expressions into the tree on
complicated mathematical expressions.
A rich source of examples are the regression tests. They show all of the
supported operations and functions (if there is a regression test for this
of course). Some examples are in the examples directory.
*/
// Local Variables:
// mode:c++
// End: