00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
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
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
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
00232 inline bool plProbability::isNaN() const
00233 {
00234 return *this == plNaNProbaConstant;
00235 }
00236
00237
00238
00239 bool plProbability::isInfinity() const
00240 {
00241 return (e == LONG_MAX) && (f != 0);
00242 }
00243
00248 #ifdef PL_NOT_IEEE754
00249
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
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
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
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
00348
00349
00350
00351
00352 #define PL_MASK_E_LD 0x7FFF
00353 #define PL_GET_E_LD(f) (f & PL_MASK_E_LD)
00354
00355
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
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
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
00398
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
00422
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
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
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
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
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
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
00997
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
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