def _eval_nseries(self, x, x0, n): assert len(self.args) == 1 arg = self.args[0] arg0 = arg.limit(x, 0) from sympy import oo if arg0 in [-oo, oo]: raise PoleError("Cannot expand around %s" % (arg)) if arg0 is not S.Zero: e = self.func(arg) e1 = e.expand() if e == e1: #for example when e = sin(x+1) or e = sin(cos(x)) #let's try the general algorithm term = e.subs(x, S.Zero) series = term fact = S.One for i in range(n - 1): i += 1 fact *= Rational(i) e = e.diff(x) term = e.subs(x, S.Zero) * (x**i) / fact term = term.expand() series += term return series + C.Order(x**n, x) return self.nseries(x, x0, n) l = [] g = None for i in xrange(n + 2): g = self.taylor_term(i, arg, g) g = g.nseries(x, x0, n) l.append(g) return Add(*l) + C.Order(x**n, x)
def _eval_expand_complex(self, *args): if self.exp.is_Integer: exp = self.exp re, im = self.base.as_real_imag() if exp >= 0: base = re + S.ImaginaryUnit * im else: mag = re ** 2 + im ** 2 base = re / mag - S.ImaginaryUnit * (im / mag) exp = -exp return (base ** exp).expand() elif self.exp.is_Rational: # NOTE: This is not totally correct since for x**(p/q) with # x being imaginary there are actually q roots, but # only a single one is returned from here. re, im = self.base.as_real_imag() r = (re ** 2 + im ** 2) ** S.Half t = C.atan2(im, re) rp, tp = r ** self.exp, t * self.exp return rp * C.cos(tp) + rp * C.sin(tp) * S.ImaginaryUnit else: return C.re(self) + S.ImaginaryUnit * C.im(self)
def check_convergence(numer, denom, n): """ Returns (h, g, p) where -- h is: > 0 for convergence of rate 1/factorial(n)**h < 0 for divergence of rate factorial(n)**(-h) = 0 for geometric or polynomial convergence or divergence -- abs(g) is: > 1 for geometric convergence of rate 1/h**n < 1 for geometric divergence of rate h**n = 1 for polynomial convergence or divergence (g < 0 indicates an alternating series) -- p is: > 1 for polynomial convergence of rate 1/n**h <= 1 for polynomial divergence of rate n**(-h) """ npol = C.Poly(numer, n) dpol = C.Poly(denom, n) p = npol.degree() q = dpol.degree() rate = q - p if rate: return rate, None, None constant = dpol.LC() / npol.LC() if abs(constant) != 1: return rate, constant, None if npol.degree() == dpol.degree() == 0: return rate, constant, 0 pc = npol.all_coeffs()[1] qc = dpol.all_coeffs()[1] return rate, constant, qc - pc
def evalf_log(expr, prec, options): arg = expr.args[0] workprec = prec + 10 xre, xim, xacc, _ = evalf(arg, workprec, options) if xim: # XXX: use get_abs etc instead re = evalf_log(C.log(C.abs(arg, evaluate=False), evaluate=False), prec, options) im = mpf_atan2(xim, xre or fzero, prec) return re[0], im, re[2], prec imaginary_term = (mpf_cmp(xre, fzero) < 0) re = mpf_log(mpf_abs(xre), prec, round_nearest) size = fastlog(re) if prec - size > workprec: # We actually need to compute 1+x accurately, not x arg = C.Add(S.NegativeOne, arg, evaluate=False) xre, xim, xre_acc, xim_acc = evalf_add(arg, prec, options) prec2 = workprec - fastlog(xre) re = mpf_log(mpf_add(xre, fone, prec2), prec, round_nearest) re_acc = prec if imaginary_term: return re, mpf_pi(prec), re_acc, prec else: return re, None, re_acc, None
def _eval_expand_complex(self, *args): if self.exp.is_Integer: exp = self.exp re, im = self.base.as_real_imag() if exp >= 0: base = re + S.ImaginaryUnit*im else: mag = re**2 + im**2 base = re/mag - S.ImaginaryUnit*(im/mag) exp = -exp return (base**exp).expand() elif self.exp.is_Rational: # NOTE: This is not totally correct since for x**(p/q) with # x being imaginary there are actually q roots, but # only a single one is returned from here. re, im = self.base.as_real_imag() r = (re**2 + im**2)**S.Half t = C.atan2(im, re) rp, tp = r**self.exp, t*self.exp return rp*C.cos(tp) + rp*C.sin(tp)*S.ImaginaryUnit else: return C.re(self) + S.ImaginaryUnit*C.im(self)
def evalf_log(expr, prec, options): arg = expr.args[0] workprec = prec+10 xre, xim, xacc, _ = evalf(arg, workprec, options) if xim: # XXX: use get_abs etc instead re = evalf_log(C.log(C.abs(arg, evaluate=False), evaluate=False), prec, options) im = mpf_atan2(xim, xre or fzero, prec) return re[0], im, re[2], prec imaginary_term = (mpf_cmp(xre, fzero) < 0) re = mpf_log(mpf_abs(xre), prec, round_nearest) size = fastlog(re) if prec - size > workprec: # We actually need to compute 1+x accurately, not x arg = C.Add(S.NegativeOne,arg,evaluate=False) xre, xim, xre_acc, xim_acc = evalf_add(arg, prec, options) prec2 = workprec - fastlog(xre) re = mpf_log(mpf_add(xre, fone, prec2), prec, round_nearest) re_acc = prec if imaginary_term: return re, mpf_pi(prec), re_acc, prec else: return re, None, re_acc, None
def as_real_imag(self, deep=True): other = [] coeff = S(1) for a in self.args: if a.is_real: coeff *= a else: other.append(a) m = Mul(*other) return (coeff*C.re(m), coeff*C.im(m))
def as_real_imag(self, deep=True): other = [] coeff = S(1) for a in self.args: if a.is_real: coeff *= a else: other.append(a) m = Mul(*other) return (coeff * C.re(m), coeff * C.im(m))
def get_integer_part(expr, no, options, return_ints=False): """ With no = 1, computes ceiling(expr) With no = -1, computes floor(expr) Note: this function either gives the exact result or signals failure. """ # The expression is likely less than 2^30 or so assumed_size = 30 ire, iim, ire_acc, iim_acc = evalf(expr, assumed_size, options) # We now know the size, so we can calculate how much extra precision # (if any) is needed to get within the nearest integer if ire and iim: gap = max(fastlog(ire) - ire_acc, fastlog(iim) - iim_acc) elif ire: gap = fastlog(ire) - ire_acc elif iim: gap = fastlog(iim) - iim_acc else: # ... or maybe the expression was exactly zero return None, None, None, None margin = 10 if gap >= -margin: ire, iim, ire_acc, iim_acc = evalf(expr, margin + assumed_size + gap, options) # We can now easily find the nearest integer, but to find floor/ceil, we # must also calculate whether the difference to the nearest integer is # positive or negative (which may fail if very close) def calc_part(expr, nexpr): nint = int(to_int(nexpr, round_nearest)) expr = C.Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) check_target(expr, (x, None, x_acc, None), 3) nint += int(no * (mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10 re, im, re_acc, im_acc = None, None, None, None if ire: re, re_acc = calc_part(C.re(expr, evaluate=False), ire) if iim: im, im_acc = calc_part(C.im(expr, evaluate=False), iim) if return_ints: return int(to_int(re or fzero)), int(to_int(im or fzero)) return re, im, re_acc, im_acc
def as_real_imag(self, deep=True, **hints): other = [] coeff = S(1) for a in self.args: if a.is_real: coeff *= a else: other.append(a) m = Mul(*other) if hints.get('ignore') == m: return None else: return (coeff*C.re(m), coeff*C.im(m))
def evalf_piecewise(expr, prec, options): if 'subs' in options: expr = expr.subs(options['subs']) del options['subs'] if hasattr(expr, 'func'): return evalf(expr, prec, options) if type(expr) == float: return evalf(C.Real(expr), prec, options) if type(expr) == int: return evalf(C.Integer(expr), prec, options) # We still have undefined symbols raise NotImplementedError
def get_integer_part(expr, no, options, return_ints=False): """ With no = 1, computes ceiling(expr) With no = -1, computes floor(expr) Note: this function either gives the exact result or signals failure. """ # The expression is likely less than 2^30 or so assumed_size = 30 ire, iim, ire_acc, iim_acc = evalf(expr, assumed_size, options) # We now know the size, so we can calculate how much extra precision # (if any) is needed to get within the nearest integer if ire and iim: gap = max(fastlog(ire)-ire_acc, fastlog(iim)-iim_acc) elif ire: gap = fastlog(ire)-ire_acc elif iim: gap = fastlog(iim)-iim_acc else: # ... or maybe the expression was exactly zero return None, None, None, None margin = 10 if gap >= -margin: ire, iim, ire_acc, iim_acc = evalf(expr, margin+assumed_size+gap, options) # We can now easily find the nearest integer, but to find floor/ceil, we # must also calculate whether the difference to the nearest integer is # positive or negative (which may fail if very close) def calc_part(expr, nexpr): nint = int(to_int(nexpr, round_nearest)) expr = C.Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) check_target(expr, (x, None, x_acc, None), 3) nint += int(no*(mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10 re, im, re_acc, im_acc = None, None, None, None if ire: re, re_acc = calc_part(C.re(expr, evaluate=False), ire) if iim: im, im_acc = calc_part(C.im(expr, evaluate=False), iim) if return_ints: return int(to_int(re or fzero)), int(to_int(im or fzero)) return re, im, re_acc, im_acc
def evalf_sum(expr, prec, options): func = expr.function limits = expr.limits if len(limits) != 1 or not isinstance(limits[0], tuple) or \ len(limits[0]) != 3: raise NotImplementedError prec2 = prec + 10 try: n, a, b = limits[0] if b != S.Infinity or a != int(a): raise NotImplementedError # Use fast hypergeometric summation if possible v = hypsum(func, n, int(a), prec2) delta = prec - fastlog(v) if fastlog(v) < -10: v = hypsum(func, n, int(a), delta) return v, None, min(prec, delta), None except NotImplementedError: # Euler-Maclaurin summation for general series eps = C.Real(2.0)**(-prec) for i in range(1, 5): m = n = 2**i * prec s, err = expr.euler_maclaurin(m=m, n=n, eps=eps, \ eval_integral=False) err = err.evalf() if err <= eps: break err = fastlog(evalf(abs(err), 20, options)[0]) re, im, re_acc, im_acc = evalf(s, prec2, options) re_acc = max(re_acc, -err) im_acc = max(im_acc, -err) return re, im, re_acc, im_acc
def extract_leading_order(self, *symbols): """ Returns the leading term and it's order. Examples: >>> (x+1+1/x**5).extract_leading_order(x) ((1/x**5, O(1/x**5)),) >>> (1+x).extract_leading_order(x) ((1, O(1, x)),) >>> (x+x**2).extract_leading_order(x) ((x, O(x)),) """ lst = [] seq = [(f, C.Order(f, *symbols)) for f in self.args] for ef,of in seq: for e,o in lst: if o.contains(of) and o != of: of = None break if of is None: continue new_lst = [(ef,of)] for e,o in lst: if of.contains(o) and o != of: continue new_lst.append((e,o)) lst = new_lst return tuple(lst)
def calc_part(expr, nexpr): nint = int(to_int(nexpr, round_nearest)) expr = C.Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) check_target(expr, (x, None, x_acc, None), 3) nint += int(no * (mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10
def _eval_as_leading_term(self, x): """General method for the leading term""" arg = self.args[0].as_leading_term(x) if C.Order(1, x).contains(arg): return arg else: return self.func(arg)
def taylor_term(cls, n, x, *previous_terms): """General method for the taylor term. This method is slow, because it differentiates n-times. Subclasses can redefine it to make it faster by using the "previous_terms". """ x = sympify(x) return cls(x).diff(x, n).subs(x, 0) * x**n / C.Factorial(n)
def as_real_imag(self, deep=True, **hints): from sympy.core.symbol import symbols from sympy.polys.polytools import poly from sympy.core.function import expand_multinomial if self.exp.is_Integer: exp = self.exp re, im = self.base.as_real_imag(deep=deep) a, b = symbols('a, b', dummy=True) if exp >= 0: if re.is_Number and im.is_Number: # We can be more efficient in this case expr = expand_multinomial(self.base**exp) return expr.as_real_imag() expr = poly((a + b)**exp) # a = re, b = im; expr = (a + b*I)**exp else: mag = re**2 + im**2 re, im = re/mag, -im/mag if re.is_Number and im.is_Number: # We can be more efficient in this case expr = expand_multinomial((re + im*S.ImaginaryUnit)**-exp) return expr.as_real_imag() expr = poly((a + b)**-exp) # Terms with even b powers will be real r = [i for i in expr.terms() if not i[0][1] % 2] re_part = Add(*[cc*a**aa*b**bb for (aa, bb), cc in r]) # Terms odd b powers will be imaginary r = [i for i in expr.terms() if i[0][1] % 4 == 1] im_part1 = Add(*[cc*a**aa*b**bb for (aa, bb), cc in r]) r = [i for i in expr.terms() if i[0][1] % 4 == 3] im_part3 = Add(*[cc*a**a*b**bb for (aa, bb), cc in r]) return (re_part.subs({a: re, b: S.ImaginaryUnit*im}), im_part1.subs({a: re, b: im}) + im_part3.subs({a: re, b: -im})) elif self.exp.is_Rational: # NOTE: This is not totally correct since for x**(p/q) with # x being imaginary there are actually q roots, but # only a single one is returned from here. re, im = self.base.as_real_imag(deep=deep) r = (re**2 + im**2)**S.Half t = C.atan2(im, re) rp, tp = r**self.exp, t*self.exp return (rp*C.cos(tp), rp*C.sin(tp)) else: if deep: hints['complex'] = False return (C.re(self.expand(deep, complex=False)), C.im(self. expand(deep, **hints))) else: return (C.re(self), C.im(self))
def _eval_subs(self, old, new): if self==old: return new if isinstance(old, self.__class__) and self.base==old.base: coeff1,terms1 = self.exp.as_coeff_terms() coeff2,terms2 = old.exp.as_coeff_terms() if terms1==terms2: return new ** (coeff1/coeff2) # (x**(2*y)).subs(x**(3*y),z) -> z**(2/3*y) if old.func is C.exp: coeff1,terms1 = old.args[0].as_coeff_terms() coeff2,terms2 = (self.exp * C.log(self.base)).as_coeff_terms() if terms1==terms2: return new ** (coeff1/coeff2) # (x**(2*y)).subs(exp(3*y*log(x)),z) -> z**(2/3*y) return self.base._eval_subs(old, new) ** self.exp._eval_subs(old, new)
def _eval_as_leading_term(self, x): coeff, factors = self.as_coeff_factors(x) has_unbounded = bool([f for f in self.args if f.is_unbounded]) if has_unbounded: if isinstance(factors, Basic): factors = factors.args factors = [f for f in factors if not f.is_bounded] if coeff is not S.Zero: o = C.Order(x) else: o = C.Order(factors[0]*x,x) n = 1 s = self.nseries(x, 0, n) while s.is_Order: n +=1 s = self.nseries(x, 0, n) if s.is_Add: s = s.removeO() if s.is_Add: lst = s.extract_leading_order(x) return Add(*[e for (e,f) in lst]) return s.as_leading_term(x)
def eval(cls, *args): obj = Expr.__new__(cls, *args) #use dummy variables internally, just to be sure nargs = len(args) - 1 expression = args[nargs] funargs = [C.Symbol(arg.name, dummy=True) for arg in args[:nargs]] #probably could use something like foldl here for arg, funarg in zip(args[:nargs], funargs): expression = expression.subs(arg, funarg) funargs.append(expression) obj._args = tuple(funargs) return obj
def as_real_imag(self, deep=True): """Performs complex expansion on 'self' and returns a tuple containing collected both real and imaginary parts. This method can't be confused with re() and im() functions, which does not perform complex expansion at evaluation. However it is possible to expand both re() and im() functions and get exactly the same results as with a single call to this function. >>> from sympy import symbols, I >>> x, y = symbols('xy', real=True) >>> (x + y*I).as_real_imag() (x, y) >>> from sympy.abc import z, w >>> (z + w*I).as_real_imag() (-im(w) + re(z), im(z) + re(w)) """ return (C.re(self), C.im(self))
def __new__(cls, num, prec=15): prec = mpmath.settings.dps_to_prec(prec) if isinstance(num, (int, long)): return Integer(num) if isinstance(num, (str, decimal.Decimal)): _mpf_ = mlib.from_str(str(num), prec, rnd) elif isinstance(num, tuple) and len(num) == 4: _mpf_ = num else: _mpf_ = mpmath.mpf(num)._mpf_ if not num: return C.Zero() obj = Basic.__new__(cls) obj._mpf_ = _mpf_ obj._prec = prec return obj
def testIt(self): from basic import C, call_f class D(C): def f(self, x=10): return x+1 d = D() c = C() self.assertEqual(c.f(), 20) self.assertEqual(c.f(3), 6) self.assertEqual(d.f(), 11) self.assertEqual(d.f(3), 4) self.assertEqual(call_f(c), 20) self.assertEqual(call_f(c, 4), 8) self.assertEqual(call_f(d), 11) self.assertEqual(call_f(d, 3), 4)
def __new__(cls, *args, **assumptions): if assumptions.get('evaluate') is False: return Basic.__new__(cls, *map(_sympify, args), **assumptions) if len(args)==0: return cls.identity() if len(args)==1: return _sympify(args[0]) c_part, nc_part, order_symbols = cls.flatten(map(_sympify, args)) if len(c_part) + len(nc_part) <= 1: if c_part: obj = c_part[0] elif nc_part: obj = nc_part[0] else: obj = cls.identity() else: obj = Basic.__new__(cls, *(c_part + nc_part), **assumptions) obj.is_commutative = not nc_part if order_symbols is not None: obj = C.Order(obj, *order_symbols) return obj
def _create_evalf_table(): global evalf_table evalf_table = { C.Symbol : evalf_symbol, C.Dummy : evalf_symbol, C.Real : lambda x, prec, options: (x._mpf_, None, prec, None), C.Rational : lambda x, prec, options: (from_rational(x.p, x.q, prec), None, prec, None), C.Integer : lambda x, prec, options: (from_int(x.p, prec), None, prec, None), C.Zero : lambda x, prec, options: (None, None, prec, None), C.One : lambda x, prec, options: (fone, None, prec, None), C.Half : lambda x, prec, options: (fhalf, None, prec, None), C.Pi : lambda x, prec, options: (mpf_pi(prec), None, prec, None), C.Exp1 : lambda x, prec, options: (mpf_e(prec), None, prec, None), C.ImaginaryUnit : lambda x, prec, options: (None, fone, None, prec), C.NegativeOne : lambda x, prec, options: (fnone, None, prec, None), C.exp : lambda x, prec, options: evalf_pow(C.Pow(S.Exp1, x.args[0], evaluate=False), prec, options), C.cos : evalf_trig, C.sin : evalf_trig, C.Add : evalf_add, C.Mul : evalf_mul, C.Pow : evalf_pow, C.log : evalf_log, C.atan : evalf_atan, C.abs : evalf_abs, C.re : evalf_re, C.im : evalf_im, C.floor : evalf_floor, C.ceiling : evalf_ceiling, C.Integral : evalf_integral, C.Sum : evalf_sum, C.Piecewise : evalf_piecewise, C.bernoulli : evalf_bernoulli, }
def _eval_expand_complex(self, *args): return C.re(self) + C.im(self)*S.ImaginaryUnit
def do_integral(expr, prec, options): func = expr.args[0] x, (xlow, xhigh) = expr.args[1][0] orig = mp.prec oldmaxprec = options.get('maxprec', DEFAULT_MAXPREC) options['maxprec'] = min(oldmaxprec, 2 * prec) try: mp.prec = prec + 5 xlow = as_mpmath(xlow, prec + 15, options) xhigh = as_mpmath(xhigh, prec + 15, options) # Integration is like summation, and we can phone home from # the integrand function to update accuracy summation style # Note that this accuracy is inaccurate, since it fails # to account for the variable quadrature weights, # but it is better than nothing have_part = [False, False] max_real_term = [MINUS_INF] max_imag_term = [MINUS_INF] def f(t): re, im, re_acc, im_acc = evalf(func, mp.prec, {'subs': {x: t}}) have_part[0] = re or have_part[0] have_part[1] = im or have_part[1] max_real_term[0] = max(max_real_term[0], fastlog(re)) max_imag_term[0] = max(max_imag_term[0], fastlog(im)) if im: return mpc(re or fzero, im) return mpf(re or fzero) if options.get('quad') == 'osc': A = C.Wild('A', exclude=[x]) B = C.Wild('B', exclude=[x]) D = C.Wild('D') m = func.match(C.cos(A * x + B) * D) if not m: m = func.match(C.sin(A * x + B) * D) if not m: raise ValueError( "An integrand of the form sin(A*x+B)*f(x) " "or cos(A*x+B)*f(x) is required for oscillatory quadrature" ) period = as_mpmath(2 * S.Pi / m[A], prec + 15, options) result = quadosc(f, [xlow, xhigh], period=period) # XXX: quadosc does not do error detection yet quadrature_error = MINUS_INF else: result, quadrature_error = quadts(f, [xlow, xhigh], error=1) quadrature_error = fastlog(quadrature_error._mpf_) finally: options['maxprec'] = oldmaxprec mp.prec = orig if have_part[0]: re = result.real._mpf_ if re == fzero: re = mpf_shift(fone, min(-prec, -max_real_term[0], -quadrature_error)) re_acc = -1 else: re_acc = -max(max_real_term[0] - fastlog(re) - prec, quadrature_error) else: re, re_acc = None, None if have_part[1]: im = result.imag._mpf_ if im == fzero: im = mpf_shift(fone, min(-prec, -max_imag_term[0], -quadrature_error)) im_acc = -1 else: im_acc = -max(max_imag_term[0] - fastlog(im) - prec, quadrature_error) else: im, im_acc = None, None result = re, im, re_acc, im_acc return result
def as_real_imag(self, deep=True): return (C.re(self), C.im(self))
def _eval_expand_complex(self, *args): func = self.func(*[a._eval_expand_complex(*args) for a in self.args]) return C.re(func) + S.ImaginaryUnit * C.im(func)
def do_integral(expr, prec, options): func = expr.args[0] x, (xlow, xhigh) = expr.args[1][0] orig = mp.prec oldmaxprec = options.get('maxprec', DEFAULT_MAXPREC) options['maxprec'] = min(oldmaxprec, 2*prec) try: mp.prec = prec+5 xlow = as_mpmath(xlow, prec+15, options) xhigh = as_mpmath(xhigh, prec+15, options) # Integration is like summation, and we can phone home from # the integrand function to update accuracy summation style # Note that this accuracy is inaccurate, since it fails # to account for the variable quadrature weights, # but it is better than nothing have_part = [False, False] max_real_term = [MINUS_INF] max_imag_term = [MINUS_INF] def f(t): re, im, re_acc, im_acc = evalf(func, mp.prec, {'subs':{x:t}}) have_part[0] = re or have_part[0] have_part[1] = im or have_part[1] max_real_term[0] = max(max_real_term[0], fastlog(re)) max_imag_term[0] = max(max_imag_term[0], fastlog(im)) if im: return mpc(re or fzero, im) return mpf(re or fzero) if options.get('quad') == 'osc': A = C.Wild('A', exclude=[x]) B = C.Wild('B', exclude=[x]) D = C.Wild('D') m = func.match(C.cos(A*x+B)*D) if not m: m = func.match(C.sin(A*x+B)*D) if not m: raise ValueError("An integrand of the form sin(A*x+B)*f(x) " "or cos(A*x+B)*f(x) is required for oscillatory quadrature") period = as_mpmath(2*S.Pi/m[A], prec+15, options) result = quadosc(f, [xlow, xhigh], period=period) # XXX: quadosc does not do error detection yet quadrature_error = MINUS_INF else: result, quadrature_error = quadts(f, [xlow, xhigh], error=1) quadrature_error = fastlog(quadrature_error._mpf_) finally: options['maxprec'] = oldmaxprec mp.prec = orig if have_part[0]: re = result.real._mpf_ if re == fzero: re = mpf_shift(fone, min(-prec,-max_real_term[0],-quadrature_error)) re_acc = -1 else: re_acc = -max(max_real_term[0]-fastlog(re)-prec, quadrature_error) else: re, re_acc = None, None if have_part[1]: im = result.imag._mpf_ if im == fzero: im = mpf_shift(fone, min(-prec,-max_imag_term[0],-quadrature_error)) im_acc = -1 else: im_acc = -max(max_imag_term[0]-fastlog(im)-prec, quadrature_error) else: im, im_acc = None, None result = re, im, re_acc, im_acc return result
def __abs__(self): return C.abs(self)
def _eval_expand_complex(self, *args): func = self.func(*[ a._eval_expand_complex(*args) for a in self.args ]) return C.re(func) + S.ImaginaryUnit * C.im(func)
def _eval_as_leading_term(self, x): if not self.exp.has(x): return self.base.as_leading_term(x) ** self.exp return C.exp(self.exp * C.log(self.base)).as_leading_term(x)
def __lt__(self, other): dif = self - other if dif.is_negative != dif.is_nonnegative: return dif.is_negative return C.StrictInequality(self, other)
def _eval_expand_complex(self, deep=True, **hints): if deep: func = self.func(*[ a.expand(deep, **hints) for a in self.args ]) else: func = self.func(*self.args) return C.re(func) + S.ImaginaryUnit * C.im(func)
def fdiff(self, *indices): # FIXME FApply -> ? return C.FApply(C.FDerivative(*indices), self)
def __gt__(self, other): dif = self - other if dif.is_positive != dif.is_nonpositive: return dif.is_positive return C.StrictInequality(other, self)
def __le__(self, other): dif = self - other if dif.is_nonpositive != dif.is_positive: return dif.is_nonpositive return C.Inequality(self, other)
def _eval_expand_complex(self, deep=True, **hints): if deep: func = self.func(*[a.expand(deep, **hints) for a in self.args]) else: func = self.func(*self.args) return C.re(func) + S.ImaginaryUnit * C.im(func)
def __ge__(self, other): dif = self - other if dif.is_nonnegative != dif.is_negative: return dif.is_nonnegative return C.Inequality(other, self)
def _eval_power(self, exp): return C.exp(exp)
def extract_additively(self, c): """Return None if it's not possible to make self in the form something + c in a nice way, i.e. preserving the properties of arguments of self. >>> from sympy import symbols >>> x, y = symbols('xy', real=True) >>> ((x*y)**3).extract_additively(1) >>> (x+1).extract_additively(x) 1 >>> (x+1).extract_additively(2*x) >>> (x+1).extract_additively(-x) 1 + 2*x >>> (-x+1).extract_additively(2*x) 1 - 3*x """ c = sympify(c) if c is S.Zero: return self elif c == self: return S.Zero elif self is S.Zero: return None elif c.is_Add: x = self.extract_additively(c.as_two_terms()[0]) if x != None: return x.extract_additively(c.as_two_terms()[1]) sub = self - c if self.is_Number: if self.is_Integer: if not sub.is_Integer: return None elif self.is_positive and sub.is_negative: return None else: return sub elif self.is_Rational: if not sub.is_Rational: return None elif self.is_positive and sub.is_negative: return None else: return sub elif self.is_Real: if not sub.is_Real: return None elif self.is_positive and sub.is_negative: return None else: return sub elif self.is_NumberSymbol or self.is_Symbol or self is S.ImaginaryUnit: if sub.is_Mul and len(sub.args) == 2: if sub.args[0].is_Integer and sub.args[ 0].is_positive and sub.args[1] == self: return sub elif sub.is_Integer: return sub elif self.is_Add: terms = self.as_two_terms() subs0 = terms[0].extract_additively(c) if subs0 != None: return subs0 + terms[1] else: subs1 = terms[1].extract_additively(c) if subs1 != None: return subs1 + terms[0] elif self.is_Mul: self_coeff, self_terms = self.as_coeff_terms() if c.is_Mul: c_coeff, c_terms = c.as_coeff_terms() if c_terms == self_terms: new_coeff = self_coeff.extract_additively(c_coeff) if new_coeff != None: return new_coeff * C.Mul(*self_terms) elif c == self_terms: new_coeff = self_coeff.extract_additively(1) if new_coeff != None: return new_coeff * C.Mul(*self_terms)
def _eval_derivative(self, s): dbase = self.base.diff(s) dexp = self.exp.diff(s) return self * (dexp * C.log(self.base) + dbase * self.exp / self.base)
def extract_multiplicatively(self, c): """Return None if it's not possible to make self in the form c * something in a nice way, i.e. preserving the properties of arguments of self. >>> from sympy import symbols, Rational >>> x, y = symbols('xy', real=True) >>> ((x*y)**3).extract_multiplicatively(x**2 * y) x*y**2 >>> ((x*y)**3).extract_multiplicatively(x**4 * y) >>> (2*x).extract_multiplicatively(2) x >>> (2*x).extract_multiplicatively(3) >>> (Rational(1,2)*x).extract_multiplicatively(3) x/6 """ c = sympify(c) if c is S.One: return self elif c == self: return S.One elif c.is_Mul: x = self.extract_multiplicatively(c.as_two_terms()[0]) if x != None: return x.extract_multiplicatively(c.as_two_terms()[1]) quotient = self / c if self.is_Number: if self is S.Infinity: if c.is_positive: return S.Infinity elif self is S.NegativeInfinity: if c.is_negative: return S.Infinity elif c.is_positive: return S.NegativeInfinity elif self is S.ComplexInfinity: if not c.is_zero: return S.ComplexInfinity elif self is S.NaN: return S.NaN elif self.is_Integer: if not quotient.is_Integer: return None elif self.is_positive and quotient.is_negative: return None else: return quotient elif self.is_Rational: if not quotient.is_Rational: return None elif self.is_positive and quotient.is_negative: return None else: return quotient elif self.is_Real: if not quotient.is_Real: return None elif self.is_positive and quotient.is_negative: return None else: return quotient elif self.is_NumberSymbol or self.is_Symbol or self is S.ImaginaryUnit: if quotient.is_Mul and len(quotient.args) == 2: if quotient.args[0].is_Integer and quotient.args[ 0].is_positive and quotient.args[1] == self: return quotient elif quotient.is_Integer: return quotient elif self.is_Add: newargs = [] for arg in self.args: newarg = arg.extract_multiplicatively(c) if newarg != None: newargs.append(newarg) else: return None return C.Add(*newargs) elif self.is_Mul: for i in xrange(len(self.args)): newargs = list(self.args) del (newargs[i]) tmp = C.Mul(*newargs).extract_multiplicatively(c) if tmp != None: return tmp * self.args[i] elif self.is_Pow: if c.is_Pow and c.base == self.base: new_exp = self.exp.extract_additively(c.exp) if new_exp != None: return self.base**(new_exp) elif c == self.base: new_exp = self.exp.extract_additively(1) if new_exp != None: return self.base**(new_exp)
def _eval_expand_complex(self, deep=True, **hints): return C.re(self) + C.im(self)*S.ImaginaryUnit