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 #include "power10.hpp"
00020
00025 template<class T, int N>
00026 class fixed
00027 {
00028 public:
00029 typedef T value_type;
00030
00031 static value_type const places = N;
00032 static value_type const places10 = power10<N>::value;
00033
00035 fixed() : value_() {}
00036
00042 fixed(value_type integer, value_type fraction);
00043
00046 fixed(value_type integer);
00047
00050 fixed(double value)
00051 : value_(static_cast<value_type>(value * places10 + (value < 0 ? -0.5 : 0.5)))
00052 {}
00053
00056 std::string as_string() const;
00061 template<class Char, class Traits>
00062 bool read(std::basic_istream<Char, Traits>& strm);
00064 double as_long_double() const { return static_cast<long double>(value()) / places10; }
00066 double as_double() const { return static_cast<double>(value()) / places10; }
00068 float as_float() const { return static_cast<float>(value()) / places10; }
00072 value_type round() const;
00073
00075 value_type integer() const { return value() / places10; }
00077 value_type fraction() const;
00078
00081 fixed& operator+=(fixed f);
00084 fixed& operator-=(fixed f);
00087 fixed& operator*=(fixed f);
00090 fixed& operator*=(value_type v);
00093 fixed& operator/=(fixed f);
00096 fixed& operator/=(value_type v);
00097
00099 void negate();
00100
00102 fixed& operator++();
00104 fixed operator++(int);
00106 fixed& operator--();
00108 fixed operator--(int);
00109
00111 value_type value() const { return value_; }
00112 private:
00114 value_type reduce(value_type frac);
00115 value_type value_;
00116 };
00117
00118
00119 template<class T, int N>
00120 fixed<T,N>::fixed(value_type integer, value_type fraction)
00121 {
00122 if (fraction < T())
00123 throw std::invalid_argument("negative fraction not allowed");
00124 fraction = reduce(fraction);
00125 if (integer < T())
00126 value_ = integer * places10 - fraction;
00127 else
00128 value_ = integer * places10 + fraction;
00129 }
00130
00131
00132 template<class T, int N>
00133 fixed<T,N>::fixed(value_type integer)
00134 : value_(integer * places10)
00135 {}
00136
00137
00138 template<class T, int N>
00139 typename fixed<T,N>::value_type fixed<T,N>::fraction()
00140 const
00141 {
00142 return std::abs(value()) % places10;
00143 }
00144
00154 template<class T, int N>
00155 typename fixed<T,N>::value_type fixed<T,N>::reduce(value_type frac)
00156 {
00157
00158 value_type f(frac);
00159 while (f >= places10*10 and f % 10 == 0)
00160 {
00161 f /= 10;
00162 }
00163
00164 if (f >= places10*10)
00165 {
00166 int x(0);
00167
00168
00169
00170 while (f >= places10)
00171 {
00172 x = f % 10;
00173 f /= 10;
00174 }
00175
00176 if (x >= 5)
00177 ++f;
00178 return f;
00179 }
00180
00181
00182 else if (f >= places10)
00183 {
00184
00185
00186 int x(f % 10);
00187 f /= 10;
00188 assert(f < places10);
00189 if (x == 5)
00190 {
00191
00192 if (f % 2 != 0)
00193 ++f;
00194 return f;
00195 }
00196 else if (x < 5)
00197 {
00198
00199 return f;
00200 }
00201 else
00202 {
00203
00204 return f + 1;
00205 }
00206 }
00207
00208 assert(frac < places10);
00209 return frac;
00210 }
00211
00212
00213 template<class T, int N>
00214 typename fixed<T,N>::value_type fixed<T,N>::round()
00215 const
00216 {
00217 const value_type frac(fraction());
00218 int adjust(value() < 0 ? -1 : +1);
00219 if (frac > places10/2)
00220 return integer()+adjust;
00221 else if (frac < places10/2)
00222 return integer();
00223 else if (integer() % 2 == 0)
00224 return integer();
00225 else
00226 return integer()+adjust;
00227 }
00228
00229
00230 template<class T, int N>
00231 std::string fixed<T,N>::as_string()
00232 const
00233 {
00234 std::ostringstream out;
00235 out << integer() << '.'
00236 << std::setfill('0') << std::setw(places) << fraction();
00237 return out.str();
00238 }
00239
00240 template<class T, int N>
00241 fixed<T,N>& fixed<T,N>::operator+=(fixed f)
00242 {
00243 value_ += f.value();
00244 return *this;
00245 }
00246
00247 template<class T, int N>
00248 fixed<T,N>& fixed<T,N>::operator-=(fixed f)
00249 {
00250 value_ -= f.value();
00251 return *this;
00252 }
00253
00254 template<class T, int N>
00255 fixed<T,N>& fixed<T,N>::operator*=(fixed f)
00256 {
00257 value_ = (value_ * f.value()) / places10;
00258 return *this;
00259 }
00260
00261 template<class T, int N>
00262 fixed<T,N>& fixed<T,N>::operator*=(value_type v)
00263 {
00264 value_ *= v;
00265 return *this;
00266 }
00267
00268 template<class T, int N>
00269 fixed<T,N>& fixed<T,N>::operator/=(fixed f)
00270 {
00271 value_ = (value_ * places10) / f.value();
00272 return *this;
00273 }
00274
00275 template<class T, int N>
00276 fixed<T,N>& fixed<T,N>::operator/=(value_type v)
00277 {
00278 value_ /= v;
00279 return *this;
00280 }
00281
00282 template<class T, int N>
00283 void fixed<T,N>::negate()
00284 {
00285 value_ = -value_;
00286 }
00287
00288 template<class T, int N>
00289 fixed<T,N>& fixed<T,N>::operator++()
00290 {
00291 value_ += places10;
00292 return *this;
00293 }
00294
00295 template<class T, int N>
00296 fixed<T,N> fixed<T,N>::operator++(int)
00297 {
00298 fixed result(*this);
00299 ++*this;
00300 return result;
00301 }
00302
00303 template<class T, int N>
00304 fixed<T,N>& fixed<T,N>::operator--()
00305 {
00306 value_ -= places10;
00307 return *this;
00308 }
00309
00310 template<class T, int N>
00311 fixed<T,N> fixed<T,N>::operator--(int)
00312 {
00313 fixed result(*this);
00314 --*this;
00315 return result;
00316 }
00317
00318 template<class T, int N>
00319 template<class Char, class Traits>
00320 bool fixed<T,N>::read(std::basic_istream<Char, Traits>& strm)
00321 {
00322 ioflags flags(strm);
00323
00324 value_type integer;
00325 char decimal;
00326 if (not (strm >> integer))
00327 return false;
00328 strm.unsetf(std::ios_base::skipws);
00329 if (not (strm >> decimal) or decimal != '.')
00330 {
00331
00332
00333
00334 strm.unget();
00335 strm.clear(strm.rdstate() & ~strm.failbit);
00336 value_ = integer * places10;
00337 return true;
00338 }
00339 else
00340 {
00341 value_type fraction(0);
00342 char c;
00343 int p(0);
00344
00345 for (;
00346 p != places+1 and strm >> c and std::isdigit(c, strm.getloc());
00347 ++p)
00348 {
00349 fraction = fraction * 10 + (c - '0');
00350 }
00351
00352 for (; p < places; ++p)
00353 fraction = fraction * 10;
00354
00355
00356 while (strm and std::isdigit(c, strm.getloc()))
00357 strm >> c;
00358
00359
00360 strm.unget();
00361
00362
00363 strm.clear(strm.rdstate() & ~strm.failbit);
00364 fraction = reduce(fraction);
00365 if (integer < 0)
00366 value_ = integer * places10 - fraction;
00367 else
00368 value_ = integer * places10 + fraction;
00369 }
00370 return true;
00371 }
00372
00376 template<class T, int N, class Char, class Traits>
00377 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& strm, fixed<T,N>& f)
00378 {
00379 if (not f.read(strm))
00380 strm.setstate(strm.failbit);
00381 return strm;
00382 }
00383
00387 template<class T, int N, class Char, class Traits>
00388 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& strm, fixed<T,N> f)
00389 {
00390 strm << f.as_string();
00391 return strm;
00392 }
00393
00397 template<class T, int N>
00398 fixed<T,N> operator+(fixed<T,N> a, fixed<T,N> b)
00399 {
00400 a += b;
00401 return a;
00402 }
00403
00407 template<class T, int N>
00408 fixed<T,N> operator+(fixed<T,N> a, T b)
00409 {
00410 a += fixed<T,N>(b);
00411 return a;
00412 }
00413
00417 template<class T, int N>
00418 fixed<T,N> operator+(T a, fixed<T,N> b)
00419 {
00420 b += a;
00421 return b;
00422 }
00423
00427 template<class T, int N>
00428 fixed<T,N> operator-(fixed<T,N> a, fixed<T,N> b)
00429 {
00430 a -= b;
00431 return a;
00432 }
00433
00437 template<class T, int N>
00438 fixed<T,N> operator-(fixed<T,N> a, T b)
00439 {
00440 a -= fixed<T,N>(b);
00441 return a;
00442 }
00443
00447 template<class T, int N>
00448 fixed<T,N> operator-(T a, fixed<T,N> b)
00449 {
00450 b += -a;
00451 return -b;
00452 }
00453
00457 template<class T, int N>
00458 fixed<T,N> operator*(fixed<T,N> a, fixed<T,N> b)
00459 {
00460 a *= b;
00461 return a;
00462 }
00463
00467 template<class T, int N>
00468 fixed<T,N> operator*(fixed<T,N> a, T b)
00469 {
00470 a *= b;
00471 return a;
00472 }
00473
00477 template<class T, int N>
00478 fixed<T,N> operator*(T a, fixed<T,N> b)
00479 {
00480 b *= a;
00481 return b;
00482 }
00483
00487 template<class T, int N>
00488 fixed<T,N> operator/(fixed<T,N> a, fixed<T,N> b)
00489 {
00490 a /= b;
00491 return a;
00492 }
00493
00497 template<class T, int N>
00498 fixed<T,N> operator/(fixed<T,N> a, T b)
00499 {
00500 a /= b;
00501 return a;
00502 }
00503
00507 template<class T, int N>
00508 fixed<T,N> operator/(T a, fixed<T,N> b)
00509 {
00510 fixed<T,N> tmp(a);
00511 tmp /= b;
00512 return tmp;
00513 }
00514
00517 template<class T, int N>
00518 fixed<T,N> operator-(fixed<T,N> a)
00519 {
00520 a.negate();
00521 return a;
00522 }
00523
00527 template<class T, int N>
00528 bool operator==(fixed<T,N> a, fixed<T,N> b)
00529 {
00530 return a.value() == b.value();
00531 }
00535 template<class T, int N>
00536 bool operator==(T a, fixed<T,N> b)
00537 {
00538 return a == b.value();
00539 }
00543 template<class T, int N>
00544 bool operator==(fixed<T,N> a, T b)
00545 {
00546 return a.value() == b;
00547 }
00548
00552 template<class T, int N>
00553 bool operator!=(fixed<T,N> a, fixed<T,N> b)
00554 {
00555 return not (a == b);
00556 }
00560 template<class T, int N>
00561 bool operator!=(T a, fixed<T,N> b)
00562 {
00563 return not (a == b);
00564 }
00568 template<class T, int N>
00569 bool operator!=(fixed<T,N> a, T b)
00570 {
00571 return not (a == b);
00572 }
00573
00577 template<class T, int N>
00578 bool operator<(fixed<T,N> a, fixed<T,N> b)
00579 {
00580 return a.value() < b.value();
00581 }
00585 template<class T, int N>
00586 bool operator<(T a, fixed<T,N> b)
00587 {
00588 return a < b.value();
00589 }
00593 template<class T, int N>
00594 bool operator<(fixed<T,N> a, T b)
00595 {
00596 return a.value() < b;
00597 }
00598
00602 template<class T, int N>
00603 bool operator>(fixed<T,N> a, fixed<T,N> b)
00604 {
00605 return b < a;
00606 }
00610 template<class T, int N>
00611 bool operator>(T a, fixed<T,N> b)
00612 {
00613 return b < a;
00614 }
00618 template<class T, int N>
00619 bool operator>(fixed<T,N> a, T b)
00620 {
00621 return b < a;
00622 }
00623
00627 template<class T, int N>
00628 bool operator<=(fixed<T,N> a, fixed<T,N> b)
00629 {
00630 return not (b < a);
00631 }
00635 template<class T, int N>
00636 bool operator<=(T a, fixed<T,N> b)
00637 {
00638 return not (b < a);
00639 }
00643 template<class T, int N>
00644 bool operator<=(fixed<T,N> a, T b)
00645 {
00646 return not (b < a);
00647 }
00648
00652 template<class T, int N>
00653 bool operator>=(fixed<T,N> a, fixed<T,N> b)
00654 {
00655 return not (a < b);
00656 }
00660 template<class T, int N>
00661 bool operator>=(T a, fixed<T,N> b)
00662 {
00663 return not (a < b);
00664 }
00668 template<class T, int N>
00669 bool operator>=(fixed<T,N> a, T b)
00670 {
00671 return not (a < b);
00672 }
00673
00674 #endif