mirror of
https://gitlab.com/libeigen/eigen.git
synced 2024-12-03 06:50:57 +08:00
Add NaN propagation options to minCoeff/maxCoeff visitors.
This commit is contained in:
parent
c0a889890f
commit
2e83cbbba9
@ -459,22 +459,48 @@ template<typename Derived> class DenseBase
|
||||
// used.
|
||||
// TODO(rmlarsen): Replace with default template argument when we move to
|
||||
// c++11 or beyond.
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar minCoeff() const {
|
||||
EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Scalar minCoeff() const {
|
||||
return minCoeff<PropagateFast>();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar maxCoeff() const {
|
||||
EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Scalar maxCoeff() const {
|
||||
return maxCoeff<PropagateFast>();
|
||||
}
|
||||
|
||||
template<typename IndexType> EIGEN_DEVICE_FUNC
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar minCoeff(IndexType* row, IndexType* col) const;
|
||||
template<typename IndexType> EIGEN_DEVICE_FUNC
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* row, IndexType* col) const;
|
||||
template<typename IndexType> EIGEN_DEVICE_FUNC
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar minCoeff(IndexType* index) const;
|
||||
template<typename IndexType> EIGEN_DEVICE_FUNC
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* index) const;
|
||||
|
||||
// TODO(rmlarsen): Replace these methods with a default template argument.
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
typename internal::traits<Derived>::Scalar minCoeff(IndexType* row, IndexType* col) const {
|
||||
return minCoeff<PropagateFast>(row, col);
|
||||
}
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* row, IndexType* col) const {
|
||||
return maxCoeff<PropagateFast>(row, col);
|
||||
}
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
typename internal::traits<Derived>::Scalar minCoeff(IndexType* index) const {
|
||||
return minCoeff<PropagateFast>(index);
|
||||
}
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* index) const {
|
||||
return maxCoeff<PropagateFast>(index);
|
||||
}
|
||||
|
||||
template<typename BinaryOp>
|
||||
EIGEN_DEVICE_FUNC
|
||||
Scalar redux(const BinaryOp& func) const;
|
||||
|
@ -157,7 +157,7 @@ struct coeff_visitor
|
||||
*
|
||||
* \sa DenseBase::minCoeff(Index*, Index*)
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename Derived, int NaNPropagation>
|
||||
struct min_coeff_visitor : coeff_visitor<Derived>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
@ -173,8 +173,40 @@ struct min_coeff_visitor : coeff_visitor<Derived>
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar>
|
||||
struct functor_traits<min_coeff_visitor<Scalar> > {
|
||||
template <typename Derived>
|
||||
struct min_coeff_visitor<Derived, PropagateNumbers> : coeff_visitor<Derived>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
void operator() (const Scalar& value, Index i, Index j)
|
||||
{
|
||||
if((numext::isnan)(this->res) || (!(numext::isnan)(value) && value < this->res))
|
||||
{
|
||||
this->res = value;
|
||||
this->row = i;
|
||||
this->col = j;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
struct min_coeff_visitor<Derived, PropagateNaN> : coeff_visitor<Derived>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
void operator() (const Scalar& value, Index i, Index j)
|
||||
{
|
||||
if((numext::isnan)(value) || value < this->res)
|
||||
{
|
||||
this->res = value;
|
||||
this->row = i;
|
||||
this->col = j;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, int NaNPropagation>
|
||||
struct functor_traits<min_coeff_visitor<Scalar, NaNPropagation> > {
|
||||
enum {
|
||||
Cost = NumTraits<Scalar>::AddCost
|
||||
};
|
||||
@ -185,7 +217,7 @@ struct functor_traits<min_coeff_visitor<Scalar> > {
|
||||
*
|
||||
* \sa DenseBase::maxCoeff(Index*, Index*)
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename Derived, int NaNPropagation>
|
||||
struct max_coeff_visitor : coeff_visitor<Derived>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
@ -201,8 +233,40 @@ struct max_coeff_visitor : coeff_visitor<Derived>
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar>
|
||||
struct functor_traits<max_coeff_visitor<Scalar> > {
|
||||
template <typename Derived>
|
||||
struct max_coeff_visitor<Derived, PropagateNumbers> : coeff_visitor<Derived>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
void operator() (const Scalar& value, Index i, Index j)
|
||||
{
|
||||
if((numext::isnan)(this->res) || (!(numext::isnan)(value) && value > this->res))
|
||||
{
|
||||
this->res = value;
|
||||
this->row = i;
|
||||
this->col = j;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
struct max_coeff_visitor<Derived, PropagateNaN> : coeff_visitor<Derived>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
void operator() (const Scalar& value, Index i, Index j)
|
||||
{
|
||||
if((numext::isnan)(value) || value > this->res)
|
||||
{
|
||||
this->res = value;
|
||||
this->row = i;
|
||||
this->col = j;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, int NaNPropagation>
|
||||
struct functor_traits<max_coeff_visitor<Scalar, NaNPropagation> > {
|
||||
enum {
|
||||
Cost = NumTraits<Scalar>::AddCost
|
||||
};
|
||||
@ -212,22 +276,24 @@ struct functor_traits<max_coeff_visitor<Scalar> > {
|
||||
|
||||
/** \fn DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
|
||||
* \returns the minimum of all coefficients of *this and puts in *row and *col its location.
|
||||
*
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \warning the result is undefined if \c *this contains NaN.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visit(), DenseBase::minCoeff()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename IndexType>
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar
|
||||
DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
|
||||
{
|
||||
eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
|
||||
|
||||
internal::min_coeff_visitor<Derived> minVisitor;
|
||||
internal::min_coeff_visitor<Derived, NaNPropagation> minVisitor;
|
||||
this->visit(minVisitor);
|
||||
*rowId = minVisitor.row;
|
||||
if (colId) *colId = minVisitor.col;
|
||||
@ -236,14 +302,16 @@ DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
|
||||
|
||||
/** \returns the minimum of all coefficients of *this and puts in *index its location.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \warning the result is undefined if \c *this contains NaN.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::minCoeff()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename IndexType>
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar
|
||||
DenseBase<Derived>::minCoeff(IndexType* index) const
|
||||
@ -251,7 +319,7 @@ DenseBase<Derived>::minCoeff(IndexType* index) const
|
||||
eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
|
||||
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
internal::min_coeff_visitor<Derived> minVisitor;
|
||||
internal::min_coeff_visitor<Derived, NaNPropagation> minVisitor;
|
||||
this->visit(minVisitor);
|
||||
*index = IndexType((RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row);
|
||||
return minVisitor.res;
|
||||
@ -260,21 +328,23 @@ DenseBase<Derived>::minCoeff(IndexType* index) const
|
||||
/** \fn DenseBase<Derived>::maxCoeff(IndexType* rowId, IndexType* colId) const
|
||||
* \returns the maximum of all coefficients of *this and puts in *row and *col its location.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \warning the result is undefined if \c *this contains NaN.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::maxCoeff()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename IndexType>
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar
|
||||
DenseBase<Derived>::maxCoeff(IndexType* rowPtr, IndexType* colPtr) const
|
||||
{
|
||||
eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
|
||||
|
||||
internal::max_coeff_visitor<Derived> maxVisitor;
|
||||
internal::max_coeff_visitor<Derived, NaNPropagation> maxVisitor;
|
||||
this->visit(maxVisitor);
|
||||
*rowPtr = maxVisitor.row;
|
||||
if (colPtr) *colPtr = maxVisitor.col;
|
||||
@ -283,14 +353,16 @@ DenseBase<Derived>::maxCoeff(IndexType* rowPtr, IndexType* colPtr) const
|
||||
|
||||
/** \returns the maximum of all coefficients of *this and puts in *index its location.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \warning the result is undefined if \c *this contains NaN.
|
||||
*
|
||||
* \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename IndexType>
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar
|
||||
DenseBase<Derived>::maxCoeff(IndexType* index) const
|
||||
@ -298,7 +370,7 @@ DenseBase<Derived>::maxCoeff(IndexType* index) const
|
||||
eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
|
||||
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
internal::max_coeff_visitor<Derived> maxVisitor;
|
||||
internal::max_coeff_visitor<Derived, NaNPropagation> maxVisitor;
|
||||
this->visit(maxVisitor);
|
||||
*index = (RowsAtCompileTime==1) ? maxVisitor.col : maxVisitor.row;
|
||||
return maxVisitor.res;
|
||||
|
@ -56,9 +56,44 @@ template<typename MatrixType> void matrixVisitor(const MatrixType& p)
|
||||
VERIFY_IS_APPROX(maxc, m.maxCoeff());
|
||||
|
||||
eigen_maxc = (m.adjoint()*m).maxCoeff(&eigen_maxrow,&eigen_maxcol);
|
||||
eigen_maxc = (m.adjoint()*m).eval().maxCoeff(&maxrow,&maxcol);
|
||||
VERIFY(maxrow == eigen_maxrow);
|
||||
VERIFY(maxcol == eigen_maxcol);
|
||||
Index maxrow2=0,maxcol2=0;
|
||||
eigen_maxc = (m.adjoint()*m).eval().maxCoeff(&maxrow2,&maxcol2);
|
||||
VERIFY(maxrow2 == eigen_maxrow);
|
||||
VERIFY(maxcol2 == eigen_maxcol);
|
||||
|
||||
if (!NumTraits<Scalar>::IsInteger && m.size() > 2) {
|
||||
// Test NaN propagation by replacing an element with NaN.
|
||||
bool stop = false;
|
||||
for (Index j = 0; j < cols && !stop; ++j) {
|
||||
for (Index i = 0; i < rows && !stop; ++i) {
|
||||
if (!(j == mincol && i == minrow) &&
|
||||
!(j == maxcol && i == maxrow)) {
|
||||
m(i,j) = NumTraits<Scalar>::quiet_NaN();
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eigen_minc = m.template minCoeff<PropagateNumbers>(&eigen_minrow, &eigen_mincol);
|
||||
eigen_maxc = m.template maxCoeff<PropagateNumbers>(&eigen_maxrow, &eigen_maxcol);
|
||||
VERIFY(minrow == eigen_minrow);
|
||||
VERIFY(maxrow == eigen_maxrow);
|
||||
VERIFY(mincol == eigen_mincol);
|
||||
VERIFY(maxcol == eigen_maxcol);
|
||||
VERIFY_IS_APPROX(minc, eigen_minc);
|
||||
VERIFY_IS_APPROX(maxc, eigen_maxc);
|
||||
VERIFY_IS_APPROX(minc, m.template minCoeff<PropagateNumbers>());
|
||||
VERIFY_IS_APPROX(maxc, m.template maxCoeff<PropagateNumbers>());
|
||||
|
||||
eigen_minc = m.template minCoeff<PropagateNaN>(&eigen_minrow, &eigen_mincol);
|
||||
eigen_maxc = m.template maxCoeff<PropagateNaN>(&eigen_maxrow, &eigen_maxcol);
|
||||
VERIFY(minrow != eigen_minrow || mincol != eigen_mincol);
|
||||
VERIFY(maxrow != eigen_maxrow || maxcol != eigen_maxcol);
|
||||
VERIFY((numext::isnan)(eigen_minc));
|
||||
VERIFY((numext::isnan)(eigen_maxc));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename VectorType> void vectorVisitor(const VectorType& w)
|
||||
@ -111,6 +146,31 @@ template<typename VectorType> void vectorVisitor(const VectorType& w)
|
||||
v2.maxCoeff(&eigen_maxidx);
|
||||
VERIFY(eigen_minidx == (std::min)(idx0,idx1));
|
||||
VERIFY(eigen_maxidx == (std::min)(idx0,idx2));
|
||||
|
||||
if (!NumTraits<Scalar>::IsInteger && size > 2) {
|
||||
// Test NaN propagation by replacing an element with NaN.
|
||||
for (Index i = 0; i < size; ++i) {
|
||||
if (i != minidx && i != maxidx) {
|
||||
v(i) = NumTraits<Scalar>::quiet_NaN();
|
||||
break;
|
||||
}
|
||||
}
|
||||
eigen_minc = v.template minCoeff<PropagateNumbers>(&eigen_minidx);
|
||||
eigen_maxc = v.template maxCoeff<PropagateNumbers>(&eigen_maxidx);
|
||||
VERIFY(minidx == eigen_minidx);
|
||||
VERIFY(maxidx == eigen_maxidx);
|
||||
VERIFY_IS_APPROX(minc, eigen_minc);
|
||||
VERIFY_IS_APPROX(maxc, eigen_maxc);
|
||||
VERIFY_IS_APPROX(minc, v.template minCoeff<PropagateNumbers>());
|
||||
VERIFY_IS_APPROX(maxc, v.template maxCoeff<PropagateNumbers>());
|
||||
|
||||
eigen_minc = v.template minCoeff<PropagateNaN>(&eigen_minidx);
|
||||
eigen_maxc = v.template maxCoeff<PropagateNaN>(&eigen_maxidx);
|
||||
VERIFY(minidx != eigen_minidx);
|
||||
VERIFY(maxidx != eigen_maxidx);
|
||||
VERIFY((numext::isnan)(eigen_minc));
|
||||
VERIFY((numext::isnan)(eigen_maxc));
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(visitor)
|
||||
|
Loading…
Reference in New Issue
Block a user