Index: ChangeLog from Damien Thivolle damien@lrde.epita.fr
* mlc/makefile.src: Add new files. * mlc/array: New. * mlc/array/nd.hh: New. * mlc/array/1d.hh: New. * mlc/array/2d.hh: New. * mlc/array/3d.hh: New. * mlc/array/all.hh: New. * mlc/array/1d.hxx: New. * mlc/array/2d.hxx: New. * mlc/array/objs.hh: New. * mlc/array/3d.hxx: New.
array/1d.hh | 294 +++++++++++++++++++++++++++++++++++++++++++++++++++ array/1d.hxx | 237 +++++++++++++++++++++++++++++++++++++++++ array/2d.hh | 326 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ array/2d.hxx | 283 +++++++++++++++++++++++++++++++++++++++++++++++++ array/3d.hh | 333 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ array/3d.hxx | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++ array/all.hh | 35 ++++++ array/nd.hh | 50 ++++++++ array/objs.hh | 78 +++++++++++++ makefile.src | 11 + 10 files changed, 1940 insertions(+)
Index: mlc/makefile.src --- mlc/makefile.src (revision 61) +++ mlc/makefile.src (working copy) @@ -5,11 +5,22 @@
MLC_DEP = \ any.hh \ + array/1d.hh \ + array/1d.hxx \ + array/2d.hh \ + array/2d.hxx \ + array/3d.hh \ + array/3d.hxx \ + array/all.hh \ + array/nd.hh \ + array/objs.hh \ bool.hh \ box.hh \ cmp.hh \ config/system.hh \ contract.hh \ + is_a.hh \ + properties.hh \ tracked_ptr.hh \ traits.hh \ types.hh Index: mlc/array/nd.hh --- mlc/array/nd.hh (revision 0) +++ mlc/array/nd.hh (revision 0) @@ -0,0 +1,50 @@ +// Copyright (C) 2001, 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 +// 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, 59 Temple Place - Suite 330, 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 METALIC_ARRAY_ND_HH +# define METALIC_ARRAY_ND_HH + + +namespace mlc +{ + + namespace internal + { + + // + // mlc::internal misc + // + //////////////////////////////////////// + + static const unsigned max_card_ = 4096; // 64 x 64 + static const unsigned unknown_ = max_card_ + 1; + + } // end of internal + +} // end of namespace mlc + +#endif // ! METALIC_ARRAY_ND_HH Index: mlc/array/1d.hh --- mlc/array/1d.hh (revision 0) +++ mlc/array/1d.hh (revision 0) @@ -0,0 +1,294 @@ +// Copyright (C) 2001, 2002, 2003, 2004 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, 59 Temple Place - Suite 330, 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 METALIC_ARRAY_1D_HH +# define METALIC_ARRAY_1D_HH + +# include <mlc/contract.hh> +# include <mlc/cmp.hh> +# include <mlc/array/objs.hh> +# include <ntg/basics.hh> +# include <iostream> + + +// impl +# include <mlc/array/1d.hxx> + +namespace mlc +{ + + template<class Info_, class T_> + struct array1d + { + typedef array1d self; + typedef T_ T; + typedef Info_ Info; + + + // + // Constructors + // + + array1d() + { + } + + array1d(T* ptr) + { + less<0, Info_::card>::ensure(); + less< Info_::card, internal::max_card_ >::ensure(); + for (unsigned i = 0; i < Info_::card; ++i) + buffer_[i] = *ptr++; + } + + // Copy + + array1d(const self& rhs) + { + for (unsigned i = 0; i < Info_::card; ++i) + buffer_[i] = rhs[i]; + } + self& operator=(const self& rhs) + { + for (unsigned i = 0; i < Info_::card; ++i) + buffer_[i] = rhs[i]; + return *this; + } + + + // Name + + static std::string + name() + { + return std::string("array1d< Info, ") + ntg_name(T) + " >"; + } + + + + // + // Operations on array + // + + // Normalize (absolute values -> relative values) + + array1d<Info_, ntg::float_s> + normalize() + { + array1d<Info_, ntg::float_s> tmp; + ntg::float_s sum = 0.f; + const ntg::float_s epsilon = 0.01f; // FIXME : epsilon should be global + unsigned i; + for (i = 0; i < Info_::card; ++i) + sum += this->buffer_[i]; + for (i = 0; i < Info_::card; ++i) + tmp[i] = this->buffer_[i] / sum; + // security + sum = 0.f; + for (i = 0; i < Info_::card; ++i) + sum += tmp[i]; + postcondition(std::abs(sum - 1) <= epsilon); + return tmp; + } + + // Central symmetry + + array1d<array1d_info<Info_::card, + Info_::card - Info_::center - 1, + Info_::i>, T> + operator-() const + { + enum { new_center = Info_::card - Info_::center - 1 }; + array1d<array1d_info< Info_::card, new_center, Info_::i>,T> tmp; + + for (unsigned i = 0; i < Info_::card; ++i) + tmp[Info_::card - i - 1] = this->operator[](i); + return tmp; + } + + + // Operators + + // FIXME: This code should be factorized between 1d, 2d and 3d. + // Think of a mechanism similar to apply() and apply2(). + + template <class U> + array1d< Info, ntg_return_type(times, T, U) > + operator*(U w) + { + array1d< Info, ntg_return_type(times, T, U) > tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] * w; + return tmp; + } + + template <class U> + array1d< Info, ntg_return_type(div, T, U) > + operator/(U w) + { + array1d< Info, ntg_return_type(div, T, U) > tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] / w; + return tmp; + } + + self operator+(const self& rhs) const + { + self tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] + rhs.buffer_[i]; + return tmp; + } + self& operator+=(const self& rhs) + { + for (unsigned i = 0; i < Info::card; ++i) + this->buffer_[i] += rhs.buffer_[i]; + return *this; + } + + self operator-(const self& rhs) const + { + self tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] - rhs.buffer_[i]; + return tmp; + } + self& operator-=(const self& rhs) + { + for (unsigned i = 0; i < Info::card; ++i) + this->buffer_[i] -= rhs.buffer_[i]; + return *this; + } + + + // + // Accessors + // + + unsigned size() const + { + return Info_::card; + } + + const T* buffer() const + { + return buffer_; + } + + // dynamic accessors: + + T operator[](unsigned i) const // Absolute position + { + precondition(i < Info_::card); + return *(buffer_ + i); + } + T& operator[](unsigned i) + { + precondition(i < Info_::card); + return *(buffer_ + i); + } + + T operator()(int i) const // Relative position + { + precondition(-Info_::center <= i); + precondition(i <= Info_::card - Info_::center - 1); + return *(buffer_ + Info_::center + i); + } + T& operator()(int i) + { + precondition(-Info_::center <= i); + precondition(i <= Info_::card - Info_::center - 1); + return *(buffer_ + Info_::center + i); + } + + + // do not use these methods... + + template<unsigned i> + T get_at_() const { + lesseq<i, Info_::card>::ensure(); + return *(buffer_ + i); + } + + template<int i> + T get_() const { + lesseq<-Info_::center, i>::ensure(); + lesseq<i, Info_::card - Info_::center - 1>::ensure(); + return *(buffer_ + Info_::center + i); + } + + protected: + + T buffer_[Info_::card]; + }; + + + // ...but these static accessors: + + template<unsigned i, class Info, class T> inline + T get_at(const array1d<Info, T>& arr) + { + return arr.template get_at_<i>(); + } + + template<int i, class Info, class T> inline + T get(const array1d<Info, T>& arr) + { + return arr.template get_<i>(); + } + + // starter objects + + // FIXME: what about other types? Replace this by a function + // returning a starter. + +# define array1d_starter(T) \ + static internal::array1d_start_<T > T##s_1d = internal::array1d_start_<T >() + + array1d_starter(int); // ints_1d + array1d_starter(float); // floats_1d + + + + // print + + template<class Info, class T> + std::ostream& operator<<(std::ostream& ostr, const array1d<Info, T>& rhs) + { + for (int i = 0; i < Info::card; ++i) + if (i == Info::center) + ostr << "<" << rhs[i] << "> "; + else + ostr << rhs[i] << " "; + ostr << std::endl; + + return ostr; + } + +} // end of mlc + +#endif // ! METALIC_ARRAY_1D_HH Index: mlc/array/2d.hh --- mlc/array/2d.hh (revision 0) +++ mlc/array/2d.hh (revision 0) @@ -0,0 +1,326 @@ +// Copyright (C) 2001, 2002, 2003, 2004 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, 59 Temple Place - Suite 330, 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 METALIC_ARRAY_2D_HH +# define METALIC_ARRAY_2D_HH + +# include <mlc/array/objs.hh> +# include <mlc/contract.hh> +# include <mlc/cmp.hh> +# include <ntg/basics.hh> + +# include <iostream> + +// impl +# include <mlc/array/2d.hxx> + +namespace mlc +{ + + template<class Info_, class T_> + struct array2d + { + typedef array2d self; + typedef T_ T; + typedef Info_ Info; + + // + // Constructors + // + + array2d() + { + } + + array2d(T* ptr) + { + less< 0, Info_::nrows >::ensure(); + less< 0, Info_::ncols >::ensure(); + less< Info_::card, internal::max_card_ >::ensure(); + for (unsigned i = 0; i < Info_::card; ++i) + buffer_[i] = *ptr++; + } + + // Copy + + array2d(const self& rhs) + { + for (unsigned i = 0; i < Info_::card; ++i) + buffer_[i] = rhs[i]; + } + self& operator=(const self& rhs) + { + for (unsigned i = 0; i < Info_::card; ++i) + buffer_[i] = rhs[i]; + return *this; + } + + + // Name + + static std::string + name() + { + return std::string("array2d< Info, ") + ntg_name(T) + " >"; + } + + + + // + // Operations on array + // + + + // Normalize (absolute values -> relative values) + + array2d<Info_, ntg::float_s> + normalize() + { + array2d<Info_, ntg::float_s> tmp; + ntg::float_s sum = 0.f; + const ntg::float_s epsilon = 0.01f; // FIXME : epsilon should be global + unsigned i; + for (i = 0; i < Info_::card; ++i) + sum += this->buffer_[i]; + for (i = 0; i < Info_::card; ++i) + tmp[i] = this->buffer_[i] / sum; + // security + sum = 0.f; + for (i = 0; i < Info_::card; ++i) + sum += tmp[i]; + postcondition(std::abs(sum - 1) <= epsilon); + return tmp; + } + + // Central symmetry + + array2d<array2d_info<Info_::nrows, + Info_::ncols, + Info_::card - Info_::center - 1, + Info_::i>, T> + operator-() const + { + enum { new_center = Info_::card - Info_::center - 1 }; + array2d<array2d_info< Info_::nrows, Info_::ncols, new_center, Info_::i>,T> tmp; + + for (unsigned i = 0; i < Info_::card; ++i) + tmp[Info_::card - i - 1] = this->operator[](i); + return tmp; + } + + + // Transpose + + typedef array2d<array2d_info< + Info_::ncols, + Info_::nrows, + (Info_::center * Info_::nrows + Info_::center / Info_::ncols) % Info_::card, + Info_::i + >, T> transposed_array_t; + + transposed_array_t transpose() const + { + transposed_array_t tmp; + for (int i = 0; i < Info::card; ++i) + tmp[i] = this->operator[]((i * Info_::ncols + i / Info_::nrows) % Info_::card); + return tmp; + } + + // Operators + + // FIXME: This code should be factorized between 1d, 2d and 3d. + // Think of a mechanism similar to apply() and apply2(). + + template <class U> + array2d< Info, ntg_return_type(times, T, U) > + operator*(U w) + { + array2d< Info, ntg_return_type(times, T, U) > tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] * w; + return tmp; + } + + template <class U> + array2d< Info, ntg_return_type(div, T, U) > + operator/(U w) + { + array2d< Info, ntg_return_type(div, T, U) > tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] / w; + return tmp; + } + + self operator+(const self& rhs) const + { + self tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] + rhs.buffer_[i]; + return tmp; + } + self& operator+=(const self& rhs) + { + for (unsigned i = 0; i < Info::card; ++i) + this->buffer_[i] += rhs.buffer_[i]; + return *this; + } + + self operator-(const self& rhs) const + { + self tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] - rhs.buffer_[i]; + return tmp; + } + self& operator-=(const self& rhs) + { + for (unsigned i = 0; i < Info::card; ++i) + this->buffer_[i] -= rhs.buffer_[i]; + return *this; + } + + + // + // Accessors + // + + unsigned size() const + { + return Info_::card; + } + + const T* buffer() const + { + return buffer_; + } + + // dynamic accessors: + + T operator[](unsigned i) const // Absolute position + { + precondition(i < Info_::card); + return *(buffer_ + i); + } + T& operator[](unsigned i) + { + precondition(i < Info_::card); + return *(buffer_ + i); + } + + + T operator()(int row, int col) const // Relative position + { + precondition(-Info_::center_row <= row); + precondition(row <= Info_::nrows - Info_::center_row - 1); + precondition(-Info_::center_col <= col); + precondition(col <= Info_::ncols - Info_::center_col - 1); + + return *(buffer_ + Info_::center + (row * Info_::ncols) + col); + } + T& operator()(int row, int col) + { + precondition(-Info_::center_row <= row); + precondition(row <= Info_::nrows - Info_::center_row - 1); + precondition(-Info_::center_col <= col); + precondition(col <= Info_::ncols - Info_::center_col - 1); + + return *(buffer_ + Info_::center + (row * Info_::ncols) + col); + } + + + // do not use these methods... + + template<unsigned i> + T get_at_() const { + lesseq<i, Info_::card>::ensure(); + return *(buffer_ + i); + } + + template<int nrow, int ncol> + T get_() const { + lesseq< -Info_::center_row, nrow >::ensure(); + lesseq< nrow, Info_::nrows - Info_::center_row - 1 >::ensure(); + lesseq< -Info_::center_col, ncol >::ensure(); + lesseq< ncol, Info_::ncols - Info_::center_col - 1 >::ensure(); + return *(buffer_ + Info_::center + (nrow * Info_::ncols) + ncol); + } + + + protected: + + T buffer_[internal::max_card_]; + }; + + + // ...but these static accessors: + + template<unsigned i, class Info, class T> inline + T get_at(const array2d<Info, T>& arr) + { + return arr.template get_at_<i>(); + } + + template<int row, int col, class Info, class T> inline + T get(const array2d<Info, T>& arr) + { + return arr.template get_<row, col>(); + } + + // starter objects + + // FIXME: what about other types? Replace this by a function + // returning a starter. + +# define array2d_starter(T) \ + static internal::array2d_start_<T > T##s_2d = internal::array2d_start_<T >() + + array2d_starter(int); // ints_2d + array2d_starter(float); // floats_2d + + + // print + + template<class Info, class T> + std::ostream& operator<<(std::ostream& ostr, const array2d<Info, T>& rhs) + { + for (int i = 0; i < Info::card; ++i) + { + if (i == Info::center) + ostr << "<" << rhs[i] << ">"; + else + ostr << rhs[i]; + + ostr << ((i + 1) % Info::ncols == 0 ? "\n" : "\t"); + } + ostr << std::flush; + return ostr; + } + +} // end of mlc + + +#endif // ! METALIC_ARRAY_2D_HH Index: mlc/array/3d.hh --- mlc/array/3d.hh (revision 0) +++ mlc/array/3d.hh (revision 0) @@ -0,0 +1,333 @@ +// Copyright (C) 2001, 2002, 2003, 2004 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, 59 Temple Place - Suite 330, 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 METALIC_ARRAY_3D_HH +# define METALIC_ARRAY_3D_HH + +# include <mlc/array/objs.hh> +# include <mlc/contract.hh> +# include <mlc/cmp.hh> +# include <ntg/basics.hh> + +# include <iostream> + +// impl +# include <mlc/array/3d.hxx> + +namespace mlc +{ + + class not_implemented_yet{}; // FIXME + + template<class Info_, class T_> + struct array3d + { + typedef array3d self; + typedef T_ T; + typedef Info_ Info; + + // + // Constructors + // + + array3d() + { + } + + array3d(T* ptr) + { + less< 0, Info_::nplanes >::ensure(); + less< 0, Info_::nrows >::ensure(); + less< 0, Info_::ncols >::ensure(); + less< Info_::card, internal::max_card_ >::ensure(); + for (unsigned i = 0; i < Info_::card; ++i) + buffer_[i] = *ptr++; + } + + // Copy + + array3d(const self& rhs) + { + for (unsigned i = 0; i < Info_::card; ++i) + buffer_[i] = rhs[i]; + } + self& operator=(const self& rhs) + { + for (unsigned i = 0; i < Info_::card; ++i) + buffer_[i] = rhs[i]; + return *this; + } + + + // Name + + static std::string + name() + { + return std::string("array3d< Info, ") + ntg_name(T) + " >"; + } + + + + // + // Operations on array + // + + // Normalize (absolute values -> relative values) + + array3d<Info_, ntg::float_s> + normalize() + { + array3d<Info_, ntg::float_s> tmp; + ntg::float_s sum = 0.f; + const ntg::float_s epsilon = 0.01f; // FIXME : epsilon should be global + unsigned i; + for (i = 0; i < Info_::card; ++i) + sum += this->buffer_[i]; + for (i = 0; i < Info_::card; ++i) + tmp[i] = this->buffer_[i] / sum; + // security + sum = 0.f; + for (i = 0; i < Info_::card; ++i) + sum += tmp[i]; + postcondition(std::abs(sum - 1) <= epsilon); + return tmp; + } + + // Central symmetry + + array3d<array3d_info<Info_::nplanes, + Info_::nrows, + Info_::ncols, + Info_::card - Info_::center - 1, + Info_::i>, T> + operator-() const + { + enum { new_center = Info_::card - Info_::center - 1 }; + array3d<array3d_info< Info_::nplanes, Info_::nrows, Info_::ncols, new_center, Info_::i>,T> tmp; + + for (unsigned i = 0; i < Info_::card; ++i) + tmp[Info_::card - i - 1] = this->operator[](i); + return tmp; + } + + + // Transpose + + array3d<Info, T> transpose() const // FIXME + { + std::cerr << "[31m===> 3D transposition not implemented yet. <===[0m" << std::endl; + throw not_implemented_yet(); + } + + + // Operators + + // FIXME: This code should be factorized between 1d, 2d and 3d. + // Think of a mechanism similar to apply() and apply2(). + + template <class U> + array3d< Info, ntg_return_type(times, T, U) > + operator*(U w) + { + array3d< Info, ntg_return_type(times, T, U) > tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] * w; + return tmp; + } + + template <class U> + array3d< Info, ntg_return_type(div, T, U) > + operator/(U w) + { + array3d< Info, ntg_return_type(div, T, U) > tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] / w; + return tmp; + } + + self operator+(const self& rhs) const + { + self tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] + rhs.buffer_[i]; + return tmp; + } + self& operator+=(const self& rhs) + { + for (unsigned i = 0; i < Info::card; ++i) + this->buffer_[i] += rhs.buffer_[i]; + return *this; + } + + self operator-(const self& rhs) const + { + self tmp; + for (unsigned i = 0; i < Info::card; ++i) + tmp[i] = this->buffer_[i] - rhs.buffer_[i]; + return tmp; + } + self& operator-=(const self& rhs) + { + for (unsigned i = 0; i < Info::card; ++i) + this->buffer_[i] -= rhs.buffer_[i]; + return *this; + } + + + + // template<class U> int operator,(U); // FIXME: why this? + + // + // Accessors + // + + unsigned size() const + { + return Info_::card; + } + + const T* buffer() const + { + return buffer_; + } + + // dynamic accessors: + + T operator[](unsigned i) const // Absolute position + { + precondition(i < Info_::card); + return *(buffer_ + i); + } + T& operator[](unsigned i) + { + precondition(i < Info_::card); + return *(buffer_ + i); + } + + + T operator()(int plane, int row, int col) const // Relative position + { + precondition(-Info_::center_plane <= plane); + precondition(plane <= Info::nplanes - Info_::center_plane - 1); + precondition(-Info_::center_row <= row); + precondition(row <= Info_::nrows - Info_::center_row - 1); + precondition(-Info_::center_col <= col); + precondition(col <= Info_::ncols - Info_::center_col - 1); + + return *(buffer_ + Info_::center + (plane * Info::nrows * Info::ncols) + (row * Info::ncols) + col); + } + + T& operator()(int plane, int row, int col) + { + precondition(-Info_::center_plane <= plane); + precondition(plane <= Info::nplanes - Info_::center_plane - 1); + precondition(-Info_::center_row <= row); + precondition(row <= Info_::nrows - Info_::center_row - 1); + precondition(-Info_::center_col <= col); + precondition(col <= Info_::ncols - Info_::center_col - 1); + + return *(buffer_ + Info_::center + (plane * Info::nrows * Info::ncols) + (row * Info::ncols) + col); + } + + + // do not use these methods... + + template<unsigned i> + T get_at_() const { + lesseq<i, Info_::card>::ensure(); + return *(buffer_ + i); + } + + template<int nplane, int nrow, int ncol> + T get_() const { + lesseq< -Info_::center_plane, nplane >::ensure(); + lesseq< nplane, Info::nplanes - Info_::center_plane - 1 >::ensure(); + lesseq< -Info_::center_row, nrow >::ensure(); + lesseq< nrow, Info_::nrows - Info_::center_row - 1 >::ensure(); + lesseq< -Info_::center_col, ncol >::ensure(); + lesseq< ncol, Info_::ncols - Info_::center_col - 1 >::ensure(); + return *(buffer_ + Info_::center + (nplane * Info::nrows * Info::ncols) + (nrow * Info::ncols) + ncol); + } + + + protected: + + T buffer_[internal::max_card_]; + }; + + + // ...but these static accessors: + + template<unsigned i, class Info, class T> inline + T get_at(const array3d<Info, T>& arr) + { + return arr.template get_at_<i>(); + } + + template<int plane, int row, int col, class Info, class T> inline + T get(const array3d<Info, T>& arr) + { + return arr.template get_<plane, row, col>(); + } + + // starter objects + + // FIXME: what about other types? Replace this by a function + // returning a starter. + +# define array3d_starter(T) \ + static internal::array3d_start_<T > T##s_3d = internal::array3d_start_<T >() + + array3d_starter(int); // ints_3d + array3d_starter(float); // floats_3d + + + // print + + template<class Info, class T> + std::ostream& operator<<(std::ostream& ostr, const array3d<Info, T>& rhs) + { + for (int i = 0; i < Info::card; ++i) + { + if (i == Info::center) + ostr << "<" << rhs[i] << "> "; + else + ostr << rhs[i] << " "; + + ostr << ((i + 1) % Info::ncols == 0 ? "\n" : "\t"); + ostr << ((i + 1) % (Info::ncols * Info::nrows) == 0 ? "\n" : ""); + } + ostr << std::flush; + + return ostr; + } + + +} // end of mlc + +#endif // ! METALIC_ARRAY_3D_HH Index: mlc/array/all.hh --- mlc/array/all.hh (revision 0) +++ mlc/array/all.hh (revision 0) @@ -0,0 +1,35 @@ +// 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 +// 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, 59 Temple Place - Suite 330, 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 METALIC_ARRAY__HH +# define METALIC_ARRAY__HH + +# include <mlc/array/1d.hh> +# include <mlc/array/2d.hh> +# include <mlc/array/3d.hh> + +#endif // ! METALIC_ARRAY__HH Index: mlc/array/1d.hxx --- mlc/array/1d.hxx (revision 0) +++ mlc/array/1d.hxx (revision 0) @@ -0,0 +1,237 @@ +// 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 +// 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, 59 Temple Place - Suite 330, 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 METALIC_ARRAY_1D_HXX +# define METALIC_ARRAY_1D_HXX + +# include <mlc/array/nd.hh> + +namespace mlc +{ + + // + // mlc::array1d_info + // + //////////////////////////////////////// + + + // card_ -> total number of elements (1-indexed) + + // center_ -> position of the central element (0-indexed) + // domain : [ 0, card [ + + // i_ -> number of elements that have been eaten yet (0-indexed) + // domain : [ 0, card ] -> watch out !! + + + template < unsigned card_, unsigned center_ = card_ / 2, unsigned i_ = card_> + struct array1d_info + { + enum { + card = card_, + center = center_, + i = i_, + well_formed = true, + get_real_center = center_ + }; + + typedef array1d_info< card_, center_, i + 1 > next_elt; + + }; + + template < unsigned card_, unsigned i_ > + struct array1d_info <card_, internal::unknown_, i_ > + { + enum { + card = card_, + center = internal::unknown_, + i = i_, + well_formed = true, + get_real_center = i_ / 2 + }; + + typedef array1d_info< card_, internal::unknown_, i + 1 > next_elt; + + }; + + // fwd decl + template<class, class> struct array1d; + + + namespace internal + { + + // fwd decl + + template<class T, class Info> + struct array1d_elt_; + + // for error messages + + template<class U> + struct here_a_value_is_not_of_type_; + + + // + // mlc::internal::array1d_start_ decl + // + //////////////////////////////////////// + + template<class T> + struct array1d_start_ { + + array1d_elt_< T, array1d_info< unknown_, unknown_, 1 > > operator=(T val); + array1d_elt_< T, array1d_info< unknown_, 0, 1 > > operator=(x_<T> val); + array1d_elt_< T, array1d_info< unknown_, 0, 1 > > operator=(x_<void> val); + + T ptr[max_card_]; // could be static + }; + + + + // + // mlc::internal::array1d_elt_ + // + //////////////////////////////////////// + + template<class T, class Info> + struct array1d_elt_ + { + typedef array1d_elt_<T, typename Info::next_elt> next_elt_t_; + + typedef array1d_elt_< T, array1d_info< Info::card, Info::i, Info::i + 1> > eat_center_t_; + + typedef array1d< array1d_info< Info::i, Info::get_real_center, Info::i > , T> array1d_t_; + + public: + + // Constructor + + array1d_elt_(T* ptr, array1d_start_<T>* arr) : ptr(ptr), arr(arr) + { + } + + + + // + // Overloading "operator," + // + + + // elt, elt + + next_elt_t_ operator,(T val) + { + is_true<Info::card == unknown_>::ensure(); + *ptr = val; + return next_elt_t_(ptr + 1, arr); + } + + + // elt, x(elt) -> center + + eat_center_t_ operator,(x_<T> val) + { + is_true<Info::center == unknown_>::ensure(); + *ptr = val.ue; // FIXME : give a *name* to this variable !! + return eat_center_t_(ptr+1, arr); + } + + + // elt, x() -> center + + eat_center_t_ operator,(x_<void>) + { + is_true<Info::center == unknown_>::ensure(); + *ptr = T(0); + return eat_center_t_(ptr+1, arr); + } + + + // elt, end + + array1d_t_ operator,(end_type) + { + // array is well-formed : + is_trueInfo::well_formed::ensure(); + // centering is automatic or user-defined : + // (commented out to allow automatic centering on even sized arrays) + // mlc::logical_or< mlc::eq< Info::i % 2, 1 >::ret, mlc::neq< Info::center, unknown_ >::ret >::ensure(); + return array1d_t_(arr->ptr); + } + + + // else -> error + + template<class U> + void operator,(array1d< Info, U >); + + template<class U> + here_a_value_is_not_of_type_<T> operator,(U u) const; + + T* ptr; + array1d_start_<T>* arr; + }; + + + + // + // mlc::internal::array1d_start_ impl + // + //////////////////////////////////////// + + template<class T> inline + array1d_elt_< T, array1d_info< unknown_, unknown_, 1 > > + array1d_start_<T>::operator=(T val) + { + ptr[0] = val; + return array1d_elt_< T, array1d_info< unknown_, unknown_, 1 > >(ptr+1, this); + } + + template<class T> inline + array1d_elt_< T, array1d_info< unknown_, 0, 1 > > + array1d_start_<T>::operator=(x_<T> val) + { + ptr[0] = val.ue; + // center <- 0 + return array1d_elt_< T, array1d_info< unknown_, 0, 1 > >(ptr+1, this); + } + + template<class T> inline + array1d_elt_< T, array1d_info< unknown_, 0, 1 > > + array1d_start_<T>::operator=(x_<void> val) + { + ptr[0] = T(0); + // center <- 0 + return array1d_elt_< T, array1d_info< unknown_, 0, 1 > >(ptr+1,this); + } + + } // end of internal + +} // end of mlc + +#endif // ! METALIC_ARRAY_1D_HXX Index: mlc/array/2d.hxx --- mlc/array/2d.hxx (revision 0) +++ mlc/array/2d.hxx (revision 0) @@ -0,0 +1,283 @@ +// 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 +// 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, 59 Temple Place - Suite 330, 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 METALIC_ARRAY_2D_HXX +# define METALIC_ARRAY_2D_HXX + +# include <mlc/array/nd.hh> + +namespace mlc +{ + + // + // mlc::array2d_info + // + //////////////////////////////////////// + + + // nrows_ -> total number of rows (1-indexed) + // ncols_ -> total number of columns (1-indexed) + + // center_ -> position of the central element (0-indexed) + // domain : [ 0, card [ + + // i_ -> number of elements that have been eaten yet (0-indexed) + // domain : [ 0, card ] -> watch out !! + + + + // Center is user-defined + + template < unsigned nrows_, + unsigned ncols_, + unsigned center_ = ncols_ * (nrows_ / 2) + (ncols_ / 2), + unsigned i_ = nrows_ * ncols_> + struct array2d_info + { + enum { + nrows = nrows_, + ncols = ncols_, + center = center_, + center_row = center_ / ncols_, + center_col = center_ % ncols_, + card = nrows_ * ncols_, + i = i_, + well_formed = ((i_ % ncols_) == 0), + get_real_center = center_ + }; + + typedef array2d_info< nrows_, ncols_, center_, i + 1 > next_elt; + + }; + + // Center is defined automatically, if nrows and ncols are both odd + + template < unsigned nrows_, unsigned ncols_, unsigned i_ > + struct array2d_info <nrows_, ncols_, internal::unknown_, i_ > + { + enum { + nrows = nrows_, + ncols = ncols_, + center = internal::unknown_, + i = i_, + card = nrows_ * ncols_, + well_formed = ((i_ % ncols_) == 0), + get_real_center = i_ / 2 + }; + + typedef array2d_info< nrows_, ncols_, internal::unknown_, i + 1 > next_elt; + + }; + + // fwd decl + template<class, class> struct array2d; + + + namespace internal + { + + // fwd decl + + template<class T, class Info> + struct array2d_elt_; + + // for error messages + + template<class U> + struct here_a_value_is_not_of_type_; + + + // + // mlc::internal::array2d_start_ decl + // + //////////////////////////////////////// + + template<class T> + struct array2d_start_ { + + array2d_elt_< T, array2d_info< unknown_, unknown_, unknown_, 1 > > + operator=(T val); + + array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > > + operator=(x_<T> val); + + array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > > + operator=(x_<void> val); + + T ptr[max_card_]; // could be static + }; + + + // + // mlc::internal::array2d_elt_ + // + //////////////////////////////////////// + + template<class T, class Info> + struct array2d_elt_ + { + typedef array2d_elt_< T, typename Info::next_elt > + next_elt_t_; + + typedef array2d_elt_< T, array2d_info< Info::nrows, Info::ncols, Info::i, Info::i + 1> > + eat_center_t_; + + typedef array2d_elt_< T, array2d_info< Info::nrows, Info::i, Info::center, Info::i > > + eat_lbrk_t_; + + typedef array2d< array2d_info< Info::i / Info::ncols, Info::ncols, Info::get_real_center, Info::i > , T> + array2d_t_; + + public: + + // Constructor + + array2d_elt_(T* ptr, array2d_start_<T>* arr) : ptr(ptr), arr(arr) + { + } + + + // + // Overloading "operator," + // + + + // elt, elt + + next_elt_t_ operator,(T val) + { + is_true<Info::nrows == unknown_>::ensure(); + *ptr = val; + return next_elt_t_(ptr + 1, arr); + } + + + // elt, x(elt) -> center + + eat_center_t_ operator,(x_<T> val) + { + is_true<Info::center == unknown_>::ensure(); + *ptr = val.ue; // FIXME : give a *name* to this variable !! + return eat_center_t_(ptr + 1, arr); + } + + + // elt, x() -> center + + eat_center_t_ operator,(x_<void>) + { + is_true<Info::center == unknown_>::ensure(); + *ptr = T(0); + return eat_center_t_(ptr + 1, arr); + } + + + // elt, lbrk + + eat_lbrk_t_ operator,(lbrk_) + { + is_true<Info::ncols == unknown_>::ensure(); + is_true<Info::ncols != 0>::ensure(); + return eat_lbrk_t_(ptr, arr); + } + + + // elt, end + + array2d_t_ operator,(end_type) + { + enum { nrows = Info::i / Info::ncols }; + + // array is well-formed : + is_true<Info::well_formed == true>::ensure(); + // centering is automatic or user-defined : + + is_true<Info::ncols != unknown_>::ensure(); + + + // both nrows and ncols must be odd + // or the center must be user-defined + + is_true< + ((Info::ncols % 2 == 1) && (nrows % 2 == 1)) + || (Info::center != unknown_) + >::ensure(); + + return array2d_t_(arr->ptr); + } + + + // else -> error + + template<class U> + void operator,(array2d< Info, U >); + + template<class U> + here_a_value_is_not_of_type_<T> operator,(U u) const; + + T* ptr; + array2d_start_<T>* arr; + }; + + + + // + // mlc::internal::array2d_start_ impl + // + //////////////////////////////////////// + + template<class T> inline + array2d_elt_< T, array2d_info< unknown_, unknown_, unknown_, 1 > > + array2d_start_<T>::operator=(T val) + { + ptr[0] = val; + return array2d_elt_< T, array2d_info< unknown_, unknown_, unknown_, 1 > >(ptr+1,this); + } + + template<class T> inline + array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > > + array2d_start_<T>::operator=(x_<T> val) + { + ptr[0] = val.ue; + // center <- 0 + return array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > >(ptr+1,this); + } + + template<class T> inline + array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > > + array2d_start_<T>::operator=(x_<void> val) + { + ptr[0] = T(0); + // center <- 0 + return array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > >(ptr+1,this); + } + + } // end of internal + +} // end of mlc + +#endif // ! METALIC_ARRAY_2D_HXX Index: mlc/array/objs.hh --- mlc/array/objs.hh (revision 0) +++ mlc/array/objs.hh (revision 0) @@ -0,0 +1,78 @@ +// Copyright (C) 2001, 2002, 2003, 2005 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, 59 Temple Place - Suite 330, 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 METALIC_ARRAY_OBJS_HH +# define METALIC_ARRAY_OBJS_HH + +// FIXME: rename, objs is not precise enough. + +// +// Defines common objects useful for array declarations. +// + +namespace mlc +{ + + class begin_type {}; + class end_type {}; + + static const begin_type begin = begin_type(); + static const end_type end = end_type(); + + namespace internal + { + + class lbrk_ {}; + class pbrk_ {}; + + template<class T> + struct x_ { + x_(T val) : ue(val) {} + T ue; + }; + template<> struct x_<void> {}; + template<> struct x_<lbrk_>; + template<> struct x_<end_type>; + + } // end of internal + + // cross means origin + + template<class T> inline + internal::x_<T> + x(T val) { return internal::x_<T>(val); } + + inline + internal::x_<void> + x() { return internal::x_<void>(); } + + static const internal::lbrk_ lbrk = internal::lbrk_(); + static const internal::pbrk_ pbrk = internal::pbrk_(); + +} // end of mlc + +#endif // METALIC_ARRAY_OBJS_HH Index: mlc/array/3d.hxx --- mlc/array/3d.hxx (revision 0) +++ mlc/array/3d.hxx (revision 0) @@ -0,0 +1,293 @@ +// 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 +// 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, 59 Temple Place - Suite 330, 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 METALIC_ARRAY_3D_HXX +# define METALIC_ARRAY_3D_HXX + +# include <mlc/array/nd.hh> + +namespace mlc +{ + + // + // mlc::array3d_info + // + //////////////////////////////////////// + + + // nrows_ -> total number of rows (1-indexed) + // ncols_ -> total number of columns (1-indexed) + // nplanes_ -> total number of planes (1-indexed) + + // center_ -> position of the central element (0-indexed) + // domain : [ 0, card [ + + // i_ -> number of elements that have been eaten yet (0-indexed) + // domain : [ 0, card ] -> watch out !! + + // Center is user-defined + + template < unsigned nplanes_, + unsigned nrows_, + unsigned ncols_, + unsigned center_ = (ncols_ * nrows_) * (nplanes_ / 2) + ncols_ * (nrows_ / 2) + (ncols_ / 2), + unsigned i_ = nplanes_ * nrows_ * ncols_> + struct array3d_info + { + enum { + nplanes = nplanes_, + nrows = nrows_, + ncols = ncols_, + center = center_, + center_plane = center_ / (nrows_ * ncols_), + center_row = (center_ % (nrows_ * ncols_)) / ncols_, + center_col = (center_ % (nrows_ * ncols_)) % ncols_, + i = i_, + card = nplanes_ * nrows_ * ncols_, + well_formed = (i_ % (ncols_ * nrows) == 0), + get_real_center = center_ + }; + + typedef array3d_info< nplanes_, nrows_, ncols_, center_, i + 1 > next_elt; + + }; + + // Center is defined automatically, if nrows and ncols are both odd + + template < unsigned nplanes_, unsigned nrows_, unsigned ncols_, unsigned i_ > + struct array3d_info < nplanes_, nrows_, ncols_, internal::unknown_, i_ > + { + enum { + nplanes = nplanes_, + nrows = nrows_, + ncols = ncols_, + center = internal::unknown_, + i = i_, + card = nplanes_ * nrows_ * ncols_, + well_formed = (i_ % (ncols_ * nrows_) == 0), + get_real_center = i_ / 2 + }; + + typedef array3d_info< nplanes_, nrows_, ncols_, internal::unknown_, i + 1 > next_elt; + + }; + + // fwd decl + template<class, class> struct array3d; + + namespace internal + { + + // fwd decl + + template<class T, class Info> + struct array3d_elt_; + + // for error messages + + template<class U> + struct here_a_value_is_not_of_type_; + + + // + // mlc::internal::array3d_start_ decl + // + //////////////////////////////////////// + + template<class T> + struct array3d_start_ { + + array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, unknown_, 1 > > + operator=(T val); + + array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, 0, 1 > > + operator=(x_<T> val); + + array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, 0, 1 > > + operator=(x_<void> val); + + T ptr[max_card_]; // could be static + }; + + // + // mlc::internal::array3d_elt_ + // + //////////////////////////////////////// + + template<class T, class Info> + struct array3d_elt_ + { + typedef array3d_elt_< T, typename Info::next_elt > + next_elt_t_; + + typedef array3d_elt_< T, array3d_info< Info::nplanes, Info::nrows, Info::ncols, Info::i, Info::i + 1> > + eat_center_t_; + + typedef array3d_elt_< T, array3d_info< Info::nplanes, Info::nrows, Info::i, Info::center, Info::i > > + eat_lbrk_t_; + + typedef array3d_elt_< T, array3d_info< Info::nplanes, Info::i / Info::ncols, Info::ncols, Info::center, Info::i > > + eat_pbrk_t_; + + typedef array3d< array3d_info< Info::i / (Info::ncols * Info::nrows), Info::nrows, Info::ncols, Info::get_real_center, Info::i > , T> + array3d_t_; + + public: + + // Constructor + + array3d_elt_(T* ptr, array3d_start_<T>* arr) : ptr(ptr), arr(arr) + { + } + + + // + // Overloading "operator," + // + + + // elt, elt + + next_elt_t_ operator,(T val) + { + is_true<Info::nplanes == unknown_>::ensure(); + *ptr = val; + return next_elt_t_(ptr + 1, arr); + } + + + // elt, x(elt) -> center + + eat_center_t_ operator,(x_<T> val) + { + is_true<Info::center == unknown_>::ensure(); + *ptr = val.ue; // FIXME : give a *name* to this variable !! + return eat_center_t_(ptr + 1, arr); + } + + + // elt, x() -> center + + eat_center_t_ operator,(x_<void>) + { + is_true<Info::center == unknown_>::ensure(); + *ptr = T(0); + return eat_center_t_(ptr + 1, arr); + } + + + // elt, lbrk + + eat_lbrk_t_ operator,(lbrk_) + { + is_true<Info::ncols == unknown_>::ensure(); + return eat_lbrk_t_(ptr, arr); + } + + + // elt, pbrk + eat_pbrk_t_ operator,(pbrk_) + { + is_true<Info::nplanes == unknown_>::ensure(); + return eat_pbrk_t_(ptr, arr); + } + + // elt, end + + array3d_t_ operator,(end_type) + { + enum { nplanes = (Info::i / (Info::ncols * Info::nrows)) }; + + // array is well-formed : + is_trueInfo::well_formed::ensure(); + // centering is automatic or user-defined : + + is_true<Info::ncols != unknown_>::ensure(); + is_true<Info::nrows != unknown_>::ensure(); + + // all of nplanes, nrows and ncols are odd + // or the center is user-defined + + is_true< + (Info::ncols % 2 == 1 && Info::nrows % 2 == 1 && nplanes % 2 == 1) + || (Info::center != unknown_) + >::ensure(); + + return array3d_t_(arr->ptr); + } + + + // else -> error + + template<class U> + void operator,(array3d< Info, U >); + + template<class U> + here_a_value_is_not_of_type_<T> operator,(U u) const; + + T* ptr; + array3d_start_<T>* arr; + }; + + + // + // mlc::internal::array3d_start_ impl + // + //////////////////////////////////////// + + template<class T> inline + array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, unknown_, 1 > > + array3d_start_<T>::operator=(T val) + { + ptr[0] = val; + return array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, unknown_, 1 > >(ptr+1,this); + } + + template<class T> inline + array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, 0, 1 > > + array3d_start_<T>::operator=(x_<T> val) + { + ptr[0] = val.ue; + // center <- 0 + return array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, 0, 1 > >(ptr+1,this); + } + + template<class T> inline + array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, 0, 1 > > + array3d_start_<T>::operator=(x_<void> val) + { + ptr[0] = T(0); + // center <- 0 + return array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, 0, 1 > >(ptr+1,this); + } + + } // end of internal + +} // end of mlc + + +#endif // ! METALIC_ARRAY_3D_HXX