diff --git a/Eigen/Array b/Eigen/Array index fbfffe36c..c9e6c761a 100644 --- a/Eigen/Array +++ b/Eigen/Array @@ -28,6 +28,7 @@ namespace Eigen { #include "src/Array/Select.h" #include "src/Array/PartialRedux.h" #include "src/Array/Random.h" +#include "src/Array/Norms.h" } // namespace Eigen diff --git a/Eigen/src/Array/Norms.h b/Eigen/src/Array/Norms.h new file mode 100644 index 000000000..10c157f0d --- /dev/null +++ b/Eigen/src/Array/Norms.h @@ -0,0 +1,80 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. Eigen itself is part of the KDE project. +// +// Copyright (C) 2008 Benoit Jacob +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +#ifndef EIGEN_ARRAY_NORMS_H +#define EIGEN_ARRAY_NORMS_H + +template +struct ei_lpNorm_selector +{ + typedef typename NumTraits::Scalar>::Real RealScalar; + inline static RealScalar run(const MatrixBase& m) + { + return ei_pow(m.cwise().abs().cwise().pow(p).sum(), RealScalar(1)/p); + } +}; + +template +struct ei_lpNorm_selector +{ + inline static typename NumTraits::Scalar>::Real run(const MatrixBase& m) + { + return m.cwise().abs().sum(); + } +}; + +template +struct ei_lpNorm_selector +{ + inline static typename NumTraits::Scalar>::Real run(const MatrixBase& m) + { + return m.norm(); + } +}; + +template +struct ei_lpNorm_selector +{ + inline static typename NumTraits::Scalar>::Real run(const MatrixBase& m) + { + return m.cwise().abs().maxCoeff(); + } +}; + +/** \array_module + * + * \returns the \f$ \ell^p \f$ norm of *this, that is, returns the p-th root of the sum of the p-th powers of the absolute values + * of the coefficients of *this. If \a p is the special value \a Eigen::Infinity, this function returns the \f$ \ell^p\infty \f$ + * norm, that is the maximum of the absolute values of the coefficients of *this. + * + * \sa norm() + */ +template +template +inline typename NumTraits::Scalar>::Real MatrixBase::lpNorm() const +{ + return ei_lpNorm_selector::run(*this); +} + +#endif // EIGEN_ARRAY_NORMS_H diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 1b07cba6b..dbf8da544 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -557,6 +557,8 @@ template class MatrixBase inline const Select, ElseDerived > select(typename ElseDerived::Scalar thenScalar, const MatrixBase& elseMatrix) const; + template RealScalar lpNorm() const; + /////////// LU module /////////// const LU lu() const; diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index 3fb5f918d..897aa8616 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -27,6 +27,7 @@ #define EIGEN_CONSTANTS_H const int Dynamic = 10000; +const int Infinity = -1; /** \defgroup flags flags * \ingroup Core_Module diff --git a/test/array.cpp b/test/array.cpp index 977449365..e1047489d 100644 --- a/test/array.cpp +++ b/test/array.cpp @@ -113,6 +113,16 @@ template void comparisons(const MatrixType& m) VERIFY_IS_APPROX( (m1.cwise().abs().cwise() void lpNorm(const VectorType& v) +{ + VectorType u = VectorType::Random(v.size()); + + VERIFY_IS_APPROX(u.template lpNorm(), u.cwise().abs().maxCoeff()); + VERIFY_IS_APPROX(u.template lpNorm<1>(), u.cwise().abs().sum()); + VERIFY_IS_APPROX(u.template lpNorm<2>(), ei_sqrt(u.cwise().abs().cwise().square().sum())); + VERIFY_IS_APPROX(ei_pow(u.template lpNorm<5>(), typename VectorType::RealScalar(5)), u.cwise().abs().cwise().pow(5).sum()); +} + void test_array() { for(int i = 0; i < g_repeat; i++) { @@ -130,4 +140,12 @@ void test_array() CALL_SUBTEST( comparisons(MatrixXf(8, 12)) ); CALL_SUBTEST( comparisons(MatrixXi(8, 12)) ); } + for(int i = 0; i < g_repeat; i++) { + CALL_SUBTEST( lpNorm(Matrix()) ); + CALL_SUBTEST( lpNorm(Vector2f()) ); + CALL_SUBTEST( lpNorm(Vector3d()) ); + CALL_SUBTEST( lpNorm(Vector4f()) ); + CALL_SUBTEST( lpNorm(VectorXf(16)) ); + CALL_SUBTEST( lpNorm(VectorXcd(10)) ); + } }