def _eval_power(b, e): """ b is Real but not equal to rationals, integers, 0.5, oo, -oo, nan e is symbolic object but not equal to 0, 1 (-p) ** r -> exp(r * log(-p)) -> exp(r * (log(p) + I*Pi)) -> -> p ** r * (sin(Pi*r) + cos(Pi*r) * I) """ if isinstance(e, Number): if isinstance(e, Integer): prec = b._prec return Real._new(mlib.mpf_pow_int(b._mpf_, e.p, prec, rnd), prec) e, prec = e._as_mpf_op(b._prec) b = b._mpf_ try: y = mpf_pow(b, e, prec, rnd) return Real._new(y, prec) except mlib.ComplexResult: re, im = mlibc.mpc_pow((b, mlib.fzero), (e, mlib.fzero), prec, rnd) return Real._new(re, prec) + Real._new(im, prec) * S.ImaginaryUnit
def evalf_pow(v, prec, options): target_prec = prec base, exp = v.args # We handle x**n separately. This has two purposes: 1) it is much # faster, because we avoid calling evalf on the exponent, and 2) it # allows better handling of real/imaginary parts that are exactly zero if exp.is_Integer: p = exp.p # Exact if not p: return fone, None, prec, None # Exponentiation by p magnifies relative error by |p|, so the # base must be evaluated with increased precision if p is large prec += int(math.log(abs(p),2)) re, im, re_acc, im_acc = evalf(base, prec+5, options) # Real to integer power if re and not im: return mpf_pow_int(re, p, target_prec), None, target_prec, None # (x*I)**n = I**n * x**n if im and not re: z = fpowi(im, p, target_prec) case = p % 4 if case == 0: return z, None, target_prec, None if case == 1: return None, z, None, target_prec if case == 2: return mpf_neg(z), None, target_prec, None if case == 3: return None, mpf_neg(z), None, target_prec # Zero raised to an integer power if not re: return None, None, None, None # General complex number to arbitrary integer power re, im = libmpc.mpc_pow_int((re, im), p, prec) # Assumes full accuracy in input return finalize_complex(re, im, target_prec) # Pure square root if exp is S.Half: xre, xim, xre_acc, yim_acc = evalf(base, prec+5, options) # General complex square root if xim: re, im = libmpc.mpc_sqrt((xre or fzero, xim), prec) return finalize_complex(re, im, prec) if not xre: return None, None, None, None # Square root of a negative real number if mpf_lt(xre, fzero): return None, mpf_sqrt(mpf_neg(xre), prec), None, prec # Positive square root return mpf_sqrt(xre, prec), None, prec, None # We first evaluate the exponent to find its magnitude # This determines the working precision that must be used prec += 10 yre, yim, yre_acc, yim_acc = evalf(exp, prec, options) # Special cases: x**0 if not (yre or yim): return fone, None, prec, None ysize = fastlog(yre) # Restart if too big # XXX: prec + ysize might exceed maxprec if ysize > 5: prec += ysize yre, yim, yre_acc, yim_acc = evalf(exp, prec, options) # Pure exponential function; no need to evalf the base if base is S.Exp1: if yim: re, im = libmpc.mpc_exp((yre or fzero, yim), prec) return finalize_complex(re, im, target_prec) return mpf_exp(yre, target_prec), None, target_prec, None xre, xim, xre_acc, yim_acc = evalf(base, prec+5, options) # 0**y if not (xre or xim): return None, None, None, None # (real ** complex) or (complex ** complex) if yim: re, im = libmpc.mpc_pow((xre or fzero, xim or fzero), (yre or fzero, yim), target_prec) return finalize_complex(re, im, target_prec) # complex ** real if xim: re, im = libmpc.mpc_pow_mpf((xre or fzero, xim), yre, target_prec) return finalize_complex(re, im, target_prec) # negative ** real elif mpf_lt(xre, fzero): re, im = libmpc.mpc_pow_mpf((xre, fzero), yre, target_prec) return finalize_complex(re, im, target_prec) # positive ** real else: return mpf_pow(xre, yre, target_prec), None, target_prec, None