library of assembled shared sources

http://lass.cocamware.com

filtered_float.h

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
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 /** @class lass::num::FilteredFloat
00057  *  @brief a float with error analysis on it's basic operations.
00058  *  @author Tom De Muer [TDM]
00059  *
00060  *  For more information we refer to the work of Shewchuck, Fortune, Van Wijck on forward
00061  *  error analysis.
00062  *
00063  *  @arg J. R. Shewchuk 1997, "Adaptive Precision Floating-Point Arithmetic and Fast Robust 
00064  *  Geometric Predicates", Discrete & Computational Geometry, 18(3), 305--363
00065  *
00066  *  The filtered float here represents X with x+e, x and e non-overlapping and e the error on the
00067  *  previous operation.  If X+Y=Z with X=x+e and Y=y+f then error of Z is g with Z=(x+y)+g.  Thus
00068  *  <b>not</b> the error on (x+e)+(y+f) but only on (x+y)!
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_,     /**< the value */
00177                     e_;     /**< the expected precision, based on forward error analysis */
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     //return a.value()+a.error() < b.value()-b.error();;
00240     LASS_ENFORCE( (a.value()+b.error() < b.value()-a.error()) == (a.value()<b.value()));
00241     return a.value()<b.value();
00242     /*
00243     if (a.value()==b.value())
00244     {
00245         return a.error() < b.error();
00246     }
00247     return a.value() < b.value();
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

Generated on Mon Nov 10 14:20:04 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo