C-XSC - A C++ Class Library for Extended Scientific Computing  2.5.4
real.inl
00001 /*
00002 **  CXSC is a C++ library for eXtended Scientific Computing (V 2.5.4)
00003 **
00004 **  Copyright (C) 1990-2000 Institut fuer Angewandte Mathematik,
00005 **                          Universitaet Karlsruhe, Germany
00006 **            (C) 2000-2014 Wiss. Rechnen/Softwaretechnologie
00007 **                          Universitaet Wuppertal, Germany   
00008 **
00009 **  This library is free software; you can redistribute it and/or
00010 **  modify it under the terms of the GNU Library General Public
00011 **  License as published by the Free Software Foundation; either
00012 **  version 2 of the License, or (at your option) any later version.
00013 **
00014 **  This library is distributed in the hope that it will be useful,
00015 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 **  Library General Public License for more details.
00018 **
00019 **  You should have received a copy of the GNU Library General Public
00020 **  License along with this library; if not, write to the Free
00021 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 */
00023 
00024 /* CVS $Id: real.inl,v 1.33 2014/01/30 17:23:48 cxsc Exp $ */
00025 
00026 #ifdef _CXSC_REAL_HPP_INCLUDED
00027 
00028 #include "fi_lib.hpp"
00029 #include <cmath>
00030 
00031 namespace cxsc {
00032 extern "C"
00033 {
00034    a_real r_comp(a_real,a_intg);
00035    a_real r_mant(a_real);
00036    a_intg r_expo(a_real);
00037 }
00038 
00039 inline double _double(const real &a) throw()
00040 { 
00041    return a.w; 
00042 }
00043 
00049 inline real   _real(const double &a) throw()
00050 { 
00051    return real(a); 
00052 }
00053 
00054 inline real pred(const real& r) throw()
00055 {
00056    real ret;
00057    ret = fi_lib::q_pred(r.w);
00058    return ret;
00059 }
00060 
00061 inline real succ(const real& r) throw()
00062 {
00063    real ret;
00064    ret = fi_lib::q_succ(r.w);
00065    return ret;
00066 }
00067 
00068 inline a_intg expo(const real &r) throw()
00069 {
00070    return r_expo(*(a_real*)&r.w);
00071 }
00072 
00073 inline real comp(const real &r, a_intg i) throw()
00074 {
00075    return real(r_comp(*(a_real*)&r.w,i));
00076 }
00077 
00078 inline real mant(const real &r) throw()
00079 {
00080    return real(r_mant(*(a_real*)&r.w));
00081 }
00082 
00083 inline real operator -(const real &a) throw()       { return -a.w; }
00084 inline real operator +(const real &a) throw()       { return a; }
00085 
00086 inline real operator +(const real &a,const real &b) throw () { return a.w+b.w; }
00087 inline real operator -(const real &a,const real &b) throw () { return a.w-b.w; }
00088 inline real operator *(const real &a,const real &b) throw () { return a.w*b.w; }
00089 inline real operator /(const real &a,const real &b) throw () { return a.w/b.w; }
00090 
00091 inline real& operator +=(real &a, const real &b) throw () { a.w+=b.w; return a; }
00092 inline real& operator -=(real &a, const real &b) throw () { a.w-=b.w; return a; }
00093 inline real& operator *=(real &a, const real &b) throw () { a.w*=b.w; return a; }
00094 inline real& operator /=(real &a, const real &b) throw () { a.w/=b.w; return a; }
00095 
00096 inline bool operator!  (const real& a)                throw () { return !a.w; }
00097 inline bool operator== (const real& a, const real& b) throw () { return a.w==b.w; }
00098 inline bool operator!= (const real& a, const real& b) throw () { return a.w!=b.w; }
00099 inline bool operator<  (const real& a, const real& b) throw () { return a.w<b.w;  }
00100 inline bool operator<= (const real& a, const real& b) throw () { return a.w<=b.w; }
00101 inline bool operator>= (const real& a, const real& b) throw () { return a.w>=b.w; }
00102 inline bool operator>  (const real& a, const real& b) throw () { return a.w>b.w;  }
00103 
00104 inline bool operator== (const real& a, const int & b) throw () { return a.w==b; }
00105 inline bool operator!= (const real& a, const int & b) throw () { return a.w!=b; }
00106 inline bool operator== (const int & a, const real& b) throw () { return a==b.w; }
00107 inline bool operator!= (const int & a, const real& b) throw () { return a!=b.w; }
00108 inline bool operator== (const real& a, const long & b) throw () { return a.w==b; }
00109 inline bool operator!= (const real& a, const long & b) throw () { return a.w!=b; }
00110 inline bool operator== (const long & a, const real& b) throw () { return a==b.w; }
00111 inline bool operator!= (const long & a, const real& b) throw () { return a!=b.w; }
00112 inline bool operator== (const real& a, const float & b) throw () { return a.w==b; }
00113 inline bool operator!= (const real& a, const float & b) throw () { return a.w!=b; }
00114 inline bool operator== (const float & a, const real& b) throw () { return a==b.w; }
00115 inline bool operator!= (const float & a, const real& b) throw () { return a!=b.w; }
00116 inline bool operator== (const real& a, const double & b) throw () { return a.w==b; }
00117 inline bool operator!= (const real& a, const double & b) throw () { return a.w!=b; }
00118 inline bool operator== (const double & a, const real& b) throw () { return a==b.w; }
00119 inline bool operator!= (const double & a, const real& b) throw () { return a!=b.w; }
00120 
00121 
00122 inline real abs(const real &a) throw()
00123 {
00124   /* if(a.w>=0)
00125       return a.w;
00126    return -a.w;*/
00127   return fabs(a.w);
00128 }
00129 
00130 inline int sign(const real &a) throw()
00131 {
00132    if(a.w>0)
00133       return 1;
00134    else
00135       if(a.w)
00136          return -1;
00137       else 
00138          return 0;
00139 }   
00140 
00141 inline void times2pown(real& r, const int n) // Blomquist 01.10.02.
00142 {   // times2pown(r,n): The reference parameter r gets the new value:  r*2^n; 
00143     // r*2^n in the normalized range --> r*2^n is the exact value.
00144     // r*2^n in the denormalized range --> r*2^n is in general not exact.
00145     int j = expo(r) + n;
00146     if (j >= -1021) { r = comp(mant(r),j); } // r is normalized up to now !
00147     else 
00148     {   // result now in the denormalized range:
00149         j += 1021;
00150         r = comp(mant(r), -1021); // r is still normalized
00151         if (j<-53) r = 0;
00152         else r = r * comp(0.5,j+1);
00153     } 
00154 } // end of times2pown(...)
00155 
00156 inline real pow2n(const int n) throw() // Blomquist 03.10.02.
00157 {   // Fast and exact calculation of 2^n; -1074 <= n <= +1023;
00158     return comp(0.5,n+1);
00159 }
00160 
00161 inline real max(const real & a, const real & b) { return a>b?a:b; }
00162 inline real min(const real & a, const real & b) { return a<b?a:b; }
00163 inline real Max(const real & a, const real & b) { return a>b?a:b; } 
00164 
00165 
00166 // ------- Verknuepfungen mit nach oben bzw. unten gerichteter Rundung ------
00167 // ------- (Operators with rounding direction upwards or downwards) ---------
00168 
00169 } // namespace cxsc
00170 
00171 #include "rts_real.hpp"
00172 
00173 #if ROUND_ASM
00174 #include <r_ari.h>
00175 #endif
00176 
00177 #if ROUND_C99_SAVE+ROUND_C99_QUICK
00178 #include <fenv.h>
00179 #endif
00180 
00181 #ifdef _MSC_VER
00182 #include <float.h>
00183 #pragma fenv_access (on)
00184         static inline void setround(int r) {
00185                 unsigned int control_word;
00186                 _controlfp_s(&control_word,0,0);
00187                 switch(r) {
00188                         case -1:
00189                                 _controlfp_s(&control_word,_RC_DOWN,_MCW_RC);
00190                                 break;
00191                         case 0:
00192                                 _controlfp_s(&control_word,_RC_NEAR,_MCW_RC);
00193                                 break;
00194                         case 1:
00195                                 _controlfp_s(&control_word,_RC_UP,_MCW_RC);
00196                                 break;
00197                         case 2: 
00198                                 _controlfp_s(&control_word,_RC_CHOP,_MCW_RC);
00199                                 break;
00200                         default:
00201                                 _controlfp_s(&control_word,_RC_NEAR,_MCW_RC);
00202                 }
00203         }
00204 
00205 #endif
00206 
00207 #if ROUND_C96_SAVE+ROUND_C96_QUICK
00208 #include <fenv96.h>
00209 #define fegetround fegetround96
00210 #define fesetround fesetround96
00211 #endif
00212 
00213 
00214 namespace cxsc {
00215 
00216 inline real addup(const real &x, const real &y)
00217 {
00218         #if ROUND_ASM
00219                 double ret;
00220                 ret = ra_addu(x.w,y.w);
00221                 return real(ret);                       
00222         #elif ROUND_C99_SAVE+ROUND_C96_SAVE
00223                 int mode;
00224                 mode=fegetround();
00225                 fesetround(FE_UPWARD);
00226                 double ret;
00227                 ret = x.w + y.w;
00228                 fesetround(mode);
00229                 return real(ret);
00230         #elif ROUND_C99_QUICK+ROUND_C96_QUICK
00231                 fesetround(FE_UPWARD);
00232                 return( x.w + y.w);
00233     #elif _MSC_VER
00234         unsigned int cw;
00235                 unsigned int mask = 0xFFFFF;
00236                 _controlfp_s(&cw,0,0);
00237         setround(1);
00238                 double ret;
00239                 ret = x.w + y.w;
00240                 _controlfp_s(&cw,cw,mask);
00241                 return real(ret);
00242         #else
00243                 a_real ret;
00244                 ret = r_addu(_a_real(x.w), _a_real(y.w));
00245                 return _real(ret);
00246         #endif
00247 }
00248 
00249 inline real adddown(const real &x, const real &y)
00250 {
00251         #if ROUND_ASM
00252                 double ret;
00253                 ret = ra_addd(x.w,y.w);
00254                 return real(ret);
00255         #elif ROUND_C99_SAVE+ROUND_C96_SAVE
00256                 int mode;
00257                 mode=fegetround();
00258                 fesetround(FE_DOWNWARD);
00259                 double ret;
00260                 ret = x.w + y.w;
00261                 fesetround(mode);
00262                 return real(ret);
00263         #elif ROUND_C99_QUICK+ROUND_C96_QUICK
00264                 fesetround(FE_DOWNWARD);
00265                 return( x.w + y.w);
00266     #elif _MSC_VER
00267         unsigned int cw;
00268                 unsigned int mask = 0xFFFFF;
00269                 _controlfp_s(&cw,0,0);
00270         setround(-1);
00271                 double ret;
00272                 ret = x.w + y.w;
00273                 _controlfp_s(&cw,cw,mask);
00274                 return real(ret);
00275         #else
00276         a_real ret;
00277                 ret = r_addd(_a_real(x.w), _a_real(y.w));
00278                 return _real(ret);
00279         #endif
00280 }
00281 
00282 inline real subup(const real &x, const real &y)
00283 {
00284         #if ROUND_ASM
00285                 double ret;
00286                 ret = ra_subu(x.w,y.w);
00287                 return real(ret);
00288         #elif ROUND_C99_SAVE+ROUND_C96_SAVE
00289                 int mode;
00290                 mode=fegetround();
00291                 fesetround(FE_UPWARD);
00292                 double ret;
00293                 ret = x.w - y.w;
00294                 fesetround(mode);
00295                 return real(ret);
00296         #elif ROUND_C99_QUICK+ROUND_C96_QUICK
00297                 fesetround(FE_UPWARD);
00298                 return( x.w - y.w);
00299     #elif _MSC_VER
00300         unsigned int cw;
00301                 unsigned int mask = 0xFFFFF;
00302                 _controlfp_s(&cw,0,0);
00303         setround(1);
00304                 double ret;
00305                 ret = x.w - y.w;
00306                 _controlfp_s(&cw,cw,mask);
00307                 return real(ret);
00308         #else
00309                 a_real ret;
00310                 ret = r_subu(_a_real(x.w), _a_real(y.w));
00311                 return _real(ret);
00312         #endif
00313 }
00314 
00315 inline real subdown(const real &x, const real &y)
00316 {
00317         #if ROUND_ASM
00318                 double ret;
00319                 ret = ra_subd(x.w,y.w);
00320                 return real(ret);                               
00321         #elif ROUND_C99_SAVE+ROUND_C96_SAVE
00322                 int mode;
00323                 mode=fegetround();
00324                 fesetround(FE_DOWNWARD);
00325                 double ret;
00326                 ret = x.w - y.w;
00327                 fesetround(mode);
00328                 return real(ret);
00329         #elif ROUND_C99_QUICK+ROUND_C96_QUICK
00330                 fesetround(FE_DOWNWARD);
00331                 return( x.w - y.w);
00332     #elif _MSC_VER
00333         unsigned int cw;
00334                 unsigned int mask = 0xFFFFF;
00335                 _controlfp_s(&cw,0,0);
00336         setround(-1);
00337                 double ret;
00338                 ret = x.w - y.w;
00339                 _controlfp_s(&cw,cw,mask);
00340                 return real(ret);
00341         #else
00342                 a_real ret;
00343                 ret = r_subd(_a_real(x.w), _a_real(y.w));
00344                 return _real(ret);
00345         #endif
00346 }
00347 
00348 inline real multup(const real &x, const real &y)
00349 {
00350         #if ROUND_ASM
00351                 double ret;
00352                 ret = ra_mulu(x.w,y.w);
00353                 return real(ret);
00354         #elif ROUND_C99_SAVE+ROUND_C96_SAVE
00355                 int mode;
00356                 mode=fegetround();
00357                 fesetround(FE_UPWARD);
00358                 double ret;
00359                 ret = x.w * y.w;
00360                 fesetround(mode);
00361                 return real(ret);
00362         #elif ROUND_C99_QUICK+ROUND_C96_QUICK
00363                 fesetround(FE_UPWARD);
00364                 return( x.w * y.w);
00365     #elif _MSC_VER
00366         unsigned int cw;
00367                 unsigned int mask = 0xFFFFF;
00368                 _controlfp_s(&cw,0,0);
00369         setround(1);
00370                 double ret;
00371                 ret = x.w * y.w;
00372                 _controlfp_s(&cw,cw,mask);
00373                 return real(ret);
00374         #else
00375                 a_real ret;
00376                 ret = r_mulu(_a_real(x.w), _a_real(y.w));
00377                 return _real(ret);
00378         #endif
00379 }
00380 
00381 inline real multdown(const real &x, const real &y)
00382 {
00383         #if ROUND_ASM
00384                 double ret;
00385                 ret = ra_muld(x.w,y.w);
00386                 return real(ret);
00387         #elif ROUND_C99_SAVE+ROUND_C96_SAVE
00388                 int mode;
00389                 mode=fegetround();
00390                 fesetround(FE_DOWNWARD);
00391                 double ret;
00392                 ret = x.w * y.w;
00393                 fesetround(mode);
00394                 return real(ret);
00395         #elif ROUND_C99_QUICK+ROUND_C96_QUICK
00396                 fesetround(FE_DOWNWARD);
00397                 return( x.w * y.w);
00398     #elif _MSC_VER
00399         unsigned int cw;
00400                 unsigned int mask = 0xFFFFF;
00401                 _controlfp_s(&cw,0,0);
00402         setround(-1);
00403                 double ret;
00404                 ret = x.w * y.w;
00405                 _controlfp_s(&cw,cw,mask);
00406                 return real(ret);
00407         #else
00408                 a_real ret;
00409                 ret = r_muld(_a_real(x.w), _a_real(y.w));
00410                 return _real(ret);
00411         #endif
00412 }
00413 
00414 inline real divup(const real &x, const real &y)
00415 {
00416         #if ROUND_ASM
00417                 double ret;
00418                 ret = ra_divu(x.w,y.w);
00419                 return real(ret);
00420         #elif ROUND_C99_SAVE+ROUND_C96_SAVE
00421                 int mode;
00422                 mode=fegetround();
00423                 fesetround(FE_UPWARD);
00424                 double ret;
00425                 ret = x.w / y.w;
00426                 fesetround(mode);
00427                 return real(ret);
00428         #elif ROUND_C99_QUICK+ROUND_C96_QUICK
00429                 fesetround(FE_UPWARD);
00430                 return( x.w / y.w);
00431     #elif _MSC_VER
00432         unsigned int cw;
00433                 unsigned int mask = 0xFFFFF;
00434                 _controlfp_s(&cw,0,0);
00435         setround(1);
00436                 double ret;
00437                 ret = x.w / y.w;
00438                 _controlfp_s(&cw,cw,mask);
00439                 return real(ret);
00440         #else
00441                 a_real ret;
00442                 ret = r_divu(_a_real(x.w), _a_real(y.w));
00443                 return _real(ret);
00444         #endif
00445 }
00446 
00447 inline real divdown(const real &x, const real &y)
00448 {
00449         #if ROUND_ASM
00450                 double ret;
00451                 ret = ra_divd(x.w,y.w);
00452                 return real(ret);
00453         #elif ROUND_C99_SAVE+ROUND_C96_SAVE
00454                 int mode;
00455                 mode=fegetround();
00456                 fesetround(FE_DOWNWARD);
00457                 double ret;
00458                 ret = x.w / y.w;
00459                 fesetround(mode);
00460                 return real(ret);
00461         #elif ROUND_C99_QUICK+ROUND_C96_QUICK
00462                 fesetround(FE_DOWNWARD);
00463                 return( x.w / y.w);
00464     #elif _MSC_VER
00465         unsigned int cw;
00466                 unsigned int mask = 0xFFFFF;
00467                 _controlfp_s(&cw,0,0);
00468         setround(-1);
00469                 double ret;
00470                 ret = x.w / y.w;
00471                 _controlfp_s(&cw,cw,mask);
00472                 return real(ret);
00473         #else
00474                 a_real ret;
00475                 ret = r_divd(_a_real(x.w), _a_real(y.w));
00476                 return _real(ret);
00477         #endif
00478 }
00479 
00480 //----------------------------------------------------------------------------
00481 // IsInfinity - prueft ob die uebergebene IEEE 64-Bit Gleitkommazahl
00482 //              'Unendlich' darstellt, dies ist der Fall, falls:
00483 //                alle Bits des Exponenten 1 sind
00484 //                alle Bits der Mantisse 0 sind
00485 //
00486 inline bool IsInfinity (const real &a) 
00487 {
00488    if ((((a_btyp*)&a)[HIGHREAL] & 0x7FF00000L) != 0x7FF00000L) 
00489       return false;
00490    if ((((a_btyp*)&a)[HIGHREAL] & 0x000FFFFFL) != 0L) 
00491       return false;
00492    if (((a_btyp*)&a)[LOWREAL] != 0L) 
00493       return false;
00494   return true;  // a ist 'unendlich'
00495 }
00496 
00497 //----------------------------------------------------------------------------
00498 // IsNan      - prueft ob die uebergebene IEEE 64-Bit Gleitkommazahl
00499 //              eine ungueltige Zahl (Not a number) darstellt,
00500 //              dies ist der Fall, falls:
00501 //                alle Bits des Exponenten 1 sind
00502 //                und nicht alle Bits der Mantisse 0 sind
00503 //
00504 inline bool IsQuietNaN (const real &a) 
00505 {
00506    if ((((a_btyp*)&a)[HIGHREAL] & 0x7FF00000L) != 0x7FF00000L) 
00507       return false;
00508 
00509    if ((((a_btyp*)&a)[HIGHREAL] & 0x000FFFFFL) == 0L) 
00510    {
00511       if (((a_btyp*)&a)[LOWREAL] == 0L) 
00512          return false;
00513    }
00514    return true;
00515 }
00516 
00517 //----------------------------------------------------------------------------
00518 // IsSignalingNaN - prueft ob die uebergebene IEEE 64-Bit Gleitkommazahl
00519 //              undefiniert ist (z.B. Berechnung der Wurzel einer negativen
00520 //              Zahl), dies ist der Fall, falls
00521 //                das Vorzeichenbit 1 ist
00522 //                alle Bits des Exponenten 1 sind
00523 //                das hoechste Bit der Mantisse 1 ist
00524 //                und alle anderen Bits der Mantisse 0 sind
00525 //
00526 inline bool IsSignalingNaN (const real &a) 
00527 {
00528    if ((((a_btyp*)&a)[HIGHREAL] & 0xFFF00000L) != 0xFFF00000L) 
00529       return false;
00530    if ((((a_btyp*)&a)[HIGHREAL] & 0x000FFFFFL) != 0x00080000L) 
00531       return false;
00532    if (((a_btyp*)&a)[LOWREAL] != 0L) 
00533       return false;
00534    return true;
00535 }
00536 
00537 } // namespace cxsc
00538 
00539 #endif // _CXSC_REAL_HPP_INCLUDED