00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #ifndef LASS_GUARDIAN_OF_INCLUSION_NUM_FILTERED_FLOAT_H
00045 #define LASS_GUARDIAN_OF_INCLUSION_NUM_FILTERED_FLOAT_H
00046
00047 #include "num_common.h"
00048 #include "../util/call_traits.h"
00049 #include <complex>
00050
00051 namespace lass
00052 {
00053 namespace num
00054 {
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 template <typename T>
00072 class FilteredFloat
00073 {
00074 public:
00075 typedef FilteredFloat< T > TSelf;
00076 typedef typename util::CallTraits<T>::TValue TValue;
00077 typedef typename util::CallTraits<T>::TParam TParam;
00078 typedef typename util::CallTraits<T>::TReference TReference;
00079 typedef typename util::CallTraits<T>::TConstReference TConstReference;
00080 typedef num::NumTraits< T > TNumTraits;
00081
00082 FilteredFloat() : t_()
00083 {
00084 }
00085
00086 FilteredFloat(TParam t):
00087 t_(t), e_(TNumTraits::epsilon*t)
00088 {
00089 }
00090
00091 explicit FilteredFloat(TParam t, TParam e):
00092 t_(t), e_(e)
00093 {
00094 }
00095
00096
00097 FilteredFloat(const TSelf& other):
00098 t_(other.t_), e_(other.e_)
00099 {
00100 }
00101
00102 TParam value() const
00103 {
00104 return t_;
00105 }
00106
00107 TParam error() const
00108 {
00109 return e_;
00110 }
00111
00112 TSelf operator-() const
00113 {
00114 return TSelf(-t_,-e_);
00115 }
00116
00117 TSelf operator+() const
00118 {
00119 return *this;
00120 }
00121
00122 TSelf& operator+=(const TSelf& other)
00123 {
00124 T x = t_ + other.t_;
00125 T bv = x-t_;
00126 T av = x-bv;
00127 T br = other.t_-bv;
00128 T ar = t_-av;
00129 t_ = x;
00130 e_ = ar+br;
00131 LASS_ENFORCE(lass::num::abs(t_)>=lass::num::abs(e_));
00132 return *this;
00133 }
00134 TSelf& operator-=(const TSelf& other)
00135 {
00136 T x = t_ - other.t_;
00137 T bv = t_-x;
00138 T av = x+bv;
00139 T br = bv-other.t_;
00140 T ar = t_-av;
00141 t_ = x;
00142 e_ = ar+br;
00143 LASS_ENFORCE(lass::num::abs(t_)>=lass::num::abs(e_));
00144 return *this;
00145 }
00146 TSelf& operator*=(const TSelf& other)
00147 {
00148 T x = t_ * other.t_;
00149 TSelf a = split(t_,(TNumTraits::mantisseSize+1)/2);
00150 TSelf b = split(other.t_,(TNumTraits::mantisseSize+1)/2);
00151 T err1 = x-(a.t_*b.t_);
00152 T err2 = err1-(a.e_*b.t_);
00153 T err3 = err2-(a.t_*b.e_);
00154 T y = (a.e_*b.e_)-err3;
00155 t_ = x;
00156 e_ = y;
00157 LASS_ENFORCE(lass::num::abs(t_)>=lass::num::abs(e_));
00158 return *this;
00159 }
00160 TSelf& operator/=(const TSelf& other)
00161 {
00162 #pragma LASS_TODO("We need to rederive the forward error for this operation!")
00163 TSelf newOther(T(1)/other.value(),0.0);
00164 this->operator *=(newOther);
00165 LASS_ENFORCE(lass::num::abs(t_)>=lass::num::abs(e_));
00166 return *this;
00167 }
00168
00169 void swap(TSelf& other)
00170 {
00171 std::swap(t_, other.t_);
00172 std::swap(e_, other.e_);
00173 }
00174
00175 private:
00176 volatile TValue t_,
00177 e_;
00178
00179 TSelf split(TParam a, int s)
00180 {
00181 static const T f = float((2<<s) + 1);
00182 T c = f*a;
00183 T abig = c-a;
00184 T ahi = c-abig;
00185 T alo = a-ahi;
00186 return TSelf(ahi,alo);
00187 }
00188 };
00189
00190
00191
00192 template <typename T> inline
00193 FilteredFloat<T> operator+(const FilteredFloat<T>& a, const FilteredFloat<T>& b)
00194 {
00195 FilteredFloat<T> result(a);
00196 result += b;
00197 return result;
00198 }
00199
00200 template <typename T> inline
00201 FilteredFloat<T> operator-(const FilteredFloat<T>& a, const FilteredFloat<T>& b)
00202 {
00203 FilteredFloat<T> result(a);
00204 result -= b;
00205 return result;
00206 }
00207
00208 template <typename T> inline
00209 FilteredFloat<T> operator*(const FilteredFloat<T>& a, const FilteredFloat<T>& b)
00210 {
00211 FilteredFloat<T> result(a);
00212 result *= b;
00213 return result;
00214 }
00215
00216 template <typename T> inline
00217 FilteredFloat<T> operator/(const FilteredFloat<T>& a, const FilteredFloat<T>& b)
00218 {
00219 FilteredFloat<T> result(a);
00220 result /= b;
00221 return result;
00222 }
00223
00224 template <typename T> inline
00225 bool operator==(const FilteredFloat<T>& a, const FilteredFloat<T>& b)
00226 {
00227 return (a.value() == b.value() && a.error() == b.error());
00228 }
00229
00230 template <typename T> inline
00231 bool operator!=(const FilteredFloat<T>& a, const FilteredFloat<T>& b)
00232 {
00233 return !(a == b);
00234 }
00235
00236 template <typename T> inline
00237 bool operator<(const FilteredFloat<T>& a, const FilteredFloat<T>& b)
00238 {
00239
00240 LASS_ENFORCE( (a.value()+b.error() < b.value()-a.error()) == (a.value()<b.value()));
00241 return a.value()<b.value();
00242
00243
00244
00245
00246
00247
00248
00249 }
00250
00251 template <typename T> inline
00252 bool operator>(const FilteredFloat<T>& a, const FilteredFloat<T>& b)
00253 {
00254 return b < a;
00255 }
00256
00257 template <typename T> inline
00258 bool operator<=(const FilteredFloat<T>& a, const FilteredFloat<T>& b)
00259 {
00260 return !(b < a);
00261 }
00262
00263 template <typename T> inline
00264 bool operator>=(const FilteredFloat<T>& a, const FilteredFloat<T>& b)
00265 {
00266 return !(a < b);
00267 }
00268
00269
00270
00271
00272 template <typename T> inline
00273 FilteredFloat<T> operator+(const FilteredFloat<T>& a, const T& b)
00274 {
00275 FilteredFloat<T> result(a);
00276 result += b;
00277 return result;
00278 }
00279
00280 template <typename T> inline
00281 FilteredFloat<T> operator-(const FilteredFloat<T>& a, const T& b)
00282 {
00283 FilteredFloat<T> result(a);
00284 result -= b;
00285 return result;
00286 }
00287
00288 template <typename T> inline
00289 FilteredFloat<T> operator*(const FilteredFloat<T>& a, const T& b)
00290 {
00291 FilteredFloat<T> result(a);
00292 result *= b;
00293 return result;
00294 }
00295
00296 template <typename T> inline
00297 FilteredFloat<T> operator/(const FilteredFloat<T>& a, const T& b)
00298 {
00299 FilteredFloat<T> result(a);
00300 result /= b;
00301 return result;
00302 }
00303
00304 template <typename T> inline
00305 bool operator==(const FilteredFloat<T>& a, const T& b)
00306 {
00307 return a == FilteredFloat<T>(b);
00308 }
00309
00310 template <typename T> inline
00311 bool operator!=(const FilteredFloat<T>& a, const T& b)
00312 {
00313 return !(a == b);
00314 }
00315
00316 template <typename T> inline
00317 bool operator<(const FilteredFloat<T>& a, const T& b)
00318 {
00319 return a < FilteredFloat<T>(b);
00320 }
00321
00322 template <typename T> inline
00323 bool operator>(const FilteredFloat<T>& a, const T& b)
00324 {
00325 return b < a;
00326 }
00327
00328 template <typename T> inline
00329 bool operator<=(const FilteredFloat<T>& a, const T& b)
00330 {
00331 return !(b < a);
00332 }
00333
00334 template <typename T> inline
00335 bool operator>=(const FilteredFloat<T>& a, const T& b)
00336 {
00337 return !(a < b);
00338 }
00339
00340
00341
00342
00343 template <typename T> inline
00344 FilteredFloat<T> operator+(const T& a, const FilteredFloat<T>& b)
00345 {
00346 FilteredFloat<T> result(a);
00347 result += b;
00348 return result;
00349 }
00350
00351 template <typename T> inline
00352 FilteredFloat<T> operator-(const T& a, const FilteredFloat<T>& b)
00353 {
00354 FilteredFloat<T> result(a);
00355 result -= b;
00356 return result;
00357 }
00358
00359 template <typename T> inline
00360 FilteredFloat<T> operator*(const T& a, const FilteredFloat<T>& b)
00361 {
00362 FilteredFloat<T> result(a);
00363 result *= b;
00364 return result;
00365 }
00366
00367 template <typename T> inline
00368 FilteredFloat<T> operator/(const T& a, const FilteredFloat<T>& b)
00369 {
00370 FilteredFloat<T> result(a);
00371 result /= b;
00372 return result;
00373 }
00374
00375 template <typename T> inline
00376 bool operator==(const T& a, const FilteredFloat<T>& b)
00377 {
00378 return FilteredFloat<T>(a) == b;
00379 }
00380
00381 template <typename T> inline
00382 bool operator!=(const T& a, const FilteredFloat<T>& b)
00383 {
00384 return !(a == b);
00385 }
00386
00387 template <typename T> inline
00388 bool operator<(const T& a, const FilteredFloat<T>& b)
00389 {
00390 return FilteredFloat<T>(a) < b;
00391 }
00392
00393 template <typename T> inline
00394 bool operator>(const T& a, const FilteredFloat<T>& b)
00395 {
00396 return b < a;
00397 }
00398
00399 template <typename T> inline
00400 bool operator<=(const T& a, const FilteredFloat<T>& b)
00401 {
00402 return !(b < a);
00403 }
00404
00405 template <typename T> inline
00406 bool operator>=(const T& a, const FilteredFloat<T>& b)
00407 {
00408 return !(a < b);
00409 }
00410
00411
00412
00413
00414
00415 template <typename T> inline
00416 FilteredFloat<T> abs(const FilteredFloat<T>& v)
00417 {
00418 return num::abs(v.value());
00419 }
00420
00421 template <typename T> inline
00422 FilteredFloat<T> inv(const FilteredFloat<T>& v)
00423 {
00424 return num::inv(v.value());
00425 }
00426
00427 template <typename T> inline
00428 FilteredFloat<T> sqrt(const FilteredFloat<T>& v)
00429 {
00430 return num::sqrt(v.value());
00431 }
00432
00433 template <typename T> inline
00434 FilteredFloat<T> pow(const FilteredFloat<T>& v, const FilteredFloat<T>& p)
00435 {
00436 return num::pow(v.value(), p.value());
00437 }
00438
00439 template <typename T> inline
00440 FilteredFloat<T> exp(const FilteredFloat<T>& v)
00441 {
00442 return num::exp(v.value());
00443 }
00444
00445 template <typename T> inline
00446 FilteredFloat<T> log(const FilteredFloat<T>& v)
00447 {
00448 return num::log(v.value());
00449 }
00450
00451 template <typename T> inline
00452 FilteredFloat<T> cos(const FilteredFloat<T>& v)
00453 {
00454 return num::cos(v.value());
00455 }
00456
00457 template <typename T> inline
00458 FilteredFloat<T> sin(const FilteredFloat<T>& v)
00459 {
00460 return num::sin(v.value());
00461 }
00462
00463 template <typename T> inline
00464 FilteredFloat<T> tan(const FilteredFloat<T>& v)
00465 {
00466 return num::tan(v.value());
00467 }
00468
00469 template <typename T> inline
00470 FilteredFloat<T> acos(const FilteredFloat<T>& v)
00471 {
00472 return num::acos(v.value());
00473 }
00474
00475 template <typename T> inline
00476 FilteredFloat<T> asin(const FilteredFloat<T>& v)
00477 {
00478 return num::asin(v.value());
00479 }
00480
00481 template <typename T> inline
00482 FilteredFloat<T> atan(const FilteredFloat<T>& v)
00483 {
00484 return num::atan(v.value());
00485 }
00486
00487 template <typename T> inline
00488 FilteredFloat<T> atan2(const FilteredFloat<T>& y, const FilteredFloat<T>& x)
00489 {
00490 return num::atan2(y.value(), x.value());
00491 }
00492
00493 template <typename T> inline
00494 FilteredFloat<T> floor(const FilteredFloat<T>& v)
00495 {
00496 return num::floor(v.value());
00497 }
00498
00499 template <typename T> inline
00500 FilteredFloat<T> ceil(const FilteredFloat<T>& v)
00501 {
00502 return num::ceil(v.value());
00503 }
00504
00505 template <typename T> inline
00506 FilteredFloat<T> round(const FilteredFloat<T>& v)
00507 {
00508 return num::round(v.value());
00509 }
00510
00511 template <typename T> inline
00512 FilteredFloat<T> fractional(const FilteredFloat<T>& v)
00513 {
00514 return num::fractional(v.value());
00515 }
00516
00517 template <typename T> inline
00518 FilteredFloat<T> div(const FilteredFloat<T>& v, const FilteredFloat<T>& m)
00519 {
00520 return num::div(v.value(), m.value());
00521 }
00522
00523 template <typename T> inline
00524 FilteredFloat<T> mod(const FilteredFloat<T>& v, const FilteredFloat<T>& m)
00525 {
00526 return num::mod(v.value(), m.value());
00527 }
00528
00529
00530 #define LASS_NUM_FILTERED_FLOAT_DECLARE_NUMTRAITS(type)\
00531 template <>\
00532 struct NumTraits< FilteredFloat< type > >\
00533 {\
00534 private:\
00535 typedef NumTraits< type > TBaseTraits;\
00536 public:\
00537 typedef FilteredFloat< type > selfType;\
00538 typedef type baseType;\
00539 typedef type intervalType;\
00540 enum\
00541 {\
00542 isDistribution = TBaseTraits::isDistribution,\
00543 isIntegral = TBaseTraits::isIntegral,\
00544 isNative = false,\
00545 isSigned = TBaseTraits::isSigned,\
00546 hasInfinity = TBaseTraits::hasInfinity,\
00547 hasNaN = TBaseTraits::hasNaN\
00548 };\
00549 static const int memorySize;\
00550 static const std::string name() { return "FilteredFloat<" + TBaseTraits::name() + ">" ; }\
00551 static const selfType one;\
00552 static const selfType zero;\
00553 static const selfType sNaN;\
00554 static const selfType qNaN;\
00555 static const selfType epsilon;\
00556 static const selfType infinity;\
00557 static const selfType min;\
00558 static const selfType max;\
00559 static const selfType minStrictPositive;\
00560 static const selfType pi;\
00561 static const selfType e;\
00562 static const selfType sqrt2;\
00563 static const selfType sqrtPi;\
00564 };
00565
00566 LASS_NUM_FILTERED_FLOAT_DECLARE_NUMTRAITS(float)
00567 LASS_NUM_FILTERED_FLOAT_DECLARE_NUMTRAITS(double)
00568 LASS_NUM_FILTERED_FLOAT_DECLARE_NUMTRAITS(long double)
00569
00570 template<class T> inline
00571 bool isNaN( const FilteredFloat<T>& v )
00572 {
00573 return num::isNaN(v.value());
00574 }
00575
00576 template <typename T, typename Char, typename Traits>
00577 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& s, const FilteredFloat<T>& v)
00578 {
00579 s << v.value();
00580 return s;
00581 }
00582
00583 template <typename T, typename Char, typename Traits>
00584 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& s, FilteredFloat<T>& v)
00585 {
00586 T temp;
00587 s >> temp;
00588 v = FilteredFloat<T>(temp);
00589 return s;
00590 }
00591
00592 }
00593
00594 }
00595
00596 namespace std
00597 {
00598
00599 template <typename T>
00600 void swap(::lass::num::FilteredFloat<T>& a, ::lass::num::FilteredFloat<T>& b)
00601 {
00602 a.swap(b);
00603 }
00604
00605 }
00606
00607 #endif