https://svn.lrde.epita.fr/svn/oln/trunk/milena
A bit of explanation about why there are deletions (lines starting with
a `-') in the diff of tests/l2.cc: I used `svn copy' to create this file from
tests/l1.cc. So, the differences you see are w.r.t. the latter.
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Refactor the L2-norm, and test it.
* mln/norm/l2.hh: Use type `mln_value_sum(C)' instead of `float'
to handle L2-norm values.
(mln::norm::impl::l2_, mln::norm::impl::l2_distance_): New.
Use to factor the implementations of...
(mln::norm::l2, mln::norm::l2_distance): ...these functions.
* tests/l2.cc: New test.
* tests/Makefile.am (check_PROGRAMS): Add l2.
(l2_SOURCES): New.
mln/norm/l2.hh | 91 +++++++++++++++++++++++++++++++++---------------------
tests/Makefile.am | 2 +
tests/l2.cc | 37 +++++++++++----------
3 files changed, 78 insertions(+), 52 deletions(-)
Index: mln/norm/l2.hh
--- mln/norm/l2.hh (revision 1416)
+++ mln/norm/l2.hh (working copy)
@@ -30,78 +30,99 @@
/*! \file mln/norm/l2.hh
*
- * \brief Define some l2-norm related routines.
+ * \brief Define some L2-norm related routines.
+ * \see
http://mathworld.wolfram.com/L2-Norm.html for more information.
*/
-# include <cmath>
-
+# include <mln/math/sqr.hh>
+# include <mln/math/sqrt.hh>
# include <mln/metal/vec.hh>
+
namespace mln
{
namespace norm
{
- /// Infinity-norm of a vector \p vec.
+ /// L2-norm of a vector \a vec.
+ /// \{
template <unsigned n, typename C>
- float l2(const C (&vec)[n]);
+ mln_value_sum(C) l2(const C (&vec)[n]);
- /// Infinity-norm distance between vectors \p v1 and \p v2.
template <unsigned n, typename C>
- float l2_distance(const C (&v1)[n], const C (&v2)[n]);
+ mln_value_sum(C) l2(const metal::vec<n,C>& vec);
+ /// \}
+ /// L2-norm distance between vectors \a vec1 and \p vec2.
+ /// \{
template <unsigned n, typename C>
- float l2(const metal::vec<n,C>& vec);
+ mln_value_sum(C) l2_distance(const C (&vec1)[n], const C (&vec2)[n]);
template <unsigned n, typename C>
- float l2_distance(const metal::vec<n,C>& vec1, const
metal::vec<n,C>& vec2);
-
- // FIXME: Replace float by mln_value_sum(C)...
+ mln_value_sum(C) l2_distance(const metal::vec<n,C>& vec1,
+ const metal::vec<n,C>& vec2);
+ /// \}
# ifndef MLN_INCLUDE_ONLY
- template <unsigned n, typename C>
- float l2(const C (&vec)[n])
+ namespace impl
+ {
+
+ template <unsigned n, typename C, typename V>
+ mln_value_sum(C)
+ l2_(const V& vec)
{
- C c = 0;
+ mln_value_sum(C) m = 0;
for (unsigned i = 0; i < n; ++i)
- c += vec[i] * vec[i];
- return sqrt(c);
+ m += mln::math::sqr(vec[i]);
+ return mln::math::sqrt(m);
}
- template <unsigned n, typename C>
- float l2_distance(const C (&v1)[n], const C (&v2)[n])
+ template <unsigned n, typename C, typename V>
+ mln_value_sum(C)
+ l2_distance_(const V& vec1, const V& vec2)
{
- C d = 0;
+ mln_value_sum(C) d = 0;
for (unsigned i = 0; i < n; ++i)
- {
- C dd = v1[i] - v2[i];
- d += dd * dd;
- }
- return sqrt(d);
+ d += mln::math::sqr(vec1[i] - vec2[i]);
+ return mln::math::sqrt(d);
}
+ } // end of namespace mln::norm::impl
+
+
+ /*----------.
+ | Facades. |
+ `----------*/
+
template <unsigned n, typename C>
- float l2(const metal::vec<n,C>& vec)
+ mln_value_sum(C)
+ l2(const C (&vec)[n])
{
- C c = 0;
- for (unsigned i = 0; i < n; ++i)
- c += vec[i] * vec[i];
- return sqrt(c);
+ return impl::l2_<n, C>(vec);
}
template <unsigned n, typename C>
- float l2(const metal::vec<n,C>& vec1, const metal::vec<n,C>&
vec2)
+ mln_value_sum(C)
+ l2(const metal::vec<n,C>& vec)
{
- C d = 0;
- for (unsigned i = 0; i < n; ++i)
+ return impl::l2_<n, C>(vec);
+ }
+
+ template <unsigned n, typename C>
+ mln_value_sum(C)
+ l2_distance(const C (&vec1)[n], const C (&vec2)[n])
{
- C dd = vec1[i] - vec2[i];
- d += dd * dd;
+ return impl::l2_distance_<n, C>(vec1, vec2);
}
- return sqrt(d);
+
+ template <unsigned n, typename C>
+ mln_value_sum(C)
+ l2_distance(const metal::vec<n,C>& vec1, const metal::vec<n,C>&
vec2)
+ {
+ return impl::l2_distance_<n, C>(vec1, vec2);
}
# endif // ! MLN_INCLUDE_ONLY
Index: tests/l2.cc
--- tests/l2.cc (revision 1411)
+++ tests/l2.cc (working copy)
@@ -25,47 +25,50 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/// \file tests/l1.hh
-/// \brief Test the L1-norm.
+/// \file tests/l2.hh
+/// \brief Test the L2-norm.
+#include <cmath>
#include <cassert>
#include <mln/metal/vec.hh>
#include <mln/math/abs.hh>
-#include <mln/norm/l1.hh>
+#include <mln/norm/l2.hh>
// FIXME: We should have a almost_equal function somewhere in Milena.
static const float epsilon = 0.0001;
using mln::metal::vec;
-using mln::norm::l1;
+using mln::norm::l2;
template <typename V>
-void check_l1 (const V& vec1, const V& vec2)
+void check_l2 (const V& vec1, const V& vec2)
{
- assert (mln::math::abs(mln::norm::l1(vec1) - mln::norm::l1(vec2))
+ assert (mln::math::abs(mln::norm::l2(vec1) - mln::norm::l2(vec2))
< epsilon);
}
template <typename V, typename S>
-void check_l1_distance (const V& vec1, const V& vec2, const S& ref_val)
+void check_l2_distance (const V& vec1, const V& vec2, const S& ref_val)
{
- assert (mln::math::abs(mln::norm::l1_distance(vec1, vec2) - ref_val)
+ assert (mln::math::abs(mln::norm::l2_distance(vec1, vec2) - ref_val)
< epsilon);
}
int main ()
{
- vec<3, int> t; t.set (1, -2, 3);
- vec<3, int> u; u.set (5, 1, 0);
- int d = (5 - 1) + (1 + 2) + 3;
+ vec<3, int> t; t.set (2, -2, 3);
+ vec<3, int> u; u.set (4, 1, 0);
+ float d = std::sqrt((4 - 2) * (4 - 2) +
+ (1 + 2) * (1 + 2) +
+ (0 - 3) * (0 - 3));
- check_l1(t, u);
- check_l1_distance (t, u, d);
+ check_l2(t, u);
+ check_l2_distance (t, u, d);
- int v[] = {1, -2, 3};
- int w[] = {5, 1, 0};
+ int v[] = {2, -2, 3};
+ int w[] = {4, 1, 0};
- check_l1(v, w);
- check_l1_distance (v, w, d);
+ check_l2(v, w);
+ check_l2_distance (v, w, d);
}
Index: tests/Makefile.am
--- tests/Makefile.am (revision 1416)
+++ tests/Makefile.am (working copy)
@@ -85,6 +85,7 @@
io_ppm \
\
l1 \
+ l2 \
labeling_algo \
labeling_estimate \
labeling_foreground \
@@ -272,6 +273,7 @@
io_ppm_SOURCES = io_ppm.cc
l1_SOURCES = l1.cc
+l2_SOURCES = l2.cc
labeling_algo_SOURCES = labeling_algo.cc
labeling_estimate_SOURCES = labeling_estimate.cc
labeling_foreground_SOURCES = labeling_foreground.cc