def eval(cls, arg, base=None): from sympy import unpolarify from sympy.calculus import AccumBounds from sympy.sets.setexpr import SetExpr from sympy.functions.elementary.complexes import Abs arg = sympify(arg) if base is not None: base = sympify(base) if base == 1: if arg == 1: return S.NaN else: return S.ComplexInfinity try: # handle extraction of powers of the base now # or else expand_log in Mul would have to handle this n = multiplicity(base, arg) if n: return n + log(arg / base**n) / log(base) else: return log(arg) / log(base) except ValueError: pass if base is not S.Exp1: return cls(arg) / cls(base) else: return cls(arg) if arg.is_Number: if arg.is_zero: return S.ComplexInfinity elif arg is S.One: return S.Zero elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Infinity elif arg is S.NaN: return S.NaN elif arg.is_Rational and arg.p == 1: return -cls(arg.q) if arg.is_Pow and arg.base is S.Exp1 and arg.exp.is_extended_real: return arg.exp I = S.ImaginaryUnit if isinstance(arg, exp) and arg.exp.is_extended_real: return arg.exp elif isinstance(arg, exp) and arg.exp.is_number: r_, i_ = match_real_imag(arg.exp) if i_ and i_.is_comparable: i_ %= 2 * S.Pi if i_ > S.Pi: i_ -= 2 * S.Pi return r_ + expand_mul(i_ * I, deep=False) elif isinstance(arg, exp_polar): return unpolarify(arg.exp) elif isinstance(arg, AccumBounds): if arg.min.is_positive: return AccumBounds(log(arg.min), log(arg.max)) else: return elif isinstance(arg, SetExpr): return arg._eval_func(cls) if arg.is_number: if arg.is_negative: return S.Pi * I + cls(-arg) elif arg is S.ComplexInfinity: return S.ComplexInfinity elif arg is S.Exp1: return S.One if arg.is_zero: return S.ComplexInfinity # don't autoexpand Pow or Mul (see the issue 3351): if not arg.is_Add: coeff = arg.as_coefficient(I) if coeff is not None: if coeff is S.Infinity: return S.Infinity elif coeff is S.NegativeInfinity: return S.Infinity elif coeff.is_Rational: if coeff.is_nonnegative: return S.Pi * I * S.Half + cls(coeff) else: return -S.Pi * I * S.Half + cls(-coeff) if arg.is_number and arg.is_algebraic: # Match arg = coeff*(r_ + i_*I) with coeff>0, r_ and i_ real. coeff, arg_ = arg.as_independent(I, as_Add=False) if coeff.is_negative: coeff *= -1 arg_ *= -1 arg_ = expand_mul(arg_, deep=False) r_, i_ = arg_.as_independent(I, as_Add=True) i_ = i_.as_coefficient(I) if coeff.is_real and i_ and i_.is_real and r_.is_real: if r_.is_zero: if i_.is_positive: return S.Pi * I * S.Half + cls(coeff * i_) elif i_.is_negative: return -S.Pi * I * S.Half + cls(coeff * -i_) else: from sympy.simplify import ratsimp # Check for arguments involving rational multiples of pi t = (i_ / r_).cancel() t1 = (-t).cancel() atan_table = { # first quadrant only sqrt(3): S.Pi / 3, 1: S.Pi / 4, sqrt(5 - 2 * sqrt(5)): S.Pi / 5, sqrt(2) * sqrt(5 - sqrt(5)) / (1 + sqrt(5)): S.Pi / 5, sqrt(5 + 2 * sqrt(5)): S.Pi * Rational(2, 5), sqrt(2) * sqrt(sqrt(5) + 5) / (-1 + sqrt(5)): S.Pi * Rational(2, 5), sqrt(3) / 3: S.Pi / 6, sqrt(2) - 1: S.Pi / 8, sqrt(2 - sqrt(2)) / sqrt(sqrt(2) + 2): S.Pi / 8, sqrt(2) + 1: S.Pi * Rational(3, 8), sqrt(sqrt(2) + 2) / sqrt(2 - sqrt(2)): S.Pi * Rational(3, 8), sqrt(1 - 2 * sqrt(5) / 5): S.Pi / 10, (-sqrt(2) + sqrt(10)) / (2 * sqrt(sqrt(5) + 5)): S.Pi / 10, sqrt(1 + 2 * sqrt(5) / 5): S.Pi * Rational(3, 10), (sqrt(2) + sqrt(10)) / (2 * sqrt(5 - sqrt(5))): S.Pi * Rational(3, 10), 2 - sqrt(3): S.Pi / 12, (-1 + sqrt(3)) / (1 + sqrt(3)): S.Pi / 12, 2 + sqrt(3): S.Pi * Rational(5, 12), (1 + sqrt(3)) / (-1 + sqrt(3)): S.Pi * Rational(5, 12) } if t in atan_table: modulus = ratsimp(coeff * Abs(arg_)) if r_.is_positive: return cls(modulus) + I * atan_table[t] else: return cls(modulus) + I * (atan_table[t] - S.Pi) elif t1 in atan_table: modulus = ratsimp(coeff * Abs(arg_)) if r_.is_positive: return cls(modulus) + I * (-atan_table[t1]) else: return cls(modulus) + I * (S.Pi - atan_table[t1])
def eval(cls, arg, base=None): from sympy import unpolarify from sympy.calculus import AccumBounds from sympy.sets.setexpr import SetExpr arg = sympify(arg) if base is not None: base = sympify(base) if base == 1: if arg == 1: return S.NaN else: return S.ComplexInfinity try: # handle extraction of powers of the base now # or else expand_log in Mul would have to handle this n = multiplicity(base, arg) if n: den = base**n if den.is_Integer: return n + log(arg // den) / log(base) else: return n + log(arg / den) / log(base) else: return log(arg) / log(base) except ValueError: pass if base is not S.Exp1: return cls(arg) / cls(base) else: return cls(arg) if arg.is_Number: if arg is S.Zero: return S.ComplexInfinity elif arg is S.One: return S.Zero elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Infinity elif arg is S.NaN: return S.NaN elif arg.is_Rational and arg.p == 1: return -cls(arg.q) if arg is S.ComplexInfinity: return S.ComplexInfinity if isinstance(arg, exp) and arg.args[0].is_real: return arg.args[0] elif isinstance(arg, exp_polar): return unpolarify(arg.exp) elif isinstance(arg, AccumBounds): if arg.min.is_positive: return AccumBounds(log(arg.min), log(arg.max)) else: return elif isinstance(arg, SetExpr): return arg._eval_func(cls) if arg.is_number: if arg.is_negative: return S.Pi * S.ImaginaryUnit + cls(-arg) elif arg is S.ComplexInfinity: return S.ComplexInfinity elif arg is S.Exp1: return S.One # don't autoexpand Pow or Mul (see the issue 3351): if not arg.is_Add: coeff = arg.as_coefficient(S.ImaginaryUnit) if coeff is not None: if coeff is S.Infinity: return S.Infinity elif coeff is S.NegativeInfinity: return S.Infinity elif coeff.is_Rational: if coeff.is_nonnegative: return S.Pi * S.ImaginaryUnit * S.Half + cls(coeff) else: return -S.Pi * S.ImaginaryUnit * S.Half + cls(-coeff)
def eval(cls, arg): from sympy.calculus import AccumBounds from sympy.sets.setexpr import SetExpr from sympy.matrices.matrices import MatrixBase from sympy import im, logcombine, re if isinstance(arg, MatrixBase): return arg.exp() elif global_parameters.exp_is_pow: return Pow(S.Exp1, arg) elif arg.is_Number: if arg is S.NaN: return S.NaN elif arg.is_zero: return S.One elif arg is S.One: return S.Exp1 elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Zero elif arg is S.ComplexInfinity: return S.NaN elif isinstance(arg, log): return arg.args[0] elif isinstance(arg, AccumBounds): return AccumBounds(exp(arg.min), exp(arg.max)) elif isinstance(arg, SetExpr): return arg._eval_func(cls) elif arg.is_Mul: coeff = arg.as_coefficient(S.Pi * S.ImaginaryUnit) if coeff: if (2 * coeff).is_integer: if coeff.is_even: return S.One elif coeff.is_odd: return S.NegativeOne elif (coeff + S.Half).is_even: return -S.ImaginaryUnit elif (coeff + S.Half).is_odd: return S.ImaginaryUnit elif coeff.is_Rational: ncoeff = coeff % 2 # restrict to [0, 2pi) if ncoeff > 1: # restrict to (-pi, pi] ncoeff -= 2 if ncoeff != coeff: return cls(ncoeff * S.Pi * S.ImaginaryUnit) # Warning: code in risch.py will be very sensitive to changes # in this (see DifferentialExtension). # look for a single log factor coeff, terms = arg.as_coeff_Mul() # but it can't be multiplied by oo if coeff in [S.NegativeInfinity, S.Infinity]: if terms.is_number: if coeff is S.NegativeInfinity: terms = -terms if re(terms).is_zero and terms is not S.Zero: return S.NaN if re(terms).is_positive and im(terms) is not S.Zero: return S.ComplexInfinity if re(terms).is_negative: return S.Zero return None coeffs, log_term = [coeff], None for term in Mul.make_args(terms): term_ = logcombine(term) if isinstance(term_, log): if log_term is None: log_term = term_.args[0] else: return None elif term.is_comparable: coeffs.append(term) else: return None return log_term**Mul(*coeffs) if log_term else None elif arg.is_Add: out = [] add = [] argchanged = False for a in arg.args: if a is S.One: add.append(a) continue newa = cls(a) if isinstance(newa, cls): if newa.args[0] != a: add.append(newa.args[0]) argchanged = True else: add.append(a) else: out.append(newa) if out or argchanged: return Mul(*out) * cls(Add(*add), evaluate=False) if arg.is_zero: return S.One
def eval(cls, arg): from sympy.assumptions import ask, Q from sympy.calculus import AccumBounds from sympy.sets.setexpr import SetExpr from sympy.matrices.matrices import MatrixBase if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.One elif arg is S.One: return S.Exp1 elif arg is S.Infinity: return S.Infinity elif arg is S.NegativeInfinity: return S.Zero elif arg is S.ComplexInfinity: return S.NaN elif isinstance(arg, log): return arg.args[0] elif isinstance(arg, AccumBounds): return AccumBounds(exp(arg.min), exp(arg.max)) elif isinstance(arg, SetExpr): return arg._eval_func(cls) elif arg.is_Mul: if arg.is_number or arg.is_Symbol: coeff = arg.coeff(S.Pi * S.ImaginaryUnit) if coeff: if ask(Q.integer(2 * coeff)): if ask(Q.even(coeff)): return S.One elif ask(Q.odd(coeff)): return S.NegativeOne elif ask(Q.even(coeff + S.Half)): return -S.ImaginaryUnit elif ask(Q.odd(coeff + S.Half)): return S.ImaginaryUnit # Warning: code in risch.py will be very sensitive to changes # in this (see DifferentialExtension). # look for a single log factor coeff, terms = arg.as_coeff_Mul() # but it can't be multiplied by oo if coeff in [S.NegativeInfinity, S.Infinity]: return None coeffs, log_term = [coeff], None for term in Mul.make_args(terms): if isinstance(term, log): if log_term is None: log_term = term.args[0] else: return None elif term.is_comparable: coeffs.append(term) else: return None return log_term**Mul(*coeffs) if log_term else None elif arg.is_Add: out = [] add = [] for a in arg.args: if a is S.One: add.append(a) continue newa = cls(a) if isinstance(newa, cls): add.append(a) else: out.append(newa) if out: return Mul(*out) * cls(Add(*add), evaluate=False) elif isinstance(arg, MatrixBase): return arg.exp()