• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

gray_.hh

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

Generated on Tue Oct 4 2011 15:23:55 for Milena (Olena) by  doxygen 1.7.1