📄 expr.h
字号:
/**************************************************************************** * Core Library Version 1.7, August 2004 * Copyright (c) 1995-2004 Exact Computation Project * All rights reserved. * * This file is part of CORE (http://cs.nyu.edu/exact/core/); you may * redistribute it under the terms of the Q Public License version 1.0. * See the file LICENSE.QPL distributed with CORE. * * Licensees holding a valid commercial license may use this file in * accordance with the commercial license agreement provided with the * software. * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * * File: Expr.h * Synopsis: a class of Expression in Level 3 * * Written by * Koji Ouchi <ouchi@simulation.nyu.edu> * Chee Yap <yap@cs.nyu.edu> * Igor Pechtchanski <pechtcha@cs.nyu.edu> * Vijay Karamcheti <vijayk@cs.nyu.edu> * Chen Li <chenli@cs.nyu.edu> * Zilin Du <zilin@cs.nyu.edu> * Sylvain Pion <pion@cs.nyu.edu> * Vikram Sharma<sharma@cs.nyu.edu> * * WWW URL: http://cs.nyu.edu/exact/ * Email: exact@cs.nyu.edu * * $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.3-branch/Core/include/CGAL/CORE/Expr.h $ * $Id: Expr.h 37555 2007-03-27 11:33:02Z afabri $ ***************************************************************************/#ifndef _CORE_EXPR_H_#define _CORE_EXPR_H_#include <CGAL/CORE/ExprRep.h>CORE_BEGIN_NAMESPACE/// \class Expr Expr.h/// \brief Expr is a class of Expression in Level 3typedef RCImpl<ExprRep> RCExpr;class Expr : public RCExpr {public: /// \name Constructors and Destructor //@{ /// default constructor Expr() : RCExpr(new ConstDoubleRep()) {} /// constructor for <tt>int</tt> Expr(int i) : RCExpr(new ConstDoubleRep(i)) {} /// constructor for <tt>short</tt> Expr(short i) : RCExpr(new ConstDoubleRep(i)) {} /// constructor for <tt>unsigned int</tt> Expr(unsigned int ui) : RCExpr(new ConstDoubleRep(ui)) {} /// constructor for <tt>long</tt> Expr(long l) : RCExpr(new ConstRealRep(Real(l))) {} /// constructor for <tt>unsigned long</tt> Expr(unsigned long ul) : RCExpr(new ConstRealRep(Real(ul))) {} /// constructor for <tt>float</tt> /** \note the results of this constructor may appear unpredictable to the * user. E.g., one may assume that new Expr(.1) is exactly equal to .1, * but it will be print as * .1000000000000000055511151231257827021181583404541015625. * This is so because .1 cannot be represented exactly as a double * (or, for that matter, as a binary fraction of any finite length). * The value is the closest double value determined by the compiler. */ Expr(float f) : RCExpr(NULL) { // check for valid numbers // (i.e., not infinite and not NaN) if (!finite(f)) { std::cerr << " ERROR : constructed an invalid float! " << std::endl; if (AbortFlag) abort(); InvalidFlag = -1; } rep = new ConstDoubleRep(f); } /// constructor for <tt>double</tt> Expr(double d) : RCExpr(NULL) { // check for valid numbers // (i.e., not infinite and not NaN) if (!finite(d)) { std::cerr << " ERROR : constructed an invalid double! " << std::endl; if (AbortFlag) abort(); InvalidFlag = -2; } rep = new ConstDoubleRep(d); } /// constructor for <tt>BigInt</tt> Expr(const BigInt& I) : RCExpr(new ConstRealRep(Real(I))) {} /// constructor for <tt>BigRat</tt> Expr(const BigRat& R) : RCExpr(new ConstRealRep(Real(R))) {} /// constructor for <tt>BigFloat</tt> Expr(const BigFloat& F) : RCExpr(new ConstRealRep(Real(F))) {} /// constructor for <tt>const char*</tt> /** construct Expr from a string representation \a s * with precision \a prec. It is perfectly predictable: * new Expr(".1") is exactly equal to .1, as one would expect. Therefore, * it is generally recommended that the (String) constructor be used in * preference to the (double) constructor. */ Expr(const char *s, const extLong& p = defInputDigits) : RCExpr(new ConstRealRep(Real(s, p))) {} /// constructor for <tt>std::string</tt> Expr(const std::string& s, const extLong& p = defInputDigits) : RCExpr(new ConstRealRep(Real(s, p))) {} /// constructor for <tt>Real</tt> Expr(const Real &r) : RCExpr(new ConstRealRep(r)) {} /// constructor for Polynomial node (n-th root) /** default value n=0 means the first positive root */ template <class NT> Expr(const Polynomial<NT>& p, int n = 0) : RCExpr(new ConstPolyRep<NT>(p, n)) {} /// constructor for Polynomial node (root in Interval <tt>I</tt>) template <class NT> Expr(const Polynomial<NT>& p, const BFInterval& I) : RCExpr(new ConstPolyRep<NT>(p, I)) {} /// constructor for ExprRep Expr(ExprRep* p) : RCExpr(p) {} //@} /// \name Copy-Assignment-Destructors //@{ /// copy constructor Expr(const Expr& rhs) : RCExpr(rhs) { rep->incRef(); } /// = operator Expr& operator=(const Expr& rhs) { if (this != &rhs) { rep->decRef(); rep = rhs.rep; rep->incRef(); } return *this; } /// destructor ~Expr() { rep->decRef(); } //@} /// \name Compound Assignment Operators //@{ /// += operator Expr& operator+=(const Expr& e) { *this = new AddRep(rep, e.rep); return *this; } /// -= operator Expr& operator-=(const Expr& e) { *this = new SubRep(rep, e.rep); return *this; } /// *= operator Expr& operator*=(const Expr& e) { *this = new MultRep(rep, e.rep); return *this; } /// /= operator Expr& operator/=(const Expr& e) { if ((e.rep)->getSign() == 0) { std::cerr << " ERROR : division by zero ! " << std::endl; if (AbortFlag) abort(); InvalidFlag = -3; } *this = new DivRep(rep, e.rep); return *this; } //@} /// \name Unary Minus, Increment and Decrement Operators //@{ /// unary plus Expr operator+() const { return Expr(*this); } /// unary minus Expr operator-() const { return Expr(new NegRep(rep)); } /// left increment operator (++i) Expr& operator++() { *this += 1; return *this; } /// right increment operator (i++) Expr operator++(int) { Expr t(*this); *this += 1; return t; } /// left decrement operator (--i) Expr& operator--() { *this -= 1; return *this; } /// right deccrement operator (i--) Expr operator--(int) { Expr t(*this); *this -= 1; return t; } //@} /// \name String Conversion Functions //@{ /// set value from <tt>const char*</tt> void fromString(const char* s, const extLong& prec = defInputDigits) { *this = Expr(s, prec); } /// convert to <tt>std::string</tt> /** give decimal string representation */ std::string toString(long prec=defOutputDigits, bool sci=false) const { return rep->toString(prec, sci); } //@} // /// \name Conversion Functions //@{ /// convert to \c int int intValue() const { return approx(64, 1024).intValue(); } /// convert to \c long long longValue() const { return approx(64, 1024).longValue(); } /// convert to \c float float floatValue() const { return approx(53, 1024).floatValue(); } /// convert to \c double /** chen: - use equivalent precision (rel:53, abs: 1024) as in IEEE double. enforce an evaluation in case before this has been done before casting. */ double doubleValue() const { return approx(53, 1024).doubleValue(); } /// convert to an interval defined by a pair of \c double /** If value is exact, the two \c double will coincide */ void doubleInterval(double & lb, double & ub) const; /// convert to \c BigInt (approximate it first!) BigInt BigIntValue() const { return rep->BigIntValue(); } /// convert to \c BigRat (approximate it first!) BigRat BigRatValue() const { return rep->BigRatValue(); } /// convert to \c BigFloat (approximate it first!) /** Ought to allow BigFloatValue() take an optional precision argument */ BigFloat BigFloatValue() const { return rep->BigFloatValue(); } //@} /// \name Approximation Function //@{ /// Compute approximation to combined precision [\a r, \a a]. /** Here is the definition of what this means: If e is the exact value and ee is the approximate value, then |e - ee| <= 2^{-a} or |e - ee| <= 2^{-r} |e|. */ const Real & approx(const extLong& relPrec = defRelPrec, const extLong& absPrec = defAbsPrec) const { return rep->getAppValue(relPrec, absPrec); } //@} /// \name Helper Functions //@{ //CONSTANTS: /// return Expr(0) static const Expr& getZero(); /// return Expr(1) static const Expr& getOne(); /// Has Exact Division static bool hasExactDivision() { return true; } /// get the sign int sign() const { return rep->getSign(); } /// is zero? bool isZero() const { return sign() == 0; } /// absolute value Expr abs() const { return (sign() >= 0) ? +(*this) : -(*this); } /// compare function int cmp(const Expr& e) const { return rep == e.rep ? 0 : SubRep(rep, e.rep).getSign(); } /// return the internal representation ExprRep* Rep() const { return rep; } /// get exponent of current approximate value long getExponent() const { return BigFloatValue().exp(); } /// get mantissa of current approximate value BigInt getMantissa() const { return BigFloatValue().m(); } //@}public: /// \name Debug Helper Function //@{ /// debug function void debug(int mode = TREE_MODE, int level = DETAIL_LEVEL, int depthLimit = INT_MAX) const; //@} /// debug information levels enum {LIST_MODE, TREE_MODE, SIMPLE_LEVEL, DETAIL_LEVEL};};// class Expr#define CORE_EXPR_ZERO Expr::getZero()/// I/O Stream operator<<inline std::ostream& operator<<(std::ostream& o, const Expr& e) { o << *(const_cast<ExprRep*>(&e.getRep())); return o;}/// I/O Stream operator>>inline std::istream& operator>>(std::istream& i, Expr& e) { Real rVal; i >> rVal; // precision is = defInputDigits if (i) e = rVal; // only assign when reading is successful. return i;}/// floor functionBigInt floor(const Expr&, Expr&);/// power functionExpr pow(const Expr&, unsigned long);/// additioninline Expr operator+(const Expr& e1, const Expr& e2) { return Expr(new AddRep(e1.Rep(), e2.Rep()));}/// substractioninline Expr operator-(const Expr& e1, const Expr& e2) { return Expr(new SubRep(e1.Rep(), e2.Rep()));}/// multiplicationinline Expr operator*(const Expr& e1, const Expr& e2) { return Expr(new MultRep(e1.Rep(), e2.Rep()));}/// divisioninline Expr operator/(const Expr& e1, const Expr& e2) { if (e2.sign() == 0) { std::cerr << " ERROR : division by zero ! " << std::endl; if (AbortFlag) abort(); InvalidFlag = -4; } return Expr(new DivRep(e1.Rep(), e2.Rep()));}/// modulo operatorinline Expr operator%(const Expr& e1, const Expr& e2) { Expr result; floor(e1/e2, result); return result;}/// operator ==/** this is inefficient if you compare to zero: * e.g., if (e != 0) {...} use e.isZero() instead */inline bool operator==(const Expr& e1, const Expr& e2) { return e1.cmp(e2) == 0;}/// operator !=inline bool operator!=(const Expr& e1, const Expr& e2) { return e1.cmp(e2) != 0;}/// operator <inline bool operator< (const Expr& e1, const Expr& e2) { return e1.cmp(e2) < 0;}/// operator <=inline bool operator<=(const Expr& e1, const Expr& e2) { return e1.cmp(e2) <= 0;}/// operator <inline bool operator> (const Expr& e1, const Expr& e2) { return e1.cmp(e2) > 0;}/// operator >=inline bool operator>=(const Expr& e1, const Expr& e2) { return e1.cmp(e2) >= 0;}/// return signinline int sign(const Expr& e) { return e.sign();}/// is zero?inline bool isZero(const Expr& e) { return e.isZero();}/// compare/** compare two Expr \a e1 and \a e2, return * \retval -1 if e1 < e2, * \retval 0 if e1 = e2, * \retval 1 if e1 > e2. */inline int cmp(const Expr& e1, const Expr& e2) { return e1.cmp(e2);}/// absolute valueinline Expr abs(const Expr& x) { return x.abs();}/// absolute value (same as abs)inline Expr fabs(const Expr& x) { return abs(x);}/// floorinline BigInt floor(const Expr& e) { Expr tmp; return floor(e, tmp);}/// ceilinginline BigInt ceil(const Expr& e) { return -floor(-e);}/// floorLginline long floorLg(const Expr& e) { Expr tmp; return floorLg(floor(e));}/// ceilLginline long ceilLg(const Expr& e) { Expr tmp; return ceilLg(ceil(e));}/// powerinline Expr power(const Expr& e, unsigned long p) { return pow(e, p);}/// divisibility predicate/** We do not check if e2 is 0. * */// NOTE: The name "isDivisible" is not consistent// with the analogous "divisible" predicate in BigInt!inline bool isDivisible(const Expr& e1, const Expr& e2) { Expr result; floor(e1/e2, result); return (result.sign() == 0);}/// square rootinline Expr sqrt(const Expr& e) { if (e.sign() < 0) { std::cerr << " ERROR : sqrt of negative value ! " << std::endl; if (AbortFlag) abort(); InvalidFlag = -5; } return Expr(new SqrtRep(e.Rep()));}//Following two have been added to make NT=Expr work for Polynomial<NT>/// gcdinline Expr gcd(const Expr& /*a*/, const Expr& /*b*/) { return Expr(1);}inline Expr div_exact(const Expr& x, const Expr& y) { return x/y - x%y;}/// helper function for constructing Polynomial node (n-th node)template <class NT>inline Expr rootOf(const Polynomial<NT>& p, int n = 0) { return Expr(p, n);}/// helper function for constructing Polynomial node witb BFIntervaltemplate <class NT>inline Expr rootOf(const Polynomial<NT>& p, const BFInterval& I) { return Expr(p, I);}/// helper function for constructing Polynomial node with pair of BigFloatstemplate <class NT>inline Expr rootOf(const Polynomial<NT>& p, const BigFloat& x, const BigFloat& y) { return Expr(p, BFInterval(x, y) );}/// helper function for constructing Polynomial node with pair of doublestemplate <class NT>inline Expr rootOf(const Polynomial<NT>& p, double x, double y) { return Expr(p, BFInterval(BigFloat(x), BigFloat(y)) );}/// helper function for constructing Polynomial node with pair of intstemplate <class NT>inline Expr rootOf(const Polynomial<NT>& p, int x, int y) { return Expr(p, BFInterval(BigFloat(x), BigFloat(y)) );}/// constructor for Polynomial node of the form x^m - n (i.e., radicals)/** We assume that n >= 0 and m >= 1 * */template <class NT>inline Expr radical(const NT& n, int m) { assert(n>=0 && m>=1); if (n == 0 || n == 1 || m == 1) return Expr(n); Polynomial<NT> Q(m); Q.setCoeff(0, -n); Q.setCoeff(m, 1); return Expr(Q, 0);}// We include this file here and not from inside Poly.h,// because otherwise VC++.net2003 can't compile Expr.cpp#include <CGAL/CORE/poly/Poly.tcc>CORE_END_NAMESPACE#endif // _CORE_EXPR_H_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -