Milena (Olena)  User documentation 2.0a Id
float01.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_FLOAT01_HH
00028 # define MLN_VALUE_FLOAT01_HH
00029 
00033 
00034 # include <iostream>
00035 # include <utility>
00036 
00037 # include <mln/core/concept/value.hh>
00038 # include <mln/value/concept/floating.hh>
00039 # include <mln/trait/value_.hh>
00040 # include <mln/trait/all.hh> // FIXME!
00041 
00042 
00043 
00044 namespace mln
00045 {
00046 
00047   namespace value
00048   {
00049 
00050     // Fwd decl.
00051     template <unsigned n> struct float01_;
00052     class float01;
00053 
00054 
00057     class float01 : public Floating<float01>
00058     {
00059     public:
00060 
00062       typedef std::pair<unsigned, unsigned long> enc;
00063 
00065       typedef float equiv;
00066 
00068       float01();
00069 
00071       template <unsigned n>
00072       float01(const float01_<n>& val);
00073 
00075       float01(unsigned nbits, float val);
00076 
00078       float value() const;
00079 
00081       unsigned long value_ind() const;
00082 
00084       unsigned nbits() const;
00085 
00086 
00088       float01&     set_nbits(unsigned nbits);
00089 
00091       const float01 to_nbits(unsigned nbits) const;
00092 
00094       operator float() const;
00095 
00096 //       template <unsigned n>
00097 //       operator float01_<n>() const;
00098 
00099     protected:
00101       unsigned nbits_;
00102 
00104       unsigned long val_;
00105     };
00106 
00107     std::ostream& operator<<(std::ostream& ostr, const float01& g);
00108 
00109     bool operator==(const float01& lhs, const float01& rhs);
00110     bool operator<(const float01& lhs, const float01& rhs);
00111 
00112 
00113 
00114 # ifndef MLN_INCLUDE_ONLY
00115 
00116     namespace internal
00117     {
00118 
00119       inline
00120       unsigned long two_pow_(unsigned n)
00121       {
00122         if (n == 0)
00123           return 1;
00124         else
00125           return 2 * two_pow_(n - 1);
00126       }
00127 
00128       inline
00129       unsigned long two_pow_n_minus_1(unsigned n)
00130       {
00131           return two_pow_(n) - 1;
00132       }
00133 
00134       template <unsigned n_dest>
00135       inline
00136       unsigned long convert(unsigned n_src, unsigned long val)
00137       {
00138         if (n_dest == n_src)
00139           return val;
00140         else
00141           if (n_dest > n_src)
00142             return val * two_pow_n_minus_1(n_dest) / two_pow_n_minus_1(n_src);
00143           else
00144             return val / two_pow_(n_src - n_dest);
00145       }
00146 
00147     } // end of mln::value::internal
00148 
00149 
00150     // Float01.
00151     inline
00152     float01::float01()
00153       : nbits_(0) // FIXME: Cost at run-time...
00154     {
00155     }
00156 
00157     template <unsigned n>
00158     inline
00159     float01::float01(const float01_<n>& g)
00160       : nbits_(n),
00161         val_(g.to_enc())
00162     {
00163     }
00164 
00165     inline
00166     float01::float01(unsigned nbits, float val)
00167       : nbits_(nbits)
00168     {
00169       val_ = static_cast<unsigned long>(val * float(internal::two_pow_n_minus_1(nbits)));
00170     }
00171 
00172     inline
00173     float float01::value() const
00174     {
00175       mln_invariant(nbits_ != 0);
00176       return float(val_) / float(internal::two_pow_n_minus_1(nbits_));
00177     }
00178 
00179     inline
00180     unsigned long float01::value_ind() const
00181     {
00182       mln_invariant(nbits_ != 0);
00183       return val_;
00184     }
00185 
00186     inline
00187     unsigned float01::nbits() const
00188     {
00189       return nbits_;
00190     }
00191 
00192     inline
00193     float01&
00194     float01::set_nbits(unsigned nbits)
00195     {
00196       mln_precondition(nbits != 0);
00197       mln_invariant(nbits_ != 0);
00198       if (nbits == nbits_)
00199         return *this;
00200       if (nbits > nbits_)
00201         {
00202           val_ *= internal::two_pow_n_minus_1(nbits);
00203           val_ /= internal::two_pow_n_minus_1(nbits_);
00204         }
00205       else // nbits < nbits_
00206         {
00207           val_ /= internal::two_pow_(nbits_ - nbits);
00208         }
00209       nbits_ = nbits;
00210       return *this;
00211     }
00212 
00213     inline
00214     const float01
00215     float01::to_nbits(unsigned nbits) const
00216     {
00217       mln_precondition(nbits != 0);
00218       mln_invariant(nbits_ != 0);
00219       float01 tmp(*this);
00220       tmp.set_nbits(nbits);
00221       return tmp;
00222     }
00223 
00224     inline
00225     float01::operator float() const
00226     {
00227       mln_precondition(nbits_ != 0);
00228       float tmp = float(val_) / float(internal::two_pow_n_minus_1(nbits_));
00229       return tmp;
00230     }
00231 
00232 //     template <unsigned n>
00233 //     float01::operator float01_<n>() const
00234 //     {
00235 //       mln_precondition(nbits_ != 0);
00236 //       float01_<n> tmp;
00237 //       tmp.set_ind(internal::convert<n>(nbits_, val_));
00238 //       mln_assertion(tmp.value() < internal::two_pow_(n));
00239 //       return tmp;
00240 //     }
00241 
00242 
00243     // Operators.
00244 
00245     inline
00246     std::ostream& operator<<(std::ostream& ostr, const float01& g)
00247     {
00248       return ostr << g.value() << '/' << g.nbits() << "nbits";
00249     }
00250 
00251     inline
00252     bool operator==(const float01& lhs, const float01& rhs)
00253     {
00254       mln_precondition(lhs.nbits() != 0 && rhs.nbits() != 0);
00255 
00256       if (rhs.nbits() == lhs.nbits())
00257         return lhs.value_ind() == rhs.value_ind();
00258 
00259       if (lhs.nbits() < rhs.nbits())
00260         return lhs.value_ind() == rhs.to_nbits(lhs.nbits()).value_ind();
00261       else
00262       {
00263         return lhs.to_nbits(rhs.nbits()).value_ind() == rhs.value_ind();
00264       }
00265     }
00266 
00267     inline
00268     bool operator<(const float01& lhs, const float01& rhs)
00269     {
00270       mln_precondition(lhs.nbits() != 0 && rhs.nbits() != 0);
00271       if (rhs.nbits() == lhs.nbits())
00272         return lhs.value() < rhs.value();
00273       if (lhs.nbits() > rhs.nbits())
00274         return lhs.value() < rhs.to_nbits(lhs.nbits()).value();
00275       else
00276         return lhs.to_nbits(rhs.nbits()).value() < rhs.value();
00277     }
00278 
00279 # endif // ! MLN_INCLUDE_ONLY
00280 
00281   } // end of namespace mln::value
00282 
00283 } // end of namespace mln
00284 
00285 # include <mln/value/float01_.hh>
00286 
00287 #endif // ! MLN_VALUE_FLOAT01_HH
 All Classes Namespaces Functions Variables Typedefs Enumerator