Add support for symbolic expressions as arguments of operator()

This commit is contained in:
Gael Guennebaud
2017-01-16 22:21:23 +01:00
parent 12e22a2844
commit 4989922be2
6 changed files with 126 additions and 80 deletions

View File

@@ -12,56 +12,6 @@
namespace Eigen {
/** \namespace Eigen::placeholders
* \ingroup Core_Module
*
* Namespace containing symbolic placeholder and identifiers
*/
namespace placeholders {
namespace internal {
struct symbolic_last_tag {};
}
/** \var last
* \ingroup Core_Module
*
* Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically reference the last element/row/columns
* of the underlying vector or matrix once passed to DenseBase::operator()(const RowIndices&, const ColIndices&).
*
* This symbolic placeholder support standard arithmetic operation.
*
* A typical usage example would be:
* \code
* using namespace Eigen;
* using Eigen::placeholders::last;
* VectorXd v(n);
* v(seq(2,last-2)).setOnes();
* \endcode
*
* \sa end
*/
static const Symbolic::SymbolExpr<internal::symbolic_last_tag> last;
/** \var end
* \ingroup Core_Module
*
* Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically reference the last+1 element/row/columns
* of the underlying vector or matrix once passed to DenseBase::operator()(const RowIndices&, const ColIndices&).
*
* This symbolic placeholder support standard arithmetic operation.
* It is essentially an alias to last+1
*
* \sa last
*/
#ifdef EIGEN_PARSED_BY_DOXYGEN
static const auto end = last+1;
#else
static const Symbolic::AddExpr<Symbolic::SymbolExpr<internal::symbolic_last_tag>,Symbolic::ValueExpr> end(last+1);
#endif
} // end namespace placeholders
//--------------------------------------------------------------------------------
// seq(first,last,incr) and seqN(first,size,incr)
//--------------------------------------------------------------------------------
@@ -293,18 +243,6 @@ seq(const Symbolic::BaseExpr<FirstTypeDerived> &f, const Symbolic::BaseExpr<Last
namespace internal {
// Replace symbolic last/end "keywords" by their true runtime value
inline Index eval_expr_given_size(Index x, Index /* size */) { return x; }
template<int N>
fix_t<N> eval_expr_given_size(fix_t<N> x, Index /*size*/) { return x; }
template<typename Derived>
Index eval_expr_given_size(const Symbolic::BaseExpr<Derived> &x, Index size)
{
return x.derived().eval(placeholders::last=size-1);
}
// Convert a symbolic span into a usable one (i.e., remove last/end "keywords")
template<typename T>
struct make_size_type {
@@ -318,7 +256,7 @@ struct IndexedViewCompatibleType<ArithmeticSequence<FirstType,SizeType,IncrType>
template<typename FirstType,typename SizeType,typename IncrType>
ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType>
makeIndexedViewCompatible(const ArithmeticSequence<FirstType,SizeType,IncrType>& ids, Index size) {
makeIndexedViewCompatible(const ArithmeticSequence<FirstType,SizeType,IncrType>& ids, Index size,SpecializedType) {
return ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType>(
eval_expr_given_size(ids.firstObject(),size),eval_expr_given_size(ids.sizeObject(),size),ids.incrObject());
}
@@ -436,7 +374,7 @@ struct IndexedViewCompatibleType<legacy::ArithmeticSequenceProxyWithBounds<First
template<typename FirstType,typename LastType,typename IncrType>
legacy::ArithmeticSequenceProxyWithBounds<Index,Index,IncrType>
makeIndexedViewCompatible(const legacy::ArithmeticSequenceProxyWithBounds<FirstType,LastType,IncrType>& ids, Index size) {
makeIndexedViewCompatible(const legacy::ArithmeticSequenceProxyWithBounds<FirstType,LastType,IncrType>& ids, Index size,SpecializedType) {
return legacy::ArithmeticSequenceProxyWithBounds<Index,Index,IncrType>(
eval_expr_given_size(ids.firstObject(),size),eval_expr_given_size(ids.lastObject(),size),ids.incrObject());
}

View File

@@ -45,6 +45,10 @@ struct traits<IndexedView<XprType, RowIndices, ColIndices> >
InnerStrideAtCompileTime = InnerIncr<0 || InnerIncr==DynamicIndex || XprInnerStride==Dynamic ? Dynamic : XprInnerStride * InnerIncr,
OuterStrideAtCompileTime = OuterIncr<0 || OuterIncr==DynamicIndex || XprOuterstride==Dynamic ? Dynamic : XprOuterstride * OuterIncr,
ReturnAsScalar = is_same<RowIndices,SingleRange>::value && is_same<ColIndices,SingleRange>::value,
ReturnAsBlock = (!ReturnAsScalar) && IsBlockAlike,
ReturnAsIndexedView = (!ReturnAsScalar) && (!ReturnAsBlock),
// FIXME we deal with compile-time strides if and only if we have DirectAccessBit flag,
// but this is too strict regarding negative strides...
DirectAccessMask = (InnerIncr!=UndefinedIncr && OuterIncr!=UndefinedIncr && InnerIncr>=0 && OuterIncr>=0) ? DirectAccessBit : 0,
@@ -91,8 +95,8 @@ class IndexedViewImpl;
* - decltype(ArrayXi::LinSpaced(...))
* - Any view/expressions of the previous types
* - Eigen::ArithmeticSequence
* - Eigen::AllRange (helper for Eigen::all)
* - Eigen::IntAsArray (helper for single index)
* - Eigen::internal::AllRange (helper for Eigen::all)
* - Eigen::internal::SingleRange (helper for single index)
* - etc.
*
* In typical usages of %Eigen, this class should never be used directly. It is the return type of

View File

@@ -13,7 +13,69 @@
namespace Eigen {
/** \namespace Eigen::placeholders
* \ingroup Core_Module
*
* Namespace containing symbolic placeholder and identifiers
*/
namespace placeholders {
namespace internal {
struct symbolic_last_tag {};
}
/** \var last
* \ingroup Core_Module
*
* Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically reference the last element/row/columns
* of the underlying vector or matrix once passed to DenseBase::operator()(const RowIndices&, const ColIndices&).
*
* This symbolic placeholder support standard arithmetic operation.
*
* A typical usage example would be:
* \code
* using namespace Eigen;
* using Eigen::placeholders::last;
* VectorXd v(n);
* v(seq(2,last-2)).setOnes();
* \endcode
*
* \sa end
*/
static const Symbolic::SymbolExpr<internal::symbolic_last_tag> last;
/** \var end
* \ingroup Core_Module
*
* Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically reference the last+1 element/row/columns
* of the underlying vector or matrix once passed to DenseBase::operator()(const RowIndices&, const ColIndices&).
*
* This symbolic placeholder support standard arithmetic operation.
* It is essentially an alias to last+1
*
* \sa last
*/
#ifdef EIGEN_PARSED_BY_DOXYGEN
static const auto end = last+1;
#else
static const Symbolic::AddExpr<Symbolic::SymbolExpr<internal::symbolic_last_tag>,Symbolic::ValueExpr> end(last+1);
#endif
} // end namespace placeholders
namespace internal {
// Replace symbolic last/end "keywords" by their true runtime value
inline Index eval_expr_given_size(Index x, Index /* size */) { return x; }
template<int N>
fix_t<N> eval_expr_given_size(fix_t<N> x, Index /*size*/) { return x; }
template<typename Derived>
Index eval_expr_given_size(const Symbolic::BaseExpr<Derived> &x, Index size)
{
return x.derived().eval(placeholders::last=size-1);
}
// Extract increment/step at compile time
template<typename T, typename EnableIf = void> struct get_compile_time_incr {
@@ -31,8 +93,8 @@ struct IndexedViewCompatibleType {
typedef T type;
};
template<typename T>
const T& makeIndexedViewCompatible(const T& x, Index /*size*/) { return x; }
template<typename T,typename Q>
const T& makeIndexedViewCompatible(const T& x, Index /*size*/, Q) { return x; }
//--------------------------------------------------------------------------------
// Handling of a single Index
@@ -62,6 +124,18 @@ struct IndexedViewCompatibleType<T,XprSize,typename internal::enable_if<internal
typedef SingleRange type;
};
template<typename T, int XprSize>
struct IndexedViewCompatibleType<T, XprSize, typename enable_if<Symbolic::is_symbolic<T>::value>::type> {
typedef SingleRange type;
};
template<typename T>
typename enable_if<Symbolic::is_symbolic<T>::value,SingleRange>::type
makeIndexedViewCompatible(const T& id, Index size, SpecializedType) {
return eval_expr_given_size(id,size);
}
//--------------------------------------------------------------------------------
// Handling of all
//--------------------------------------------------------------------------------
@@ -85,7 +159,7 @@ struct IndexedViewCompatibleType<all_t,XprSize> {
};
template<typename XprSizeType>
inline AllRange<get_compile_time<XprSizeType>::value> makeIndexedViewCompatible(all_t , XprSizeType size) {
inline AllRange<get_compile_time<XprSizeType>::value> makeIndexedViewCompatible(all_t , XprSizeType size, SpecializedType) {
return AllRange<get_compile_time<XprSizeType>::value>(size);
}