def mag(ctx, x): """ Quick logarithmic magnitude estimate of a number. Returns an integer or infinity `m` such that `|x| <= 2^m`. It is not guaranteed that `m` is an optimal bound, but it will never be off by more than 2 (and probably not more than 1). """ if hasattr(x, "_mpf_"): return ctx._mpf_mag(x._mpf_) elif hasattr(x, "_mpc_"): r, i = x._mpc_ if r == fzero: return ctx._mpf_mag(i) if i == fzero: return ctx._mpf_mag(r) return 1 + max(ctx._mpf_mag(r), ctx._mpf_mag(i)) elif isinstance(x, int_types): if x: return bitcount(abs(x)) return ctx.ninf elif isinstance(x, rational.mpq): p, q = x if p: return 1 + bitcount(abs(p)) - bitcount(abs(q)) return ctx.ninf else: x = ctx.convert(x) if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): return ctx.mag(x) else: raise TypeError("requires an mpf/mpc")
def mag(ctx, x): """ Quick logarithmic magnitude estimate of a number. Returns an integer or infinity `m` such that `|x| <= 2^m`. It is not guaranteed that `m` is an optimal bound, but it will never be off by more than 2 (and probably not more than 1). """ if hasattr(x, "_mpf_"): return ctx._mpf_mag(x._mpf_) elif hasattr(x, "_mpc_"): r, i = x._mpc_ if r == fzero: return ctx._mpf_mag(i) if i == fzero: return ctx._mpf_mag(r) return 1+max(ctx._mpf_mag(r), ctx._mpf_mag(i)) elif isinstance(x, int_types): if x: return bitcount(abs(x)) return ctx.ninf elif isinstance(x, rational.mpq): p, q = x if p: return 1 + bitcount(abs(p)) - bitcount(abs(q)) return ctx.ninf else: x = ctx.convert(x) if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): return ctx.mag(x) else: raise TypeError("requires an mpf/mpc")
def __hash__(s): a, b = s._mpq_ if b == 1: return hash(a) # Power of two: mpf compatible hash if not (b & (b - 1)): return mpf_hash(from_man_exp(a, 1 - bitcount(b))) return hash((a, b))
def __hash__(s): a, b = s._mpq_ if b == 1: return hash(a) # Power of two: mpf compatible hash if not (b & (b-1)): return mpf_hash(from_man_exp(a, 1-bitcount(b))) return hash((a,b))
def mag(ctx, x): """ Quick logarithmic magnitude estimate of a number. Returns an integer or infinity `m` such that `|x| <= 2^m`. It is not guaranteed that `m` is an optimal bound, but it will never be too large by more than 2 (and probably not more than 1). **Examples** >>> from mpmath import * >>> mp.pretty = True >>> mag(10), mag(10.0), mag(mpf(10)), int(ceil(log(10,2))) (4, 4, 4, 4) >>> mag(10j), mag(10+10j) (4, 5) >>> mag(0.01), int(ceil(log(0.01,2))) (-6, -6) >>> mag(0), mag(inf), mag(-inf), mag(nan) (-inf, +inf, +inf, nan) """ if hasattr(x, "_mpf_"): return ctx._mpf_mag(x._mpf_) elif hasattr(x, "_mpc_"): r, i = x._mpc_ if r == fzero: return ctx._mpf_mag(i) if i == fzero: return ctx._mpf_mag(r) return 1+max(ctx._mpf_mag(r), ctx._mpf_mag(i)) elif isinstance(x, int_types): if x: return bitcount(abs(x)) return ctx.ninf elif isinstance(x, rational.mpq): p, q = x._mpq_ if p: return 1 + bitcount(abs(p)) - bitcount(q) return ctx.ninf else: x = ctx.convert(x) if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): return ctx.mag(x) else: raise TypeError("requires an mpf/mpc")
def mag(ctx, x): """ Quick logarithmic magnitude estimate of a number. Returns an integer or infinity `m` such that `|x| <= 2^m`. It is not guaranteed that `m` is an optimal bound, but it will never be too large by more than 2 (and probably not more than 1). **Examples** >>> from mpmath import * >>> mp.pretty = True >>> mag(10), mag(10.0), mag(mpf(10)), int(ceil(log(10,2))) (4, 4, 4, 4) >>> mag(10j), mag(10+10j) (4, 5) >>> mag(0.01), int(ceil(log(0.01,2))) (-6, -6) >>> mag(0), mag(inf), mag(-inf), mag(nan) (-inf, +inf, +inf, nan) """ if hasattr(x, "_mpf_"): return ctx._mpf_mag(x._mpf_) elif hasattr(x, "_mpc_"): r, i = x._mpc_ if r == fzero: return ctx._mpf_mag(i) if i == fzero: return ctx._mpf_mag(r) return 1 + max(ctx._mpf_mag(r), ctx._mpf_mag(i)) elif isinstance(x, int_types): if x: return bitcount(abs(x)) return ctx.ninf elif isinstance(x, rational.mpq): p, q = x._mpq_ if p: return 1 + bitcount(abs(p)) - bitcount(q) return ctx.ninf else: x = ctx.convert(x) if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): return ctx.mag(x) else: raise TypeError("requires an mpf/mpc")
def nint_distance(ctx, x): """ Returns (n, d) where n is the nearest integer to x and d is the log-2 distance (i.e. distance in bits) of n from x. If d < 0, (-d) gives the bits of cancellation when n is subtracted from x. This function is intended to be used to check for cancellation at poles. """ if hasattr(x, "_mpf_"): re = x._mpf_ im_dist = ctx.ninf elif hasattr(x, "_mpc_"): re, im = x._mpc_ isign, iman, iexp, ibc = im if iman: im_dist = iexp + ibc elif im == fzero: im_dist = ctx.ninf else: raise ValueError("requires a finite number") elif isinstance(x, int_types): return int(x), ctx.ninf elif isinstance(x, rational.mpq): p, q = x n, r = divmod(p, q) if 2*r >= q: n += 1 elif not r: return n, ctx.ninf # log(p/q-n) = log((p-nq)/q) = log(p-nq) - log(q) d = bitcount(abs(p-n*q)) - bitcount(q) return n, d else: x = ctx.convert(x) if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): return ctx.nint_distance(x) else: raise TypeError("requires an mpf/mpc") sign, man, exp, bc = re shift = exp+bc if sign: man = -man if shift < -1: n = 0 re_dist = shift elif man: if exp >= 0: n = man << exp re_dist = ctx.ninf else: if shift >= 0: xfixed = man << shift else: xfixed = man >> (-shift) n1 = xfixed >> bc n2 = -((-xfixed) >> bc) dist1 = abs(xfixed - (n1<<bc)) dist2 = abs(xfixed - (n2<<bc)) if dist1 < dist2: re_dist = dist1 n = n1 else: re_dist = dist2 n = n2 if re_dist: re_dist = bitcount(re_dist) - bc else: re_dist = ctx.ninf elif re == fzero: re_dist = ctx.ninf n = 0 else: raise ValueError("requires a finite number") return n, max(re_dist, im_dist)
def nint_distance(ctx, x): r""" Return `(n,d)` where `n` is the nearest integer to `x` and `d` is an estimate of `\log_2(|x-n|)`. If `d < 0`, `-d` gives the precision (measured in bits) lost to cancellation when computing `x-n`. >>> from mpmath import * >>> n, d = nint_distance(5) >>> print n, d 5 -inf >>> n, d = nint_distance(mpf(5)) >>> print n, d 5 -inf >>> n, d = nint_distance(mpf(5.00000001)) >>> print n, d 5 -26 >>> n, d = nint_distance(mpf(4.99999999)) >>> print n, d 5 -26 >>> n, d = nint_distance(mpc(5,10)) >>> print n, d 5 4 >>> n, d = nint_distance(mpc(5,0.000001)) >>> print n, d 5 -19 """ if hasattr(x, "_mpf_"): re = x._mpf_ im_dist = ctx.ninf elif hasattr(x, "_mpc_"): re, im = x._mpc_ isign, iman, iexp, ibc = im if iman: im_dist = iexp + ibc elif im == fzero: im_dist = ctx.ninf else: raise ValueError("requires a finite number") elif isinstance(x, int_types): return int(x), ctx.ninf elif isinstance(x, rational.mpq): p, q = x._mpq_ n, r = divmod(p, q) if 2*r >= q: n += 1 elif not r: return n, ctx.ninf # log(p/q-n) = log((p-nq)/q) = log(p-nq) - log(q) d = bitcount(abs(p-n*q)) - bitcount(q) return n, d else: x = ctx.convert(x) if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): return ctx.nint_distance(x) else: raise TypeError("requires an mpf/mpc") sign, man, exp, bc = re shift = exp+bc if sign: man = -man if shift < -1: n = 0 re_dist = shift elif man: if exp >= 0: n = man << exp re_dist = ctx.ninf else: if shift >= 0: xfixed = man << shift else: xfixed = man >> (-shift) n1 = xfixed >> bc n2 = -((-xfixed) >> bc) dist1 = abs(xfixed - (n1<<bc)) dist2 = abs(xfixed - (n2<<bc)) if dist1 < dist2: re_dist = dist1 n = n1 else: re_dist = dist2 n = n2 if re_dist: re_dist = bitcount(re_dist) - bc else: re_dist = ctx.ninf elif re == fzero: re_dist = ctx.ninf n = 0 else: raise ValueError("requires a finite number") return n, max(re_dist, im_dist)
def nint_distance(ctx, x): r""" Return `(n,d)` where `n` is the nearest integer to `x` and `d` is an estimate of `\log_2(|x-n|)`. If `d < 0`, `-d` gives the precision (measured in bits) lost to cancellation when computing `x-n`. >>> from mpmath import * >>> n, d = nint_distance(5) >>> print n, d 5 -inf >>> n, d = nint_distance(mpf(5)) >>> print n, d 5 -inf >>> n, d = nint_distance(mpf(5.00000001)) >>> print n, d 5 -26 >>> n, d = nint_distance(mpf(4.99999999)) >>> print n, d 5 -26 >>> n, d = nint_distance(mpc(5,10)) >>> print n, d 5 4 >>> n, d = nint_distance(mpc(5,0.000001)) >>> print n, d 5 -19 """ typx = type(x) if typx in int_types: return int(x), ctx.ninf elif typx is rational.mpq: p, q = x._mpq_ n, r = divmod(p, q) if 2*r >= q: n += 1 elif not r: return n, ctx.ninf # log(p/q-n) = log((p-nq)/q) = log(p-nq) - log(q) d = bitcount(abs(p-n*q)) - bitcount(q) return n, d if hasattr(x, "_mpf_"): re = x._mpf_ im_dist = ctx.ninf elif hasattr(x, "_mpc_"): re, im = x._mpc_ isign, iman, iexp, ibc = im if iman: im_dist = iexp + ibc elif im == fzero: im_dist = ctx.ninf else: raise ValueError("requires a finite number") else: x = ctx.convert(x) if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"): return ctx.nint_distance(x) else: raise TypeError("requires an mpf/mpc") sign, man, exp, bc = re mag = exp+bc # |x| < 0.5 if mag < 0: n = 0 re_dist = mag elif man: # exact integer if exp >= 0: n = man << exp re_dist = ctx.ninf # exact half-integer elif exp == -1: n = (man>>1)+1 re_dist = 0 else: d = (-exp-1) t = man >> d if t & 1: t += 1 man = (t<<d) - man else: man -= (t<<d) n = t>>1 # int(t)>>1 re_dist = exp+bitcount(man) if sign: n = -n elif re == fzero: re_dist = ctx.ninf n = 0 else: raise ValueError("requires a finite number") return n, max(re_dist, im_dist)