00001
00004 #ifndef FIXED_HPP_
00005 #define FIXED_HPP_
00006
00007 #include <cassert>
00008 #include <cmath>
00009 #include <iomanip>
00010 #include <ios>
00011 #include <istream>
00012 #include <locale>
00013 #include <ostream>
00014 #include <sstream>
00015 #include <stdexcept>
00016 #include <string>
00017
00018 #include "ioflags.hpp"
00019
00024 template<class T, int N>
00025 class fixed
00026 {
00027 public:
00028 typedef T value_type;
00029
00030 static value_type const places = N;
00031 static value_type const places10;
00032
00034 fixed() : value_() {}
00035
00039 fixed(value_type integer, value_type fraction);
00040
00042 fixed(value_type integer);
00043
00045 fixed(double value)
00046 : value_(static_cast<value_type>(value * places10 + (value < 0 ? -0.5 : 0.5)))
00047 {}
00048
00051 std::string as_string() const;
00056 template<class Char, class Traits>
00057 bool read(std::basic_istream<Char, Traits>& strm);
00059 double as_long_double() const { return static_cast<long double>(value()) / places10; }
00061 double as_double() const { return static_cast<double>(value()) / places10; }
00063 float as_float() const { return static_cast<float>(value()) / places10; }
00067 value_type round() const;
00068
00070 value_type integer() const { return value() / places10; }
00072 value_type fraction() const;
00073
00075 fixed& operator+=(fixed f);
00077 fixed& operator-=(fixed f);
00079 fixed& operator*=(fixed f);
00081 fixed& operator/=(fixed f);
00082
00084 void negate();
00085
00087 fixed& operator++();
00089 fixed operator++(int);
00091 fixed& operator--();
00093 fixed operator--(int);
00094
00096 value_type value() const { return value_; }
00097 private:
00099 value_type reduce(value_type frac);
00100 value_type value_;
00101 };
00102
00103 template<class T, int N>
00104 typename fixed<T,N>::value_type const fixed<T,N>::places10 = static_cast<typename fixed<T,N>::value_type>(std::pow(10.0, double(places)));
00105
00106
00107 template<class T, int N>
00108 fixed<T,N>::fixed(value_type integer, value_type fraction)
00109 {
00110 if (fraction < T())
00111 throw std::invalid_argument("negative fraction not allowed");
00112 fraction = reduce(fraction);
00113 if (integer < T())
00114 value_ = integer * places10 - fraction;
00115 else
00116 value_ = integer * places10 + fraction;
00117 }
00118
00119
00120 template<class T, int N>
00121 fixed<T,N>::fixed(value_type integer)
00122 : value_(integer * places10)
00123 {}
00124
00125
00126 template<class T, int N>
00127 typename fixed<T,N>::value_type fixed<T,N>::fraction()
00128 const
00129 {
00130 return std::abs(value()) % places10;
00131 }
00132
00142 template<class T, int N>
00143 typename fixed<T,N>::value_type fixed<T,N>::reduce(value_type frac)
00144 {
00145
00146 value_type f(frac);
00147 while (f >= places10*10 and f % 10 == 0)
00148 {
00149 f /= 10;
00150 }
00151
00152 if (f >= places10*10)
00153 {
00154 int x(0);
00155
00156
00157
00158 while (f >= places10)
00159 {
00160 x = f % 10;
00161 f /= 10;
00162 }
00163
00164 if (x >= 5)
00165 ++f;
00166 return f;
00167 }
00168
00169
00170 else if (f >= places10)
00171 {
00172
00173
00174 int x(f % 10);
00175 f /= 10;
00176 assert(f < places10);
00177 if (x == 5)
00178 {
00179
00180 if (f % 2 != 0)
00181 ++f;
00182 return f;
00183 }
00184 else if (x < 5)
00185 {
00186
00187 return f;
00188 }
00189 else
00190 {
00191
00192 return f + 1;
00193 }
00194 }
00195
00196 assert(frac < places10);
00197 return frac;
00198 }
00199
00200
00201 template<class T, int N>
00202 typename fixed<T,N>::value_type fixed<T,N>::round()
00203 const
00204 {
00205 const value_type frac(fraction());
00206 int adjust(value() < 0 ? -1 : +1);
00207 if (frac > places10/2)
00208 return integer()+adjust;
00209 else if (frac < places10/2)
00210 return integer();
00211 else if (integer() % 2 == 0)
00212 return integer();
00213 else
00214 return integer()+adjust;
00215 }
00216
00217
00218 template<class T, int N>
00219 std::string fixed<T,N>::as_string()
00220 const
00221 {
00222 std::ostringstream out;
00223 out << integer() << '.'
00224 << std::setfill('0') << std::setw(places) << fraction();
00225 return out.str();
00226 }
00227
00228 template<class T, int N>
00229 fixed<T,N>& fixed<T,N>::operator+=(fixed f)
00230 {
00231 value_ += f.value();
00232 return *this;
00233 }
00234
00235 template<class T, int N>
00236 fixed<T,N>& fixed<T,N>::operator-=(fixed f)
00237 {
00238 value_ -= f.value();
00239 return *this;
00240 }
00241
00242 template<class T, int N>
00243 fixed<T,N>& fixed<T,N>::operator*=(fixed f)
00244 {
00245 value_ = (value_ * f.value()) / places10;
00246 return *this;
00247 }
00248
00249 template<class T, int N>
00250 fixed<T,N>& fixed<T,N>::operator/=(fixed f)
00251 {
00252 value_ = (value_ * places10) / f.value();
00253 return *this;
00254 }
00255
00256 template<class T, int N>
00257 void fixed<T,N>::negate()
00258 {
00259 value_ = -value_;
00260 }
00261
00262 template<class T, int N>
00263 fixed<T,N>& fixed<T,N>::operator++()
00264 {
00265 value_ += places10;
00266 return *this;
00267 }
00268
00269 template<class T, int N>
00270 fixed<T,N> fixed<T,N>::operator++(int)
00271 {
00272 fixed result(*this);
00273 ++*this;
00274 return result;
00275 }
00276
00277 template<class T, int N>
00278 fixed<T,N>& fixed<T,N>::operator--()
00279 {
00280 value_ -= places10;
00281 return *this;
00282 }
00283
00284 template<class T, int N>
00285 fixed<T,N> fixed<T,N>::operator--(int)
00286 {
00287 fixed result(*this);
00288 --*this;
00289 return result;
00290 }
00291
00292 template<class T, int N>
00293 template<class Char, class Traits>
00294 bool fixed<T,N>::read(std::basic_istream<Char, Traits>& strm)
00295 {
00296 ioflags flags(strm);
00297
00298 value_type integer;
00299 char decimal;
00300 if (not (strm >> integer))
00301 return false;
00302 strm.unsetf(std::ios_base::skipws);
00303 if (not (strm >> decimal) or decimal != '.')
00304 {
00305
00306
00307
00308 strm.unget();
00309 strm.clear(strm.rdstate() & ~strm.failbit);
00310 value_ = integer * places10;
00311 return true;
00312 }
00313 else
00314 {
00315 value_type fraction(0);
00316 char c;
00317 int p(0);
00318
00319 for (;
00320 p != places+1 and strm >> c and std::isdigit(c, strm.getloc());
00321 ++p)
00322 {
00323 fraction = fraction * 10 + (c - '0');
00324 }
00325
00326 for (; p < places; ++p)
00327 fraction = fraction * 10;
00328
00329
00330 while (strm and std::isdigit(c, strm.getloc()))
00331 strm >> c;
00332
00333
00334 strm.unget();
00335
00336
00337 strm.clear(strm.rdstate() & ~strm.failbit);
00338 fraction = reduce(fraction);
00339 if (integer < 0)
00340 value_ = integer * places10 - fraction;
00341 else
00342 value_ = integer * places10 + fraction;
00343 }
00344 return true;
00345 }
00346
00348 template<class T, int N, class Char, class Traits>
00349 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& strm, fixed<T,N>& f)
00350 {
00351 if (not f.read(strm))
00352 strm.setstate(strm.failbit);
00353 return strm;
00354 }
00355
00357 template<class T, int N, class Char, class Traits>
00358 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& strm, fixed<T,N> f)
00359 {
00360 strm << f.as_string();
00361 return strm;
00362 }
00363
00365 template<class T, int N>
00366 fixed<T,N> operator+(fixed<T,N> a, fixed<T,N> b)
00367 {
00368 a += b;
00369 return a;
00370 }
00371
00373 template<class T, int N>
00374 fixed<T,N> operator-(fixed<T,N> a, fixed<T,N> b)
00375 {
00376 a -= b;
00377 return a;
00378 }
00379
00381 template<class T, int N>
00382 fixed<T,N> operator*(fixed<T,N> a, fixed<T,N> b)
00383 {
00384 a *= b;
00385 return a;
00386 }
00387
00389 template<class T, int N>
00390 fixed<T,N> operator/(fixed<T,N> a, fixed<T,N> b)
00391 {
00392 a /= b;
00393 return a;
00394 }
00395
00397 template<class T, int N>
00398 fixed<T,N> operator-(fixed<T,N> a)
00399 {
00400 a.negate();
00401 return a;
00402 }
00403
00405 template<class T, int N>
00406 bool operator==(fixed<T,N> a, fixed<T,N> b)
00407 {
00408 return a.value() == b.value();
00409 }
00411 template<class T, int N>
00412 bool operator==(T a, fixed<T,N> b)
00413 {
00414 return a == b.value();
00415 }
00417 template<class T, int N>
00418 bool operator==(fixed<T,N> a, T b)
00419 {
00420 return a.value() == b;
00421 }
00422
00424 template<class T, int N>
00425 bool operator!=(fixed<T,N> a, fixed<T,N> b)
00426 {
00427 return not (a == b);
00428 }
00430 template<class T, int N>
00431 bool operator!=(T a, fixed<T,N> b)
00432 {
00433 return not (a == b);
00434 }
00436 template<class T, int N>
00437 bool operator!=(fixed<T,N> a, T b)
00438 {
00439 return not (a == b);
00440 }
00441
00443 template<class T, int N>
00444 bool operator<(fixed<T,N> a, fixed<T,N> b)
00445 {
00446 return a.value() < b.value();
00447 }
00449 template<class T, int N>
00450 bool operator<(T a, fixed<T,N> b)
00451 {
00452 return a < b.value();
00453 }
00455 template<class T, int N>
00456 bool operator<(fixed<T,N> a, T b)
00457 {
00458 return a.value() < b;
00459 }
00460
00462 template<class T, int N>
00463 bool operator>(fixed<T,N> a, fixed<T,N> b)
00464 {
00465 return b < a;
00466 }
00468 template<class T, int N>
00469 bool operator>(T a, fixed<T,N> b)
00470 {
00471 return b < a;
00472 }
00474 template<class T, int N>
00475 bool operator>(fixed<T,N> a, T b)
00476 {
00477 return b < a;
00478 }
00479
00481 template<class T, int N>
00482 bool operator<=(fixed<T,N> a, fixed<T,N> b)
00483 {
00484 return not (b < a);
00485 }
00487 template<class T, int N>
00488 bool operator<=(T a, fixed<T,N> b)
00489 {
00490 return not (b < a);
00491 }
00493 template<class T, int N>
00494 bool operator<=(fixed<T,N> a, T b)
00495 {
00496 return not (b < a);
00497 }
00498
00500 template<class T, int N>
00501 bool operator>=(fixed<T,N> a, fixed<T,N> b)
00502 {
00503 return not (a < b);
00504 }
00506 template<class T, int N>
00507 bool operator>=(T a, fixed<T,N> b)
00508 {
00509 return not (a < b);
00510 }
00512 template<class T, int N>
00513 bool operator>=(fixed<T,N> a, T b)
00514 {
00515 return not (a < b);
00516 }
00517
00518 #endif