bug #100: add support for explicit scalar to Array conversion (as enable implicit conversion is much more tricky)

This commit is contained in:
Gael Guennebaud 2014-09-19 13:25:28 +02:00
parent 7b044c0ead
commit 0a18eecab3
4 changed files with 82 additions and 3 deletions

View File

@ -75,6 +75,21 @@ class Array
return Base::operator=(other); return Base::operator=(other);
} }
/** Set all the entries to \a value.
* \sa DenseBase::setConstant(), DenseBase::fill()
*/
/* This overload is needed because the usage of
* using Base::operator=;
* fails on MSVC. Since the code below is working with GCC and MSVC, we skipped
* the usage of 'using'. This should be done only for operator=.
*/
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array& operator=(const Scalar &value)
{
Base::setConstant(value);
return *this;
}
/** Copies the value of the expression \a other into \c *this with automatic resizing. /** Copies the value of the expression \a other into \c *this with automatic resizing.
* *
* *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized), * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
@ -144,7 +159,6 @@ class Array
} }
#endif #endif
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename T> template<typename T>
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC

View File

@ -123,6 +123,12 @@ template<typename Derived> class ArrayBase
internal::call_assignment(derived(), other.derived()); internal::call_assignment(derived(), other.derived());
} }
/** Set all the entries to \a value.
* \sa DenseBase::setConstant(), DenseBase::fill() */
EIGEN_DEVICE_FUNC
Derived& operator=(const Scalar &value)
{ Base::setConstant(value); return derived(); }
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
Derived& operator+=(const Scalar& scalar); Derived& operator+=(const Scalar& scalar);
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC

View File

@ -700,9 +700,12 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
m_storage.data()[1] = Scalar(val1); m_storage.data()[1] = Scalar(val1);
} }
// The argument is convertible to the Index type and we either have a non 1x1 Matrix, or a dynamic-sized Array,
// then the argument is meant to be the size of the object.
template<typename T> template<typename T>
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(Index size, typename internal::enable_if<Base::SizeAtCompileTime!=1 || !internal::is_convertible<T, Scalar>::value,T>::type* = 0) EIGEN_STRONG_INLINE void _init1(Index size, typename internal::enable_if< (Base::SizeAtCompileTime!=1 || !internal::is_convertible<T, Scalar>::value)
&& ((!internal::is_same<typename internal::traits<Derived>::XprKind,ArrayXpr>::value || Base::SizeAtCompileTime==Dynamic)),T>::type* = 0)
{ {
// NOTE MSVC 2008 complains if we directly put bool(NumTraits<T>::IsInteger) as the EIGEN_STATIC_ASSERT argument. // NOTE MSVC 2008 complains if we directly put bool(NumTraits<T>::IsInteger) as the EIGEN_STATIC_ASSERT argument.
const bool is_integer = NumTraits<T>::IsInteger; const bool is_integer = NumTraits<T>::IsInteger;
@ -710,6 +713,8 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
resize(size); resize(size);
} }
// We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar type can be implicitely converted)
template<typename T> template<typename T>
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const Scalar& val0, typename internal::enable_if<Base::SizeAtCompileTime==1 && internal::is_convertible<T, Scalar>::value,T>::type* = 0) EIGEN_STRONG_INLINE void _init1(const Scalar& val0, typename internal::enable_if<Base::SizeAtCompileTime==1 && internal::is_convertible<T, Scalar>::value,T>::type* = 0)
@ -718,6 +723,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
m_storage.data()[0] = val0; m_storage.data()[0] = val0;
} }
// We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar type match the index type)
template<typename T> template<typename T>
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const Index& val0, EIGEN_STRONG_INLINE void _init1(const Index& val0,
@ -730,18 +736,21 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
m_storage.data()[0] = Scalar(val0); m_storage.data()[0] = Scalar(val0);
} }
// Initialize a fixed size matrix from a pointer to raw data
template<typename T> template<typename T>
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const Scalar* data){ EIGEN_STRONG_INLINE void _init1(const Scalar* data){
this->_set_noalias(ConstMapType(data)); this->_set_noalias(ConstMapType(data));
} }
// Initialize an arbitrary matrix from a dense expression
template<typename T, typename OtherDerived> template<typename T, typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const DenseBase<OtherDerived>& other){ EIGEN_STRONG_INLINE void _init1(const DenseBase<OtherDerived>& other){
this->_set_noalias(other); this->_set_noalias(other);
} }
// Initialize an arbitrary matrix from a generic Eigen expression
template<typename T, typename OtherDerived> template<typename T, typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const EigenBase<OtherDerived>& other){ EIGEN_STRONG_INLINE void _init1(const EigenBase<OtherDerived>& other){
@ -763,6 +772,31 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
this->derived() = r; this->derived() = r;
} }
// For fixed -size arrays:
template<typename T>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const Scalar& val0,
typename internal::enable_if< Base::SizeAtCompileTime!=Dynamic
&& Base::SizeAtCompileTime!=1
&& internal::is_convertible<T, Scalar>::value
&& internal::is_same<typename internal::traits<Derived>::XprKind,ArrayXpr>::value,T>::type* = 0)
{
Base::setConstant(val0);
}
template<typename T>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const Index& val0,
typename internal::enable_if< (!internal::is_same<Index,Scalar>::value)
&& (internal::is_same<Index,T>::value)
&& Base::SizeAtCompileTime!=Dynamic
&& Base::SizeAtCompileTime!=1
&& internal::is_convertible<T, Scalar>::value
&& internal::is_same<typename internal::traits<Derived>::XprKind,ArrayXpr>::value,T*>::type* = 0)
{
Base::setConstant(val0);
}
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
friend struct internal::matrix_swap_impl; friend struct internal::matrix_swap_impl;

View File

@ -81,6 +81,31 @@ template<typename ArrayType> void array(const ArrayType& m)
VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1); VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1);
m3 = m1; m3 = m1;
VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1); VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1);
// Conversion from scalar
VERIFY_IS_APPROX((m3 = s1), ArrayType::Constant(rows,cols,s1));
VERIFY_IS_APPROX((m3 = 1), ArrayType::Constant(rows,cols,1));
VERIFY_IS_APPROX((m3.topLeftCorner(rows,cols) = 1), ArrayType::Constant(rows,cols,1));
typedef Array<Scalar,
ArrayType::RowsAtCompileTime==Dynamic?2:ArrayType::RowsAtCompileTime,
ArrayType::ColsAtCompileTime==Dynamic?2:ArrayType::ColsAtCompileTime,
ArrayType::Options> FixedArrayType;
FixedArrayType f1(s1);
VERIFY_IS_APPROX(f1, FixedArrayType::Constant(s1));
FixedArrayType f2(numext::real(s1));
VERIFY_IS_APPROX(f2, FixedArrayType::Constant(numext::real(s1)));
FixedArrayType f3((int)100*numext::real(s1));
VERIFY_IS_APPROX(f3, FixedArrayType::Constant((int)100*numext::real(s1)));
f1.setRandom();
FixedArrayType f4(f1.data());
VERIFY_IS_APPROX(f4, f1);
// Check possible conflicts with 1D ctor
typedef Array<Scalar, Dynamic, 1> OneDArrayType;
OneDArrayType o1(rows);
VERIFY(o1.size()==rows);
OneDArrayType o4((int)rows);
VERIFY(o4.size()==rows);
} }
template<typename ArrayType> void comparisons(const ArrayType& m) template<typename ArrayType> void comparisons(const ArrayType& m)