00001 #include "QMCDouble.h"
00002 #include <iomanip>
00003
00004 QMCDouble::QMCDouble()
00005 {
00006 initialize();
00007 }
00008
00009 QMCDouble::QMCDouble(double value)
00010 {
00011 initialize();
00012 k = value;
00013 }
00014
00015 QMCDouble::QMCDouble(double w, double x, double y,\
00016 double z)
00017 {
00018 initialize();
00019 k = w;
00020 a = x;
00021 b = y;
00022 c = z;
00023 }
00024
00025 QMCDouble::QMCDouble( const QMCDouble & rhs )
00026 {
00027 *this = rhs;
00028 }
00029
00030 QMCDouble::~QMCDouble()
00031 {
00032
00033 }
00034
00035 void QMCDouble::initialize()
00036 {
00037 k = 1.0;
00038 a = 1.0;
00039 b = 0.0;
00040 c = 0.0;
00041 }
00042
00043 ostream& operator << (ostream& strm, const QMCDouble &rhs)
00044 {
00045 int w = 15;
00046 strm.setf(ios::scientific);
00047
00048
00049 strm << setw(w) << rhs.k;
00050 strm << " ( " << setw(w) << rhs.a;
00051 strm << " ^ " << setw(w) << rhs.b;
00052 strm << " ) Exp[ " << setw(w) << rhs.c << " ]";
00053
00054
00055
00056
00057
00058
00059 return strm;
00060 }
00061
00062 void QMCDouble::toXML(ostream & strm)
00063 {
00064 strm << "<QMCDouble>" << endl;
00065 strm << "\t<k>\t" << k << "\t</k>" << endl;
00066 strm << "\t<a>\t" << a << "\t</a>" << endl;
00067 strm << "\t<b>\t" << b << "\t</b>" << endl;
00068 strm << "\t<c>\t" << c << "\t</c>" << endl;
00069 strm << "</QMCDouble>\n" << endl;
00070 }
00071
00072
00073 void QMCDouble::SimplifyRatioPowers(double na, double nb,
00074 double da, double db, double &ra, double &rb)
00075 {
00076 double power1, power2;
00077 int method = -1;
00078
00079 #ifdef CRAY_X1_DEBUG
00080 cout << "----------------------------------------------------------" << endl;
00081 cout << "na:\t" << na << "\tnb:\t" << nb << "\tda:\t" << da << "\tdb:\t";
00082 cout << db << endl;
00083 cout << "&&&\t" << fabs(na-da) << endl;
00084 #endif
00085
00086 if ( fabs(na-da) < 1e-15 )
00087
00088 method = 0;
00089
00090 else if ( na>0.0 && da>0.0 )
00091 {
00092 if ( fabs(log(na)) > fabs(log(da)) )
00093 method = 1;
00094 else
00095 method = 2;
00096 }
00097 if ( (fabs(na-1.0) < 1e-15) || (fabs(nb) < 1e-15) )
00098 method = 3;
00099 if ( (fabs(da-1.0) < 1e-15) || (fabs(db) < 1e-15) )
00100 method = 4;
00101
00102 #ifdef CRAY_X1_DEBUG
00103 cout << "method:\t" << method << endl;
00104 #endif
00105
00106 if (method == 0)
00107 {
00108 ra = na;
00109 rb = nb-db;
00110 }
00111 else if (method == 1)
00112 {
00113 ra = na;
00114 power1 = nb;
00115 power2 = (log(da)/log(na))*db;
00116 rb = power1 - power2;
00117 }
00118
00119 else if (method == 2)
00120 {
00121 ra = da;
00122 power1 = (log(na)/log(da))*nb;
00123 power2 = db;
00124 rb = power1 - power2;
00125 }
00126 else if (method == 3)
00127 {
00128 ra = da;
00129 rb = -db;
00130 }
00131 else if (method == 4)
00132 {
00133 ra = na;
00134 rb = nb;
00135 }
00136 else
00137 {
00138 cerr << "Error in QMCDouble::SimplifyRatioPowers()";
00139 cerr << endl;
00140 cerr << "Your query is not yet supported." << endl;
00141 cerr << "na:\t" << na << endl;
00142 cerr << "nb:\t" << nb << endl;
00143 cerr << "da:\t" << da << endl;
00144 cerr << "db:\t" << db << endl;
00145 exit(1);
00146 }
00147 #ifdef CRAY_X1_DEBUG
00148 cout << "RESULTS:\tra:\t" << ra << "\trb:\t" << rb << endl;
00149 cout << "----------------------------------------------------------" << endl;
00150 #endif
00151 }
00152
00153 double QMCDouble::getValue() const
00154 {
00155 if (a<0.0)
00156 {
00157 cerr << "Error in QMCDouble::getValue():" << endl;
00158 cerr << "attempting to take a power of a negative number." << endl;
00159 cerr << "value = " << *this << endl;
00160 exit(1);
00161 }
00162 double t1 = 1.0;
00163 double t2 = 1.0;
00164
00165 if(b != 0.0) t1 = pow(a,b);
00166 if(c > 500) t2 = 1e250;
00167 else if(c != 0.0) t2 = exp(c);
00168
00169 return k*t1*t2;
00170 }
00171
00172 bool QMCDouble::isNotValid() const
00173 {
00174
00175 if(IeeeMath::isNaN(k) || IeeeMath::isNaN(a) || IeeeMath::isNaN(b) || IeeeMath::isNaN(c))
00176 {
00177 return true;
00178 }
00179 #ifdef QMC_DEBUG
00180 if(a < 0.0)
00181 {
00182
00183
00184
00185
00186
00187 return true;
00188 }
00189 #endif
00190 return false;
00191 }
00192
00193 bool QMCDouble::isZero() const
00194 {
00195 if(fabs(k) < 1e-250 || c < -690.0 )
00196 {
00197 return true;
00198 }
00199 return false;
00200 }
00201
00202 QMCDouble & QMCDouble::divideBy(const QMCDouble & denom)
00203 {
00204 if(isZero())
00205 return *this;
00206
00207
00208 double POW_A, POW_B;
00209 SimplifyRatioPowers(a,b,denom.a,denom.b,POW_A,POW_B);
00210
00211 k /= denom.k;
00212 a = POW_A;
00213 b = POW_B;
00214 c -= denom.c;
00215
00216
00217
00218 if ( (c < -10.0) && (log(fabs(k)) > 10.0) )
00219 {
00220 c += log(fabs(k));
00221 k = k < 0 ? -1.0 : 1.0;
00222 }
00223 else if ( (c > 10.0) && (log(fabs(k)) < -10.0) )
00224 {
00225 c += log(fabs(k));
00226 k = k < 0 ? -1.0 : 1.0;
00227 }
00228
00229 if ( (c < -10.0) && (b*log(fabs(a)) > 10.0) )
00230 {
00231 c += b*log(fabs(a));
00232 a = 1.0;
00233 b = 0.0;
00234 }
00235 else if ( (c > 10.0) && (b*log(fabs(a)) < -10.0) )
00236 {
00237 c += b*log(fabs(a));
00238 a = 1.0;
00239 b = 0.0;
00240 }
00241
00242 if (isNotValid())
00243 {
00244 cerr << "Error in QMCDouble::divideBy():" << endl;
00245 cerr << "dividend = " << *this << endl;
00246 cerr << " divisor = " << denom << endl;
00247 exit(1);
00248 }
00249
00250 return *this;
00251 }
00252
00253 QMCDouble & QMCDouble::multiplyBy(const QMCDouble &X)
00254 {
00255 if (isNotValid() || X.isNotValid())
00256 {
00257 cerr << "Error in QMCDouble::multiplyBy():" << endl;
00258 cerr << "multiplicand = " << *this << endl;
00259 cerr << " multiplier = " << X << endl;
00260 }
00261
00262 double temp_k, temp_a, temp_b;
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 temp_k = k * X.k;
00273 if( (fabs(temp_k) > 1e200 || fabs(temp_k) < 1e-200) &&
00274 (fabs(k) > 1e-300 && fabs(X.k) > 1e-300) )
00275 {
00276 if (fabs(k) < 1e-100)
00277 c += log(fabs(k)*1e100) + log(1e-100);
00278 else if (fabs(k) > 1e100)
00279 c += log(fabs(k)*1e-100) + log(1e100);
00280 else
00281 c += log(fabs(k));
00282
00283 if (fabs(X.k) < 1e-100)
00284 c += log(fabs(X.k)*1e100) + log(1e-100);
00285 else if (fabs(X.k) > 1e100)
00286 c += log(fabs(X.k)*1e-100) + log(1e100);
00287 else
00288 c += log(fabs(X.k));
00289
00290 k = k < 0 ? -1.0 : 1.0;
00291 k = X.k < 0 ? -k : k;
00292 }
00293 else
00294 k = temp_k;
00295
00296 c += X.c;
00297
00298 if ( (fabs(a-1.0) < 1e-15) || (fabs(b) < 1e-15) )
00299 {
00300 if ( (fabs(X.a-1.0) < 1e-15) || (fabs(X.b) < 1e-15) )
00301 {
00302 temp_a = 1.0;
00303 temp_b = 0.0;
00304 }
00305 else
00306 {
00307 temp_a = X.a;
00308 temp_b = X.b;
00309 }
00310 }
00311 else if ( (fabs(X.a-1.0) < 1e-15) || (fabs(X.b) < 1e-15) )
00312 {
00313 temp_a = a;
00314 temp_b = b;
00315 }
00316 else if ( fabs(a-X.a) < 1e-15 )
00317 {
00318 temp_a = a;
00319 temp_b = b + X.b;
00320 }
00321 else if (a < X.a)
00322 {
00323 temp_a = X.a;
00324
00325 temp_b = b;
00326 if (fabs(a) < 1e-100)
00327 temp_b *= log(fabs(a)*1e100) + log(1e-100);
00328 else if (fabs(a) > 1e100)
00329 temp_b *= log(fabs(a)*1e-100) + log(1e100);
00330 else
00331 temp_b *= log(fabs(a));
00332
00333 if (fabs(X.a) < 1e-100)
00334 temp_b /= log(fabs(X.a)*1e100) + log(1e-100);
00335 else if (fabs(X.a) > 1e100)
00336 temp_b /= log(fabs(X.a)*1e-100) + log(1e100);
00337 else
00338 temp_b /= log(fabs(X.a));
00339
00340 temp_b += X.b;
00341 }
00342 else
00343 {
00344 temp_a = a;
00345
00346 temp_b = X.b;
00347 if (fabs(X.a) < 1e-100)
00348 temp_b *= log(fabs(X.a)*1e100) + log(1e-100);
00349 else if (fabs(X.a) > 1e100)
00350 temp_b *= log(fabs(X.a)*1e-100) + log(1e100);
00351 else
00352 temp_b *= log(fabs(X.a));
00353
00354 if (fabs(a) < 1e-100)
00355 temp_b /= log(fabs(a)*1e100) + log(1e-100);
00356 else if (fabs(a) > 1e100)
00357 temp_b /= log(fabs(a)*1e-100) + log(1e100);
00358 else
00359 temp_b /= log(fabs(a));
00360
00361 temp_b += b;
00362 }
00363 a = temp_a;
00364 b = temp_b;
00365
00366
00367
00368 if ( (c < -10.0) && (log(fabs(k)) > 10.0) )
00369 {
00370 c += log(fabs(k));
00371 k = k < 0 ? -1.0 : 1.0;
00372 }
00373 else if ( (c > 10.0) && (log(fabs(k)) < -10.0) )
00374 {
00375 c += log(fabs(k));
00376 k = k < 0 ? -1.0 : 1.0;
00377 }
00378
00379 if ( (c < -10.0) && (b*log(fabs(a)) > 10.0) )
00380 {
00381 c += b*log(fabs(a));
00382 a = 1.0;
00383 b = 0.0;
00384 }
00385 else if ( (c > 10.0) && (b*log(fabs(a)) < -10.0) )
00386 {
00387 c += b*log(fabs(a));
00388 a = 1.0;
00389 b = 0.0;
00390 }
00391
00392 if (isNotValid() || X.isNotValid())
00393 {
00394 cerr << "Error in QMCDouble::multiplyBy():" << endl;
00395 cerr << "multiplicand = " << *this << endl;
00396 cerr << " multiplier = " << X << endl;
00397 *this = 0.0;
00398 }
00399
00400 return *this;
00401 }
00402
00403 QMCDouble & QMCDouble::add(const QMCDouble &X)
00404 {
00405
00406
00407
00408 if (isNotValid() || X.isNotValid())
00409 {
00410 cerr << "Error in QMCDouble::add():" << endl;
00411 cerr << "augend = " << *this << endl;
00412 cerr << "addend = " << X << endl;
00413 exit(1);
00414 }
00415
00416 if(k == 0.0)
00417 {
00418 *this = X;
00419 return *this;
00420 }
00421 else if(X.k == 0.0)
00422 return *this;
00423
00424
00425 if (fabs(k) < 1e-100)
00426 {
00427 c += log(fabs(k)*1e100) + log(1e-100);
00428 k = k > 0.0 ? 1.0 : -1.0;
00429 }
00430 else if (fabs(k) > 1e100)
00431 {
00432 c += log(fabs(k)*1e-100) + log(1e100);
00433 k = k > 0.0 ? 1.0 : -1.0;
00434 }
00435
00436 double log_middle_term;
00437 double expArg = X.c - c;
00438 double temp, Xtemp, signK = k, signXk = X.k;
00439
00440 if (fabs(a) < 1e-100)
00441 temp = b*(log(a*1e100) + log(1e-100));
00442
00443 else if (fabs(a) > 1e100)
00444 temp = b*(log(a*1e-100) + log(1e100));
00445
00446 else
00447 temp = b*log(a);
00448
00449 if (fabs(X.a) < 1e-100)
00450 Xtemp = X.b*(log(X.a*1e100) + log(1e-100));
00451
00452 else if (fabs(X.a) > 1e100)
00453 Xtemp = X.b*(log(X.a*1e-100) + log(1e100));
00454
00455 else
00456 Xtemp = X.b*log(X.a);
00457
00458 log_middle_term = Xtemp - temp;
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 if(fabs(expArg) > 690)
00470 {
00471
00472 if (fabs(X.k) < 1e-100)
00473 expArg += log(fabs(X.k)*1e100) + log(1e-100);
00474 else if (fabs(X.k) > 1e100)
00475 expArg += log(fabs(X.k)*1e-100) + log(1e100);
00476 else
00477 expArg += log(fabs(X.k));
00478
00479 expArg += log_middle_term;
00480
00481
00482 temp = log(fabs(k));
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 if (IeeeMath::isNaN(temp))
00499 {
00500 cerr << "Error in QMCDouble::add()" << endl;
00501 cerr << "Attempting to calculate exp(" << temp << ")" << endl;
00502 cerr << "augend = " << *this << endl;
00503 cerr << "addend = " << X << endl;
00504 exit(1);
00505 }
00506 else if(fabs(temp - expArg) < 34)
00507 {
00508 if (temp > expArg)
00509 {
00510 temp -= expArg;
00511 k = exp(temp);
00512 k = signK < 0 ? -k : k;
00513 k += signXk < 0 ? -1.0 : 1.0;
00514 c += expArg;
00515 }
00516 else if (expArg > temp)
00517 {
00518 expArg -= temp;
00519 k = exp(expArg);
00520 k = signXk < 0 ? -k : k;
00521 k += signK < 0 ? -1.0 : 1.0;
00522 c += temp;
00523 }
00524 }
00525 else if (expArg > temp)
00526 {
00527 k = 1.0;
00528 k = signXk < 0 ? -k : k;
00529 c += expArg;
00530 }
00531 else
00532 {
00533 k = 1.0;
00534 k = signK < 0 ? -k : k;
00535 c += temp;
00536 }
00537 }
00538 else
00539 {
00540
00541 expArg += log_middle_term;
00542
00543 if (IeeeMath::isNaN(expArg))
00544 {
00545 cerr << "Error in QMCDouble::add()" << endl;
00546 cerr << "Attempting to calculate exp(" << expArg << ")" << endl;
00547 cerr << "augend = " << *this << endl;
00548 cerr << "addend = " << X << endl;
00549 exit(1);
00550 }
00551 k += X.k * exp(expArg);
00552 }
00553
00554
00555
00556 if ( (c < -10.0) && (log(fabs(k)) > 10.0) )
00557 {
00558 c += log(fabs(k));
00559 k = k < 0 ? -1.0 : 1.0;
00560 }
00561 else if ( (c > 10.0) && (log(fabs(k)) < -10.0) )
00562 {
00563 c += log(fabs(k));
00564 k = k < 0 ? -1.0 : 1.0;
00565 }
00566
00567 if ( (c < -10.0) && (b*log(fabs(a)) > 10.0) )
00568 {
00569 c += b*log(fabs(a));
00570 a = 1.0;
00571 b = 0.0;
00572 }
00573 else if ( (c > 10.0) && (b*log(fabs(a)) < -10.0) )
00574 {
00575 c += b*log(fabs(a));
00576 a = 1.0;
00577 b = 0.0;
00578 }
00579
00580 return *this;
00581 }
00582
00583 QMCDouble QMCDouble::operator + ( const QMCDouble & rhs ) const {
00584 QMCDouble result = *this;
00585 return result.add(rhs);
00586 }
00587
00588 QMCDouble QMCDouble::operator - ( const QMCDouble & rhs ) const {
00589 QMCDouble result = *this;
00590 return result.add(rhs*-1.0);
00591 }
00592
00593 QMCDouble QMCDouble::operator * ( const QMCDouble & rhs ) const {
00594 QMCDouble result = *this;
00595 return result.multiplyBy(rhs);
00596 }
00597
00598 QMCDouble QMCDouble::operator / ( const QMCDouble & rhs ) const {
00599 QMCDouble result = *this;
00600 return result.divideBy(rhs);
00601 }
00602
00603 void QMCDouble::operator += ( const QMCDouble & rhs ){
00604 add(rhs);
00605 }
00606
00607 void QMCDouble::operator -= ( const QMCDouble & rhs ){
00608 add(rhs*-1.0);
00609 }
00610
00611 void QMCDouble::operator *= ( const QMCDouble & rhs ){
00612 multiplyBy(rhs);
00613 }
00614
00615 void QMCDouble::operator /= ( const QMCDouble & rhs ){
00616 divideBy(rhs);
00617 }
00618
00619 void QMCDouble::operator = ( const QMCDouble & rhs ){
00620 k = rhs.k;
00621 a = rhs.a;
00622 b = rhs.b;
00623 c = rhs.c;
00624 }
00625
00626 QMCDouble QMCDouble::operator + ( const double & rhs ) const {
00627 QMCDouble result = *this;
00628 return result.add(QMCDouble(rhs));
00629 }
00630
00631 QMCDouble QMCDouble::operator - ( const double & rhs ) const {
00632 QMCDouble result = *this;
00633 return result.add(QMCDouble(-1.0*rhs));
00634 }
00635
00636 QMCDouble QMCDouble::operator * ( const double & rhs ) const {
00637 QMCDouble result = *this;
00638 return result.multiplyBy(QMCDouble(rhs));
00639 }
00640
00641 QMCDouble QMCDouble::operator / ( const double & rhs ) const {
00642 QMCDouble result = *this;
00643 return result.divideBy(QMCDouble(rhs));
00644 }
00645
00646 void QMCDouble::operator += ( const double & rhs ){
00647 add(QMCDouble(rhs));
00648 }
00649
00650 void QMCDouble::operator -= ( const double & rhs ){
00651 add(QMCDouble(-1.0*rhs));
00652 }
00653
00654 void QMCDouble::operator *= ( const double & rhs ){
00655 multiplyBy(QMCDouble(rhs));
00656 }
00657
00658 void QMCDouble::operator /= ( const double & rhs ){
00659 divideBy(QMCDouble(rhs));
00660 }
00661
00662 void QMCDouble::operator = ( double rhs ){
00663 operator = (QMCDouble(rhs));
00664 }
00665
00666 QMCDouble::operator double() const {
00667 return getValue();
00668 }
00669
00670
00671
00672
00673