https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add pixel in milena.
* tests/pixel.cc: New.
* mln/core/pixel.hh: New.
* mln/core/concept/genpixel.hh: New.
* mln/core/internal/force_exact.hh
(mln_internal_add_force_exact_): Remove.
(force_exact): New.
* mln/convert/to_dpoint.hh,
* mln/core/dpoints_piter.hh,
* mln/core/concept/genpoint.hh,
* mln/core/internal/coord_impl.hh,
* mln/core/internal/box_impl.hh: Update.
mln/convert/to_dpoint.hh | 2
mln/core/concept/genpixel.hh | 126 +++++++++++++++++++++++++++++++
mln/core/concept/genpoint.hh | 23 ++---
mln/core/dpoints_piter.hh | 2
mln/core/internal/box_impl.hh | 20 +---
mln/core/internal/coord_impl.hh | 49 ++++--------
mln/core/internal/force_exact.hh | 45 +++++++----
mln/core/pixel.hh | 158 +++++++++++++++++++++++++++++++++++++++
tests/pixel.cc | 61 +++++++++++++++
9 files changed, 415 insertions(+), 71 deletions(-)
Index: tests/pixel.cc
--- tests/pixel.cc (revision 0)
+++ tests/pixel.cc (revision 0)
@@ -0,0 +1,61 @@
+// 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/pixel.cc
+ *
+ * \brief Tests on mln::pixel.
+ */
+
+#include <mln/core/pixel.hh>
+#include <mln/core/image2d_b.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ typedef image2d_b<int> I;
+ I ima(3, 3);
+
+ {
+ pixel<I> pxl(ima);
+ pxl.site() = make::point2d(1, 1);
+ *pxl = 51;
+ mln_assertion(ima.at(1,1) = 51);
+ }
+
+ {
+ pixel<const I> pxl(ima);
+ pxl.site() = make::point2d(1, 1);
+ ima.at(1,1) = 51;
+ mln_assertion(*pxl = 51);
+
+ // hopefully the code below does not compile:
+ // *pxl = 0;
+ // assignment of read-only location
+ }
+}
Index: mln/convert/to_dpoint.hh
--- mln/convert/to_dpoint.hh (revision 1010)
+++ mln/convert/to_dpoint.hh (working copy)
@@ -52,7 +52,7 @@
template <typename P>
mln_dpoint(P) to_dpoint(const GenPoint<P>& p_)
{
- const P& p = p_.force_exact_();
+ const P& p = internal::force_exact<P>(p_);
mln_dpoint(P) tmp;
for (unsigned i = 0; i < P::dim; ++i)
tmp[i] = p[i];
Index: mln/core/pixel.hh
--- mln/core/pixel.hh (revision 0)
+++ mln/core/pixel.hh (revision 0)
@@ -0,0 +1,158 @@
+// 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_CORE_PIXEL_HH
+# define MLN_CORE_PIXEL_HH
+
+/*! \file mln/core/pixel.hh
+ *
+ * \brief Definition of the generic pixel class mln::pixel.
+ */
+
+# include <mln/core/concept/genpixel.hh>
+
+
+namespace mln
+{
+
+
+ template <typename I>
+ struct pixel_lvalue
+ {
+ typedef mln_lvalue(I) ret;
+ };
+
+ template <typename I>
+ struct pixel_lvalue< const I >
+ {
+ typedef mln_rvalue(I) ret;
+ };
+
+
+
+ /*! \brief Generic pixel class.
+ *
+ * The parameter is \c I the type of the image it belongs to.
+ */
+ template <typename I>
+ struct pixel : public Object< pixel<I> >,
+ public GenPixel< pixel<I> >
+ {
+ typedef mln_psite(I) psite;
+ typedef mln_value(I) value;
+
+ pixel(I& ima);
+ pixel(I& ima, const psite& p);
+
+ const I& image() const;
+
+ const psite& site() const;
+ psite& site();
+
+ mln_rvalue(I) operator*() const;
+ typename pixel_lvalue<I>::ret operator*();
+
+ const value* address() const;
+ value* address();
+
+ protected:
+
+ I& ima_;
+ psite p_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ pixel<I>::pixel(I& image)
+ : ima_(image)
+ {
+ }
+
+ template <typename I>
+ pixel<I>::pixel(I& image, const psite& p)
+ : ima_(image),
+ p_(p)
+ {
+ }
+
+ template <typename I>
+ const I&
+ pixel<I>::image() const
+ {
+ return ima_;
+ }
+
+ template <typename I>
+ const mln_psite(I)&
+ pixel<I>::site() const
+ {
+ return p_;
+ }
+
+ template <typename I>
+ mln_psite(I)&
+ pixel<I>::site()
+ {
+ return p_;
+ }
+
+ template <typename I>
+ mln_rvalue(I)
+ pixel<I>::operator*() const
+ {
+ return ima_(p_);
+ }
+
+ template <typename I>
+ typename pixel_lvalue<I>::ret
+ pixel<I>::operator*()
+ {
+ return ima_(p_);
+ }
+
+ template <typename I>
+ const mln_value(I)*
+ pixel<I>::address() const
+ {
+ return & ima_(p_);
+ }
+
+ template <typename I>
+ mln_value(I)*
+ pixel<I>::address()
+ {
+ return & ima_(p_);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_PIXEL_HH
Index: mln/core/dpoints_piter.hh
--- mln/core/dpoints_piter.hh (revision 1010)
+++ mln/core/dpoints_piter.hh (working copy)
@@ -112,7 +112,7 @@
dpoints_fwd_piter<D>::dpoints_fwd_piter(const Dps& dps,
const GenPoint<Pref>& p_ref)
: dps_(exact(dps).vec()),
- p_ref_(* p_ref.force_exact_().pointer())
+ p_ref_(* internal::force_exact<Pref>(p_ref).pointer())
{
invalidate();
}
Index: mln/core/concept/genpoint.hh
--- mln/core/concept/genpoint.hh (revision 1010)
+++ mln/core/concept/genpoint.hh (working copy)
@@ -77,8 +77,6 @@
coord operator[](unsigned i) const;
*/
- mln_internal_add_force_exact_(GenPoint<E>)
-
protected:
GenPoint();
@@ -210,8 +208,10 @@
std::ostream& operator<<(std::ostream& ostr, const GenPoint<P>&
p);
+
# ifndef MLN_INCLUDE_ONLY
+
template <typename E>
GenPoint<E>::GenPoint()
{
@@ -227,12 +227,13 @@
m2 = 0;
}
+
template <typename Pl, typename Pr>
bool operator=(const GenPoint<Pl>& lhs, const GenPoint<Pr>& rhs)
{
// FIXME: mlc::same_grid<Pl, Pr>::check();
- const Pl& lhs_ = lhs.force_exact_();
- const Pr& rhs_ = rhs.force_exact_();
+ const Pl& lhs_ = internal::force_exact<Pl>(lhs);
+ const Pr& rhs_ = internal::force_exact<Pr>(rhs);
mlc::same_point<Pl, Pr>::check();
for (unsigned i = 0; i < Pl::dim; ++i)
if (lhs_[i] != rhs_[i])
@@ -244,8 +245,8 @@
bool operator<(const GenPoint<Pl>& lhs, const GenPoint<Pr>&
rhs)
{
// FIXME: mlc::same_grid<Pl, Pr>::check();
- const Pl& lhs_ = lhs.force_exact_();
- const Pr& rhs_ = rhs.force_exact_();
+ const Pl& lhs_ = internal::force_exact<Pl>(lhs);
+ const Pr& rhs_ = internal::force_exact<Pr>(rhs);
for (unsigned i = 0; i < Pl::dim; ++i)
{
if (lhs_[i] = rhs_[i])
@@ -262,8 +263,8 @@
mlc::equal<mln_dpoint(Pl), mln_dpoint(Pr)>::check();
// FIXME: mlc::same_grid<Pl, Pr>::check();
mlc::same_coord<Pl, Pr>::check();
- const Pl& lhs_ = lhs.force_exact_();
- const Pr& rhs_ = rhs.force_exact_();
+ const Pl& lhs_ = internal::force_exact<Pl>(lhs);
+ const Pr& rhs_ = internal::force_exact<Pr>(rhs);
mln_dpoint(Pl) tmp;
for (unsigned i = 0; i < Pl::dim; ++i)
tmp[i] = lhs_[i] - rhs_[i];
@@ -275,7 +276,7 @@
mln_point(P)
operator+(const GenPoint<P>& lhs, const mln_dpoint(P)& rhs)
{
- const P& lhs_ = lhs.force_exact_();
+ const P& lhs_ = internal::force_exact<P>(lhs);
mln_point(P) tmp;
for (unsigned i = 0; i < P::dim; ++i)
tmp[i] = lhs_[i] + rhs[i];
@@ -286,7 +287,7 @@
mln_point(P)
operator-(const GenPoint<P>& lhs, const mln_dpoint(P)& rhs)
{
- const P& lhs_ = lhs.force_exact_();
+ const P& lhs_ = internal::force_exact<P>(lhs);
mln_point(P) tmp;
for (unsigned i = 0; i < P::dim; ++i)
tmp[i] = lhs_[i] - rhs[i];
@@ -296,7 +297,7 @@
template <typename P>
std::ostream& operator<<(std::ostream& ostr, const GenPoint<P>&
p)
{
- const P& p_ = p.force_exact_();
+ const P& p_ = internal::force_exact<P>(p);
ostr << '(';
for (unsigned i = 0; i < P::dim; ++i)
Index: mln/core/concept/genpixel.hh
--- mln/core/concept/genpixel.hh (revision 0)
+++ mln/core/concept/genpixel.hh (revision 0)
@@ -0,0 +1,126 @@
+// 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_CORE_CONCEPT_GENPIXEL_HH
+# define MLN_CORE_CONCEPT_GENPIXEL_HH
+
+/*! \file mln/core/concept/genpixel.hh
+ * \brief Definition of the concept of mln::Genpixel.
+ */
+
+# include <mln/core/concept/object.hh>
+
+# include <mln/core/macros.hh>
+# include <mln/core/contract.hh>
+# include <mln/core/internal/force_exact.hh>
+
+
+namespace mln
+{
+
+ // FIXME: \class GenPixel GenPixel.hh "mln/core/concept/doc/GenPixel.hh"
+
+ /*! \brief Base class for implementation classes that are pixels or that
+ * have the behavior of pixels.
+ *
+ * "GenPixel" is "Generalized Pixel" for short.
+ *
+ * \warning This class does \em not derive from mln::Object; it is
+ * for use as a parallel hierarchy.
+ *
+ * \see mln::doc::GenPixel for a complete documentation of this
+ * class contents.
+ */
+ template <typename E>
+ struct GenPixel
+ {
+
+ /*
+ typedef image; // not const!
+ typedef psite;
+ typedef rvalue;
+
+ const image& image() const;
+ const psite& psite() const; // FIXME ou cpy
+
+ rvalue operator*() const;
+
+ const value* address() const;
+ */
+
+ protected:
+ GenPixel();
+
+ };
+
+ /*! \brief Print a generalized pixel \p p into the output stream \p
+ * ostr.
+ *
+ * \param[in,out] ostr An output stream.
+ * \param[in] p A generalized pixel.
+ *
+ * \return The modified output stream \p ostr.
+ *
+ * \relates mln::GenPixel
+ */
+ template <typename P>
+ std::ostream& operator<<(std::ostream& ostr, const GenPixel<P>&
p);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename E>
+ GenPixel<E>::GenPixel()
+ {
+ // FIXME
+// int dim = E::dim;
+// mln_invariant(dim > 0);
+// dim = 0;
+// typedef mln_point(E) point;
+// typedef mln_dpoint(E) dpoint;
+// typedef mln_coord(E) coord;
+// const point* (E::*m1)() const = & E::pointer;
+// m1 = 0;
+// coord (E::*m2)(unsigned i) const = & E::operator[];
+// m2 = 0;
+ }
+
+
+ template <typename P>
+ std::ostream& operator<<(std::ostream& ostr, const GenPixel<P>&
pxl)
+ {
+ return ostr << pxl.psite() << '@' << & pxl.image();
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_CONCEPT_GENPIXEL_HH
Index: mln/core/internal/force_exact.hh
--- mln/core/internal/force_exact.hh (revision 1010)
+++ mln/core/internal/force_exact.hh (working copy)
@@ -30,11 +30,20 @@
/*! \file mln/core/internal/force_exact.hh
*
- * \brief Definition of a macro for internal use only.
+ * \brief Definition of a violent cast for internal use only.
+ *
+ * \internal
*/
-/*! \brief Macro to add a violent exact cast method.
+
+namespace mln
+{
+
+ namespace internal
+ {
+
+ /*! \brief Violent cast.
*
* \internal
*
@@ -45,18 +54,28 @@
*
* \see mln::exact
*/
-
-# define mln_internal_add_force_exact_(Type) \
- \
- E& force_exact_() const \
- { \
- static const E* exact_obj; \
- static const Type& exact_obj_ref = *exact_obj; \
- static const int exact_offset = \
- (const char*)(void*)(&exact_obj_ref) \
- - (const char*)(void*)( exact_obj); \
- return *(E*)((char*)(this) - exact_offset); \
+ template <typename E, typename T>
+ E& force_exact(const T& ref)
+ {
+ /*
+ static const E exact_obj;
+ static const Type& exact_obj_ref = exact_obj;
+ static const int exact_offset + (const char*)(void*)(&exact_obj_ref)
+ - (const char*)(void*)(&exact_obj);
+ return *(E*)((char*)(this_) - exact_offset);
+ */
+ static const E* exact_obj;
+ static const T& exact_obj_ref = *exact_obj;
+ static const int exact_offset + (const char*)(void*)(&exact_obj_ref)
+ - (const char*)(void*)( exact_obj);
+ return *(E*)((char*)(&ref) - exact_offset);
}
+ } // end of namespace mln::internal
+
+} // end of namespace mln
+
#endif // ! MLN_CORE_INTERNAL_FORCE_EXACT_HH
Index: mln/core/internal/coord_impl.hh
--- mln/core/internal/coord_impl.hh (revision 1010)
+++ mln/core/internal/coord_impl.hh (working copy)
@@ -44,13 +44,6 @@
namespace internal
{
- template <typename E>
- struct coord_impl_base_
- {
- mln_internal_add_force_exact_(coord_impl_base_<E>)
- };
-
-
// coord_impl
/*! \brief Implementation class to equip generalized points with
@@ -63,7 +56,6 @@
template <typename C, typename E>
struct coord_impl_<1, C, E>
- : coord_impl_base_<E>
{
C ind() const;
private:
@@ -73,7 +65,6 @@
template <typename C, typename E>
struct coord_impl_<2, C, E>
- : coord_impl_base_<E>
{
C row() const;
C col() const;
@@ -81,7 +72,6 @@
template <typename C, typename E>
struct coord_impl_<3, C, E>
- : coord_impl_base_<E>
{
C sli() const;
C row() const;
@@ -96,7 +86,6 @@
template <typename C, typename E>
struct mutable_coord_impl_<1, C, E>
- : coord_impl_base_<E>
{
C ind() const;
C& ind();
@@ -104,7 +93,6 @@
template <typename C, typename E>
struct mutable_coord_impl_<2, C, E>
- : coord_impl_base_<E>
{
C row() const;
C& row();
@@ -114,7 +102,6 @@
template <typename C, typename E>
struct mutable_coord_impl_<3, C, E>
- : coord_impl_base_<E>
{
C sli() const;
C& sli();
@@ -134,7 +121,7 @@
template <typename C, typename E>
C coord_impl_<1, C, E>::ind() const
{
- return this->force_exact_()[0];
+ return internal::force_exact<E>(*this)[0];
}
// 2
@@ -142,13 +129,13 @@
template <typename C, typename E>
C coord_impl_<2, C, E>::row() const
{
- return this->force_exact_()[0];
+ return internal::force_exact<E>(*this)[0];
}
template <typename C, typename E>
C coord_impl_<2, C, E>::col() const
{
- return this->force_exact_()[1];
+ return internal::force_exact<E>(*this)[1];
}
// 3
@@ -156,19 +143,19 @@
template <typename C, typename E>
C coord_impl_<3, C, E>::sli() const
{
- return this->force_exact_()[0];
+ return internal::force_exact<E>(*this)[0];
}
template <typename C, typename E>
C coord_impl_<3, C, E>::row() const
{
- return this->force_exact_()[1];
+ return internal::force_exact<E>(*this)[1];
}
template <typename C, typename E>
C coord_impl_<3, C, E>::col() const
{
- return this->force_exact_()[2];
+ return internal::force_exact<E>(*this)[2];
}
@@ -179,13 +166,13 @@
template <typename C, typename E>
C mutable_coord_impl_<1, C, E>::ind() const
{
- return this->force_exact_()[0];
+ return internal::force_exact<E>(*this)[0];
}
template <typename C, typename E>
C& mutable_coord_impl_<1, C, E>::ind()
{
- return this->force_exact_()[0];
+ return internal::force_exact<E>(*this)[0];
}
// 2
@@ -193,25 +180,25 @@
template <typename C, typename E>
C mutable_coord_impl_<2, C, E>::row() const
{
- return this->force_exact_()[0];
+ return internal::force_exact<E>(*this)[0];
}
template <typename C, typename E>
C& mutable_coord_impl_<2, C, E>::row()
{
- return this->force_exact_()[0];
+ return internal::force_exact<E>(*this)[0];
}
template <typename C, typename E>
C mutable_coord_impl_<2, C, E>::col() const
{
- return this->force_exact_()[1];
+ return internal::force_exact<E>(*this)[1];
}
template <typename C, typename E>
C& mutable_coord_impl_<2, C, E>::col()
{
- return this->force_exact_()[1];
+ return internal::force_exact<E>(*this)[1];
}
// 3
@@ -219,37 +206,37 @@
template <typename C, typename E>
C mutable_coord_impl_<3, C, E>::sli() const
{
- return this->force_exact_()[0];
+ return internal::force_exact<E>(*this)[0];
}
template <typename C, typename E>
C& mutable_coord_impl_<3, C, E>::sli()
{
- return this->force_exact_()[0];
+ return internal::force_exact<E>(*this)[0];
}
template <typename C, typename E>
C mutable_coord_impl_<3, C, E>::row() const
{
- return this->force_exact_()[1];
+ return internal::force_exact<E>(*this)[1];
}
template <typename C, typename E>
C& mutable_coord_impl_<3, C, E>::row()
{
- return this->force_exact_()[1];
+ return internal::force_exact<E>(*this)[1];
}
template <typename C, typename E>
C mutable_coord_impl_<3, C, E>::col() const
{
- return this->force_exact_()[2];
+ return internal::force_exact<E>(*this)[2];
}
template <typename C, typename E>
C& mutable_coord_impl_<3, C, E>::col()
{
- return this->force_exact_()[2];
+ return internal::force_exact<E>(*this)[2];
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/core/internal/box_impl.hh
--- mln/core/internal/box_impl.hh (revision 1010)
+++ mln/core/internal/box_impl.hh (working copy)
@@ -45,13 +45,6 @@
namespace internal
{
- template <typename E>
- struct box_impl_base_
- {
- mln_internal_add_force_exact_(box_impl_base_<E>)
- };
-
-
// box_impl
/*! \brief Implementation class to equip objects having a bounding
@@ -64,7 +57,6 @@
template <typename C, typename E> // FIXME: Add an extra param to replace
'unsigned'.
struct box_impl_<2, C, E>
- : box_impl_base_<E>
{
/// Give the number of rows.
unsigned nrows() const;
@@ -95,37 +87,37 @@
template <typename C, typename E>
unsigned box_impl_<2, C, E>::nrows() const
{
- return this->force_exact_().bbox().len(0);
+ return internal::force_exact<E>(*this).bbox().len(0);
}
template <typename C, typename E>
C box_impl_<2, C, E>::min_row() const
{
- return this->force_exact_().bbox().pmin()[0];
+ return internal::force_exact<E>(*this).bbox().pmin()[0];
}
template <typename C, typename E>
C box_impl_<2, C, E>::max_row() const
{
- return this->force_exact_().bbox().pmax()[0];
+ return internal::force_exact<E>(*this).bbox().pmax()[0];
}
template <typename C, typename E>
unsigned box_impl_<2, C, E>::ncols() const
{
- return this->force_exact_().bbox().len(1);
+ return internal::force_exact<E>(*this).bbox().len(1);
}
template <typename C, typename E>
C box_impl_<2, C, E>::min_col() const
{
- return this->force_exact_().bbox().pmin()[1];
+ return internal::force_exact<E>(*this).bbox().pmin()[1];
}
template <typename C, typename E>
C box_impl_<2, C, E>::max_col() const
{
- return this->force_exact_().bbox().pmax()[1];
+ return internal::force_exact<E>(*this).bbox().pmax()[1];
}
# endif // ! MLN_INCLUDE_ONLY