Milena (Olena)
User documentation 2.0a Id
|
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