mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
408 lines
11 KiB
Plaintext
408 lines
11 KiB
Plaintext
|
|
/*
|
||
|
|
* $Id: usage.dox,v 1.14 2004/07/03 17:09:23 opetzold Exp $
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
\page usage Usage
|
||
|
|
|
||
|
|
<p>Contents:</p>
|
||
|
|
-# \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
|
||
|
|
<tt><%tvmet/Vector></tt> for vector operations and/or
|
||
|
|
<tt><%tvmet/Matrix></tt> for matrix operations.
|
||
|
|
|
||
|
|
\par Example:
|
||
|
|
\code
|
||
|
|
#include <tvmet/Matrix.h>
|
||
|
|
#include <tvmet/Vector.h>
|
||
|
|
|
||
|
|
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
|
||
|
|
<a href=http://extreme.indiana.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html>
|
||
|
|
Expression Templates</a> (ET) you can't write code like
|
||
|
|
|
||
|
|
\par Example:
|
||
|
|
\code
|
||
|
|
tvmet::Vector<double, 3> v1(1,2,3); // OK
|
||
|
|
tvmet::Vector<double, 3> 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<double, 3> v1(1,2,3);
|
||
|
|
Vector<double, 3> v2; // construct the Vector<T,Sz> object at first
|
||
|
|
v2 = v1; // ... and assign the contents of v1 to v2
|
||
|
|
Vector<double, 3> 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<double, 3, 2> 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<double, 3> v4(0);
|
||
|
|
Matrix<double, 3, 4> 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<double, 3> v5(1,2,3);
|
||
|
|
Vector<double, 3> v6(v5);
|
||
|
|
Vector<double, 3> 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<double, 3, 3> 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<double, 3, 3> 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<double,3,3> matrix_type;
|
||
|
|
...
|
||
|
|
matrix_type E( identity<matrix_type>() );
|
||
|
|
\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<float, 3, 3> matrix_type;
|
||
|
|
|
||
|
|
matrix_type M( prod(matrix_ref<float, 3, 3>(&lhs[0][0]),
|
||
|
|
matrix_ref<float, 3, 3>(&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<double, 3> 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<d, 3>[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 <tt>double</tt> and
|
||
|
|
<tt>int</tt> as data type of a %Vector or %Matrix. However, we are not limited to
|
||
|
|
this - we can use e.g. <tt>std::complex<></tt> as well:
|
||
|
|
|
||
|
|
\par Example:
|
||
|
|
\code
|
||
|
|
using namespace tvmet;
|
||
|
|
|
||
|
|
Vector<std::complex<double>,3> v1, v2;
|
||
|
|
Matrix<std::complex<double>,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. <tt>std::complex<></tt> 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<double, 6> 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<double>(std::cout, "\n"));
|
||
|
|
\endcode
|
||
|
|
|
||
|
|
Or, you create a random matrix and print it as shown here:
|
||
|
|
|
||
|
|
\par Example:
|
||
|
|
\code
|
||
|
|
tvmet::Matrix<double,6,6> 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<T>.
|
||
|
|
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<double 5, 3> matrix_type;
|
||
|
|
typedef Vector<double, 5> matrix_rowvector;
|
||
|
|
typedef Vector<double, 3> 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
|
||
|
|
<a href=http://extreme.indiana.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html>here</a>).
|
||
|
|
|
||
|
|
You can write out a simple matrix-vector multiplication of a vector
|
||
|
|
<tt>v1</tt> and a matrix <tt>m1</tt> 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:
|