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) # xre is now x - 1 so we add 1 back here to calculate x re = mpf_log(mpf_abs(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 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 round(x, p=0): """Return x rounded to the given decimal place. If x is not an Expr, Python's round function is employed. Examples ======== >>> from sympy import round, pi, S, Number >>> round(S(10.5)) 11. >>> round(pi) 3. >>> round(pi, 2) 3.14 If x is not a SymPy Expr then Python's round is used and it returns a Python type, not a SymPy Number: >>> isinstance(round(543210, -2), Number) False >>> round(S(543210), -2) 5.432e+5 >>> _.is_Number True """ from sympy.functions.elementary.exponential import log from sympy.mpmath.libmp import prec_to_dps if not isinstance(x, Expr): return _pyround(x, p) if not x.is_number: raise TypeError('%s is not a number' % x) if not x.is_real: raise TypeError("can't convert complex to int") if not x: return x p = int(p) precs = [f._prec for f in x.atoms(C.Float)] dps = prec_to_dps(max(precs)) if precs else None xpos = abs(x.n()) try: mag_first_dig = int(ceil(log10(xpos))) except (ValueError, OverflowError): mag_first_dig = int(ceil(C.Float(mpf_log(xpos._mpf_, 53))/log(10))) # check that we aren't off by 1 if (xpos/10**mag_first_dig) >= 1: mag_first_dig += 1 assert .1 <= (xpos/10**mag_first_dig) < 1 allow = digits_needed = mag_first_dig + p if dps is not None and allow > dps: allow = dps mag = Pow(10, p) # magnitude needed to bring digit p to units place x += 1/(2*mag) # add the half for rounding i10 = 10*mag*x.n((dps if dps is not None else digits_needed) + 1) rv = Integer(i10)//10 q = 1 if p > 0: q = mag elif p < 0: rv /= mag rv = Rational(rv, q) if rv.is_Integer: # use str or else it won't be a float return C.Float(str(rv), digits_needed) else: return C.Float(rv, allow)