Milena (Olena)  User documentation 2.0a Id
gray_.hh
00001 // Copyright (C) 2006, 2007, 2008, 2009, 2011 EPITA Research and
00002 // Development Laboratory (LRDE)
00003 //
00004 // This file is part of Olena.
00005 //
00006 // Olena is free software: you can redistribute it and/or modify it under
00007 // the terms of the GNU General Public License as published by the Free
00008 // Software Foundation, version 2 of the License.
00009 //
00010 // Olena is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software project without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to produce
00022 // an executable, this file does not by itself cause the resulting
00023 // executable to be covered by the GNU General Public License.  This
00024 // exception does not however invalidate any other reasons why the
00025 // executable file might be covered by the GNU General Public License.
00026 
00027 #ifndef MLN_VALUE_INTERNAL_GRAY__HH
00028 # define MLN_VALUE_INTERNAL_GRAY__HH
00029 
00033 
00034 # include <iostream>
00035 # include <cmath>
00036 
00037 # include <mln/metal/math/max.hh>
00038 # include <mln/metal/math/pow.hh>
00039 
00040 # include <mln/value/concept/integer.hh>
00041 # include <mln/value/internal/value_like.hh>
00042 
00043 # include <mln/value/graylevel_f.hh>
00044 
00045 namespace mln
00046 {
00047 
00048   namespace literal
00049   {
00051     struct black_t;
00052     struct white_t;
00054   }
00055 
00056   namespace value
00057   {
00059     template <unsigned n>
00060     struct graylevel;
00061     template <unsigned N> struct graylevel;
00062     struct graylevel_f;
00063     namespace internal
00064     {
00065       template <unsigned n> class gray_;
00066       struct gray_f;
00067     }
00069   }
00070 
00071 
00072   namespace trait
00073   {
00074 
00075     template < template <class, class> class Name, unsigned n, unsigned m>
00076     struct set_precise_binary_< Name, mln::value::internal::gray_<n>, mln::value::internal::gray_<m> >
00077     {
00078       typedef mln::value::internal::gray_< mlc_max_int(n, m) > ret;
00079     };
00080 
00081     template <unsigned n, unsigned m>
00082     struct set_precise_binary_< op::greater, mln::value::internal::gray_<n>, mln::value::internal::gray_<m> >
00083     {
00084       typedef bool ret;
00085     };
00086 
00087     template <unsigned n, unsigned m>
00088     struct set_precise_binary_< op::eq, mln::value::internal::gray_<n>, mln::value::internal::gray_<m> >
00089     {
00090       typedef bool ret;
00091     };
00092 
00093     // 'gray_' as a value.
00094 
00095     template <unsigned n>
00096     struct value_< mln::value::internal::gray_<n> >
00097     {
00098     private:
00099       typedef mln::value::internal::gray_<n> self_;
00100     public:
00101 
00102       enum {
00103         nbits = 8 * (sizeof(unsigned) + sizeof(long)),
00104         card  = 0
00105       };
00106 
00107       typedef trait::value::nature::integer nature; // FIXME: Or scalar?.
00108       typedef trait::value::kind::gray      kind;
00109       typedef trait::value::quant::high     quant;
00110 
00111       static self_ min();
00112       static self_ max();
00113       static self_ epsilon();
00114 
00115       typedef self_ sum; // FIXME: OK?.
00116     };
00117 
00118   } // end of namespace mln::trait
00119 
00120 
00121 
00122   namespace value
00123   {
00124 
00125     namespace internal
00126     {
00127 
00130       template <unsigned n>
00131       class gray_
00132         :
00133         public Integer< gray_<n> >,
00134 
00135         public internal::value_like_< int,          // Equivalent.
00136                                       int,          // Encoding.
00137                                       gray_<n>,     // Interoperation.
00138                                       gray_<n> >    // Exact.
00139 
00140       {
00141       public:
00142 
00144         typedef int enc;
00145 
00147         typedef int equiv;
00148 
00150         gray_();
00152         gray_(int val);
00153 
00155         explicit gray_(const literal::white_t&);
00156         explicit gray_(const literal::black_t&);
00158 
00159 
00161         template <unsigned m>
00162         gray_(const graylevel<m>& val);
00163         template <unsigned m>
00164         gray_<n>& operator=(const graylevel<m>& val);
00166 
00168         int value() const;
00169 
00171         template <unsigned m>
00172         operator gray_<m>() const;
00173 
00175         template <unsigned m>
00176         operator graylevel<m>() const;
00177 
00179         operator graylevel_f() const;
00180 
00181       };
00182 
00183 
00184     // Operators.
00185 
00186       template <unsigned n>
00187       std::ostream& operator<<(std::ostream& ostr, const gray_<n>& g);
00188 
00189       template <unsigned n, unsigned m>
00190       bool operator==(const gray_<n>& lhs, const gray_<m>& rhs);
00191       template <unsigned n, unsigned m>
00192       bool operator<(const gray_<n>& lhs, const gray_<m>& rhs);
00193 
00194       template <unsigned n, unsigned m>
00195       mln_trait_op_plus(gray_<n>, gray_<m>)
00196       operator+(const gray_<n>& lhs, const gray_<m>& rhs);
00197 
00198       template <unsigned n, unsigned m>
00199       mln_trait_op_minus(gray_<n>, gray_<m>)
00200       operator-(const gray_<n>& lhs, const gray_<m>& rhs);
00201 
00202       template <unsigned n>
00203       gray_<n> operator*(int s, const gray_<n>& rhs);
00204       template <unsigned n>
00205       gray_<n> operator*(const gray_<n>& lhs, int s);
00206       template <unsigned n>
00207       gray_<n> operator/(const gray_<n>& lhs, int s);
00208 
00209     } // end of namespace mln::value::internal
00210 
00211   } // end of namespace mln::value
00212 
00213 } // end of namespace mln
00214 
00215 
00216 # include <mln/value/internal/gray_f.hh>
00217 
00218 
00219 namespace mln
00220 {
00221 
00222 # ifndef MLN_INCLUDE_ONLY
00223 
00224   namespace value
00225   {
00226     namespace internal
00227     {
00228 
00229       template <unsigned n_src, unsigned n_dest>
00230       inline
00231       long convert(int val)
00232       {
00233         using mln::metal::int_;
00234         typedef mlc_max(int_<n_dest - n_src> , int_<n_src - n_dest>) m;
00235 
00236         if (n_dest == n_src)
00237           return val;
00238         else
00239           if (n_dest > n_src)
00240             return val * mlc_pow_int(2, m::value);
00241           else
00242             return val / mlc_pow_int(2, m::value);
00243       }
00244 
00245       // Gray_<N>.
00246 
00247       template <unsigned n>
00248       inline
00249       gray_<n>::gray_()
00250       {
00251       }
00252 
00253       template <unsigned n>
00254       template <unsigned m>
00255       gray_<n>::gray_(const graylevel<m>& g)
00256       {
00257         this->v_ = convert<m, n>(g.value());
00258       }
00259 
00260       template <unsigned n>
00261       template <unsigned m>
00262       inline
00263       gray_<n>&
00264       gray_<n>::operator=(const graylevel<m>& g)
00265       {
00266         this->v_ = convert<m, n>(g.value());
00267         return *this;
00268       }
00269 
00270       template <unsigned n>
00271       inline
00272       gray_<n>::gray_(const literal::white_t&)
00273       {
00274         this->v_ = mlc_pow_int(2, n) - 1;
00275       }
00276 
00277       template <unsigned n>
00278       inline
00279       gray_<n>::gray_(const literal::black_t&)
00280       {
00281         this->v_ = 0;
00282       }
00283 
00284       template <unsigned n>
00285       inline
00286       gray_<n>::gray_(int val)
00287       {
00288         this->v_ = val;
00289       }
00290 
00291       template <unsigned n>
00292       inline
00293       int
00294       gray_<n>::value() const
00295       {
00296         return this->v_;
00297       }
00298 
00299       template <unsigned n>
00300       template <unsigned m>
00301       inline
00302       gray_<n>::operator gray_<m>() const
00303       {
00304         return gray_<m>(convert<n, m>(this->v_));
00305       }
00306 
00307 
00308       template <unsigned n>
00309       template <unsigned m>
00310       inline
00311       gray_<n>::operator graylevel<m>() const
00312       {
00313         graylevel<m> tmp(convert<n, m>(this->v_));
00314         mln_assertion(tmp.value() < std::pow(2.f, int(m)));
00315         return tmp;
00316       }
00317 
00318 
00319       template <unsigned n>
00320       inline
00321       gray_<n>::operator graylevel_f() const
00322       {
00323         static const float denom = float(metal::math::pow_int<2, n>::value) - 1.f;
00324         return graylevel_f(float(this->v_) / denom);
00325       }
00326 
00327       // Operators.
00328 
00329       template <unsigned n>
00330       inline
00331       std::ostream& operator<<(std::ostream& ostr, const gray_<n>& g)
00332       {
00333         return ostr << g.value() << "g/" << n << "bits";
00334       }
00335 
00336       template <unsigned n, unsigned m>
00337       inline
00338       bool operator==(const gray_<n>& lhs, const gray_<m>& rhs)
00339       {
00340         if (n == m)
00341           return internal::gray_<mlc_max_int(n, m)>(lhs).value() ==
00342             internal::gray_<mlc_max_int(n, m)>(rhs).value();
00343         if (n > m)
00344         {
00345           gray_<n> down = rhs;
00346           gray_<n> up(down.value() +
00347                       mlc_pow_int(2, m));
00348           return (lhs.value() >= down.value() && lhs.value() < up.value());
00349         }
00350         else
00351         {
00352           gray_<m> down = lhs;
00353           gray_<m> up(down.value() +
00354                       mlc_pow_int(2, n));
00355           return (rhs.value() >= down.value() && rhs.value() < up.value());
00356         }
00357       }
00358 
00359       template <unsigned n, unsigned m>
00360       inline
00361       bool operator<(const gray_<n>& lhs, const gray_<m>& rhs)
00362       {
00363         if (m == n)
00364           return lhs.value() < rhs.value();
00365         if (n > m)
00366           return lhs.value() < gray_<n>(rhs).value();
00367         else
00368           return gray_<m>(lhs).value() < rhs.value();
00369       }
00370 
00371       template <unsigned n, unsigned m>
00372       inline
00373       mln_trait_op_plus(gray_<n>, gray_<m>)
00374         operator+(const gray_<n>& lhs, const gray_<m>& rhs)
00375       {
00376         typedef mln_trait_op_plus(gray_<n>, gray_<m>) ret;
00377         if (n > m)
00378         {
00379           ret tmp(ret(lhs).value() + ret(rhs).value());
00380           return tmp;
00381         }
00382         else
00383         {
00384           ret tmp(ret(lhs).value() + ret(rhs).value());
00385           return tmp;
00386         }
00387       }
00388 
00389       template <unsigned n, unsigned m>
00390       inline
00391       mln_trait_op_minus(gray_<n>, gray_<m>)
00392         operator-(const gray_<n>& lhs, const gray_<m>& rhs)
00393       {
00394         typedef mln_trait_op_minus(gray_<n>, gray_<m>) ret;
00395 
00396 
00397         if (lhs == rhs)
00398           return ret(0);
00399         if (n == m)
00400           return ret(lhs.value() - rhs.value());
00401         if (n > m)
00402         {
00403           ret l = rhs;
00404           mln_assertion(lhs.value() >= l.value());
00405           ret tmp(lhs.value() - l.value());
00406           return tmp;
00407         }
00408         else
00409         {
00410           ret l = lhs;
00411           mln_assertion(l.value() >= rhs.value());
00412           ret tmp(l.value() - rhs.value());
00413           return tmp;
00414         }
00415       }
00416 
00417       template <unsigned n, unsigned m>
00418       inline
00419       mln_trait_op_times(gray_<n>, gray_<m>)
00420         operator*(const gray_<n>& lhs, const gray_<m>& rhs)
00421       {
00422         typedef mln_trait_op_times(gray_<n>, gray_<m>) ret;
00423 
00424         return ret(ret(lhs).value() * ret(rhs).value());
00425       }
00426 
00427       template <unsigned n>
00428       inline
00429       gray_<n> operator*(int s, const gray_<n>& rhs)
00430       {
00431         gray_<n> tmp(rhs.value() * s);
00432         return tmp;
00433       }
00434 
00435       template <unsigned n>
00436       inline
00437       gray_<n> operator*(const gray_<n>& lhs, int s)
00438       {
00439         gray_<n> tmp(lhs.value() * s);
00440         return tmp;
00441       }
00442 
00443       template <unsigned n>
00444       inline
00445       gray_<n> operator/(const gray_<n>& lhs, int s)
00446       {
00447         mln_precondition(s != 0);
00448         gray_<n> tmp(lhs.value() / s);
00449         return tmp;
00450       }
00451 
00452     } // end of namespace mln::value::internal
00453 
00454     // Graylevel operators.
00455 
00456     // Op gl == Int.
00457 
00458     template <typename I, unsigned n>
00459     inline
00460     bool
00461     operator==(const Integer<I>& lhs, const graylevel<n>& rhs)
00462     {
00463       return rhs.value() == exact(lhs);
00464     }
00465 
00466     // Op gl == gl.
00467 
00468     template <unsigned n, unsigned m>
00469     inline
00470     bool
00471     operator==(const graylevel<n>& lhs, const graylevel<m>& rhs)
00472     {
00473       return internal::gray_<n>(rhs) == internal::gray_<m>(lhs);
00474     }
00475 
00476     // Op gl + gl.
00477 
00478     template <unsigned n, unsigned m>
00479     inline
00480     mln_trait_op_plus(graylevel<n>, graylevel<m>)
00481       operator+(const graylevel<n>& lhs, const graylevel<m>& rhs)
00482     {
00483       return internal::gray_<n>(lhs) + internal::gray_<m>(rhs);
00484     }
00485 
00486     // Op gl + Another type.
00487     template <unsigned n, typename I>
00488     inline
00489     void
00490     operator+(const graylevel<n>& lhs, const I& i)
00491     {
00492       (void) lhs;
00493       (void) i;
00494       typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
00495     }
00496 
00497 
00498     // Op  Another type + gl.
00499     template <unsigned n, typename I>
00500     inline
00501     void
00502     operator+(const I& i, const graylevel<n>& rhs)
00503     {
00504       (void) i;
00505       (void) rhs;
00506       typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
00507     }
00508 
00509     // Op gl - gl.
00510     template <unsigned n, unsigned m>
00511     inline
00512     mln_trait_op_minus(graylevel<n>, graylevel<m>)
00513       operator-(const graylevel<n>& lhs, const graylevel<m>& rhs)
00514     {
00515       return internal::gray_<n>(lhs) - internal::gray_<m>(rhs);
00516     }
00517 
00518     // Op gl - Another type.
00519     template <unsigned n, typename I>
00520     inline
00521     void
00522     operator-(const graylevel<n>& lhs, const I& i)
00523     {
00524       (void) lhs;
00525       (void) i;
00526       typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
00527     }
00528 
00529 
00530     // Op  Another type - gl.
00531     template <unsigned n, typename I>
00532     inline
00533     void
00534     operator-(const I& i, const graylevel<n>& rhs)
00535     {
00536       (void) i;
00537       (void) rhs;
00538       typename graylevel<n>::wrong_use_of_graylevel___Please_use_the__to_enc__method a;
00539     }
00540 
00541     // Op gl * gl.
00542     template <unsigned n, unsigned m>
00543     inline
00544     mln_trait_op_times(graylevel<n>, graylevel<m>)
00545       operator*(const graylevel<n>& lhs, const graylevel<m>& rhs)
00546     {
00547       return internal::gray_<n>(lhs) * internal::gray_<m>(rhs);
00548     }
00549 
00550     // Op symm gl * Integer.
00551     template <unsigned n, typename I>
00552     inline
00553     internal::gray_<n>
00554       operator*(const graylevel<n>& lhs, const Integer<I>& rhs)
00555     {
00556       return internal::gray_<n>(lhs) * int(exact(rhs));
00557     }
00558 
00559     template <typename I, unsigned n>
00560     inline
00561     mln_trait_op_times(I, graylevel<n>)
00562       operator*(const Integer<I>& lhs, const graylevel<n>& rhs)
00563     {
00564       return internal::gray_<n>(rhs) * int(exact(lhs));
00565     }
00566 
00567     // Op symm gl * Floating.
00568     template <unsigned n, typename F>
00569     inline
00570     mln_trait_op_times(graylevel<n>, F)
00571       operator*(const graylevel<n>& lhs, const Floating<F>& rhs)
00572     {
00573       return lhs.to_float() * float(exact(rhs));
00574     }
00575 
00576     template <typename F, unsigned n>
00577     inline
00578     mln_trait_op_times(F, graylevel<n>)
00579       operator*(const Floating<F>& lhs, const graylevel<n>& rhs)
00580     {
00581       return rhs.to_float() * float(exact(lhs));
00582     }
00583 
00584     // Op * Builtin.
00585     template <unsigned n, typename T>
00586     mln_trait_op_times(graylevel<n>, T)
00587       operator*(const graylevel<n>& lhs, const T& rhs)
00588     {
00589       return lhs * scalar_<T>(rhs);
00590     }
00591 
00592     template <unsigned n, typename T>
00593     mln_trait_op_times(graylevel<n>, T)
00594       operator*(const T& lhs, const graylevel<n>& rhs)
00595     {
00596       return rhs * scalar_<T>(lhs);
00597     }
00598 
00599 
00600     // Op / Builtin.
00602     namespace internal
00603     {
00604       struct gray_f;
00605     }
00607 
00608     template <unsigned n, typename T>
00609     mln::value::internal::gray_f
00610     operator/(const graylevel<n>& lhs, const T& rhs)
00611     {
00612       return lhs / scalar_<T>(rhs);
00613     }
00614 
00615 
00616     // Op * scalar.
00617     namespace internal
00618     {
00619 
00620       template <typename ret>
00621       struct helper_gray__op_;
00622 
00623       template <unsigned n>
00624       struct helper_gray__op_< gray_<n> >
00625       {
00626         template <unsigned m, typename S>
00627         inline static
00628         mln_trait_op_times(graylevel<m>, scalar_<S>)
00629         times(const graylevel<m>& lhs, const scalar_<S>& rhs)
00630         {
00631           typedef mln_trait_op_times(graylevel<m>, scalar_<S>) ret;
00632           ret tmp(typename ret::equiv
00633                   (lhs.value() * typename ret::equiv(rhs.to_equiv())));
00634           return tmp;
00635         }
00636 
00637         template <unsigned m, typename S>
00638         inline static
00639         mln_trait_op_times(graylevel<m>, scalar_<S>)
00640         div(const graylevel<m>& lhs, const scalar_<S>& rhs)
00641         {
00642           typedef mln_trait_op_times(graylevel<m>, scalar_<S>) ret;
00643           ret tmp(typename ret::equiv
00644                   (lhs.value() / typename ret::equiv(rhs.to_equiv())));
00645           return tmp;
00646         }
00647       };
00648 
00649       template <>
00650       struct helper_gray__op_< gray_f >
00651       {
00652         template <unsigned n, typename S>
00653         inline static
00654         mln_trait_op_times(graylevel<n>, scalar_<S>)
00655           times(const graylevel<n>& lhs, const scalar_<S>& rhs)
00656         {
00657           typedef mln_trait_op_times(graylevel<n>, scalar_<S>) ret;
00658           ret tmp(lhs.to_float() * typename ret::equiv(rhs.to_equiv()));
00659           return tmp;
00660         }
00661         template <unsigned n, typename S>
00662         inline static
00663         mln_trait_op_div(graylevel<n>, scalar_<S>)
00664           div(const graylevel<n>& lhs, const scalar_<S>& rhs)
00665         {
00666           typedef mln_trait_op_div(graylevel<n>, scalar_<S>) ret;
00667           ret tmp(typename ret::equiv
00668                   (lhs.to_float() / typename ret::equiv(rhs.to_equiv())));
00669           return tmp;
00670         }
00671       };
00672 
00673     } // end of namespace mln::value::internal
00674 
00675     // Op graylevel<n> * scalar_<S>.
00676     template <unsigned n, typename S>
00677     inline
00678     mln_trait_op_times(graylevel<n>, scalar_<S>)
00679       operator*(const graylevel<n>& lhs, const scalar_<S>& rhs)
00680     {
00681       typedef mln_trait_op_times(graylevel<n>, scalar_<S>) ret;
00682       return internal::helper_gray__op_<ret>::times(lhs, rhs);
00683     }
00684 
00685     // Op graylevel<n> / scalar_<S>.
00686     template <unsigned n, typename S>
00687     inline
00688     mln_trait_op_div(graylevel<n>, scalar_<S>)
00689       operator/(const graylevel<n>& lhs, const scalar_<S>& rhs)
00690     {
00691       mln_precondition(rhs.to_equiv() != S(0));
00692       typedef mln_trait_op_div(graylevel<n>, scalar_<S>) ret;
00693       return internal::helper_gray__op_<ret>::div(lhs, rhs);
00694     }
00695 
00696   } //end of namespace mln::value
00697 
00698 
00699 
00700 namespace trait
00701 {
00702 
00703   // 'gray_<n>' as a value.
00704 
00705   template <unsigned n>
00706   inline
00707   mln::value::internal::gray_<n>
00708   value_< mln::value::internal::gray_<n> >::min()
00709   {
00710     return mln::value::internal::gray_<n>(1, 0);
00711   }
00712 
00713   template <unsigned n>
00714   inline
00715   mln::value::internal::gray_<n>
00716   value_< mln::value::internal::gray_<n> >::max()
00717   {
00718     return mln::value::internal::gray_<n>(1, 1);
00719   }
00720 
00721   template <unsigned n>
00722   inline
00723   mln::value::internal::gray_<n>
00724   value_< mln::value::internal::gray_<n> >::epsilon()
00725   {
00726     return mln::value::internal::gray_<n>(1, 0); // Means '0'.
00727   }
00728 
00729 } // end of namespace mln::trait
00730 
00731 
00732 # endif // ! MLN_INCLUDE_ONLY
00733 
00734 } // end of namespace mln
00735 
00736 #endif // ! MLN_VALUE_INTERNAL_GRAY__HH
 All Classes Namespaces Functions Variables Typedefs Enumerator