def evalf_log(expr, prec, options): arg = expr.args[0] workprec = prec + 10 xre, xim, xacc, _ = evalf(arg, workprec, options) if xim: # XXX: use get_abs etc instead re = evalf_log(C.log(C.Abs(arg, evaluate=False), evaluate=False), prec, options) im = mpf_atan2(xim, xre or fzero, prec) return re[0], im, re[2], prec imaginary_term = mpf_cmp(xre, fzero) < 0 re = mpf_log(mpf_abs(xre), prec, rnd) size = fastlog(re) if prec - size > workprec: # We actually need to compute 1+x accurately, not x arg = C.Add(S.NegativeOne, arg, evaluate=False) xre, xim, _, _ = evalf_add(arg, prec, options) prec2 = workprec - fastlog(xre) re = mpf_log(mpf_add(xre, fone, prec2), prec, rnd) re_acc = prec if imaginary_term: return re, mpf_pi(prec), re_acc, prec else: return re, None, re_acc, None
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_subs(self, old, new): if old.func is self.func and self.base == old.base: coeff1, terms1 = self.exp.as_independent(C.Symbol, as_Add=False) coeff2, terms2 = old.exp.as_independent(C.Symbol, as_Add=False) if terms1 == terms2: pow = coeff1/coeff2 ok = False # True if int(pow) == pow OR self.base.is_positive try: pow = as_int(pow) ok = True except ValueError: ok = self.base.is_positive if ok: # 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_independent(C.Symbol, as_Add=False) # we can only do this when the base is positive AND the exponent # is real coeff2, terms2 = (self.exp*C.log(self.base)).as_independent( C.Symbol, as_Add=False) 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
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 evalf_log(expr, prec, options): arg = expr.args[0] workprec = prec + 10 xre, xim, xacc, _ = evalf(arg, workprec, options) if xim: # XXX: use get_abs etc instead re = evalf_log(C.log(C.Abs(arg, evaluate=False), evaluate=False), prec, options) im = mpf_atan2(xim, xre or fzero, prec) return re[0], im, re[2], prec imaginary_term = (mpf_cmp(xre, fzero) < 0) re = mpf_log(mpf_abs(xre), prec, round_nearest) size = fastlog(re) if prec - size > workprec: # We actually need to compute 1+x accurately, not x arg = C.Add(S.NegativeOne, arg, evaluate=False) xre, xim, xre_acc, xim_acc = evalf_add(arg, prec, options) prec2 = workprec - fastlog(xre) re = mpf_log(mpf_add(xre, fone, prec2), prec, round_nearest) re_acc = prec if imaginary_term: return re, mpf_pi(prec), re_acc, prec else: return re, None, re_acc, None
def _eval_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
def _eval_subs(self, old, new): if self == old: return 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.is_Integer or self.base.is_commutative: return Pow(new, pow) # (x**(2*y)).subs(x**(3*y),z) -> z**(2/3) if old.func is C.exp: coeff1, terms1 = old.args[0].as_coeff_mul() coeff2, terms2 = (self.exp*C.log(self.base)).as_coeff_mul() if terms1 == terms2: pow = coeff1/coeff2 if pow.is_Integer or self.base.is_commutative: return Pow(new, pow) # (x**(2*y)).subs(x**(3*y),z) -> z**(2/3) return Pow(self.base._eval_subs(old, new), self.exp._eval_subs(old, new))
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
def _eval_subs(self, old, new): if self == old: return 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.is_Integer or self.base.is_commutative: return Pow(new, pow) # (x**(2*y)).subs(x**(3*y),z) -> z**(2/3) if old.func is C.exp: coeff1, terms1 = old.args[0].as_coeff_mul() coeff2, terms2 = (self.exp*C.log(self.base)).as_coeff_mul() if terms1 == terms2: pow = coeff1/coeff2 if pow.is_Integer or self.base.is_commutative: return Pow(new, pow) # (x**(2*y)).subs(x**(3*y),z) -> z**(2/3) b, e = self.base._eval_subs(old, new), self.exp._eval_subs(old, new) if not b and e.is_negative: # don't let subs create an infinity return S.NaN return Pow(b, e)
def _eval_subs(self, old, new): if self == old: return 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.is_Integer or self.base.is_commutative: return Pow(new, pow) # (x**(2*y)).subs(x**(3*y),z) -> z**(2/3) if old.func is C.exp: coeff1, terms1 = old.args[0].as_coeff_mul() coeff2, terms2 = (self.exp * C.log(self.base)).as_coeff_mul() if terms1 == terms2: pow = coeff1 / coeff2 if pow.is_Integer or self.base.is_commutative: return Pow(new, pow) # (x**(2*y)).subs(x**(3*y),z) -> z**(2/3) b, e = self.base._eval_subs(old, new), self.exp._eval_subs(old, new) if not b and e.is_negative: # don't let subs create an infinity return S.NaN return Pow(b, e)
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)
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_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)