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: ExprRep.h 00019 * Synopsis: Internal Representation of Expr. 00020 * 00021 * Written by 00022 * Koji Ouchi <ouchi@simulation.nyu.edu> 00023 * Chee Yap <yap@cs.nyu.edu> 00024 * Igor Pechtchanski <pechtcha@cs.nyu.edu> 00025 * Vijay Karamcheti <vijayk@cs.nyu.edu> 00026 * Chen Li <chenli@cs.nyu.edu> 00027 * Zilin Du <zilin@cs.nyu.edu> 00028 * Sylvain Pion <pion@cs.nyu.edu> 00029 * Vikram Sharma<sharma@cs.nyu.edu> 00030 * 00031 * WWW URL: http://cs.nyu.edu/exact/ 00032 * Email: exact@cs.nyu.edu 00033 * 00034 * $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Core/include/CGAL/CORE/ExprRep.h $ 00035 * $Id: ExprRep.h 41739 2008-01-20 23:09:58Z spion $ 00036 ***************************************************************************/ 00037 00038 #ifndef _CORE_EXPRREP_H_ 00039 #define _CORE_EXPRREP_H_ 00040 00041 #include <CGAL/CORE/Real.h> 00042 #include <CGAL/CORE/Filter.h> 00043 #include <CGAL/CORE/poly/Sturm.h> 00044 00045 CORE_BEGIN_NAMESPACE 00046 00047 #ifdef CORE_DEBUG_BOUND 00048 // These counters are incremented each time each bound is recognized as equal 00049 // to the best one in computeBound(). 00050 extern unsigned int BFMSS_counter; 00051 extern unsigned int Measure_counter; 00052 // extern unsigned int Cauchy_counter; 00053 extern unsigned int LiYap_counter; 00054 // These counters are incremented each time each bound is recognized as equal 00055 // to the best one in computeBound(), and it's strictly the best. 00056 extern unsigned int BFMSS_only_counter; 00057 extern unsigned int Measure_only_counter; 00058 // extern unsigned int Cauchy_only_counter; 00059 extern unsigned int LiYap_only_counter; 00060 // This counter is incremented each time the precision needed matches the 00061 // root bound. 00062 extern unsigned int rootBoundHitCounter; 00063 #endif 00064 00065 const extLong EXTLONG_BIG = (1L << 30); 00066 const extLong EXTLONG_SMALL = -(1L << 30); 00067 00068 const double log_5 = log(double(5))/log(double(2)); 00069 00070 // Returns the ceil of log_2(5^a). 00071 inline extLong ceilLg5(const extLong & a) { 00072 #if defined (_MSC_VER) 00073 return (int) ::ceil(log_5 * a.toLong()); 00074 #else 00075 return (int) std::ceil(log_5 * a.toLong()); 00076 #endif 00077 } 00078 00081 struct NodeInfo { 00082 Real appValue; 00083 bool appComputed; 00084 bool flagsComputed; 00085 extLong knownPrecision; 00086 00087 #ifdef CORE_DEBUG 00088 extLong relPrecision; 00089 extLong absPrecision; 00090 unsigned long numNodes; 00091 #endif 00092 00094 00097 extLong d_e; 00098 00099 bool visited; 00100 int sign; 00101 00102 extLong uMSB; 00103 extLong lMSB; 00104 00105 // For the degree-length method mentioned in Chee's book. 00106 /* the degree of defining polynomial P(X) obtained from Resultant calculus 00107 * (deprecated now) */ 00108 // extLong degree; 00109 00110 // extLong length; ///< length is really lg(|| P(X) ||) 00111 extLong measure; 00112 00113 // For our new bound. 00115 00116 extLong high; 00118 00120 extLong low; 00123 extLong lc; 00126 extLong tc; 00127 00128 // For the 2-ary BFMSS bound. 00129 extLong v2p, v2m; 00130 // For the 5-ary BFMSS bound. 00131 extLong v5p, v5m; 00133 00134 extLong u25; 00136 00137 extLong l25; 00138 00139 int ratFlag; 00140 BigRat* ratValue; 00141 00143 NodeInfo(); 00144 };//NodeInfo struct 00145 00146 // forward reference 00147 // class Expr; 00148 00151 // Members: private: int refCount, 00152 // public: NodeInfo* nodeInfo, 00153 // filteredFp ffVal. 00154 class ExprRep { 00155 public: 00157 00158 00159 ExprRep(); 00161 virtual ~ExprRep() { 00162 if (nodeInfo != NULL) // This check is only for optimization. 00163 delete nodeInfo; 00164 } 00166 00168 00169 00170 void incRef() { 00171 ++refCount; 00172 } 00174 void decRef() { 00175 if (--refCount == 0) 00176 delete this; 00177 } 00179 int getRefCount() const { 00180 return refCount; 00181 } 00183 int isUnique() const { 00184 return refCount == 1; 00185 } 00187 00189 00190 00191 const Real & getAppValue(const extLong& relPrec = defRelPrec, 00192 const extLong& absPrec = defAbsPrec); 00194 int getSign(); 00195 int getExactSign(); 00196 00197 const Real& appValue() const { 00198 return nodeInfo->appValue; 00199 } 00200 Real& appValue() { 00201 return nodeInfo->appValue; 00202 } 00203 00204 const bool& appComputed() const { 00205 return nodeInfo->appComputed; 00206 } 00207 bool& appComputed() { 00208 return nodeInfo->appComputed; 00209 } 00210 00211 const bool& flagsComputed() const { 00212 return nodeInfo->flagsComputed; 00213 } 00214 bool& flagsComputed() { 00215 return nodeInfo->flagsComputed; 00216 } 00217 00218 const extLong& knownPrecision() const { 00219 return nodeInfo->knownPrecision; 00220 } 00221 extLong& knownPrecision() { 00222 return nodeInfo->knownPrecision; 00223 } 00224 00225 #ifdef CORE_DEBUG 00226 const extLong& relPrecision() const { 00227 return nodeInfo->relPrecision; 00228 } 00229 extLong& relPrecision() { 00230 return nodeInfo->relPrecision; 00231 } 00232 00233 const extLong& absPrecision() const { 00234 return nodeInfo->absPrecision; 00235 } 00236 extLong& absPrecision() { 00237 return nodeInfo->absPrecision; 00238 } 00239 00240 const unsigned long& numNodes() const { 00241 return nodeInfo->numNodes; 00242 } 00243 unsigned long& numNodes() { 00244 return nodeInfo->numNodes; 00245 } 00246 #endif 00247 00248 const extLong& d_e() const { 00249 return nodeInfo->d_e; 00250 } 00251 extLong& d_e() { 00252 return nodeInfo->d_e; 00253 } 00254 00255 const bool& visited() const { 00256 return nodeInfo->visited; 00257 } 00258 bool& visited() { 00259 return nodeInfo->visited; 00260 } 00261 00262 const int& sign() const { 00263 return nodeInfo->sign; 00264 } 00265 int& sign() { 00266 return nodeInfo->sign; 00267 } 00268 00269 const extLong& uMSB() const { 00270 return nodeInfo->uMSB; 00271 } 00272 extLong& uMSB() { 00273 return nodeInfo->uMSB; 00274 } 00275 00276 const extLong& lMSB() const { 00277 return nodeInfo->lMSB; 00278 } 00279 extLong& lMSB() { 00280 return nodeInfo->lMSB; 00281 } 00282 00283 // const extLong& length() const { return nodeInfo->length; } 00284 // extLong& length() { return nodeInfo->length; } 00285 00286 const extLong& measure() const { 00287 return nodeInfo->measure; 00288 } 00289 extLong& measure() { 00290 return nodeInfo->measure; 00291 } 00292 00293 const extLong& high() const { 00294 return nodeInfo->high; 00295 } 00296 extLong& high() { 00297 return nodeInfo->high; 00298 } 00299 00300 const extLong& low() const { 00301 return nodeInfo->low; 00302 } 00303 extLong& low() { 00304 return nodeInfo->low; 00305 } 00306 00307 const extLong& lc() const { 00308 return nodeInfo->lc; 00309 } 00310 extLong& lc() { 00311 return nodeInfo->lc; 00312 } 00313 00314 const extLong& tc() const { 00315 return nodeInfo->tc; 00316 } 00317 extLong& tc() { 00318 return nodeInfo->tc; 00319 } 00320 00321 const extLong& v2p() const { 00322 return nodeInfo->v2p; 00323 } 00324 extLong& v2p() { 00325 return nodeInfo->v2p; 00326 } 00327 00328 const extLong& v2m() const { 00329 return nodeInfo->v2m; 00330 } 00331 extLong& v2m() { 00332 return nodeInfo->v2m; 00333 } 00334 00335 extLong v2() const { 00336 return v2p()-v2m(); 00337 } 00338 00339 const extLong& v5p() const { 00340 return nodeInfo->v5p; 00341 } 00342 extLong& v5p() { 00343 return nodeInfo->v5p; 00344 } 00345 00346 const extLong& v5m() const { 00347 return nodeInfo->v5m; 00348 } 00349 extLong& v5m() { 00350 return nodeInfo->v5m; 00351 } 00352 00353 extLong v5() const { 00354 return v5p()-v5m(); 00355 } 00356 00357 const extLong& u25() const { 00358 return nodeInfo->u25; 00359 } 00360 extLong& u25() { 00361 return nodeInfo->u25; 00362 } 00363 00364 const extLong& l25() const { 00365 return nodeInfo->l25; 00366 } 00367 extLong& l25() { 00368 return nodeInfo->l25; 00369 } 00370 00371 const int& ratFlag() const { 00372 return nodeInfo->ratFlag; 00373 } 00374 int& ratFlag() { 00375 return nodeInfo->ratFlag; 00376 } 00377 00378 const BigRat* ratValue() const { 00379 return nodeInfo->ratValue; 00380 } 00381 BigRat*& ratValue() { 00382 return nodeInfo->ratValue; 00383 } 00384 00386 BigInt BigIntValue(); 00387 BigRat BigRatValue(); 00388 BigFloat BigFloatValue(); 00390 // toString() Joaquin Grech 31/5/2003 00391 std::string toString(long prec=defOutputDigits, bool sci=false) { 00392 return (getAppValue(defRelPrec, defAbsPrec)).toString(prec,sci); 00393 } 00395 00397 00398 00399 const std::string dump(int = OPERATOR_VALUE) const; 00401 virtual void debugList(int level, int depthLimit) const = 0; 00403 virtual void debugTree(int level, int indent, int depthLimit) const = 0; 00405 00407 00408 friend std::ostream& operator<<(std::ostream&, ExprRep&); 00410 00411 private: 00412 int refCount; // reference count 00413 00414 public: 00415 enum {OPERATOR_ONLY, VALUE_ONLY, OPERATOR_VALUE, FULL_DUMP}; 00416 00417 NodeInfo* nodeInfo; 00418 filteredFp ffVal; 00419 00421 00422 00423 virtual void initNodeInfo() = 0; 00425 virtual void computeExactFlags() = 0; 00427 extLong computeBound(); 00429 void approx(const extLong& relPrec, const extLong& absPrec); 00431 virtual void computeApproxValue(const extLong&, const extLong&) = 0; 00433 bool withinKnownPrecision(const extLong&, const extLong&); 00435 00437 00438 00439 void reduceToBigRat(const BigRat&); 00441 void reduceTo(const ExprRep*); 00443 void reduceToZero(); 00445 virtual const std::string op() const { 00446 return "UNKNOWN"; 00447 } 00449 00451 00452 00453 extLong degreeBound(); 00455 virtual extLong count() = 0; 00457 virtual void clearFlag() = 0; 00459 #ifdef CORE_DEBUG 00460 virtual unsigned long dagSize() = 0; 00461 virtual void fullClearFlag() = 0; 00462 #endif 00463 };//ExprRep 00464 00467 class ConstRep : public ExprRep { 00468 public: 00470 00471 00472 ConstRep() {} 00474 virtual ~ConstRep() {} 00476 00478 00479 00480 void debugList(int level, int depthLimit) const; 00482 void debugTree(int level, int indent, int depthLimit) const; 00484 protected: 00486 virtual void initNodeInfo(); 00488 const std::string op() const { 00489 return "C"; 00490 } 00492 //extLong count() { return d_e(); } 00493 extLong count(); 00495 void clearFlag() { 00496 visited() = false; 00497 } 00498 #ifdef CORE_DEBUG 00499 unsigned long dagSize(); 00500 void fullClearFlag(); 00501 #endif 00502 }; 00503 00506 class ConstDoubleRep : public ConstRep { 00507 public: 00509 00510 00511 ConstDoubleRep() {} 00513 ConstDoubleRep(double d) { 00514 ffVal = d; 00515 } 00517 ~ConstDoubleRep() {} 00519 CORE_MEMORY(ConstDoubleRep) 00520 protected: 00522 void computeExactFlags(); 00524 void computeApproxValue(const extLong&, const extLong&); 00525 }; 00526 00529 class ConstRealRep : public ConstRep { 00530 public: 00532 00533 00534 ConstRealRep() : value(CORE_REAL_ZERO) { } 00536 ConstRealRep(const Real &); 00538 ~ConstRealRep() {} 00540 CORE_MEMORY(ConstRealRep) 00541 private: 00542 Real value; 00543 protected: 00545 void computeExactFlags(); 00547 void computeApproxValue(const extLong&, const extLong&); 00548 }; 00549 00552 template <class NT> 00553 class ConstPolyRep : public ConstRep { 00554 public: 00556 00557 00558 ConstPolyRep() { } 00559 00561 ConstPolyRep(const Polynomial<NT>& p, int n) : ss(p) { 00562 // isolate roots using Sturm Sequences 00563 I = ss.isolateRoot(n); 00564 // check whether n-th root exists 00565 if (I.first == 1 && I.second == 0) { 00566 core_error("CORE ERROR! root index out of bound", 00567 __FILE__, __LINE__, true); 00568 abort(); 00569 } 00570 // test if the root isolated in I is 0: 00571 if ((I.first == 0)&&(I.second == 0)) 00572 ffVal = 0; 00573 else 00574 ffVal = computeFilteredValue(); // silly to use a filter here! 00575 // since sign is known. 00576 } 00577 00579 ConstPolyRep(const Polynomial<NT>& p, const BFInterval& II) 00580 : ss(p), I(II) { 00581 BFVecInterval v; 00582 ss.isolateRoots(I.first, I.second, v); 00583 I = v.front(); 00584 if (v.size() != 1) { 00585 core_error("CORE ERROR! non-isolating interval", 00586 __FILE__, __LINE__, true); 00587 abort(); 00588 } 00589 ffVal = computeFilteredValue(); // Chee: this line seems unnecessary 00590 } 00591 00593 ~ConstPolyRep() {} 00595 CORE_MEMORY(ConstPolyRep) 00596 00597 private: 00598 Sturm<NT> ss; 00599 BFInterval I; 00600 // IMPORTANT: I.first and I.second are exact BigFloats 00601 filteredFp computeFilteredValue() { 00602 // refine initial interval to absolute error of 2^(lMSB(k)-54) where 00603 // k is a lower bound on the root (use Cauchy Lower Bound). 00604 // Hence, the precision we pass to refine should be 54-lMSB(k). 00605 00606 // refine with newton (new method) 00607 // ss.seq[0] could be zero!! 00608 // I=ss.newtonRefine(I, 00609 // 54-(ss.seq[0].CauchyLowerBound()).lMSB().asLong()); 00610 extLong lbd = ss.seq[0].CauchyLowerBound().lMSB(); 00611 00612 if (lbd.isTiny()) 00613 I = ss.newtonRefine(I, 54); 00614 else 00615 I = ss.newtonRefine(I, 54-lbd.asLong()); // is this necessary? 00616 00617 //return I.first.doubleValue(); // NOTE: This is not quite right! 00618 // It should be "centralized" to set 00619 // the error bit correctly. 00620 // E.g., otherwise, radical(4,2) will print wrongly. 00621 if ((I.first == 0) && (I.second == 0)) // Checkfor zero value 00622 return filteredFp(0); 00623 BigFloat x = centerize(I.first, I.second); 00624 double val = x.doubleValue(); 00625 double max = core_max(core_abs(I.first), core_abs(I.second)).doubleValue(); 00626 int ind = 1; 00627 /* 00628 long ee = x.exp()*CHUNK_BIT; 00629 unsigned long err = ee > 0 ? (x.err() << ee) : (x.err() >> (-ee)); 00630 double max = core_abs(val) + err; 00631 int ind = longValue((BigInt(x.err()) << 53) / (x.m() + x.err())); 00632 */ 00633 return filteredFp(val, max, ind); // Aug 8, 2004, Comment from Chee: 00634 // I think we should get rid of filters here! Given the interval I, 00635 // we either know the sign (I.first >=0) or (I.second <=0) 00636 // or we don't. We don't need to compute all the index stuff. 00637 // In fact, you have lost the sign in the above computation... 00638 // ALSO, why bother to use filter? 00639 }//computeFilteredValue 00640 00641 protected: 00642 void initNodeInfo() { 00643 nodeInfo = new NodeInfo(); 00644 d_e() = ss.seq[0].getTrueDegree(); // return degree of the polynomial 00645 } 00647 void computeExactFlags() { 00648 00649 if ((I.first == 0) && (I.second == 0)) { 00650 reduceToZero(); 00651 return; 00652 } else if (I.second > 0) { 00653 uMSB() = I.second.uMSB(); 00654 lMSB() = I.first.lMSB(); 00655 sign() = 1; 00656 } else { // we know that I.first < 0 00657 lMSB() = I.second.lMSB(); 00658 uMSB() = I.first.uMSB(); 00659 sign() = -1; 00660 } 00661 // length() = 1+ ss.seq[0].length().uMSB(); 00662 measure() = 1+ ss.seq[0].length().uMSB(); // since measure<= length 00663 00664 // compute u25, l25, v2p, v2m, v5p, v5m 00665 v2p() = v2m() = v5p() = v5m() = 0; 00666 u25() = 1+ss.seq[0].CauchyUpperBound().uMSB(); 00667 l25() = ceilLg(ss.seq[0].getLeadCoeff()); // assumed coeff is integer!! 00668 // ceilLg(BigInt) and ceilLg(Expr) are defined. But if 00669 // NT=int, ceilLg(int) is ambiguous! Added ceilLg(int) 00670 // under BigInt.h 00671 00672 // compute high, low, lc, tc 00673 high() = u25(); 00674 low() = - (ss.seq[0].CauchyLowerBound().lMSB()); // note the use of negative 00675 lc() = l25(); 00676 tc() = ceilLg(ss.seq[0].getTailCoeff()); 00677 00678 // no rational reduction 00679 if (rationalReduceFlag) 00680 ratFlag() = -1; 00681 00682 flagsComputed() = true; 00683 appValue()=centerize(I.first, I.second);// set an initial value for appValue 00684 } 00686 void computeApproxValue(const extLong& relPrec, const extLong& absPrec) { 00687 extLong pr = -lMSB() + relPrec; 00688 extLong p = pr < absPrec ? pr : absPrec; 00689 00690 // bisection sturm (old method) 00691 //I = ss.refine(I, p.asLong()+1); 00692 00693 // refine with newton (new method) 00694 I = ss.newtonRefine(I, p.asLong()+1); 00695 appValue() = centerize(I.first, I.second); 00696 } 00697 }; 00700 class UnaryOpRep : public ExprRep { 00701 public: 00703 00704 00705 UnaryOpRep(ExprRep* c) : child(c) { 00706 child->incRef(); 00707 } 00709 virtual ~UnaryOpRep() { 00710 child->decRef(); 00711 } 00713 00715 00716 00717 void debugList(int level, int depthLimit) const; 00719 void debugTree(int level, int indent, int depthLimit) const; 00721 protected: 00722 ExprRep* child; 00723 00724 virtual void initNodeInfo(); 00726 void clearFlag(); 00727 #ifdef CORE_DEBUG 00728 unsigned long dagSize(); 00729 void fullClearFlag(); 00730 #endif 00731 }; 00732 00735 class NegRep : public UnaryOpRep { 00736 public: 00738 00739 00740 NegRep(ExprRep* c) : UnaryOpRep(c) { 00741 ffVal = - child->ffVal; 00742 } 00744 ~NegRep() {} 00746 00747 CORE_MEMORY(NegRep) 00748 protected: 00750 void computeExactFlags(); 00752 void computeApproxValue(const extLong&, const extLong&); 00754 const std::string op() const { 00755 return "Neg"; 00756 } 00758 00760 extLong count(); 00761 }; 00762 00765 class SqrtRep : public UnaryOpRep { 00766 public: 00768 00769 00770 SqrtRep(ExprRep* c) : UnaryOpRep(c) { 00771 ffVal = (child->ffVal).sqrt(); 00772 } 00774 ~SqrtRep() {} 00776 00777 CORE_MEMORY(SqrtRep) 00778 protected: 00780 void computeExactFlags(); 00782 void computeApproxValue(const extLong&, const extLong&); 00784 const std::string op() const { 00785 return "Sqrt"; 00786 } 00788 00790 extLong count(); 00791 }; 00792 00795 class BinOpRep : public ExprRep { 00796 public: 00798 00799 00800 BinOpRep(ExprRep* f, ExprRep* s) : first(f), second(s) { 00801 first->incRef(); 00802 second->incRef(); 00803 } 00805 virtual ~BinOpRep() { 00806 first->decRef(); 00807 second->decRef(); 00808 } 00810 00812 00813 00814 void debugList(int level, int depthLimit) const; 00816 void debugTree(int level, int indent, int depthLimit) const; 00818 protected: 00819 ExprRep* first; 00820 ExprRep* second; 00821 00823 virtual void initNodeInfo(); 00825 void clearFlag(); 00827 00829 extLong count(); 00830 #ifdef CORE_DEBUG 00831 unsigned long dagSize(); 00832 void fullClearFlag(); 00833 #endif 00834 }; 00835 00838 struct Add { 00840 static const char* name; 00841 00843 template <class T> 00844 const T& operator()(const T& t) const { 00845 return t; 00846 } 00847 00849 template <class T> 00850 T operator()(const T& a, const T& b) const { 00851 return a+b; 00852 } 00853 }; 00854 00857 struct Sub { 00859 static const char* name; 00860 00862 template <class T> 00863 T operator()(const T& t) const { 00864 return -t; 00865 } 00866 00868 template <class T> 00869 T operator()(const T& a, const T& b) const { 00870 return a-b; 00871 } 00872 }; 00873 00876 template <class Operator> 00877 class AddSubRep : public BinOpRep { 00878 public: 00880 00881 00882 AddSubRep(ExprRep* f, ExprRep* s) : BinOpRep(f, s) { 00883 ffVal = Op(first->ffVal, second->ffVal); 00884 } 00886 ~AddSubRep() {} 00888 00889 CORE_MEMORY(AddSubRep) 00890 protected: 00892 void computeExactFlags(); 00894 void computeApproxValue(const extLong&, const extLong&); 00896 const std::string op() const { 00897 return Operator::name; 00898 } 00899 private: 00900 static Operator Op; 00901 };//AddSubRep class 00902 00903 template <class Operator> 00904 Operator AddSubRep<Operator>::Op; 00905 00910 template <class Operator> 00911 void AddSubRep<Operator>::computeExactFlags() { 00912 if (!first->flagsComputed()) 00913 first->computeExactFlags(); 00914 if (!second->flagsComputed()) 00915 second->computeExactFlags(); 00916 00917 int sf = first->sign(); 00918 int ss = second->sign(); 00919 00920 if ((sf == 0) && (ss == 0)) { // the node is zero 00921 reduceToZero(); 00922 return; 00923 } else if (sf == 0) { // first operand is zero 00924 reduceTo(second); 00925 sign() = Op(ss); 00926 appValue() = Op(appValue()); 00927 if (rationalReduceFlag && ratFlag() > 0) 00928 *(ratValue()) = Op(*(ratValue())); 00929 return; 00930 } else if (ss == 0) { // second operand is zero 00931 reduceTo(first); 00932 return; 00933 } 00934 // rational node 00935 if (rationalReduceFlag) { 00936 if (first->ratFlag() > 0 && second->ratFlag() > 0) { 00937 BigRat val=Op(*(first->ratValue()), *(second->ratValue())); 00938 reduceToBigRat(val); 00939 ratFlag() = first->ratFlag() + second->ratFlag(); 00940 return; 00941 } else 00942 ratFlag() = -1; 00943 } 00944 00945 // neither operand is zero 00946 extLong df = first->d_e(); 00947 extLong ds = second->d_e(); 00948 // extLong md = df < ds ? df : ds; 00949 // extLong l1 = first->length(); 00950 // extLong l2 = second->length(); 00951 extLong m1 = first->measure(); 00952 extLong m2 = second->measure(); 00953 00954 // length() = df * l2 + ds * l1 + d_e() + md; 00955 measure() = m1 * ds + m2 * df + d_e(); 00956 00957 // BFMSS[2,5] bound. 00958 v2p() = core_min(first->v2p() + second->v2m(), 00959 first->v2m() + second->v2p()); 00960 v2m() = first->v2m() + second->v2m(); 00961 v5p() = core_min(first->v5p() + second->v5m(), 00962 first->v5m() + second->v5p()); 00963 v5m() = first->v5m() + second->v5m(); 00964 00965 if (v2p().isInfty() || v5p().isInfty()) 00966 u25() = CORE_INFTY; 00967 else 00968 u25() = EXTLONG_ONE + core_max(first->v2p() + second->v2m() 00969 - v2p() + ceilLg5(first->v5p() + second->v5m() - v5p()) 00970 + first->u25() + second->l25(), 00971 first->v2m() + second->v2p() - v2p() 00972 + ceilLg5(first->v5m() + second->v5p() - v5p()) 00973 + first->l25() + second->u25()); 00974 l25() = first->l25() + second->l25(); 00975 00976 lc() = ds * first->lc() + df * second->lc(); 00977 tc() = measure(); 00978 00979 high() = core_max(first->high(),second->high())+EXTLONG_ONE; 00980 // The following is a subset of the minimization in computeBound(). 00981 low() = core_min(measure(), (d_e()-EXTLONG_ONE)*high() + lc()); 00982 00983 extLong lf = first->lMSB(); 00984 extLong ls = second->lMSB(); 00985 extLong uf = first->uMSB(); 00986 extLong us = second->uMSB(); 00987 00988 extLong l = core_max(lf, ls); 00989 extLong u = core_max(uf, us); 00990 00991 #ifdef CORE_TRACE 00992 std::cout << "INSIDE Add/sub Rep: " << std::endl; 00993 #endif 00994 00995 if (Op(sf, ss) != 0) { // can't possibly cancel out 00996 #ifdef CORE_TRACE 00997 std::cout << "Add/sub Rep: Op(sf, ss) non-zero" << std::endl; 00998 #endif 00999 01000 uMSB() = u + EXTLONG_ONE; 01001 lMSB() = l; // lMSB = core_min(lf, ls)+1 better 01002 sign() = sf; 01003 } else { // might cancel out 01004 #ifdef CORE_TRACE 01005 std::cout << "Add/sub Rep: Op(sf, ss) zero" << std::endl; 01006 #endif 01007 01008 uMSB() = u + EXTLONG_ONE; 01009 uMSB() = u; 01010 if (lf >= us + EXTLONG_TWO) {// one is at least 1 order of magnitude larger 01011 #ifdef CORE_TRACE 01012 std::cout << "Add/sub Rep: Can't cancel" << std::endl; 01013 #endif 01014 01015 lMSB() = lf - EXTLONG_ONE; // can't possibly cancel out 01016 sign() = sf; 01017 } else if (ls >= uf + EXTLONG_TWO) { 01018 #ifdef CORE_TRACE 01019 std::cout << "Add/sub Rep: Can't cancel" << std::endl; 01020 #endif 01021 01022 lMSB() = ls - EXTLONG_ONE; 01023 sign() = Op(ss); 01024 } else if (ffVal.isOK()) {// begin filter computation 01025 #ifdef CORE_TRACE 01026 std::cout << "Add/sub Rep: filter used" << std::endl; 01027 #endif 01028 #ifdef CORE_DEBUG_FILTER 01029 std::cout << "call filter in " << op() << "Rep" << std::endl; 01030 #endif 01031 sign() = ffVal.sign(); 01032 lMSB() = ffVal.lMSB(); 01033 uMSB() = ffVal.uMSB(); 01034 } else { // about the same size, might cancel out 01035 #ifdef CORE_TRACE 01036 std::cout << "Add/sub Rep: iteration start" << std::endl; 01037 #endif 01038 01039 extLong lowBound = computeBound(); 01040 /* Zilin 06/11/2003 01041 * as BFMSS[2] might be a negative number, lowBound can be negative. 01042 * In this case, we just set it to 1 since we need at least one bit 01043 * to get the sign. In the future, we may need to improve this. 01044 */ 01045 if (lowBound <= EXTLONG_ZERO) 01046 lowBound = EXTLONG_ONE; 01047 01048 if (!progressiveEvalFlag) { 01049 // convert the absolute error requirement "lowBound" to 01050 // a relative error requirement "ur", s.t. 01051 // |x|*2^(-ur) <= 2^(-lowBound). 01052 // ==> r >= a + lg(x) >= a + (uMSB + 1); 01053 // extLong rf = lowBound + (uf + 1); 01054 // extLong rs = lowBound + (us + 1); 01055 // first->approx(rf, CORE_INFTY); 01056 // second->approx(rs, CORE_INFTY); 01057 // Chen: considering the uMSB is also an approximate bound. 01058 // we choose to use absolute precision up-front. 01059 Real newValue = Op(first->getAppValue(CORE_INFTY, 01060 lowBound + EXTLONG_ONE), 01061 second->getAppValue(CORE_INFTY, 01062 lowBound + EXTLONG_ONE)); 01063 if (!newValue.isZeroIn()) { // Op(first, second) != 0 01064 lMSB() = newValue.lMSB(); 01065 uMSB() = newValue.uMSB(); // chen: to get tighers value. 01066 sign() = newValue.sign(); 01067 } else if (lowBound.isInfty()) {//check if rootbound is too big 01068 core_error("AddSubRep:root bound has exceeded the maximum size\n \ 01069 but we still cannot decide zero.\n", __FILE__, __LINE__, false); 01070 } else { // Op(first, second) == 0 01071 lMSB() = CORE_negInfty; 01072 sign() = 0; 01073 } 01074 } else { // else do progressive evaluation 01075 #ifdef CORE_TRACE 01076 std::cout << "Add/sub Rep: progressive eval" << std::endl; 01077 #endif 01078 // Oct 30, 2002: fixed a bug here! Old versions used relative 01079 // precision bounds, but one should absolute precision for addition! 01080 // Moreover, this is much more efficient. 01081 01082 // ua is the upper bound on the absolute precision in our iteration 01083 // Chee, Aug 8, 2004: it is important that ua be strictly 01084 // larger than lowBound AND the defaultInitialProgressivePrec, 01085 // so that we do at least one iteration of the for-loop. So: 01086 // i is the variable for iteration. 01087 extLong i = core_min(defInitialProgressivePrec, lowBound.asLong()); 01088 extLong ua = lowBound.asLong() + EXTLONG_ONE; 01089 // NOTE: ua is allowed to be CORE_INFTY 01090 01091 #ifdef CORE_DEBUG_BOUND 01092 std::cout << "DebugBound:" << "ua = " << ua << std::endl; 01093 #endif 01094 // We initially set the lMSB and sign as if the value is zero: 01095 lMSB() = CORE_negInfty; 01096 sign() = 0; 01097 01098 EscapePrecFlag = 0; // reset the Escape Flag 01099 01100 // Now we try to determine the real lMSB and sign, 01101 // in case it is not really zero: 01102 #ifdef CORE_TRACE 01103 std::cout << "Upper bound (ua) for iteration is " << ua << std::endl; 01104 std::cout << "Starting iteration at i = " << i << std::endl; 01105 #endif 01106 01107 for ( ; i<ua; i*=EXTLONG_TWO) { 01108 // relative bits = i 01109 // 01110 // PROBLEM WITH NEXT LINE: you must ensure that 01111 // first and second are represented by BigFloats... 01112 // 01113 Real newValue = Op(first->getAppValue(CORE_INFTY, i), 01114 second->getAppValue(CORE_INFTY, i)); 01115 01116 #ifdef CORE_TRACE 01117 if (newValue.getRep().ID() == REAL_BIGFLOAT) 01118 std::cout << "BigFloat! newValue->rep->ID() = " 01119 << newValue.getRep().ID() << std::endl; 01120 else 01121 std::cout << "ERROR, Not BigFloat! newValue->rep->ID() =" 01122 << newValue.getRep().ID() << std::endl; 01123 std::cout << "newValue = Op(first,second) = " 01124 << newValue << std::endl; 01125 std::cout << "first:appVal, appComputed, knownPrec, sign =" 01126 << first->appValue() << "," 01127 << first->appComputed() << "," 01128 << first->knownPrecision() << "," 01129 << first->sign() << std::endl; 01130 std::cout << "second:appVal, appComputed, knownPrec, sign =" 01131 << second->appValue() << "," 01132 << second->appComputed() << "," 01133 << second->knownPrecision() << "," 01134 << second->sign() << std::endl; 01135 #endif 01136 if (!newValue.isZeroIn()) { // Op(first, second) != 0 01137 lMSB() = newValue.lMSB(); 01138 uMSB() = newValue.uMSB(); 01139 sign() = newValue.sign(); 01140 #ifdef CORE_DEBUG_BOUND 01141 std::cout << "DebugBound(Exit Loop): " << "i=" << i << std::endl; 01142 #endif 01143 #ifdef CORE_TRACE 01144 std::cout << "Zero is not in, lMSB() = " << lMSB() 01145 << ", uMSB() = " << uMSB() 01146 << ", sign() = " << sign() << std::endl; 01147 std::cout << "newValue = " << newValue << std::endl; 01148 #endif 01149 01150 break; // assert -- this must happen in the loop if nonzero! 01151 } 01152 //8/9/01, Chee: implement escape precision here: 01153 if (i> EscapePrec) { 01154 EscapePrecFlag = -i.asLong();//negative means EscapePrec is used 01155 core_error("Escape precision triggered at", 01156 __FILE__, __LINE__, false); 01157 if (EscapePrecWarning) 01158 std::cout<< "Escape Precision triggered at " 01159 << EscapePrec << " bits" << std::endl; 01160 #ifdef CORE_DEBUG 01161 std::cout << "EscapePrecFlags=" << EscapePrecFlag << std::endl; 01162 std::cout << "ua =" << ua << ",lowBound=" << lowBound << std::endl; 01163 #endif 01164 break; 01165 }// if 01166 }// for (long i=1...) 01167 01168 #ifdef CORE_DEBUG_BOUND 01169 rootBoundHitCounter++; 01170 #endif 01171 01172 if (sign() == 0 && ua .isInfty()) { 01173 core_error("AddSubRep: root bound has exceeded the maximum size\n \ 01174 but we still cannot decide zero.\n", __FILE__, __LINE__, true); 01175 } // if (sign == 0 && ua .isInfty()) 01176 }// else do progressive 01177 } 01178 } 01179 flagsComputed() = true; 01180 }// AddSubRep::computeExactFlags 01181 01182 template <class Operator> 01183 void AddSubRep<Operator>::computeApproxValue(const extLong& relPrec, 01184 const extLong& absPrec) { 01185 // Nov 13, 2002: added the analog of "reduceTo(first)" and "reduceTo(second)" 01186 // that is found in computeExactFlags. This is more efficient, but 01187 // it also removes a NaN warning in subsequent logic! 01188 // E.g., if first=0, then first->uMSB and first->lMSB are -infty, and 01189 // subtracting them creates NaN. Chee and Zilin. 01190 if (first->sign() == 0) { 01191 appValue() = Op(second->getAppValue(relPrec, absPrec)); 01192 return; 01193 } 01194 if (second->sign() == 0) { 01195 appValue() = first->getAppValue(relPrec, absPrec); 01196 return; 01197 } 01198 if (lMSB() < EXTLONG_BIG && lMSB() > EXTLONG_SMALL) { 01199 extLong rf = first->uMSB()-lMSB()+relPrec+EXTLONG_FOUR; // 2 better 01200 if (rf < EXTLONG_ZERO) 01201 rf = EXTLONG_ZERO; // from Koji's thesis P63: Proposition 26 01202 extLong rs = second->uMSB()-lMSB()+relPrec+EXTLONG_FOUR; // 2 better 01203 if (rs < EXTLONG_ZERO) 01204 rs = EXTLONG_ZERO; // from Koji's thesis P63: Proposition 26 01205 extLong a = absPrec + EXTLONG_THREE; // 1 better 01206 appValue() = Op(first->getAppValue(rf, a), second->getAppValue(rs, a)); 01207 } else { 01208 std::cerr << "lMSB = " << lMSB() << std::endl; // should be in core_error 01209 core_error("CORE WARNING: a huge lMSB in AddSubRep", 01210 __FILE__, __LINE__, false); 01211 } 01212 } 01213 01216 typedef AddSubRep<Add> AddRep; 01217 01220 typedef AddSubRep<Sub> SubRep; 01221 01224 class MultRep : public BinOpRep { 01225 public: 01227 01228 01229 MultRep(ExprRep* f, ExprRep* s) : BinOpRep(f, s) { 01230 ffVal = first->ffVal * second->ffVal; 01231 } 01233 ~MultRep() {} 01235 01236 CORE_MEMORY(MultRep) 01237 protected: 01239 void computeExactFlags(); 01241 void computeApproxValue(const extLong&, const extLong&); 01243 const std::string op() const { 01244 return "*"; 01245 } 01246 }; 01247 01250 class DivRep : public BinOpRep { 01251 public: 01253 01254 01255 DivRep(ExprRep* f, ExprRep* s) : BinOpRep(f, s) { 01256 ffVal = first->ffVal / second->ffVal; 01257 } 01259 ~DivRep() {} 01261 01262 CORE_MEMORY(DivRep) 01263 protected: 01265 void computeExactFlags(); 01267 void computeApproxValue(const extLong&, const extLong&); 01269 const std::string op() const { 01270 return "/"; 01271 } 01272 }; 01273 01274 // inline functions 01275 inline int ExprRep::getExactSign() { 01276 if (!nodeInfo) 01277 initNodeInfo(); 01278 01279 if (!flagsComputed()) { 01280 degreeBound(); 01281 #ifdef CORE_DEBUG 01282 dagSize(); 01283 fullClearFlag(); 01284 #endif 01285 computeExactFlags(); 01286 } 01287 return sign(); 01288 } 01289 01290 // Chee, 7/17/02: degreeBound() function is now 01291 // taken out of "computeExactFlags() 01292 inline int ExprRep::getSign() { 01293 if (ffVal.isOK()) 01294 return ffVal.sign(); 01295 else 01296 return getExactSign(); 01297 } 01298 01299 // you need force to approximate before call these functions!! 01300 inline BigInt ExprRep::BigIntValue() { 01301 return getAppValue().BigIntValue(); 01302 } 01303 01304 inline BigRat ExprRep::BigRatValue() { 01305 return getAppValue().BigRatValue(); 01306 } 01307 01308 inline BigFloat ExprRep::BigFloatValue() { 01309 return getAppValue().BigFloatValue(); 01310 } 01311 01312 CORE_END_NAMESPACE 01313 #endif // _CORE_EXPRREP_H_