2016-12-22 4 views
5

최신 설명서 https://eigen.tuxfamily.org/dox-devel/TopicNewExpressionType.html에 이어 새로운 Eigen 표현식을 작성하려고합니다. 기본적으로, 내가 원하는 것은 Eigen에서 여전히 존재하지 않는 모양 변경 기능의 일부입니다. 그래서 chop_expr (여기서 고유 벡터 표현)은 입력 벡터를 n 번 매트릭스로 변형해야합니다.새로운 고유 표현 작성

불행히도 내가 구현 한 코드는 힙에 할당 된 식과 작동하지 않습니다. 예를 들어 아래 코드는 작동하지 않지만 MAXV를 10으로 변경하면 모든 것이 완벽 해집니다.

또 다른 질문에 대한

enum {Flags = EvalBeforeNestingBit} 

나는 내가 행렬 곱셈을 잘라 때, 아이겐는 임시직을 만들지 않습니다,하지만 난 chop_expr을 강제로이 방법은 임의의 임시 만들 수 있다는 생각, 그렇지 않으면이 필요하다는 것을 발견 다른 표현들도. 그래서 문제는 어떻게해야 제대로 할 수 있을까요?

namespace Eigen { 

template <int chunk, typename Derived> struct ChoppedExpression; 

namespace internal { 

template <int chunk, typename Derived> 
struct traits<ChoppedExpression<chunk, Derived>> : traits<Derived> { 
    enum {Flags = EvalBeforeNestingBit}; 
    enum {IsRowMajor = 0}; 

    enum { RowsAtCompileTime = chunk}; 
    enum {MaxRowsAtCompileTime = chunk}; 

    enum {ColsAtCompileTime = (Derived::RowsAtCompileTime == Eigen::Dynamic 
     ? Eigen::Dynamic : Derived::RowsAtCompileTime/chunk)}; 

    enum {MaxColsAtCompileTime = (Derived::MaxRowsAtCompileTime == Eigen::Dynamic 
     ? Eigen::Dynamic : (Derived::MaxRowsAtCompileTime + chunk - 1)/chunk)}; 
}; 

} // namespace internal 

template <int chunk, class Derived> struct ChoppedExpression 
    : public MatrixBase<ChoppedExpression<chunk, Derived>> { 

    ChoppedExpression(const Derived& arg) : m_arg(arg) { 
    EIGEN_STATIC_ASSERT(Derived::ColsAtCompileTime == 1, 
     YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX); 

    EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime % chunk == 0 
     || Derived::RowsAtCompileTime == Eigen::Dynamic, 
     VECTOR_SHOULD_HAVE_INTEGER_NUMBER_OF_CHUNKS_FOR_CHOPPING); 
    } 

    typedef Index Index; 

    EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rows() const { return chunk; } 
    EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const { return m_arg.size()/chunk; } 

    typedef typename internal::ref_selector<ChoppedExpression>::type Nested; 
    typedef typename internal::ref_selector<Derived>::type DerivedTypeNested; 

    DerivedTypeNested m_arg; 
}; 

namespace internal { 

template<int chunk, typename Derived> 
struct evaluator<ChoppedExpression<chunk, Derived>> 
    : public evaluator_base<ChoppedExpression<chunk, Derived>> { 

    typedef ChoppedExpression<chunk, Derived> XprType; 
    typedef typename nested_eval<Derived, XprType::ColsAtCompileTime>::type DerivedNested; 
    typedef typename remove_all<DerivedNested>::type DerivedNestedCleaned; 
    typedef typename XprType::CoeffReturnType CoeffReturnType; 

    enum { 
    CoeffReadCost = evaluator<DerivedNestedCleaned>::CoeffReadCost, 
    Flags = traits<XprType>::Flags, IsRowMajor = 0 
    }; 

    evaluator(const XprType& xpr) : m_argImpl(xpr.m_arg) {} 

    EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const 
    { return m_argImpl.coeff(col * chunk + row); } 

    evaluator<DerivedNestedCleaned> m_argImpl; 
}; 

} // namespace internal 
} // namespace Eigen 

template<int chunk, typename Derived> EIGEN_ALWAYS_INLINE 
EIGEN_DEVICE_FUNC static Eigen::ChoppedExpression<chunk, Derived> 
chop_expr(const Eigen::MatrixBase<Derived> &expr) 
    { return Eigen::ChoppedExpression<chunk, Derived>(expr.derived()); } 


#define MAXV -1 

Eigen::Matrix<double, -1, 1, 0, std::max(3*MAXV, -1)> _blendshapes(2, 1); 

int main() { 
    for (int i = 0; i < 2; ++i) _blendshapes[i] = double(i + 10); 

    std::cout << chop_expr<2>(_blendshapes + Eigen::Matrix<double, 2, 1>(1, 1)) << std::endl; 
} 

업데이트

마지막으로, 나는 그것이 작동되도록하는 방법을 발견했다. 해결 방법은 DerivedNested 및 DerivedNestedCleaned typedef를 제거하는 것입니다. (필자가 표현식에서 필요로하지 않는 것은 분명히 모양을 바꿀 뿐이지 만 잘못된 결과가 나오는 이유를 설명 할 수는 없습니다.) 따라서 남은 유일한 질문은 EvalBeforeNestingBit에 대해 어떻게해야합니까?

답변

2

EvalBeforeNestingBit은 필요하지 않지만 평가 기에서 플래그를 전파 할 때는주의해야합니다.

Flags = traits<XprType>::Flags&HereditaryBits 
+0

적어도 일부 표현에 대한 특성 (예를 들어, 아이겐 :: 내부 :: 특성 :: 플래그) 제로 것 같다, 그래서 사용 : 안전을 위해, 쓰기 평가자 :: 플래그 대신. 하지만 당신은 분명히 그 문제를 지적했습니다. –