// 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, alignment = 1 }; }; template::size)==0 || is_same::half>::value> struct find_best_packet_helper; template< int Size, typename PacketType> struct find_best_packet_helper { typedef PacketType type; }; template struct find_best_packet_helper { typedef typename find_best_packet_helper::half>::type type; }; template struct find_best_packet { typedef typename find_best_packet_helper::type>::type type; }; #if EIGEN_MAX_STATIC_ALIGN_BYTES>0 templateEIGEN_MIN_ALIGN_BYTES) > struct compute_default_alignment_helper { enum { value = 0 }; }; template struct compute_default_alignment_helper // Match { enum { value = AlignmentBytes }; }; template struct compute_default_alignment_helper // Try-half { // current packet too large, try with an half-packet enum { value = compute_default_alignment_helper::value }; }; #else // If static alignment is disabled, no need to bother. // This also avoids a division by zero in "bool Match = bool((ArrayBytes%AlignmentBytes)==0)" template struct compute_default_alignment_helper { enum { value = 0 }; }; #endif template struct compute_default_alignment { enum { value = compute_default_alignment_helper::value }; }; template struct compute_default_alignment { enum { value = EIGEN_MAX_ALIGN_BYTES }; }; 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 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, traits::Flags>::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 | (Flags&RowMajorBit ? RowMajor : ColMajor), traits::MaxRowsAtCompileTime, traits::MaxColsAtCompileTime > type; }; template struct plain_matrix_type_dense { typedef Array::Scalar, traits::RowsAtCompileTime, traits::ColsAtCompileTime, AutoAlign | (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; }; /* similar to plain_matrix_type, but using the evaluator's Flags */ template::StorageKind> struct plain_object_eval; template struct plain_object_eval { typedef typename plain_matrix_type_dense::XprKind, evaluator::Flags>::type 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; }; /** \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; typedef typename conditional< bool(traits::Flags & NestByRefBit), T &, T >::type non_const_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 { ScalarReadCost = NumTraits::Scalar>::ReadCost, CoeffReadCost = evaluator::CoeffReadCost, // NOTE What if an evaluator evaluate itself into a tempory? // Then CoeffReadCost will be small (e.g., 1) but we still have to evaluate, especially if n>1. // This situation is already taken care by the EvalBeforeNestingBit flag, which is turned ON // for all evaluator creating a temporary. This flag is then propagated by the parent evaluators. // Another solution could be to count the number of temps? NAsInteger = n == Dynamic ? HugeCost : n, CostEval = (NAsInteger+1) * ScalarReadCost + CoeffReadCost, CostNoEval = NAsInteger * CoeffReadCost }; typedef typename conditional< ( (int(evaluator::Flags) & EvalBeforeNestingBit) || (int(CostEval) < int(CostNoEval)) ), 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 BaseType { // dummy operator* so that the // "using special_scalar_op_base::operator*" compiles struct dummy {}; void operator*(dummy) const; void operator/(dummy) const; }; template struct special_scalar_op_base : public BaseType { 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); } 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_quotient2_op(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; } template struct is_same_or_void { enum { value = is_same::value }; }; template struct is_same_or_void { enum { value = 1 }; }; template struct is_same_or_void { enum { value = 1 }; }; template<> struct is_same_or_void { enum { value = 1 }; }; #ifdef EIGEN_DEBUG_ASSIGN std::string demangle_traversal(int t) { if(t==DefaultTraversal) return "DefaultTraversal"; if(t==LinearTraversal) return "LinearTraversal"; if(t==InnerVectorizedTraversal) return "InnerVectorizedTraversal"; if(t==LinearVectorizedTraversal) return "LinearVectorizedTraversal"; if(t==SliceVectorizedTraversal) return "SliceVectorizedTraversal"; return "?"; } std::string demangle_unrolling(int t) { if(t==NoUnrolling) return "NoUnrolling"; if(t==InnerUnrolling) return "InnerUnrolling"; if(t==CompleteUnrolling) return "CompleteUnrolling"; return "?"; } std::string demangle_flags(int f) { std::string res; if(f&RowMajorBit) res += " | RowMajor"; if(f&PacketAccessBit) res += " | Packet"; if(f&LinearAccessBit) res += " | Linear"; if(f&LvalueBit) res += " | Lvalue"; if(f&DirectAccessBit) res += " | Direct"; if(f&NestByRefBit) res += " | NestByRef"; if(f&NoPreferredStorageOrderBit) res += " | NoPreferredStorageOrderBit"; return res; } #endif } // 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_or_void::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