/* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ extern void __assert_fail(const char*, const char*, int, const char*); namespace Eigen { enum { AutoAlign }; template <int, typename> struct conditional; template <typename Else> struct conditional<false, Else> { typedef Else type; }; template <typename T> struct remove_reference { typedef T type; }; struct is_arithmetic { enum { value }; }; template <typename> struct traits; template <typename T> struct traits<const T> : traits<T> {}; template <typename> struct evaluator; template <typename> struct EigenBase; template <typename> class PlainObjectBase; template <typename, int _Rows, int _Cols, int = AutoAlign, int = _Rows, int = _Cols> class Matrix; template <typename> class MatrixBase; template <typename, typename> class CwiseNullaryOp; template <typename, typename, typename> class CwiseBinaryOp; template <typename> struct scalar_constant_op; template <int _Rows> struct size_at_compile_time { enum { ret = _Rows }; }; struct ref_selector { typedef const Matrix<float, 3, 1>& type; }; template <typename Derived> struct dense_xpr_base { typedef MatrixBase<Derived> type; }; template <typename Derived, typename = typename traits<Derived>::XprKind> struct generic_xpr_base { typedef typename dense_xpr_base<Derived>::type type; }; template <typename Expr, typename Scalar = typename Expr::Scalar> struct plain_constant_type { ; typedef CwiseNullaryOp<scalar_constant_op<Scalar>, Matrix<Scalar, traits<Expr>::ColsAtCompileTime, traits<Expr>::MaxRowsAtCompileTime, traits<Expr>::MaxColsAtCompileTime>> type; }; struct scalar_product_op { float operator()(float a, float b) { return a * b; } }; template <typename> struct scalar_constant_op { scalar_constant_op(float other) : m_other(other) {} float operator()() { return m_other; } float m_other; }; struct assign_op { void assignCoeff(float& a, float b) { a = b; } }; template <typename Derived> class DenseCoeffsBase : public EigenBase<Derived> { public: typedef typename traits<Derived>::Scalar Scalar; typedef typename conditional<is_arithmetic::value, Scalar>::type CoeffReturnType; }; template <typename Derived> class DenseBase : public DenseCoeffsBase<Derived> { public: enum { RowsAtCompileTime = traits<Derived>::RowsAtCompileTime, SizeAtCompileTime = size_at_compile_time<RowsAtCompileTime>::ret, MaxSizeAtCompileTime }; }; template <typename Derived> class MatrixBase : public DenseBase<Derived> { public: using DenseBase<Derived>::derived; template <typename T> CwiseBinaryOp<scalar_product_op, const Derived, const typename plain_constant_type<Derived, T>::type> operator*(T& scalar) { return CwiseBinaryOp<scalar_product_op, const Derived, const typename plain_constant_type<Derived>::type>( derived(), typename plain_constant_type<Derived>::type(derived().rows(), 0, scalar)); } }; template <typename Derived> struct EigenBase { const Derived& derived() const { return *static_cast<const Derived*>(this); } Derived& const_cast_derived() const { return *static_cast<Derived*>(const_cast<EigenBase*>(this)); } }; template <typename> struct binary_evaluator; template <typename T> struct evaluator<const T> : evaluator<T> { evaluator(const T& xpr) : evaluator<T>(xpr) {} }; template <typename Derived> struct evaluator { typedef Derived PlainObjectType; typedef typename PlainObjectType::Scalar Scalar; evaluator(const PlainObjectType& m) : m_data(m.data()) {} typename PlainObjectType::CoeffReturnType coeff(long row, long) { return m_data[row]; } Scalar& coeffRef(long row, long) { return const_cast<Scalar*>(m_data)[row]; } const Scalar* m_data; }; template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols> struct evaluator<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>> : evaluator<PlainObjectBase<Matrix<Scalar, Rows, Cols>>> { typedef Matrix<Scalar, Rows, Cols> XprType; evaluator(const XprType& m) : evaluator<PlainObjectBase<XprType>>(m) {} }; struct nullary_wrapper { template <typename IndexType> float operator()(scalar_constant_op<float> op, IndexType, IndexType) const { return op(); } }; template <typename NullaryOp, typename PlainObjectType> struct evaluator<CwiseNullaryOp<NullaryOp, PlainObjectType>> { typedef CwiseNullaryOp<NullaryOp, PlainObjectType> XprType; evaluator(XprType n) : m_functor(n.functor()) {} template <typename IndexType> typename XprType::CoeffReturnType coeff(IndexType row, IndexType col) { return m_wrapper(m_functor, row, col); } NullaryOp m_functor; nullary_wrapper m_wrapper; }; template <typename BinaryOp, typename Lhs, typename Rhs> struct evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>> : binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>> { evaluator(CwiseBinaryOp<BinaryOp, Lhs, Rhs> xpr) : binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>>(xpr) {} }; template <typename BinaryOp, typename Lhs, typename Rhs> struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>> { typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType; binary_evaluator(XprType xpr) : m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {} typename XprType::CoeffReturnType coeff(long row, long col) { return m_functor(m_lhsImpl.coeff(row, col), m_rhsImpl.coeff(row, col)); } BinaryOp m_functor; evaluator<Lhs> m_lhsImpl; evaluator<Rhs> m_rhsImpl; }; template <typename Kernel, int Index, int Stop> struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling { enum { outer, inner = Index }; static void run(Kernel kernel) { kernel.assignCoeffByOuterInner(outer, inner); copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Index + 1, Stop>::run(kernel); } }; template <typename Kernel, int Stop> struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Stop, Stop> { static void run(Kernel) {} }; template <typename Kernel> struct dense_assignment_loop { static void run(Kernel kernel) { typedef typename Kernel::DstEvaluatorType::XprType DstXprType; enum { size = DstXprType::SizeAtCompileTime, alignedSize = 0 }; copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, alignedSize, size>::run(kernel); } }; template <typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor> class generic_dense_assignment_kernel { typedef typename DstEvaluatorTypeT::XprType DstXprType; public: typedef DstEvaluatorTypeT DstEvaluatorType; typedef SrcEvaluatorTypeT SrcEvaluatorType; generic_dense_assignment_kernel(DstEvaluatorType dst, SrcEvaluatorType src, Functor, DstXprType& dstExpr) : m_dst(dst), m_src(src), m_dstExpr(dstExpr) {} long assignCoeff_col; void assignCoeffByOuterInner(long, long inner) { long __trans_tmp_1 = inner; m_functor.assignCoeff(m_dst.coeffRef(__trans_tmp_1, assignCoeff_col), m_src.coeff(__trans_tmp_1, assignCoeff_col)); } DstEvaluatorType m_dst; SrcEvaluatorType m_src; Functor m_functor; DstXprType& m_dstExpr; }; template <typename DstXprType, typename SrcXprType, typename Functor> void call_dense_assignment_loop(DstXprType& dst, SrcXprType src, Functor func) { typedef evaluator<DstXprType> DstEvaluatorType; typedef evaluator<SrcXprType> SrcEvaluatorType; SrcEvaluatorType srcEvaluator(src); DstEvaluatorType dstEvaluator(dst); typedef generic_dense_assignment_kernel<DstEvaluatorType, SrcEvaluatorType, Functor> Kernel; Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived()); dense_assignment_loop<Kernel>::run(kernel); } template <typename Dst, typename Src, typename Func> void call_assignment_no_alias(Dst& dst, Src src, Func func) { enum { NeedToTranspose }; typename conditional<NeedToTranspose, Dst&>::type actualDst(dst); CwiseBinaryOp<scalar_product_op, const Matrix<float, 3, 1>, const CwiseNullaryOp<scalar_constant_op<float>, const Matrix<float, 3, 1, 0, 2, 3>>> __trans_tmp_4 = src; call_dense_assignment_loop(actualDst, __trans_tmp_4, func); } template <int Size> struct plain_array { float array[Size]; }; template <int Size, int _Rows> class DenseStorage { plain_array<Size> m_data; public: DenseStorage() {} DenseStorage(const DenseStorage&); static long rows() { return _Rows; } const float* data() const { return m_data.array; } float* data() { return m_data.array; } }; template <typename Derived> class PlainObjectBase : public dense_xpr_base<Derived>::type { public: typedef typename dense_xpr_base<Derived>::type Base; typedef typename traits<Derived>::Scalar Scalar; DenseStorage<Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime> m_storage; long rows() const { return m_storage.rows(); } const Scalar* data() const { return m_storage.data(); } PlainObjectBase() {} template <typename OtherDerived> PlainObjectBase(const DenseBase<OtherDerived>& other) { _set_noalias(other); } template <typename OtherDerived> void _set_noalias(const DenseBase<OtherDerived>& other) { call_assignment_no_alias(this->derived(), other.derived(), assign_op()); } }; template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> struct traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>> { typedef _Scalar Scalar; typedef int XprKind; enum { RowsAtCompileTime = _Rows, ColsAtCompileTime, MaxRowsAtCompileTime, MaxColsAtCompileTime, }; }; template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> class Matrix : public PlainObjectBase< Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>> { public: typedef PlainObjectBase<Matrix> Base; typedef typename traits<Matrix>::Scalar Scalar; Matrix(Scalar& x, Scalar& y, Scalar& z) { m_storage.data()[0] = x; m_storage.data()[1] = y; m_storage.data()[2] = z; } template <typename OtherDerived> Matrix(const EigenBase<OtherDerived>& other) : Base(other.derived()) {} using Base::m_storage; }; template <typename BinaryOp, typename Lhs, typename Rhs> struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs>> { typedef typename traits<Lhs>::XprKind XprKind; enum { RowsAtCompileTime }; typedef float Scalar; }; template <typename> class CwiseBinaryOpImpl; template <typename, typename, typename RhsType> class CwiseBinaryOp : public CwiseBinaryOpImpl<RhsType> { public: typedef ref_selector::type LhsNested; typedef RhsType RhsNested; CwiseBinaryOp(const Matrix<float, 3, 1>& aLhs, RhsType& aRhs) : m_lhs(aLhs), m_rhs(aRhs) {} remove_reference<LhsNested>::type& lhs() { return m_lhs; } typename remove_reference<RhsNested>::type& rhs() { return m_rhs; } LhsNested m_lhs; RhsNested m_rhs; }; template <typename> class CwiseBinaryOpImpl : public generic_xpr_base<CwiseBinaryOp< scalar_product_op, const Matrix<float, 3, 1>, const CwiseNullaryOp<scalar_constant_op<float>, const Matrix<float, 3, 1, 0, 2, 3>>>>::type {}; template <typename NullaryOp, typename PlainObjectType> struct traits<CwiseNullaryOp<NullaryOp, PlainObjectType>> : traits<PlainObjectType> {}; template <typename, typename PlainObjectType> class CwiseNullaryOp : public dense_xpr_base<CwiseNullaryOp<int, PlainObjectType>>::type { public: CwiseNullaryOp(long rows, long, scalar_constant_op<float> func) : m_functor(func) { rows ? void() : __assert_fail("", "", 1, __PRETTY_FUNCTION__); } scalar_constant_op<float> functor() { return m_functor; } scalar_constant_op<float> m_functor; }; } // namespace Eigen Eigen::Matrix<float, 3, 1> should_inline(float x, float y, float z, float scale) { return Eigen::Matrix<float, 3, 1>(x, y, z) * scale; } // We should inline everything to should_inline /* { dg-final { scan-tree-dump-times "Function" "optimized" } } */