00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #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
00125
00126
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)
00142 {
00143
00144
00145 int j = expo(r) + n;
00146 if (j >= -1021) { r = comp(mant(r),j); }
00147 else
00148 {
00149 j += 1021;
00150 r = comp(mant(r), -1021);
00151 if (j<-53) r = 0;
00152 else r = r * comp(0.5,j+1);
00153 }
00154 }
00155
00156 inline real pow2n(const int n) throw()
00157 {
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
00167
00168
00169 }
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
00482
00483
00484
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;
00495 }
00496
00497
00498
00499
00500
00501
00502
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
00519
00520
00521
00522
00523
00524
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 }
00538
00539 #endif // _CXSC_REAL_HPP_INCLUDED