* allow matrix dimensions to be 0 (also at compile time) and provide a specialization

of ei_matrix_array for size 0
* adapt many xprs to have the right storage order, now that it matters
* add static assert on expressions to check that vector xprs
  have the righ storage order
* adapt ei_plain_matrix_type_(column|row)_major
* implement assignment of selfadjointview to matrix
  (was before failing to compile) and add nestedExpression() methods
* expand product_symm test
* in ei_gemv_selector, use the PlainObject type instead of a custom Matrix<...> type
* fix VectorBlock and Block mistakes
This commit is contained in:
Benoit Jacob 2010-03-21 11:28:03 -04:00
parent 547269da35
commit 92da574ec2
19 changed files with 117 additions and 59 deletions

View File

@ -55,7 +55,10 @@ struct ei_traits<Replicate<MatrixType,RowFactor,ColFactor> >
: ColFactor * MatrixType::ColsAtCompileTime,
MaxRowsAtCompileTime = RowsAtCompileTime,
MaxColsAtCompileTime = ColsAtCompileTime,
Flags = (_MatrixTypeNested::Flags & HereditaryBits),
IsRowMajor = RowsAtCompileTime==1 && ColsAtCompileTime!=1 ? 1
: ColsAtCompileTime==1 && RowsAtCompileTime!=1 ? 0
: (MatrixType::Flags & RowMajorBit) ? 1 : 0,
Flags = (_MatrixTypeNested::Flags & HereditaryBits & ~RowMajorBit) | (IsRowMajor ? RowMajorBit : 0),
CoeffReadCost = _MatrixTypeNested::CoeffReadCost
};
};

View File

@ -70,11 +70,11 @@ struct ei_traits<Block<MatrixType, BlockRows, BlockCols, _DirectAccessStatus> >
: (BlockRows==Dynamic ? int(ei_traits<MatrixType>::MaxRowsAtCompileTime) : BlockRows),
MaxColsAtCompileTime = ColsAtCompileTime == 1 ? 1
: (BlockCols==Dynamic ? int(ei_traits<MatrixType>::MaxColsAtCompileTime) : BlockCols),
MatrixTypeIsRowMajor = int(ei_traits<MatrixType>::Flags)&RowMajorBit,
MatrixTypeIsRowMajor = (int(ei_traits<MatrixType>::Flags)&RowMajorBit) != 0,
IsRowMajor = (BlockRows==1&&BlockCols!=1) ? 1
: (BlockCols==1&&BlockRows!=1) ? 0
: MatrixTypeIsRowMajor,
InnerSize = RowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
: (BlockCols==1&&BlockRows!=1) ? 0
: MatrixTypeIsRowMajor,
InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % ei_packet_traits<Scalar>::size) == 0)
&& (IsRowMajor == MatrixTypeIsRowMajor) // check for bad case of row-xpr inside col-major matrix...
? PacketAccessBit : 0,

View File

@ -66,7 +66,7 @@ struct ei_traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > : ei_traits<Lhs>
LhsFlags = _LhsNested::Flags,
RhsFlags = _RhsNested::Flags,
StorageOrdersAgree = (int(Lhs::Flags)&RowMajorBit)==(int(Rhs::Flags)&RowMajorBit),
Flags = (int(LhsFlags) | int(RhsFlags)) & (
Flags0 = (int(LhsFlags) | int(RhsFlags)) & (
HereditaryBits
| (int(LhsFlags) & int(RhsFlags) &
( AlignedBit
@ -75,6 +75,7 @@ struct ei_traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > : ei_traits<Lhs>
)
)
),
Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + ei_functor_traits<BinaryOp>::Cost
};
};

View File

@ -589,6 +589,9 @@ template<typename Derived> class DenseBase
#ifdef EIGEN_INTERNAL_DEBUGGING
EIGEN_STATIC_ASSERT(ei_are_flags_consistent<Flags>::ret,
INVALID_MATRIXBASE_TEMPLATE_PARAMETERS)
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(RowsAtCompileTime==1 && ColsAtCompileTime!=1, (Flags&RowMajorBit)==RowMajorBit)
&& EIGEN_IMPLIES(ColsAtCompileTime==1 && RowsAtCompileTime!=1, (Flags&RowMajorBit)==0)),
INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION)
#endif
}

View File

@ -514,8 +514,8 @@ class DenseStorageBase : public _Base<Derived>
&& EIGEN_IMPLIES(ColsAtCompileTime==1 && RowsAtCompileTime!=1, (_Options&RowMajor)==0)
&& (RowsAtCompileTime >= MaxRowsAtCompileTime)
&& (ColsAtCompileTime >= MaxColsAtCompileTime)
&& (MaxRowsAtCompileTime >= 1)
&& (MaxColsAtCompileTime >= 1)
&& (MaxRowsAtCompileTime >= 0)
&& (MaxColsAtCompileTime >= 0)
&& (RowsAtCompileTime <= Dynamic)
&& (ColsAtCompileTime <= Dynamic)
&& (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic)

View File

@ -58,7 +58,7 @@ struct ei_traits<Diagonal<MatrixType,Index> >
: Index == Dynamic ? EIGEN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime)
: (EIGEN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime) - AbsIndex),
MaxColsAtCompileTime = 1,
Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit),
Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit) & ~RowMajorBit,
CoeffReadCost = _MatrixTypeNested::CoeffReadCost
};
};

View File

@ -68,6 +68,14 @@ struct ei_matrix_array<T, Size, MatrixOptions, 16>
ei_matrix_array(ei_constructor_without_unaligned_array_assert) {}
};
template <typename T, int MatrixOptions, int Alignment>
struct ei_matrix_array<T, 0, MatrixOptions, Alignment>
{
EIGEN_ALIGN16 T array[1];
ei_matrix_array() {}
ei_matrix_array(ei_constructor_without_unaligned_array_assert) {}
};
/** \internal
*
* \class ei_matrix_storage

View File

@ -330,7 +330,7 @@ template<> struct ei_gemv_selector<OnTheRight,ColMajor,true>
else
{
actualDest = ei_aligned_stack_new(Scalar,dest.size());
Map<Matrix<Scalar,Dest::RowsAtCompileTime,1> >(actualDest, dest.size()) = dest;
Map<typename Dest::PlainObject>(actualDest, dest.size()) = dest;
}
ei_cache_friendly_product_colmajor_times_vector
@ -341,7 +341,7 @@ template<> struct ei_gemv_selector<OnTheRight,ColMajor,true>
if (!EvalToDest)
{
dest = Map<Matrix<Scalar,Dest::SizeAtCompileTime,1> >(actualDest, dest.size());
dest = Map<typename Dest::PlainObject>(actualDest, dest.size());
ei_aligned_stack_delete(Scalar, actualDest, dest.size());
}
}
@ -376,7 +376,7 @@ template<> struct ei_gemv_selector<OnTheRight,RowMajor,true>
else
{
rhs_data = ei_aligned_stack_new(Scalar, actualRhs.size());
Map<Matrix<Scalar,_ActualRhsType::SizeAtCompileTime,1> >(rhs_data, actualRhs.size()) = actualRhs;
Map<typename _ActualRhsType::PlainObject>(rhs_data, actualRhs.size()) = actualRhs;
}
ei_cache_friendly_product_rowmajor_times_vector

View File

@ -37,7 +37,7 @@
template<typename Func, typename Derived>
struct ei_redux_traits
{
private:
public:
enum {
PacketSize = ei_packet_traits<typename Derived::Scalar>::size,
InnerMaxSize = int(Derived::IsRowMajor)
@ -55,11 +55,11 @@ private:
public:
enum {
Traversal = int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
: int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
: int(DefaultTraversal)
: int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
: int(DefaultTraversal)
};
private:
public:
enum {
Cost = Derived::SizeAtCompileTime * Derived::CoeffReadCost
+ (Derived::SizeAtCompileTime-1) * NumTraits<typename Derived::Scalar>::AddCost,

View File

@ -99,6 +99,9 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
/** \internal */
const MatrixType& _expression() const { return m_matrix; }
const MatrixType& nestedExpression() const { return m_matrix; }
MatrixType& nestedExpression() { return const_cast<MatrixType&>(m_matrix); }
/** Efficient self-adjoint matrix times vector/matrix product */
template<typename OtherDerived>
SelfadjointProductMatrix<MatrixType,Mode,false,OtherDerived,0,OtherDerived::IsVectorAtCompileTime>

View File

@ -205,7 +205,7 @@ struct ei_triangular_solver_unroller<Lhs,Rhs,Mode,Index,Size,false> {
static void run(const Lhs& lhs, Rhs& rhs)
{
if (Index>0)
rhs.coeffRef(I) -= ((lhs.row(I).template segment<Index>(S).transpose()).cwiseProduct(rhs.template segment<Index>(S))).sum();
rhs.coeffRef(I) -= lhs.row(I).template segment<Index>(S).transpose().cwiseProduct(rhs.template segment<Index>(S)).sum();
if(!(Mode & UnitDiag))
rhs.coeffRef(I) /= lhs.coeff(I,I);

View File

@ -472,6 +472,40 @@ struct ei_triangular_assignment_selector<Derived1, Derived2, UnitLower, Dynamic,
}
};
template<typename Derived1, typename Derived2, bool ClearOpposite>
struct ei_triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Upper, Dynamic, ClearOpposite>
{
inline static void run(Derived1 &dst, const Derived2 &src)
{
for(int j = 0; j < dst.cols(); ++j)
{
for(int i = 0; i < j; ++i)
{
dst.copyCoeff(i, j, src);
dst.coeffRef(j,i) = ei_conj(dst.coeff(i,j));
}
dst.copyCoeff(j, j, src);
}
}
};
template<typename Derived1, typename Derived2, bool ClearOpposite>
struct ei_triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, Dynamic, ClearOpposite>
{
inline static void run(Derived1 &dst, const Derived2 &src)
{
for(int i = 0; i < dst.rows(); ++i)
{
for(int j = 0; j < i; ++j)
{
dst.copyCoeff(i, j, src);
dst.coeffRef(j,i) = ei_conj(dst.coeff(i,j));
}
dst.copyCoeff(i, i, src);
}
}
};
// FIXME should we keep that possibility
template<typename MatrixType, unsigned int Mode>
template<typename OtherDerived>

View File

@ -58,34 +58,21 @@
template<typename VectorType, int Size>
struct ei_traits<VectorBlock<VectorType, Size> >
: public ei_traits<Block<VectorType,
ei_traits<VectorType>::RowsAtCompileTime==1 ? 1 : Size,
ei_traits<VectorType>::ColsAtCompileTime==1
// handle the 1x1 case. Taking a dynamic-sized vectorblock in a 1x1 xpr.
// example: when doing HouseholderQR<Matrix<float,1,1> >.
&& ei_traits<VectorType>::RowsAtCompileTime!=1
? 1 : Size> >
ei_traits<VectorType>::Flags & RowMajorBit ? 1 : Size,
ei_traits<VectorType>::Flags & RowMajorBit ? Size : 1> >
{
};
template<typename VectorType, int Size> class VectorBlock
: public Block<VectorType,
ei_traits<VectorType>::RowsAtCompileTime==1 ? 1 : Size,
ei_traits<VectorType>::ColsAtCompileTime==1
// handle the 1x1 case. Taking a dynamic-sized vectorblock in a 1x1 xpr.
// example: when doing HouseholderQR<Matrix<float,1,1> >.
&& ei_traits<VectorType>::RowsAtCompileTime!=1
? 1 : Size>
ei_traits<VectorType>::Flags & RowMajorBit ? 1 : Size,
ei_traits<VectorType>::Flags & RowMajorBit ? Size : 1>
{
typedef Block<VectorType,
ei_traits<VectorType>::RowsAtCompileTime==1 ? 1 : Size,
ei_traits<VectorType>::ColsAtCompileTime==1
// handle the 1x1 case. Taking a dynamic-sized vectorblock in a 1x1 xpr.
// example: when doing HouseholderQR<Matrix<float,1,1> >.
&& ei_traits<VectorType>::RowsAtCompileTime!=1
? 1 : Size
> Base;
ei_traits<VectorType>::Flags & RowMajorBit ? 1 : Size,
ei_traits<VectorType>::Flags & RowMajorBit ? Size : 1> Base;
enum {
IsColVector = ei_traits<VectorType>::ColsAtCompileTime==1 && ei_traits<VectorType>::RowsAtCompileTime!=1
IsColVector = !(ei_traits<VectorType>::Flags & RowMajorBit)
};
public:
EIGEN_DENSE_PUBLIC_INTERFACE(VectorBlock)

View File

@ -77,11 +77,12 @@ struct ei_traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> >
CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags & PacketAccessBit)
&& (RowsAtCompileTime == Dynamic || (RowsAtCompileTime % ei_packet_traits<Scalar>::size) == 0),
EvalToRowMajor = RhsRowMajor && (!CanVectorizeLhs),
EvalToRowMajor = (RowsAtCompileTime==1&&ColsAtCompileTime!=1) ? 1
: (ColsAtCompileTime==1&&RowsAtCompileTime!=1) ? 0
: (RhsRowMajor && !CanVectorizeLhs),
RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit),
Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & ~RowMajorBit)
| (EvalToRowMajor ? RowMajorBit : 0)
| NestingFlags
| (CanVectorizeLhs || CanVectorizeRhs ? PacketAccessBit : 0)
| (LhsFlags & RhsFlags & AlignedBit),

View File

@ -82,7 +82,8 @@
THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX,
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE,
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES,
YOU_ALREADY_SPECIFIED_THIS_STRIDE
YOU_ALREADY_SPECIFIED_THIS_STRIDE,
INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION
};
};
@ -144,12 +145,17 @@
YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES)
#define EIGEN_PREDICATE_SAME_MATRIX_SIZE(TYPE0,TYPE1) \
((int(TYPE0::RowsAtCompileTime)==Eigen::Dynamic \
|| int(TYPE1::RowsAtCompileTime)==Eigen::Dynamic \
|| int(TYPE0::RowsAtCompileTime)==int(TYPE1::RowsAtCompileTime)) \
&& (int(TYPE0::ColsAtCompileTime)==Eigen::Dynamic \
|| int(TYPE1::ColsAtCompileTime)==Eigen::Dynamic \
|| int(TYPE0::ColsAtCompileTime)==int(TYPE1::ColsAtCompileTime)))
( \
(int(TYPE0::SizeAtCompileTime)==0 && int(TYPE1::SizeAtCompileTime)==0) \
|| (\
(int(TYPE0::RowsAtCompileTime)==Eigen::Dynamic \
|| int(TYPE1::RowsAtCompileTime)==Eigen::Dynamic \
|| int(TYPE0::RowsAtCompileTime)==int(TYPE1::RowsAtCompileTime)) \
&& (int(TYPE0::ColsAtCompileTime)==Eigen::Dynamic \
|| int(TYPE1::ColsAtCompileTime)==Eigen::Dynamic \
|| int(TYPE0::ColsAtCompileTime)==int(TYPE1::ColsAtCompileTime))\
) \
)
// static assertion failing if it is guaranteed at compile-time that the two matrix expression types have different sizes
#define EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(TYPE0,TYPE1) \

View File

@ -203,10 +203,13 @@ struct ei_eval<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense
*/
template<typename T> struct ei_plain_matrix_type_column_major
{
enum { Rows = ei_traits<T>::RowsAtCompileTime,
Cols = ei_traits<T>::ColsAtCompileTime
};
typedef Matrix<typename ei_traits<T>::Scalar,
ei_traits<T>::RowsAtCompileTime,
ei_traits<T>::ColsAtCompileTime,
AutoAlign | ColMajor,
Rows,
Cols,
(Rows==1&&Cols!=1) ? RowMajor : ColMajor,
ei_traits<T>::MaxRowsAtCompileTime,
ei_traits<T>::MaxColsAtCompileTime
> type;
@ -216,10 +219,13 @@ template<typename T> struct ei_plain_matrix_type_column_major
*/
template<typename T> struct ei_plain_matrix_type_row_major
{
enum { Rows = ei_traits<T>::RowsAtCompileTime,
Cols = ei_traits<T>::ColsAtCompileTime
};
typedef Matrix<typename ei_traits<T>::Scalar,
ei_traits<T>::RowsAtCompileTime,
ei_traits<T>::ColsAtCompileTime,
AutoAlign | RowMajor,
Rows,
Cols,
(Cols==1&&Rows!=1) ? ColMajor : RowMajor,
ei_traits<T>::MaxRowsAtCompileTime,
ei_traits<T>::MaxColsAtCompileTime
> type;

View File

@ -58,7 +58,7 @@ template<typename _MatrixType> class Tridiagonalization
};
typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType;
typedef typename ei_plain_col_type<MatrixType>::type DiagonalType;
typedef typename ei_plain_col_type<MatrixType, RealScalar>::type DiagonalType;
typedef Matrix<RealScalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> SubDiagonalType;
typedef typename ei_plain_row_type<MatrixType>::type RowVectorType;

View File

@ -48,13 +48,14 @@ template<typename Scalar, int Size, int OtherSize> void symm(int size = Size, in
typedef Matrix<Scalar, Size, Size> MatrixType;
typedef Matrix<Scalar, Size, OtherSize> Rhs1;
typedef Matrix<Scalar, OtherSize, Size> Rhs2;
typedef Matrix<Scalar, Size, OtherSize,RowMajor> Rhs3;
enum { order = OtherSize==1 ? 0 : RowMajor };
typedef Matrix<Scalar, Size, OtherSize,order> Rhs3;
int rows = size;
int cols = size;
MatrixType m1 = MatrixType::Random(rows, cols),
m2 = MatrixType::Random(rows, cols);
m2 = MatrixType::Random(rows, cols), m3;
m1 = (m1+m1.adjoint()).eval();
@ -66,10 +67,14 @@ template<typename Scalar, int Size, int OtherSize> void symm(int size = Size, in
s2 = ei_random<Scalar>();
m2 = m1.template triangularView<Lower>();
m3 = m2.template selfadjointView<Lower>();
VERIFY_IS_EQUAL(m1, m3);
VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<Lower>() * (s2*rhs1),
rhs13 = (s1*m1) * (s2*rhs1));
m2 = m1.template triangularView<Upper>(); rhs12.setRandom(); rhs13 = rhs12;
m3 = m2.template selfadjointView<Upper>();
VERIFY_IS_EQUAL(m1, m3);
VERIFY_IS_APPROX(rhs12 += (s1*m2).template selfadjointView<Upper>() * (s2*rhs1),
rhs13 += (s1*m1) * (s2*rhs1));

View File

@ -43,8 +43,9 @@ template<typename Scalar,int Size, int Cols> void trsolve(int size=Size,int cols
Matrix<Scalar,Size,Size,ColMajor> cmLhs(size,size);
Matrix<Scalar,Size,Size,RowMajor> rmLhs(size,size);
Matrix<Scalar,Size,Cols,ColMajor> cmRhs(size,cols), ref(size,cols);
Matrix<Scalar,Size,Cols,RowMajor> rmRhs(size,cols);
enum { order = Size==1 ? RowMajor : ColMajor };
Matrix<Scalar,Size,Cols,order> cmRhs(size,cols), ref(size,cols);
Matrix<Scalar,Size,Cols,order> rmRhs(size,cols);
cmLhs.setRandom(); cmLhs *= static_cast<RealScalar>(0.1); cmLhs.diagonal().array() += static_cast<RealScalar>(1);
rmLhs.setRandom(); rmLhs *= static_cast<RealScalar>(0.1); rmLhs.diagonal().array() += static_cast<RealScalar>(1);