Commit 65fd6b89 authored by Nicolas Ballas's avatar Nicolas Ballas
Browse files

Externalize element and nelement method in fastest images.

	* mln/opt/element.hh: New, define opt::element and opt::nelements.
	* mln/debug/println_with_border.spe.hh,
	* mln/debug/println_with_border.hh,
	* mln/data/paste.spe.hh,
	* mln/data/fill_with_value.spe.hh,
	* mln/data/fill_with_image.spe.hh,
	* mln/data/memcpy_.hh,
	* mln/data/memset_.hh,
	* mln/border/fill.hh,
	* mln/border/duplicate.hh,
	* mln/border/mirror.hh,
	* tests/opt/value.cc,
	* tests/border/duplicate_full.cc,
	* tests/border/mirror_full.cc,
	* tests/border/fill_full.cc,
	* tests/border/duplicate.cc,
	* tests/border/mirror.cc,
	* tests/border/fill.cc: Use now opt::element and opt::nelements.
	* mln/opt/value.hh: Update Copyright.
	* tests/opt/element.cc: New tests.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@3179 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent 4258ef25
2009-01-21 Nicolas Ballas <ballas@lrde.epita.fr>
Externalize element and nelement method in fastest images.
* mln/opt/element.hh: New, define opt::element and opt::nelements.
* mln/debug/println_with_border.spe.hh,
* mln/debug/println_with_border.hh,
* mln/data/paste.spe.hh,
* mln/data/fill_with_value.spe.hh,
* mln/data/fill_with_image.spe.hh,
* mln/data/memcpy_.hh,
* mln/data/memset_.hh,
* mln/border/fill.hh,
* mln/border/duplicate.hh,
* mln/border/mirror.hh,
* tests/opt/value.cc,
* tests/border/duplicate_full.cc,
* tests/border/mirror_full.cc,
* tests/border/fill_full.cc,
* tests/border/duplicate.cc,
* tests/border/mirror.cc,
* tests/border/fill.cc: Use now opt::element and opt::nelements.
* mln/opt/value.hh: Update Copyright.
* tests/opt/element.cc: New tests.
2009-01-21 Ugo Jardonnet <ugo.jardonnet@lrde.epita.fr>
 
Fix mln mean. mln_sum(T) MUST be divisible by unsigned.
......@@ -37,6 +37,7 @@
# include <mln/core/routine/primary.hh>
# include <mln/core/box_runstart_piter.hh>
# include <mln/border/get.hh>
# include <mln/opt/element.hh>
namespace mln
......@@ -75,11 +76,11 @@ namespace mln
unsigned border = ima.border();
for (unsigned i = 0; i < border; ++i)
ima.element(i) = ima.element(border);
opt::element(ima, i) = opt::element(ima, border);
unsigned st = border + len_c - 1;
for (unsigned i = st + 1; i < ima.nelements(); ++i)
ima.element(i) = ima.element(st);
for (unsigned i = st + 1; i < opt::nelements(ima); ++i)
opt::element(ima, i) = opt::element(ima, st);
trace::exiting("border::impl::duplicate_1D");
}
......@@ -104,23 +105,23 @@ namespace mln
{
st = ima.index_of_point (pl);
for (unsigned i = 1; i <= border; ++i)
ima.element(st - i) = ima.element(st);
opt::element(ima, st - i) = opt::element(ima, st);
st = st + len_c - 1;
for (unsigned i = 1; i <= border; ++i)
ima.element(st + i) = ima.element(st);
opt::element(ima, st + i) = opt::element(ima, st);
}
// Duplicate n first * border line
st = real_len_c * border;
for (unsigned k = 0; k < border; ++k)
for (unsigned i = 0; i < real_len_c; ++i)
ima.element(k * real_len_c + i) = ima.element(st + i);
opt::element(ima, k * real_len_c + i) = opt::element(ima, st + i);
// Duplicate n last * border line
st = real_len_c * (border + len_r - 1);
for (unsigned k = 1; k <= border; ++k)
for (unsigned i = st; i < st + real_len_c; ++i)
ima.element(k * real_len_c + i) = ima.element(i);
opt::element(ima, k * real_len_c + i) = opt::element(ima, i);
trace::exiting("border::impl::duplicate_2D");
}
......@@ -155,10 +156,10 @@ namespace mln
{
st = ima.index_of_point (pl);
for (unsigned i = 1; i <= border; ++i)
ima.element(st - i) = ima.element(st);
opt::element(ima, st - i) = opt::element(ima, st);
st = st + len_c - 1;
for (unsigned i = 1; i <= border; ++i)
ima.element(st + i) = ima.element(st);
opt::element(ima, st + i) = opt::element(ima, st);
pl.next();
}
......@@ -166,26 +167,28 @@ namespace mln
st = border * face + k * face + border * real_len_c ;
for (unsigned j = 1; j <= border; ++j)
for (unsigned i = 0; i < real_len_c; ++i)
ima.element(st - j * real_len_c + i) = ima.element(st + i);
opt::element(ima, st - j * real_len_c + i) =
opt::element(ima, st + i);
// Duplicate n last * border line
st = border * face + k * face + (len_r + border - 1) * real_len_c ;
for (unsigned j = 1; j <= border; ++j)
for (unsigned i = 0; i < real_len_c; ++i)
ima.element(st + j * real_len_c + i) = ima.element(st + i);
opt::element(ima, st + j * real_len_c + i) =
opt::element(ima, st + i);
}
// Duplicate n first * border face
st = border * face;
for (unsigned k = 0; k < border; ++k)
for (unsigned i = 0; i < face; ++i)
ima.element(k * face + i) = ima.element(st + i);
opt::element(ima, k * face + i) = opt::element(ima, st + i);
// Duplicate n last * border face
st = (len_s + border - 1) * face;
for (unsigned k = 1; k <= border; ++k)
for (unsigned i = 0; i < face; ++i)
ima.element(st + k * face + i) = ima.element(st + i);
opt::element(ima, st + k * face + i) = opt::element(ima, st + i);
trace::exiting("border::impl::duplicate_3D");
}
......
......@@ -38,6 +38,7 @@
# include <mln/core/concept/image.hh>
# include <mln/core/box_runstart_piter.hh>
# include <mln/opt/element.hh>
namespace mln
......@@ -85,7 +86,7 @@ namespace mln
void fill_size_1(const Image<I>& ima_, const mln_value(I)& v)
{
trace::entering("border::impl::fill_size_1");
const I& ima = exact(ima_);
internal::fill_tests(ima, v);
......@@ -99,14 +100,14 @@ namespace mln
for_all (pl)
{
unsigned end = ima.index_of_point (pl);
std::memset((void*)&ima.element(st),
std::memset((void*)&opt::element(ima, st),
*(const int*)(&v),
end - st);
st = end + len_r;
}
std::memset((void*)&ima.element(st),
std::memset((void*)&opt::element(ima, st),
*(const int*)(&v),
ima.nelements () - st);
opt::nelements(ima) - st);
trace::exiting("border::impl::fill_size_1");
}
......@@ -130,11 +131,11 @@ namespace mln
{
unsigned end = ima.index_of_point (pl);
for (unsigned i = st; i < end; ++i)
ima.element(i) = v;
opt::element(ima, i) = v;
st = end + len_r;
}
for (unsigned i = st; i < ima.nelements (); ++i)
ima.element(i) = v;
for (unsigned i = st; i < opt::nelements(ima); ++i)
opt::element(ima, i) = v;
trace::exiting("border::impl::fill_size_n");
}
......@@ -145,7 +146,7 @@ namespace mln
namespace internal
{
// Dispatch.
template <typename I>
......
......@@ -49,6 +49,8 @@
# include <mln/geom/max_col.hh>
# include <mln/geom/ninds.hh>
# include <mln/opt/element.hh>
namespace mln
{
......@@ -95,10 +97,10 @@ namespace mln
{
def::coord i = 0;
for (; i < min; ++i)
ima.element(border - 1 - i) = ima(point1d(i));
opt::element(ima, border - 1 - i) = ima(point1d(i));
for (; i < border; ++i)
ima.element(border - 1 - i) = ima(point1d(static_cast<def::coord>(min - 1)));
opt::element(ima, border - 1 - i) = ima(point1d(static_cast<def::coord>(min - 1)));
}
/// right border
......@@ -109,12 +111,12 @@ namespace mln
for (;
i < min;
++i, --j)
ima.element(border + nbinds + i) = ima(point1d(j));
opt::element(ima, border + nbinds + i) = ima(point1d(j));
++j;
for (;
i < border;
++i)
ima.element(border + nbinds + i) = ima(point1d(j));
opt::element(ima, border + nbinds + i) = ima(point1d(j));
}
trace::exiting("border::impl::mirror_");
}
......@@ -136,49 +138,56 @@ namespace mln
// mirror top left corner
for (unsigned i = 0; i < border; ++i)
for (unsigned j = 0; j < border; ++j)
ima.element(i * ((nbcols + 1) + 2 * border) + j) = ima.element(s);
opt::element(ima, i * ((nbcols + 1) + 2 * border) + j) =
opt::element(ima, s);
// mirror top left corner
s = start + nbcols;
for (unsigned i = 0; i < border; ++i)
for (unsigned j = 1; j <= border; ++j)
ima.element(i * ((nbcols + 1) + 2 * border) + (nbcols + border + j)) = ima.element(s);
opt::element(ima, i * ((nbcols + 1) + 2 * border) + (nbcols + border + j)) = opt::element(ima, s);
// mirror bottom left corner
s = start + (nbrows * real_nbcols);
for (unsigned i = 1; i <= border; ++i)
for (unsigned j = 1; j <= border; ++j)
ima.element(s - i + (j * (real_nbcols))) = ima.element(s);
opt::element(ima, s - i + (j * (real_nbcols))) =
opt::element(ima, s);
// mirror bottom right corner
s = start + (nbrows * real_nbcols) + nbcols;
for (unsigned i = 1; i <= border; ++i)
for (unsigned j = 1; j <= border; ++j)
ima.element(s + i + (j * real_nbcols)) = ima.element(s);
opt::element(ima, s + i + (j * real_nbcols)) =
opt::element(ima, s);
// mirror top border
s = start;
for (unsigned i = 0; i <= nbcols; ++i)
for (unsigned j = 1; j <= border; ++j)
ima.element(s + i - (j * real_nbcols)) = ima.element(s + i + ((j - 1)* real_nbcols));
opt::element(ima, s + i - (j * real_nbcols)) =
opt::element(ima, s + i + ((j - 1)* real_nbcols));
// mirror left border
s = start;
for (unsigned i = 0; i <= nbrows; ++i)
for (unsigned j = 1; j <= border; ++j)
ima.element(s + (i * real_nbcols) - j) = ima.element(s + (i * real_nbcols) + (j - 1));
opt::element(ima, s + (i * real_nbcols) - j) =
opt::element(ima, s + (i * real_nbcols) + (j - 1));
// mirror right border
s = start;
for (unsigned i = 0; i <= nbrows; ++i)
for (unsigned j = 1; j <= border; ++j)
ima.element(s + (i * real_nbcols + nbcols) + j) = ima.element(s + (i * real_nbcols + nbcols) - (j - 1));
opt::element(ima, s + (i * real_nbcols + nbcols) + j) =
opt::element(ima, s + (i * real_nbcols + nbcols) - (j - 1));
// mirror bottom border
s = start + (nbrows * real_nbcols);
for (unsigned i = 0; i <= nbcols; ++i)
for (unsigned j = 1; j <= border; ++j)
ima.element(s + i + (j * real_nbcols)) = ima.element(s + i - ((j - 1)* real_nbcols));
opt::element(ima, s + i + (j * real_nbcols)) =
opt::element(ima, s + i - ((j - 1)* real_nbcols));
trace::exiting("border::impl::mirror_");
}
......
......@@ -44,6 +44,7 @@
# include <mln/core/box_runstart_piter.hh>
# include <mln/border/get.hh>
# include <mln/opt/value.hh>
# include <mln/opt/element.hh>
# ifndef MLN_INCLUDE_ONLY
......@@ -89,7 +90,7 @@ namespace mln
*(src.address_()) = data.buffer();
*(dst.address_()) = ima.buffer();
memcpy_(dst, src, ima.nelements());
memcpy_(dst, src, opt::nelements(ima));
trace::exiting("data::impl::fill_with_image_fastest");
}
......
......@@ -38,6 +38,7 @@
# include <mln/data/memset_.hh>
# include <mln/opt/value.hh>
# include <mln/opt/element.hh>
# ifndef MLN_INCLUDE_ONLY
......@@ -89,7 +90,7 @@ namespace mln
trait::image::value_access::direct))::check();
mln_value(I) v = static_cast<mln_value(I)>(val);
data::memset_(ima, ima.point_at_index(0), v, ima.nelements());
data::memset_(ima, ima.point_at_index(0), v, opt::nelements(ima));
trace::exiting("data::impl::fill_with_value_one_block");
}
......
......@@ -39,6 +39,8 @@
# include <mln/core/concept/image.hh>
# include <mln/core/pixel.hh>
# include <mln/metal/is_not_const.hh>
# include <mln/opt/element.hh>
namespace mln
......@@ -126,18 +128,18 @@ namespace mln
mln_precondition(dest.ima().is_valid());
mln_precondition(src.ima().is_valid());
mln_precondition(&dest.val() >= &dest.ima().element(0));
mln_precondition(&dest.val() < &dest.ima().element(0) +
dest.ima().nelements());
mln_precondition(&dest.val() >= &opt::element(dest.ima(), 0));
mln_precondition(&dest.val() < &opt::element(dest.ima(), 0) +
opt::nelements(dest.ima()));
mln_precondition(&dest.val() + n <= &dest.ima().element(0) +
dest.ima().nelements());
mln_precondition(&dest.val() + n <= &opt::element(dest.ima(), 0) +
opt::nelements(dest.ima()));
mln_precondition(&src.val() >= &src.ima().element(0));
mln_precondition(&src.val() < &src.ima().element(0) +
src.ima().nelements());
mln_precondition(&src.val() + n <= &src.ima().element(0) +
src.ima().nelements());
mln_precondition(&src.val() >= &opt::element(src.ima(), 0));
mln_precondition(&src.val() < &opt::element(src.ima(), 0) +
opt::nelements(src.ima()));
mln_precondition(&src.val() + n <= &opt::element(src.ima(), 0) +
opt::nelements(src.ima()));
impl::memcpy__(dest, src, n);
......
......@@ -38,6 +38,8 @@
# include <mln/core/concept/image.hh>
# include <mln/core/pixel.hh>
# include <mln/metal/is_not_const.hh>
# include <mln/opt/element.hh>
namespace mln
......@@ -132,8 +134,10 @@ namespace mln
P& pix = mln::internal::force_exact<P>(pix_);
mln_precondition(pix.ima().is_valid());
mln_precondition(& pix.val() >= & pix.ima()[0]);
mln_precondition(& pix.val() < & pix.ima()[0] + pix.ima().nelements());
mln_precondition(& pix.val() + n <= & pix.ima()[0] + pix.ima().nelements());
mln_precondition(& pix.val() < & pix.ima()[0] +
opt::nelements(pix.ima()));
mln_precondition(& pix.val() + n <= & pix.ima()[0] +
opt::nelements(pix.ima()));
impl::memset__(pix, v, n);
......@@ -151,7 +155,7 @@ namespace mln
mln_precondition(input.is_valid());
mln_precondition(input.has(p));
mln_precondition(input.index_of_point(p) + n <= input.nelements());
mln_precondition(input.index_of_point(p) + n <= opt::nelements(input));
pixel<I> pix(input, p);
impl::memset__(pix, v, n);
......
......@@ -43,6 +43,7 @@
# include <mln/core/box_runstart_piter.hh>
# include <mln/border/get.hh>
# include <mln/opt/value.hh>
# include <mln/opt/element.hh>
......@@ -111,7 +112,7 @@ namespace mln
*(src.address_()) = input.buffer();
*(dst.address_()) = output.buffer();
memcpy_(dst, src, input.nelements());
memcpy_(dst, src, opt::nelements(input));
trace::exiting("data::impl::paste_fastest");
}
......
......@@ -43,6 +43,7 @@
# include <mln/debug/format.hh>
// Specializations are in:
# include <mln/debug/println_with_border.spe.hh>
# include <mln/opt/element.hh>
namespace mln
{
......@@ -66,7 +67,7 @@ namespace mln
void
println_with_border(const S&, const I& input)
{
for (size_t i = 0; i < input.nelements(); i++)
for (size_t i = 0; i < opt::nelements(input); i++)
std::cout << format(input.buffer()[i]) << ' ';
std::cout << std::endl;
}
......
......@@ -40,6 +40,7 @@
# include <mln/core/concept/image.hh>
# include <mln/core/concept/window.hh>
# include <mln/debug/format.hh>
# include <mln/opt/element.hh>
namespace mln
{
......@@ -61,7 +62,7 @@ namespace mln
println_with_border(const box2d& b, const I& input)
{
const unsigned ncols = b.ncols() + 2 * input.border();
for (size_t i = 0; i < input.nelements(); i++)
for (size_t i = 0; i < opt::nelements(input); i++)
{
std::cout << format(input.buffer()[i]) << ' ';
if (((i + 1) % ncols) == 0)
......
// Copyright (C) 2009 EPITA Research and Development Laboratory
// (LRDE)
//
// 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_OPT_ELEMENT_HH
# define MLN_OPT_ELEMENT_HH
/// \file mln/opt/element.hh
///
/// Define the opt::element and opt::nelements routines.
# include <mln/core/concept/image.hh>
# include <mln/trait/images.hh>
namespace mln
{
namespace opt
{
template <typename I>
inline
mln_rvalue(I) element(const Image<I>& ima, unsigned index);
template <typename I>
inline
mln_lvalue(I) element(Image<I>& ima, unsigned index);
template <typename I>
inline
unsigned nelements(const Image<I>& ima);
# ifndef MLN_INCLUDE_ONLY
namespace impl
{
template <typename I>
inline
mln_rvalue(I) element_impl(trait::image::category::domain_morpher,
const Image<I>& ima, unsigned index)
{
return element(*exact(ima).delegatee_());
}
template <typename I>
inline
mln_rvalue(I) element_impl(trait::image::category::any,
const Image<I>& ima, unsigned index)
{
mlc_and(mlc_is(mln_trait_image_value_storage(I),
trait::image::value_storage::one_block),
mlc_is(mln_trait_image_value_access(I),
trait::image::value_access::direct))::check();
return exact(ima).element(index);
}
template <typename I>
inline
mln_lvalue(I) element_impl(trait::image::category::domain_morpher,
Image<I>& ima, unsigned index)
{
return element(*exact(ima).delegatee_());
}
template <typename I>
inline
mln_lvalue(I) element_impl(trait::image::category::any,
Image<I>& ima, unsigned index)
{
mlc_and(mlc_is(mln_trait_image_value_storage(I),
trait::image::value_storage::one_block),
mlc_is(mln_trait_image_value_access(I),
trait::image::value_access::direct))::check();
return exact(ima).element(index);
}
template <typename I>
inline
unsigned nelements_impl(trait::image::category::domain_morpher,
const Image<I>& ima)
{
return nelements(*exact(ima).delegatee_());
}
template <typename I>
inline
unsigned nelements_impl(trait::image::category::any,
const Image<I>& ima)
{
mlc_is(mln_trait_image_value_storage(I),
trait::image::value_storage::one_block)::check();
return exact(ima).nelements();
}
} // end of namespace mln::opt::impl
template <typename I>
inline
mln_rvalue(I) element(const Image<I>& ima, unsigned index)
{
return impl::element_impl(mln_trait_image_category(I)(), ima, index);
}
template <typename I>
inline
mln_lvalue(I) element(Image<I>& ima, unsigned index)
{
return impl::element_impl(mln_trait_image_category(I)(), ima, index);
}
template <typename I>