BWAPI
|
00001 /**************************************************************************** 00002 * Core Library Version 1.7, August 2004 00003 * Copyright (c) 1995-2004 Exact Computation Project 00004 * All rights reserved. 00005 * 00006 * This file is part of CORE (http://cs.nyu.edu/exact/core/); you may 00007 * redistribute it under the terms of the Q Public License version 1.0. 00008 * See the file LICENSE.QPL distributed with CORE. 00009 * 00010 * Licensees holding a valid commercial license may use this file in 00011 * accordance with the commercial license agreement provided with the 00012 * software. 00013 * 00014 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00015 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00016 * 00017 * 00018 * File: BigFloatRep.h 00019 * Synopsis: 00020 * Internal Representation BigFloat. 00021 * 00022 * Written by 00023 * Chee Yap <yap@cs.nyu.edu> 00024 * Chen Li <chenli@cs.nyu.edu> 00025 * Zilin Du <zilin@cs.nyu.edu> 00026 * 00027 * WWW URL: http://cs.nyu.edu/exact/ 00028 * Email: exact@cs.nyu.edu 00029 * 00030 * $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Core/include/CGAL/CORE/BigFloatRep.h $ 00031 * $Id: BigFloatRep.h 37563 2007-03-27 13:28:17Z afabri $ 00032 ***************************************************************************/ 00033 00034 #ifndef _CORE_BIGFLOATREP_H_ 00035 #define _CORE_BIGFLOATREP_H_ 00036 00037 #include <CGAL/CORE/BigRat.h> 00038 #include <CGAL/CORE/CoreAux.h> 00039 #include <CGAL/CORE/CoreDefs.h> 00040 #include <CGAL/CORE/extLong.h> 00041 00042 CORE_BEGIN_NAMESPACE 00043 00044 // forward reference 00045 class BigFloat; 00046 00047 // class BigFloatRep (internal representation for BigFloat) 00048 class BigFloatRep : public RCRepImpl<BigFloatRep> { 00049 public: 00050 static long chunkCeil(long bits); //inline 00051 static long chunkFloor(long bits); //inline 00052 static long bits(long chunks); //inline 00053 static BigInt chunkShift(const BigInt& x, long s); //inline 00054 static double lg10(BigInt x); //inline 00055 static long floorlg10(BigInt x); //inline 00056 00058 00059 static BigFloatRep* exp2(int e); 00060 00061 struct DecimalOutput; 00062 00063 friend class BigFloat; 00064 00065 BigInt m; 00066 unsigned long err; 00067 long exp; 00068 00069 public: 00070 // constructors 00071 BigFloatRep(int=0); //inline 00072 BigFloatRep(short); //inline 00073 BigFloatRep(float); //inline 00074 BigFloatRep(long); //inline 00075 BigFloatRep(double); //inline 00076 BigFloatRep(const BigInt& I, unsigned long u, long l); //inline 00077 BigFloatRep(const BigInt& I, long l); //inline 00078 BigFloatRep(const BigInt& I); //inline 00079 BigFloatRep(const char *); //inline 00080 00081 BigRat BigRatize() const; //inline 00082 00083 // the destructor 00084 ~BigFloatRep(); //inline 00085 00086 CORE_MEMORY(BigFloatRep) // allocate the memory pool, unless 00087 // memory pool feature is disabled. 00088 00089 // approximation 00090 void trunc(const BigInt&, const extLong&, const extLong&); 00091 void truncM(const BigFloatRep&, const extLong&, const extLong&); 00092 void approx(const BigFloatRep&, const extLong&, const extLong&); 00093 00094 void div(const BigInt&, const BigInt&, const extLong&, const extLong&); 00095 void approx(const BigRat&, const extLong&, const extLong&); //inline 00096 00097 // error-normalization 00098 void eliminateTrailingZeroes(); //inline 00099 void normal(); 00100 void bigNormal(BigInt&); 00101 00102 // arithmetics 00103 public: 00104 void add(const BigFloatRep&, const BigFloatRep&); 00105 void sub(const BigFloatRep&, const BigFloatRep&); 00106 void mul(const BigFloatRep&, const BigFloatRep&); 00107 void div(const BigFloatRep&, const BigFloatRep&, const extLong&); 00108 void div2(const BigFloatRep&); 00109 00110 void centerize(const BigFloatRep&, const BigFloatRep&); 00111 private: 00112 // squareroot 00113 // arguments: r = value whose square root we want 00114 // a = absolute precision of the desired result 00115 // init = initial approx. to the square root (for Newton) 00116 void sqrt(const BigInt& r, const extLong& a); 00119 void sqrt(const BigInt& r, const extLong& a, const BigFloat& init); 00120 void sqrt(const BigFloatRep& r, const extLong& a); 00123 void sqrt(const BigFloatRep& r, const extLong& a, const BigFloat& init); 00124 00125 // comparison 00126 int compareMExp(const BigFloatRep&) const; 00127 00128 // builtin functions 00129 extLong lMSB() const; //inline 00130 extLong uMSB() const; //inline 00131 extLong MSB() const; //inline 00132 extLong flrLgErr() const; //inline 00133 extLong clLgErr() const; //inline 00134 00135 bool isZeroIn() const; //inline 00136 int signM() const; //inline 00137 00138 // cast functions 00139 double toDouble() const; 00140 long toLong() const; 00141 BigInt toBigInt() const; 00142 00143 // conversion 00144 00145 // toString() Joaquin Grech 31/5/2003 00146 std::string toString(long prec=defBigFloatOutputDigits, bool sci=false) const; 00147 std::string round(std::string inRep, long& L10, unsigned int width) const; 00148 DecimalOutput toDecimal(unsigned int width=defBigFloatOutputDigits, 00149 bool Scientific=false) const; 00150 void fromString(const char *p, const extLong & prec = defBigFloatInputDigits); 00151 00152 void dump() const; //inline 00153 long adjustE(long E, BigInt M, long e) const; 00154 00155 public: 00156 // stream operators 00157 std::ostream& operator <<(std::ostream&) const; //inline 00158 std::istream& operator >>(std::istream&); 00159 };//class BigFloatRep 00160 00162 // Implementations 00164 00165 struct BigFloatRep::DecimalOutput { 00166 std::string rep; // decimal output string 00167 int sign; // 0, +1 or -1 00168 bool isScientific; // false=positional notation 00169 int noSignificant; // number of significant digits 00170 // -1 means this information is not explicitly 00171 // given, and must be determined from rep, etc. 00172 bool isExact; // 00173 int errorCode; // 0 = no error 00174 // 1 = sign of number is unknown (e.g., mantissa 00175 // is smaller than error) 00176 00177 DecimalOutput() : rep(""), sign(1), isScientific(false), 00178 noSignificant(0), isExact(false), errorCode(0) {} 00179 };//DecimalOutput 00180 00181 // constants used by BigFloatRep 00182 // NOTES: CHUNK_BIT is the number of bits in each Chunk 00183 // Since LONG_BIT = 32 or 64, then CHUNK_BIT = 14 or 30. 00184 // We have: 0 <= err < 4 * 2^{CHUNK_BIT} 00185 00186 const long CHUNK_BIT = (long)(LONG_BIT / 2 - 2); // chunks 00187 const long HALF_CHUNK_BIT = (CHUNK_BIT + 1) / 2; 00188 const long DBL_MAX_CHUNK = (DBL_MAX_EXP - 1) / CHUNK_BIT + 1; 00189 const double lgTenM = 3.321928094887362; 00190 00191 inline long BigFloatRep::chunkCeil(long bits) { 00192 if (bits > 0) 00193 return (bits - 1) / CHUNK_BIT + 1; 00194 else 00195 return - (- bits) / CHUNK_BIT; 00196 }//chunkCeil 00197 00198 inline long BigFloatRep::chunkFloor(long bits) { 00199 if (bits >= 0) 00200 return bits / CHUNK_BIT; 00201 else 00202 return - (- bits - 1) / CHUNK_BIT - 1; 00203 }//chunkFloor 00204 00205 // bits(c) returns the number of bits in c chunks: 00206 inline long BigFloatRep::bits(long chunks) { 00207 return CHUNK_BIT * chunks; 00208 } 00209 00210 inline BigInt BigFloatRep::chunkShift(const BigInt& x, long s) { 00211 if (!s || sign(x) == 0) 00212 return x; 00213 else if (s > 0) 00214 // shift left 00215 if (sign(x) > 0) 00216 return x << static_cast<unsigned long>(bits(s)); 00217 else // x < 0 00218 return - ((-x) << static_cast<unsigned long>(bits(s))); 00219 else // shift right 00220 if (sign(x) > 0) 00221 return x >> static_cast<unsigned long>(bits(-s)); 00222 else // x < 0 00223 return - ((-x) >> static_cast<unsigned long>(bits(-s))); 00224 }//chunkShift 00225 00226 inline BigFloatRep* BigFloatRep::exp2(int e) { 00227 long ee; // this is going to be the exponent 00228 if (e >= 0) 00229 ee = e/CHUNK_BIT; 00230 else 00231 ee = - ((-e + CHUNK_BIT -1)/CHUNK_BIT); 00232 00233 int rem = e - (ee * CHUNK_BIT); // Assert: 0 <= rem < CHUNK_BIT 00234 00235 return new BigFloatRep((1<<rem), 0, ee); 00236 // Here, we assume CHUNK_BIT is less than int width 00237 } 00238 00239 // constructors 00240 inline BigFloatRep::BigFloatRep(short n) 00241 : m(n), err(0), exp(0) {} 00242 00243 inline BigFloatRep::BigFloatRep(float n) 00244 : m(n), err(0), exp(0) {} 00245 00246 // Chee (8/8/04) -- introduced constructor from int 00247 inline BigFloatRep::BigFloatRep(int n) 00248 : m(n), err(0), exp(0) {} 00249 00250 // Chee (8/8/04) -- introduced constructor from long 00251 inline BigFloatRep::BigFloatRep(long n) 00252 : m(n), err(0), exp(0) {} 00253 00254 // Chee (8/8/04) -- introduced constructor from double 00255 /* This turns out to be an alternative implementation of the 00256 * original one in BigFloat.cpp!! 00257 inline BigFloatRep::BigFloatRep(double d) 00258 : m(IntMantissa(d)), err(0), exp(0) { 00259 BigFloatRep * bfr = exp2(IntExponent(d)); // take care of the exponent 00260 m *= bfr->m; 00261 exp = bfr->exp; 00262 } 00263 */ 00264 00265 inline BigFloatRep::BigFloatRep(const BigInt& I, unsigned long er, long ex) 00266 : m(I), err(er), exp(ex) {} 00267 00268 inline BigFloatRep::BigFloatRep(const BigInt& I) 00269 : m(I), err(0), exp(0) {} 00270 00271 //Constructs the BigFloat representing I*2^{ex}. 00272 //If ex >=0 then it is clear how to do it. 00273 //Otherwise, let |ex| = CHUNK_BIT * q + r. Then 00274 //I*2^{ex} = I*2^{CHUNK_BIT -r} 2^{-CHUNK_BIT * (q+1)} 00275 inline BigFloatRep::BigFloatRep(const BigInt& I, long ex) { 00276 err=0; 00277 exp = chunkFloor(ex); 00278 if(ex >= 0) 00279 m = I<<(ex - bits(exp)); 00280 else{//ex < 0 00281 exp = chunkFloor(abs(ex)); 00282 m = I << (CHUNK_BIT - (-ex - bits(exp))); 00283 exp = -1*(1 + exp); 00284 } 00285 } 00286 00287 inline BigFloatRep::BigFloatRep(const char *str) : m(0), err(0), exp(0) { 00288 fromString(str); 00289 } 00290 00291 inline BigRat BigFloatRep::BigRatize() const { 00292 if (exp >= 0) 00293 return BigRat(chunkShift(m, exp), 1); 00294 else 00295 return BigRat(m, chunkShift(1, - exp)); 00296 } 00297 00298 // the destructor 00299 inline BigFloatRep::~BigFloatRep() {} 00300 00301 inline void BigFloatRep::approx(const BigRat& R, const extLong& r, const extLong& a) { 00302 div(numerator(R), denominator(R), r, a); 00303 } 00304 00305 // eliminate trailing zeroes 00306 inline void BigFloatRep::eliminateTrailingZeroes() { 00307 // eliminate trailing 0's -- IP 10/9/98 00308 /*if (err == 0 && m != 0) { 00309 while ((m & ((1 << CHUNK_BIT) - 1)) == 0) { 00310 m >>= CHUNK_BIT; 00311 exp++; 00312 } 00313 }*/ 00314 // new code, much faster, Zilin Du (Nov, 2003) 00315 if (err == 0 && sign(m) != 0) { 00316 int r = getBinExpo(m) / CHUNK_BIT; 00317 m >>= (r * CHUNK_BIT); 00318 exp += r; 00319 } 00320 } 00321 00322 // bultin functions 00323 inline extLong BigFloatRep::lMSB() const { 00324 if (!isZeroIn()) 00325 return extLong(floorLg(abs(m) - err)) + bits(exp); 00326 else 00327 return extLong(CORE_negInfty); 00328 } 00329 00331 00334 inline extLong BigFloatRep::uMSB() const { 00335 return extLong(floorLg(abs(m) + err)) + bits(exp); 00336 } 00337 00338 inline extLong BigFloatRep::MSB() const { 00339 // Note : MSB is undefined if it's not exact. 00340 if (sign(m)) // sign(m) is non-zero 00341 return extLong(floorLg(m)) + bits(exp); 00342 else 00343 return extLong(CORE_negInfty); 00344 } 00345 00346 inline extLong BigFloatRep::flrLgErr() const { 00347 if (err) 00348 return extLong(flrLg(err)) + bits(exp); 00349 else 00350 return extLong(CORE_negInfty); 00351 } 00352 00353 inline extLong BigFloatRep::clLgErr() const { 00354 if (err) 00355 return extLong(clLg(err)) + bits(exp); 00356 else 00357 return extLong(CORE_negInfty); 00358 } 00359 00360 // isZero() = true iff zero is inside the interval of BigFloat: 00361 inline bool BigFloatRep::isZeroIn() const { 00362 if (err == 0){ 00363 return (m == 0); //Nov 6, 2002: bug fix! 00364 } 00365 long lm = bitLength(m); 00366 if (lm > CHUNK_BIT+2) { 00367 return false; // since err < 4 * 2^{CHUNK_BIT} 00368 } else { 00369 return (abs(m) <= BigInt(err)); 00370 } 00371 } 00372 00373 inline int BigFloatRep::signM() const { 00374 return sign(m); 00375 } 00376 00377 inline double BigFloatRep::lg10(BigInt x) { 00378 if (x == 0) 00379 return 0; 00380 00381 BigInt t(abs(x)); 00382 long l = -1; 00383 double d = 0; 00384 00385 while (t > 0) { 00386 l++; 00387 d /= 10; 00388 d += ulongValue(t%10); 00389 t /= 10; 00390 } 00391 return std::log10(d) + l; 00392 } 00393 00394 // this is a simpler form of lg10() 00395 inline long BigFloatRep::floorlg10(BigInt x) { 00396 if (x == 0) 00397 return 0; 00398 BigInt t(abs(x)); 00399 long l = -1; 00400 00401 while (t > 0) { 00402 l++; 00403 t /= 10; 00404 } 00405 return l; 00406 } 00407 00408 inline std::ostream& BigFloatRep::operator<<(std::ostream& o) const { 00409 bool sci = (o.flags() & std::ios::scientific) > 0; 00410 BigFloatRep::DecimalOutput r = toDecimal(o.precision(), sci); 00411 if (r.sign == -1) 00412 o << "-"; 00413 o << r.rep; 00414 return o; 00415 } 00416 00417 /* Returns a std::string with precision and format specified 00418 Works as cout << with the exception that if the output 00419 contains any error it returns a NULL 00420 Joaquin Grech 31/5/03 00421 */ 00422 inline std::string BigFloatRep::toString(long prec, bool sci) const { 00423 BigFloatRep::DecimalOutput r = toDecimal(prec, sci); 00424 00425 if (r.errorCode == 0) { 00426 if (r.sign < 0) 00427 return std::string("-")+r.rep; 00428 else 00429 return r.rep; 00430 } 00431 return NULL; 00432 } 00433 00434 inline void BigFloatRep::dump() const { 00435 std::cout << "---- BFRep: " << this << " ----" << std::endl; 00436 std::cout << " BF value: "; 00437 this->operator<<(std::cout); 00438 std::cout << std::endl; 00439 std::cout << " m = " << m << std::endl; 00440 std::cout << " err = " << err << std::endl; 00441 std::cout << " exp = " << exp << std::endl; 00442 std::cout << " -- End of BFRep " << this << " -- " << std::endl; 00443 } 00444 00445 CORE_END_NAMESPACE 00446 #endif // _CORE_BIGFLOATREP_H_