Source code for sympy.core.power

from math import log as _log

from .sympify import _sympify
from .cache import cacheit
from .core import C
from sympy.core.function import (_coeff_isneg, expand_complex,
    expand_multinomial, expand_mul)
from .singleton import S
from .expr import Expr

from sympy import mpmath
from sympy.utilities.iterables import sift

[docs]def integer_nthroot(y, n): """ Return a tuple containing x = floor(y**(1/n)) and a boolean indicating whether the result is exact (that is, whether x**n == y). >>> from sympy import integer_nthroot >>> integer_nthroot(16,2) (4, True) >>> integer_nthroot(26,2) (5, False) """ y, n = int(y), int(n) if y < 0: raise ValueError("y must be nonnegative") if n < 1: raise ValueError("n must be positive") if y in (0, 1): return y, True if n == 1: return y, True if n == 2: x, rem = mpmath.libmp.sqrtrem(y) return int(x), not rem if n > y: return 1, False # Get initial estimate for Newton's method. Care must be taken to # avoid overflow try: guess = int(y**(1./n) + 0.5) except OverflowError: exp = _log(y, 2)/n if exp > 53: shift = int(exp - 53) guess = int(2.0**(exp - shift) + 1) << shift else: guess = int(2.0**exp) #print n if guess > 2**50: # Newton iteration xprev, x = -1, guess while 1: t = x**(n-1) #xprev, x = x, x - (t*x-y)//(n*t) xprev, x = x, ((n-1)*x + y//t)//n #print n, x-xprev, abs(x-xprev) < 2 if abs(x - xprev) < 2: break else: x = guess # Compensate t = x**n while t < y: x += 1 t = x**n while t > y: x -= 1 t = x**n return x, t == y
[docs]class Pow(Expr): is_Pow = True __slots__ = ['is_commutative'] @cacheit def __new__(cls, b, e, evaluate=True): # don't optimize "if e==0; return 1" here; it's better to handle that # in the calling routine so this doesn't get called b = _sympify(b) e = _sympify(e) if evaluate: if e is S.Zero: return S.One elif e is S.One: return b elif S.NaN in (b, e): if b is S.One: # already handled e == 0 above return S.One return S.NaN else: obj = b._eval_power(e) if obj is not None: return obj obj = Expr.__new__(cls, b, e) obj.is_commutative = (b.is_commutative and e.is_commutative) return obj @property def base(self): return self._args[0] @property def exp(self): return self._args[1] @classmethod def class_key(cls): return 3, 2, cls.__name__ def _eval_power(self, other): from sympy.functions.elementary.exponential import log b, e = self.as_base_exp() b_nneg = b.is_nonnegative if b.is_real and not b_nneg and e.is_even: b = abs(b) b_nneg = True smallarg = (abs(e) <= abs(S.Pi/log(b))) if (other.is_Rational and other.q == 2 and e.is_real is False and smallarg is False): return -Pow(b, e*other) if (other.is_integer or e.is_real and (b_nneg or abs(e) < 1) or e.is_real is False and smallarg is True or b.is_polar): return Pow(b, e*other) def _eval_is_even(self): if self.exp.is_integer and self.exp.is_positive: return self.base.is_even def _eval_is_positive(self): if self.base.is_positive: if self.exp.is_real: return True elif self.base.is_negative: if self.exp.is_even: return True if self.exp.is_odd: return False elif self.base.is_nonpositive: if self.exp.is_odd: return False def _eval_is_negative(self): if self.base.is_negative: if self.exp.is_odd: return True if self.exp.is_even: return False elif self.base.is_positive: if self.exp.is_real: return False elif self.base.is_nonnegative: if self.exp.is_real: return False elif self.base.is_nonpositive: if self.exp.is_even: return False elif self.base.is_real: if self.exp.is_even: return False def _eval_is_integer(self): b, e = self.args c1 = b.is_integer c2 = e.is_integer if c1 is None or c2 is None: return None if not c1 and e.is_nonnegative: #rat**nonneg return False if c1 and c2: # int**int if e.is_nonnegative or e.is_positive: return True if self.exp.is_negative: return False if c1 and e.is_negative and e.is_bounded: #int**neg return False if b.is_Number and e.is_Number: # int**nonneg or rat**? check = Pow(*self.args) return check.is_Integer def _eval_is_real(self): real_b = self.base.is_real if real_b is None: return real_e = self.exp.is_real if real_e is None: return if real_b and real_e: if self.base.is_positive: return True else: # negative or zero (or positive) if self.exp.is_integer: return True elif self.base.is_negative: if self.exp.is_Rational: return False im_b = self.base.is_imaginary im_e = self.exp.is_imaginary if im_b: if self.exp.is_integer: if self.exp.is_even: return True elif self.exp.is_odd: return False elif (self.exp in [S.ImaginaryUnit, -S.ImaginaryUnit] and self.base in [S.ImaginaryUnit, -S.ImaginaryUnit]): return True if real_b and im_e: c = self.exp.coeff(S.ImaginaryUnit) if c: ok = (c*C.log(self.base)/S.Pi).is_Integer if ok is not None: return ok def _eval_is_odd(self): if self.exp.is_integer: if self.exp.is_positive: return self.base.is_odd elif self.exp.is_nonnegative and self.base.is_odd: return True def _eval_is_bounded(self): if self.exp.is_negative: if self.base.is_infinitesimal: return False if self.base.is_unbounded: return True c1 = self.base.is_bounded if c1 is None: return c2 = self.exp.is_bounded if c2 is None: return if c1 and c2: if self.exp.is_nonnegative or self.base.is_nonzero: return True def _eval_is_polar(self): return self.base.is_polar def _eval_subs(self, old, new): if old.func is self.func and self.base == old.base: coeff1, terms1 = self.exp.as_coeff_Mul() coeff2, terms2 = old.exp.as_coeff_Mul() if terms1 == terms2: pow = coeff1/coeff2 if pow == int(pow) or self.base.is_positive: # issue 2081 return Pow(new, pow) # (x**(6*y)).subs(x**(3*y),z)->z**2 if old.func is C.exp and self.exp.is_real and self.base.is_positive: coeff1, terms1 = old.args[0].as_coeff_Mul() # we can only do this when the base is positive AND the exponent # is real coeff2, terms2 = (self.exp*C.log(self.base)).as_coeff_Mul() if terms1 == terms2: pow = coeff1/coeff2 if pow == int(pow) or self.base.is_positive: return Pow(new, pow) # (2**x).subs(exp(x*log(2)), z) -> z
[docs] def as_base_exp(self): """Return base and exp of self unless base is 1/Integer, then return Integer, -exp. If this extra processing is not needed, the base and exp properties will give the raw arguments, e.g. (1/2, 2) for (1/2)**2 rather than (2, -2). """ b, e = self.args if b.is_Rational and b.p == 1: return Integer(b.q), -e return b, e
def _eval_adjoint(self): from sympy.functions.elementary.complexes import adjoint i, p = self.exp.is_integer, self.base.is_positive if i: return adjoint(self.base)**self.exp if p: return self.base**adjoint(self.exp) if i is False and p is False: expanded = expand_complex(self) if expanded != self: return adjoint(expanded) def _eval_conjugate(self): from sympy.functions.elementary.complexes import conjugate as c i, p = self.exp.is_integer, self.base.is_positive if i: return c(self.base)**self.exp if p: return self.base**c(self.exp) if i is False and p is False: expanded = expand_complex(self) if expanded != self: return c(expanded) def _eval_transpose(self): from sympy.functions.elementary.complexes import transpose i, p = self.exp.is_integer, self.base.is_complex if p: return self.base**self.exp if i: return transpose(self.base)**self.exp if i is False and p is False: expanded = expand_complex(self) if expanded != self: return transpose(expanded) def _eval_expand_power_exp(self, **hints): """a**(n+m) -> a**n*a**m""" b = self.base e = self.exp if e.is_Add and e.is_commutative: expr = [] for x in e.args: expr.append(Pow(self.base, x)) return Mul(*expr) return Pow(b, e) def _eval_expand_power_base(self, **hints): """(a*b)**n -> a**n * b**n""" force = hints.get('force', False) b, ewas = self.args e = self.exp if b.is_Mul: bargs = b.args if force or e.is_integer: nonneg = bargs other = [] elif ewas.is_Rational or len(bargs) == 2 and bargs[0] is S.NegativeOne: # the Rational exponent was already expanded automatically # if there is a negative Number * foo, foo must be unknown # or else it, too, would have automatically expanded; # sqrt(-Number*foo) -> sqrt(Number)*sqrt(-foo); then # sqrt(-foo) -> unchanged if foo is not positive else # -> I*sqrt(foo) # So...if we have a 2 arg Mul and the first is a Number # that number is -1 and there is nothing more than can # be done without the force=True hint nonneg= [] else: # this is just like what is happening automatically, except # that now we are doing it for an arbitrary exponent for which # no automatic expansion is done def pred(x): if x.is_polar is None: return x.is_nonnegative return x.is_polar sifted = sift(b.args, pred) nonneg = sifted[True] other = sifted[None] neg = sifted[False] # make sure the Number gets pulled out if neg and neg[0].is_Number and neg[0] is not S.NegativeOne: nonneg.append(-neg[0]) neg[0] = S.NegativeOne # leave behind a negative sign oddneg = len(neg) % 2 if oddneg: other.append(S.NegativeOne) # negate all negatives and append to nonneg nonneg += [-n for n in neg] if nonneg: # then there's a new expression to return d = sift(nonneg, lambda x: x.is_commutative is True) c = d[True] nc = d[False] if not e.is_Integer: other.extend(nc) nc = [] elif len(nc) == 1: c.extend(nc) nc = [] else: nc = [Mul._from_args(nc)]*e other = [Pow(Mul(*other), e)] + nc return Mul(*([Pow(b, e) for b in c] + other)) return Pow(b, e) def _eval_expand_multinomial(self, **hints): """(a+b+..) ** n -> a**n + n*a**(n-1)*b + .., n is nonzero integer""" b = self.base e = self.exp if b is None: base = self.base else: base = b if e is None: exp = self.exp else: exp = e if e is not None or b is not None: result = Pow(base, exp) if result.is_Pow: base, exp = result.base, result.exp else: return result else: result = None if exp.is_Rational and exp.p > 0 and base.is_Add: if not exp.is_Integer: n = Integer(exp.p // exp.q) if not n: return Pow(base, exp) else: radical, result = Pow(base, exp - n), [] expanded_base_n = Pow(base, n) if expanded_base_n.is_Pow: expanded_base_n = expanded_base_n._eval_expand_multinomial() for term in Add.make_args(expanded_base_n): result.append(term*radical) return Add(*result) n = int(exp) if base.is_commutative: order_terms, other_terms = [], [] for order in base.args: if order.is_Order: order_terms.append(order) else: other_terms.append(order) if order_terms: # (f(x) + O(x^n))^m -> f(x)^m + m*f(x)^{m-1} *O(x^n) f = Add(*other_terms) if n == 2: return expand_multinomial(f**n, deep=False) + n*f*Add(*order_terms) else: g = expand_multinomial(f**(n - 1), deep=False) return expand_mul(f*g, deep=False) + n*g*Add(*order_terms) if base.is_number: # Efficiently expand expressions of the form (a + b*I)**n # where 'a' and 'b' are real numbers and 'n' is integer. a, b = base.as_real_imag() if a.is_Rational and b.is_Rational: if not a.is_Integer: if not b.is_Integer: k = Pow(a.q * b.q, n) a, b = a.p*b.q, a.q*b.p else: k = Pow(a.q, n) a, b = a.p, a.q*b elif not b.is_Integer: k = Pow(b.q, n) a, b = a*b.q, b.p else: k = 1 a, b, c, d = int(a), int(b), 1, 0 while n: if n & 1: c, d = a*c-b*d, b*c+a*d n -= 1 a, b = a*a-b*b, 2*a*b n //= 2 I = S.ImaginaryUnit if k == 1: return c + I*d else: return Integer(c)/k + I*d/k p = other_terms # (x+y)**3 -> x**3 + 3*x**2*y + 3*x*y**2 + y**3 # in this particular example: # p = [x,y]; n = 3 # so now it's easy to get the correct result -- we get the # coefficients first: from sympy import multinomial_coefficients expansion_dict = multinomial_coefficients(len(p), n) # in our example: {(3, 0): 1, (1, 2): 3, (0, 3): 1, (2, 1): 3} # and now construct the expression. # An elegant way would be to use Poly, but unfortunately it is # slower than the direct method below, so it is commented out: #b = {} #for k in expansion_dict: # b[k] = Integer(expansion_dict[k]) #return Poly(b, *p).as_expr() from sympy.polys.polyutils import basic_from_dict result = basic_from_dict(expansion_dict, *p) return result else: if n == 2: return Add(*[f*g for f in base.args for g in base.args]) else: multi = (base**(n-1))._eval_expand_multinomial() if multi.is_Add: return Add(*[f*g for f in base.args for g in multi.args]) else: return Add(*[f*multi for f in base.args]) elif exp.is_Rational and exp.p < 0 and base.is_Add and abs(exp.p) > exp.q: return 1 / Pow(base, -exp)._eval_expand_multinomial() elif exp.is_Add and base.is_Number: # a + b a b # n --> n n , where n, a, b are Numbers coeff, tail = S.One, S.Zero for term in exp.args: if term.is_Number: coeff *= Pow(base, term) else: tail += term return coeff * Pow(base, tail) else: return result def as_real_imag(self, deep=True, **hints): from sympy.core.symbol import symbols from sympy.polys.polytools import poly if self.exp.is_Integer: exp = self.exp re, im = self.base.as_real_imag(deep=deep) if re.func == C.re or im.func == C.im or not im: return self, S.Zero a, b = symbols('a b', cls=Dummy) 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 with 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**aa*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 = Pow(Pow(re, 2) + Pow(im, 2), S.Half) t = C.atan2(im, re) rp, tp = Pow(r, self.exp), t*self.exp return (rp*C.cos(tp), rp*C.sin(tp)) else: if deep: hints['complex'] = False expanded = self.expand(deep, **hints) if hints.get('ignore') == expanded: return None else: return (C.re(expanded), C.im(expanded)) else: return (C.re(self), C.im(self)) 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 _eval_evalf(self, prec): base, exp = self.as_base_exp() base = base._evalf(prec) if not exp.is_Integer: exp = exp._evalf(prec) if exp < 0 and base.is_number and base.is_real is False: base = base.conjugate() / (base * base.conjugate())._evalf(prec) exp = -exp return Pow(base, exp).expand() return Pow(base, exp) def _eval_is_polynomial(self, syms): if self.exp.has(*syms): return False if self.base.has(*syms): return self.base._eval_is_polynomial(syms) and \ self.exp.is_Integer and \ self.exp >= 0 else: return True def _eval_is_rational(self): p = self.func(*self.as_base_exp()) # in case it's unevaluated if not p.is_Pow: return p.is_rational b, e = p.as_base_exp() if e.is_Rational and b.is_Rational: # we didn't check that e is not an Integer # because Rational**Integer autosimplifies return False if e.is_integer: return b.is_rational def _eval_is_rational_function(self, syms): if self.exp.has(*syms): return False if self.base.has(*syms): return self.base._eval_is_rational_function(syms) and \ self.exp.is_Integer else: return True def as_numer_denom(self): if not self.is_commutative: return self, S.One base, exp = self.as_base_exp() n, d = base.as_numer_denom() # this should be the same as ExpBase.as_numer_denom wrt # exponent handling neg_exp = exp.is_negative int_exp = exp.is_integer if not neg_exp and not exp.is_real: neg_exp = _coeff_isneg(exp) # the denominator cannot be separated from the numerator if # its sign is unknown unless the exponent is an integer, e.g. # sqrt(a/b) != sqrt(a)/sqrt(b) when a=1 and b=-1. But if the # denominator is negative the numerator and denominator can # be negated and the denominator (now positive) separated. if not (d.is_real or int_exp): n = base d = S.One dnonpos = d.is_nonpositive if dnonpos: n, d = -n, -d elif dnonpos is None and not int_exp: n = base d = S.One if neg_exp: n, d = d, n exp = -exp return Pow(n, exp), Pow(d, exp) def matches(self, expr, repl_dict={}): expr = _sympify(expr) b, e = expr.as_base_exp() # special case, pattern = 1 and expr.exp can match to 0 if expr is S.One: d = repl_dict.copy() d = self.exp.matches(S.Zero, d) if d is not None: return d d = repl_dict.copy() d = self.base.matches(b, d) if d is None: return None d = self.exp.xreplace(d).matches(e, d) if d is None: return Expr.matches(self, expr, repl_dict) return d def _eval_nseries(self, x, n, logx): # NOTE! This function is an important part of the gruntz algorithm # for computing limits. It has to return a generalized power series # with coefficients in C(log, log(x)). In more detail: # It has to return an expression # c_0*x**e_0 + c_1*x**e_1 + ... (finitely many terms) # where e_i are numbers (not necessarily integers) and c_i are expression # involving only numbers, the log function, and log(x). from sympy import powsimp, collect, exp, log, O, ceiling b, e = self.args if e.is_Integer: if e > 0: # positive integer powers are easy to expand, e.g.: # sin(x)**4 = (x-x**3/3+...)**4 = ... return expand_multinomial(Pow(b._eval_nseries(x, n=n, logx=logx), e), deep=False) elif e is S.NegativeOne: # this is also easy to expand using the formula: # 1/(1 + x) = 1 - x + x**2 - x**3 ... # so we need to rewrite base to the form "1+x" b = b._eval_nseries(x, n=n, logx=logx) prefactor = b.as_leading_term(x) # express "rest" as: rest = 1 + k*x**l + ... + O(x**n) rest = expand_mul((b - prefactor)/prefactor) if rest == 0: # if prefactor == w**4 + x**2*w**4 + 2*x*w**4, we need to # factor the w**4 out using collect: return 1/collect(prefactor, x) if rest.is_Order: return 1/prefactor + rest/prefactor n2 = rest.getn() if n2 is not None: n = n2 # remove the O - powering this is slow if logx is not None: rest = rest.removeO() k, l = rest.leadterm(x) if l.is_Rational and l > 0: pass elif l.is_number and l > 0: l = l.evalf() else: raise NotImplementedError() terms = [1/prefactor] for m in range(1, ceiling(n/l)): new_term = terms[-1]*(-rest) if new_term.is_Pow: new_term = new_term._eval_expand_multinomial(deep=False) else: new_term = expand_mul(new_term, deep=False) terms.append(new_term) # Append O(...), we know the order. if n2 is None or logx is not None: terms.append(O(x**n)) return powsimp(Add(*terms), deep=True, combine='exp') else: # negative powers are rewritten to the cases above, for example: # sin(x)**(-4) = 1/( sin(x)**4) = ... # and expand the denominator: denominator = (b**(-e))._eval_nseries(x, n=n, logx=logx) if 1/denominator == self: return self # now we have a type 1/f(x), that we know how to expand return (1/denominator)._eval_nseries(x, n=n, logx=logx) if e.has(Symbol): return exp(e*log(b))._eval_nseries(x, n=n, logx=logx) # see if the base is as simple as possible bx = b while bx.is_Pow and bx.exp.is_Rational: bx = bx.base if bx == x: return self # work for b(x)**e where e is not an Integer and does not contain x # and hopefully has no other symbols def e2int(e): """return the integer value (if possible) of e and a flag indicating whether it is bounded or not.""" n = e.limit(x, 0) unbounded = n.is_unbounded if not unbounded: # XXX was int or floor intended? int used to behave like floor # so int(-Rational(1, 2)) returned -1 rather than int's 0 try: n = int(n) except TypeError: #well, the n is something more complicated (like 1+log(2)) try: n = int(n.evalf()) + 1 # XXX why is 1 being added? except TypeError: pass # hope that base allows this to be resolved n = _sympify(n) return n, unbounded order = O(x**n, x) ei, unbounded = e2int(e) b0 = b.limit(x, 0) if unbounded and (b0 is S.One or b0.has(Symbol)): # XXX what order if b0 is S.One: resid = (b - 1) if resid.is_positive: return S.Infinity elif resid.is_negative: return S.Zero raise ValueError('cannot determine sign of %s' % resid) return b0**ei if (b0 is S.Zero or b0.is_unbounded): if unbounded is not False: return b0**e # XXX what order if not ei.is_number: # if not, how will we proceed? raise ValueError('expecting numerical exponent but got %s' % ei) nuse = n - ei bs = b._eval_nseries(x, n=nuse, logx=logx) terms = bs.removeO() if terms.is_Add: bs = terms lt = terms.as_leading_term(x) # bs -> lt + rest -> lt*(1 + (bs/lt - 1)) return ((Pow(lt, e)* Pow((bs/lt).expand(), e). nseries(x, n=nuse, logx=logx)).expand() + order) rv = bs**e if terms != bs: rv += order return rv # either b0 is bounded but neither 1 nor 0 or e is unbounded # b -> b0 + (b-b0) -> b0 * (1 + (b/b0-1)) o2 = order*(b0**-e) z = (b/b0 - 1) o = O(z, x) #r = self._compute_oseries3(z, o2, self.taylor_term) if o is S.Zero or o2 is S.Zero: unbounded = True else: if o.expr.is_number: e2 = log(o2.expr*x)/log(x) else: e2 = log(o2.expr)/log(o.expr) n, unbounded = e2int(e2) if unbounded: # requested accuracy gives infinite series, # order is probably non-polynomial e.g. O(exp(-1/x), x). r = 1 + z else: l = [] g = None for i in range(n + 2): g = self.taylor_term(i, z, g) g = g.nseries(x, n=n, logx=logx) l.append(g) r = Add(*l) return r*b0**e + order def _eval_as_leading_term(self, x): if not self.exp.has(x): return Pow(self.base.as_leading_term(x), self.exp) return C.exp(self.exp * C.log(self.base)).as_leading_term(x) @cacheit def taylor_term(self, n, x, *previous_terms): # of (1+x)**e if n<0: return S.Zero x = _sympify(x) return C.binomial(self.exp, n) * Pow(x, n) def _sage_(self): return self.args[0]._sage_()**self.args[1]._sage_()
[docs] def as_content_primitive(self, radical=False): """Return the tuple (R, self/R) where R is the positive Rational extracted from self. Examples ======== >>> from sympy import sqrt >>> sqrt(4 + 4*sqrt(2)).as_content_primitive() (2, sqrt(1 + sqrt(2))) >>> sqrt(3 + 3*sqrt(2)).as_content_primitive() (1, sqrt(3)*sqrt(1 + sqrt(2))) >>> from sympy import expand_power_base, powsimp, Mul >>> from sympy.abc import x, y >>> ((2*x + 2)**2).as_content_primitive() (4, (x + 1)**2) >>> (4**((1 + y)/2)).as_content_primitive() (2, 4**(y/2)) >>> (3**((1 + y)/2)).as_content_primitive() (1, 3**((y + 1)/2)) >>> (3**((5 + y)/2)).as_content_primitive() (9, 3**((y + 1)/2)) >>> eq = 3**(2 + 2*x) >>> powsimp(eq) == eq True >>> eq.as_content_primitive() (9, 3**(2*x)) >>> powsimp(Mul(*_)) 9**(x + 1) >>> eq = (2 + 2*x)**y >>> s = expand_power_base(eq); s.is_Mul, s (False, (2*x + 2)**y) >>> eq.as_content_primitive() (1, (2*(x + 1))**y) >>> s = expand_power_base(_[1]); s.is_Mul, s (True, 2**y*(x + 1)**y) See docstring of Expr.as_content_primitive for more examples. """ b, e = self.as_base_exp() b = _keep_coeff(*b.as_content_primitive(radical=radical)) ce, pe = e.as_content_primitive(radical=radical) if b.is_Rational: #e #= ce*pe #= ce*(h + t) #= ce*h + ce*t #=> self #= b**(ce*h)*b**(ce*t) #= b**(cehp/cehq)*b**(ce*t) #= b**(iceh+r/cehq)*b**(ce*t) #= b**(iceh)*b**(r/cehq)*b**(ce*t) #= b**(iceh)*b**(ce*t + r/cehq) h, t = pe.as_coeff_Add() if h.is_Rational: ceh = ce*h c = Pow(b, ceh) r = S.Zero if not c.is_Rational: iceh, r = divmod(ceh.p, ceh.q) c = Pow(b, iceh) return c, Pow(b, _keep_coeff(ce, t + r/ce/ceh.q)) e = _keep_coeff(ce, pe) # b**e = (h*t)**e = h**e*t**e = c*m*t**e if e.is_Rational and b.is_Mul: h, t = b.as_content_primitive(radical=radical) # h is positive c, m = Pow(h, e).as_coeff_Mul() # so c is positive m, me = m.as_base_exp() if m is S.One or me == e: # probably always true # return the following, not return c, m*Pow(t, e) # which would change Pow into Mul; we let sympy # decide what to do by using the unevaluated Mul, e.g # should it stay as sqrt(2 + 2*sqrt(5)) or become # sqrt(2)*sqrt(1 + sqrt(5)) return c, Pow(_keep_coeff(m, t), e) return S.One, Pow(b, e)
def is_constant(self, *wrt, **flags): if flags.get('simplify', True): self = self.simplify() b, e = self.as_base_exp() bz = b.equals(0) if bz: # recalculate with assumptions in case it's unevaluated new = b**e if new != self: return new.is_constant() econ = e.is_constant(*wrt) bcon = b.is_constant(*wrt) if bcon: if econ: return True bz = b.equals(0) if bz is False: return False elif bcon is None: return None return e.equals(0)
from .add import Add from .numbers import Integer from .mul import Mul, _keep_coeff from .symbol import Symbol, Dummy