aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/Core
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2008-08-24 15:15:32 +0000
committerGravatar Gael Guennebaud <g.gael@free.fr>2008-08-24 15:15:32 +0000
commitba100998bfab8fcf325451be050cabb52f641f46 (patch)
tree7b18bcccdd10dd109c383948b186b996cabae67d /Eigen/src/Core
parentbfe86b8fc0434cf03838bc1534f9f810594f2f08 (diff)
* split Meta.h to Meta.h (generic meta programming) and XprHelper.h (relates to eigen mechanism)
* added a meta.cpp unit test * EIGEN_TUNE_FOR_L2_CACHE_SIZE now represents L2 block size in Bytes (whence the ei_meta_sqrt...) * added a CustomizeEigen.dox page * added a TOC to QuickStartGuide.dox
Diffstat (limited to 'Eigen/src/Core')
-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
5 files changed, 210 insertions, 149 deletions
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