Navigation

Source code for sympy.core.numbers

from__future__importprint_function,divisionimportdecimalimportfractionsimportmathimportreasregexfromcollectionsimportdefaultdictfrom.containersimportTuplefrom.sympifyimportconverter,sympify,_sympify,SympifyErrorfrom.singletonimportS,Singletonfrom.exprimportExpr,AtomicExprfrom.decoratorsimport_sympifyitfrom.cacheimportcacheit,clear_cachefrom.logicimportfuzzy_notfromsympy.core.compatibilityimport(as_int,integer_types,long,string_types,with_metaclass,HAS_GMPY,SYMPY_INTS)importmpmathimportmpmath.libmpasmlibfrommpmath.libmpimportmpf_pow,mpf_pi,mpf_e,phi_fixedfrommpmath.ctx_mpimportmpnumericfrommpmath.libmp.libmpfimport(finfas_mpf_inf,fninfas_mpf_ninf,fnanas_mpf_nan,fzeroas_mpf_zero,_normalizeasmpf_normalize,prec_to_dps)fromsympy.utilities.miscimportdebug,filldedentrnd=mlib.round_nearest_LOG2=math.log(2)defcomp(z1,z2,tol=None):"""Return a bool indicating whether the error between z1 and z2 is <= tol. If ``tol`` is None then True will be returned if there is a significant difference between the numbers: ``abs(z1 - z2)*10**p <= 1/2`` where ``p`` is the lower of the precisions of the values. A comparison of strings will be made if ``z1`` is a Number and a) ``z2`` is a string or b) ``tol`` is '' and ``z2`` is a Number. When ``tol`` is a nonzero value, if z2 is non-zero and ``|z1| > 1`` the error is normalized by ``|z1|``, so if you want to see if the absolute error between ``z1`` and ``z2`` is <= ``tol`` then call this as ``comp(z1 - z2, 0, tol)``. """iftype(z2)isstr:ifnotisinstance(z1,Number):raiseValueError('when z2 is a str z1 must be a Number')returnstr(z1)==z2ifnotz1:z1,z2=z2,z1ifnotz1:returnTrueifnottol:iftolisNone:iftype(z2)isstrandgetattr(z1,'is_Number',False):returnstr(z1)==z2a,b=Float(z1),Float(z2)returnint(abs(a-b)*10**prec_to_dps(min(a._prec,b._prec)))*2<=1elifall(getattr(i,'is_Number',False)foriin(z1,z2)):returnz1._prec==z2._precandstr(z1)==str(z2)raiseValueError('exact comparison requires two Numbers')diff=abs(z1-z2)az1=abs(z1)ifz2andaz1>1:returndiff/az1<=tolelse:returndiff<=toldefmpf_norm(mpf,prec):"""Return the mpf tuple normalized appropriately for the indicated precision after doing a check to see if zero should be returned or not when the mantissa is 0. ``mpf_normlize`` always assumes that this is zero, but it may not be since the mantissa for mpf's values "+inf", "-inf" and "nan" have a mantissa of zero, too. Note: this is not intended to validate a given mpf tuple, so sending mpf tuples that were not created by mpmath may produce bad results. This is only a wrapper to ``mpf_normalize`` which provides the check for non- zero mpfs that have a 0 for the mantissa. """sign,man,expt,bc=mpfifnotman:# hack for mpf_normalize which does not do this;# it assumes that if man is zero the result is 0# (see issue 6639)ifnotbc:return_mpf_zeroelse:# don't change anything; this should already# be a well formed mpf tuplereturnmpfrv=mpf_normalize(sign,man,expt,bc,prec,rnd)returnrv# TODO: we should use the warnings module_errdict={"divide":False}

def_decimal_to_Rational_prec(dec):"""Convert an ordinary decimal instance to a Rational."""ifnotdec.is_finite():raiseTypeError("dec must be finite, got %s."%dec)s,d,e=dec.as_tuple()prec=len(d)ife>=0:# it's an integerrv=Integer(int(dec))else:s=(-1)**sd=sum([di*10**ifori,diinenumerate(reversed(d))])rv=Rational(s*d,10**-e)returnrv,precdef_literal_float(f):"""Return True if n can be interpreted as a floating point number."""pat=r"[-+]?((\d*\.\d+)|(\d+\.?))(eE[-+]?\d+)?"returnbool(regex.match(pat,f))# (a,b) -> gcd(a,b)_gcdcache={}# TODO caching with decorator, but not to degrade performance

[docs]defigcd(*args):"""Computes positive integer greatest common divisor. The algorithm is based on the well known Euclid's algorithm. To improve speed, igcd() has its own caching mechanism implemented. Examples ======== >>> from sympy.core.numbers import igcd >>> igcd(2, 4) 2 >>> igcd(5, 10, 15) 5 """a=args[0]forbinargs[1:]:try:a=_gcdcache[(a,b)]exceptKeyError:a,b=as_int(a),as_int(b)ifaandb:ifb<0:b=-bwhileb:a,b=b,a%belse:a=abs(aorb)_gcdcache[(a,b)]=aifa==1orb==1:return1returna

[docs]classNumber(AtomicExpr):""" Represents any kind of number in sympy. Floating point numbers are represented by the Float class. Integer numbers (of any size), together with rational numbers (again, there is no limit on their size) are represented by the Rational class. If you want to represent, for example, ``1+sqrt(2)``, then you need to do:: Rational(1) + sqrt(Rational(2)) """is_commutative=Trueis_number=Trueis_Number=True__slots__=[]# Used to make max(x._prec, y._prec) return x._prec when only x is a float_prec=-1def__new__(cls,*obj):iflen(obj)==1:obj=obj[0]ifisinstance(obj,Number):returnobjifisinstance(obj,SYMPY_INTS):returnInteger(obj)ifisinstance(obj,tuple)andlen(obj)==2:returnRational(*obj)ifisinstance(obj,(float,mpmath.mpf,decimal.Decimal)):returnFloat(obj)ifisinstance(obj,string_types):val=sympify(obj)ifisinstance(val,Number):returnvalelse:raiseValueError('String "%s" does not denote a Number'%obj)ifisinstance(obj,Number):returnobjmsg="expected str|int|long|float|Decimal|Number object but got %r"raiseTypeError(msg%type(obj).__name__)definvert(self,other,*gens,**args):fromsympy.polys.polytoolsimportinvertifgetattr(other,'is_number',True):returnmod_inverse(self,other)returninvert(self,other,*gens,**args)def__divmod__(self,other):from.containersimportTuplefromsympy.functions.elementary.complexesimportsigntry:other=Number(other)exceptTypeError:msg="unsupported operand type(s) for divmod(): '%s' and '%s'"raiseTypeError(msg%(type(self).__name__,type(other).__name__))ifnotother:raiseZeroDivisionError('modulo by zero')ifself.is_Integerandother.is_Integer:returnTuple(*divmod(self.p,other.p))else:rat=self/otherw=sign(rat)*int(abs(rat))# = rat.floor()r=self-other*wreturnTuple(w,r)def__rdivmod__(self,other):try:other=Number(other)exceptTypeError:msg="unsupported operand type(s) for divmod(): '%s' and '%s'"raiseTypeError(msg%(type(other).__name__,type(self).__name__))returndivmod(other,self)def__round__(self,*args):returnround(float(self),*args)def_as_mpf_val(self,prec):"""Evaluation of mpf tuple accurate to at least prec bits."""raiseNotImplementedError('%s needs ._as_mpf_val() method'%(self.__class__.__name__))def_eval_evalf(self,prec):returnFloat._new(self._as_mpf_val(prec),prec)def_as_mpf_op(self,prec):prec=max(prec,self._prec)returnself._as_mpf_val(prec),precdef__float__(self):returnmlib.to_float(self._as_mpf_val(53))def_eval_conjugate(self):returnselfdef_eval_order(self,*symbols):fromsympyimportOrder# Order(5, x, y) -> Order(1,x,y)returnOrder(S.One,*symbols)def_eval_subs(self,old,new):ifold==-self:return-newreturnself# there is no other possibilitydef_eval_is_finite(self):returnTrue@classmethoddefclass_key(cls):return1,0,'Number'@cacheitdefsort_key(self,order=None):returnself.class_key(),(0,()),(),self@_sympifyit('other',NotImplemented)def__add__(self,other):ifisinstance(other,Number):ifotherisS.NaN:returnS.NaNelifotherisS.Infinity:returnS.InfinityelifotherisS.NegativeInfinity:returnS.NegativeInfinityreturnAtomicExpr.__add__(self,other)@_sympifyit('other',NotImplemented)def__sub__(self,other):ifisinstance(other,Number):ifotherisS.NaN:returnS.NaNelifotherisS.Infinity:returnS.NegativeInfinityelifotherisS.NegativeInfinity:returnS.InfinityreturnAtomicExpr.__sub__(self,other)@_sympifyit('other',NotImplemented)def__mul__(self,other):ifisinstance(other,Number):ifotherisS.NaN:returnS.NaNelifotherisS.Infinity:ifself.is_zero:returnS.NaNelifself.is_positive:returnS.Infinityelse:returnS.NegativeInfinityelifotherisS.NegativeInfinity:ifself.is_zero:returnS.NaNelifself.is_positive:returnS.NegativeInfinityelse:returnS.Infinityelifisinstance(other,Tuple):returnNotImplementedreturnAtomicExpr.__mul__(self,other)@_sympifyit('other',NotImplemented)def__div__(self,other):ifisinstance(other,Number):ifotherisS.NaN:returnS.NaNelifotherisS.InfinityorotherisS.NegativeInfinity:returnS.ZeroreturnAtomicExpr.__div__(self,other)__truediv__=__div__def__eq__(self,other):raiseNotImplementedError('%s needs .__eq__() method'%(self.__class__.__name__))def__ne__(self,other):raiseNotImplementedError('%s needs .__ne__() method'%(self.__class__.__name__))def__lt__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s < %s"%(self,other))raiseNotImplementedError('%s needs .__lt__() method'%(self.__class__.__name__))def__le__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s <= %s"%(self,other))raiseNotImplementedError('%s needs .__le__() method'%(self.__class__.__name__))def__gt__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s > %s"%(self,other))return_sympify(other).__lt__(self)def__ge__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s >= %s"%(self,other))return_sympify(other).__le__(self)def__hash__(self):returnsuper(Number,self).__hash__()defis_constant(self,*wrt,**flags):returnTruedefas_coeff_mul(self,*deps,**kwargs):# a -> c*tifself.is_Rationalornotkwargs.pop('rational',True):returnself,tuple()elifself.is_negative:returnS.NegativeOne,(-self,)returnS.One,(self,)defas_coeff_add(self,*deps):# a -> c + tifself.is_Rational:returnself,tuple()returnS.Zero,(self,)

[docs]defas_coeff_Mul(self,rational=False):"""Efficiently extract the coefficient of a product. """ifrationalandnotself.is_Rational:returnS.One,selfreturn(self,S.One)ifselfelse(S.One,self)

[docs]defas_coeff_Add(self):"""Efficiently extract the coefficient of a summation. """returnself,S.Zero

[docs]defcofactors(self,other):"""Compute GCD and cofactors of `self` and `other`. """fromsympy.polysimportcofactorsreturncofactors(self,other)

[docs]classFloat(Number):"""Represent a floating-point number of arbitrary precision. Examples ======== >>> from sympy import Float >>> Float(3.5) 3.50000000000000 >>> Float(3) 3.00000000000000 Creating Floats from strings (and Python ``int`` and ``long`` types) will give a minimum precision of 15 digits, but the precision will automatically increase to capture all digits entered. >>> Float(1) 1.00000000000000 >>> Float(10**20) 100000000000000000000. >>> Float('1e20') 100000000000000000000. However, *floating-point* numbers (Python ``float`` types) retain only 15 digits of precision: >>> Float(1e20) 1.00000000000000e+20 >>> Float(1.23456789123456789) 1.23456789123457 It may be preferable to enter high-precision decimal numbers as strings: Float('1.23456789123456789') 1.23456789123456789 The desired number of digits can also be specified: >>> Float('1e-3', 3) 0.00100 >>> Float(100, 4) 100.0 Float can automatically count significant figures if a null string is sent for the precision; space are also allowed in the string. (Auto- counting is only allowed for strings, ints and longs). >>> Float('123 456 789 . 123 456', '') 123456789.123456 >>> Float('12e-3', '') 0.012 >>> Float(3, '') 3. If a number is written in scientific notation, only the digits before the exponent are considered significant if a decimal appears, otherwise the "e" signifies only how to move the decimal: >>> Float('60.e2', '') # 2 digits significant 6.0e+3 >>> Float('60e2', '') # 4 digits significant 6000. >>> Float('600e-2', '') # 3 digits significant 6.00 Notes ===== Floats are inexact by their nature unless their value is a binary-exact value. >>> approx, exact = Float(.1, 1), Float(.125, 1) For calculation purposes, evalf needs to be able to change the precision but this will not increase the accuracy of the inexact value. The following is the most accurate 5-digit approximation of a value of 0.1 that had only 1 digit of precision: >>> approx.evalf(5) 0.099609 By contrast, 0.125 is exact in binary (as it is in base 10) and so it can be passed to Float or evalf to obtain an arbitrary precision with matching accuracy: >>> Float(exact, 5) 0.12500 >>> exact.evalf(20) 0.12500000000000000000 Trying to make a high-precision Float from a float is not disallowed, but one must keep in mind that the *underlying float* (not the apparent decimal value) is being obtained with high precision. For example, 0.3 does not have a finite binary representation. The closest rational is the fraction 5404319552844595/2**54. So if you try to obtain a Float of 0.3 to 20 digits of precision you will not see the same thing as 0.3 followed by 19 zeros: >>> Float(0.3, 20) 0.29999999999999998890 If you want a 20-digit value of the decimal 0.3 (not the floating point approximation of 0.3) you should send the 0.3 as a string. The underlying representation is still binary but a higher precision than Python's float is used: >>> Float('0.3', 20) 0.30000000000000000000 Although you can increase the precision of an existing Float using Float it will not increase the accuracy -- the underlying value is not changed: >>> def show(f): # binary rep of Float ... from sympy import Mul, Pow ... s, m, e, b = f._mpf_ ... v = Mul(int(m), Pow(2, int(e), evaluate=False), evaluate=False) ... print('%s at prec=%s' % (v, f._prec)) ... >>> t = Float('0.3', 3) >>> show(t) 4915/2**14 at prec=13 >>> show(Float(t, 20)) # higher prec, not higher accuracy 4915/2**14 at prec=70 >>> show(Float(t, 2)) # lower prec 307/2**10 at prec=10 The same thing happens when evalf is used on a Float: >>> show(t.evalf(20)) 4915/2**14 at prec=70 >>> show(t.evalf(2)) 307/2**10 at prec=10 Finally, Floats can be instantiated with an mpf tuple (n, c, p) to produce the number (-1)**n*c*2**p: >>> n, c, p = 1, 5, 0 >>> (-1)**n*c*2**p -5 >>> Float((1, 5, 0)) -5.00000000000000 An actual mpf tuple also contains the number of bits in c as the last element of the tuple: >>> _._mpf_ (1, 5, 0, 3) This is not needed for instantiation and is not the same thing as the precision. The mpf tuple and the precision are two separate quantities that Float tracks. """__slots__=['_mpf_','_prec']# A Float represents many real numbers,# both rational and irrational.is_rational=Noneis_irrational=Noneis_number=Trueis_real=Trueis_Float=Truedef__new__(cls,num,prec=None):ifisinstance(num,string_types):num=num.replace(' ','')ifnum.startswith('.')andlen(num)>1:num='0'+numelifnum.startswith('-.')andlen(num)>2:num='-0.'+num[2:]elifisinstance(num,float)andnum==0:num='0'elifisinstance(num,(SYMPY_INTS,Integer)):num=str(num)# faster than mlib.from_intelifnumisS.Infinity:num='+inf'elifnumisS.NegativeInfinity:num='-inf'elifisinstance(num,mpmath.mpf):num=num._mpf_ifprecisNone:dps=15ifisinstance(num,Float):returnnumifisinstance(num,string_types)and_literal_float(num):try:Num=decimal.Decimal(num)exceptdecimal.InvalidOperation:passelse:isint='.'notinnumnum,dps=_decimal_to_Rational_prec(Num)ifnum.is_Integerandisint:dps=max(dps,len(str(num).lstrip('-')))dps=max(15,dps)elifprec=='':ifnotisinstance(num,string_types):raiseValueError('The null string can only be used when ''the number to Float is passed as a string or an integer.')ok=Noneif_literal_float(num):try:Num=decimal.Decimal(num)exceptdecimal.InvalidOperation:passelse:isint='.'notinnumnum,dps=_decimal_to_Rational_prec(Num)ifnum.is_Integerandisint:dps=max(dps,len(str(num).lstrip('-')))ok=TrueifokisNone:raiseValueError('string-float not recognized: %s'%num)else:dps=precprec=mlib.libmpf.dps_to_prec(dps)ifisinstance(num,float):_mpf_=mlib.from_float(num,prec,rnd)elifisinstance(num,str):_mpf_=mlib.from_str(num,prec,rnd)elifisinstance(num,decimal.Decimal):ifnum.is_finite():_mpf_=mlib.from_str(str(num),prec,rnd)elifnum.is_nan():_mpf_=_mpf_nanelifnum.is_infinite():ifnum>0:_mpf_=_mpf_infelse:_mpf_=_mpf_ninfelse:raiseValueError("unexpected decimal value %s"%str(num))elifisinstance(num,Rational):_mpf_=mlib.from_rational(num.p,num.q,prec,rnd)elifisinstance(num,tuple)andlen(num)in(3,4):iftype(num[1])isstr:# it's a hexadecimal (coming from a pickled object)# assume that it is in standard formnum=list(num)num[1]=long(num[1],16)_mpf_=tuple(num)else:ifnotnum[1]andlen(num)==4:# handle normalization hackreturnFloat._new(num,prec)else:_mpf_=mpmath.mpf(S.NegativeOne**num[0]*num[1]*2**num[2])._mpf_elifisinstance(num,Float):_mpf_=num._mpf_ifprec<num._prec:_mpf_=mpf_norm(_mpf_,prec)else:_mpf_=mpmath.mpf(num)._mpf_# special casesif_mpf_==_mpf_zero:pass# we want a Floatelif_mpf_==_mpf_nan:returnS.NaNobj=Expr.__new__(cls)obj._mpf_=_mpf_obj._prec=precreturnobj@classmethoddef_new(cls,_mpf_,_prec):# special casesif_mpf_==_mpf_zero:returnS.Zero# XXX this is different from Float which gives 0.0elif_mpf_==_mpf_nan:returnS.NaNobj=Expr.__new__(cls)obj._mpf_=mpf_norm(_mpf_,_prec)obj._prec=_precreturnobj# mpz can't be pickleddef__getnewargs__(self):return(mlib.to_pickable(self._mpf_),)def__getstate__(self):return{'_prec':self._prec}def_hashable_content(self):return(self._mpf_,self._prec)deffloor(self):returnInteger(int(mlib.to_int(mlib.mpf_floor(self._mpf_,self._prec))))defceiling(self):returnInteger(int(mlib.to_int(mlib.mpf_ceil(self._mpf_,self._prec))))@propertydefnum(self):returnmpmath.mpf(self._mpf_)def_as_mpf_val(self,prec):rv=mpf_norm(self._mpf_,prec)ifrv!=self._mpf_andself._prec==prec:debug(self._mpf_,rv)returnrvdef_as_mpf_op(self,prec):returnself._mpf_,max(prec,self._prec)def_eval_is_finite(self):ifself._mpf_in(_mpf_inf,_mpf_ninf):returnFalsereturnTruedef_eval_is_infinite(self):ifself._mpf_in(_mpf_inf,_mpf_ninf):returnTruereturnFalsedef_eval_is_integer(self):returnself._mpf_==_mpf_zerodef_eval_is_negative(self):ifself._mpf_==_mpf_ninf:returnTrueifself._mpf_==_mpf_inf:returnFalsereturnself.num<0def_eval_is_positive(self):ifself._mpf_==_mpf_inf:returnTrueifself._mpf_==_mpf_ninf:returnFalsereturnself.num>0def_eval_is_zero(self):returnself._mpf_==_mpf_zerodef__nonzero__(self):returnself._mpf_!=_mpf_zero__bool__=__nonzero__def__neg__(self):returnFloat._new(mlib.mpf_neg(self._mpf_),self._prec)@_sympifyit('other',NotImplemented)def__add__(self,other):ifisinstance(other,Number):rhs,prec=other._as_mpf_op(self._prec)returnFloat._new(mlib.mpf_add(self._mpf_,rhs,prec,rnd),prec)returnNumber.__add__(self,other)@_sympifyit('other',NotImplemented)def__sub__(self,other):ifisinstance(other,Number):rhs,prec=other._as_mpf_op(self._prec)returnFloat._new(mlib.mpf_sub(self._mpf_,rhs,prec,rnd),prec)returnNumber.__sub__(self,other)@_sympifyit('other',NotImplemented)def__mul__(self,other):ifisinstance(other,Number):rhs,prec=other._as_mpf_op(self._prec)returnFloat._new(mlib.mpf_mul(self._mpf_,rhs,prec,rnd),prec)returnNumber.__mul__(self,other)@_sympifyit('other',NotImplemented)def__div__(self,other):ifisinstance(other,Number)andother!=0:rhs,prec=other._as_mpf_op(self._prec)returnFloat._new(mlib.mpf_div(self._mpf_,rhs,prec,rnd),prec)returnNumber.__div__(self,other)__truediv__=__div__@_sympifyit('other',NotImplemented)def__mod__(self,other):ifisinstance(other,Rational)andother.q!=1:# calculate mod with Rationals, *then* round the resultreturnFloat(Rational.__mod__(Rational(self),other),prec_to_dps(self._prec))ifisinstance(other,Float):r=self/otherifr==int(r):prec=max([prec_to_dps(i)foriin(self._prec,other._prec)])returnFloat(0,prec)ifisinstance(other,Number):rhs,prec=other._as_mpf_op(self._prec)returnFloat._new(mlib.mpf_mod(self._mpf_,rhs,prec,rnd),prec)returnNumber.__mod__(self,other)@_sympifyit('other',NotImplemented)def__rmod__(self,other):ifisinstance(other,Float):returnother.__mod__(self)ifisinstance(other,Number):rhs,prec=other._as_mpf_op(self._prec)returnFloat._new(mlib.mpf_mod(rhs,self._mpf_,prec,rnd),prec)returnNumber.__rmod__(self,other)def_eval_power(self,expt):""" expt is symbolic object but not equal to 0, 1 (-p)**r -> exp(r*log(-p)) -> exp(r*(log(p) + I*Pi)) -> -> p**r*(sin(Pi*r) + cos(Pi*r)*I) """ifself==0:ifexpt.is_positive:returnS.Zeroifexpt.is_negative:returnFloat('inf')ifisinstance(expt,Number):ifisinstance(expt,Integer):prec=self._precreturnFloat._new(mlib.mpf_pow_int(self._mpf_,expt.p,prec,rnd),prec)elifisinstance(expt,Rational)and \
expt.p==1andexpt.q%2andself.is_negative:returnPow(S.NegativeOne,expt,evaluate=False)*(-self)._eval_power(expt)expt,prec=expt._as_mpf_op(self._prec)mpfself=self._mpf_try:y=mpf_pow(mpfself,expt,prec,rnd)returnFloat._new(y,prec)exceptmlib.ComplexResult:re,im=mlib.mpc_pow((mpfself,_mpf_zero),(expt,_mpf_zero),prec,rnd)returnFloat._new(re,prec)+ \
Float._new(im,prec)*S.ImaginaryUnitdef__abs__(self):returnFloat._new(mlib.mpf_abs(self._mpf_),self._prec)def__int__(self):ifself._mpf_==_mpf_zero:return0returnint(mlib.to_int(self._mpf_))# uses round_fast = round_down__long__=__int__def__eq__(self,other):ifisinstance(other,float):# coerce to Float at same precisiono=Float(other)try:ompf=o._as_mpf_val(self._prec)exceptValueError:returnFalsereturnbool(mlib.mpf_eq(self._mpf_,ompf))try:other=_sympify(other)exceptSympifyError:returnFalse# sympy != other --> not ==ifisinstance(other,NumberSymbol):ifother.is_irrational:returnFalsereturnother.__eq__(self)ifisinstance(other,Float):returnbool(mlib.mpf_eq(self._mpf_,other._mpf_))ifisinstance(other,Number):# numbers should compare at the same precision;# all _as_mpf_val routines should be sure to abide# by the request to change the prec if necessary; if# they don't, the equality test will fail since it compares# the mpf tuplesompf=other._as_mpf_val(self._prec)returnbool(mlib.mpf_eq(self._mpf_,ompf))returnFalse# Float != non-Numberdef__ne__(self,other):returnnotself.__eq__(other)def__gt__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s > %s"%(self,other))ifisinstance(other,NumberSymbol):returnother.__le__(self)ifother.is_comparable:other=other.evalf()ifisinstance(other,Number)andotherisnotS.NaN:return_sympify(bool(mlib.mpf_gt(self._mpf_,other._as_mpf_val(self._prec))))returnExpr.__gt__(self,other)def__ge__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s >= %s"%(self,other))ifisinstance(other,NumberSymbol):returnother.__lt__(self)ifother.is_comparable:other=other.evalf()ifisinstance(other,Number)andotherisnotS.NaN:return_sympify(bool(mlib.mpf_ge(self._mpf_,other._as_mpf_val(self._prec))))returnExpr.__ge__(self,other)def__lt__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s < %s"%(self,other))ifisinstance(other,NumberSymbol):returnother.__ge__(self)ifother.is_realandother.is_number:other=other.evalf()ifisinstance(other,Number)andotherisnotS.NaN:return_sympify(bool(mlib.mpf_lt(self._mpf_,other._as_mpf_val(self._prec))))returnExpr.__lt__(self,other)def__le__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s <= %s"%(self,other))ifisinstance(other,NumberSymbol):returnother.__gt__(self)ifother.is_realandother.is_number:other=other.evalf()ifisinstance(other,Number)andotherisnotS.NaN:return_sympify(bool(mlib.mpf_le(self._mpf_,other._as_mpf_val(self._prec))))returnExpr.__le__(self,other)def__hash__(self):returnsuper(Float,self).__hash__()defepsilon_eq(self,other,epsilon="1e-15"):returnabs(self-other)<Float(epsilon)def_sage_(self):importsage.allassagereturnsage.RealNumber(str(self))def__format__(self,format_spec):returnformat(decimal.Decimal(str(self)),format_spec)# Add sympify converters

converter[float]=converter[decimal.Decimal]=Float# this is here to work nicely in SageRealNumber=Float

[docs]classRational(Number):"""Represents integers and rational numbers (p/q) of any size. Examples ======== >>> from sympy import Rational, nsimplify, S, pi >>> Rational(3) 3 >>> Rational(1, 2) 1/2 Rational is unprejudiced in accepting input. If a float is passed, the underlying value of the binary representation will be returned: >>> Rational(.5) 1/2 >>> Rational(.2) 3602879701896397/18014398509481984 If the simpler representation of the float is desired then consider limiting the denominator to the desired value or convert the float to a string (which is roughly equivalent to limiting the denominator to 10**12): >>> Rational(str(.2)) 1/5 >>> Rational(.2).limit_denominator(10**12) 1/5 An arbitrarily precise Rational is obtained when a string literal is passed: >>> Rational("1.23") 123/100 >>> Rational('1e-2') 1/100 >>> Rational(".1") 1/10 >>> Rational('1e-2/3.2') 1/320 The conversion of other types of strings can be handled by the sympify() function, and conversion of floats to expressions or simple fractions can be handled with nsimplify: >>> S('.[3]') # repeating digits in brackets 1/3 >>> S('3**2/10') # general expressions 9/10 >>> nsimplify(.3) # numbers that have a simple form 3/10 But if the input does not reduce to a literal Rational, an error will be raised: >>> Rational(pi) Traceback (most recent call last): ... TypeError: invalid input: pi Low-level --------- Access numerator and denominator as .p and .q: >>> r = Rational(3, 4) >>> r 3/4 >>> r.p 3 >>> r.q 4 Note that p and q return integers (not SymPy Integers) so some care is needed when using them in expressions: >>> r.p/r.q 0.75 See Also ======== sympify, sympy.simplify.simplify.nsimplify """is_real=Trueis_integer=Falseis_rational=Trueis_number=True__slots__=['p','q']is_Rational=True@cacheitdef__new__(cls,p,q=None):ifqisNone:ifisinstance(p,Rational):returnpifisinstance(p,string_types):p=p.replace(' ','')try:# we might have a Floatneg_pow,digits,expt=decimal.Decimal(p).as_tuple()p=[1,-1][neg_pow]*int("".join(str(x)forxindigits))ifexpt>0:returnRational(p*Pow(10,expt),1)returnRational(p,Pow(10,-expt))exceptdecimal.InvalidOperation:f=regex.match('^([-+]?[0-9]+)/([0-9]+)$',p)iff:n,d=f.groups()returnRational(int(n),int(d))elifp.count('/')==1:p,q=p.split('/')returnRational(Rational(p),Rational(q))else:pass# error will raise belowelse:try:ifisinstance(p,fractions.Fraction):returnRational(p.numerator,p.denominator)exceptNameError:pass# error will raise belowifisinstance(p,(float,Float)):returnRational(*float(p).as_integer_ratio())ifnotisinstance(p,SYMPY_INTS+(Rational,)):raiseTypeError('invalid input: %s'%p)q=S.Oneelse:p=Rational(p)q=Rational(q)ifisinstance(q,Rational):p*=q.qq=q.pifisinstance(p,Rational):q*=p.qp=p.p# p and q are now integersifq==0:ifp==0:if_errdict["divide"]:raiseValueError("Indeterminate 0/0")else:returnS.NaNifp<0:returnS.NegativeInfinityreturnS.Infinityifq<0:q=-qp=-pn=igcd(abs(p),q)ifn>1:p//=nq//=nifq==1:returnInteger(p)ifp==1andq==2:returnS.Halfobj=Expr.__new__(cls)obj.p=pobj.q=qreturnobj

[docs]deflimit_denominator(self,max_denominator=1000000):"""Closest Rational to self with denominator at most max_denominator. >>> from sympy import Rational >>> Rational('3.141592653589793').limit_denominator(10) 22/7 >>> Rational('3.141592653589793').limit_denominator(100) 311/99 """# Algorithm notes: For any real number x, define a *best upper# approximation* to x to be a rational number p/q such that:## (1) p/q >= x, and# (2) if p/q > r/s >= x then s > q, for any rational r/s.## Define *best lower approximation* similarly. Then it can be# proved that a rational number is a best upper or lower# approximation to x if, and only if, it is a convergent or# semiconvergent of the (unique shortest) continued fraction# associated to x.## To find a best rational approximation with denominator <= M,# we find the best upper and lower approximations with# denominator <= M and take whichever of these is closer to x.# In the event of a tie, the bound with smaller denominator is# chosen. If both denominators are equal (which can happen# only when max_denominator == 1 and self is midway between# two integers) the lower bound---i.e., the floor of self, is# taken.ifmax_denominator<1:raiseValueError("max_denominator should be at least 1")ifself.q<=max_denominator:returnselfp0,q0,p1,q1=0,1,1,0n,d=self.p,self.qwhileTrue:a=n//dq2=q0+a*q1ifq2>max_denominator:breakp0,q0,p1,q1=p1,q1,p0+a*p1,q2n,d=d,n-a*dk=(max_denominator-q0)//q1bound1=Rational(p0+k*p1,q0+k*q1)bound2=Rational(p1,q1)ifabs(bound2-self)<=abs(bound1-self):returnbound2else:returnbound1

[docs]deffactors(self,limit=None,use_trial=True,use_rho=False,use_pm1=False,verbose=False,visual=False):"""A wrapper to factorint which return factors of self that are smaller than limit (or cheap to compute). Special methods of factoring are disabled by default so that only trial division is used. """fromsympy.ntheoryimportfactorratreturnfactorrat(self,limit=limit,use_trial=use_trial,use_rho=use_rho,use_pm1=use_pm1,verbose=verbose).copy()

[docs]classInteger(Rational):q=1is_integer=Trueis_number=Trueis_Integer=True__slots__=['p']def_as_mpf_val(self,prec):returnmlib.from_int(self.p,prec)def_mpmath_(self,prec,rnd):returnmpmath.make_mpf(self._as_mpf_val(prec))# TODO caching with decorator, but not to degrade performance@int_tracedef__new__(cls,i):ifisinstance(i,string_types):i=i.replace(' ','')# whereas we cannot, in general, make a Rational from an# arbitrary expression, we can make an Integer unambiguously# (except when a non-integer expression happens to round to# an integer). So we proceed by taking int() of the input and# let the int routines determine whether the expression can# be made into an int or whether an error should be raised.try:ival=int(i)exceptTypeError:raiseTypeError('Integer can only work with integer expressions.')try:return_intcache[ival]exceptKeyError:# We only work with well-behaved integer types. This converts, for# example, numpy.int32 instances.obj=Expr.__new__(cls)obj.p=ival_intcache[ival]=objreturnobjdef__getnewargs__(self):return(self.p,)# Arithmetic operations are here for efficiencydef__int__(self):returnself.p__long__=__int__def__neg__(self):returnInteger(-self.p)def__abs__(self):ifself.p>=0:returnselfelse:returnInteger(-self.p)def__divmod__(self,other):from.containersimportTupleifisinstance(other,Integer):returnTuple(*(divmod(self.p,other.p)))else:returnNumber.__divmod__(self,other)def__rdivmod__(self,other):from.containersimportTupleifisinstance(other,integer_types):returnTuple(*(divmod(other,self.p)))else:try:other=Number(other)exceptTypeError:msg="unsupported operand type(s) for divmod(): '%s' and '%s'"oname=type(other).__name__sname=type(self).__name__raiseTypeError(msg%(oname,sname))returnNumber.__divmod__(other,self)# TODO make it decorator + bytecodehacks?def__add__(self,other):ifisinstance(other,integer_types):returnInteger(self.p+other)elifisinstance(other,Integer):returnInteger(self.p+other.p)returnRational.__add__(self,other)def__radd__(self,other):ifisinstance(other,integer_types):returnInteger(other+self.p)returnRational.__add__(self,other)def__sub__(self,other):ifisinstance(other,integer_types):returnInteger(self.p-other)elifisinstance(other,Integer):returnInteger(self.p-other.p)returnRational.__sub__(self,other)def__rsub__(self,other):ifisinstance(other,integer_types):returnInteger(other-self.p)returnRational.__rsub__(self,other)def__mul__(self,other):ifisinstance(other,integer_types):returnInteger(self.p*other)elifisinstance(other,Integer):returnInteger(self.p*other.p)returnRational.__mul__(self,other)def__rmul__(self,other):ifisinstance(other,integer_types):returnInteger(other*self.p)returnRational.__mul__(self,other)def__mod__(self,other):ifisinstance(other,integer_types):returnInteger(self.p%other)elifisinstance(other,Integer):returnInteger(self.p%other.p)returnRational.__mod__(self,other)def__rmod__(self,other):ifisinstance(other,integer_types):returnInteger(other%self.p)elifisinstance(other,Integer):returnInteger(other.p%self.p)returnRational.__rmod__(self,other)def__eq__(self,other):ifisinstance(other,integer_types):return(self.p==other)elifisinstance(other,Integer):return(self.p==other.p)returnRational.__eq__(self,other)def__ne__(self,other):returnnotself.__eq__(other)def__gt__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s > %s"%(self,other))ifisinstance(other,Integer):return_sympify(self.p>other.p)returnRational.__gt__(self,other)def__lt__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s < %s"%(self,other))ifisinstance(other,Integer):return_sympify(self.p<other.p)returnRational.__lt__(self,other)def__ge__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s >= %s"%(self,other))ifisinstance(other,Integer):return_sympify(self.p>=other.p)returnRational.__ge__(self,other)def__le__(self,other):try:other=_sympify(other)exceptSympifyError:raiseTypeError("Invalid comparison %s <= %s"%(self,other))ifisinstance(other,Integer):return_sympify(self.p<=other.p)returnRational.__le__(self,other)def__hash__(self):returnhash(self.p)def__index__(self):returnself.p########################################def_eval_is_odd(self):returnbool(self.p%2)def_eval_power(self,expt):""" Tries to do some simplifications on self**expt Returns None if no further simplifications can be done When exponent is a fraction (so we have for example a square root), we try to find a simpler representation by factoring the argument up to factors of 2**15, e.g. - sqrt(4) becomes 2 - sqrt(-4) becomes 2*I - (2**(3+7)*3**(6+7))**Rational(1,7) becomes 6*18**(3/7) Further simplification would require a special call to factorint on the argument which is not done here for sake of speed. """fromsympyimportperfect_powerifexptisS.Infinity:ifself.p>S.One:returnS.Infinity# cases -1, 0, 1 are done in their respective classesreturnS.Infinity+S.ImaginaryUnit*S.InfinityifexptisS.NegativeInfinity:returnRational(1,self)**S.Infinityifnotisinstance(expt,Number):# simplify when expt is even# (-2)**k --> 2**kifself.is_negativeandexpt.is_even:return(-self)**exptifisinstance(expt,Float):# Rational knows how to exponentiate by a Floatreturnsuper(Integer,self)._eval_power(expt)ifnotisinstance(expt,Rational):returnifexptisS.Halfandself.is_negative:# we extract I for this special case since everyone is doing soreturnS.ImaginaryUnit*Pow(-self,expt)ifexpt.is_negative:# invert base and change sign on exponentne=-exptifself.is_negative:ifexpt.q!=1:return-(S.NegativeOne)**((expt.p%expt.q)/S(expt.q))*Rational(1,-self)**neelse:return(S.NegativeOne)**ne*Rational(1,-self)**neelse:returnRational(1,self.p)**ne# see if base is a perfect root, sqrt(4) --> 2x,xexact=integer_nthroot(abs(self.p),expt.q)ifxexact:# if it's a perfect root we've finishedresult=Integer(x**abs(expt.p))ifself.is_negative:result*=S.NegativeOne**exptreturnresult# The following is an algorithm where we collect perfect roots# from the factors of base.# if it's not an nth root, it still might be a perfect powerb_pos=int(abs(self.p))p=perfect_power(b_pos)ifpisnotFalse:dict={p[0]:p[1]}else:dict=Integer(self).factors(limit=2**15)# now process the dict of factorsifself.is_negative:dict[-1]=1out_int=1# integer partout_rad=1# extracted radicalssqr_int=1sqr_gcd=0sqr_dict={}forprime,exponentindict.items():exponent*=expt.p# remove multiples of expt.q: (2**12)**(1/10) -> 2*(2**2)**(1/10)div_e,div_m=divmod(exponent,expt.q)ifdiv_e>0:out_int*=prime**div_eifdiv_m>0:# see if the reduced exponent shares a gcd with e.q# (2**2)**(1/10) -> 2**(1/5)g=igcd(div_m,expt.q)ifg!=1:out_rad*=Pow(prime,Rational(div_m//g,expt.q//g))else:sqr_dict[prime]=div_m# identify gcd of remaining powersforp,exinsqr_dict.items():ifsqr_gcd==0:sqr_gcd=exelse:sqr_gcd=igcd(sqr_gcd,ex)ifsqr_gcd==1:breakfork,vinsqr_dict.items():sqr_int*=k**(v//sqr_gcd)ifsqr_int==selfandout_int==1andout_rad==1:result=Noneelse:result=out_int*out_rad*Pow(sqr_int,Rational(sqr_gcd,expt.q))returnresultdef_eval_is_prime(self):fromsympy.ntheoryimportisprimereturnisprime(self)def_eval_is_composite(self):ifself>1:returnfuzzy_not(self.is_prime)else:returnFalsedefas_numer_denom(self):returnself,S.Onedef__floordiv__(self,other):returnInteger(self.p//Integer(other).p)def__rfloordiv__(self,other):returnInteger(Integer(other).p//self.p)# Add sympify converters

fori_typeininteger_types:converter[i_type]=IntegerclassAlgebraicNumber(Expr):"""Class for representing algebraic numbers in SymPy. """__slots__=['rep','root','alias','minpoly']is_AlgebraicNumber=Trueis_algebraic=Trueis_number=Truedef__new__(cls,expr,coeffs=None,alias=None,**args):"""Construct a new algebraic number. """fromsympyimportPolyfromsympy.polys.polyclassesimportANP,DMPfromsympy.polys.numberfieldsimportminimal_polynomialfromsympy.core.symbolimportSymbolexpr=sympify(expr)ifisinstance(expr,(tuple,Tuple)):minpoly,root=exprifnotminpoly.is_Poly:minpoly=Poly(minpoly)elifexpr.is_AlgebraicNumber:minpoly,root=expr.minpoly,expr.rootelse:minpoly,root=minimal_polynomial(expr,args.get('gen'),polys=True),exprdom=minpoly.get_domain()ifcoeffsisnotNone:ifnotisinstance(coeffs,ANP):rep=DMP.from_sympy_list(sympify(coeffs),0,dom)scoeffs=Tuple(*coeffs)else:rep=DMP.from_list(coeffs.to_list(),0,dom)scoeffs=Tuple(*coeffs.to_list())ifrep.degree()>=minpoly.degree():rep=rep.rem(minpoly.rep)else:rep=DMP.from_list([1,0],0,dom)scoeffs=Tuple(1,0)ifroot.is_negative:rep=-repscoeffs=Tuple(-1,0)sargs=(root,scoeffs)ifaliasisnotNone:ifnotisinstance(alias,Symbol):alias=Symbol(alias)sargs=sargs+(alias,)obj=Expr.__new__(cls,*sargs)obj.rep=repobj.root=rootobj.alias=aliasobj.minpoly=minpolyreturnobjdef__hash__(self):returnsuper(AlgebraicNumber,self).__hash__()def_eval_evalf(self,prec):returnself.as_expr()._evalf(prec)@propertydefis_aliased(self):"""Returns ``True`` if ``alias`` was set. """returnself.aliasisnotNonedefas_poly(self,x=None):"""Create a Poly instance from ``self``. """fromsympyimportDummy,Poly,PurePolyifxisnotNone:returnPoly.new(self.rep,x)else:ifself.aliasisnotNone:returnPoly.new(self.rep,self.alias)else:returnPurePoly.new(self.rep,Dummy('x'))defas_expr(self,x=None):"""Create a Basic expression from ``self``. """returnself.as_poly(xorself.root).as_expr().expand()defcoeffs(self):"""Returns all SymPy coefficients of an algebraic number. """return[self.rep.dom.to_sympy(c)forcinself.rep.all_coeffs()]defnative_coeffs(self):"""Returns all native coefficients of an algebraic number. """returnself.rep.all_coeffs()defto_algebraic_integer(self):"""Convert ``self`` to an algebraic integer. """fromsympyimportPolyf=self.minpolyiff.LC()==1:returnselfcoeff=f.LC()**(f.degree()-1)poly=f.compose(Poly(f.gen/f.LC()))minpoly=poly*coeffroot=f.LC()*self.rootreturnAlgebraicNumber((minpoly,root),self.coeffs())def_eval_simplify(self,ratio,measure):fromsympy.polysimportCRootOf,minpolyforrin[rforrinself.minpoly.all_roots()ifr.func!=CRootOf]:ifminpoly(self.root-r).is_Symbol:# use the matching root if it's simplerifmeasure(r)<ratio*measure(self.root):returnAlgebraicNumber(r)returnselfclassRationalConstant(Rational):""" Abstract base class for rationals with specific behaviors Derived classes must define class attributes p and q and should probably all be singletons. """__slots__=[]def__new__(cls):returnAtomicExpr.__new__(cls)classIntegerConstant(Integer):__slots__=[]def__new__(cls):returnAtomicExpr.__new__(cls)

[docs]classZero(with_metaclass(Singleton,IntegerConstant)):"""The number zero. Zero is a singleton, and can be accessed by ``S.Zero`` Examples ======== >>> from sympy import S, Integer, zoo >>> Integer(0) is S.Zero True >>> 1/S.Zero zoo References ========== .. [1] http://en.wikipedia.org/wiki/Zero """p=0q=1is_positive=Falseis_negative=Falseis_zero=Trueis_number=True__slots__=[]@staticmethoddef__abs__():returnS.Zero@staticmethoddef__neg__():returnS.Zerodef_eval_power(self,expt):ifexpt.is_positive:returnselfifexpt.is_negative:returnS.ComplexInfinityifexpt.is_realisFalse:returnS.NaN# infinities are already handled with pos and neg# tests above; now throw away leading numbers on Mul# exponentcoeff,terms=expt.as_coeff_Mul()ifcoeff.is_negative:returnS.ComplexInfinity**termsifcoeffisnotS.One:# there is a Number to discardreturnself**termsdef_eval_order(self,*symbols):# Order(0,x) -> 0returnselfdef__nonzero__(self):returnFalse__bool__=__nonzero__

[docs]classOne(with_metaclass(Singleton,IntegerConstant)):"""The number one. One is a singleton, and can be accessed by ``S.One``. Examples ======== >>> from sympy import S, Integer >>> Integer(1) is S.One True References ========== .. [1] http://en.wikipedia.org/wiki/1_%28number%29 """is_number=Truep=1q=1__slots__=[]@staticmethoddef__abs__():returnS.One@staticmethoddef__neg__():returnS.NegativeOnedef_eval_power(self,expt):returnselfdef_eval_order(self,*symbols):return@staticmethoddeffactors(limit=None,use_trial=True,use_rho=False,use_pm1=False,verbose=False,visual=False):ifvisual:returnS.Oneelse:return{}

[docs]classNegativeOne(with_metaclass(Singleton,IntegerConstant)):"""The number negative one. NegativeOne is a singleton, and can be accessed by ``S.NegativeOne``. Examples ======== >>> from sympy import S, Integer >>> Integer(-1) is S.NegativeOne True See Also ======== One References ========== .. [1] http://en.wikipedia.org/wiki/%E2%88%921_%28number%29 """is_number=Truep=-1q=1__slots__=[]@staticmethoddef__abs__():returnS.One@staticmethoddef__neg__():returnS.Onedef_eval_power(self,expt):ifexpt.is_odd:returnS.NegativeOneifexpt.is_even:returnS.Oneifisinstance(expt,Number):ifisinstance(expt,Float):returnFloat(-1.0)**exptifexptisS.NaN:returnS.NaNifexptisS.InfinityorexptisS.NegativeInfinity:returnS.NaNifexptisS.Half:returnS.ImaginaryUnitifisinstance(expt,Rational):ifexpt.q==2:returnS.ImaginaryUnit**Integer(expt.p)i,r=divmod(expt.p,expt.q)ifi:returnself**i*self**Rational(r,expt.q)return

[docs]classNaN(with_metaclass(Singleton,Number)):""" Not a Number. This serves as a place holder for numeric values that are indeterminate. Most operations on NaN, produce another NaN. Most indeterminate forms, such as ``0/0`` or ``oo - oo` produce NaN. Two exceptions are ``0**0`` and ``oo**0``, which all produce ``1`` (this is consistent with Python's float). NaN is loosely related to floating point nan, which is defined in the IEEE 754 floating point standard, and corresponds to the Python ``float('nan')``. Differences are noted below. NaN is mathematically not equal to anything else, even NaN itself. This explains the initially counter-intuitive results with ``Eq`` and ``==`` in the examples below. NaN is not comparable so inequalities raise a TypeError. This is in constrast with floating point nan where all inequalities are false. NaN is a singleton, and can be accessed by ``S.NaN``, or can be imported as ``nan``. Examples ======== >>> from sympy import nan, S, oo, Eq >>> nan is S.NaN True >>> oo - oo nan >>> nan + 1 nan >>> Eq(nan, nan) # mathematical equality False >>> nan == nan # structural equality True References ========== .. [1] http://en.wikipedia.org/wiki/NaN """is_commutative=Trueis_real=Noneis_rational=Noneis_algebraic=Noneis_transcendental=Noneis_integer=Noneis_comparable=Falseis_finite=Noneis_zero=Noneis_prime=Noneis_positive=Noneis_negative=Noneis_number=True__slots__=[]def__new__(cls):returnAtomicExpr.__new__(cls)def_latex(self,printer):returnr"\mathrm{NaN}"@_sympifyit('other',NotImplemented)def__add__(self,other):returnself@_sympifyit('other',NotImplemented)def__sub__(self,other):returnself@_sympifyit('other',NotImplemented)def__mul__(self,other):returnself@_sympifyit('other',NotImplemented)def__div__(self,other):returnself__truediv__=__div__def_as_mpf_val(self,prec):return_mpf_nandef_sage_(self):importsage.allassagereturnsage.NaNdef__hash__(self):returnsuper(NaN,self).__hash__()def__eq__(self,other):# NaN is structurally equal to another NaNreturnotherisS.NaNdef__ne__(self,other):returnotherisnotS.NaNdef_eval_Eq(self,other):# NaN is not mathematically equal to anything, even NaNreturnS.false# Expr will _sympify and raise TypeError__gt__=Expr.__gt____ge__=Expr.__ge____lt__=Expr.__lt____le__=Expr.__le__

[docs]classExp1(with_metaclass(Singleton,NumberSymbol)):r"""The `e` constant. The transcendental number `e = 2.718281828\dots` is the base of the natural logarithm and of the exponential function, `e = \exp(1)`. Sometimes called Euler's number or Napier's constant. Exp1 is a singleton, and can be accessed by ``S.Exp1``, or can be imported as ``E``. Examples ======== >>> from sympy import exp, log, E >>> E is exp(1) True >>> log(E) 1 References ========== .. [1] http://en.wikipedia.org/wiki/E_%28mathematical_constant%29 """is_real=Trueis_positive=Trueis_negative=False# XXX Forces is_negative/is_nonnegativeis_irrational=Trueis_number=Trueis_algebraic=Falseis_transcendental=True__slots__=[]def_latex(self,printer):returnr"e"@staticmethoddef__abs__():returnS.Exp1def__int__(self):return2def_as_mpf_val(self,prec):returnmpf_e(prec)defapproximation_interval(self,number_cls):ifissubclass(number_cls,Integer):return(Integer(2),Integer(3))elifissubclass(number_cls,Rational):passdef_eval_power(self,expt):fromsympyimportexpreturnexp(expt)def_eval_rewrite_as_sin(self):fromsympyimportsinI=S.ImaginaryUnitreturnsin(I+S.Pi/2)-I*sin(I)def_eval_rewrite_as_cos(self):fromsympyimportcosI=S.ImaginaryUnitreturncos(I)+I*cos(I+S.Pi/2)def_sage_(self):importsage.allassagereturnsage.e

[docs]classGoldenRatio(with_metaclass(Singleton,NumberSymbol)):r"""The golden ratio, `\phi`. `\phi = \frac{1 + \sqrt{5}}{2}` is algebraic number. Two quantities are in the golden ratio if their ratio is the same as the ratio of their sum to the larger of the two quantities, i.e. their maximum. GoldenRatio is a singleton, and can be accessed by ``S.GoldenRatio``. Examples ======== >>> from sympy import S >>> S.GoldenRatio > 1 True >>> S.GoldenRatio.expand(func=True) 1/2 + sqrt(5)/2 >>> S.GoldenRatio.is_irrational True References ========== .. [1] http://en.wikipedia.org/wiki/Golden_ratio """is_real=Trueis_positive=Trueis_negative=Falseis_irrational=Trueis_number=Trueis_algebraic=Trueis_transcendental=False__slots__=[]def_latex(self,printer):returnr"\phi"def__int__(self):return1def_as_mpf_val(self,prec):# XXX track down why this has to be increasedrv=mlib.from_man_exp(phi_fixed(prec+10),-prec-10)returnmpf_norm(rv,prec)def_eval_expand_func(self,**hints):fromsympyimportsqrtreturnS.Half+S.Half*sqrt(5)defapproximation_interval(self,number_cls):ifissubclass(number_cls,Integer):return(S.One,Rational(2))elifissubclass(number_cls,Rational):passdef_sage_(self):importsage.allassagereturnsage.golden_ratio

[docs]classEulerGamma(with_metaclass(Singleton,NumberSymbol)):r"""The Euler-Mascheroni constant. `\gamma = 0.5772157\dots` (also called Euler's constant) is a mathematical constant recurring in analysis and number theory. It is defined as the limiting difference between the harmonic series and the natural logarithm: .. math:: \gamma = \lim\limits_{n\to\infty} \left(\sum\limits_{k=1}^n\frac{1}{k} - \ln n\right) EulerGamma is a singleton, and can be accessed by ``S.EulerGamma``. Examples ======== >>> from sympy import S >>> S.EulerGamma.is_irrational >>> S.EulerGamma > 0 True >>> S.EulerGamma > 1 False References ========== .. [1] http://en.wikipedia.org/wiki/Euler%E2%80%93Mascheroni_constant """is_real=Trueis_positive=Trueis_negative=Falseis_irrational=Noneis_number=True__slots__=[]def_latex(self,printer):returnr"\gamma"def__int__(self):return0def_as_mpf_val(self,prec):# XXX track down why this has to be increasedv=mlib.libhyper.euler_fixed(prec+10)rv=mlib.from_man_exp(v,-prec-10)returnmpf_norm(rv,prec)defapproximation_interval(self,number_cls):ifissubclass(number_cls,Integer):return(S.Zero,S.One)elifissubclass(number_cls,Rational):return(S.Half,Rational(3,5))def_sage_(self):importsage.allassagereturnsage.euler_gamma