Skip to content

Commit 1cfd218

Browse files
committed
Update Eigen to 3.3.2
1 parent 5080ffe commit 1cfd218

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1554
-527
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
- The [Catch unit test framework](https://github.com/philsquared/Catch) has
1111
been updated to its latest version
1212
[v1.7.2](https://github.com/philsquared/Catch/releases/tag/v1.7.2)
13+
- Updated the version of Eigen bundled with the code.
14+
The minimum required version of Eigen is still 3.3.0, but we ship
15+
[Eigen 3.3.2](http://eigen.tuxfamily.org/index.php?title=ChangeLog#Eigen_3.3.2)
1316

1417
## [Version 1.1.8] - 2017-02-06
1518

cmake/custom/eigen.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ if(EIGEN3_ROOT)
1616
message(STATUS "Eigen " ${EIGEN3_VERSION} " is located here: " ${EIGEN3_INCLUDE_DIR})
1717
if(NOT EIGEN3_FOUND)
1818
set(EIGEN3_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/external/eigen3/include/eigen3)
19-
message(STATUS "Eigen 3.3.0 is located here: " ${EIGEN3_INCLUDE_DIR})
19+
message(STATUS "Eigen 3.3.2 is located here: " ${EIGEN3_INCLUDE_DIR})
2020
endif()
2121
else()
2222
set(EIGEN3_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/external/eigen3/include/eigen3)
23-
message(STATUS "Eigen 3.3.0 is located here: " ${EIGEN3_INCLUDE_DIR})
23+
message(STATUS "Eigen 3.3.2 is located here: " ${EIGEN3_INCLUDE_DIR})
2424
endif()
2525
include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR})

external/eigen3/include/eigen3/Eigen/src/Core/AssignEvaluator.h

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, NoUnrolling>
407407
: int(Kernel::AssignmentTraits::DstAlignment),
408408
srcAlignment = Kernel::AssignmentTraits::JointAlignment
409409
};
410-
const Index alignedStart = dstIsAligned ? 0 : internal::first_aligned<requestedAlignment>(&kernel.dstEvaluator().coeffRef(0), size);
410+
const Index alignedStart = dstIsAligned ? 0 : internal::first_aligned<requestedAlignment>(kernel.dstDataPtr(), size);
411411
const Index alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
412412

413413
unaligned_dense_assignment_loop<dstIsAligned!=0>::run(kernel, 0, alignedStart);
@@ -527,7 +527,7 @@ struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, NoUnrolling>
527527
dstAlignment = alignable ? int(requestedAlignment)
528528
: int(Kernel::AssignmentTraits::DstAlignment)
529529
};
530-
const Scalar *dst_ptr = &kernel.dstEvaluator().coeffRef(0,0);
530+
const Scalar *dst_ptr = kernel.dstDataPtr();
531531
if((!bool(dstIsAligned)) && (UIntPtr(dst_ptr) % sizeof(Scalar))>0)
532532
{
533533
// the pointer is not aligend-on scalar, so alignment is not possible
@@ -683,6 +683,11 @@ class generic_dense_assignment_kernel
683683
: int(DstEvaluatorType::Flags)&RowMajorBit ? inner
684684
: outer;
685685
}
686+
687+
EIGEN_DEVICE_FUNC const Scalar* dstDataPtr() const
688+
{
689+
return m_dstExpr.data();
690+
}
686691

687692
protected:
688693
DstEvaluatorType& m_dst;
@@ -876,6 +881,34 @@ struct Assignment<DstXprType, SrcXprType, Functor, EigenBase2EigenBase, Weak>
876881
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
877882
src.evalTo(dst);
878883
}
884+
885+
// NOTE The following two functions are templated to avoid their instanciation if not needed
886+
// This is needed because some expressions supports evalTo only and/or have 'void' as scalar type.
887+
template<typename SrcScalarType>
888+
EIGEN_DEVICE_FUNC
889+
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<typename DstXprType::Scalar,SrcScalarType> &/*func*/)
890+
{
891+
Index dstRows = src.rows();
892+
Index dstCols = src.cols();
893+
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
894+
dst.resize(dstRows, dstCols);
895+
896+
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
897+
src.addTo(dst);
898+
}
899+
900+
template<typename SrcScalarType>
901+
EIGEN_DEVICE_FUNC
902+
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<typename DstXprType::Scalar,SrcScalarType> &/*func*/)
903+
{
904+
Index dstRows = src.rows();
905+
Index dstCols = src.cols();
906+
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
907+
dst.resize(dstRows, dstCols);
908+
909+
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
910+
src.subTo(dst);
911+
}
879912
};
880913

881914
} // namespace internal

external/eigen3/include/eigen3/Eigen/src/Core/CwiseBinaryOp.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
4646
typedef typename remove_reference<LhsNested>::type _LhsNested;
4747
typedef typename remove_reference<RhsNested>::type _RhsNested;
4848
enum {
49-
Flags = _LhsNested::Flags & RowMajorBit
49+
Flags = cwise_promote_storage_order<typename traits<Lhs>::StorageKind,typename traits<Rhs>::StorageKind,_LhsNested::Flags & RowMajorBit,_RhsNested::Flags & RowMajorBit>::value
5050
};
5151
};
5252
} // end namespace internal
@@ -84,6 +84,7 @@ class CwiseBinaryOp :
8484
{
8585
public:
8686

87+
typedef typename internal::remove_all<BinaryOp>::type Functor;
8788
typedef typename internal::remove_all<LhsType>::type Lhs;
8889
typedef typename internal::remove_all<RhsType>::type Rhs;
8990

external/eigen3/include/eigen3/Eigen/src/Core/Dot.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ struct dot_nocheck<T, U, true>
5151

5252
} // end namespace internal
5353

54-
/** \returns the dot product of *this with other.
54+
/** \fn MatrixBase::dot
55+
* \returns the dot product of *this with other.
5556
*
5657
* \only_for_vectors
5758
*
@@ -70,9 +71,11 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
7071
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
7172
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
7273
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
74+
#if !(defined(EIGEN_NO_STATIC_ASSERT) && defined(EIGEN_NO_DEBUG))
7375
typedef internal::scalar_conj_product_op<Scalar,typename OtherDerived::Scalar> func;
7476
EIGEN_CHECK_BINARY_COMPATIBILIY(func,Scalar,typename OtherDerived::Scalar);
75-
77+
#endif
78+
7679
eigen_assert(size() == other.size());
7780

7881
return internal::dot_nocheck<Derived,OtherDerived>::run(*this, other);

external/eigen3/include/eigen3/Eigen/src/Core/GeneralProduct.h

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ template<int Rows, int Cols, int Depth> struct product_type_selector;
2525
template<int Size, int MaxSize> struct product_size_category
2626
{
2727
enum { is_large = MaxSize == Dynamic ||
28-
Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD,
28+
Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD ||
29+
(Size==Dynamic && MaxSize>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD),
2930
value = is_large ? Large
3031
: Size == 1 ? 1
3132
: Small
@@ -223,50 +224,65 @@ template<> struct gemv_dense_selector<OnTheRight,ColMajor,true>
223224
// on, the other hand it is good for the cache to pack the vector anyways...
224225
EvalToDestAtCompileTime = (ActualDest::InnerStrideAtCompileTime==1),
225226
ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
226-
MightCannotUseDest = (ActualDest::InnerStrideAtCompileTime!=1) || ComplexByReal
227+
MightCannotUseDest = (!EvalToDestAtCompileTime) || ComplexByReal
227228
};
228229

229-
gemv_static_vector_if<ResScalar,ActualDest::SizeAtCompileTime,ActualDest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
230+
typedef const_blas_data_mapper<LhsScalar,Index,ColMajor> LhsMapper;
231+
typedef const_blas_data_mapper<RhsScalar,Index,RowMajor> RhsMapper;
232+
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
230233

231-
const bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
232-
const bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
234+
if(!MightCannotUseDest)
235+
{
236+
// shortcut if we are sure to be able to use dest directly,
237+
// this ease the compiler to generate cleaner and more optimzized code for most common cases
238+
general_matrix_vector_product
239+
<Index,LhsScalar,LhsMapper,ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsMapper,RhsBlasTraits::NeedToConjugate>::run(
240+
actualLhs.rows(), actualLhs.cols(),
241+
LhsMapper(actualLhs.data(), actualLhs.outerStride()),
242+
RhsMapper(actualRhs.data(), actualRhs.innerStride()),
243+
dest.data(), 1,
244+
compatibleAlpha);
245+
}
246+
else
247+
{
248+
gemv_static_vector_if<ResScalar,ActualDest::SizeAtCompileTime,ActualDest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
233249

234-
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
250+
const bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
251+
const bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
235252

236-
ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
237-
evalToDest ? dest.data() : static_dest.data());
253+
ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
254+
evalToDest ? dest.data() : static_dest.data());
238255

239-
if(!evalToDest)
240-
{
241-
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
242-
Index size = dest.size();
243-
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
244-
#endif
245-
if(!alphaIsCompatible)
256+
if(!evalToDest)
246257
{
247-
MappedDest(actualDestPtr, dest.size()).setZero();
248-
compatibleAlpha = RhsScalar(1);
258+
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
259+
Index size = dest.size();
260+
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
261+
#endif
262+
if(!alphaIsCompatible)
263+
{
264+
MappedDest(actualDestPtr, dest.size()).setZero();
265+
compatibleAlpha = RhsScalar(1);
266+
}
267+
else
268+
MappedDest(actualDestPtr, dest.size()) = dest;
249269
}
250-
else
251-
MappedDest(actualDestPtr, dest.size()) = dest;
252-
}
253270

254-
typedef const_blas_data_mapper<LhsScalar,Index,ColMajor> LhsMapper;
255-
typedef const_blas_data_mapper<RhsScalar,Index,RowMajor> RhsMapper;
256-
general_matrix_vector_product
257-
<Index,LhsScalar,LhsMapper,ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsMapper,RhsBlasTraits::NeedToConjugate>::run(
258-
actualLhs.rows(), actualLhs.cols(),
259-
LhsMapper(actualLhs.data(), actualLhs.outerStride()),
260-
RhsMapper(actualRhs.data(), actualRhs.innerStride()),
261-
actualDestPtr, 1,
262-
compatibleAlpha);
271+
general_matrix_vector_product
272+
<Index,LhsScalar,LhsMapper,ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsMapper,RhsBlasTraits::NeedToConjugate>::run(
273+
actualLhs.rows(), actualLhs.cols(),
274+
LhsMapper(actualLhs.data(), actualLhs.outerStride()),
275+
RhsMapper(actualRhs.data(), actualRhs.innerStride()),
276+
actualDestPtr, 1,
277+
compatibleAlpha);
263278

264-
if (!evalToDest)
265-
{
266-
if(!alphaIsCompatible)
267-
dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
268-
else
269-
dest = MappedDest(actualDestPtr, dest.size());
279+
if (!evalToDest)
280+
{
281+
if(!alphaIsCompatible)
282+
dest.matrix() += actualAlpha * MappedDest(actualDestPtr, dest.size());
283+
else
284+
dest = MappedDest(actualDestPtr, dest.size());
285+
}
270286
}
271287
}
272288
};
@@ -329,6 +345,7 @@ template<> struct gemv_dense_selector<OnTheRight,ColMajor,false>
329345
template<typename Lhs, typename Rhs, typename Dest>
330346
static void run(const Lhs &lhs, const Rhs &rhs, Dest& dest, const typename Dest::Scalar& alpha)
331347
{
348+
EIGEN_STATIC_ASSERT((!nested_eval<Lhs,1>::Evaluate),EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE);
332349
// TODO if rhs is large enough it might be beneficial to make sure that dest is sequentially stored in memory, otherwise use a temp
333350
typename nested_eval<Rhs,1>::type actual_rhs(rhs);
334351
const Index size = rhs.rows();
@@ -342,6 +359,7 @@ template<> struct gemv_dense_selector<OnTheRight,RowMajor,false>
342359
template<typename Lhs, typename Rhs, typename Dest>
343360
static void run(const Lhs &lhs, const Rhs &rhs, Dest& dest, const typename Dest::Scalar& alpha)
344361
{
362+
EIGEN_STATIC_ASSERT((!nested_eval<Lhs,1>::Evaluate),EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE);
345363
typename nested_eval<Rhs,Lhs::RowsAtCompileTime>::type actual_rhs(rhs);
346364
const Index rows = dest.rows();
347365
for(Index i=0; i<rows; ++i)

external/eigen3/include/eigen3/Eigen/src/Core/IO.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class WithFormat
105105
}
106106

107107
protected:
108-
const typename ExpressionType::Nested m_matrix;
108+
typename ExpressionType::Nested m_matrix;
109109
IOFormat m_format;
110110
};
111111

external/eigen3/include/eigen3/Eigen/src/Core/Inverse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class Inverse : public InverseImpl<XprType,typename internal::traits<XprType>::S
4545
public:
4646
typedef typename XprType::StorageIndex StorageIndex;
4747
typedef typename XprType::PlainObject PlainObject;
48+
typedef typename XprType::Scalar Scalar;
4849
typedef typename internal::ref_selector<XprType>::type XprTypeNested;
4950
typedef typename internal::remove_all<XprTypeNested>::type XprTypeNestedCleaned;
5051
typedef typename internal::ref_selector<Inverse>::type Nested;

external/eigen3/include/eigen3/Eigen/src/Core/PlainObjectBase.h

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,33 +58,39 @@ template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct m
5858

5959
} // end namespace internal
6060

61-
/** \class PlainObjectBase
62-
* \ingroup Core_Module
63-
* \brief %Dense storage base class for matrices and arrays.
64-
*
65-
* This class can be extended with the help of the plugin mechanism described on the page
66-
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_PLAINOBJECTBASE_PLUGIN.
67-
*
68-
* \sa \ref TopicClassHierarchy
69-
*/
7061
#ifdef EIGEN_PARSED_BY_DOXYGEN
7162
namespace doxygen {
7263

73-
// this is a workaround to doxygen not being able to understand the inheritance logic
64+
// This is a workaround to doxygen not being able to understand the inheritance logic
7465
// when it is hidden by the dense_xpr_base helper struct.
66+
// Moreover, doxygen fails to include members that are not documented in the declaration body of
67+
// MatrixBase if we inherits MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >,
68+
// this is why we simply inherits MatrixBase, though this does not make sense.
69+
7570
/** This class is just a workaround for Doxygen and it does not not actually exist. */
7671
template<typename Derived> struct dense_xpr_base_dispatcher;
7772
/** This class is just a workaround for Doxygen and it does not not actually exist. */
7873
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
7974
struct dense_xpr_base_dispatcher<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
80-
: public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {};
75+
: public MatrixBase {};
8176
/** This class is just a workaround for Doxygen and it does not not actually exist. */
8277
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
8378
struct dense_xpr_base_dispatcher<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
84-
: public ArrayBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {};
79+
: public ArrayBase {};
8580

8681
} // namespace doxygen
8782

83+
/** \class PlainObjectBase
84+
* \ingroup Core_Module
85+
* \brief %Dense storage base class for matrices and arrays.
86+
*
87+
* This class can be extended with the help of the plugin mechanism described on the page
88+
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_PLAINOBJECTBASE_PLUGIN.
89+
*
90+
* \tparam Derived is the derived type, e.g., a Matrix or Array
91+
*
92+
* \sa \ref TopicClassHierarchy
93+
*/
8894
template<typename Derived>
8995
class PlainObjectBase : public doxygen::dense_xpr_base_dispatcher<Derived>
9096
#else
@@ -554,7 +560,8 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
554560

555561
public:
556562

557-
/** \copydoc DenseBase::operator=(const EigenBase<OtherDerived>&)
563+
/** \brief Copies the generic expression \a other into *this.
564+
* \copydetails DenseBase::operator=(const EigenBase<OtherDerived> &other)
558565
*/
559566
template<typename OtherDerived>
560567
EIGEN_DEVICE_FUNC
@@ -763,6 +770,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
763770
{
764771
// NOTE MSVC 2008 complains if we directly put bool(NumTraits<T>::IsInteger) as the EIGEN_STATIC_ASSERT argument.
765772
const bool is_integer = NumTraits<T>::IsInteger;
773+
EIGEN_UNUSED_VARIABLE(is_integer);
766774
EIGEN_STATIC_ASSERT(is_integer,
767775
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
768776
resize(size);

external/eigen3/include/eigen3/Eigen/src/Core/ProductEvaluators.h

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,7 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,Options>, internal::add_assign_op<
158158
static EIGEN_STRONG_INLINE
159159
void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<Scalar,Scalar> &)
160160
{
161-
Index dstRows = src.rows();
162-
Index dstCols = src.cols();
163-
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
164-
dst.resize(dstRows, dstCols);
161+
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
165162
// FIXME shall we handle nested_eval here?
166163
generic_product_impl<Lhs, Rhs>::addTo(dst, src.lhs(), src.rhs());
167164
}
@@ -176,10 +173,7 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,Options>, internal::sub_assign_op<
176173
static EIGEN_STRONG_INLINE
177174
void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<Scalar,Scalar> &)
178175
{
179-
Index dstRows = src.rows();
180-
Index dstCols = src.cols();
181-
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
182-
dst.resize(dstRows, dstCols);
176+
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
183177
// FIXME shall we handle nested_eval here?
184178
generic_product_impl<Lhs, Rhs>::subTo(dst, src.lhs(), src.rhs());
185179
}
@@ -366,17 +360,21 @@ template<typename Lhs, typename Rhs>
366360
struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemvProduct>
367361
: generic_product_impl_base<Lhs,Rhs,generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemvProduct> >
368362
{
363+
typedef typename nested_eval<Lhs,1>::type LhsNested;
364+
typedef typename nested_eval<Rhs,1>::type RhsNested;
369365
typedef typename Product<Lhs,Rhs>::Scalar Scalar;
370366
enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight };
371-
typedef typename internal::conditional<int(Side)==OnTheRight,Lhs,Rhs>::type MatrixType;
367+
typedef typename internal::remove_all<typename internal::conditional<int(Side)==OnTheRight,LhsNested,RhsNested>::type>::type MatrixType;
372368

373369
template<typename Dest>
374370
static EIGEN_STRONG_INLINE void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
375371
{
372+
LhsNested actual_lhs(lhs);
373+
RhsNested actual_rhs(rhs);
376374
internal::gemv_dense_selector<Side,
377375
(int(MatrixType::Flags)&RowMajorBit) ? RowMajor : ColMajor,
378376
bool(internal::blas_traits<MatrixType>::HasUsableDirectAccess)
379-
>::run(lhs, rhs, dst, alpha);
377+
>::run(actual_lhs, actual_rhs, dst, alpha);
380378
}
381379
};
382380

0 commit comments

Comments
 (0)