Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members

plProbability32.h

00001 /*=============================================================================
00002  * Product        : OpenPL 
00003  * File           : plProbability32.h
00004  * Author         : Kamel Mekhnacha
00005  * Creation       : September 2001
00006  * 
00007  *=============================================================================
00008  *     (c) Copyright 2000, Centre National de la Recherche Scientifique,
00009  *                              all rights reserved
00010  *=============================================================================
00011  *
00012  *------------------------- Description ---------------------------------------
00013  *   Implements a new arithmetics to handle probabilities.
00014  *   
00015  *   
00016  *-----------------------------------------------------------------------------
00017  */
00018 
00019 #ifndef _plProbability_h_
00020 #define _plProbability_h_
00021 
00022 
00023 #include <plError.h>
00024 #include <iostream>
00025 #include <math.h>
00026 #include <limits.h>
00027 #include <errno.h>
00028 
00029 
00030 
00031 #define PL_F_SIZE 31
00032 
00033 #define PL_MASK_32 0x80000000
00034 #define PL_MASK_31 0x40000000
00035 #define PL_MASK_30 0x20000000
00036 #define PL_MASK_29 0x10000000
00037 
00038 #define PL_MAX_31_BITS 0x3FFFFFFF
00039 #define PL_MIN_31_BITS (-0x3FFFFFFF)
00040 
00041 #define PL_BIT_32(v) ( (v) & PL_MASK_32)
00042 #define PL_BIT_31(v) ( (v) & PL_MASK_31)
00043 
00044 #define PL_LOG_BASE2(v) (log(v)/0.69314718055994530942)
00045 
00046 #ifndef PL_LOG_OF_10_BASE2
00047 #define PL_LOG_OF_10_BASE2 3.321928094887362660
00048 #endif
00049 
00050 #ifndef PL_LOG_OF_E_BASE2
00051 #define PL_LOG_OF_E_BASE2 1.442695040888963
00052 #endif
00053 
00054 
00055 
00056 /*****************************************************************************
00057  *                           Classes Definitions
00058  *****************************************************************************/
00059 
00060 
00061 
00063 class plProbability
00064 {
00065 protected:
00066   unsigned long f;
00067   long e;
00068 
00069 protected:
00070 
00071 public:
00075   inline plProbability();
00076 
00078   inline plProbability(const long double &f);
00079 
00081   inline plProbability(const double &f);
00082   
00084   inline plProbability(const float &f);
00085 
00087   inline plProbability(const int &i);
00088 
00090   inline plProbability(const unsigned int &i);
00091 
00093   inline plProbability( unsigned long f, long e);
00094 
00096   inline operator float() const;
00097 
00099   inline operator double() const;
00100 
00102   inline operator long double() const;
00103 
00105   inline  plProbability operator+(const plProbability& pc) const;
00106   inline  plProbability operator+(const long double& fl) const;
00107   inline  plProbability operator+(const double& fl) const;
00108   inline  plProbability operator+(const float& fl) const;
00109 
00111   inline  plProbability operator-(const plProbability& pc) const;
00112   inline  plProbability operator-(const long double& fl) const;
00113   inline  plProbability operator-(const double& fl) const;
00114   inline  plProbability operator-(const float& fl) const;
00115 
00117   inline  plProbability& operator+=(const plProbability& pc);
00118   inline  plProbability& operator+=(const long double& fl);
00119   inline  plProbability& operator+=(const double& fl);
00120   inline  plProbability& operator+=(const float& fl);
00121 
00123   inline  plProbability& operator-=(const plProbability& pc);
00124   inline  plProbability& operator-=(const long double& fl);
00125   inline  plProbability& operator-=(const double& fl);
00126   inline  plProbability& operator-=(const float& fl);
00127   
00129   inline  plProbability operator*(const plProbability& pc) const;
00130   inline  plProbability operator*(const long double& fl) const;
00131   inline  plProbability operator*(const double& fl) const;
00132   inline  plProbability operator*(const float& fl) const;
00133   
00135   inline  plProbability& operator*=(const plProbability& pc);
00136   inline  plProbability& operator*=(const long double& fl);
00137   inline  plProbability& operator*=(const double& fl);
00138   inline  plProbability& operator*=(const float& fl);
00139 
00141   inline  plProbability operator/(const plProbability& pc) const;
00142   inline  plProbability operator/(const long double& fl) const;
00143   inline  plProbability operator/(const double& fl) const;
00144   inline  plProbability operator/(const float& fl) const;
00145 
00147   inline  plProbability& operator/=(const plProbability& pc);
00148   inline  plProbability& operator/=(const long double& fl);
00149   inline  plProbability& operator/=(const double& fl);
00150   inline  plProbability& operator/=(const float& fl);
00151     
00154   inline bool operator==(const plProbability& p) const; 
00155   inline bool operator==(const long double&) const;
00156   inline bool operator==(const double&) const;
00157   inline bool operator==(const float&) const;
00158   
00159   inline bool operator!=(const plProbability& p) const; 
00160   inline bool operator!=(const long double&) const;
00161   inline bool operator!=(const double&) const;
00162   inline bool operator!=(const float&) const;
00163   
00164 
00165   inline bool operator<=(const plProbability& p) const;
00166   inline bool operator<=(const long double&) const;
00167   inline bool operator<=(const double&) const;
00168   inline bool operator<=(const float&) const;
00169   
00170   inline bool operator>=(const plProbability& p) const;
00171   inline bool operator>=(const long double&) const;
00172   inline bool operator>=(const double&) const;
00173   inline bool operator>=(const float&) const;
00174 
00175   inline bool operator<(const plProbability& p) const;
00176   inline bool operator<(const long double&) const;
00177   inline bool operator<(const double&) const;
00178   inline bool operator<(const float&) const;
00179   
00180   inline bool operator>(const plProbability& p) const;
00181   inline bool operator>(const long double&) const;
00182   inline bool operator>(const double&) const;
00183   inline bool operator>(const float&) const;
00184 
00186   inline bool isNaN() const;
00187 
00189   inline bool isInfinity() const;
00190   
00192   friend inline double log2(const plProbability &pr);
00193   
00195   friend inline double log(const plProbability &pr);
00196   
00198   friend inline double log10(const plProbability &pr);
00199   
00201   friend inline plProbability ppow( const plProbability &pr, long exp );
00202   
00203  
00204   // Friend oprerators
00205   
00207   friend inline std::ostream& operator<<(std::ostream& out, const plProbability& p);
00208   friend inline std::istream& operator>>(std::istream& out, plProbability& p);
00209   
00210   
00211   friend inline long double operator*(const long double& theFloat, const plProbability& p);
00212   friend inline double operator*(const double& theFloat, const plProbability& p);
00213   friend inline float operator*(const float& theFloat, const plProbability& p);
00214 
00215   friend inline long double operator/(const long double& theFloat, const plProbability& p);
00216   friend inline double operator/(const double& theFloat, const plProbability& p);
00217   friend inline float operator/(const float& theFloat, const plProbability& p);
00218   
00219 
00220   // Defining some constants
00221   static const plProbability plZeroProbaConstant;
00222   static const plProbability plOneProbaConstant;
00223   static const plProbability plTwoProbaConstant;
00224   static const plProbability plHalfProbaConstant;
00225 
00226   static const plProbability plInfinityProbaConstant;
00227   static const plProbability plNaNProbaConstant;
00228 };
00229 
00230 //=============================================================================
00231 // Returns "true" is the value is "NaN" and "false" otherwise.
00232 inline bool plProbability::isNaN() const
00233 {
00234     return *this == plNaNProbaConstant;
00235 }
00236 
00237 //=============================================================================
00238 // Returns "true" is the value is "Infinity" and "false" otherwise.
00239 bool plProbability::isInfinity() const
00240 {
00241     return (e == LONG_MAX) && (f != 0);
00242 }
00243 
00248 #ifdef PL_NOT_IEEE754
00249 // We use a generic (but slow) method!!!
00250 //=============================================================================
00251 inline plProbability::plProbability(const long double &fl)
00252 {
00253   if(fl == 0.0L){
00254     *this = plZeroProbaConstant;
00255   }
00256   else{
00257     e = (long)(PL_LOG_BASE2(fl))+1;
00258     f = (unsigned long) (fl*pow(2.0, PL_F_SIZE - (double)e ));
00259 
00260     if(PL_BIT_32(f)){
00261       f >>=1; e++;
00262     }
00263     else{
00264       if( (f!=0) && (!PL_BIT_31(f)) ) {
00265     while(!PL_BIT_31(f)) {
00266       f <<=1; e--;
00267     }
00268       }
00269     }
00270   }
00271 }
00272 
00273 //=============================================================================
00274 inline plProbability::plProbability(const double &fl)
00275 {
00276   if(fl == 0.0){
00277     *this = plZeroProbaConstant;
00278   }
00279   else{
00280     e = (long)(PL_LOG_BASE2(fl))+1;
00281     f = (unsigned long) (fl*pow(2.0, PL_F_SIZE - (double)e ));
00282 
00283     if(PL_BIT_32(f)){
00284       f >>=1; e++;
00285     }
00286     else{
00287       if( (f!=0) && (!PL_BIT_31(f)) ) {
00288     while(!PL_BIT_31(f)) {
00289       f <<=1; e--;
00290     }
00291       }
00292     }
00293   }
00294 }
00295 
00296 //=============================================================================
00297 inline plProbability::plProbability(const float &fl)
00298 {
00299   if(fl == 0.0f){
00300     *this = plZeroProbaConstant;
00301   }
00302   else{
00303     e = (long)(PL_LOG_BASE2(fl))+1;
00304     f = (unsigned long) (fl*pow(2.0, PL_F_SIZE - (double)e ));
00305 
00306     if(PL_BIT_32(f)){
00307       f >>=1; e++;
00308     }
00309     else{
00310       if( (f!=0) && (!PL_BIT_31(f)) ) {
00311     while(!PL_BIT_31(f)) {
00312       f <<=1; e--;
00313     }
00314       }
00315     }
00316   }
00317 }
00318 
00319 
00320 // Conversion to float
00321 //=============================================================================
00322 inline plProbability::operator float() const
00323 {
00324   if (*this == plZeroProbaConstant) return 0.0f;
00325 
00326   return  f * pow(2.0, ((double)e - PL_F_SIZE));
00327 }
00328 
00329 // Conversion to double
00330 //=============================================================================
00331 inline plProbability::operator double() const
00332 {
00333   if (*this == plZeroProbaConstant) return 0.0;
00334 
00335   return  f * pow(2.0, ((double)e - PL_F_SIZE));
00336 }
00337 
00338 // Conversion to long double
00339 //=============================================================================
00340 inline plProbability::operator long double() const
00341 {
00342   if (*this == plZeroProbaConstant) return 0.0L;
00343 
00344   return  f * pow(2.0, ((double)e - PL_F_SIZE));
00345 }
00346 
00347 #else // PL_NOT_IEEE754 is defined
00348 // We use a precific method for IEEE754 machines 
00349 
00350 
00351 // Masks and macros for long double conversion
00352 #define PL_MASK_E_LD  0x7FFF
00353 #define PL_GET_E_LD(f) (f & PL_MASK_E_LD)
00354 
00355 // Masks and macros for double conversion
00356 #define PL_MASK_E_D  0x7FF00000
00357 #define PL_MASK_FH_D 0x000FFFFF
00358 #define PL_GET_E_D(f) ((f & PL_MASK_E_D) >> 20)
00359 #define PL_GET_FH_D(f)(f & PL_MASK_FH_D)
00360 
00361 // Masks and macros for float conversion
00362 #define PL_MASK_E_S  0x7F800000
00363 #define PL_MASK_FH_S  0x007FFFFF
00364 #define PL_GET_E_S(f) ((f & PL_MASK_E_S) >> 23)
00365 #define PL_GET_FH_S(f)(f & PL_MASK_FH_S)
00366 
00367 typedef struct {unsigned long w1, w2;} TwoWords;
00368 typedef union {TwoWords longPart; double doublePart;} DoubleUnion;
00369 
00370 
00371 typedef union { unsigned long longPart; float floatPart;} FloatUnion;
00372 
00373 // Converting a "long double" to a plProbability
00374 //=============================================================================
00375 inline plProbability::plProbability(const long double &ld)
00376 {
00377   if(ld == 0.0L){
00378     *this = plZeroProbaConstant;
00379   }
00380   else{
00381     
00382     DoubleUnion dCopy;
00383     dCopy.doublePart = double(ld);
00384     unsigned long dh, dl;
00385 #ifdef __BIG_ENDIAN__ //macintosh
00386     dh = dCopy.longPart.w1;
00387     dl = dCopy.longPart.w2;
00388 #else
00389     dh = dCopy.longPart.w2;
00390     dl = dCopy.longPart.w1;
00391 #endif
00392     f = ( (PL_GET_FH_D(dh)  | 0x00100000) << 10) | (dl >> 22) ;
00393     e = PL_GET_E_D(dh) - 1022;
00394   }
00395 }
00396 
00397 // Converting a "double" to a plProbability
00398 // This is a hidden-bit representation!!!
00399 //=============================================================================
00400 inline plProbability::plProbability(const double &fl)
00401 {
00402   if(fl == 0.0){
00403     *this = plZeroProbaConstant;
00404   }
00405   else{
00406     DoubleUnion dCopy;
00407     dCopy.doublePart = fl;
00408     unsigned long dh, dl;
00409 #ifdef __BIG_ENDIAN__ //macintosh
00410     dh = dCopy.longPart.w1;
00411     dl = dCopy.longPart.w2;
00412 #else
00413     dh = dCopy.longPart.w2;
00414     dl = dCopy.longPart.w1;
00415 #endif
00416     f = ( (PL_GET_FH_D(dh)  | 0x00100000) << 10) | (dl >> 22) ;
00417     e = PL_GET_E_D(dh) - 1022;
00418   }
00419 }
00420 
00421 // Converting a "float" to a plProbability
00422 // This is a hidden-bit representation!!!
00423 //=============================================================================
00424 inline plProbability::plProbability(const float &fl)
00425 {
00426   if(fl == 0.0f){
00427     *this = plZeroProbaConstant;
00428   }
00429   else{
00430     FloatUnion flCopy;
00431     flCopy.floatPart = fl;
00432     unsigned long af = flCopy.longPart;
00433     f =  ((PL_GET_FH_S(af) | 0x00800000) << 7);
00434     e = PL_GET_E_S(af)- 126;
00435   }
00436 }
00437 
00438 
00439 
00440 // Conversion to float
00441 //=============================================================================
00442 inline plProbability::operator float() const
00443 {
00444   if(f == 0) return 0.0f;
00445   if(e < -126) return 0.0f;
00446   if(e > 0x000000FF) return HUGE_VAL;
00447   
00448   FloatUnion flCopy;
00449   unsigned long fe = ( (e+126) << 23 );
00450   unsigned long ff = ( (f & 0x3FFFFFFF) >> 7);
00451   unsigned long fint = ( (fe | ff) & 0x7FFFFFFF);
00452   flCopy.longPart = fint;
00453   
00454   return flCopy.floatPart;
00455 }
00456 
00457 
00458 // Conversion to double
00459 //=============================================================================
00460 inline plProbability::operator double() const
00461 {
00462   if(f == 0) return 0.0;
00463   if(e < -1022) return 0.0;
00464   if(e > 0x000007FF) return HUGE_VAL;
00465   
00466   DoubleUnion dCopy;
00467   unsigned long dh =  ( ((e + 1022) << 20) | ( (f & 0x3FFFFC00) >> 10) ) & 0x7FFFFFFF;
00468   unsigned long dl =  (f & 0x000003FF) << 22;
00469   
00470   
00471 #ifdef __BIG_ENDIAN__ //macintosh
00472   dCopy.longPart.w1 = dh;
00473   dCopy.longPart.w2 = dl;
00474 #else
00475   dCopy.longPart.w2 = dh;
00476   dCopy.longPart.w1 = dl;
00477 #endif
00478   
00479   return dCopy.doublePart;
00480 }
00481 
00482 // Conversion to long double
00483 //=============================================================================
00484 inline plProbability::operator long double() const
00485 {
00486   return (long double) (double(*this));
00487 }
00488 
00489 
00490 #endif // PL_NOT_IEEE754
00491 
00492 //=============================================================================
00493 inline plProbability::plProbability(const int &i)
00494 {
00495   *this = double(i);
00496 }
00497 
00498 //=============================================================================
00499 inline plProbability::plProbability(const unsigned int &i)
00500 {
00501   *this = double(i);
00502 }
00503 
00504 //=============================================================================
00505 inline plProbability::plProbability()
00506 {
00507 }
00508 
00509 //=============================================================================
00510 inline plProbability::plProbability(unsigned long _f,  long _e)
00511 {
00512   f = _f; 
00513   e = _e; 
00514 }
00515 
00516 
00517 
00518 
00519 // Comparison operators
00520 //=============================================================================
00521 inline bool plProbability::operator==(const plProbability& p) const
00522 {
00523   return ( (f==p.f) && (e==p.e) );
00524 }
00525 
00526 //=============================================================================
00527 inline bool plProbability::operator==(const long double& fl) const 
00528 {
00529   return ( (*this) == (plProbability)fl ); 
00530 } 
00531 
00532 
00533 //=============================================================================
00534 inline bool plProbability::operator==(const double& fl) const 
00535 {
00536   return ( (*this) == (plProbability)fl ); 
00537 } 
00538 
00539 
00540 //=============================================================================
00541 inline bool plProbability::operator==(const float& fl) const 
00542 {
00543   return ( (*this) == (plProbability)fl ); 
00544 } 
00545 
00546 
00547 //=============================================================================
00548 inline bool plProbability::operator!=(const plProbability& p) const
00549 {
00550   return (!(*this == p));
00551 }
00552 
00553 //=============================================================================
00554 inline bool plProbability::operator!=(const long double& fl) const 
00555 { 
00556   return ( (*this) != (plProbability)fl ); 
00557 } 
00558 
00559 //=============================================================================
00560 inline bool plProbability::operator!=(const double& fl) const 
00561 { 
00562   return ( (*this) != (plProbability)fl ); 
00563 } 
00564 
00565 //=============================================================================
00566 inline bool plProbability::operator!=(const float& fl) const 
00567 { 
00568   return ( (*this) != (plProbability)fl ); 
00569 } 
00570 
00571 
00572 
00573 
00574 //=============================================================================
00575 inline bool plProbability::operator<=(const plProbability& p) const
00576 {
00577   if(f == 0) return true;
00578   if(p.f == 0) return false;
00579 
00580   if(e < p.e) return true;
00581   if(e == p.e) return (f <= p.f);
00582   return false;
00583 }
00584 
00585 //=============================================================================
00586 inline bool plProbability::operator<=(const long double& fl) const 
00587 {
00588   return ( (*this) <= (plProbability)fl ); 
00589 }
00590 
00591 
00592 //=============================================================================
00593 inline bool plProbability::operator<=(const double& fl) const 
00594 {
00595   return ( (*this) <= (plProbability)fl ); 
00596 }
00597 
00598 //=============================================================================
00599 inline bool plProbability::operator<=(const float& fl) const 
00600 {
00601   return ( (*this) <= (plProbability)fl ); 
00602 }
00603 
00604 
00605 //=============================================================================
00606 inline bool plProbability::operator<(const plProbability& p) const
00607 {
00608   if(f == 0) return (p.f != 0);
00609   if(p.f == 0) return false;
00610   if(e < p.e) return true;
00611   if(e == p.e) return (f < p.f);
00612   return false;
00613 }
00614 
00615 //=============================================================================
00616 inline bool plProbability::operator<(const long double& fl) const 
00617 {
00618   return ( (*this) < (plProbability)fl );
00619 } 
00620 
00621 //=============================================================================
00622 inline bool plProbability::operator<(const double& fl) const 
00623 {
00624   return ( (*this) < (plProbability)fl );
00625 } 
00626 
00627 //=============================================================================
00628 inline bool plProbability::operator<(const float& fl) const 
00629 {
00630   return ( (*this) < (plProbability)fl );
00631 } 
00632 
00633 
00634 
00635 //=============================================================================
00636 inline bool plProbability::operator>=(const plProbability& p) const 
00637 {
00638   if(p.f == 0) return true;
00639   if(f == 0) return false;
00640   if(e > p.e) return true;
00641   if(e == p.e) return (f >= p.f);
00642   return false;
00643 }
00644 
00645 //=============================================================================
00646 inline bool plProbability::operator>=(const long double& fl) const
00647 { 
00648   return ( (*this) >= (plProbability)fl );
00649 }
00650 
00651 
00652 //=============================================================================
00653 inline bool plProbability::operator>=(const double& fl) const
00654 { 
00655   return ( (*this) >= (plProbability)fl );
00656 }
00657 
00658 
00659 //=============================================================================
00660 inline bool plProbability::operator>=(const float& fl) const
00661 { 
00662   return ( (*this) >= (plProbability)fl );
00663 }
00664 
00665 
00666 //=============================================================================
00667 inline bool plProbability::operator>(const plProbability& p) const 
00668 { 
00669   if(p.f == 0) return (f != 0);
00670   if(f == 0) return false;
00671   if(e > p.e) return true;
00672   if(e == p.e) return (f > p.f);
00673   return false;
00674 }
00675 
00676 //=============================================================================
00677 inline bool plProbability::operator>(const long double& fl) const 
00678 {
00679   return ( (*this) > (plProbability)fl ); 
00680 }
00681 
00682 //=============================================================================
00683 inline bool plProbability::operator>(const double& fl) const 
00684 {
00685   return ( (*this) > (plProbability)fl ); 
00686 }
00687 
00688 //=============================================================================
00689 inline bool plProbability::operator>(const float& fl) const 
00690 {
00691   return ( (*this) > (plProbability)fl ); 
00692 }
00693 
00694 
00697 //=============================================================================
00698 inline  plProbability plProbability::operator+(const plProbability& pc) const
00699 { 
00700   if(isNaN()) return plNaNProbaConstant;
00701   if(pc.isNaN()) return plNaNProbaConstant;
00702   
00703   if(isInfinity()) return plInfinityProbaConstant;
00704   if(pc.isInfinity()) return plInfinityProbaConstant;
00705   
00706   long first_exponent_minus_second = e - pc.e;
00707   if(first_exponent_minus_second >= PL_F_SIZE) return *this;
00708   if(first_exponent_minus_second <= -PL_F_SIZE) return pc;
00709    
00710    plProbability pa;
00711   
00712   if (first_exponent_minus_second < 0){
00713     pa.f = (f >> (-first_exponent_minus_second )) + pc.f;
00714     pa.e = pc.e;
00715   }
00716   else{
00717     pa.f = f + (pc.f >> first_exponent_minus_second);
00718     pa.e = e;
00719   }
00720   
00721   if(PL_BIT_32(pa.f)){
00722     pa.f >>= 1;
00723     pa.e++;
00724     if( (pa.e > PL_MAX_31_BITS)) return plInfinityProbaConstant;
00725   }
00726   
00727   return pa;
00728 }
00729 
00730 //=============================================================================
00731 inline  plProbability plProbability::operator+(const long double& fl) const
00732 {
00733   return (*this) + (plProbability)fl;
00734 }
00735 
00736 
00737 //=============================================================================
00738 inline  plProbability plProbability::operator+(const double& fl) const
00739 {
00740   return (*this) + (plProbability)fl;
00741 }
00742 
00743 //=============================================================================
00744 inline  plProbability plProbability::operator+(const float& fl) const
00745 {
00746   return (*this) + (plProbability)fl;
00747 }
00748 
00749 //=============================================================================
00750 inline  plProbability& plProbability::operator+=(const plProbability& pc)
00751 {
00752   if(isNaN()) {*this = plNaNProbaConstant; return *this;}
00753   if(pc.isNaN()) {*this = plNaNProbaConstant; return *this;}
00754   
00755   if(isInfinity()) {*this = plInfinityProbaConstant; return *this;}
00756   if(pc.isInfinity()) {*this = plInfinityProbaConstant; return *this;}
00757   
00758   long first_exponent_minus_second = e - pc.e;
00759 
00760   if(first_exponent_minus_second >= PL_F_SIZE) return *this;
00761 
00762   if(first_exponent_minus_second <= -PL_F_SIZE){
00763     f = pc.f; 
00764     e = pc.e;
00765     return *this;
00766   }
00767   
00768   if (first_exponent_minus_second < 0){ 
00769     f = (f >> (-first_exponent_minus_second )) + pc.f;
00770     e = pc.e;
00771   }
00772   else{
00773     f += (pc.f >> first_exponent_minus_second);
00774   }
00775   
00776   if(PL_BIT_32(f)){
00777     f >>= 1;
00778     e++;
00779     if( (e > PL_MAX_31_BITS)) *this = plInfinityProbaConstant;
00780   }
00781   return *this;
00782 }
00783 
00784 //=============================================================================
00785 inline  plProbability& plProbability::operator+=(const long double& fl)
00786 {
00787   return (*this)+= ((plProbability)fl); 
00788 }
00789 
00790 //=============================================================================
00791 inline  plProbability& plProbability::operator+=(const double& fl)
00792 {
00793   return (*this)+= ((plProbability)fl); 
00794 }
00795 
00796 //=============================================================================
00797 inline  plProbability& plProbability::operator+=(const float& fl)
00798 {
00799   return (*this)+= ((plProbability)fl); 
00800 }
00801 
00803 //=============================================================================
00804 inline  plProbability plProbability::operator-(const plProbability& pc) const
00805 {
00806   if(isNaN()) return plNaNProbaConstant;
00807   if(pc.isNaN()) return plNaNProbaConstant;
00808   
00809   if(isInfinity() && !pc.isInfinity()) return plInfinityProbaConstant;
00810   if(pc.isInfinity()) return plNaNProbaConstant;
00811   
00812   if(*this == pc) return plZeroProbaConstant;
00813   
00814   if( *this < pc){
00815     plWarning(34);
00816     return plNaNProbaConstant;
00817   }
00818 
00819   
00820   long first_exponent_minus_second = e - pc.e;
00821   
00822   if(first_exponent_minus_second >= PL_F_SIZE) return *this;
00823   
00824   plProbability pa;
00825   pa.f = f - (pc.f >> first_exponent_minus_second);
00826   pa.e = e;
00827   
00828   while(!PL_BIT_31(pa.f)){
00829     pa.f <<= 1;
00830     pa.e--;
00831   }
00832   
00833   return pa;
00834 }
00835 
00836 //=============================================================================
00837 inline  plProbability plProbability::operator-(const long double& fl) const 
00838 {
00839   return (*this) - (plProbability)fl;
00840 }
00841 
00842 //=============================================================================
00843 inline  plProbability plProbability::operator-(const double& fl) const 
00844 {
00845   return (*this) - (plProbability)fl;
00846 }
00847 
00848 //=============================================================================
00849 inline  plProbability plProbability::operator-(const float& fl) const 
00850 {
00851   return (*this) - (plProbability)fl;
00852 }
00853 
00854 //=============================================================================
00855 inline  plProbability& plProbability::operator-=(const plProbability& pc)
00856 {
00857   if(isNaN()) return *this;
00858   if(pc.isNaN()) {*this = pc; return *this;}
00859    
00860   if(isInfinity() && !pc.isInfinity() ) {*this = plInfinityProbaConstant; return *this;}
00861   if(pc.isInfinity()) {*this = plNaNProbaConstant; return *this;}
00862   
00863   if(*this == pc) {*this = plZeroProbaConstant; return *this;}
00864   
00865   if( *this < pc){
00866     plWarning(34);
00867     *this = plNaNProbaConstant;
00868   }
00869 
00870   
00871   long first_exponent_minus_second = e - pc.e;
00872   
00873   if(first_exponent_minus_second >= PL_F_SIZE) return *this;
00874   
00875   f -= (pc.f >> first_exponent_minus_second);
00876   
00877   while(!PL_BIT_31(f)){
00878     f <<= 1;
00879     e--;
00880   }
00881   
00882   return *this;
00883 }
00884 
00885 //=============================================================================
00886 inline  plProbability& plProbability::operator-=(const long double& fl)
00887 {
00888   return (*this)-= ((plProbability)fl); 
00889 }
00890 
00891 //=============================================================================
00892 inline  plProbability& plProbability::operator-=(const double& fl)
00893 {
00894   return (*this)-= ((plProbability)fl); 
00895 }
00896 
00897 //=============================================================================
00898 inline  plProbability& plProbability::operator-=(const float& fl)
00899 {
00900   return (*this)-= ((plProbability)fl); 
00901 }
00902 
00903 
00906 //=============================================================================
00907 inline  plProbability plProbability::operator*(const plProbability& pc) const
00908 {
00909   if(isNaN()) return plNaNProbaConstant;
00910   if(pc.isNaN()) return plNaNProbaConstant;
00911   
00912   if(isInfinity()){
00913     if(pc.f == 0) return plNaNProbaConstant;
00914     else return plInfinityProbaConstant;
00915   }
00916   
00917   if(pc.isInfinity()){
00918     if(f == 0) return plNaNProbaConstant;
00919     else return plInfinityProbaConstant;
00920   }
00921   
00922   plProbability pa;
00923   //pa.f = (f >> 15) * (pc.f >> 15);
00924   pa.f = ((unsigned long long)f * (unsigned long long)pc.f) >> 30;
00925 
00926   pa.e = e + pc.e - 1 ;
00927 
00928   if(PL_BIT_32(pa.f)){
00929     pa.f >>= 1;
00930     pa.e++;
00931   }
00932 
00933   if(pa.e > PL_MAX_31_BITS) return plInfinityProbaConstant;
00934   
00935   if(pa.e < PL_MIN_31_BITS) return plZeroProbaConstant;
00936  
00937   
00938   return pa;
00939 }
00940 
00941 //=============================================================================
00942 inline  plProbability plProbability::operator*(const long double& fl) const 
00943 {
00944   return (*this) * (plProbability)fl;
00945 }
00946 
00947 //=============================================================================
00948 inline  plProbability plProbability::operator*(const double& fl) const 
00949 {
00950   return (*this) * (plProbability)fl;
00951 }
00952 
00953 //=============================================================================
00954 inline  plProbability plProbability::operator*(const float& fl) const 
00955 {
00956   return (*this) * (plProbability)fl;
00957 }
00958 
00959 
00960 //=============================================================================
00961 inline long double operator*(const long double& theFloat, const plProbability& p)
00962 {
00963   return (theFloat * (long double)p);
00964 }
00965 
00966 
00967 //=============================================================================
00968 inline double operator*(const double& theFloat, const plProbability& p)
00969 {
00970   return (theFloat * double(p));
00971 }
00972 
00973 //=============================================================================
00974 inline float operator*(const float& theFloat, const plProbability& p)
00975 {
00976   return (theFloat * float(p));
00977 }
00978 
00979 //=============================================================================
00980 inline  plProbability& plProbability::operator*=(const plProbability& pc)
00981 {
00982   if(isNaN()) {*this = plNaNProbaConstant; return *this;}
00983   if(pc.isNaN()) {*this = plNaNProbaConstant; return *this;}
00984   
00985   if(isInfinity()){
00986     if(pc.f == 0) {*this = plNaNProbaConstant; return *this;}
00987     else {*this = plInfinityProbaConstant; return *this;}
00988   }
00989   
00990   if(pc.isInfinity()){
00991     if(f == 0) {*this = plNaNProbaConstant; return *this;}
00992     else {*this = plInfinityProbaConstant; return *this;}
00993   }
00994   
00995   
00996   //f>>=15;
00997   //f *= (pc.f>>15);
00998   f = ((unsigned long long)f * (unsigned long long)pc.f) >> 30;
00999 
01000   e += (pc.e - 1) ;
01001   
01002   if(PL_BIT_32(f)){
01003     f >>= 1;
01004     e ++;
01005   }
01006 
01007   if(e > PL_MAX_31_BITS){
01008     *this = plInfinityProbaConstant;
01009   }
01010   else{
01011     if(e < PL_MIN_31_BITS){
01012       *this = plZeroProbaConstant;
01013     }
01014   }
01015   
01016   return *this;
01017 }
01018 
01019 //=============================================================================
01020 inline  plProbability& plProbability::operator*=(const long double& fl)
01021 { 
01022   return (*this)*= ((plProbability)fl);
01023 }
01024 
01025 
01026 //=============================================================================
01027 inline  plProbability& plProbability::operator*=(const double& fl)
01028 { 
01029   return (*this)*= ((plProbability)fl);
01030 }
01031 
01032 //=============================================================================
01033 inline  plProbability& plProbability::operator*=(const float& fl)
01034 { 
01035   return (*this)*= ((plProbability)fl);
01036 }
01037 
01038 
01041 //=============================================================================
01042 inline  plProbability plProbability::operator/(const plProbability& pc) const
01043 {
01044   if(isNaN()) return plNaNProbaConstant;
01045   if(pc.isNaN()) return plNaNProbaConstant;
01046   
01047   if(isInfinity()) {
01048     if(pc.isInfinity()) return plNaNProbaConstant;
01049     else return plInfinityProbaConstant;
01050   }
01051   
01052   if(pc.isInfinity()) return plZeroProbaConstant;
01053 
01054   if(pc.f == 0){
01055     plWarning(33);
01056     if(f == 0) return plNaNProbaConstant;
01057     return plInfinityProbaConstant;
01058   }
01059   if(f == 0) return plZeroProbaConstant;
01060   
01061   plProbability pa;
01062   pa.e = e - pc.e + 3 ;
01063   long double f_over_pcf = (long double)f/(long double)pc.f;
01064   unsigned long int_f_over_pcf = (unsigned long) (PL_MASK_29 * f_over_pcf);
01065   pa.f = int_f_over_pcf;
01066   while(pa.f < PL_MASK_31){
01067     pa.f <<= 1;
01068     pa.e--;
01069     if(pa.e < PL_MIN_31_BITS){
01070       return plZeroProbaConstant;
01071     }
01072   }
01073  
01074   return pa;
01075 }
01076 
01077 //=============================================================================
01078 inline long double operator/(const long double& theFloat, const plProbability& p)
01079 {
01080   return theFloat/(long double)p;
01081 }
01082 
01083 //=============================================================================
01084 inline double operator/(const double& theFloat, const plProbability& p)
01085 {
01086   return theFloat/double(p);
01087 }
01088 
01089 //=============================================================================
01090 inline float operator/(const float& theFloat, const plProbability& p)
01091 {
01092   return theFloat/float(p);
01093 }
01094 
01095 //=============================================================================
01096 inline  plProbability plProbability::operator/(const long double& fl) const 
01097 { 
01098   return (*this)/(plProbability)fl;
01099 }
01100 
01101 //=============================================================================
01102 inline  plProbability plProbability::operator/(const double& fl) const 
01103 { 
01104   return (*this)/(plProbability)fl;
01105 }
01106 
01107 //=============================================================================
01108 inline  plProbability plProbability::operator/(const float& fl) const 
01109 { 
01110   return (*this)/(plProbability)fl;
01111 }
01112 
01114 //=============================================================================
01115 inline  plProbability& plProbability::operator/=(const plProbability& pc)
01116 {
01117   
01118   *this =  *this / pc;
01119   
01120   return *this;
01121 }
01122 
01123 //=============================================================================
01124 inline  plProbability& plProbability::operator/=(const long double& fl)
01125 {
01126   return (*this) /=((plProbability)fl);
01127 }
01128 
01129 //=============================================================================
01130 inline  plProbability& plProbability::operator/=(const double& fl)
01131 {
01132   return (*this) /=((plProbability)fl);
01133 }
01134 
01135 //=============================================================================
01136 inline  plProbability& plProbability::operator/=(const float& fl)
01137 {
01138   return (*this) /=((plProbability)fl);
01139 }
01140 
01141 //=============================================================================
01142 inline std::istream& operator>>(std::istream& in, plProbability& p)
01143 {
01144     string st;
01145     in >> st;
01146     
01147     if(strcasecmp(st.c_str(), "NAN") == 0) { p = plProbability::plNaNProbaConstant; return in;}
01148     if(strcasecmp(st.c_str(), "INF") == 0) { p = plProbability::plInfinityProbaConstant; return in;}
01149     
01150     long df = 0;
01151     long ide = 0;
01152     string dfStr, ideStr;
01153     
01154     unsigned int i = 0;
01155     unsigned int ndec = 0;
01156     bool afterdot = false;
01157 
01158     while( (st[i] != 'e') && (st[i] != 'E') && (i < st.size()) ) {
01159         if(afterdot) ndec++;
01160         
01161         if(st[i] == '.') afterdot = true;
01162         else dfStr += st[i];
01163         
01164         i++;
01165     }
01166     i++;
01167     while(i < st.size() ) ideStr += st[i++];
01168 
01169     sscanf(dfStr.c_str(), "%ld", &df);
01170     sscanf(ideStr.c_str(), "%ld", &ide);
01171     
01172     if(df == 0){ p = plProbability::plZeroProbaConstant; return in;}
01173     if(df < 0){ p = plProbability::plNaNProbaConstant; return in;}
01174 
01175     ide -= ndec;
01176     
01177     long double fideBin = ide*3.321928094887362660L;
01178     long ideBin = long(fideBin);
01179     long double diff = fideBin - ideBin;
01180     
01181     long double fdf = df * pow(2.0L, diff);
01182     
01183     while(fdf < PL_MASK_31) {
01184         fdf *= 2.0L;
01185         ideBin--;
01186     }
01187     
01188     p.e = ideBin + PL_F_SIZE;
01189     p.f = (unsigned long)fdf;
01190     
01191     return in;
01192 }
01193 
01194 //=============================================================================
01195 inline std::ostream& operator<<(std::ostream& out,  const plProbability& p)
01196 {
01197   if(p.isNaN()) {out << "NaN"; return out;}
01198   if(p.isInfinity()) {out << "Inf"; return out;}
01199   
01200   if(p.f ==  0){
01201     out << "0";
01202     return out;
01203   }
01204   
01205   long double de = p.e/3.321928094887362660L;
01206   long ide = long(de);
01207   long double diff =  de - ide;
01208   long double df = p.f/(0x80000000 * pow(10.0L, -diff));
01209   out << df;
01210   if(ide){
01211     out << "e";
01212     if( ide > 0) out << "+";
01213     out << ide;
01214   }
01215   
01216   //out << "\t---->\tf=" << p.f << " e=" << p.e << hex << "\t---->\tf=" << p.f << " e=" << p.e << endl << dec;
01217   return out;
01218 }
01219 
01220 //=============================================================================
01221 inline double log2(const plProbability &pr)
01222 {
01223     if(pr.f == 0){
01224         errno = ERANGE;
01225         return -HUGE_VAL;
01226     }
01227     
01228     if(pr.isNaN()) return NAN;
01229     if(pr.isInfinity()) return HUGE_VAL;
01230     
01231     return PL_LOG_BASE2((double)pr.f) + pr.e - PL_F_SIZE;
01232 }
01233 
01234 //=============================================================================
01235 inline double log(const plProbability &pr)
01236 {
01237     return log2(pr)/PL_LOG_OF_E_BASE2;
01238 }
01239   
01240 //=============================================================================
01241 inline double log10(const plProbability &pr)
01242 {
01243     return log2(pr)/PL_LOG_OF_10_BASE2;
01244 }
01245 
01246 //=============================================================================
01247 inline plProbability ppow( const plProbability &pr, long exp )
01248 {
01249   if( pr.isNaN() )
01250     {
01251       return pr;
01252     }
01253   else
01254     {
01255       if( 0 == exp )
01256     {
01257       return plProbability::plOneProbaConstant;
01258     }
01259       if( 1 == exp )
01260     {
01261       return pr;
01262     }
01263 
01264       plProbability pr_aux;
01265       if( exp < 0 )
01266     {
01267       pr_aux = plProbability(1)/pr;
01268       exp = -exp;
01269     }
01270       else
01271     pr_aux = pr;
01272 
01274       double mantisse = pow( (double)pr_aux.f, (double)exp );
01275       plProbability interm( mantisse );
01276       if( interm.isNaN() 
01277       || interm.isInfinity() )
01278     {
01279       return plProbability::plNaNProbaConstant;
01280     }
01281 
01283       long exposant = interm.e + (pr_aux.e - PL_F_SIZE)*exp;
01285       if( !(LONG_MIN + PL_F_SIZE <= pr_aux.e ) 
01286       || !( (pr_aux.e - PL_F_SIZE)<= LONG_MAX/exp  )
01287       || !( LONG_MIN/exp <= (pr_aux.e - PL_F_SIZE) )
01288       )
01289     return plProbability::plNaNProbaConstant;
01290 
01291       if( interm.e > 0 )
01292     {
01294           if( !( ( pr_aux.e - PL_F_SIZE )*exp <= LONG_MAX - interm.e ) )
01295         {
01296           return plProbability::plNaNProbaConstant;
01297         }
01298     }
01299       else
01300     if( interm.e < 0 )
01301       {
01303         if( !(LONG_MIN - interm.e <= ( pr_aux.e - PL_F_SIZE )*exp ) )
01304           {
01305         return plProbability::plNaNProbaConstant;
01306           }
01307       }
01308 
01309       return plProbability( interm.f, exposant );
01310     }
01311 }
01312 
01313 #endif

Generated on Fri Apr 1 10:58:14 2005 for ProBT by  doxygen 1.4.1