123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004 |
- from __future__ import annotations
- from typing import Callable
- from math import log as _log, sqrt as _sqrt
- from itertools import product
- from .sympify import _sympify
- from .cache import cacheit
- from .singleton import S
- from .expr import Expr
- from .evalf import PrecisionExhausted
- from .function import (expand_complex, expand_multinomial,
- expand_mul, _mexpand, PoleError)
- from .logic import fuzzy_bool, fuzzy_not, fuzzy_and, fuzzy_or
- from .parameters import global_parameters
- from .relational import is_gt, is_lt
- from .kind import NumberKind, UndefinedKind
- from sympy.external.gmpy import HAS_GMPY, gmpy
- from sympy.utilities.iterables import sift
- from sympy.utilities.exceptions import sympy_deprecation_warning
- from sympy.utilities.misc import as_int
- from sympy.multipledispatch import Dispatcher
- from mpmath.libmp import sqrtrem as mpmath_sqrtrem
- def isqrt(n):
- """Return the largest integer less than or equal to sqrt(n)."""
- if n < 0:
- raise ValueError("n must be nonnegative")
- n = int(n)
- # Fast path: with IEEE 754 binary64 floats and a correctly-rounded
- # math.sqrt, int(math.sqrt(n)) works for any integer n satisfying 0 <= n <
- # 4503599761588224 = 2**52 + 2**27. But Python doesn't guarantee either
- # IEEE 754 format floats *or* correct rounding of math.sqrt, so check the
- # answer and fall back to the slow method if necessary.
- if n < 4503599761588224:
- s = int(_sqrt(n))
- if 0 <= n - s*s <= 2*s:
- return s
- return integer_nthroot(n, 2)[0]
- 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).
- Examples
- ========
- >>> from sympy import integer_nthroot
- >>> integer_nthroot(16, 2)
- (4, True)
- >>> integer_nthroot(26, 2)
- (5, False)
- To simply determine if a number is a perfect square, the is_square
- function should be used:
- >>> from sympy.ntheory.primetest import is_square
- >>> is_square(26)
- False
- See Also
- ========
- sympy.ntheory.primetest.is_square
- integer_log
- """
- y, n = as_int(y), as_int(n)
- if y < 0:
- raise ValueError("y must be nonnegative")
- if n < 1:
- raise ValueError("n must be positive")
- if HAS_GMPY and n < 2**63:
- # Currently it works only for n < 2**63, else it produces TypeError
- # sympy issue: https://github.com/sympy/sympy/issues/18374
- # gmpy2 issue: https://github.com/aleaxit/gmpy/issues/257
- if HAS_GMPY >= 2:
- x, t = gmpy.iroot(y, n)
- else:
- x, t = gmpy.root(y, n)
- return as_int(x), bool(t)
- return _integer_nthroot_python(y, n)
- def _integer_nthroot_python(y, n):
- if y in (0, 1):
- return y, True
- if n == 1:
- return y, True
- if n == 2:
- x, rem = mpmath_sqrtrem(y)
- return int(x), not rem
- if n >= y.bit_length():
- 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)
- if guess > 2**50:
- # Newton iteration
- xprev, x = -1, guess
- while 1:
- t = x**(n - 1)
- xprev, x = x, ((n - 1)*x + y//t)//n
- 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 int(x), t == y # int converts long to int if possible
- def integer_log(y, x):
- r"""
- Returns ``(e, bool)`` where e is the largest nonnegative integer
- such that :math:`|y| \geq |x^e|` and ``bool`` is True if $y = x^e$.
- Examples
- ========
- >>> from sympy import integer_log
- >>> integer_log(125, 5)
- (3, True)
- >>> integer_log(17, 9)
- (1, False)
- >>> integer_log(4, -2)
- (2, True)
- >>> integer_log(-125,-5)
- (3, True)
- See Also
- ========
- integer_nthroot
- sympy.ntheory.primetest.is_square
- sympy.ntheory.factor_.multiplicity
- sympy.ntheory.factor_.perfect_power
- """
- if x == 1:
- raise ValueError('x cannot take value as 1')
- if y == 0:
- raise ValueError('y cannot take value as 0')
- if x in (-2, 2):
- x = int(x)
- y = as_int(y)
- e = y.bit_length() - 1
- return e, x**e == y
- if x < 0:
- n, b = integer_log(y if y > 0 else -y, -x)
- return n, b and bool(n % 2 if y < 0 else not n % 2)
- x = as_int(x)
- y = as_int(y)
- r = e = 0
- while y >= x:
- d = x
- m = 1
- while y >= d:
- y, rem = divmod(y, d)
- r = r or rem
- e += m
- if y > d:
- d *= d
- m *= 2
- return e, r == 0 and y == 1
- class Pow(Expr):
- """
- Defines the expression x**y as "x raised to a power y"
- .. deprecated:: 1.7
- Using arguments that aren't subclasses of :class:`~.Expr` in core
- operators (:class:`~.Mul`, :class:`~.Add`, and :class:`~.Pow`) is
- deprecated. See :ref:`non-expr-args-deprecated` for details.
- Singleton definitions involving (0, 1, -1, oo, -oo, I, -I):
- +--------------+---------+-----------------------------------------------+
- | expr | value | reason |
- +==============+=========+===============================================+
- | z**0 | 1 | Although arguments over 0**0 exist, see [2]. |
- +--------------+---------+-----------------------------------------------+
- | z**1 | z | |
- +--------------+---------+-----------------------------------------------+
- | (-oo)**(-1) | 0 | |
- +--------------+---------+-----------------------------------------------+
- | (-1)**-1 | -1 | |
- +--------------+---------+-----------------------------------------------+
- | S.Zero**-1 | zoo | This is not strictly true, as 0**-1 may be |
- | | | undefined, but is convenient in some contexts |
- | | | where the base is assumed to be positive. |
- +--------------+---------+-----------------------------------------------+
- | 1**-1 | 1 | |
- +--------------+---------+-----------------------------------------------+
- | oo**-1 | 0 | |
- +--------------+---------+-----------------------------------------------+
- | 0**oo | 0 | Because for all complex numbers z near |
- | | | 0, z**oo -> 0. |
- +--------------+---------+-----------------------------------------------+
- | 0**-oo | zoo | This is not strictly true, as 0**oo may be |
- | | | oscillating between positive and negative |
- | | | values or rotating in the complex plane. |
- | | | It is convenient, however, when the base |
- | | | is positive. |
- +--------------+---------+-----------------------------------------------+
- | 1**oo | nan | Because there are various cases where |
- | 1**-oo | | lim(x(t),t)=1, lim(y(t),t)=oo (or -oo), |
- | | | but lim( x(t)**y(t), t) != 1. See [3]. |
- +--------------+---------+-----------------------------------------------+
- | b**zoo | nan | Because b**z has no limit as z -> zoo |
- +--------------+---------+-----------------------------------------------+
- | (-1)**oo | nan | Because of oscillations in the limit. |
- | (-1)**(-oo) | | |
- +--------------+---------+-----------------------------------------------+
- | oo**oo | oo | |
- +--------------+---------+-----------------------------------------------+
- | oo**-oo | 0 | |
- +--------------+---------+-----------------------------------------------+
- | (-oo)**oo | nan | |
- | (-oo)**-oo | | |
- +--------------+---------+-----------------------------------------------+
- | oo**I | nan | oo**e could probably be best thought of as |
- | (-oo)**I | | the limit of x**e for real x as x tends to |
- | | | oo. If e is I, then the limit does not exist |
- | | | and nan is used to indicate that. |
- +--------------+---------+-----------------------------------------------+
- | oo**(1+I) | zoo | If the real part of e is positive, then the |
- | (-oo)**(1+I) | | limit of abs(x**e) is oo. So the limit value |
- | | | is zoo. |
- +--------------+---------+-----------------------------------------------+
- | oo**(-1+I) | 0 | If the real part of e is negative, then the |
- | -oo**(-1+I) | | limit is 0. |
- +--------------+---------+-----------------------------------------------+
- Because symbolic computations are more flexible than floating point
- calculations and we prefer to never return an incorrect answer,
- we choose not to conform to all IEEE 754 conventions. This helps
- us avoid extra test-case code in the calculation of limits.
- See Also
- ========
- sympy.core.numbers.Infinity
- sympy.core.numbers.NegativeInfinity
- sympy.core.numbers.NaN
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Exponentiation
- .. [2] https://en.wikipedia.org/wiki/Zero_to_the_power_of_zero
- .. [3] https://en.wikipedia.org/wiki/Indeterminate_forms
- """
- is_Pow = True
- __slots__ = ('is_commutative',)
- args: tuple[Expr, Expr]
- _args: tuple[Expr, Expr]
- @cacheit
- def __new__(cls, b, e, evaluate=None):
- if evaluate is None:
- evaluate = global_parameters.evaluate
- b = _sympify(b)
- e = _sympify(e)
- # XXX: This can be removed when non-Expr args are disallowed rather
- # than deprecated.
- from .relational import Relational
- if isinstance(b, Relational) or isinstance(e, Relational):
- raise TypeError('Relational cannot be used in Pow')
- # XXX: This should raise TypeError once deprecation period is over:
- for arg in [b, e]:
- if not isinstance(arg, Expr):
- sympy_deprecation_warning(
- f"""
- Using non-Expr arguments in Pow is deprecated (in this case, one of the
- arguments is of type {type(arg).__name__!r}).
- If you really did intend to construct a power with this base, use the **
- operator instead.""",
- deprecated_since_version="1.7",
- active_deprecations_target="non-expr-args-deprecated",
- stacklevel=4,
- )
- if evaluate:
- if e is S.ComplexInfinity:
- return S.NaN
- if e is S.Infinity:
- if is_gt(b, S.One):
- return S.Infinity
- if is_gt(b, S.NegativeOne) and is_lt(b, S.One):
- return S.Zero
- if is_lt(b, S.NegativeOne):
- if b.is_finite:
- return S.ComplexInfinity
- if b.is_finite is False:
- return S.NaN
- if e is S.Zero:
- return S.One
- elif e is S.One:
- return b
- elif e == -1 and not b:
- return S.ComplexInfinity
- elif e.__class__.__name__ == "AccumulationBounds":
- if b == S.Exp1:
- from sympy.calculus.accumulationbounds import AccumBounds
- return AccumBounds(Pow(b, e.min), Pow(b, e.max))
- # autosimplification if base is a number and exp odd/even
- # if base is Number then the base will end up positive; we
- # do not do this with arbitrary expressions since symbolic
- # cancellation might occur as in (x - 1)/(1 - x) -> -1. If
- # we returned Piecewise((-1, Ne(x, 1))) for such cases then
- # we could do this...but we don't
- elif (e.is_Symbol and e.is_integer or e.is_Integer
- ) and (b.is_number and b.is_Mul or b.is_Number
- ) and b.could_extract_minus_sign():
- if e.is_even:
- b = -b
- elif e.is_odd:
- return -Pow(-b, e)
- if S.NaN in (b, e): # XXX S.NaN**x -> S.NaN under assumption that x != 0
- return S.NaN
- elif b is S.One:
- if abs(e).is_infinite:
- return S.NaN
- return S.One
- else:
- # recognize base as E
- from sympy.functions.elementary.exponential import exp_polar
- if not e.is_Atom and b is not S.Exp1 and not isinstance(b, exp_polar):
- from .exprtools import factor_terms
- from sympy.functions.elementary.exponential import log
- from sympy.simplify.radsimp import fraction
- c, ex = factor_terms(e, sign=False).as_coeff_Mul()
- num, den = fraction(ex)
- if isinstance(den, log) and den.args[0] == b:
- return S.Exp1**(c*num)
- elif den.is_Add:
- from sympy.functions.elementary.complexes import sign, im
- s = sign(im(b))
- if s.is_Number and s and den == \
- log(-factor_terms(b, sign=False)) + s*S.ImaginaryUnit*S.Pi:
- return S.Exp1**(c*num)
- obj = b._eval_power(e)
- if obj is not None:
- return obj
- obj = Expr.__new__(cls, b, e)
- obj = cls._exec_constructor_postprocessors(obj)
- if not isinstance(obj, Pow):
- return obj
- obj.is_commutative = (b.is_commutative and e.is_commutative)
- return obj
- def inverse(self, argindex=1):
- if self.base == S.Exp1:
- from sympy.functions.elementary.exponential import log
- return log
- return None
- @property
- def base(self) -> Expr:
- return self._args[0]
- @property
- def exp(self) -> Expr:
- return self._args[1]
- @property
- def kind(self):
- if self.exp.kind is NumberKind:
- return self.base.kind
- else:
- return UndefinedKind
- @classmethod
- def class_key(cls):
- return 3, 2, cls.__name__
- def _eval_refine(self, assumptions):
- from sympy.assumptions.ask import ask, Q
- b, e = self.as_base_exp()
- if ask(Q.integer(e), assumptions) and b.could_extract_minus_sign():
- if ask(Q.even(e), assumptions):
- return Pow(-b, e)
- elif ask(Q.odd(e), assumptions):
- return -Pow(-b, e)
- def _eval_power(self, other):
- b, e = self.as_base_exp()
- if b is S.NaN:
- return (b**e)**other # let __new__ handle it
- s = None
- if other.is_integer:
- s = 1
- elif b.is_polar: # e.g. exp_polar, besselj, var('p', polar=True)...
- s = 1
- elif e.is_extended_real is not None:
- from sympy.functions.elementary.complexes import arg, im, re, sign
- from sympy.functions.elementary.exponential import exp, log
- from sympy.functions.elementary.integers import floor
- # helper functions ===========================
- def _half(e):
- """Return True if the exponent has a literal 2 as the
- denominator, else None."""
- if getattr(e, 'q', None) == 2:
- return True
- n, d = e.as_numer_denom()
- if n.is_integer and d == 2:
- return True
- def _n2(e):
- """Return ``e`` evaluated to a Number with 2 significant
- digits, else None."""
- try:
- rv = e.evalf(2, strict=True)
- if rv.is_Number:
- return rv
- except PrecisionExhausted:
- pass
- # ===================================================
- if e.is_extended_real:
- # we need _half(other) with constant floor or
- # floor(S.Half - e*arg(b)/2/pi) == 0
- # handle -1 as special case
- if e == -1:
- # floor arg. is 1/2 + arg(b)/2/pi
- if _half(other):
- if b.is_negative is True:
- return S.NegativeOne**other*Pow(-b, e*other)
- elif b.is_negative is False: # XXX ok if im(b) != 0?
- return Pow(b, -other)
- elif e.is_even:
- if b.is_extended_real:
- b = abs(b)
- if b.is_imaginary:
- b = abs(im(b))*S.ImaginaryUnit
- if (abs(e) < 1) == True or e == 1:
- s = 1 # floor = 0
- elif b.is_extended_nonnegative:
- s = 1 # floor = 0
- elif re(b).is_extended_nonnegative and (abs(e) < 2) == True:
- s = 1 # floor = 0
- elif _half(other):
- s = exp(2*S.Pi*S.ImaginaryUnit*other*floor(
- S.Half - e*arg(b)/(2*S.Pi)))
- if s.is_extended_real and _n2(sign(s) - s) == 0:
- s = sign(s)
- else:
- s = None
- else:
- # e.is_extended_real is False requires:
- # _half(other) with constant floor or
- # floor(S.Half - im(e*log(b))/2/pi) == 0
- try:
- s = exp(2*S.ImaginaryUnit*S.Pi*other*
- floor(S.Half - im(e*log(b))/2/S.Pi))
- # be careful to test that s is -1 or 1 b/c sign(I) == I:
- # so check that s is real
- if s.is_extended_real and _n2(sign(s) - s) == 0:
- s = sign(s)
- else:
- s = None
- except PrecisionExhausted:
- s = None
- if s is not None:
- return s*Pow(b, e*other)
- def _eval_Mod(self, q):
- r"""A dispatched function to compute `b^e \bmod q`, dispatched
- by ``Mod``.
- Notes
- =====
- Algorithms:
- 1. For unevaluated integer power, use built-in ``pow`` function
- with 3 arguments, if powers are not too large wrt base.
- 2. For very large powers, use totient reduction if $e \ge \log(m)$.
- Bound on m, is for safe factorization memory wise i.e. $m^{1/4}$.
- For pollard-rho to be faster than built-in pow $\log(e) > m^{1/4}$
- check is added.
- 3. For any unevaluated power found in `b` or `e`, the step 2
- will be recursed down to the base and the exponent
- such that the $b \bmod q$ becomes the new base and
- $\phi(q) + e \bmod \phi(q)$ becomes the new exponent, and then
- the computation for the reduced expression can be done.
- """
- base, exp = self.base, self.exp
- if exp.is_integer and exp.is_positive:
- if q.is_integer and base % q == 0:
- return S.Zero
- from sympy.ntheory.factor_ import totient
- if base.is_Integer and exp.is_Integer and q.is_Integer:
- b, e, m = int(base), int(exp), int(q)
- mb = m.bit_length()
- if mb <= 80 and e >= mb and e.bit_length()**4 >= m:
- phi = int(totient(m))
- return Integer(pow(b, phi + e%phi, m))
- return Integer(pow(b, e, m))
- from .mod import Mod
- if isinstance(base, Pow) and base.is_integer and base.is_number:
- base = Mod(base, q)
- return Mod(Pow(base, exp, evaluate=False), q)
- if isinstance(exp, Pow) and exp.is_integer and exp.is_number:
- bit_length = int(q).bit_length()
- # XXX Mod-Pow actually attempts to do a hanging evaluation
- # if this dispatched function returns None.
- # May need some fixes in the dispatcher itself.
- if bit_length <= 80:
- phi = totient(q)
- exp = phi + Mod(exp, phi)
- return Mod(Pow(base, exp, evaluate=False), q)
- def _eval_is_even(self):
- if self.exp.is_integer and self.exp.is_positive:
- return self.base.is_even
- def _eval_is_negative(self):
- ext_neg = Pow._eval_is_extended_negative(self)
- if ext_neg is True:
- return self.is_finite
- return ext_neg
- def _eval_is_extended_positive(self):
- if self.base == self.exp:
- if self.base.is_extended_nonnegative:
- return True
- elif self.base.is_positive:
- if self.exp.is_real:
- return True
- elif self.base.is_extended_negative:
- if self.exp.is_even:
- return True
- if self.exp.is_odd:
- return False
- elif self.base.is_zero:
- if self.exp.is_extended_real:
- return self.exp.is_zero
- elif self.base.is_extended_nonpositive:
- if self.exp.is_odd:
- return False
- elif self.base.is_imaginary:
- if self.exp.is_integer:
- m = self.exp % 4
- if m.is_zero:
- return True
- if m.is_integer and m.is_zero is False:
- return False
- if self.exp.is_imaginary:
- from sympy.functions.elementary.exponential import log
- return log(self.base).is_imaginary
- def _eval_is_extended_negative(self):
- if self.exp is S.Half:
- if self.base.is_complex or self.base.is_extended_real:
- return False
- if self.base.is_extended_negative:
- if self.exp.is_odd and self.base.is_finite:
- return True
- if self.exp.is_even:
- return False
- elif self.base.is_extended_positive:
- if self.exp.is_extended_real:
- return False
- elif self.base.is_zero:
- if self.exp.is_extended_real:
- return False
- elif self.base.is_extended_nonnegative:
- if self.exp.is_extended_nonnegative:
- return False
- elif self.base.is_extended_nonpositive:
- if self.exp.is_even:
- return False
- elif self.base.is_extended_real:
- if self.exp.is_even:
- return False
- def _eval_is_zero(self):
- if self.base.is_zero:
- if self.exp.is_extended_positive:
- return True
- elif self.exp.is_extended_nonpositive:
- return False
- elif self.base == S.Exp1:
- return self.exp is S.NegativeInfinity
- elif self.base.is_zero is False:
- if self.base.is_finite and self.exp.is_finite:
- return False
- elif self.exp.is_negative:
- return self.base.is_infinite
- elif self.exp.is_nonnegative:
- return False
- elif self.exp.is_infinite and self.exp.is_extended_real:
- if (1 - abs(self.base)).is_extended_positive:
- return self.exp.is_extended_positive
- elif (1 - abs(self.base)).is_extended_negative:
- return self.exp.is_extended_negative
- elif self.base.is_finite and self.exp.is_negative:
- # when self.base.is_zero is None
- return False
- def _eval_is_integer(self):
- b, e = self.args
- if b.is_rational:
- if b.is_integer is False and e.is_positive:
- return False # rat**nonneg
- if b.is_integer and e.is_integer:
- if b is S.NegativeOne:
- return True
- if e.is_nonnegative or e.is_positive:
- return True
- if b.is_integer and e.is_negative and (e.is_finite or e.is_integer):
- if fuzzy_not((b - 1).is_zero) and fuzzy_not((b + 1).is_zero):
- return False
- if b.is_Number and e.is_Number:
- check = self.func(*self.args)
- return check.is_Integer
- if e.is_negative and b.is_positive and (b - 1).is_positive:
- return False
- if e.is_negative and b.is_negative and (b + 1).is_negative:
- return False
- def _eval_is_extended_real(self):
- if self.base is S.Exp1:
- if self.exp.is_extended_real:
- return True
- elif self.exp.is_imaginary:
- return (2*S.ImaginaryUnit*self.exp/S.Pi).is_even
- from sympy.functions.elementary.exponential import log, exp
- real_b = self.base.is_extended_real
- if real_b is None:
- if self.base.func == exp and self.base.exp.is_imaginary:
- return self.exp.is_imaginary
- if self.base.func == Pow and self.base.base is S.Exp1 and self.base.exp.is_imaginary:
- return self.exp.is_imaginary
- return
- real_e = self.exp.is_extended_real
- if real_e is None:
- return
- if real_b and real_e:
- if self.base.is_extended_positive:
- return True
- elif self.base.is_extended_nonnegative and self.exp.is_extended_nonnegative:
- return True
- elif self.exp.is_integer and self.base.is_extended_nonzero:
- return True
- elif self.exp.is_integer and self.exp.is_nonnegative:
- return True
- elif self.base.is_extended_negative:
- if self.exp.is_Rational:
- return False
- if real_e and self.exp.is_extended_negative and self.base.is_zero is False:
- return Pow(self.base, -self.exp).is_extended_real
- 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 im_e and log(self.base).is_imaginary:
- return True
- elif self.exp.is_Add:
- c, a = self.exp.as_coeff_Add()
- if c and c.is_Integer:
- return Mul(
- self.base**c, self.base**a, evaluate=False).is_extended_real
- elif self.base in (-S.ImaginaryUnit, S.ImaginaryUnit):
- if (self.exp/2).is_integer is False:
- return False
- if real_b and im_e:
- if self.base is S.NegativeOne:
- return True
- c = self.exp.coeff(S.ImaginaryUnit)
- if c:
- if self.base.is_rational and c.is_rational:
- if self.base.is_nonzero and (self.base - 1).is_nonzero and c.is_nonzero:
- return False
- ok = (c*log(self.base)/S.Pi).is_integer
- if ok is not None:
- return ok
- if real_b is False and real_e: # we already know it's not imag
- from sympy.functions.elementary.complexes import arg
- i = arg(self.base)*self.exp/S.Pi
- if i.is_complex: # finite
- return i.is_integer
- def _eval_is_complex(self):
- if self.base == S.Exp1:
- return fuzzy_or([self.exp.is_complex, self.exp.is_extended_negative])
- if all(a.is_complex for a in self.args) and self._eval_is_finite():
- return True
- def _eval_is_imaginary(self):
- if self.base.is_commutative is False:
- return False
- if self.base.is_imaginary:
- if self.exp.is_integer:
- odd = self.exp.is_odd
- if odd is not None:
- return odd
- return
- if self.base == S.Exp1:
- f = 2 * self.exp / (S.Pi*S.ImaginaryUnit)
- # exp(pi*integer) = 1 or -1, so not imaginary
- if f.is_even:
- return False
- # exp(pi*integer + pi/2) = I or -I, so it is imaginary
- if f.is_odd:
- return True
- return None
- if self.exp.is_imaginary:
- from sympy.functions.elementary.exponential import log
- imlog = log(self.base).is_imaginary
- if imlog is not None:
- return False # I**i -> real; (2*I)**i -> complex ==> not imaginary
- if self.base.is_extended_real and self.exp.is_extended_real:
- if self.base.is_positive:
- return False
- else:
- rat = self.exp.is_rational
- if not rat:
- return rat
- if self.exp.is_integer:
- return False
- else:
- half = (2*self.exp).is_integer
- if half:
- return self.base.is_negative
- return half
- if self.base.is_extended_real is False: # we already know it's not imag
- from sympy.functions.elementary.complexes import arg
- i = arg(self.base)*self.exp/S.Pi
- isodd = (2*i).is_odd
- if isodd is not None:
- return isodd
- 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
- elif self.base is S.NegativeOne:
- return True
- def _eval_is_finite(self):
- if self.exp.is_negative:
- if self.base.is_zero:
- return False
- if self.base.is_infinite or self.base.is_nonzero:
- return True
- c1 = self.base.is_finite
- if c1 is None:
- return
- c2 = self.exp.is_finite
- if c2 is None:
- return
- if c1 and c2:
- if self.exp.is_nonnegative or fuzzy_not(self.base.is_zero):
- return True
- def _eval_is_prime(self):
- '''
- An integer raised to the n(>=2)-th power cannot be a prime.
- '''
- if self.base.is_integer and self.exp.is_integer and (self.exp - 1).is_positive:
- return False
- def _eval_is_composite(self):
- """
- A power is composite if both base and exponent are greater than 1
- """
- if (self.base.is_integer and self.exp.is_integer and
- ((self.base - 1).is_positive and (self.exp - 1).is_positive or
- (self.base + 1).is_negative and self.exp.is_positive and self.exp.is_even)):
- return True
- def _eval_is_polar(self):
- return self.base.is_polar
- def _eval_subs(self, old, new):
- from sympy.calculus.accumulationbounds import AccumBounds
- if isinstance(self.exp, AccumBounds):
- b = self.base.subs(old, new)
- e = self.exp.subs(old, new)
- if isinstance(e, AccumBounds):
- return e.__rpow__(b)
- return self.func(b, e)
- from sympy.functions.elementary.exponential import exp, log
- def _check(ct1, ct2, old):
- """Return (bool, pow, remainder_pow) where, if bool is True, then the
- exponent of Pow `old` will combine with `pow` so the substitution
- is valid, otherwise bool will be False.
- For noncommutative objects, `pow` will be an integer, and a factor
- `Pow(old.base, remainder_pow)` needs to be included. If there is
- no such factor, None is returned. For commutative objects,
- remainder_pow is always None.
- cti are the coefficient and terms of an exponent of self or old
- In this _eval_subs routine a change like (b**(2*x)).subs(b**x, y)
- will give y**2 since (b**x)**2 == b**(2*x); if that equality does
- not hold then the substitution should not occur so `bool` will be
- False.
- """
- coeff1, terms1 = ct1
- coeff2, terms2 = ct2
- if terms1 == terms2:
- if old.is_commutative:
- # Allow fractional powers for commutative objects
- pow = coeff1/coeff2
- try:
- as_int(pow, strict=False)
- combines = True
- except ValueError:
- b, e = old.as_base_exp()
- # These conditions ensure that (b**e)**f == b**(e*f) for any f
- combines = b.is_positive and e.is_real or b.is_nonnegative and e.is_nonnegative
- return combines, pow, None
- else:
- # With noncommutative symbols, substitute only integer powers
- if not isinstance(terms1, tuple):
- terms1 = (terms1,)
- if not all(term.is_integer for term in terms1):
- return False, None, None
- try:
- # Round pow toward zero
- pow, remainder = divmod(as_int(coeff1), as_int(coeff2))
- if pow < 0 and remainder != 0:
- pow += 1
- remainder -= as_int(coeff2)
- if remainder == 0:
- remainder_pow = None
- else:
- remainder_pow = Mul(remainder, *terms1)
- return True, pow, remainder_pow
- except ValueError:
- # Can't substitute
- pass
- return False, None, None
- if old == self.base or (old == exp and self.base == S.Exp1):
- if new.is_Function and isinstance(new, Callable):
- return new(self.exp._subs(old, new))
- else:
- return new**self.exp._subs(old, new)
- # issue 10829: (4**x - 3*y + 2).subs(2**x, y) -> y**2 - 3*y + 2
- if isinstance(old, self.func) and self.exp == old.exp:
- l = log(self.base, old.base)
- if l.is_Number:
- return Pow(new, l)
- if isinstance(old, self.func) and self.base == old.base:
- if self.exp.is_Add is False:
- ct1 = self.exp.as_independent(Symbol, as_Add=False)
- ct2 = old.exp.as_independent(Symbol, as_Add=False)
- ok, pow, remainder_pow = _check(ct1, ct2, old)
- if ok:
- # issue 5180: (x**(6*y)).subs(x**(3*y),z)->z**2
- result = self.func(new, pow)
- if remainder_pow is not None:
- result = Mul(result, Pow(old.base, remainder_pow))
- return result
- else: # b**(6*x + a).subs(b**(3*x), y) -> y**2 * b**a
- # exp(exp(x) + exp(x**2)).subs(exp(exp(x)), w) -> w * exp(exp(x**2))
- oarg = old.exp
- new_l = []
- o_al = []
- ct2 = oarg.as_coeff_mul()
- for a in self.exp.args:
- newa = a._subs(old, new)
- ct1 = newa.as_coeff_mul()
- ok, pow, remainder_pow = _check(ct1, ct2, old)
- if ok:
- new_l.append(new**pow)
- if remainder_pow is not None:
- o_al.append(remainder_pow)
- continue
- elif not old.is_commutative and not newa.is_integer:
- # If any term in the exponent is non-integer,
- # we do not do any substitutions in the noncommutative case
- return
- o_al.append(newa)
- if new_l:
- expo = Add(*o_al)
- new_l.append(Pow(self.base, expo, evaluate=False) if expo != 1 else self.base)
- return Mul(*new_l)
- if (isinstance(old, exp) or (old.is_Pow and old.base is S.Exp1)) and self.exp.is_extended_real and self.base.is_positive:
- ct1 = old.exp.as_independent(Symbol, as_Add=False)
- ct2 = (self.exp*log(self.base)).as_independent(
- Symbol, as_Add=False)
- ok, pow, remainder_pow = _check(ct1, ct2, old)
- if ok:
- result = self.func(new, pow) # (2**x).subs(exp(x*log(2)), z) -> z
- if remainder_pow is not None:
- result = Mul(result, Pow(old.base, remainder_pow))
- return result
- def as_base_exp(self):
- """Return base and exp of self.
- Explanation
- ===========
- If base a Rational less than 1, then return 1/Rational, -exp.
- If this extra processing is not needed, the base and exp
- properties will give the raw arguments.
- Examples
- ========
- >>> from sympy import Pow, S
- >>> p = Pow(S.Half, 2, evaluate=False)
- >>> p.as_base_exp()
- (2, -2)
- >>> p.args
- (1/2, 2)
- >>> p.base, p.exp
- (1/2, 2)
- """
- b, e = self.args
- if b.is_Rational and b.p < b.q and b.p > 0:
- return 1/b, -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)
- if self.is_extended_real:
- return self
- def _eval_transpose(self):
- from sympy.functions.elementary.complexes import transpose
- if self.base == S.Exp1:
- return self.func(S.Exp1, self.exp.transpose())
- i, p = self.exp.is_integer, (self.base.is_complex or self.base.is_infinite)
- 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 b == S.Exp1:
- from sympy.concrete.summations import Sum
- if isinstance(e, Sum) and e.is_commutative:
- from sympy.concrete.products import Product
- return Product(self.func(b, e.function), *e.limits)
- if e.is_Add and (hints.get('force', False) or
- b.is_zero is False or e._all_nonneg_or_nonppos()):
- if e.is_commutative:
- return Mul(*[self.func(b, x) for x in e.args])
- if b.is_commutative:
- c, nc = sift(e.args, lambda x: x.is_commutative, binary=True)
- if c:
- return Mul(*[self.func(b, x) for x in c]
- )*b**Add._from_args(nc)
- return self
- def _eval_expand_power_base(self, **hints):
- """(a*b)**n -> a**n * b**n"""
- force = hints.get('force', False)
- b = self.base
- e = self.exp
- if not b.is_Mul:
- return self
- cargs, nc = b.args_cnc(split_1=False)
- # expand each term - this is top-level-only
- # expansion but we have to watch out for things
- # that don't have an _eval_expand method
- if nc:
- nc = [i._eval_expand_power_base(**hints)
- if hasattr(i, '_eval_expand_power_base') else i
- for i in nc]
- if e.is_Integer:
- if e.is_positive:
- rv = Mul(*nc*e)
- else:
- rv = Mul(*[i**-1 for i in nc[::-1]]*-e)
- if cargs:
- rv *= Mul(*cargs)**e
- return rv
- if not cargs:
- return self.func(Mul(*nc), e, evaluate=False)
- nc = [Mul(*nc)]
- # sift the commutative bases
- other, maybe_real = sift(cargs, lambda x: x.is_extended_real is False,
- binary=True)
- def pred(x):
- if x is S.ImaginaryUnit:
- return S.ImaginaryUnit
- polar = x.is_polar
- if polar:
- return True
- if polar is None:
- return fuzzy_bool(x.is_extended_nonnegative)
- sifted = sift(maybe_real, pred)
- nonneg = sifted[True]
- other += sifted[None]
- neg = sifted[False]
- imag = sifted[S.ImaginaryUnit]
- if imag:
- I = S.ImaginaryUnit
- i = len(imag) % 4
- if i == 0:
- pass
- elif i == 1:
- other.append(I)
- elif i == 2:
- if neg:
- nonn = -neg.pop()
- if nonn is not S.One:
- nonneg.append(nonn)
- else:
- neg.append(S.NegativeOne)
- else:
- if neg:
- nonn = -neg.pop()
- if nonn is not S.One:
- nonneg.append(nonn)
- else:
- neg.append(S.NegativeOne)
- other.append(I)
- del imag
- # bring out the bases that can be separated from the base
- if force or e.is_integer:
- # treat all commutatives the same and put nc in other
- cargs = nonneg + neg + other
- other = nc
- 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
- assert not e.is_Integer
- # handle negatives by making them all positive and putting
- # the residual -1 in other
- if len(neg) > 1:
- o = S.One
- if not other and neg[0].is_Number:
- o *= neg.pop(0)
- if len(neg) % 2:
- o = -o
- for n in neg:
- nonneg.append(-n)
- if o is not S.One:
- other.append(o)
- elif neg and other:
- if neg[0].is_Number and neg[0] is not S.NegativeOne:
- other.append(S.NegativeOne)
- nonneg.append(-neg[0])
- else:
- other.extend(neg)
- else:
- other.extend(neg)
- del neg
- cargs = nonneg
- other += nc
- rv = S.One
- if cargs:
- if e.is_Rational:
- npow, cargs = sift(cargs, lambda x: x.is_Pow and
- x.exp.is_Rational and x.base.is_number,
- binary=True)
- rv = Mul(*[self.func(b.func(*b.args), e) for b in npow])
- rv *= Mul(*[self.func(b, e, evaluate=False) for b in cargs])
- if other:
- rv *= self.func(Mul(*other), e, evaluate=False)
- return rv
- def _eval_expand_multinomial(self, **hints):
- """(a + b + ..)**n -> a**n + n*a**(n-1)*b + .., n is nonzero integer"""
- base, exp = self.args
- result = self
- 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 result
- else:
- radical, result = self.func(base, exp - n), []
- expanded_base_n = self.func(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 b in base.args:
- if b.is_Order:
- order_terms.append(b)
- else:
- other_terms.append(b)
- if order_terms:
- # (f(x) + O(x^n))^m -> f(x)^m + m*f(x)^{m-1} *O(x^n)
- f = Add(*other_terms)
- o = Add(*order_terms)
- if n == 2:
- return expand_multinomial(f**n, deep=False) + n*f*o
- else:
- g = expand_multinomial(f**(n - 1), deep=False)
- return expand_mul(f*g, deep=False) + n*g*o
- 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 = self.func(a.q * b.q, n)
- a, b = a.p*b.q, a.q*b.p
- else:
- k = self.func(a.q, n)
- a, b = a.p, a.q*b
- elif not b.is_Integer:
- k = self.func(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.ntheory.multinomial import multinomial_coefficients
- from sympy.polys.polyutils import basic_from_dict
- 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.
- return basic_from_dict(expansion_dict, *p)
- 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:
- # XXX can this ever happen if base was an Add?
- 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 / self.func(base, -exp)._eval_expand_multinomial()
- elif exp.is_Add and base.is_Number and (hints.get('force', False) or
- base.is_zero is False or exp._all_nonneg_or_nonppos()):
- # a + b a b
- # n --> n n, where n, a, b are Numbers
- # XXX should be in expand_power_exp?
- coeff, tail = [], []
- for term in exp.args:
- if term.is_Number:
- coeff.append(self.func(base, term))
- else:
- tail.append(term)
- return Mul(*(coeff + [self.func(base, Add._from_args(tail))]))
- else:
- return result
- def as_real_imag(self, deep=True, **hints):
- if self.exp.is_Integer:
- from sympy.polys.polytools import poly
- exp = self.exp
- re_e, im_e = self.base.as_real_imag(deep=deep)
- if not im_e:
- return self, S.Zero
- a, b = symbols('a b', cls=Dummy)
- if exp >= 0:
- if re_e.is_Number and im_e.is_Number:
- # We can be more efficient in this case
- expr = expand_multinomial(self.base**exp)
- if expr != self:
- return expr.as_real_imag()
- expr = poly(
- (a + b)**exp) # a = re, b = im; expr = (a + b*I)**exp
- else:
- mag = re_e**2 + im_e**2
- re_e, im_e = re_e/mag, -im_e/mag
- if re_e.is_Number and im_e.is_Number:
- # We can be more efficient in this case
- expr = expand_multinomial((re_e + im_e*S.ImaginaryUnit)**-exp)
- if expr != self:
- 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_e, b: S.ImaginaryUnit*im_e}),
- im_part1.subs({a: re_e, b: im_e}) + im_part3.subs({a: re_e, b: -im_e}))
- from sympy.functions.elementary.trigonometric import atan2, cos, sin
- if self.exp.is_Rational:
- re_e, im_e = self.base.as_real_imag(deep=deep)
- if im_e.is_zero and self.exp is S.Half:
- if re_e.is_extended_nonnegative:
- return self, S.Zero
- if re_e.is_extended_nonpositive:
- return S.Zero, (-self.base)**self.exp
- # XXX: 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.
- r = self.func(self.func(re_e, 2) + self.func(im_e, 2), S.Half)
- t = atan2(im_e, re_e)
- rp, tp = self.func(r, self.exp), t*self.exp
- return rp*cos(tp), rp*sin(tp)
- elif self.base is S.Exp1:
- from sympy.functions.elementary.exponential import exp
- re_e, im_e = self.exp.as_real_imag()
- if deep:
- re_e = re_e.expand(deep, **hints)
- im_e = im_e.expand(deep, **hints)
- c, s = cos(im_e), sin(im_e)
- return exp(re_e)*c, exp(re_e)*s
- else:
- from sympy.functions.elementary.complexes import im, re
- if deep:
- hints['complex'] = False
- expanded = self.expand(deep, **hints)
- if hints.get('ignore') == expanded:
- return None
- else:
- return (re(expanded), im(expanded))
- else:
- return re(self), im(self)
- def _eval_derivative(self, s):
- from sympy.functions.elementary.exponential import log
- dbase = self.base.diff(s)
- dexp = self.exp.diff(s)
- return self * (dexp * log(self.base) + dbase * self.exp/self.base)
- def _eval_evalf(self, prec):
- base, exp = self.as_base_exp()
- if base == S.Exp1:
- # Use mpmath function associated to class "exp":
- from sympy.functions.elementary.exponential import exp as exp_function
- return exp_function(self.exp, evaluate=False)._eval_evalf(prec)
- base = base._evalf(prec)
- if not exp.is_Integer:
- exp = exp._evalf(prec)
- if exp.is_negative and base.is_number and base.is_extended_real is False:
- base = base.conjugate() / (base * base.conjugate())._evalf(prec)
- exp = -exp
- return self.func(base, exp).expand()
- return self.func(base, exp)
- def _eval_is_polynomial(self, syms):
- if self.exp.has(*syms):
- return False
- if self.base.has(*syms):
- return bool(self.base._eval_is_polynomial(syms) and
- self.exp.is_Integer and (self.exp >= 0))
- else:
- return True
- def _eval_is_rational(self):
- # The evaluation of self.func below can be very expensive in the case
- # of integer**integer if the exponent is large. We should try to exit
- # before that if possible:
- if (self.exp.is_integer and self.base.is_rational
- and fuzzy_not(fuzzy_and([self.exp.is_negative, self.base.is_zero]))):
- return True
- 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:
- if b.is_rational:
- if fuzzy_not(b.is_zero) or e.is_nonnegative:
- return True
- if b == e: # always rational, even for 0**0
- return True
- elif b.is_irrational:
- return e.is_zero
- if b is S.Exp1:
- if e.is_rational and e.is_nonzero:
- return False
- def _eval_is_algebraic(self):
- def _is_one(expr):
- try:
- return (expr - 1).is_zero
- except ValueError:
- # when the operation is not allowed
- return False
- if self.base.is_zero or _is_one(self.base):
- return True
- elif self.base is S.Exp1:
- s = self.func(*self.args)
- if s.func == self.func:
- if self.exp.is_nonzero:
- if self.exp.is_algebraic:
- return False
- elif (self.exp/S.Pi).is_rational:
- return False
- elif (self.exp/(S.ImaginaryUnit*S.Pi)).is_rational:
- return True
- else:
- return s.is_algebraic
- elif self.exp.is_rational:
- if self.base.is_algebraic is False:
- return self.exp.is_zero
- if self.base.is_zero is False:
- if self.exp.is_nonzero:
- return self.base.is_algebraic
- elif self.base.is_algebraic:
- return True
- if self.exp.is_positive:
- return self.base.is_algebraic
- elif self.base.is_algebraic and self.exp.is_algebraic:
- if ((fuzzy_not(self.base.is_zero)
- and fuzzy_not(_is_one(self.base)))
- or self.base.is_integer is False
- or self.base.is_irrational):
- return self.exp.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 _eval_is_meromorphic(self, x, a):
- # f**g is meromorphic if g is an integer and f is meromorphic.
- # E**(log(f)*g) is meromorphic if log(f)*g is meromorphic
- # and finite.
- base_merom = self.base._eval_is_meromorphic(x, a)
- exp_integer = self.exp.is_Integer
- if exp_integer:
- return base_merom
- exp_merom = self.exp._eval_is_meromorphic(x, a)
- if base_merom is False:
- # f**g = E**(log(f)*g) may be meromorphic if the
- # singularities of log(f) and g cancel each other,
- # for example, if g = 1/log(f). Hence,
- return False if exp_merom else None
- elif base_merom is None:
- return None
- b = self.base.subs(x, a)
- # b is extended complex as base is meromorphic.
- # log(base) is finite and meromorphic when b != 0, zoo.
- b_zero = b.is_zero
- if b_zero:
- log_defined = False
- else:
- log_defined = fuzzy_and((b.is_finite, fuzzy_not(b_zero)))
- if log_defined is False: # zero or pole of base
- return exp_integer # False or None
- elif log_defined is None:
- return None
- if not exp_merom:
- return exp_merom # False or None
- return self.exp.subs(x, a).is_finite
- def _eval_is_algebraic_expr(self, syms):
- if self.exp.has(*syms):
- return False
- if self.base.has(*syms):
- return self.base._eval_is_algebraic_expr(syms) and \
- self.exp.is_Rational
- else:
- return True
- def _eval_rewrite_as_exp(self, base, expo, **kwargs):
- from sympy.functions.elementary.exponential import exp, log
- if base.is_zero or base.has(exp) or expo.has(exp):
- return base**expo
- if base.has(Symbol):
- # delay evaluation if expo is non symbolic
- # (as exp(x*log(5)) automatically reduces to x**5)
- if global_parameters.exp_is_pow:
- return Pow(S.Exp1, log(base)*expo, evaluate=expo.has(Symbol))
- else:
- return exp(log(base)*expo, evaluate=expo.has(Symbol))
- else:
- from sympy.functions.elementary.complexes import arg, Abs
- return exp((log(Abs(base)) + S.ImaginaryUnit*arg(base))*expo)
- 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
- if exp.is_Mul and not neg_exp and not exp.is_positive:
- neg_exp = exp.could_extract_minus_sign()
- int_exp = exp.is_integer
- # 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_extended_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
- if exp.is_infinite:
- if n is S.One and d is not S.One:
- return n, self.func(d, exp)
- if n is not S.One and d is S.One:
- return self.func(n, exp), d
- return self.func(n, exp), self.func(d, exp)
- def matches(self, expr, repl_dict=None, old=False):
- expr = _sympify(expr)
- if repl_dict is None:
- repl_dict = {}
- # special case, pattern = 1 and expr.exp can match to 0
- if expr is S.One:
- d = self.exp.matches(S.Zero, repl_dict)
- if d is not None:
- return d
- # make sure the expression to be matched is an Expr
- if not isinstance(expr, Expr):
- return None
- b, e = expr.as_base_exp()
- # special case number
- sb, se = self.as_base_exp()
- if sb.is_Symbol and se.is_Integer and expr:
- if e.is_rational:
- return sb.matches(b**(e/se), repl_dict)
- return sb.matches(expr**(1/se), repl_dict)
- 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, cdir=0):
- # 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
- # expressions involving only numbers, the log function, and log(x).
- # The series expansion of b**e is computed as follows:
- # 1) We express b as f*(1 + g) where f is the leading term of b.
- # g has order O(x**d) where d is strictly positive.
- # 2) Then b**e = (f**e)*((1 + g)**e).
- # (1 + g)**e is computed using binomial series.
- from sympy.functions.elementary.exponential import exp, log
- from sympy.series.limits import limit
- from sympy.series.order import Order
- from sympy.core.sympify import sympify
- if self.base is S.Exp1:
- e_series = self.exp.nseries(x, n=n, logx=logx)
- if e_series.is_Order:
- return 1 + e_series
- e0 = limit(e_series.removeO(), x, 0)
- if e0 is S.NegativeInfinity:
- return Order(x**n, x)
- if e0 is S.Infinity:
- return self
- t = e_series - e0
- exp_series = term = exp(e0)
- # series of exp(e0 + t) in t
- for i in range(1, n):
- term *= t/i
- term = term.nseries(x, n=n, logx=logx)
- exp_series += term
- exp_series += Order(t**n, x)
- from sympy.simplify.powsimp import powsimp
- return powsimp(exp_series, deep=True, combine='exp')
- from sympy.simplify.powsimp import powdenest
- from .numbers import _illegal
- self = powdenest(self, force=True).trigsimp()
- b, e = self.as_base_exp()
- if e.has(*_illegal):
- raise PoleError()
- if e.has(x):
- return exp(e*log(b))._eval_nseries(x, n=n, logx=logx, cdir=cdir)
- if logx is not None and b.has(log):
- from .symbol import Wild
- c, ex = symbols('c, ex', cls=Wild, exclude=[x])
- b = b.replace(log(c*x**ex), log(c) + ex*logx)
- self = b**e
- b = b.removeO()
- try:
- from sympy.functions.special.gamma_functions import polygamma
- if b.has(polygamma, S.EulerGamma) and logx is not None:
- raise ValueError()
- _, m = b.leadterm(x)
- except (ValueError, NotImplementedError, PoleError):
- b = b._eval_nseries(x, n=max(2, n), logx=logx, cdir=cdir).removeO()
- if b.has(S.NaN, S.ComplexInfinity):
- raise NotImplementedError()
- _, m = b.leadterm(x)
- if e.has(log):
- from sympy.simplify.simplify import logcombine
- e = logcombine(e).cancel()
- if not (m.is_zero or e.is_number and e.is_real):
- if self == self._eval_as_leading_term(x, logx=logx, cdir=cdir):
- res = exp(e*log(b))._eval_nseries(x, n=n, logx=logx, cdir=cdir)
- if res == exp(e*log(b)):
- return self
- return res
- f = b.as_leading_term(x, logx=logx)
- g = (b/f - S.One).cancel(expand=False)
- if not m.is_number:
- raise NotImplementedError()
- maxpow = n - m*e
- if maxpow.has(Symbol):
- maxpow = sympify(n)
- if maxpow.is_negative:
- return Order(x**(m*e), x)
- if g.is_zero:
- r = f**e
- if r != self:
- r += Order(x**n, x)
- return r
- def coeff_exp(term, x):
- coeff, exp = S.One, S.Zero
- for factor in Mul.make_args(term):
- if factor.has(x):
- base, exp = factor.as_base_exp()
- if base != x:
- try:
- return term.leadterm(x)
- except ValueError:
- return term, S.Zero
- else:
- coeff *= factor
- return coeff, exp
- def mul(d1, d2):
- res = {}
- for e1, e2 in product(d1, d2):
- ex = e1 + e2
- if ex < maxpow:
- res[ex] = res.get(ex, S.Zero) + d1[e1]*d2[e2]
- return res
- try:
- c, d = g.leadterm(x, logx=logx)
- except (ValueError, NotImplementedError):
- if limit(g/x**maxpow, x, 0) == 0:
- # g has higher order zero
- return f**e + e*f**e*g # first term of binomial series
- else:
- raise NotImplementedError()
- if c.is_Float and d == S.Zero:
- # Convert floats like 0.5 to exact SymPy numbers like S.Half, to
- # prevent rounding errors which can induce wrong values of d leading
- # to a NotImplementedError being returned from the block below.
- from sympy.simplify.simplify import nsimplify
- _, d = nsimplify(g).leadterm(x, logx=logx)
- if not d.is_positive:
- g = g.simplify()
- if g.is_zero:
- return f**e
- _, d = g.leadterm(x, logx=logx)
- if not d.is_positive:
- g = ((b - f)/f).expand()
- _, d = g.leadterm(x, logx=logx)
- if not d.is_positive:
- raise NotImplementedError()
- from sympy.functions.elementary.integers import ceiling
- gpoly = g._eval_nseries(x, n=ceiling(maxpow), logx=logx, cdir=cdir).removeO()
- gterms = {}
- for term in Add.make_args(gpoly):
- co1, e1 = coeff_exp(term, x)
- gterms[e1] = gterms.get(e1, S.Zero) + co1
- k = S.One
- terms = {S.Zero: S.One}
- tk = gterms
- from sympy.functions.combinatorial.factorials import factorial, ff
- while (k*d - maxpow).is_negative:
- coeff = ff(e, k)/factorial(k)
- for ex in tk:
- terms[ex] = terms.get(ex, S.Zero) + coeff*tk[ex]
- tk = mul(tk, gterms)
- k += S.One
- from sympy.functions.elementary.complexes import im
- if not e.is_integer and m.is_zero and f.is_negative:
- ndir = (b - f).dir(x, cdir)
- if im(ndir).is_negative:
- inco, inex = coeff_exp(f**e*(-1)**(-2*e), x)
- elif im(ndir).is_zero:
- inco, inex = coeff_exp(exp(e*log(b)).as_leading_term(x, logx=logx, cdir=cdir), x)
- else:
- inco, inex = coeff_exp(f**e, x)
- else:
- inco, inex = coeff_exp(f**e, x)
- res = S.Zero
- for e1 in terms:
- ex = e1 + inex
- res += terms[e1]*inco*x**(ex)
- if not (e.is_integer and e.is_positive and (e*d - n).is_nonpositive and
- res == _mexpand(self)):
- try:
- res += Order(x**n, x)
- except NotImplementedError:
- return exp(e*log(b))._eval_nseries(x, n=n, logx=logx, cdir=cdir)
- return res
- def _eval_as_leading_term(self, x, logx=None, cdir=0):
- from sympy.functions.elementary.exponential import exp, log
- e = self.exp
- b = self.base
- if self.base is S.Exp1:
- arg = e.as_leading_term(x, logx=logx)
- arg0 = arg.subs(x, 0)
- if arg0 is S.NaN:
- arg0 = arg.limit(x, 0)
- if arg0.is_infinite is False:
- return S.Exp1**arg0
- raise PoleError("Cannot expand %s around 0" % (self))
- elif e.has(x):
- lt = exp(e * log(b))
- return lt.as_leading_term(x, logx=logx, cdir=cdir)
- else:
- from sympy.functions.elementary.complexes import im
- try:
- f = b.as_leading_term(x, logx=logx, cdir=cdir)
- except PoleError:
- return self
- if not e.is_integer and f.is_negative and not f.has(x):
- ndir = (b - f).dir(x, cdir)
- if im(ndir).is_negative:
- # Normally, f**e would evaluate to exp(e*log(f)) but on branch cuts
- # an other value is expected through the following computation
- # exp(e*(log(f) - 2*pi*I)) == f**e*exp(-2*e*pi*I) == f**e*(-1)**(-2*e).
- return self.func(f, e) * (-1)**(-2*e)
- elif im(ndir).is_zero:
- log_leadterm = log(b)._eval_as_leading_term(x, logx=logx, cdir=cdir)
- if log_leadterm.is_infinite is False:
- return exp(e*log_leadterm)
- return self.func(f, e)
- @cacheit
- def _taylor_term(self, n, x, *previous_terms): # of (1 + x)**e
- from sympy.functions.combinatorial.factorials import binomial
- return binomial(self.exp, n) * self.func(x, n)
- def taylor_term(self, n, x, *previous_terms):
- if self.base is not S.Exp1:
- return super().taylor_term(n, x, *previous_terms)
- if n < 0:
- return S.Zero
- if n == 0:
- return S.One
- from .sympify import sympify
- x = sympify(x)
- if previous_terms:
- p = previous_terms[-1]
- if p is not None:
- return p * x / n
- from sympy.functions.combinatorial.factorials import factorial
- return x**n/factorial(n)
- def _eval_rewrite_as_sin(self, base, exp):
- if self.base is S.Exp1:
- from sympy.functions.elementary.trigonometric import sin
- return sin(S.ImaginaryUnit*self.exp + S.Pi/2) - S.ImaginaryUnit*sin(S.ImaginaryUnit*self.exp)
- def _eval_rewrite_as_cos(self, base, exp):
- if self.base is S.Exp1:
- from sympy.functions.elementary.trigonometric import cos
- return cos(S.ImaginaryUnit*self.exp) + S.ImaginaryUnit*cos(S.ImaginaryUnit*self.exp + S.Pi/2)
- def _eval_rewrite_as_tanh(self, base, exp):
- if self.base is S.Exp1:
- from sympy.functions.elementary.hyperbolic import tanh
- return (1 + tanh(self.exp/2))/(1 - tanh(self.exp/2))
- def _eval_rewrite_as_sqrt(self, base, exp, **kwargs):
- from sympy.functions.elementary.trigonometric import sin, cos
- if base is not S.Exp1:
- return None
- if exp.is_Mul:
- coeff = exp.coeff(S.Pi * S.ImaginaryUnit)
- if coeff and coeff.is_number:
- cosine, sine = cos(S.Pi*coeff), sin(S.Pi*coeff)
- if not isinstance(cosine, cos) and not isinstance (sine, sin):
- return cosine + S.ImaginaryUnit*sine
- def as_content_primitive(self, radical=False, clear=True):
- """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(*_))
- 3**(2*x + 2)
- >>> 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, clear=clear))
- ce, pe = e.as_content_primitive(radical=radical, clear=clear)
- 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 and b != S.Zero:
- ceh = ce*h
- c = self.func(b, ceh)
- r = S.Zero
- if not c.is_Rational:
- iceh, r = divmod(ceh.p, ceh.q)
- c = self.func(b, iceh)
- return c, self.func(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, clear=clear) # h is positive
- c, m = self.func(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, self.func(_keep_coeff(m, t), e)
- return S.One, self.func(b, e)
- def is_constant(self, *wrt, **flags):
- expr = self
- if flags.get('simplify', True):
- expr = expr.simplify()
- b, e = expr.as_base_exp()
- bz = b.equals(0)
- if bz: # recalculate with assumptions in case it's unevaluated
- new = b**e
- if new != expr:
- 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)
- def _eval_difference_delta(self, n, step):
- b, e = self.args
- if e.has(n) and not b.has(n):
- new_e = e.subs(n, n + step)
- return (b**(new_e - e) - 1) * self
- power = Dispatcher('power')
- power.add((object, object), Pow)
- from .add import Add
- from .numbers import Integer
- from .mul import Mul, _keep_coeff
- from .symbol import Symbol, Dummy, symbols
|