https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add memcpy_ and memset_ for fast images; some fixes.
* tests/histo.cc: Augment.
* tests/level_memcpy_.cc: New.
* tests/level_memset_.cc: New.
* mln/convert/to_vec_p.hh: Typos.
* mln/core/concept/generalized_pixel.hh (doc): Fix.
* mln/core/concept/fast_image.hh (ncells): New.
Add FIXMEs.
* mln/core/concept/doc/fast_image.hh: Update.
* mln/level/fill.hh (fill_with_value): Use memset_.
* mln/level/memset_.hh: New.
* mln/level/memcpy_.hh: New.
* mln/value/int_s.hh (props): Fix card_.
(int_s): Fix preconditions.
mln/convert/to_vec_p.hh | 16 ++--
mln/core/concept/doc/fast_image.hh | 7 +
mln/core/concept/fast_image.hh | 16 ++--
mln/core/concept/generalized_pixel.hh | 4 -
mln/level/fill.hh | 17 ----
mln/level/memcpy_.hh | 112 ++++++++++++++++++++++++++++
mln/level/memset_.hh | 133 ++++++++++++++++++++++++++++++++++
mln/value/int_s.hh | 14 ++-
tests/histo.cc | 22 +++++
tests/level_memcpy_.cc | 58 ++++++++++++++
tests/level_memset_.cc | 53 +++++++++++++
11 files changed, 416 insertions(+), 36 deletions(-)
Index: tests/histo.cc
--- tests/histo.cc (revision 1080)
+++ tests/histo.cc (working copy)
@@ -34,8 +34,10 @@
#include <mln/core/image2d_b.hh>
#include <mln/value/int_u8.hh>
+#include <mln/value/int_s.hh>
#include <mln/debug/iota.hh>
+#include <mln/debug/println.hh>
#include <mln/accu/histo.hh>
#include <mln/histo/compute.hh>
@@ -62,8 +64,28 @@
{
image2d_b<int_u8> ima(3, 3);
debug::iota(ima);
+ ima.at(0,0) = 2;
+ debug::println(ima);
+
histo::data< value::set<int_u8> > h = histo::compute(ima);
std::cout << h << std::endl;
+
+ int_u8 i = 2;
+ std::cout << h(i) << std::endl;
}
+// {
+// typedef value::int_s<5> int_s5;
+// image2d_b<int_s5> ima(3, 3);
+// debug::iota(ima);
+// ima.at(0,0) = 2;
+// debug::println(ima);
+
+// histo::data< value::set<int_s5> > h = histo::compute(ima);
+// std::cout << h(2) << std::endl;
+
+// for (unsigned i = 0; i < h.vset().nvalues(); ++i)
+// std::cout << h[i] << std::endl;
+// }
+
}
Index: tests/level_memcpy_.cc
--- tests/level_memcpy_.cc (revision 0)
+++ tests/level_memcpy_.cc (revision 0)
@@ -0,0 +1,58 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/*! \file tests/level_memcpy_.cc
+ *
+ * \brief Tests on mln::level::memcpy_.
+ *
+ * \todo Make this test not dummy!
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/core/inplace.hh>
+#include <mln/debug/iota.hh>
+#include <mln/level/memcpy_.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ typedef image2d_b<int> I;
+ I ima(3, 3);
+ debug::iota(ima);
+
+ point2d
+ src = make::point2d(0, 2),
+ dest = make::point2d(1, 2);
+
+ level::memcpy_(inplace(make::pixel(ima, dest)),
+ make::pixel(ima, src),
+ 2 + 2 * ima.border());
+
+ mln_assertion(ima(dest) = ima(src));
+}
Index: tests/level_memset_.cc
--- tests/level_memset_.cc (revision 0)
+++ tests/level_memset_.cc (revision 0)
@@ -0,0 +1,53 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/*! \file tests/level_memset_.cc
+ *
+ * \brief Tests on mln::level::memset_.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/geom/ncols.hh>
+#include <mln/level/fill.hh>
+#include <mln/level/memset_.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ image2d_b<int> ima(3, 3);
+ level::fill(ima, 0);
+ int X = 9;
+ level::memset_(ima, make::point2d(0,0),
+ X,
+ geom::ncols(ima) + 2 * ima.border() + 1);
+ // ^
+ // |
+ mln_assertion(ima.at(1,0) = X); // <----------------+
+ mln_assertion(ima.at(1,1) != X);
+}
Index: mln/convert/to_vec_p.hh
--- mln/convert/to_vec_p.hh (revision 1080)
+++ mln/convert/to_vec_p.hh (working copy)
@@ -34,6 +34,7 @@
*/
# include <mln/core/vec_p.hh>
+# include <mln/core/concept/window.hh>
namespace mln
@@ -47,9 +48,9 @@
vec_p<mln_point(S)> to_vec_p(const Point_Set<S>& pset);
- /// Convert a window \p win with a point \p p into a vec_p (point set vector).
+ /// Convert a window \p win centered at point \p p into a vec_p (point set vector).
template <typename W>
- vec_p<mln_point(W)> to_vec_p(const Window<W>& win, const mln_point(W)
p);
+ vec_p<mln_point(W)> to_vec_p(const Window<W>& win, const
mln_point(W)& p);
# ifndef MLN_INCLUDE_ONLY
@@ -67,17 +68,16 @@
}
template <typename W>
- vec_p<mln_point(W)> to_vec_p(const Window<W>& win, const mln_point(W)
p_center)
+ vec_p<mln_point(W)> to_vec_p(const Window<W>& win, const
mln_point(W)& p)
{
vec_p<mln_point(W)> v;
- mln_qiter(W) dp(win, p_center);
-
v.reserve(exact(win).ndpoints());
-
- for_all(dp)
- v.append(dp);
+ mln_qiter(W) q(win, p);
+ for_all(q)
+ v.append(q);
return v;
}
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::convert
Index: mln/core/concept/generalized_pixel.hh
--- mln/core/concept/generalized_pixel.hh (revision 1080)
+++ mln/core/concept/generalized_pixel.hh (working copy)
@@ -41,13 +41,9 @@
namespace mln
{
- // FIXME: \class Generalized_Pixel Generalized_Pixel.hh
"mln/core/concept/doc/Generalized_Pixel.hh"
-
/*! \brief Base class for implementation classes that are pixels or that
* have the behavior of pixels.
*
- * "Generalized_Pixel" is "Generalized Pixel" for short.
- *
* \warning This class does \em not derive from mln::Object; it is
* for use as a parallel hierarchy.
*
Index: mln/core/concept/fast_image.hh
--- mln/core/concept/fast_image.hh (revision 1080)
+++ mln/core/concept/fast_image.hh (working copy)
@@ -51,7 +51,7 @@
/*
unsigned border();
- int offset(const dpoint& dp) const;
+ int offset(const dpoint& dp) const; // FIXME: std::ptr_diff_t?
point point_at_offset(unsigned o) const;
mln_qlf_value(E)* buffer();
@@ -59,6 +59,8 @@
rvalue operator[](unsigned o) const;
lvalue operator[](unsigned o);
+
+ std::size_t ncells() const;
*/
@@ -72,7 +74,8 @@
* \post p = point_at_offset(result)
*/
template <typename P>
- unsigned offset(const Generalized_Point<P>& p) const;
+ unsigned
+ offset_at(const Generalized_Point<P>& p) const;
protected:
Fast_Image();
@@ -83,11 +86,11 @@
template <typename E>
template <typename P>
- unsigned
- Fast_Image<E>::offset(const Generalized_Point<P>& p_) const
+ unsigned // FIXME: std::size_t?
+ Fast_Image<E>::offset_at(const Generalized_Point<P>& p_) const
{
// FIXME: check that P is mln_point(E)
- const E& this_ = exact(this);
+ const E* this_ = exact(this);
const P& p = internal::force_exact<P>(p_);
mln_precondition(this_->has_data());
mln_precondition(this_->owns_(p));
@@ -128,6 +131,9 @@
lvalue (E::*m7)(unsigned) = & E::operator[];
m7 = 0;
+ std::size_t (E::*m8)() const = & E::ncells;
+ m8 = 0;
+
// FIXME: how to check that qixter are defined when W is unknown!
}
Index: mln/core/concept/doc/fast_image.hh
--- mln/core/concept/doc/fast_image.hh (revision 1080)
+++ mln/core/concept/doc/fast_image.hh (working copy)
@@ -97,6 +97,13 @@
*/
lvalue operator[](unsigned o);
+
+ /*! \brief Give the number of pixels of the image including
+ * those of the virtual border.
+ *
+ * \pre The image has to be initialized.
+ */
+ std::size_t ncells() const;
};
} // end of namespace mln::doc
Index: mln/level/fill.hh
--- mln/level/fill.hh (revision 1080)
+++ mln/level/fill.hh (working copy)
@@ -39,6 +39,7 @@
# include <mln/core/concept/image.hh>
# include <mln/core/concept/function.hh>
+# include <mln/level/memset_.hh>
namespace mln
@@ -131,10 +132,8 @@
// fill_with_value
template <typename I>
- void fill_with_value(Image<I>& ima_, const mln_value(I)& value,
- bool force_call = false)
+ void fill_with_value(Image<I>& ima_, const mln_value(I)& value)
{
- force_call = false; // just to avoid warning ("unused param")
I& ima = exact(ima_);
mln_piter(I) p(ima.domain());
for_all(p)
@@ -145,17 +144,7 @@
void fill_with_value(Fast_Image<I>& ima_, const mln_value(I)& value)
{
I& ima = exact(ima_);
- if (sizeof(mln_value(I)) = 1)
- {
- std::memset((void*)(ima.buffer()),
- *(const int*)(& value), // violent cast
- sizeof(mln_value(I)) * ima.ncells());
- }
- else
- {
- // FIXME: Use memcpy on a chunck when image size is large!
- fill_with_value(ima, value, true);
- }
+ level::memset_(ima, ima.point_at_offset(0), value, ima.ncells());
}
Index: mln/level/memset_.hh
--- mln/level/memset_.hh (revision 0)
+++ mln/level/memset_.hh (revision 0)
@@ -0,0 +1,133 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_LEVEL_MEMSET_HH
+# define MLN_LEVEL_MEMSET_HH
+
+/*! \file mln/level/memset_.hh
+ *
+ * \brief Same as std::memset but for fast images.
+ */
+
+# include <mln/core/concept/fast_image.hh>
+# include <mln/core/pixel.hh>
+
+
+namespace mln
+{
+
+ namespace level
+ {
+
+ /*! Set \p n pixels at value \p v starting from pixel \p p.
+ *
+ * \param[in,out] pix The first pixel to set.
+ * \param[in] v The value to set pixels with.
+ * \param[in] n The number of pixels to set.
+ *
+ * \pre FIXME: !
+ */
+ template <typename P>
+ void memset_(Generalized_Pixel<P>& pix,
+ const mln_value(P)& v, std::size_t n);
+
+ /*! Set \p n points of image \p ima at value \p v starting from
+ * point \p p.
+ *
+ * \param[in,out] input The image.
+ * \param[in] p The first point to set.
+ * \param[in] v The value to set to points.
+ * \param[in] n The number of points to set.
+ *
+ * \pre \p input has to be initialized. FIXME: More.
+ */
+ template <typename I>
+ void memset_(Fast_Image<I>& input, const mln_point(I)& p,
+ const mln_value(I)& v, std::size_t n);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename P>
+ void memset_(Generalized_Pixel<P>& pix_,
+ const mln_value(P)& v, std::size_t n)
+ {
+ typedef mln_image(P) I;
+ // FIXME: metal::is_not_const<I>::check();
+
+ P& pix = internal::force_exact<P>(pix_);
+ mln_precondition(pix.ima().has_data());
+ mln_precondition(& pix.val() >= & pix.ima()[0]);
+ mln_precondition(& pix.val() < & pix.ima()[0] + pix.ima().ncells());
+ mln_precondition(& pix.val() + n <= & pix.ima()[0] +
pix.ima().ncells());
+
+ if (n = 0)
+ {
+ return; // no-op
+ }
+
+ if (n = 1)
+ {
+ pix.val() = v; // one assignment
+ return;
+ }
+
+ if (sizeof(mln_value(I)) = 1)
+ {
+ std::memset((void*)(& pix.val()),
+ *(const int*)(&v), // violent cast
+ n);
+ }
+ else
+ {
+ mln_value(I)* ptr = & pix.val();
+ for (std::size_t i = 0; i < n; ++i)
+ *ptr++ = v;
+ }
+ }
+
+ template <typename I>
+ void memset_(Fast_Image<I>& input_, const mln_point(I)& p,
+ const mln_value(I)& v, std::size_t n)
+ {
+ I& input = exact(input_);
+ mln_precondition(input.has_data());
+ mln_precondition(input.owns_(p));
+ mln_precondition(input.offset_at(p) + n <= input.ncells());
+
+ pixel<I> pix(input, p);
+ memset_(pix, v, n);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::level
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LEVEL_MEMSET_HH
Index: mln/level/memcpy_.hh
--- mln/level/memcpy_.hh (revision 0)
+++ mln/level/memcpy_.hh (revision 0)
@@ -0,0 +1,112 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_LEVEL_MEMCPY_HH
+# define MLN_LEVEL_MEMCPY_HH
+
+/*! \file mln/level/memcpy_.hh
+ *
+ * \brief Same as std::memcpy but for fast images.
+ *
+ * \todo Overload with images and points; Cf. memset_.
+ */
+
+# include <mln/core/concept/fast_image.hh>
+# include <mln/core/pixel.hh>
+
+
+namespace mln
+{
+
+ namespace level
+ {
+
+ /*! Copy \p n pixels starting from pixel \p src to destination
+ * starting from pixel \p dest.
+ *
+ * \param[in,out] dest The destination pixel (to set values).
+ * \param[in] v The source pixel (to get values).
+ * \param[in] n The number of pixels to copy.
+ *
+ * \pre FIXME: !
+ */
+ template <typename Pd, typename Ps>
+ void memcpy_(Generalized_Pixel<Pd>& dest, const
Generalized_Pixel<Ps>& src,
+ std::size_t n);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename Pd, typename Ps>
+ void memcpy_(Generalized_Pixel<Pd>& dest_, const
Generalized_Pixel<Ps>& src_,
+ std::size_t n)
+ {
+ typedef mln_image(Pd) Id;
+ // FIXME: metal::is_not_const<Id>::check();
+ typedef mln_image(Ps) Is;
+ Pd& dest = internal::force_exact<Pd>(dest_);
+ Ps& src = internal::force_exact<Ps>(src_);
+
+ mln_precondition(sizeof(mln_value(Id)) = sizeof(mln_value(Is)));
+ mln_precondition(dest.ima().has_data());
+ mln_precondition(src.ima().has_data());
+ // FIXME: Add precondition about n.
+
+ if (n = 0)
+ {
+ return; // no-op
+ }
+
+ if (n = 1)
+ {
+ dest.val() = src.val(); // one assignment
+ return;
+ }
+
+ if (sizeof(mln_value(Id)) = 1)
+ {
+ std::memcpy(( void*)(& dest.val()), // violent casts
+ (const void*)(& src.val()),
+ n);
+ }
+ else
+ {
+ mln_value(Id)* p_d = & dest.val();
+ const mln_value(Is)* p_s = & src.val();
+ for (std::size_t i = 0; i < n; ++i)
+ *p_d++ = *p_s++;
+ }
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::level
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LEVEL_MEMCPY_HH
Index: mln/value/int_s.hh
--- mln/value/int_s.hh (revision 1080)
+++ mln/value/int_s.hh (working copy)
@@ -101,7 +101,7 @@
template <unsigned n>
struct props< int_s<n> >
{
- static const std::size_t card_ = metal::pow<2, n>::value;
+ static const std::size_t card_ = metal::pow<2, n>::value - 1;
static const int_s<n> max() { return metal::pow<2, n-1>::value - 1; }
static const int_s<n> min() { return - max(); }
static const unsigned nbits = n;
@@ -132,8 +132,10 @@
template <unsigned n>
int_s<n>::int_s(int i)
{
- mln_precondition(i >= mln_min(enc));
- mln_precondition(i <= mln_max(enc));
+ static const int max = metal::pow<2, n-1>::value - 1;
+ static const int min = - max;
+ mln_precondition(i >= min);
+ mln_precondition(i <= max);
this->v_ = enc(i);
}
@@ -141,8 +143,10 @@
int_s<n>&
int_s<n>::operator=(int i)
{
- mln_precondition(i >= mln_min(enc));
- mln_precondition(i <= mln_max(enc));
+ static const int max = metal::pow<2, n-1>::value - 1;
+ static const int min = - max;
+ mln_precondition(i >= min);
+ mln_precondition(i <= max);
this->v_ = i;
return *this;
}