
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@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; }