Re: [eigen] benchmarking weirdness

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]



So I can now provide some results with ICC 10.0 20070809 :

Fixed size 3x3, ColumnMajor, -DNDEBUG

real    0m31.536s
user    0m30.570s
sys     0m0.068s

Fixed size 3x3, ColumnMajor, with asserts

real    0m30.766s
user    0m30.270s
sys     0m0.012s

Fixed size 3x3, RowMajor, -DNDEBUG

real    0m31.198s
user    0m30.794s
sys     0m0.036s

Fixed size 3x3, RowMajor, with asserts

real    0m31.456s
user    0m30.902s
sys     0m0.064s

Dynamic size 20x20, ColumnMajor, -DNDEBUG

real    0m17.801s
user    0m17.369s
sys     0m0.016s

Dynamic size 20x20, ColumnMajor, with asserts

real    0m19.043s
user    0m18.681s
sys     0m0.036s

Dynamic size 20x20, RowMajor, -DNDEBUG

real    0m17.406s
user    0m17.269s
sys     0m0.004s

Dynamic size 20x20, RowMajor, with asserts

real    0m17.526s
user    0m17.313s
sys     0m0.020s

hum... pretty strange, is'nt it ? it seems ICC really does not like template based unrolling.

I also attached the diff.

Gael.



On Jan 5, 2008 11:45 PM, Gael Guennebaud <gael.guennebaud@xxxxxxxxx> wrote:

I tried to make ICC happy. The enum trick does not work, at least I did not succeed. On the other hand it works if we use an intermediate class like this:

template <typename Derived> struct DerivedTraits

{
    static const int RowsAtCompileTime = Derived::RowsAtCompileTime;
    static const int ColsAtCompileTime = Derived::ColsAtCompileTime;
    static const TraversalOrder Order = Derived::Order;
    static const int SizeAtCompileTime  = Derived::RowsAtCompileTime == Dynamic || Derived::ColsAtCompileTime == Dynamic
      ? Dynamic : Derived::RowsAtCompileTime * Derived::ColsAtCompileTime;
    static const bool IsVectorAtCompileTime = Derived::RowsAtCompileTime == 1 || Derived::ColsAtCompileTime == 1;
};

template<typename Scalar, typename Derived> class MatrixBase
{
  public:
    typedef DerivedTraits<Derived> Traits;
 ...
};

I also made the ColsAtCompileTime, RowsAtCompileTime and Order public inside all the "Derived" classes.
One strange thing is that the Product class did not define any _Order member, so I added one, but it is strange that GCC did not complain about the previous declaration MatrixBase::Order !

The only difference is that we have to add some "Traits::" everywhere...

What do you think ?

Gael.


On Jan 5, 2008 10:15 PM, Benoît Jacob < jacob@xxxxxxxxxxxxxxx> wrote:
Regarding intel's binary stuff:
I tried downloading vtune, was very annoyed to have to register, had a good
laugh when I saw that the .tar.gz file to download weighs 500 MB, started the
download which took long (because their server serves 100 KB/s), only to
notice now that the download failed at around 90% and I'm left with an
incomplete file.

I don't want to be of bad will, but I'm afraid that this is all the time that
I can spend on it right now.

That, plus the obvious conflict of interest when a CPU manufacturer provides
the profiling/optimizing software... moreover in binary-only form... sounds
very fishy to me.

Feel free to profile using vtume and port to icc (the enums trick should work,
it's actually an old trick used for old compilers, which suggests that icc's
c++ frontend is not very modern). I am of course very interested in vtune
results and in icc support. Only I can't do everything myself :)

Cheers,

Benoit

On Saturday 05 January 2008 21:51:27 Benoît Jacob wrote:
> Thanks Gael for benchmarking on your CPU. Indeed it is much closer to what
> I expected. FWIW, my CPU is a Core 1 duo at 1.66 GHz.
>
> I ran the benchmark_suite several times with various small modifications in
> Eigen. Results in attached spreadsheet. The most interesting thing is the
> last column: here we see that there is no benefit in adapting the traversal
> order to the storage order; instead, we get better results by always
> traversing in column-major order even for row-major matrices. So I'll
> revert that part of today's changes.
>
> Regarding the slowdown of disabling asserts, I also suspect an instruction
> cache miss. Indeed, disabling asserts means that more functions can get
> inlined, which is harder on the instruction cache. That's why I tested
> running the benchmark without using always_inline at certain places. See
> results in columns C,D,E. The result is that indeed the slowdown is reduced
> with column-major order, but not with row-major order. Meanwhile, the
> always_inline are really beneficial for fixed-size matrices. More
> importantly, the functions that I always_inline are trivial (one line, they
> are of the form "return Constructor();") so it seems strange to me that the
> compiler would not inline them.
>
> I would indeed like to make Eigen ICC-compatible; the error that you
> describe might be fixed by moving _RowsAtCompileTime from class Derived to
> class ForwardDecl<Derived> (see in Util.h ) or some similar trick. Help is
> welcome here as I am very short on time and have not yet installed ICC.
>
> Note that the standard workaround (such as used in TVMET) is to use an enum
> instead of static const int, but this is not really convenient here as
> Dynamic is set to -1 and C++ enums are not guaranteed to be signed. It is
> still possible to set Dynamic to some very large positive value, and go for
> enums, but then there are throughout the code some "Size>0" conditions that
> would have to be changed to "Size>0 && Size<Dynamic".
>
> Cheers,
>
> Benoit
>
> On Saturday 05 January 2008 17:43:46 Christian Mayer wrote:
> > Gael Guennebaud schrieb:
> > > Also, seeing the benchmark code, I don't think that any cache miss
> > > occurs since you only have two matrices.
> >
> > "Think" is a very bad guide when it comes to performance optimization.
> > Onlöy real measurements can count as it's far too easy to make things
> > worse by over optimizing (especially true when it comes to manual loop
> > unrolling).
> >
> > You must not only take care about cache misses for the data but also
> > about cache misses for the instructions (that's where loop unrolling can
> > really bite you).
> >
> > You also must have a look at register useage which can be thought as a
> > "level 0" cache. Especially changing between row and column major can
> > make a huge difference here.
> >
> > And at the end (IIRC VTune can also tell you that) a huge performance
> > difference can be achieved by optimization of the branch prediction.
> >
> > > I would also suggest to bench with different compilers, the results
> > > might be very different. However, eigein2 is currently not compatible
> > > with ICC.
> >
> > That's sad and we should fix it ASAP. ICC is a very good compiler when
> > it comes to optimal performance. It's also quite good at auto
> > vectorisation which is crucial for SSE useage (unless you are doing it
> > by hand with intrinsics)
> >
> > CU,
> > Christian




Index: Eigen/src/Core/Matrix.h
===================================================================
--- Eigen/src/Core/Matrix.h	(revision 757589)
+++ Eigen/src/Core/Matrix.h	(working copy)
@@ -91,15 +91,16 @@
     Scalar* data()
     { return Storage::m_data; }
     
+    static const TraversalOrder Order = _StorageOrder;
+    static const int RowsAtCompileTime = _Rows, ColsAtCompileTime = _Cols;
+
   private:
-    static const TraversalOrder _Order = _StorageOrder;
-    static const int _RowsAtCompileTime = _Rows, _ColsAtCompileTime = _Cols;
-    
+
     Ref _ref() const { return Ref(*this); }
     
     const Scalar& _coeff(int row, int col) const
     {
-      if(_Order == ColumnMajor)
+      if(Order == ColumnMajor)
         return (Storage::m_data)[row + col * Storage::_rows()];
       else // RowMajor
         return (Storage::m_data)[col + row * Storage::_cols()];
@@ -107,7 +108,7 @@
     
     Scalar& _coeffRef(int row, int col)
     {
-      if(_Order == ColumnMajor)
+      if(Order == ColumnMajor)
         return (Storage::m_data)[row + col * Storage::_rows()];
       else // RowMajor
         return (Storage::m_data)[col + row * Storage::_cols()];
@@ -125,12 +126,12 @@
     template<typename OtherDerived> 
     Matrix& operator=(const MatrixBase<Scalar, OtherDerived>& other)
     {
-      if(_RowsAtCompileTime == 1)
+      if(RowsAtCompileTime == 1)
       {
         assert(other.isVector());
         resize(1, other.size());
       }
-      else if(_ColsAtCompileTime == 1)
+      else if(ColsAtCompileTime == 1)
       {
         assert(other.isVector());
         resize(other.size(), 1);
@@ -165,7 +166,7 @@
       */
     explicit Matrix() : Storage()
     {
-      assert(_RowsAtCompileTime > 0 && _ColsAtCompileTime > 0);
+      assert(RowsAtCompileTime > 0 && ColsAtCompileTime > 0);
     }
     
     /** Constructs a vector or row-vector with given dimension. \only_for_vectors
@@ -177,10 +178,10 @@
     explicit Matrix(int dim) : Storage(dim)
     {
       assert(dim > 0);
-      assert((_RowsAtCompileTime == 1
-              && (_ColsAtCompileTime == Dynamic || _ColsAtCompileTime == dim))
-          || (_ColsAtCompileTime == 1
-              && (_RowsAtCompileTime == Dynamic || _RowsAtCompileTime == dim)));
+      assert((RowsAtCompileTime == 1
+              && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == dim))
+          || (ColsAtCompileTime == 1
+              && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == dim)));
     }
     
     /** This constructor has two very different behaviors, depending on the type of *this.
@@ -195,39 +196,39 @@
       */
     Matrix(int x, int y) : Storage(x, y)
     {
-      if((_RowsAtCompileTime == 1 && _ColsAtCompileTime == 2)
-      || (_RowsAtCompileTime == 2 && _ColsAtCompileTime == 1))
+      if((RowsAtCompileTime == 1 && ColsAtCompileTime == 2)
+      || (RowsAtCompileTime == 2 && ColsAtCompileTime == 1))
       {
         (Storage::m_data)[0] = x;
         (Storage::m_data)[1] = y;
       }
       else
       {
-        assert(x > 0 && (_RowsAtCompileTime == Dynamic || _RowsAtCompileTime == x)
-            && y > 0 && (_ColsAtCompileTime == Dynamic || _ColsAtCompileTime == y));
+        assert(x > 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == x)
+            && y > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == y));
       }
     }
     /** constructs an initialized 2D vector with given coefficients */
     Matrix(const float& x, const float& y)
     {
-      assert((_RowsAtCompileTime == 1 && _ColsAtCompileTime == 2)
-          || (_RowsAtCompileTime == 2 && _ColsAtCompileTime == 1));
+      assert((RowsAtCompileTime == 1 && ColsAtCompileTime == 2)
+          || (RowsAtCompileTime == 2 && ColsAtCompileTime == 1));
       (Storage::m_data)[0] = x;
       (Storage::m_data)[1] = y;
     }
     /** constructs an initialized 2D vector with given coefficients */
     Matrix(const double& x, const double& y)
     {
-      assert((_RowsAtCompileTime == 1 && _ColsAtCompileTime == 2)
-          || (_RowsAtCompileTime == 2 && _ColsAtCompileTime == 1));
+      assert((RowsAtCompileTime == 1 && ColsAtCompileTime == 2)
+          || (RowsAtCompileTime == 2 && ColsAtCompileTime == 1));
       (Storage::m_data)[0] = x;
       (Storage::m_data)[1] = y;
     }
     /** constructs an initialized 3D vector with given coefficients */
     Matrix(const Scalar& x, const Scalar& y, const Scalar& z)
     {
-      assert((_RowsAtCompileTime == 1 && _ColsAtCompileTime == 3)
-          || (_RowsAtCompileTime == 3 && _ColsAtCompileTime == 1));
+      assert((RowsAtCompileTime == 1 && ColsAtCompileTime == 3)
+          || (RowsAtCompileTime == 3 && ColsAtCompileTime == 1));
       (Storage::m_data)[0] = x;
       (Storage::m_data)[1] = y;
       (Storage::m_data)[2] = z;
@@ -235,8 +236,8 @@
     /** constructs an initialized 4D vector with given coefficients */
     Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
     {
-      assert((_RowsAtCompileTime == 1 && _ColsAtCompileTime == 4)
-          || (_RowsAtCompileTime == 4 && _ColsAtCompileTime == 1));
+      assert((RowsAtCompileTime == 1 && ColsAtCompileTime == 4)
+          || (RowsAtCompileTime == 4 && ColsAtCompileTime == 1));
       (Storage::m_data)[0] = x;
       (Storage::m_data)[1] = y;
       (Storage::m_data)[2] = z;
Index: Eigen/src/Core/OperatorEquals.h
===================================================================
--- Eigen/src/Core/OperatorEquals.h	(revision 757589)
+++ Eigen/src/Core/OperatorEquals.h	(working copy)
@@ -105,13 +105,13 @@
 Derived& MatrixBase<Scalar, Derived>
   ::operator=(const MatrixBase<Scalar, OtherDerived>& other)
 {
-  if(IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime)
+  if(Traits::IsVectorAtCompileTime && OtherDerived::Traits::IsVectorAtCompileTime)
     // copying a vector expression into a vector
   {
     assert(size() == other.size());
-    if(EIGEN_UNROLLED_LOOPS && SizeAtCompileTime != Dynamic && SizeAtCompileTime <= 25)
+    if(EIGEN_UNROLLED_LOOPS && Traits::SizeAtCompileTime != Dynamic && Traits::SizeAtCompileTime <= 25)
       VectorOperatorEqualsUnroller
-        <Derived, OtherDerived, SizeAtCompileTime>::run
+        <Derived, OtherDerived, Traits::SizeAtCompileTime>::run
           (*static_cast<Derived*>(this), *static_cast<const OtherDerived*>(&other));
     else
       for(int i = 0; i < size(); i++)
@@ -121,13 +121,13 @@
   else // copying a matrix expression into a matrix
   {
     assert(rows() == other.rows() && cols() == other.cols());
-    if(EIGEN_UNROLLED_LOOPS && SizeAtCompileTime != Dynamic && SizeAtCompileTime <= 25)
+    if(EIGEN_UNROLLED_LOOPS && Traits::SizeAtCompileTime != Dynamic && Traits::SizeAtCompileTime <= 25)
       MatrixOperatorEqualsUnroller
-        <Derived, OtherDerived, SizeAtCompileTime, Order>::run
+        <Derived, OtherDerived, Traits::SizeAtCompileTime, Traits::Order>::run
           (*static_cast<Derived*>(this), *static_cast<const OtherDerived*>(&other));
     else
     {
-      if(Order == ColumnMajor)
+      if(Traits::Order == ColumnMajor)
         for(int j = 0; j < cols(); j++)
           for(int i = 0; i < rows(); i++)
             coeffRef(i, j) = other.coeff(i, j);
Index: Eigen/src/Core/Random.h
===================================================================
--- Eigen/src/Core/Random.h	(revision 757589)
+++ Eigen/src/Core/Random.h	(working copy)
@@ -39,11 +39,12 @@
     typedef typename MatrixType::Scalar Scalar;
     friend class MatrixBase<Scalar, Random<MatrixType> >;
   
+    static const TraversalOrder Order = Indifferent;
+    static const int RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+                     ColsAtCompileTime = MatrixType::ColsAtCompileTime;
+  
   private:
-    static const TraversalOrder _Order = Indifferent;
-    static const int _RowsAtCompileTime = MatrixType::RowsAtCompileTime,
-                     _ColsAtCompileTime = MatrixType::ColsAtCompileTime;
-
+  
     const Random& _ref() const { return *this; }
     int _rows() const { return m_rows; }
     int _cols() const { return m_cols; }
@@ -57,9 +58,9 @@
     Random(int rows, int cols) : m_rows(rows), m_cols(cols)
     {
       assert(rows > 0
-          && (_RowsAtCompileTime == Dynamic || _RowsAtCompileTime == rows)
+          && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
           && cols > 0
-          && (_ColsAtCompileTime == Dynamic || _ColsAtCompileTime == cols));
+          && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
     }
     
   protected:
@@ -105,8 +106,8 @@
 template<typename Scalar, typename Derived>
 const Eval<Random<Derived> > MatrixBase<Scalar, Derived>::random(int size)
 {
-  assert(IsVectorAtCompileTime);
-  if(RowsAtCompileTime == 1) return Random<Derived>(1, size).eval();
+  assert(Traits::IsVectorAtCompileTime);
+  if(Traits::RowsAtCompileTime == 1) return Random<Derived>(1, size).eval();
   else return Random<Derived>(size, 1).eval();
 }
 
@@ -124,7 +125,7 @@
 template<typename Scalar, typename Derived>
 const Eval<Random<Derived> > MatrixBase<Scalar, Derived>::random()
 {
-  return Random<Derived>(RowsAtCompileTime, ColsAtCompileTime).eval();
+  return Random<Derived>(Traits::RowsAtCompileTime, Traits::ColsAtCompileTime).eval();
 }
 
 #endif // EIGEN_RANDOM_H
Index: Eigen/src/Core/Product.h
===================================================================
--- Eigen/src/Core/Product.h	(revision 757589)
+++ Eigen/src/Core/Product.h	(working copy)
@@ -75,9 +75,11 @@
       assert(lhs.cols() == rhs.rows());
     }
     
+    static const TraversalOrder Order = Lhs::Order;
+    static const int RowsAtCompileTime = Lhs::RowsAtCompileTime,
+                     ColsAtCompileTime = Rhs::ColsAtCompileTime;
+
   private:
-    static const int _RowsAtCompileTime = Lhs::RowsAtCompileTime,
-                     _ColsAtCompileTime = Rhs::ColsAtCompileTime;
 
     const Product& _ref() const { return *this; }
     int _rows() const { return m_lhs.rows(); }
Index: Eigen/src/Core/ScalarMultiple.h
===================================================================
--- Eigen/src/Core/ScalarMultiple.h	(revision 757589)
+++ Eigen/src/Core/ScalarMultiple.h	(working copy)
@@ -37,6 +37,9 @@
     ScalarMultiple(const MatRef& matrix, FactorType factor)
       : m_matrix(matrix), m_factor(factor) {}
 
+    static const TraversalOrder Order = MatrixType::Order;
+    static const int RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+                     ColsAtCompileTime = MatrixType::ColsAtCompileTime;
   private:
     static const TraversalOrder _Order = MatrixType::Order;
     static const int _RowsAtCompileTime = MatrixType::RowsAtCompileTime,
Index: Eigen/src/Core/Dot.h
===================================================================
--- Eigen/src/Core/Dot.h	(revision 757589)
+++ Eigen/src/Core/Dot.h	(working copy)
@@ -72,10 +72,10 @@
 template<typename OtherDerived>
 Scalar MatrixBase<Scalar, Derived>::dot(const OtherDerived& other) const
 {
-  assert(IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime && size() == other.size());
+  assert(Traits::IsVectorAtCompileTime && OtherDerived::Traits::IsVectorAtCompileTime && size() == other.size());
   Scalar res;
-  if(EIGEN_UNROLLED_LOOPS && SizeAtCompileTime != Dynamic && SizeAtCompileTime <= 16)
-    DotUnroller<SizeAtCompileTime-1, SizeAtCompileTime, Derived, OtherDerived>
+  if(EIGEN_UNROLLED_LOOPS && Traits::SizeAtCompileTime != Dynamic && Traits::SizeAtCompileTime <= 16)
+    DotUnroller<Traits::SizeAtCompileTime-1, Traits::SizeAtCompileTime, Derived, OtherDerived>
       ::run(*static_cast<const Derived*>(this), other, res);
   else
   {
Index: Eigen/src/Core/Fuzzy.h
===================================================================
--- Eigen/src/Core/Fuzzy.h	(revision 757589)
+++ Eigen/src/Core/Fuzzy.h	(working copy)
@@ -34,7 +34,7 @@
 ) const
 {
   assert(rows() == other.rows() && cols() == other.cols());
-  if(IsVectorAtCompileTime)
+  if(Traits::IsVectorAtCompileTime)
   {
     return((*this - other).norm2() <= std::min(norm2(), other.norm2()) * prec * prec);
   }
@@ -54,7 +54,7 @@
   const typename NumTraits<Scalar>::Real& prec = precision<Scalar>()
 ) const
 {
-  if(IsVectorAtCompileTime)
+  if(Traits::IsVectorAtCompileTime)
   {
     return(norm2() <= abs2(other * prec));
   }
@@ -75,7 +75,7 @@
 ) const
 {
   assert(rows() == other.rows() && cols() == other.cols());
-  if(IsVectorAtCompileTime)
+  if(Traits::IsVectorAtCompileTime)
   {
     return(norm2() <= other.norm2() * prec * prec);
   }
Index: Eigen/src/Core/Identity.h
===================================================================
--- Eigen/src/Core/Identity.h	(revision 757589)
+++ Eigen/src/Core/Identity.h	(working copy)
@@ -38,6 +38,10 @@
       assert(rows > 0 && _RowsAtCompileTime == _ColsAtCompileTime);
     }
     
+    static const TraversalOrder Order = Indifferent;
+    static const int RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+                     ColsAtCompileTime = MatrixType::ColsAtCompileTime;
+    
   private:
     static const TraversalOrder _Order = Indifferent;
     static const int _RowsAtCompileTime = MatrixType::RowsAtCompileTime,
Index: Eigen/src/Core/Block.h
===================================================================
--- Eigen/src/Core/Block.h	(revision 757589)
+++ Eigen/src/Core/Block.h	(working copy)
@@ -66,11 +66,11 @@
     
     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
     
+    static const TraversalOrder Order = MatrixType::Order;
+    static const int RowsAtCompileTime = BlockRows,
+                     ColsAtCompileTime = BlockCols;
+
   private:
-    static const TraversalOrder _Order = MatrixType::Order;
-    static const int _RowsAtCompileTime = BlockRows,
-                     _ColsAtCompileTime = BlockCols;
-    
     const Block& _ref() const { return *this; }
     int _rows() const { return BlockRows; }
     int _cols() const { return BlockCols; }
Index: Eigen/src/Core/Trace.h
===================================================================
--- Eigen/src/Core/Trace.h	(revision 757589)
+++ Eigen/src/Core/Trace.h	(working copy)
@@ -62,8 +62,8 @@
 {
   assert(rows() == cols());
   Scalar res;
-  if(EIGEN_UNROLLED_LOOPS && RowsAtCompileTime != Dynamic && RowsAtCompileTime <= 16)
-    TraceUnroller<RowsAtCompileTime-1, RowsAtCompileTime, Derived>
+  if(EIGEN_UNROLLED_LOOPS && Traits::RowsAtCompileTime != Dynamic && Traits::RowsAtCompileTime <= 16)
+    TraceUnroller<Traits::RowsAtCompileTime-1, Traits::RowsAtCompileTime, Derived>
       ::run(*static_cast<const Derived*>(this), res);
   else
   {
Index: Eigen/src/Core/MatrixBase.h
===================================================================
--- Eigen/src/Core/MatrixBase.h	(revision 757589)
+++ Eigen/src/Core/MatrixBase.h	(working copy)
@@ -26,6 +26,39 @@
 #ifndef EIGEN_MATRIXBASE_H
 #define EIGEN_MATRIXBASE_H
 
+#include "Util.h"
+
+template <typename Derived>
+struct DerivedTraits
+{
+    static const TraversalOrder Order = Derived::Order;
+    
+    /** The number of rows at compile-time. This is just a copy of the value provided
+      * by the \a Derived type. If a value is not known at compile-time,
+      * it is set to the \a Dynamic constant.
+      * \sa rows(), cols(), ColsAtCompileTime, SizeAtCompileTime */
+    static const int RowsAtCompileTime = Derived::RowsAtCompileTime;
+    
+    /** The number of columns at compile-time. This is just a copy of the value provided
+      * by the \a Derived type. If a value is not known at compile-time,
+      * it is set to the \a Dynamic constant.
+      * \sa rows(), cols(), RowsAtCompileTime, SizeAtCompileTime */
+    static const int ColsAtCompileTime = Derived::ColsAtCompileTime;
+    
+    /** This is equal to the number of coefficients, i.e. the number of
+      * rows times the number of columns, or to \a Dynamic if this is not
+      * known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */
+    static const int SizeAtCompileTime
+      = Derived::RowsAtCompileTime == Dynamic || Derived::ColsAtCompileTime == Dynamic
+      ? Dynamic : Derived::RowsAtCompileTime * Derived::ColsAtCompileTime;
+    
+    /** This is set to true if either the number of rows or the number of
+      * columns is known at compile-time to be equal to 1. Indeed, in that case,
+      * we are dealing with a column-vector (if there is only one column) or with
+      * a row-vector (if there is only one row). */
+    static const bool IsVectorAtCompileTime = Derived::RowsAtCompileTime == 1 || Derived::ColsAtCompileTime == 1;
+};
+
 /** \class MatrixBase
   *
   * \brief Base class for all matrices, vectors, and expressions
@@ -57,32 +90,8 @@
 template<typename Scalar, typename Derived> class MatrixBase
 {
   public:
-    static const TraversalOrder Order = Derived::_Order;
-  
-    /** The number of rows at compile-time. This is just a copy of the value provided
-      * by the \a Derived type. If a value is not known at compile-time,
-      * it is set to the \a Dynamic constant.
-      * \sa rows(), cols(), ColsAtCompileTime, SizeAtCompileTime */
-    static const int RowsAtCompileTime = Derived::_RowsAtCompileTime;
+    typedef DerivedTraits<Derived> Traits;
     
-    /** The number of columns at compile-time. This is just a copy of the value provided
-      * by the \a Derived type. If a value is not known at compile-time,
-      * it is set to the \a Dynamic constant.
-      * \sa rows(), cols(), RowsAtCompileTime, SizeAtCompileTime */
-    static const int ColsAtCompileTime = Derived::_ColsAtCompileTime;
-    
-    /** This is equal to the number of coefficients, i.e. the number of
-      * rows times the number of columns, or to \a Dynamic if this is not
-      * known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */
-    static const int SizeAtCompileTime
-      = RowsAtCompileTime == Dynamic || ColsAtCompileTime == Dynamic
-      ? Dynamic : RowsAtCompileTime * ColsAtCompileTime;
-    /** This is set to true if either the number of rows or the number of
-      * columns is known at compile-time to be equal to 1. Indeed, in that case,
-      * we are dealing with a column-vector (if there is only one column) or with
-      * a row-vector (if there is only one row). */
-    static const bool IsVectorAtCompileTime = RowsAtCompileTime == 1 || ColsAtCompileTime == 1;
-    
     /** This is the "reference type" used to pass objects of type MatrixBase as arguments
       * to functions. If this MatrixBase type represents an expression, then \a Ref
       * is just this MatrixBase type itself, i.e. expressions are just passed by value
@@ -170,7 +179,7 @@
     static const Ones<Derived> ones(int rows, int cols);
     static const Ones<Derived> ones(int size);
     static const Ones<Derived> ones();
-    static const Identity<Derived> identity(int rows = RowsAtCompileTime);
+    static const Identity<Derived> identity(int rows = Derived::RowsAtCompileTime);
     
     bool isZero(const typename NumTraits<Scalar>::Real& prec) const;
     bool isOnes(const typename NumTraits<Scalar>::Real& prec) const;
Index: Eigen/src/Core/Opposite.h
===================================================================
--- Eigen/src/Core/Opposite.h	(revision 757589)
+++ Eigen/src/Core/Opposite.h	(working copy)
@@ -36,11 +36,11 @@
     
     Opposite(const MatRef& matrix) : m_matrix(matrix) {}
     
+    static const TraversalOrder Order = MatrixType::Order;
+    static const int RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+                     ColsAtCompileTime = MatrixType::ColsAtCompileTime;
+
   private:
-    static const TraversalOrder _Order = MatrixType::Order;
-    static const int _RowsAtCompileTime = MatrixType::RowsAtCompileTime,
-                     _ColsAtCompileTime = MatrixType::ColsAtCompileTime;
-
     const Opposite& _ref() const { return *this; }
     int _rows() const { return m_matrix.rows(); }
     int _cols() const { return m_matrix.cols(); }
Index: Eigen/src/Core/Ones.h
===================================================================
--- Eigen/src/Core/Ones.h	(revision 757589)
+++ Eigen/src/Core/Ones.h	(working copy)
@@ -39,11 +39,12 @@
     typedef typename MatrixType::Scalar Scalar;
     friend class MatrixBase<Scalar, Ones<MatrixType> >;
   
+    static const TraversalOrder Order = Indifferent;
+    static const int RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+                     ColsAtCompileTime = MatrixType::ColsAtCompileTime;
+
   private:
-    static const TraversalOrder _Order = Indifferent;
-    static const int _RowsAtCompileTime = MatrixType::RowsAtCompileTime,
-                     _ColsAtCompileTime = MatrixType::ColsAtCompileTime;
-
+  
     const Ones& _ref() const { return *this; }
     int _rows() const { return m_rows; }
     int _cols() const { return m_cols; }
@@ -57,9 +58,9 @@
     Ones(int rows, int cols) : m_rows(rows), m_cols(cols)
     {
       assert(rows > 0
-          && (_RowsAtCompileTime == Dynamic || _RowsAtCompileTime == rows)
+          && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
           && cols > 0
-          && (_ColsAtCompileTime == Dynamic || _ColsAtCompileTime == cols));
+          && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
     }
     
   protected:
@@ -105,8 +106,8 @@
 template<typename Scalar, typename Derived>
 const Ones<Derived> MatrixBase<Scalar, Derived>::ones(int size)
 {
-  assert(IsVectorAtCompileTime);
-  if(RowsAtCompileTime == 1) return Ones<Derived>(1, size);
+  assert(Traits::IsVectorAtCompileTime);
+  if(Traits::RowsAtCompileTime == 1) return Ones<Derived>(1, size);
   else return Ones<Derived>(size, 1);
 }
 
@@ -123,7 +124,7 @@
 template<typename Scalar, typename Derived>
 const Ones<Derived> MatrixBase<Scalar, Derived>::ones()
 {
-  return Ones<Derived>(RowsAtCompileTime, ColsAtCompileTime);
+  return Ones<Derived>(Traits::RowsAtCompileTime, Traits::ColsAtCompileTime);
 }
 
 template<typename Scalar, typename Derived>
Index: Eigen/src/Core/Sum.h
===================================================================
--- Eigen/src/Core/Sum.h	(revision 757589)
+++ Eigen/src/Core/Sum.h	(working copy)
@@ -41,10 +41,11 @@
       assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
     }
 
+    static const TraversalOrder Order = Lhs::Order;
+    static const int RowsAtCompileTime = Lhs::RowsAtCompileTime,
+                     ColsAtCompileTime = Rhs::ColsAtCompileTime;
+
   private:
-    static const TraversalOrder _Order = Lhs::Order;
-    static const int _RowsAtCompileTime = Lhs::RowsAtCompileTime,
-                     _ColsAtCompileTime = Rhs::ColsAtCompileTime;
 
     const Sum& _ref() const { return *this; }
     int _rows() const { return m_lhs.rows(); }
Index: Eigen/src/Core/Coeffs.h
===================================================================
--- Eigen/src/Core/Coeffs.h	(revision 757589)
+++ Eigen/src/Core/Coeffs.h	(working copy)
@@ -116,8 +116,8 @@
 Scalar MatrixBase<Scalar, Derived>
   ::coeff(int index) const
 {
-  eigen_internal_assert(IsVectorAtCompileTime);
-  if(RowsAtCompileTime == 1)
+  eigen_internal_assert(Traits::IsVectorAtCompileTime);
+  if(Traits::RowsAtCompileTime == 1)
   {
     eigen_internal_assert(index >= 0 && index < cols());
     return coeff(0, index);
@@ -140,8 +140,8 @@
 Scalar MatrixBase<Scalar, Derived>
   ::operator[](int index) const
 {
-  assert(IsVectorAtCompileTime);
-  if(RowsAtCompileTime == 1)
+  assert(Traits::IsVectorAtCompileTime);
+  if(Traits::RowsAtCompileTime == 1)
   {
     assert(index >= 0 && index < cols());
     return coeff(0, index);
@@ -171,8 +171,8 @@
 Scalar& MatrixBase<Scalar, Derived>
   ::coeffRef(int index)
 {
-  eigen_internal_assert(IsVectorAtCompileTime);
-  if(RowsAtCompileTime == 1)
+  eigen_internal_assert(Traits::IsVectorAtCompileTime);
+  if(Traits::RowsAtCompileTime == 1)
   {
     eigen_internal_assert(index >= 0 && index < cols());
     return coeffRef(0, index);
@@ -194,8 +194,8 @@
 Scalar& MatrixBase<Scalar, Derived>
   ::operator[](int index)
 {
-  assert(IsVectorAtCompileTime);
-  if(RowsAtCompileTime == 1)
+  assert(Traits::IsVectorAtCompileTime);
+  if(Traits::RowsAtCompileTime == 1)
   {
     assert(index >= 0 && index < cols());
     return coeffRef(0, index);
Index: Eigen/src/Core/Zero.h
===================================================================
--- Eigen/src/Core/Zero.h	(revision 757589)
+++ Eigen/src/Core/Zero.h	(working copy)
@@ -39,11 +39,11 @@
     typedef typename MatrixType::Scalar Scalar;
     friend class MatrixBase<Scalar, Zero<MatrixType> >;
   
+    static const TraversalOrder Order = Indifferent;
+    static const int RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+                     ColsAtCompileTime = MatrixType::ColsAtCompileTime;
+
   private:
-    static const TraversalOrder _Order = Indifferent;
-    static const int _RowsAtCompileTime = MatrixType::RowsAtCompileTime,
-                     _ColsAtCompileTime = MatrixType::ColsAtCompileTime;
-
     const Zero& _ref() const { return *this; }
     int _rows() const { return m_rows; }
     int _cols() const { return m_cols; }
@@ -57,9 +57,9 @@
     Zero(int rows, int cols) : m_rows(rows), m_cols(cols)
     {
       assert(rows > 0
-          && (_RowsAtCompileTime == Dynamic || _RowsAtCompileTime == rows)
+          && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
           && cols > 0
-          && (_ColsAtCompileTime == Dynamic || _ColsAtCompileTime == cols));
+          && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
     }
     
   protected:
@@ -105,8 +105,8 @@
 template<typename Scalar, typename Derived>
 const Zero<Derived> MatrixBase<Scalar, Derived>::zero(int size)
 {
-  assert(IsVectorAtCompileTime);
-  if(RowsAtCompileTime == 1) return Zero<Derived>(1, size);
+  assert(Traits::IsVectorAtCompileTime);
+  if(Traits::RowsAtCompileTime == 1) return Zero<Derived>(1, size);
   else return Zero<Derived>(size, 1);
 }
 
@@ -123,7 +123,7 @@
 template<typename Scalar, typename Derived>
 const Zero<Derived> MatrixBase<Scalar, Derived>::zero()
 {
-  return Zero<Derived>(RowsAtCompileTime, ColsAtCompileTime);
+  return Zero<Derived>(Traits::RowsAtCompileTime, Traits::ColsAtCompileTime);
 }
 
 template<typename Scalar, typename Derived>


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/