BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/CORE/ExprRep.h
Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines