aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Eigen/CoreDeclarations1
-rw-r--r--Eigen/src/Core/CacheFriendlyProduct.h7
-rw-r--r--Eigen/src/Core/MatrixBase.h2
-rw-r--r--Eigen/src/Core/util/Macros.h13
-rw-r--r--Eigen/src/Core/util/Meta.h177
-rw-r--r--Eigen/src/Core/util/XprHelper.h160
-rw-r--r--doc/CustomizingEigen.dox77
-rw-r--r--doc/QuickStartGuide.dox55
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/meta.cpp71
10 files changed, 397 insertions, 167 deletions
diff --git a/Eigen/CoreDeclarations b/Eigen/CoreDeclarations
index 4c85b6d65..6e5fb2d9e 100644
--- a/Eigen/CoreDeclarations
+++ b/Eigen/CoreDeclarations
@@ -47,6 +47,7 @@ namespace Eigen {
#include "src/Core/util/Constants.h"
#include "src/Core/util/ForwardDeclarations.h"
#include "src/Core/util/Meta.h"
+#include "src/Core/util/XprHelper.h"
#include "src/Core/util/StaticAssert.h"
} // namespace Eigen
diff --git a/Eigen/src/Core/CacheFriendlyProduct.h b/Eigen/src/Core/CacheFriendlyProduct.h
index a4cce99bf..051477cad 100644
--- a/Eigen/src/Core/CacheFriendlyProduct.h
+++ b/Eigen/src/Core/CacheFriendlyProduct.h
@@ -25,6 +25,11 @@
#ifndef EIGEN_CACHE_FRIENDLY_PRODUCT_H
#define EIGEN_CACHE_FRIENDLY_PRODUCT_H
+template <int L2MemorySize,typename Scalar>
+struct ei_L2_block_traits {
+ enum {width = ei_meta_sqrt<L2MemorySize/(64*sizeof(Scalar))>::ret };
+};
+
#ifndef EIGEN_EXTERN_INSTANTIATIONS
template<typename Scalar>
@@ -76,7 +81,7 @@ static void ei_cache_friendly_product(
MaxBlockRows_ClampingMask = 0xFFFFF8,
#endif
// maximal size of the blocks fitted in L2 cache
- MaxL2BlockSize = EIGEN_TUNE_FOR_L2_CACHE_SIZE / sizeof(Scalar)
+ MaxL2BlockSize = ei_L2_block_traits<EIGEN_TUNE_FOR_L2_CACHE_SIZE,Scalar>::width
};
const bool resIsAligned = (PacketSize==1) || (((resStride%PacketSize) == 0) && (size_t(res)%16==0));
diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h
index a36376bfd..c563466b4 100644
--- a/Eigen/src/Core/MatrixBase.h
+++ b/Eigen/src/Core/MatrixBase.h
@@ -569,8 +569,6 @@ template<typename Derived> class MatrixBase
EvalType cross(const MatrixBase<OtherDerived>& other) const;
EvalType someOrthogonal(void) const;
- /**
- */
#ifdef EIGEN_MATRIXBASE_PLUGIN
#include EIGEN_MATRIXBASE_PLUGIN
#endif
diff --git a/Eigen/src/Core/util/Macros.h b/Eigen/src/Core/util/Macros.h
index 29ac98b1f..ae2041875 100644
--- a/Eigen/src/Core/util/Macros.h
+++ b/Eigen/src/Core/util/Macros.h
@@ -28,20 +28,15 @@
#undef minor
-#ifdef EIGEN_DONT_USE_UNROLLED_LOOPS
-#define EIGEN_UNROLLING_LIMIT 0
-#endif
-
-/** Defines the maximal loop size to enable meta unrolling of loops */
+/** \internal Defines the maximal loop size to enable meta unrolling of loops */
#ifndef EIGEN_UNROLLING_LIMIT
#define EIGEN_UNROLLING_LIMIT 100
#endif
-/** Define a hint size when dealing with large matrices and L2 cache friendlyness
- * More precisely, its square value represents the amount of bytes which can be assumed to stay in L2 cache.
- */
+/** \internal Define the maximal size in Bytes of L2 blocks.
+ * The current value is set to generate blocks of 256x256 for float */
#ifndef EIGEN_TUNE_FOR_L2_CACHE_SIZE
-#define EIGEN_TUNE_FOR_L2_CACHE_SIZE 1024
+#define EIGEN_TUNE_FOR_L2_CACHE_SIZE (1024*256)
#endif
#define USING_PART_OF_NAMESPACE_EIGEN \
diff --git a/Eigen/src/Core/util/Meta.h b/Eigen/src/Core/util/Meta.h
index a937819fb..97e455d83 100644
--- a/Eigen/src/Core/util/Meta.h
+++ b/Eigen/src/Core/util/Meta.h
@@ -26,40 +26,15 @@
#ifndef EIGEN_META_H
#define EIGEN_META_H
-// just a workaround because GCC seems to not really like empty structs
-#ifdef __GNUG__
- struct ei_empty_struct{char _ei_dummy_;};
- #define EIGEN_EMPTY_STRUCT : Eigen::ei_empty_struct
-#else
- #define EIGEN_EMPTY_STRUCT
-#endif
-
-//classes inheriting ei_no_assignment_operator don't generate a default operator=.
-class ei_no_assignment_operator
-{
- private:
- ei_no_assignment_operator& operator=(const ei_no_assignment_operator&);
-};
-
-template<int Value> class ei_int_if_dynamic EIGEN_EMPTY_STRUCT
-{
- public:
- ei_int_if_dynamic() {}
- explicit ei_int_if_dynamic(int) {}
- static int value() { return Value; }
- void setValue(int) {}
-};
-
-template<> class ei_int_if_dynamic<Dynamic>
-{
- int m_value;
- ei_int_if_dynamic() {}
- public:
- explicit ei_int_if_dynamic(int value) : m_value(value) {}
- int value() const { return m_value; }
- void setValue(int value) { m_value = value; }
-};
+/** \internal
+ * \file Meta.h
+ * This file contains generic metaprogramming classes which are not specifically related to Eigen.
+ * \note In case you wonder, yes we're aware that Boost already provides all these features,
+ * we however don't want to add a dependency to Boost.
+ */
+struct ei_meta_true { enum { ret = 1 }; };
+struct ei_meta_false { enum { ret = 0 }; };
template<bool Condition, typename Then, typename Else>
struct ei_meta_if { typedef Then ret; };
@@ -70,8 +45,23 @@ struct ei_meta_if <false, Then, Else> { typedef Else ret; };
template<typename T, typename U> struct ei_is_same_type { enum { ret = 0 }; };
template<typename T> struct ei_is_same_type<T,T> { enum { ret = 1 }; };
-struct ei_meta_true {};
-struct ei_meta_false {};
+template<typename T> struct ei_unref { typedef T type; };
+template<typename T> struct ei_unref<T&> { typedef T type; };
+
+template<typename T> struct ei_unpointer { typedef T type; };
+template<typename T> struct ei_unpointer<T*> { typedef T type; };
+template<typename T> struct ei_unpointer<T*const> { typedef T type; };
+
+template<typename T> struct ei_unconst { typedef T type; };
+template<typename T> struct ei_unconst<const T> { typedef T type; };
+template<typename T> struct ei_unconst<const T&> { typedef T& type; };
+
+template<typename T> struct ei_cleantype { typedef T type; };
+template<typename T> struct ei_cleantype<const T> { typedef typename ei_cleantype<T>::type type; };
+template<typename T> struct ei_cleantype<const T&> { typedef typename ei_cleantype<T>::type type; };
+template<typename T> struct ei_cleantype<T&> { typedef typename ei_cleantype<T>::type type; };
+template<typename T> struct ei_cleantype<const T*> { typedef typename ei_cleantype<T>::type type; };
+template<typename T> struct ei_cleantype<T*> { typedef typename ei_cleantype<T>::type type; };
/** \internal
* Convenient struct to get the result type of a unary or binary functor.
@@ -132,113 +122,26 @@ struct ei_result_of<Func(ArgType0,ArgType1)> {
typedef typename ei_binary_result_of_select<Func, ArgType0, ArgType1, FunctorType>::type type;
};
-template<typename T> struct ei_functor_traits
-{
- enum
- {
- Cost = 10,
- PacketAccess = false
- };
-};
-
-template<typename T> struct ei_packet_traits
-{
- typedef T type;
- enum {size=1};
-};
-
-template<typename T> struct ei_unpacket_traits
-{
- typedef T type;
- enum {size=1};
-};
-
-
-template<typename Scalar, int Rows, int Cols, int StorageOrder, int MaxRows, int MaxCols>
-class ei_compute_matrix_flags
+/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
+ * Usage example: \code ei_meta_sqrt<1023>::ret \endcode
+ */
+template<int Y,
+ int InfX = 0,
+ int SupX = (Y==1 ? 1 : Y/2),
+ bool Done = (((SupX-InfX)<=1) || ( (SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
+class ei_meta_sqrt
{
enum {
- row_major_bit = (Rows != 1 && Cols != 1) // if this is not a vector,
- // then the storage order really matters,
- // so let us strictly honor the user's choice.
- ? StorageOrder
- : Cols > 1 ? RowMajorBit : 0,
- inner_max_size = row_major_bit ? MaxCols : MaxRows,
- is_big = inner_max_size == Dynamic,
- is_packet_size_multiple = (Cols * Rows)%ei_packet_traits<Scalar>::size==0,
- packet_access_bit = ei_packet_traits<Scalar>::size > 1
- && (is_big || is_packet_size_multiple) ? PacketAccessBit : 0,
- aligned_bit = packet_access_bit && (is_big || is_packet_size_multiple) ? AlignedBit : 0
+ MidX = (InfX+SupX)/2,
+ TakeInf = MidX*MidX > Y,
+ NewInf = TakeInf ? InfX : MidX,
+ NewSup = TakeInf ? MidX : SupX
};
-
public:
- enum { ret = LinearAccessBit | DirectAccessBit | packet_access_bit | row_major_bit | aligned_bit };
-};
-
-template<int _Rows, int _Cols> struct ei_size_at_compile_time
-{
- enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
-};
-
-template<typename T, int Sparseness = ei_traits<T>::Flags&SparseBit> class ei_eval;
-
-template<typename T> struct ei_eval<T,Dense>
-{
- typedef Matrix<typename ei_traits<T>::Scalar,
- ei_traits<T>::RowsAtCompileTime,
- ei_traits<T>::ColsAtCompileTime,
- ei_traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor,
- ei_traits<T>::MaxRowsAtCompileTime,
- ei_traits<T>::MaxColsAtCompileTime
- > type;
-};
-
-template<typename T> struct ei_unref { typedef T type; };
-template<typename T> struct ei_unref<T&> { typedef T type; };
-
-template<typename T> struct ei_unconst { typedef T type; };
-template<typename T> struct ei_unconst<const T> { typedef T type; };
-
-template<typename T> struct ei_cleantype { typedef T type; };
-template<typename T> struct ei_cleantype<const T> { typedef T type; };
-template<typename T> struct ei_cleantype<const T&> { typedef T type; };
-template<typename T> struct ei_cleantype<T&> { typedef T type; };
-
-template<typename T> struct ei_must_nest_by_value { enum { ret = false }; };
-template<typename T> struct ei_must_nest_by_value<NestByValue<T> > { enum { ret = true }; };
-
-
-template<typename T, int n=1, typename EvalType = typename ei_eval<T>::type> struct ei_nested
-{
- enum {
- CostEval = (n+1) * int(NumTraits<typename ei_traits<T>::Scalar>::ReadCost),
- CostNoEval = (n-1) * int(ei_traits<T>::CoeffReadCost)
- };
- typedef typename ei_meta_if<
- ei_must_nest_by_value<T>::ret,
- T,
- typename ei_meta_if<
- (int(ei_traits<T>::Flags) & EvalBeforeNestingBit)
- || ( int(CostEval) <= int(CostNoEval) ),
- EvalType,
- const T&
- >::ret
- >::ret type;
+ enum { ret = ei_meta_sqrt<Y,NewInf,NewSup>::ret };
};
-template<unsigned int Flags> struct ei_are_flags_consistent
-{
- enum { ret = !( (Flags&UnitDiagBit && Flags&ZeroDiagBit) )
- };
-};
-
-/** \internal Gives the type of a sub-matrix or sub-vector of a matrix of type \a ExpressionType and size \a Size
- * TODO: could be a good idea to define a big ReturnType struct ??
- */
-template<typename ExpressionType, int RowsOrSize=Dynamic, int Cols=Dynamic> struct BlockReturnType {
- typedef Block<ExpressionType, (ei_traits<ExpressionType>::RowsAtCompileTime == 1 ? 1 : RowsOrSize),
- (ei_traits<ExpressionType>::ColsAtCompileTime == 1 ? 1 : RowsOrSize)> SubVectorType;
- typedef Block<ExpressionType, RowsOrSize, Cols> Type;
-};
+template<int Y, int InfX, int SupX>
+class ei_meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
#endif // EIGEN_META_H
diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h
new file mode 100644
index 000000000..225100118
--- /dev/null
+++ b/Eigen/src/Core/util/XprHelper.h
@@ -0,0 +1,160 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_XPRHELPER_H
+#define EIGEN_XPRHELPER_H
+
+// just a workaround because GCC seems to not really like empty structs
+#ifdef __GNUG__
+ struct ei_empty_struct{char _ei_dummy_;};
+ #define EIGEN_EMPTY_STRUCT : Eigen::ei_empty_struct
+#else
+ #define EIGEN_EMPTY_STRUCT
+#endif
+
+//classes inheriting ei_no_assignment_operator don't generate a default operator=.
+class ei_no_assignment_operator
+{
+ private:
+ ei_no_assignment_operator& operator=(const ei_no_assignment_operator&);
+};
+
+template<int Value> class ei_int_if_dynamic EIGEN_EMPTY_STRUCT
+{
+ public:
+ ei_int_if_dynamic() {}
+ explicit ei_int_if_dynamic(int) {}
+ static int value() { return Value; }
+ void setValue(int) {}
+};
+
+template<> class ei_int_if_dynamic<Dynamic>
+{
+ int m_value;
+ ei_int_if_dynamic() {}
+ public:
+ explicit ei_int_if_dynamic(int value) : m_value(value) {}
+ int value() const { return m_value; }
+ void setValue(int value) { m_value = value; }
+};
+
+template<typename T> struct ei_functor_traits
+{
+ enum
+ {
+ Cost = 10,
+ PacketAccess = false
+ };
+};
+
+template<typename T> struct ei_packet_traits
+{
+ typedef T type;
+ enum {size=1};
+};
+
+template<typename T> struct ei_unpacket_traits
+{
+ typedef T type;
+ enum {size=1};
+};
+
+
+template<typename Scalar, int Rows, int Cols, int StorageOrder, int MaxRows, int MaxCols>
+class ei_compute_matrix_flags
+{
+ enum {
+ row_major_bit = (Rows != 1 && Cols != 1) // if this is not a vector,
+ // then the storage order really matters,
+ // so let us strictly honor the user's choice.
+ ? StorageOrder
+ : Cols > 1 ? RowMajorBit : 0,
+ inner_max_size = row_major_bit ? MaxCols : MaxRows,
+ is_big = inner_max_size == Dynamic,
+ is_packet_size_multiple = (Cols * Rows)%ei_packet_traits<Scalar>::size==0,
+ packet_access_bit = ei_packet_traits<Scalar>::size > 1
+ && (is_big || is_packet_size_multiple) ? PacketAccessBit : 0,
+ aligned_bit = packet_access_bit && (is_big || is_packet_size_multiple) ? AlignedBit : 0
+ };
+
+ public:
+ enum { ret = LinearAccessBit | DirectAccessBit | packet_access_bit | row_major_bit | aligned_bit };
+};
+
+template<int _Rows, int _Cols> struct ei_size_at_compile_time
+{
+ enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
+};
+
+template<typename T, int Sparseness = ei_traits<T>::Flags&SparseBit> class ei_eval;
+
+template<typename T> struct ei_eval<T,Dense>
+{
+ typedef Matrix<typename ei_traits<T>::Scalar,
+ ei_traits<T>::RowsAtCompileTime,
+ ei_traits<T>::ColsAtCompileTime,
+ ei_traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor,
+ ei_traits<T>::MaxRowsAtCompileTime,
+ ei_traits<T>::MaxColsAtCompileTime
+ > type;
+};
+
+template<typename T> struct ei_must_nest_by_value { enum { ret = false }; };
+template<typename T> struct ei_must_nest_by_value<NestByValue<T> > { enum { ret = true }; };
+
+template<typename T, int n=1, typename EvalType = typename ei_eval<T>::type> struct ei_nested
+{
+ enum {
+ CostEval = (n+1) * int(NumTraits<typename ei_traits<T>::Scalar>::ReadCost),
+ CostNoEval = (n-1) * int(ei_traits<T>::CoeffReadCost)
+ };
+ typedef typename ei_meta_if<
+ ei_must_nest_by_value<T>::ret,
+ T,
+ typename ei_meta_if<
+ (int(ei_traits<T>::Flags) & EvalBeforeNestingBit)
+ || ( int(CostEval) <= int(CostNoEval) ),
+ EvalType,
+ const T&
+ >::ret
+ >::ret type;
+};
+
+template<unsigned int Flags> struct ei_are_flags_consistent
+{
+ enum { ret = !( (Flags&UnitDiagBit && Flags&ZeroDiagBit) )
+ };
+};
+
+/** \internal Gives the type of a sub-matrix or sub-vector of a matrix of type \a ExpressionType and size \a Size
+ * TODO: could be a good idea to define a big ReturnType struct ??
+ */
+template<typename ExpressionType, int RowsOrSize=Dynamic, int Cols=Dynamic> struct BlockReturnType {
+ typedef Block<ExpressionType, (ei_traits<ExpressionType>::RowsAtCompileTime == 1 ? 1 : RowsOrSize),
+ (ei_traits<ExpressionType>::ColsAtCompileTime == 1 ? 1 : RowsOrSize)> SubVectorType;
+ typedef Block<ExpressionType, RowsOrSize, Cols> Type;
+};
+
+#endif // EIGEN_XPRHELPER_H
diff --git a/doc/CustomizingEigen.dox b/doc/CustomizingEigen.dox
new file mode 100644
index 000000000..74108c999
--- /dev/null
+++ b/doc/CustomizingEigen.dox
@@ -0,0 +1,77 @@
+namespace Eigen {
+
+/** \page CustomizingEigen
+
+<h1>Customizing Eigen</h1>
+
+Eigen2 can be extended in several way, for instance, by defining global methods, \link ExtendingMatrixBase by adding custom methods to MatrixBase \endlink, etc.
+
+\section ExtendingMatrixBase Extending MatrixBase
+
+In this section we will see how to add custom methods to MatrixBase. Since all expressions and matrix types inherit MatrixBase, adding a method to MatrixBase make it immediately available to all expressions ! A typical use case is, for instance, to make Eigen compatible with another API.
+
+You certainly know that in C++ it is not possible to add methods to an extending class. So how that's possible ? Here the trick is to include in the declaration of MatrixBase a file defined by the preprocessor token \c EIGEN_MATRIXBASE_PLUGIN:
+\code
+class MatrixBase {
+ // ...
+ #ifdef EIGEN_MATRIXBASE_PLUGIN
+ #include EIGEN_MATRIXBASE_PLUGIN
+ #endif
+};
+\endcode
+Therefore to extend MatrixBase with you own methods you just have to create a file with your method declaration and define EIGEN_MATRIXBASE_PLUGIN before you include any Eigen's header file.
+
+Here is an example of such an extension file: \n
+\b MatrixBaseAddons.h
+\code
+inline Scalar at(uint i, uint j) const { return this->operator()(i,j); }
+inline Scalar& at(uint i, uint j) { return this->operator()(i,j); }
+inline Scalar at(uint i) const { return this->operator[](i); }
+inline Scalar& at(uint i) { return this->operator[](i); }
+
+inline RealScalar squaredLength() const { return norm2(); }
+inline RealScalar length() const { return norm(); }
+inline RealScalar invLength(void) const { return fast_inv_sqrt(norm2()); }
+
+template<typename OtherDerived>
+inline Scalar squaredDistanceTo(const MatrixBase<OtherDerived>& other) const
+{ return (derived() - other.derived()).norm2(); }
+
+template<typename OtherDerived>
+inline RealScalar distanceTo(const MatrixBase<OtherDerived>& other) const
+{ return ei_sqrt(derived().squaredDistanceTo(other)); }
+
+inline void scaleTo(RealScalar l) { RealScalar vl = norm(); if (vl>1e-9) derived() *= (l/vl); }
+
+inline Transpose<Derived> transposed() {return transpose();}
+inline const Transpose<Derived> transposed() const {return transpose();}
+
+inline uint minComponentId(void) const { int i; minCoeff(&i); return i; }
+inline uint maxComponentId(void) const { int i; maxCoeff(&i); return i; }
+
+template<typename OtherDerived>
+void makeFloor(const MatrixBase<OtherDerived>& other) { derived() = derived().cwise().min(other.derived()); }
+template<typename OtherDerived>
+void makeCeil(const MatrixBase<OtherDerived>& other) { derived() = derived().cwise().max(other.derived()); }
+
+const typename Cwise<Derived>::ScalarAddReturnType
+operator+(const Scalar& scalar) const { return cwise() + scalar }
+
+friend const typename Cwise<Derived>::ScalarAddReturnType
+operator+(const Scalar& scalar, const MatrixBase<Derived>& mat) { return mat + scalar; }
+\endcode
+
+Then one can the following declaration in the config.h or whatever prerequisites header file of his project:
+\code
+#define EIGEN_MATRIXBASE_PLUGIN "MatrixBaseAddons.h"
+\endcode
+
+\section PreprocessorDirectives Preprocessor directives
+
+ - \b EIGEN_DONT_VECTORIZE disables explicit vectorization when defined.
+ - \b EIGEN_UNROLLING_LIMIT defines the maximal instruction counts to enable meta unrolling of loops. Set it to zero to disable unrolling. The default is 100.
+ - \b EIGEN_TUNE_FOR_L2_CACHE_SIZE represents the maximal size in Bytes of L2 blocks. Since several blocks have to stay concurently in L2 cache, this value should correspond to at most 1/4 of the size of L2 cache.
+
+*/
+
+}
diff --git a/doc/QuickStartGuide.dox b/doc/QuickStartGuide.dox
index 86405a705..aa505b91d 100644
--- a/doc/QuickStartGuide.dox
+++ b/doc/QuickStartGuide.dox
@@ -4,7 +4,25 @@ namespace Eigen {
<h1>Quick start guide</h1>
-<h2>Simple example with fixed-size matrices and vectors</h2>
+\b Table \b of \b contents
+ - \ref SimpleExampleFixedSize
+ - \ref SimpleExampleDynamicSize
+ - \ref MatrixTypes
+ - \ref MatrixInitialization
+ - \ref BasicLinearAlgebra
+ - \ref Reductions
+ - \ref SubMatrix
+ - \ref MatrixTransformations
+ - \ref Geometry
+ - \ref Performance
+ - \ref AdvancedLinearAlgebra
+ - \ref LinearSolvers
+ - \ref LU
+ - \ref Cholesky
+ - \ref QR
+ - \ref EigenProblems
+
+\section SimpleExampleFixedSize Simple example with fixed-size matrices and vectors
By fixed-size, we mean that the number of rows and columns are known at compile-time. In this case, Eigen avoids dynamic memory allocation and unroll loops. This is useful for very small sizes (typically up to 4x4).
@@ -16,7 +34,7 @@ output:
\include Tutorial_simple_example_fixed_size.out
</td></tr></table>
-<h2>Simple example with dynamic-size matrices and vectors</h2>
+\section SimpleExampleDynamicSize Simple example with dynamic-size matrices and vectors
Dynamic-size means that the number of rows and columns are not known at compile-time. In this case, they are stored as runtime variables and the arrays are dynamically allocated.
@@ -28,7 +46,7 @@ output:
\include Tutorial_simple_example_dynamic_size.out
</td></tr></table>
-<h2>Matrix and vector types</h2>
+\section MatrixTypes Matrix and vector types
In Eigen, all kinds of dense matrices and vectors are represented by the template class Matrix. In most cases you can simply use one of the several convenient typedefs (\ref matrixtypedefs).
@@ -39,11 +57,11 @@ The template class Matrix takes a number of template parameters, but for now it
\li \c Scalar is the scalar type, i.e. the type of the coefficients. That is, if you want a vector of floats, choose \c float here.
\li \c RowsAtCompileTime and \c ColsAtCompileTime are the number of rows and columns of the matrix as known at compile-time.
-For example, \c Vector3d is a typedef for \code Matrix<double, 3, 1> \endcode.
+For example, \c Vector3d is a typedef for \code Matrix<double, 3, 1> \endcode
-What if the matrix has dynamic-size i.e. the number of rows or cols isn't known at compile-time? Then use the special value Eigen::Dynamic. For example, \c VectorXd is a typedef for \code Matrix<double, Dynamic, 1> \endcode.
+What if the matrix has dynamic-size i.e. the number of rows or cols isn't known at compile-time? Then use the special value Eigen::Dynamic. For example, \c VectorXd is a typedef for \code Matrix<double, Dynamic, 1> \endcode
-<h2>Matrix and vector creation and initialization</h2>
+\section MatrixInitialization Matrix and vector creation and initialization
To get a matrix with all coefficients equals to a given value you can use the Matrix::Constant() function, e.g.:
<table><tr><td>
@@ -151,7 +169,7 @@ Here .finished() is used to get the actual matrix object once the comma initiali
of our temporary submatrix is done. Note that despite the appearant complexity of such an expression
Eigen's comma initializer usually yields to very optimized code without any overhead.
-<h2>Basic Linear Algebra</h2>
+\section BasicLinearAlgebra Basic Linear Algebra
In short all mathematically well defined operators can be used right away as in the following example:
\code
@@ -249,7 +267,7 @@ mat3 = mat1.cwise().abs2(mat2);
\endcode</td></tr>
</table>
-<h2>Reductions</h2>
+\section Reductions Reductions
Reductions can be done matrix-wise,
\link MatrixBase::colwise() column-wise \endlink or
@@ -285,7 +303,7 @@ The all() and any() functions are especially useful in combinaison with coeff-wi
-<h2>Sub matrices</h2>
+\section SubMatrix Sub matrices
Read-write access to a \link MatrixBase::col(int) column \endlink
or a \link MatrixBase::row(int) row \endlink of a matrix:
@@ -336,24 +354,25 @@ Read-write access to sub-matrices:
</table>
-<h2>Transformations</h2>
+\section MatrixTransformations Matrix transformations
transpose, adjoint, etc...
-<h2>Geometry features</h2>
+\section Geometry Geometry features
+maybe a second tutorial for that
-<h2>Notes on performances</h2>
+\section Performance Notes on performances
-<h2>Advanced Linear Algebra</h2>
+\section AdvancedLinearAlgebra Advanced Linear Algebra
-<h3>Solving linear problems</h3>
-<h3>LU</h3>
-<h3>Cholesky</h3>
-<h3>QR</h3>
-<h3>Eigen value problems</h3>
+\subsection LinearSolvers Solving linear problems
+\subsection LU LU
+\subsection Cholesky Cholesky
+\subsection QR QR
+\subsection EigenProblems Eigen value problems
*/
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 8964ef75d..c81876596 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -92,6 +92,7 @@ IF(TEST_LIB)
ADD_DEFINITIONS("-DEIGEN_EXTERN_INSTANTIATIONS=1")
ENDIF(TEST_LIB)
+EI_ADD_TEST(meta)
EI_ADD_TEST(sizeof)
EI_ADD_TEST(nomalloc)
EI_ADD_TEST(packetmath)
diff --git a/test/meta.cpp b/test/meta.cpp
new file mode 100644
index 000000000..21cb522be
--- /dev/null
+++ b/test/meta.cpp
@@ -0,0 +1,71 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#include "main.h"
+
+void test_meta()
+{
+ VERIFY((ei_meta_if<(3<4),ei_meta_true, ei_meta_false>::ret::ret));
+ VERIFY(( ei_is_same_type<float,float>::ret));
+ VERIFY((!ei_is_same_type<float,double>::ret));
+ VERIFY((!ei_is_same_type<float,float&>::ret));
+ VERIFY((!ei_is_same_type<float,const float&>::ret));
+
+ VERIFY(( ei_is_same_type<float,ei_cleantype<const float&>::type >::ret));
+ VERIFY(( ei_is_same_type<float,ei_cleantype<const float*>::type >::ret));
+ VERIFY(( ei_is_same_type<float,ei_cleantype<const float*&>::type >::ret));
+ VERIFY(( ei_is_same_type<float,ei_cleantype<float**>::type >::ret));
+ VERIFY(( ei_is_same_type<float,ei_cleantype<float**&>::type >::ret));
+ VERIFY(( ei_is_same_type<float,ei_cleantype<float* const *&>::type >::ret));
+ VERIFY(( ei_is_same_type<float,ei_cleantype<float* const>::type >::ret));
+
+ VERIFY(( ei_is_same_type<float&,ei_unconst<const float&>::type >::ret));
+ VERIFY(( ei_is_same_type<float&,ei_unconst<float&>::type >::ret));
+ VERIFY(( ei_is_same_type<float,ei_unref<float&>::type >::ret));
+ VERIFY(( ei_is_same_type<const float,ei_unref<const float&>::type >::ret));
+ VERIFY(( ei_is_same_type<float,ei_unpointer<float*>::type >::ret));
+ VERIFY(( ei_is_same_type<const float,ei_unpointer<const float*>::type >::ret));
+ VERIFY(( ei_is_same_type<float,ei_unpointer<float* const >::type >::ret));
+
+ VERIFY(ei_meta_sqrt<1>::ret == 1);
+ #define VERIFY_META_SQRT(X) \
+ std::cerr << ei_meta_sqrt<X>::ret << " == " << int(ei_sqrt(double(X))) << "\n"; \
+ VERIFY(ei_meta_sqrt<X>::ret == int(ei_sqrt(double(X))))
+ VERIFY_META_SQRT(2);
+ VERIFY_META_SQRT(3);
+ VERIFY_META_SQRT(4);
+ VERIFY_META_SQRT(5);
+ VERIFY_META_SQRT(6);
+ VERIFY_META_SQRT(8);
+ VERIFY_META_SQRT(9);
+ VERIFY_META_SQRT(15);
+ VERIFY_META_SQRT(16);
+ VERIFY_META_SQRT(17);
+ VERIFY_META_SQRT(255);
+ VERIFY_META_SQRT(256);
+ VERIFY_META_SQRT(257);
+ VERIFY_META_SQRT(1023);
+ VERIFY_META_SQRT(1024);
+ VERIFY_META_SQRT(1025);
+}