// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_XPRHELPER_H #define EIGEN_XPRHELPER_H // just a workaround because GCC seems to not really like empty structs // FIXME: gcc 4.3 generates bad code when strict-aliasing is enabled // so currently we simply disable this optimization for gcc 4.3 #if EIGEN_COMP_GNUC && !EIGEN_GNUC_AT(4,3) #define EIGEN_EMPTY_STRUCT_CTOR(X) \ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE X() {} \ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE X(const X& ) {} #else #define EIGEN_EMPTY_STRUCT_CTOR(X) #endif namespace Eigen { typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex; /** * \brief The Index type as used for the API. * \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE. * \sa \ref TopicPreprocessorDirectives, StorageIndex. */ typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE Index; namespace internal { template EIGEN_DEVICE_FUNC inline IndexDest convert_index(const IndexSrc& idx) { // for sizeof(IndexDest)>=sizeof(IndexSrc) compilers should be able to optimize this away: eigen_internal_assert(idx <= NumTraits::highest() && "Index value to big for target type"); return IndexDest(idx); } //classes inheriting no_assignment_operator don't generate a default operator=. class no_assignment_operator { private: no_assignment_operator& operator=(const no_assignment_operator&); }; /** \internal return the index type with the largest number of bits */ template struct promote_index_type { typedef typename conditional<(sizeof(I1)::type type; }; /** \internal If the template parameter Value is Dynamic, this class is just a wrapper around a T variable that * can be accessed using value() and setValue(). * Otherwise, this class is an empty structure and value() just returns the template parameter Value. */ template class variable_if_dynamic { public: EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamic) EIGEN_DEVICE_FUNC explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); } EIGEN_DEVICE_FUNC static T value() { return T(Value); } EIGEN_DEVICE_FUNC void setValue(T) {} }; template class variable_if_dynamic { T m_value; EIGEN_DEVICE_FUNC variable_if_dynamic() { eigen_assert(false); } public: EIGEN_DEVICE_FUNC explicit variable_if_dynamic(T value) : m_value(value) {} EIGEN_DEVICE_FUNC T value() const { return m_value; } EIGEN_DEVICE_FUNC void setValue(T value) { m_value = value; } }; /** \internal like variable_if_dynamic but for DynamicIndex */ template class variable_if_dynamicindex { public: EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamicindex) EIGEN_DEVICE_FUNC explicit variable_if_dynamicindex(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); eigen_assert(v == T(Value)); } EIGEN_DEVICE_FUNC static T value() { return T(Value); } EIGEN_DEVICE_FUNC void setValue(T) {} }; template class variable_if_dynamicindex { T m_value; EIGEN_DEVICE_FUNC variable_if_dynamicindex() { eigen_assert(false); } public: EIGEN_DEVICE_FUNC explicit variable_if_dynamicindex(T value) : m_value(value) {} EIGEN_DEVICE_FUNC T value() const { return m_value; } EIGEN_DEVICE_FUNC void setValue(T value) { m_value = value; } }; template struct functor_traits { enum { Cost = 10, PacketAccess = false, IsRepeatable = false }; }; template struct packet_traits; template struct unpacket_traits { typedef T type; typedef T half; enum {size=1}; }; template class make_proper_matrix_type { enum { IsColVector = _Cols==1 && _Rows!=1, IsRowVector = _Rows==1 && _Cols!=1, Options = IsColVector ? (_Options | ColMajor) & ~RowMajor : IsRowVector ? (_Options | RowMajor) & ~ColMajor : _Options }; public: typedef Matrix<_Scalar, _Rows, _Cols, Options, _MaxRows, _MaxCols> type; }; template class compute_matrix_flags { enum { row_major_bit = Options&RowMajor ? RowMajorBit : 0 }; public: // FIXME currently we still have to handle DirectAccessBit at the expression level to handle DenseCoeffsBase<> // and then propagate this information to the evaluator's flags. // However, I (Gael) think that DirectAccessBit should only matter at the evaluation stage. enum { ret = DirectAccessBit | LvalueBit | NestByRefBit | row_major_bit }; }; template class compute_matrix_evaluator_flags { enum { row_major_bit = Options&RowMajor ? RowMajorBit : 0, is_dynamic_size_storage = MaxRows==Dynamic || MaxCols==Dynamic, // TODO: should check for smaller packet types once we can handle multi-sized packet types align_bytes = int(packet_traits::size) * sizeof(Scalar), aligned_bit = ( ((Options&DontAlign)==0) && ( #if EIGEN_ALIGN_STATICALLY ((!is_dynamic_size_storage) && (((MaxCols*MaxRows*int(sizeof(Scalar))) % align_bytes) == 0)) #else 0 #endif || #if EIGEN_ALIGN is_dynamic_size_storage #else 0 #endif ) ) ? AlignedBit : 0, packet_access_bit = packet_traits::Vectorizable && aligned_bit ? PacketAccessBit : 0 }; public: enum { ret = LinearAccessBit | DirectAccessBit | packet_access_bit | row_major_bit | aligned_bit }; }; template struct size_at_compile_time { enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols }; }; template struct size_of_xpr_at_compile_time { enum { ret = size_at_compile_time::RowsAtCompileTime,traits::ColsAtCompileTime>::ret }; }; /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type, * whereas eval is a const reference in the case of a matrix */ template::StorageKind> struct plain_matrix_type; template struct plain_matrix_type_dense; template struct plain_matrix_type { typedef typename plain_matrix_type_dense::XprKind>::type type; }; template struct plain_matrix_type { typedef typename T::PlainObject type; }; template struct plain_matrix_type_dense { typedef Matrix::Scalar, traits::RowsAtCompileTime, traits::ColsAtCompileTime, AutoAlign | (traits::Flags&RowMajorBit ? RowMajor : ColMajor), traits::MaxRowsAtCompileTime, traits::MaxColsAtCompileTime > type; }; template struct plain_matrix_type_dense { typedef Array::Scalar, traits::RowsAtCompileTime, traits::ColsAtCompileTime, AutoAlign | (traits::Flags&RowMajorBit ? RowMajor : ColMajor), traits::MaxRowsAtCompileTime, traits::MaxColsAtCompileTime > type; }; /* eval : the return type of eval(). For matrices, this is just a const reference * in order to avoid a useless copy */ template::StorageKind> struct eval; template struct eval { typedef typename plain_matrix_type::type type; // typedef typename T::PlainObject type; // typedef T::Matrix::Scalar, // traits::RowsAtCompileTime, // traits::ColsAtCompileTime, // AutoAlign | (traits::Flags&RowMajorBit ? RowMajor : ColMajor), // traits::MaxRowsAtCompileTime, // traits::MaxColsAtCompileTime // > type; }; template struct eval { typedef typename plain_matrix_type::type type; }; // for matrices, no need to evaluate, just use a const reference to avoid a useless copy template struct eval, Dense> { typedef const Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type; }; template struct eval, Dense> { typedef const Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type; }; /* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major */ template struct plain_matrix_type_column_major { enum { Rows = traits::RowsAtCompileTime, Cols = traits::ColsAtCompileTime, MaxRows = traits::MaxRowsAtCompileTime, MaxCols = traits::MaxColsAtCompileTime }; typedef Matrix::Scalar, Rows, Cols, (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor, MaxRows, MaxCols > type; }; /* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major */ template struct plain_matrix_type_row_major { enum { Rows = traits::RowsAtCompileTime, Cols = traits::ColsAtCompileTime, MaxRows = traits::MaxRowsAtCompileTime, MaxCols = traits::MaxColsAtCompileTime }; typedef Matrix::Scalar, Rows, Cols, (MaxCols==1&&MaxRows!=1) ? RowMajor : ColMajor, MaxRows, MaxCols > type; }; // TODO we should be able to get rid of this one too template struct must_nest_by_value { enum { ret = false }; }; /** \internal The reference selector for template expressions. The idea is that we don't * need to use references for expressions since they are light weight proxy * objects which should generate no copying overhead. */ template struct ref_selector { typedef typename conditional< bool(traits::Flags & NestByRefBit), T const&, const T >::type type; }; /** \internal Adds the const qualifier on the value-type of T2 if and only if T1 is a const type */ template struct transfer_constness { typedef typename conditional< bool(internal::is_const::value), typename internal::add_const_on_value_type::type, T2 >::type type; }; // However, we still need a mechanism to detect whether an expression which is evaluated multiple time // has to be evaluated into a temporary. // That's the purpose of this new nested_eval helper: /** \internal Determines how a given expression should be nested when evaluated multiple times. * For example, when you do a * (b+c), Eigen will determine how the expression b+c should be * evaluated into the bigger product expression. The choice is between nesting the expression b+c as-is, or * evaluating that expression b+c into a temporary variable d, and nest d so that the resulting expression is * a*d. Evaluating can be beneficial for example if every coefficient access in the resulting expression causes * many coefficient accesses in the nested expressions -- as is the case with matrix product for example. * * \param T the type of the expression being nested. * \param n the number of coefficient accesses in the nested expression for each coefficient access in the bigger expression. * \param PlainObject the type of the temporary if needed. */ template::type> struct nested_eval { enum { // For the purpose of this test, to keep it reasonably simple, we arbitrarily choose a value of Dynamic values. // the choice of 10000 makes it larger than any practical fixed value and even most dynamic values. // in extreme cases where these assumptions would be wrong, we would still at worst suffer performance issues // (poor choice of temporaries). // It's important that this value can still be squared without integer overflowing. DynamicAsInteger = 10000, ScalarReadCost = NumTraits::Scalar>::ReadCost, ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? int(DynamicAsInteger) : int(ScalarReadCost), CoeffReadCost = evaluator::CoeffReadCost, // TODO What if an evaluator evaluate itself into a tempory? // Then CoeffReadCost will be small but we still have to evaluate if n>1... // The solution might be to ask the evaluator if it creates a temp. Perhaps we could even ask the number of temps? CoeffReadCostAsInteger = CoeffReadCost == Dynamic ? int(DynamicAsInteger) : int(CoeffReadCost), NAsInteger = n == Dynamic ? int(DynamicAsInteger) : n, CostEvalAsInteger = (NAsInteger+1) * ScalarReadCostAsInteger + CoeffReadCostAsInteger, CostNoEvalAsInteger = NAsInteger * CoeffReadCostAsInteger }; typedef typename conditional< ( (int(evaluator::Flags) & EvalBeforeNestingBit) || (int(CostEvalAsInteger) < int(CostNoEvalAsInteger)) ), PlainObject, typename ref_selector::type >::type type; }; template EIGEN_DEVICE_FUNC inline T* const_cast_ptr(const T* ptr) { return const_cast(ptr); } template::XprKind> struct dense_xpr_base { /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */ }; template struct dense_xpr_base { typedef MatrixBase type; }; template struct dense_xpr_base { typedef ArrayBase type; }; template::XprKind, typename StorageKind = typename traits::StorageKind> struct generic_xpr_base; template struct generic_xpr_base { typedef typename dense_xpr_base::type type; }; /** \internal Helper base class to add a scalar multiple operator * overloads for complex types */ template::value > struct special_scalar_op_base : public DenseCoeffsBase { // dummy operator* so that the // "using special_scalar_op_base::operator*" compiles void operator*() const; }; template struct special_scalar_op_base : public DenseCoeffsBase { const CwiseUnaryOp, Derived> operator*(const OtherScalar& scalar) const { #ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN #endif return CwiseUnaryOp, Derived> (*static_cast(this), scalar_multiple2_op(scalar)); } inline friend const CwiseUnaryOp, Derived> operator*(const OtherScalar& scalar, const Derived& matrix) { #ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN #endif return static_cast(matrix).operator*(scalar); } }; template struct cast_return_type { typedef typename XprType::Scalar CurrentScalarType; typedef typename remove_all::type _CastType; typedef typename _CastType::Scalar NewScalarType; typedef typename conditional::value, const XprType&,CastType>::type type; }; template struct promote_storage_type; template struct promote_storage_type { typedef A ret; }; template struct promote_storage_type { typedef A ret; }; template struct promote_storage_type { typedef A ret; }; /** \internal Specify the "storage kind" of applying a coefficient-wise * binary operations between two expressions of kinds A and B respectively. * The template parameter Functor permits to specialize the resulting storage kind wrt to * the functor. * The default rules are as follows: * \code * A op A -> A * A op dense -> dense * dense op B -> dense * A * dense -> A * dense * B -> B * \endcode */ template struct cwise_promote_storage_type; template struct cwise_promote_storage_type { typedef A ret; }; template struct cwise_promote_storage_type { typedef Dense ret; }; template struct cwise_promote_storage_type > { typedef Dense ret; }; template struct cwise_promote_storage_type { typedef Dense ret; }; template struct cwise_promote_storage_type { typedef Dense ret; }; template struct cwise_promote_storage_type > { typedef A ret; }; template struct cwise_promote_storage_type > { typedef B ret; }; /** \internal Specify the "storage kind" of multiplying an expression of kind A with kind B. * The template parameter ProductTag permits to specialize the resulting storage kind wrt to * some compile-time properties of the product: GemmProduct, GemvProduct, OuterProduct, InnerProduct. * The default rules are as follows: * \code * K * K -> K * dense * K -> dense * K * dense -> dense * diag * K -> K * K * diag -> K * Perm * K -> K * K * Perm -> K * \endcode */ template struct product_promote_storage_type; template struct product_promote_storage_type { typedef A ret;}; template struct product_promote_storage_type { typedef Dense ret;}; template struct product_promote_storage_type { typedef Dense ret; }; template struct product_promote_storage_type { typedef Dense ret; }; template struct product_promote_storage_type { typedef A ret; }; template struct product_promote_storage_type { typedef B ret; }; template struct product_promote_storage_type { typedef Dense ret; }; template struct product_promote_storage_type { typedef Dense ret; }; template struct product_promote_storage_type { typedef A ret; }; template struct product_promote_storage_type { typedef B ret; }; template struct product_promote_storage_type { typedef Dense ret; }; template struct product_promote_storage_type { typedef Dense ret; }; /** \internal gives the plain matrix or array type to store a row/column/diagonal of a matrix type. * \param Scalar optional parameter allowing to pass a different scalar type than the one of the MatrixType. */ template struct plain_row_type { typedef Matrix MatrixRowType; typedef Array ArrayRowType; typedef typename conditional< is_same< typename traits::XprKind, MatrixXpr >::value, MatrixRowType, ArrayRowType >::type type; }; template struct plain_col_type { typedef Matrix MatrixColType; typedef Array ArrayColType; typedef typename conditional< is_same< typename traits::XprKind, MatrixXpr >::value, MatrixColType, ArrayColType >::type type; }; template struct plain_diag_type { enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime), max_diag_size = EIGEN_SIZE_MIN_PREFER_FIXED(ExpressionType::MaxRowsAtCompileTime, ExpressionType::MaxColsAtCompileTime) }; typedef Matrix MatrixDiagType; typedef Array ArrayDiagType; typedef typename conditional< is_same< typename traits::XprKind, MatrixXpr >::value, MatrixDiagType, ArrayDiagType >::type type; }; template struct is_lvalue { enum { value = !bool(is_const::value) && bool(traits::Flags & LvalueBit) }; }; template struct is_diagonal { enum { ret = false }; }; template struct is_diagonal > { enum { ret = true }; }; template struct is_diagonal > { enum { ret = true }; }; template struct is_diagonal > { enum { ret = true }; }; template struct glue_shapes; template<> struct glue_shapes { typedef TriangularShape type; }; template bool is_same_dense(const T1 &mat1, const T2 &mat2, typename enable_if::ret&&has_direct_access::ret, T1>::type * = 0) { return (mat1.data()==mat2.data()) && (mat1.innerStride()==mat2.innerStride()) && (mat1.outerStride()==mat2.outerStride()); } template bool is_same_dense(const T1 &, const T2 &, typename enable_if::ret&&has_direct_access::ret), T1>::type * = 0) { return false; } } // end namespace internal // we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor // that would take two operands of different types. If there were such an example, then this check should be // moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as // currently they take only one typename Scalar template parameter. // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths. // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to // add together a float matrix and a double matrix. #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \ EIGEN_STATIC_ASSERT((internal::functor_is_product_like::ret \ ? int(internal::scalar_product_traits::Defined) \ : int(internal::is_same::value)), \ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) } // end namespace Eigen #endif // EIGEN_XPRHELPER_H