Olena
Threads by month
- ----- 2025 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
October 2003
- 13 participants
- 16 discussions
1
0
La réflexion de Pollux disant que les adresses étaient forcément
connues par le compilateur à compile-time me titillait sous la douche
ce matin, et je suis arrivé à ça :
---------------8>--------------------------
template <class E>
struct Any
{
static const E obj;
static const Any<E>& obj_ref;
static const int offset;
E& exact() { return *(E*)((char*)(this) - offset); }
// For testing purposes, makes the address of Any<E> different than
// E's address.
int i;
};
// Nécessite un constructeur par défaut et stocke un objet par classe
// (pas par instance). Y'a-t-il moyen de contourner ça ?
template <class E>
const Any<E> obj = E();
template <class E>
const Any<E>& Any<E>::obj_ref = Any<E>::obj;
// Pourrait etre calculé directement dans exact().
template <class E>
const int Any<E>::offset =
(char*)(void*)(&Any<E>::obj_ref) - (char*)(void*)(&Any<E>::obj);
---------------8>--------------------------
L'idée est de prendre la différence d'adresse entre un objet de type
Exact et une référence dessus upcastée en Any<Exact>. Vu que ces
membres sont statiques et constants, le compilateur connaît leurs
adresses à la compilation et peut calculer l'offset à la compilation
également, et donc l'adresse du type exact.
Autre avantage, plus besoin de magouiller dans les constructeurs des
classes filles, la classe de base Any se débrouille toute seule !
Problème majeur pour l'instant, ça nécessite un moyen d'instancier un
objet exact dans Any, et ça stocke une instance de classe par
classe. Mais si on a des types qui peuvent être vides (genre les
images), ca reste cool.
J'en ai profité pour faire qq benchs sur un truc proche de ce qu'on a
dans olena (affectation de tous les points d'une image 10000x10000 en
passant par l'operateur [] de la classe de base Image), ca fait assez
peur avec 3.3 pour les hiérarchies multiples, mais 3.4 sera notre ami :
/*--------.
| g++-3.3 |
`--------*/
Avec héritage multiple (emulé pour le code en static_cast):
======================
Static_cast 1.42s
Pointeur sur exact 2.35s
Offset dynamique 2.55s
Offset statique 2.35s
Sans héritage multiple
======================
Static_cast 1.42s
Pointeur sur exact 1.45s
Offset dynamique 2.55s
Offset statique 1.42s
/*--------.
| g++-3.4 |
`--------*/
Avec héritage multiple (emulé pour le code en static_cast):
======================
Static_cast 1.40s
Pointeur sur exact 2.36s
Offset dynamique 2.57s
Offset statique 1.38s
Sans héritage multiple
======================
Static_cast 1.40s
Pointeur sur exact 1.42s
Offset dynamique 2.56s
Offset statique 1.41s
Bref, dans tous les cas la version offset dynamique est à la rue, et
le pointeur sur this est toujours à la rue aussi avec de l'héritage
multiple. Avec 3.4, l'offset statique s'en sort bien meme en héritage
multiple, alors qu'il se vautre comme les autres avec 3.3.
Enfin bon, tout ça est a prendre avec des pincettes, ca varie
beaucoup selon les compilos.
PS: ca ne marche pas avec 2.95, l'offset vaut toujours 0 !
1
0
Le but est de permettre l'utilisation des types builtin du langage
quand c'est possible (on n'a pas envie de transformer explicitement
une valeur en int_u8 avant de l'affecter à une image).
Exemple pour une image de int_u8 en ruby:
ima = Image2d_u8.new(5, 5)
ima[2, 2] = 12
print ima[2, 2]
print ima[2, 2] + 5
ima_erosion = erosion(ima, win_c4p())
Les checks de ranges sont fait implicitement en c++, au moment de la
conversion en int_u8.
Index: olena/ChangeLog
from Nicolas Burrus <burrus_n(a)lrde.epita.fr>
* oln/io/readable.hh: Add default constructors for SWIG.
+2003-10-09 Nicolas Burrus <burrus_n(a)lrde.epita.fr>
+
* oln/utils/histogram.hh: Temporary fix for ntg::bin type.
2003-10-08 Nicolas Burrus <burrus_n(a)lrde.epita.fr>
Index: tools/swilena/ChangeLog
from Nicolas Burrus <burrus_n(a)lrde.epita.fr>
* meta/swilena_ntg.i: Use builtin value type when possible. Define
int_u8 and int_s8. Remove obsolete typemaps.
* generate_morpho_instantiations.py (write_algorithms): Add int_u8
and int_s8. Enable algorithms fixed by previous patches.
* meta/swilena_image.i: Cleanup. Use builtin value type instead of real
data type when possible.
* expand.sh: Adjust consequently.
* ruby/tests/simple1.rb: Adjust consequently.
* python/tests/simple1.py: Adjust consequently.
* doc/examples/ruby/simple.rb: Adjust consequently.
* doc/examples/python/simple.py: Adjust consequently.
Index: olena/oln/io/readable.hh
--- olena/oln/io/readable.hh Thu, 07 Aug 2003 02:37:23 +0200 burrus_n (oln/b/13_readable.h 1.11 640)
+++ olena/oln/io/readable.hh Thu, 09 Oct 2003 00:37:39 +0200 burrus_n (oln/b/13_readable.h 1.11 640)
@@ -46,6 +46,10 @@
class anything
{
public:
+ // FIXME: these constructors are required by swig
+ anything() : str_() {}
+ anything(const anything& rhs) : str_(rhs.str_) {}
+
anything(const std::string& str) : str_(str) {}
anything(const char* c) : str_(c) {}
Index: tools/swilena/expand.sh
--- tools/swilena/expand.sh Sat, 27 Sep 2003 19:02:23 +0200 burrus_n (oln/s/25_expand.sh 1.10 750)
+++ tools/swilena/expand.sh Thu, 09 Oct 2003 00:37:39 +0200 burrus_n (oln/s/25_expand.sh 1.10 750)
@@ -36,10 +36,12 @@
# int_u8s int_u16s int_u32s
# float_s rgb_8 rgb_16 rgb_32
cat >> "$SWILENA/src/swilena_image${dim}d.i" <<EOF
-make_image(image${dim}d_bin, $dim, ntg_bin)
-make_image(image${dim}d_uint, $dim, ntg_uint)
-make_image(image${dim}d_sint, $dim, ntg_sint)
-make_image(image${dim}d_float, $dim, ntg_float)
+make_image(image${dim}d_bin, $dim, ntg_bin, ntg_bin_value)
+make_image(image${dim}d_u8, $dim, ntg_int_u8, ntg_int_u8_value)
+make_image(image${dim}d_u32, $dim, ntg_int_u32, ntg_int_u32_value)
+make_image(image${dim}d_s8, $dim, ntg_int_s8, ntg_int_s8_value)
+make_image(image${dim}d_s32, $dim, ntg_int_s32, ntg_int_s32_value)
+make_image(image${dim}d_float, $dim, ntg_float, ntg_float_value)
EOF
## Morpho algorithms
MODULES="$MODULES morpho${dim}d"
Index: tools/swilena/meta/swilena_ntg.i
--- tools/swilena/meta/swilena_ntg.i Sun, 28 Sep 2003 22:01:27 +0200 burrus_n (oln/s/33_swilena_nt 1.5 640)
+++ tools/swilena/meta/swilena_ntg.i Thu, 09 Oct 2003 15:38:43 +0200 burrus_n (oln/s/33_swilena_nt 1.5 640)
@@ -3,6 +3,9 @@
/***** Generic class declaration for scalars ******/
+
+/* Predecls */
+
%define decl_scalar_class(Ns, Name, ValueType)
template<unsigned nbits, typename behavior>
class Name
@@ -18,23 +21,23 @@
{ *self = Ns::Name<nbits, behavior>(x); }
#if defined(SWIGPYTHON) || defined(SWIGRUBY)
- Ns::Name<nbits, behavior> operator+ (const Ns::Name<nbits, behavior>& other) const { return (*self) + other; }
- Ns::Name<nbits, behavior> operator- (const Ns::Name<nbits, behavior>& other) const { return (*self) - other; }
- Ns::Name<nbits, behavior> operator* (const Ns::Name<nbits, behavior>& other) const { return (*self) * other; }
- Ns::Name<nbits, behavior> operator/ (const Ns::Name<nbits, behavior>& other) const { return (*self) / other; }
- Ns::Name<nbits, behavior> operator+ (ValueType other) const { return (*self) + other; }
- Ns::Name<nbits, behavior> operator- (ValueType other) const { return (*self) - other; }
- Ns::Name<nbits, behavior> operator* (ValueType other) const { return (*self) * other; }
- Ns::Name<nbits, behavior> operator/ (ValueType other) const { return (*self) / other; }
+ ValueType operator+ (const Ns::Name<nbits, behavior>& other) const { return (*self) + other; }
+ ValueType operator- (const Ns::Name<nbits, behavior>& other) const { return (*self) - other; }
+ ValueType operator* (const Ns::Name<nbits, behavior>& other) const { return (*self) * other; }
+ ValueType operator/ (const Ns::Name<nbits, behavior>& other) const { return (*self) / other; }
+ ValueType operator+ (ValueType other) const { return (*self) + other; }
+ ValueType operator- (ValueType other) const { return (*self) - other; }
+ ValueType operator* (ValueType other) const { return (*self) * other; }
+ ValueType operator/ (ValueType other) const { return (*self) / other; }
#else
- Ns::Name<nbits, behavior> add (const Ns::Name<nbits, behavior>& other) const { return (*self) + other; }
- Ns::Name<nbits, behavior> sub (const Ns::Name<nbits, behavior>& other) const { return (*self) - other; }
- Ns::Name<nbits, behavior> mul (const Ns::Name<nbits, behavior>& other) const { return (*self) * other; }
- Ns::Name<nbits, behavior> div (const Ns::Name<nbits, behavior>& other) const { return (*self) / other; }
- Ns::Name<nbits, behavior> add (ValueType other) const { return (*self) + other; }
- Ns::Name<nbits, behavior> sub (ValueType other) const { return (*self) - other; }
- Ns::Name<nbits, behavior> mul (ValueType other) const { return (*self) * other; }
- Ns::Name<nbits, behavior> div (ValueType other) const { return (*self) / other; }
+ ValueType add (const Ns::Name<nbits, behavior>& other) const { return (*self) + other; }
+ ValueType sub (const Ns::Name<nbits, behavior>& other) const { return (*self) - other; }
+ ValueType mul (const Ns::Name<nbits, behavior>& other) const { return (*self) * other; }
+ ValueType div (const Ns::Name<nbits, behavior>& other) const { return (*self) / other; }
+ ValueType add (ValueType other) const { return (*self) + other; }
+ ValueType sub (ValueType other) const { return (*self) - other; }
+ ValueType mul (ValueType other) const { return (*self) * other; }
+ ValueType div (ValueType other) const { return (*self) / other; }
#endif
#if defined(SWIGPYTHON)
@@ -110,12 +113,12 @@
{ *self = Ns::Name(x); }
#if defined(SWIGPYTHON)
- Ns::Name operator| (const Ns::Name& other) const { return (*self) | other; }
- Ns::Name operator| (ValueType other) const { return (*self) | other; }
- Ns::Name operator& (const Ns::Name& other) const { return (*self) & other; }
- Ns::Name operator& (ValueType other) const { return (*self) & other; }
- Ns::Name operator^ (const Ns::Name& other) const { return (*self) ^ other; }
- Ns::Name operator^ (ValueType other) const { return (*self) ^ other; }
+ ValueType operator| (const Ns::Name& other) const { return (*self) | other; }
+ ValueType operator| (ValueType other) const { return (*self) | other; }
+ ValueType operator& (const Ns::Name& other) const { return (*self) & other; }
+ ValueType operator& (ValueType other) const { return (*self) & other; }
+ ValueType operator^ (const Ns::Name& other) const { return (*self) ^ other; }
+ ValueType operator^ (ValueType other) const { return (*self) ^ other; }
Ns::Name& operator|= (const Ns::Name& other) { return (*self) |= other; }
Ns::Name& operator|= (ValueType other) { return (*self) |= other; }
Ns::Name& operator&= (const Ns::Name& other) { return (*self) &= other; }
@@ -129,12 +132,12 @@
bool operator== (ValueType other) const { return (*self) == other; }
bool operator!= (ValueType other) const { return (*self) != other; }
#else
- Ns::Name lor (const Ns::Name& other) const { return (*self) | other; }
- Ns::Name lor (ValueType other) const { return (*self) | other; }
- Ns::Name land (const Ns::Name& other) const { return (*self) & other; }
- Ns::Name land (ValueType other) const { return (*self) & other; }
- Ns::Name lxor (const Ns::Name& other) const { return (*self) ^ other; }
- Ns::Name lxor (ValueType other) const { return (*self) ^ other; }
+ ValueType lor (const Ns::Name& other) const { return (*self) | other; }
+ ValueType lor (ValueType other) const { return (*self) | other; }
+ ValueType land (const Ns::Name& other) const { return (*self) & other; }
+ ValueType land (ValueType other) const { return (*self) & other; }
+ ValueType lxor (const Ns::Name& other) const { return (*self) ^ other; }
+ ValueType lxor (ValueType other) const { return (*self) ^ other; }
Ns::Name& ilor (const Ns::Name& other) { return (*self) |= other; }
Ns::Name& ilor (ValueType other) { return (*self) |= other; }
Ns::Name& iland (const Ns::Name& other) { return (*self) &= other; }
@@ -218,34 +221,36 @@
- if another module use ntg::int_u32, operations on it won't be
possible since this module won't recognize the type ntg::int_u32.
- - ntg::int_u<32, ntg::strict> or ntg_uint should be used
+ - ntg::int_u<32, ntg::strict> or ntg_int_u32 should be used
everywhere. ntg_uint is just a convenient macro.
*/
#define ntg_bin ntg::bin
+#define ntg_bin_value bool
-%template(uint) ntg::int_u< 32, ntg::strict >;
-#define ntg_uint ntg::int_u< 32, ntg::strict >
-
-%template(sint) ntg::int_s< 32, ntg::strict >;
-#define ntg_sint ntg::int_s< 32, ntg::strict >
+%template(int_u32) ntg::int_u< 32, ntg::strict >;
+#define ntg_int_u32 ntg::int_u< 32, ntg::strict >
+#define ntg_int_u32_value unsigned long
+
+%template(int_s32) ntg::int_s< 32, ntg::strict >;
+#define ntg_int_s32 ntg::int_s< 32, ntg::strict >
+#define ntg_int_s32_value long
+
+%template(int_u8) ntg::int_u< 8, ntg::strict >;
+#define ntg_int_u8 ntg::int_u< 8, ntg::strict >
+#define ntg_int_u8_value unsigned long
+
+%template(int_s8) ntg::int_s< 8, ntg::strict >;
+#define ntg_int_s8 ntg::int_s< 8, ntg::strict >
+#define ntg_int_s8_value long
#define ntg_float ntg::float_d
+#define ntg_float_value ntg_float
%template(cplx_rect) ntg::cplx< ntg::rect, ntg_float >;
#define ntg_cplx_rect ntg::cplx< ntg::rect, ntg_float >
+#define ntg_cplx_rect_value ntg_cplx_rect
%template(cplx_polar) ntg::cplx< ntg::polar, ntg_float >;
#define ntg_cplx_polar ntg::cplx< ntg::polar, ntg_float >
-
-#if defined(SWIGPYTHON)
-%typemap(in) ntg_uint {
- $1 = ntg::int_u<32, ntg::strict>(PyLong_AsLong($input));
-}
-%typemap(in) ntg_sint {
- $1 = ntg::int_s<32, ntg::strict>(PyLong_AsLong($input));
-}
-%typemap(in) ntg_bin {
- $1 = ntg::bin(PyInt_AsLong($input));
-}
-#endif
+#define ntg_cplx_polar_value ntg_cplx_polar
Index: tools/swilena/meta/swilena_image.i
--- tools/swilena/meta/swilena_image.i Sun, 28 Sep 2003 22:01:27 +0200 burrus_n (oln/s/36_swilena_im 1.6 640)
+++ tools/swilena/meta/swilena_image.i Thu, 09 Oct 2003 13:21:32 +0200 burrus_n (oln/s/36_swilena_im 1.6 640)
@@ -1,18 +1,59 @@
// -*- C++ -*-
-/*----------------------.
-| oln::image structures |
-`----------------------*/
+%define decl_image(Dim)
+%include swilena_describe.i
+%include swilena_core.i
+
+%import swilena_imagesize ## Dim ## d.i
+%import swilena_point ## Dim ## d.i
+
+#if Dim == 1
+%{
+#include <oln/basics1d.hh>
+%}
+#elif Dim == 2
+%{
+#include <oln/basics2d.hh>
+%}
+#elif Dim == 3
+%{
+#include <oln/basics3d.hh>
+%}
+#endif
+
+namespace oln
+{
+ template<typename T>
+ struct image ## Dim ## d;
-%define image_methods(T, Val, Dim)
+ namespace io {
+ namespace internal {
+ struct anything {
+ anything();
+ anything(const anything& rhs);
+ };
+ }
+ ::oln::io::internal::anything load(const char*);
+ }
+}
+%enddef
+%define make_image(Name, Dim, T, ValueType)
+#define I image ## Dim ## d < T >
+
+namespace oln
+{
+
+ template <>
+ struct image ## Dim ## d < T >
+ {
// default constructor
- T();
- T(const image ## Dim ## d_size&);
- T(T& other);
+ I();
+ I(const image ## Dim ## d_size&);
+ I(const oln::io::internal::anything& any);
// operators
- T clone() const;
+ I clone() const;
void clear();
@@ -23,76 +64,77 @@
bool hold(const point ## Dim ## d&) const;
%extend {
-#if defined(SWIGPYTHON) || defined(SWIGRUBY)
- Val __getitem__(const point ## Dim ## d& p)
+
+#if defined SWIGPYTHON || defined SWIGRUBY
+ ValueType __getitem__(const point ## Dim ## d& p)
{ return (*self)[p]; }
- T& __setitem__(const point ## Dim ## d& p, Val v)
+ I& __setitem__(const point ## Dim ## d& p, ValueType v)
{ (*self)[p] = v; return *self; }
#else
- Val at(const point ## Dim ## d& p)
+ ValueType at(const point ## Dim ## d& p)
{ return (*self)[p]; }
- T& set(const point ## Dim ## d& p, Val v)
+ I& set(const point ## Dim ## d& p, ValueType v)
{ (*self)[p] = v; return *self; }
- Val& ref(const point ## Dim ## d& p)
+ T& ref(const point ## Dim ## d& p)
{ return (*self)[p]; }
#endif
}
- EXTEND_DESCRIBE(T)
+ EXTEND_DESCRIBE(I)
#if Dim == 1
- T(coord, coord border = 2);
+ I(coord, coord border = 2);
+
+ T& operator()(coord);
- Val& operator()(coord);
%extend {
-#if defined(SWIGRUBY)
- Val __getitem__(coord x)
+#if defined SWIGRUBY
+ ValueType __getitem__(coord x)
{ return (*self)(x); }
- T __setitem__(coord x, Val v)
+ I __setitem__(coord x, ValueType v)
{ (*self)(x) = v; return *self; }
#else
- Val at(coord x) { return (*self)(x); }
- T& set(coord x, Val v) { (*self)(x) = v; return *self; }
- Val& ref(coord x) { return (*self)(x); }
+ ValueType at(coord x) { return (*self)(x); }
+ I& set(coord x, ValueType v) { (*self)(x) = v; return *self; }
+ T& ref(coord x) { return (*self)(x); }
#endif
}
#elif Dim == 2
- T(coord, coord, coord border = 2);
+ I(coord, coord, coord border = 2);
+
+ T& operator()(coord, coord);
- Val& operator()(coord, coord);
%extend {
-#if defined(SWIGRUBY)
- Val __getitem__(coord x, coord y)
+#if defined SWIGRUBY
+ ValueType __getitem__(coord x, coord y)
{ return (*self)(x, y); }
- T __setitem__(coord x, coord y, Val v)
+ I __setitem__(coord x, coord y, ValueType v)
{ (*self)(x, y) = v; return *self; }
#else
- Val at(coord x, coord y)
- { return (*self)(x, y); }
- T& set(coord x, coord y, Val v)
- { (*self)(x, y) = v; return *self; }
- Val& ref(coord x, coord y)
- { return (*self)(x, y); }
+ ValueType at(coord x, coord y) { return (*self)(x, y); }
+ I& set(coord x, coord y, ValueType v) { (*self)(x, y) = v; return *self; }
+ T& ref(coord x, coord y) { return (*self)(x, y); }
#endif
}
#elif Dim == 3
- T(coord, coord, coord, coord border = 3);
+ I(coord, coord, coord, coord border = 3);
+
+ T& operator()(coord, coord, coord);
- Val& operator()(coord, coord, coord);
%extend {
-#if defined(SWIGRUBY)
- Val __getitem__(coord x, coord y, coord z)
+#if defined SWIGRUBY
+ ValueType __getitem__(coord x, coord y, coord z)
{ return (*self)(x, y, z); }
- T __setitem__(coord x, coord y, coord z, Val v)
+ I __setitem__(coord x, coord y, coord z, ValueType v)
{ (*self)(x, y, z) = v; return *self; }
#else
- Val at(coord x, coord y, coord z)
+ ValueType at(coord x, coord y, coord z)
{ return (*self)(x, y, z); }
- T& set(coord x, coord y, coord z, Val v)
+ I& set(coord x, coord y, coord z, ValueType v)
{ (*self)(x, y, z) = v; return *self; }
- Val& ref(coord x, coord y, coord z)
+ T& ref(coord x, coord y, coord z)
{ return (*self)(x, y, z); }
#endif
}
@@ -108,23 +150,6 @@
coord nslices() const;
#endif
-// border methods
-
-%extend
-{
- // FIXME: borders are in image.
-// void border_set_width(coord new_border, bool copy_border = false)
-// { oln::border::set_width(*self, new_border, copy_border); }
-// void border_adapt_width(coord new_border, bool copy_border = false)
-// { oln::border::adapt_width(*self, new_border, copy_border); }
-// void border_adapt_copy(coord min_border)
-// { oln::border::adapt_copy(*self, min_border); }
-// void border_adapt_mirror(coord min_border)
-// { oln::border::adapt_mirror(*self, min_border); }
-// void border_adapt_assign(coord min_border, Val v)
-// { oln::border::adapt_assign(*self, min_border, v); }
-}
-
// image I/O
#if Dim == 2
@@ -137,41 +162,10 @@
}
#endif
-%enddef
-
-%define decl_image(Dim)
-
-%include swilena_describe.i
-%include swilena_core.i
-
-%import swilena_imagesize ## Dim ## d.i
-%import swilena_point ## Dim ## d.i
-
-#if Dim == 1
-%{
-#include <oln/basics1d.hh>
-%}
-#elif Dim == 2
-%{
-#include <oln/basics2d.hh>
-%}
-#elif Dim == 3
-%{
-#include <oln/basics3d.hh>
-%}
-#endif
-
-namespace oln
-{
- template<typename T>
- struct image ## Dim ## d
- {
- image_methods(image ## Dim ## d<T>, T, Dim)
};
}
-%enddef
+%template(Name) oln::image ## Dim ## d< T >;
-%define make_image(name, Dim, T)
-%template(name) oln::image ## Dim ## d< T >;
+#undef I
%enddef
Index: tools/swilena/python/tests/simple1.py
--- tools/swilena/python/tests/simple1.py Sun, 28 Sep 2003 22:01:27 +0200 burrus_n (oln/v/16_simple1.py 1.3 700)
+++ tools/swilena/python/tests/simple1.py Thu, 09 Oct 2003 15:40:22 +0200 burrus_n (oln/v/16_simple1.py 1.3 700)
@@ -7,7 +7,7 @@
imgdir = os.environ['IMGDIR']
-lena = image2d_uint()
+lena = image2d_u8()
lena.load(imgdir + "/lena.pgm")
# FIXME: uncomment when ready
#assert(lena.has_impl())
@@ -15,5 +15,5 @@
lena.set(5, 5, 51)
lena.ref(6, 6).value(42)
-assert(lena.at(5, 5).value() == 51)
-assert(lena.at(6, 6).value() == 42)
+assert(lena.at(5, 5) == 51)
+assert(lena.at(6, 6) == 42)
Index: tools/swilena/ruby/tests/simple1.rb
--- tools/swilena/ruby/tests/simple1.rb Sun, 28 Sep 2003 22:01:27 +0200 burrus_n (oln/v/19_simple1.rb 1.3 700)
+++ tools/swilena/ruby/tests/simple1.rb Thu, 09 Oct 2003 16:17:57 +0200 burrus_n (oln/v/19_simple1.rb 1.3 700)
@@ -11,13 +11,12 @@
imgdir = ENV["IMGDIR"]
-lena = Image2d_uint.new
-lena.load(imgdir + "/lena.pgm")
+lena = Image2d_u8.new(load(imgdir + "/lena.pgm"))
# FIXME: uncomment when ready
#exit 1 unless lena.has_impl()
-lena[5, 5] = Uint.new(51)
-lena[6, 6] = Uint.new(42)
+lena[5, 5] = 51
+lena[6, 6] = 42
-exit 1 unless lena[5, 5].value() == 51
-exit 1 unless lena[6, 6].value() == 42
+exit 1 unless lena[5, 5] == 51
+exit 1 unless lena[6, 6] == 42
Index: tools/swilena/doc/examples/ruby/simple.rb
--- tools/swilena/doc/examples/ruby/simple.rb Sun, 28 Sep 2003 22:01:27 +0200 burrus_n (oln/v/22_simple.rb 1.3 600)
+++ tools/swilena/doc/examples/ruby/simple.rb Thu, 09 Oct 2003 16:18:52 +0200 burrus_n (oln/v/22_simple.rb 1.3 600)
@@ -15,11 +15,11 @@
display.tmpdir = "/tmp/swilena"
display.display_command = "display %{image_file}"
-ima = Image2d_uint.new(5,5)
+ima = Image2d_u8.new(5,5)
for i in 0..5 do
for j in 0..5 do
- ima[i, j] = Uint.new(i + j)
+ ima[i, j] = i + j
end
end
Index: tools/swilena/doc/examples/python/simple.py
--- tools/swilena/doc/examples/python/simple.py Sun, 28 Sep 2003 22:01:27 +0200 burrus_n (oln/v/23_simple.py 1.3 600)
+++ tools/swilena/doc/examples/python/simple.py Thu, 09 Oct 2003 15:42:05 +0200 burrus_n (oln/v/23_simple.py 1.3 600)
@@ -10,8 +10,8 @@
swilena_display.tmpdir = "/tmp/swilena"
swilena_display.display_command = "xv %{image_file}"
-ima = image2d_uint(5,5)
-print ima.at(5,5).value()
+ima = image2d_u8(5,5)
+print ima.at(5,5)
ima.set(2, 2, 2)
print ima
@@ -20,7 +20,7 @@
p.value(3)
print ima
-lena = image2d_uint();
+lena = image2d_u8();
lena.load("lena.pgm")
display_image (ima, "lena")
Index: tools/swilena/generate_morpho_instantiations.py
--- tools/swilena/generate_morpho_instantiations.py Sat, 27 Sep 2003 19:02:23 +0200 burrus_n (oln/v/24_generate_m 1.1 700)
+++ tools/swilena/generate_morpho_instantiations.py Thu, 09 Oct 2003 14:22:05 +0200 burrus_n (oln/v/24_generate_m 1.1 700)
@@ -38,7 +38,10 @@
def write_algorithms():
# Algorithms with all types and all dims
for dim in range(1, 4):
- for type in [ "ntg_bin", "ntg_uint", "ntg_sint", "ntg_float" ]:
+ for type in [ "ntg_bin",
+ "ntg_int_u8", "ntg_int_u32",
+ "ntg_int_s8", "ntg_int_s32",
+ "ntg_float" ]:
img_type = "::oln::image%(dim)sd< %(type)s >" % vars()
win_type = "::oln::window%(dim)sd" % vars()
neighb_type = "::oln::neighborhood%(dim)sd" % vars()
@@ -86,8 +89,8 @@
instantiate(dim, "hit_or_miss_closing_bg", img_type, img_type, win_type, win_type)
instantiate(dim, "fast_hit_or_miss_closing_bg", img_type, img_type, win_type, win_type)
- # FIXME: these algorithms do not work with binary types
- if type != "ntg_bin" and type != "ntg_float":
+ # FIXME: these algorithms do not work with float neither binary types
+ if type != "ntg_bin":
instantiate(dim, "beucher_gradient", img_type, img_type, win_type)
instantiate(dim, "fast_beucher_gradient", img_type, img_type, win_type)
@@ -109,10 +112,10 @@
instantiate(dim, "top_hat_contrast_op", img_type, img_type, win_type)
instantiate(dim, "fast_top_hat_contrast_op", img_type, img_type, win_type)
- # FIXME: watershed only works with ntg_uint
- if type == "ntg_uint":
+ # FIXME: watershed only works with ntg_int_u8
+ if type == "ntg_int_u32":
# Watershed
- img_ret_type = "::oln::image%(dim)sd< ntg_uint >" % vars()
+ img_ret_type = "::oln::image%(dim)sd< ntg_int_u32 >" % vars()
instantiate(dim, "watershed_seg", img_ret_type, img_type, neighb_type)
instantiate(dim, "watershed_con", img_ret_type, img_type, neighb_type)
instantiate(dim, "watershed_seg_or", img_type, img_type, img_ret_type, neighb_type)
1
0
Faudrait demander au bocal de nous envoyer un gars qui doit faire un
TIG pour réecrire arith un de ces 4 ...
Index: integre/ChangeLog
from Nicolas Burrus <burrus_n(a)lrde.epita.fr>
* ntg/core/internal/global_ops.hh: Import min and max into
namespace ntg.
Index: olena/ChangeLog
from Nicolas Burrus <burrus_n(a)lrde.epita.fr>
* oln/arith/internal/opdecls.hh: Support builtin types. Document.
* oln/arith/ops.hh: Support builtin types.
* oln/utils/histogram.hh: Support builtin types.
* oln/convert/nrgbhsl.hh: Use ntg::{min,max} instead of
std::{min,max}.
* oln/core/box.hxx: Likewise.
* oln/morpho/reconstruction.hh: Likewise.
* oln/morpho/geodesic_dilation.hh: Force the output type of
arith::min. Use ntg::min instead of std::min.
* oln/morpho/geodesic_erosion.hh: Likewise with s/min/max/.
+2003-10-08 Nicolas Burrus <burrus_n(a)lrde.epita.fr>
+
* tests/morpho/tests/builtin_types: New test.
2003-09-27 Nicolas Burrus <burrus_n(a)lrde.epita.fr>
Index: olena/oln/arith/internal/opdecls.hh
--- olena/oln/arith/internal/opdecls.hh Thu, 07 Aug 2003 02:08:21 +0200 david (oln/b/22_opdecls.hh 1.13 640)
+++ olena/oln/arith/internal/opdecls.hh Wed, 08 Oct 2003 23:36:51 +0200 burrus_n (oln/b/22_opdecls.hh 1.14 640)
@@ -28,17 +28,33 @@
#ifndef OLENA_ARITH_INTERNAL_OPDECLS_HH
# define OLENA_ARITH_INTERNAL_OPDECLS_HH
-/*-------------------.
-| Binary functions. |
-`-------------------*/
+/*
+ These macros should be rewritten / split into real code to make
+ things clearer.
+
+ Operations are defined between two images and between one image and
+ one constant value (with the cst suffix).
+
+ The two main components are:
+
+ 1) Define functors for each operations, taking two values and
+ returning the result.
+
+ 2) Define front-end functions applying a functor on the whole image.
+ 3 versions are defined, leaving the possibility to specify the
+ return type automatically, manually or using a conversion (from
+ convert).
+*/
+
+/*------------------.
+| Binary functors. |
+`------------------*/
-/* For binary operators that takes rev_values<T> arguments
- and define ntg::internal::operator_##OPNAME##_traits. */
# define oln_arith_declare_binrecval_functor_(OPNAME, OPCODE) \
- template<class T1, class T2 = T1> \
- struct f_##OPNAME : std::binary_function<const ntg::value<T1>&, \
- const ntg::value<T2>&, \
- ntg_return_type(OPNAME, T1, T2) > \
+ template<class T1, class T2, class Ret> \
+ struct f_##OPNAME : std::binary_function<const T1&, \
+ const T2&, \
+ Ret> \
{ \
typedef f_##OPNAME self_type; \
typename self_type::result_type \
@@ -49,12 +65,12 @@
} \
} /* no ; */
-/* For binary operators that takes rev_values<T> arguments \
- and define ntg::internal::operator_##OPNAME##_traits. */ \
+// Functor used by operations between an image and a constant
+
# define oln_arith_declare_binrecvalcst_functor_(OPNAME, OPCODE_CST) \
- template<class T1, class T2 = T1> \
- struct f_##OPNAME##_cst : std::unary_function<const ntg::value<T1>&, \
- ntg_return_type(OPNAME, T1, T2) > \
+ template<class T1, class T2, class Ret> \
+ struct f_##OPNAME##_cst : std::unary_function<const T1&, \
+ Ret> \
{ \
typedef f_##OPNAME##_cst self_type; \
f_##OPNAME##_cst(T2 cst) : cst_(cst) {} \
@@ -73,7 +89,6 @@
oln_arith_declare_binrecval_functor_(OPNAME, OPCODE); \
oln_arith_declare_binrecvalcst_functor_(OPNAME, OPCODE_CST)
-
/* For binary functions that work on a single known datatype. */
# define oln_arith_declare_binfixedtype_functor_(OPNAME, OPCODE, TYPE) \
struct f_##OPNAME : std::binary_function< const TYPE&, const TYPE&, TYPE> \
@@ -106,83 +121,123 @@
oln_arith_declare_binfixedtype_functor_(NAME, CODE, TYPE); \
oln_arith_declare_binfixedtypecst_functor_(NAME, CODE_CST, TYPE)
+// Shortcuts
+#define default_functor_return_type_(OPNAME, I1, I2) \
+ typename f_##OPNAME<oln_value_type(I1), \
+ oln_value_type(I2), \
+ ntg_return_type(OPNAME, \
+ oln_value_type(I1), \
+ oln_value_type(I2))>::result_type
+
+#define default_functor_type_cst_(OPNAME, I1, T2) \
+ f_##OPNAME##_cst<oln_value_type(I1), \
+ T2, \
+ ntg_return_type(OPNAME, \
+ oln_value_type(I1), \
+ T2)>
+
+#define default_functor_return_type_cst_(OPNAME, I1, T2) \
+ typename default_functor_type_cst_(OPNAME, I1, T2)::result_type
+
+/*----------------------------.
+| Declare front-end functions |
+`----------------------------*/
+
# define oln_arith_declare_binop_procs_(OPNAME) \
+ /* \
+ FIXME: this is a workaround for an odd bug of icc and como \
+ http://www.lrde.epita.fr/cgi-bin/twiki/view/Know/MysteriousTemplateFunction… \
+ Remove this traits and use its content directly when this bug gets fixed. \
+ */ \
+ template <class I1, class I2> \
+ struct arith_return_type_proxy_##OPNAME##_ \
+ { \
+ typedef typename mute<I1, default_functor_return_type_(OPNAME, I1, I2)>::ret ret; \
+ }; \
+ \
/* Standard application of OPNAME */ \
template<class I1, class I2> inline \
- typename mute<I1, \
- typename f_##OPNAME<oln_value_type(I1),oln_value_type(I2)>::result_type>::ret \
+ typename arith_return_type_proxy_##OPNAME##_<I1, I2>::ret \
OPNAME(const abstract::image<I1>& input1, const abstract::image<I2>& input2) \
{ \
+ typedef oln_value_type(I1) T1; \
+ typedef oln_value_type(I2) T2; \
/* KLUGE: Build the functor, don't pass it as a parameter as in \
apply2<f_##OPNAME>(input1, input2) \
otherwise GCC 2.95.x will ICE. */ \
- return apply2(f_##OPNAME<oln_value_type(I1),oln_value_type(I2)>(), input1, input2); \
+ return apply2(f_##OPNAME<T1, \
+ T2, \
+ ntg_return_type(OPNAME, T1, T2)>(), \
+ input1, input2); \
} \
\
/* Same as above, plus conversion. */ \
template<class C, class B, class I1, class I2> inline \
typename mute<I1, \
- typename convoutput<C, B, \
- typename f_##OPNAME<oln_value_type(I1),oln_value_type(I2)>::result_type>::ret>::ret \
+ typename convoutput<C, B, default_functor_return_type_(OPNAME, I1, I2)>::ret>::ret \
OPNAME(const convert::abstract::conversion<C, B>& conv, \
const abstract::image<I1>& input1, const abstract::image<I2>& input2) \
{ \
+ typedef oln_value_type(I1) T1; \
+ typedef oln_value_type(I2) T2; \
return apply2(convert::compconv2(conv, \
- f_##OPNAME<oln_value_type(I1),oln_value_type(I2)>()), \
+ f_##OPNAME<T1, \
+ T2, \
+ ntg_return_type(OPNAME, T1, T2)>()), \
+ input1, input2); \
+ } \
+ \
+ /* Same as above, with inline conversion in the functor. */ \
+ template<class IRet, class I1, class I2> inline \
+ typename mute<I1, oln_value_type(IRet)>::ret \
+ OPNAME(const abstract::image<I1>& input1, const abstract::image<I2>& input2) \
+ { \
+ return apply2(f_##OPNAME<oln_value_type(I1), \
+ oln_value_type(I2), \
+ oln_value_type(IRet)>(), \
input1, input2); \
}
# define oln_arith_declare_binopcst_procs_(OPNAME) \
/* Apply OPNAME with a constant as second operand. */ \
+ \
+ /* FIXME: cf explications above */ \
+ template <class I, class T> \
+ struct arith_return_type_proxy_cst_##OPNAME##_ \
+ { \
+ typedef typename mute<I, default_functor_return_type_cst_(OPNAME, I, T)>::ret ret; \
+ }; \
+ \
template<class I, class T> inline \
- typename mute<I, \
- typename f_##OPNAME##_cst<oln_value_type(I), T>::result_type>::ret \
+ typename arith_return_type_proxy_cst_##OPNAME##_<I, T>::ret \
OPNAME##_cst(const abstract::image<I>& input, T val) \
{ \
- return apply(f_##OPNAME##_cst<oln_value_type(I),T>(val), input); \
+ typedef default_functor_type_cst_(OPNAME, I, T) functor_type; \
+ return apply(functor_type(val), input); \
} \
\
/* Same as above, plus conversion. */ \
template<class C, class B, class I, class T> inline \
typename mute<I, \
- typename convoutput<C, B, \
- typename f_##OPNAME##_cst<oln_value_type(I), T>::result_type>::ret>::ret \
- OPNAME##_cst(const convert::abstract::conversion<C, B>& conv, const abstract::image<I>& input, T val) \
+ typename convoutput<C, B, default_functor_return_type_cst_(OPNAME, I, T)>::ret>::ret \
+ OPNAME##_cst(const convert::abstract::conversion<C, B>& conv, \
+ const abstract::image<I>& input, T val) \
{ \
- return apply(convert::compconv1(conv, \
- f_##OPNAME##_cst<oln_value_type(I),T>(val)), \
- input); \
+ typedef default_functor_type_cst_(OPNAME, I, T) functor_type; \
+ return apply(convert::compconv1(conv, functor_type(val)), input); \
+ } \
+ \
+ template<class IRet, class I, class T> inline \
+ typename mute<I, oln_value_type(IRet)>::ret \
+ OPNAME##_cst(const abstract::image<I>& input, T val) \
+ { \
+ return apply(f_##OPNAME##_cst<oln_value_type(I), T, oln_value_type(IRet)>(val), input); \
}
# define oln_arith_declare_all_binop_procs_(OPNAME) \
oln_arith_declare_binop_procs_(OPNAME) \
oln_arith_declare_binopcst_procs_(OPNAME)
-
-/* Same as oln_arith_declare_binop_procs_, for functor parametred by
- a single type. */
-# define oln_arith_declare_semigeneric_binop_procs_(OPNAME) \
- /* Standard application of OPNAME */ \
- template<class I1, class I2> inline \
- typename mute<I1, \
- typename f_##OPNAME<oln_value_type(I1)>::result_type>::ret \
- OPNAME(const abstract::image<I1>& input1, const abstract::image<I2>& input2) \
- { \
- return apply2<f_##OPNAME>(input1, input2); \
- } \
- \
- /* Same as above, plus conversion. */ \
- template<class C, class B, class I1, class I2> inline \
- typename mute<I1, \
- typename convoutput<C, B, \
- typename f_##OPNAME<oln_value_type(I1)>::result_type>::ret>::ret \
- OPNAME(const convert::abstract::conversion<C, B>& conv, \
- const abstract::image<I1>& input1, const abstract::image<I2>& input2) \
- { \
- return apply2(convert::compconv2(conv, f_##OPNAME<oln_value_type(I1)>()), \
- input1, input2); \
- }
-
/* Same as oln_arith_declare_nongenericbinop_procs_ but for non template
functors. */
# define oln_arith_declare_nongenericbinop_procs_(OPNAME) \
@@ -221,7 +276,8 @@
typename mute<I, \
typename convoutput<C, B, \
typename f_##OPNAME##_cst::result_type>::ret>::ret \
- OPNAME##_cst(const convert::abstract::conversion<C, B>& conv, const abstract::image<I>& input, T val) \
+ OPNAME##_cst(const convert::abstract::conversion<C, B>& conv, \
+ const abstract::image<I>& input, T val) \
{ \
return apply(convert::compconv1(conv, f_##OPNAME##_cst(val)), \
input); \
@@ -233,7 +289,6 @@
oln_arith_declare_nongenericbinop_procs_(OPNAME) \
oln_arith_declare_nongenericbinopcst_procs_(OPNAME)
-
/*------------------.
| Unary functions. |
`------------------*/
@@ -285,5 +340,34 @@
return apply(convert::compconv2(conv, f_##OPNAME<oln_value_type(I)>()), input1); \
}
+// FIXME: this code sounds odd and isn't used anywhere.
+// It should be rewritten properly if we want to keep it.
+# if 0
+
+/* Same as oln_arith_declare_binop_procs_, for functor parametred by
+ a single type. */
+# define oln_arith_declare_semigeneric_binop_procs_(OPNAME) \
+ /* Standard application of OPNAME */ \
+ template<class I1, class I2> inline \
+ typename mute<I1, \
+ typename f_##OPNAME<oln_value_type(I1), oln_value_type(I1)>::result_type>::ret \
+ OPNAME(const abstract::image<I1>& input1, const abstract::image<I2>& input2) \
+ { \
+ return apply2<f_##OPNAME>(input1, input2); \
+ } \
+ \
+ /* Same as above, plus conversion. */ \
+ template<class C, class B, class I1, class I2> inline \
+ typename mute<I1, \
+ typename convoutput<C, B, \
+ typename f_##OPNAME<oln_value_type(I1)>::result_type>::ret>::ret \
+ OPNAME(const convert::abstract::conversion<C, B>& conv, \
+ const abstract::image<I1>& input1, const abstract::image<I2>& input2) \
+ { \
+ return apply2(convert::compconv2(conv, f_##OPNAME<oln_value_type(I1)>()), \
+ input1, input2); \
+ }
+
+# endif
-#endif // OLENA_ARITH_INTERNAL_OPDECLS_HH
+#endif // ! OLENA_ARITH_INTERNAL_OPDECLS_HH
Index: olena/oln/arith/ops.hh
--- olena/oln/arith/ops.hh Thu, 07 Aug 2003 02:08:21 +0200 david (oln/b/23_ops.hh 1.5.1.2.1.7 640)
+++ olena/oln/arith/ops.hh Wed, 08 Oct 2003 23:36:51 +0200 burrus_n (oln/b/23_ops.hh 1.5.1.2.1.8 640)
@@ -41,24 +41,24 @@
namespace arith {
oln_arith_declare_binrecval_functors_(plus,
- val1.exact() + val2.exact(),
- val.exact() + cst_);
+ val1 + val2,
+ val + cst_);
// need a cast for the case int_u - int_u
oln_arith_declare_binrecval_functors_(minus,
- val1.exact() - val2.exact(),
- val.exact() - cst_);
+ val1 - val2,
+ val - cst_);
oln_arith_declare_binrecval_functors_(times,
- val1.exact() * val2.exact(),
- val.exact() * cst_);
+ val1 * val2,
+ val * cst_);
oln_arith_declare_binrecval_functors_(div,
- val1.exact() / val2.exact(),
- val.exact() / cst_);
+ val1 / val2,
+ val / cst_);
oln_arith_declare_binrecval_functors_(min,
- min(val1.exact(), val2.exact()),
- min(val.exact(), cst_));
+ ntg::min(val1, val2),
+ ntg::min(val, cst_));
oln_arith_declare_binrecval_functors_(max,
- max(val1.exact(), val2.exact()),
- max(val.exact(), cst_));
+ ntg::max(val1, val2),
+ ntg::max(val, cst_));
oln_arith_declare_all_binop_procs_(plus)
oln_arith_declare_all_binop_procs_(minus)
Index: olena/oln/convert/nrgbhsl.hh
--- olena/oln/convert/nrgbhsl.hh Thu, 07 Aug 2003 02:08:21 +0200 david (oln/12_nrgbhsl.hh 1.16 640)
+++ olena/oln/convert/nrgbhsl.hh Wed, 08 Oct 2003 23:36:51 +0200 burrus_n (oln/12_nrgbhsl.hh 1.17 640)
@@ -63,8 +63,8 @@
vec<3, float> in = v.to_float();
vec<3, float> out;
- float max_in = std::max(in[nrgb_R], std::max(in[nrgb_B], in[nrgb_G]));
- float min_in = std::min(in[nrgb_R], std::min(in[nrgb_B], in[nrgb_G]));
+ float max_in = ntg::max(in[nrgb_R], std::max(in[nrgb_B], in[nrgb_G]));
+ float min_in = ntg::min(in[nrgb_R], std::min(in[nrgb_B], in[nrgb_G]));
float diff = max_in-min_in;
out[hsl_L] = (max_in + min_in) / 2;
Index: olena/oln/core/box.hxx
--- olena/oln/core/box.hxx Thu, 07 Aug 2003 02:08:21 +0200 david (oln/p/0_box.hxx 1.4.1.1.1.4 640)
+++ olena/oln/core/box.hxx Wed, 08 Oct 2003 23:36:51 +0200 burrus_n (oln/p/0_box.hxx 1.4.1.1.1.5 640)
@@ -64,7 +64,7 @@
{
for (unsigned i = 0; i < dim(); ++i)
{
- top_.nth(i) = std::max(top_.nth(i), p.nth(i));
+ top_.nth(i) = ntg::max(top_.nth(i), p.nth(i));
bottom_.nth(i) = std::min(bottom_.nth(i), p.nth(i));
mass_[i] += p.nth(i);
}
Index: olena/oln/morpho/geodesic_dilation.hh
--- olena/oln/morpho/geodesic_dilation.hh Thu, 07 Aug 2003 02:08:21 +0200 david (oln/37_geodesic_d 1.11.1.9 640)
+++ olena/oln/morpho/geodesic_dilation.hh Wed, 08 Oct 2003 23:36:51 +0200 burrus_n (oln/37_geodesic_d 1.11.1.10 640)
@@ -74,7 +74,9 @@
mlc::eq<I1::dim, N::dim>::ensure();
precondition(marker.size() == mask.size());
precondition(level::is_greater_or_equal(mask, marker));
- return arith::min(dilation(marker, convert::ng_to_cse(Ng)), mask);
+ return arith::min<oln_concrete_type(I1)>(dilation(marker,
+ convert::ng_to_cse(Ng)),
+ mask);
}
namespace sure {
@@ -116,7 +118,7 @@
marker.border_adapt_copy(Ng.delta());
oln_iter_type(I1) p(marker);
for_all (p)
- output[p] = min(morpho::max(marker, p, convert::ng_to_cse(Ng)), mask[p]);
+ output[p] = std::min(morpho::max(marker, p, convert::ng_to_cse(Ng)), mask[p]);
return output;
}
Index: olena/oln/morpho/geodesic_erosion.hh
--- olena/oln/morpho/geodesic_erosion.hh Thu, 07 Aug 2003 02:08:21 +0200 david (oln/36_geodesic_e 1.16 640)
+++ olena/oln/morpho/geodesic_erosion.hh Wed, 08 Oct 2003 23:36:51 +0200 burrus_n (oln/36_geodesic_e 1.17 640)
@@ -1,4 +1,4 @@
-// Copyright (C) 2001, 2002 EPITA Research and Development Laboratory
+// Copyright (C) 2001, 2002, 2003 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
@@ -70,10 +70,9 @@
mlc::eq<I1::dim, N::dim>::ensure();
precondition(marker.size() == mask.size());
precondition(level::is_greater_or_equal(marker, mask));
- return arith::max(erosion(marker, convert::ng_to_cse(Ng)), mask);
+ return arith::max<oln_concrete_type(I1)>(erosion(marker, convert::ng_to_cse(Ng)), mask);
}
-
namespace sure {
/*=processing simple_geodesic_erosion
* ns: morpho
@@ -112,7 +111,7 @@
marker.border_adapt_copy(Ng.delta());
oln_iter_type(I1) p(marker);
for_all (p)
- output[p] = max(morpho::min(marker, p, convert::ng_to_cse(Ng)), mask[p]);
+ output[p] = ntg::max(morpho::min(marker, p, convert::ng_to_cse(Ng)), mask[p]);
return output;
}
Index: olena/oln/morpho/reconstruction.hh
--- olena/oln/morpho/reconstruction.hh Thu, 07 Aug 2003 02:08:21 +0200 david (oln/35_reconstruc 1.13.1.10 640)
+++ olena/oln/morpho/reconstruction.hh Wed, 08 Oct 2003 23:36:51 +0200 burrus_n (oln/35_reconstruc 1.13.1.11 640)
@@ -137,9 +137,9 @@
oln_concrete_type(I1) work = output.clone();
work.border_adapt_copy(Ng.delta());
for_all (fwd_p)
- work[fwd_p] = min(morpho::max(work, fwd_p, se_plus), mask[fwd_p]);
+ work[fwd_p] = ntg::min(morpho::max(work, fwd_p, se_plus), mask[fwd_p]);
for_all (bkd_p)
- work[bkd_p] = min(morpho::max(work, bkd_p, se_minus), mask[bkd_p]);
+ work[bkd_p] = ntg::min(morpho::max(work, bkd_p, se_minus), mask[bkd_p]);
non_stability = !(level::is_equal(work, output));
output = work;
}
@@ -217,13 +217,13 @@
typename I1::fwd_iter_type fwd_p(output);
typename I1::bkd_iter_type bkd_p(output);
for_all (fwd_p)
- output[fwd_p] = std::min(morpho::max(output, fwd_p, Ng_plus),
+ output[fwd_p] = ntg::min(morpho::max(output, fwd_p, Ng_plus),
mask[fwd_p]);
std::queue<oln_point_type(I1) > fifo;
for_all (bkd_p)
{
- output[bkd_p] = std::min(morpho::max(output, bkd_p, Ng_minus),
+ output[bkd_p] = ntg::min(morpho::max(output, bkd_p, Ng_minus),
mask[bkd_p]);
if (internal::exist_init_dilation(bkd_p.cur(), output, mask, Ng_minus))
fifo.push(bkd_p);
@@ -238,7 +238,7 @@
{
if ((output[q] < output[p]) && (mask[q] != output[q]))
{
- output[q] = std::min(output[p], mask[q]);
+ output[q] = ntg::min(output[p], mask[q]);
fifo.push(q);
}
}
@@ -345,9 +345,9 @@
oln_concrete_type(I1) work = output.clone();
work.border_adapt_copy(Ng.delta());
for_all (fwd_p)
- work[fwd_p] = max(morpho::min(work, fwd_p, se_plus), mask[fwd_p]);
+ work[fwd_p] = ntg::max(morpho::min(work, fwd_p, se_plus), mask[fwd_p]);
for_all (bkd_p)
- work[bkd_p] = max(morpho::min(work, bkd_p, se_minus), mask[bkd_p]);
+ work[bkd_p] = ntg::max(morpho::min(work, bkd_p, se_minus), mask[bkd_p]);
non_stability = !(level::is_equal(work, output));
output = work;
}
@@ -423,13 +423,13 @@
typename I1::fwd_iter_type fwd_p(output);
typename I1::bkd_iter_type bkd_p(output);
for_all (fwd_p)
- output[fwd_p] = max(morpho::min(output, fwd_p, Ng_plus),
+ output[fwd_p] = ntg::max(morpho::min(output, fwd_p, Ng_plus),
mask[fwd_p]);
std::queue<oln_point_type(I1) > fifo;
for_all (bkd_p)
{
- output[bkd_p] = max(morpho::min(output, bkd_p, Ng_minus),
+ output[bkd_p] = ntg::max(morpho::min(output, bkd_p, Ng_minus),
mask[bkd_p]);
if (internal::exist_init_erosion(bkd_p.cur(), output, mask, Ng_minus))
fifo.push(bkd_p);
@@ -444,7 +444,7 @@
{
if ((output[q] > output[p]) && (mask[q] != output[q]))
{
- output[q] = max(output[p], mask[q]);
+ output[q] = ntg::max(output[p], mask[q]);
fifo.push(q);
}
}
Index: integre/ntg/core/internal/global_ops.hh
--- integre/ntg/core/internal/global_ops.hh Wed, 30 Jul 2003 18:49:16 +0200 burrus_n (oln/g/27_global_ops 1.11.1.13 640)
+++ integre/ntg/core/internal/global_ops.hh Wed, 08 Oct 2003 23:36:51 +0200 burrus_n (oln/g/27_global_ops 1.11.1.14 640)
@@ -46,6 +46,9 @@
// macros defs
# include <ntg/core/internal/global_ops_defs.hh>
+// min and max
+# include <algorithm>
+
namespace ntg
{
@@ -204,6 +207,11 @@
| Min/Max operators |
`------------------*/
+ /*
+ These operators are slighly different from standard library ones
+ since they can operate on values of 2 different types.
+ */
+
template <class T1, class T2> inline
ntg_return_type(min, T1, T2)
min (const T1& lhs, const T2& rhs)
@@ -222,6 +230,12 @@
} // end of internal.
+ // FIXME: those are needed to handle max and min between two builtin
+ // types. Maybe std::min and std::max should be extended to work
+ // with builtin types?
+ using internal::min;
+ using internal::max;
+
} // end of ntg.
#endif // ndef NTG_CORE_INTERNAL_GLOBAL_OPS_HH
Index: olena/oln/utils/histogram.hh
--- olena/oln/utils/histogram.hh Thu, 07 Aug 2003 02:37:23 +0200 burrus_n (oln/10_histogram. 1.6.1.12 640)
+++ olena/oln/utils/histogram.hh Wed, 08 Oct 2003 23:36:51 +0200 burrus_n (oln/10_histogram. 1.6.1.13 640)
@@ -53,7 +53,6 @@
{
private:
typedef typename ntg_is_a(T, ntg::non_vectorial)::ensure_type ensure_type;
-
public:
histogram() : values_(0)
@@ -61,6 +60,10 @@
unsigned size = unsigned(ntg_max_val(T)
- ntg_min_val(T)
+ ntg_unit_val(T));
+ // FIXME: what if T is an unsigned int?
+ // This should be checked more strictly somewhere.
+ // size = max + 1 = 0
+ precondition(size > 0);
values_ = new U[size];
for (unsigned i = 0; i < size; ++i)
values_[i] = 0;
@@ -78,7 +81,7 @@
U&
operator[](const T& i)
{
- return values_[unsigned(i.val() - ntg_min_val(T))];
+ return values_[unsigned(i - ntg_min_val(T))];
}
friend T min<T, U>(const histogram<T, U>& hist);
@@ -91,7 +94,7 @@
oln_iter_type(I) p(img);
for_all (p)
- values_[unsigned(img[p].val())]++;
+ values_[unsigned(img[p])]++;
}
protected:
@@ -162,7 +165,7 @@
U&
operator[](const T& i)
{
- unsigned idx = unsigned(i.val() - ntg_min_val(T));
+ unsigned idx = unsigned(i - ntg_min_val(T));
adjust(idx);
return this->values_[idx];
}
@@ -210,7 +213,7 @@
U&
operator[](const T& i)
{
- unsigned idx = unsigned(i.val() - ntg_min_val(T));
+ unsigned idx = unsigned(i - ntg_min_val(T));
adjust(idx);
return this->values_[idx];
}
@@ -334,7 +337,7 @@
// level
oln_iter_type(I) p(im);
for_all(p)
- *(ptr[unsigned(im[p].val())]++) = p;
+ *(ptr[unsigned(im[p])]++) = p;
}
} // end of namespace utils
Index: olena/tests/morpho/tests/builtin_types
--- olena/tests/morpho/tests/builtin_types Wed, 08 Oct 2003 11:15:11 +0200 burrus_n (oln/v/30_builtin_ty 1.1 640)
+++ olena/tests/morpho/tests/builtin_types Wed, 08 Oct 2003 23:36:51 +0200 burrus_n (oln/v/30_builtin_ty 1.2 640)
@@ -1,8 +1,5 @@
// -*- c++ -*-
-// FIXME: this test should work before any serious release.
-// XFAIL
-
#include <oln/basics2d.hh>
#include <oln/morpho/opening.hh>
@@ -32,9 +29,9 @@
{
bool fail = false;
- image2d<unsigned> lena_uint = load(rdata("lena128.pgm"));
- image2d<signed> lena_sint = load(rdata("lena128.pgm"));
- image2d<unsigned> lena_open = morpho::fast::opening(lena_uint, win_c4p());
+ image2d<unsigned char> lena_uint = load(rdata("lena128.pgm"));
+ image2d<unsigned char> lena_open = morpho::fast::opening(lena_uint, win_c4p());
+
image2d<ntg::bin> minima_map(lena_uint.size());
image2d<int_u8> max_map(lena_uint.size());
1
0
J'ai ajouté ce test pour qu'on n'oublie pas que bcp d'algos sont
cassés avec des image<type_builtin>, notamment à cause de arith.
J'ai aussi ajouté
https://www.lrde.epita.fr/cgi-bin/twiki/view/Projects/BugMorphoAlgorithmsWi…
Index: olena/ChangeLog
from Nicolas Burrus <burrus_n(a)lrde.epita.fr>
* tests/morpho/tests/builtin_types: New test.
Index: olena/tests/morpho/tests/reconstruction
--- olena/tests/morpho/tests/reconstruction Mon, 28 Jul 2003 16:23:13 +0200 palma_g (oln/e/34_reconstruc 1.10 640)
+++ olena/tests/morpho/tests/reconstruction Wed, 08 Oct 2003 10:23:32 +0200 burrus_n (oln/e/34_reconstruc 1.10 640)
@@ -1,3 +1,5 @@
+// -*- c++ -*-
+
#include <oln/basics2d.hh>
#include <oln/morpho/opening.hh>
Index: olena/tests/morpho/tests/builtin_types
--- olena/tests/morpho/tests/builtin_types Wed, 08 Oct 2003 11:14:24 +0200 burrus_n ()
+++ olena/tests/morpho/tests/builtin_types Wed, 08 Oct 2003 11:04:03 +0200 burrus_n (oln/v/30_builtin_ty 644)
@@ -0,0 +1,128 @@
+// -*- c++ -*-
+
+// FIXME: this test should work before any serious release.
+// XFAIL
+
+#include <oln/basics2d.hh>
+
+#include <oln/morpho/opening.hh>
+#include <oln/morpho/geodesic_dilation.hh>
+#include <oln/morpho/geodesic_erosion.hh>
+#include <oln/morpho/reconstruction.hh>
+#include <oln/morpho/extrema.hh>
+#include <oln/level/fill.hh>
+#include <ntg/all.hh>
+#include "check.hh"
+#include "data.hh"
+
+using namespace oln;
+using namespace oln::level;
+using namespace ntg;
+
+#define OK_OR_FAIL \
+ std::cout << "OK" << std::endl; \
+ else \
+ { \
+ std::cout << "FAIL" << std::endl; \
+ fail = true; \
+ }
+
+bool
+check()
+{
+ bool fail = false;
+
+ image2d<unsigned> lena_uint = load(rdata("lena128.pgm"));
+ image2d<signed> lena_sint = load(rdata("lena128.pgm"));
+ image2d<unsigned> lena_open = morpho::fast::opening(lena_uint, win_c4p());
+ image2d<ntg::bin> minima_map(lena_uint.size());
+ image2d<int_u8> max_map(lena_uint.size());
+
+ level::fill (minima_map, false);
+ level::fill (max_map, 255);
+ minima_map(10,10) = true;
+ minima_map(100,100) = true;
+
+ // test regional minima
+ {
+ std::cout << "regional minima sequential ... " << std::flush;
+ if (level::is_equal(morpho::sure::regional_minima(lena_uint, neighb_c4()),
+ morpho::sequential::regional_minima(lena_uint, neighb_c4())))
+ OK_OR_FAIL;
+
+ std::cout << "regional minima hybrid ... " << std::flush;
+ if (level::is_equal(morpho::sure::regional_minima(lena_uint, neighb_c4()),
+ morpho::hybrid::regional_minima(lena_uint, neighb_c4())))
+ OK_OR_FAIL;
+ }
+
+ // test minima imposition
+ {
+ std::cout << "minima impos sequential ... " << std::flush;
+ if (level::is_equal(morpho::sure::minima_imposition(lena_uint,
+ minima_map, neighb_c4()),
+ morpho::sequential::minima_imposition(lena_uint,
+ minima_map,
+ neighb_c4())))
+ OK_OR_FAIL;
+
+ std::cout << "minima impos hybrid ... " << std::flush;
+ if (level::is_equal(morpho::sure::minima_imposition(lena_uint,
+ minima_map, neighb_c4()),
+ morpho::hybrid::minima_imposition(lena_uint,
+ minima_map,
+ neighb_c4())))
+ OK_OR_FAIL;
+ }
+
+ // test geodesic erosion and geodesic dilation
+ {
+ std::cout << "geodesic erosion ... " << std::flush;
+ if (level::is_equal(morpho::geodesic_erosion(lena_uint, lena_open, neighb_c4()),
+ morpho::sure::geodesic_erosion(lena_uint, lena_open,
+ neighb_c4())))
+ OK_OR_FAIL;
+
+ std::cout << "geodesic dilation ... " << std::flush;
+ if (level::is_equal(morpho::geodesic_dilation(lena_open, lena_uint, neighb_c4()),
+ morpho::sure::geodesic_dilation(lena_open,
+ lena_uint, neighb_c4())))
+ OK_OR_FAIL;
+ }
+
+
+
+ {
+ std::cout << "sequential G.R. erosion ... " << std::flush;
+ if (level::is_equal(morpho::sequential::geodesic_reconstruction_erosion
+ (max_map, lena_open, neighb_c4()),
+ morpho::sure::geodesic_reconstruction_erosion
+ (max_map, lena_open, neighb_c4())))
+ OK_OR_FAIL;
+
+ std::cout << "hybrid G.R. erosion ... " << std::flush;
+ if (level::is_equal(morpho::hybrid::geodesic_reconstruction_erosion
+ (max_map, lena_open, neighb_c4()),
+ morpho::sure::geodesic_reconstruction_erosion
+ (max_map, lena_open, neighb_c4())))
+ OK_OR_FAIL;
+ }
+
+ {
+ std::cout << "sequential G.R. dilation ... " << std::flush;
+ if (level::is_equal(morpho::sequential::geodesic_reconstruction_dilation
+ (lena_open, lena_uint, neighb_c4()),
+ morpho::sure::geodesic_reconstruction_dilation
+ (lena_open, lena_uint, neighb_c4())))
+ OK_OR_FAIL;
+
+ std::cout << "hybrid G.R. dilation ... " << std::flush;
+ if (level::is_equal(morpho::hybrid::geodesic_reconstruction_dilation
+ (lena_open, lena_uint, neighb_c4()),
+ morpho::sure::geodesic_reconstruction_dilation
+ (lena_open, lena_uint, neighb_c4())))
+ OK_OR_FAIL;
+ }
+
+ return fail;
+}
1
0
Scénario:
---------
Développement d'un algorithme pour Vaucanson.
Développement d'un petit programme utilisant Vaucanson.
ie: un "main.cc" avec des inclusions des headers de la
bibliothèque.
Problème:
---------
Qu'est-ce que c'est long, la compilation !
Sans option de compilation, sur un 2.5Ghz :
~/work_local/vaucanson/vgrep % g++ -c -I ../prcs-toy/include vgrep.cc
7.84s user 0.28s system 98% cpu 8.275 total
Solution:
---------
1. Le programme est compilé une première fois (c'est long mais
c'est principalement à cause de l'analyse/instanciation du code
de Vaucanson). Cette compilation se decompose en deux etapes :
a. compilation d'une unité d'instanciation main.unit.o
(la même chose que le code de main.cc mais ses fonctions
sont envoyees dans un namespace poubelle).
b. compilation de main.o mais seulement avec les interfaces
de vaucanson.
c. liaison de main.o et main.unit.o.
2. Je travaille sur le code de mon algorithme (pas sur Vaucanson).
Faire b. puis c. tant qu'il n'y a pas de problème de liaison,
sinon faire a. b. c.
Benchmark:
----------
~/work_local/vaucanson/vgrep % make
g++ -I ../prcs-toy/include -c -o vgrep.unit.o vgrep.unit.cc
g++ -o vgrep vgrep.o vgrep.unit.o
make 8.20s user 0.37s system 96% cpu 8.885 total
... modification dans vgrep.cc ...
~/work_local/vaucanson/vgrep % make
g++ -c -I ../prcs-toy/include vgrep.cc -DINTERFACE_ONLY
g++ -o vgrep vgrep.o vgrep.unit.o
make 1.64s user 0.17s system 92% cpu 1.956 total
... repetition tant qu'on n'utilise pas de nouveaux types/algorithmes
de Vaucanson ...
Conclusion:
-----------
Soit un gain de 5 (qui a priori doit etre encore plus fort sur
des machines plus lentes).
Le Makefile qui suit est une ebauche grossiere
mais l'idee est la.
Je propose la distribution d'un tel Makefile(.am) dans la tarball
de Vaucanson.
--- Makefile --------------------------------------------------------------
---------------------------------------------------------------------------
CXX=g++
CXXFLAGS=
CPPFLAGS=-I ../prcs-toy/include
MAKE=make
GREP=grep
all: vgrep
vgrep.unit.cc:
@ $(GREP) '#include' vgrep.cc > vgrep.unit.cc
@ echo 'namespace __instanciator_code {' >> vgrep.unit.cc
@ $(GREP) -v '#include' vgrep.cc >> vgrep.unit.cc
@ echo '}' >> vgrep.unit.cc
vgrep.o: vgrep.cc
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) vgrep.cc -DINTERFACE_ONLY
vgrep: vgrep.o vgrep.unit.o
@ $(CXX) -o vgrep vgrep.o vgrep.unit.o &> /tmp/log || \
(grep 'ld returned 1 exit status' /tmp/log &> /dev/null && \
rm vgrep.unit.cc && \
$(MAKE))
@ cat /tmp/log
1
0