Spaces:
Sleeping
Sleeping
from .ctx_base import StandardBaseContext | |
import math | |
import cmath | |
from . import math2 | |
from . import function_docs | |
from .libmp import mpf_bernoulli, to_float, int_types | |
from . import libmp | |
class FPContext(StandardBaseContext): | |
""" | |
Context for fast low-precision arithmetic (53-bit precision, giving at most | |
about 15-digit accuracy), using Python's builtin float and complex. | |
""" | |
def __init__(ctx): | |
StandardBaseContext.__init__(ctx) | |
# Override SpecialFunctions implementation | |
ctx.loggamma = math2.loggamma | |
ctx._bernoulli_cache = {} | |
ctx.pretty = False | |
ctx._init_aliases() | |
_mpq = lambda cls, x: float(x[0])/x[1] | |
NoConvergence = libmp.NoConvergence | |
def _get_prec(ctx): return 53 | |
def _set_prec(ctx, p): return | |
def _get_dps(ctx): return 15 | |
def _set_dps(ctx, p): return | |
_fixed_precision = True | |
prec = property(_get_prec, _set_prec) | |
dps = property(_get_dps, _set_dps) | |
zero = 0.0 | |
one = 1.0 | |
eps = math2.EPS | |
inf = math2.INF | |
ninf = math2.NINF | |
nan = math2.NAN | |
j = 1j | |
# Called by SpecialFunctions.__init__() | |
def _wrap_specfun(cls, name, f, wrap): | |
if wrap: | |
def f_wrapped(ctx, *args, **kwargs): | |
convert = ctx.convert | |
args = [convert(a) for a in args] | |
return f(ctx, *args, **kwargs) | |
else: | |
f_wrapped = f | |
f_wrapped.__doc__ = function_docs.__dict__.get(name, f.__doc__) | |
setattr(cls, name, f_wrapped) | |
def bernoulli(ctx, n): | |
cache = ctx._bernoulli_cache | |
if n in cache: | |
return cache[n] | |
cache[n] = to_float(mpf_bernoulli(n, 53, 'n'), strict=True) | |
return cache[n] | |
pi = math2.pi | |
e = math2.e | |
euler = math2.euler | |
sqrt2 = 1.4142135623730950488 | |
sqrt5 = 2.2360679774997896964 | |
phi = 1.6180339887498948482 | |
ln2 = 0.69314718055994530942 | |
ln10 = 2.302585092994045684 | |
euler = 0.57721566490153286061 | |
catalan = 0.91596559417721901505 | |
khinchin = 2.6854520010653064453 | |
apery = 1.2020569031595942854 | |
glaisher = 1.2824271291006226369 | |
absmin = absmax = abs | |
def is_special(ctx, x): | |
return x - x != 0.0 | |
def isnan(ctx, x): | |
return x != x | |
def isinf(ctx, x): | |
return abs(x) == math2.INF | |
def isnormal(ctx, x): | |
if x: | |
return x - x == 0.0 | |
return False | |
def isnpint(ctx, x): | |
if type(x) is complex: | |
if x.imag: | |
return False | |
x = x.real | |
return x <= 0.0 and round(x) == x | |
mpf = float | |
mpc = complex | |
def convert(ctx, x): | |
try: | |
return float(x) | |
except: | |
return complex(x) | |
power = staticmethod(math2.pow) | |
sqrt = staticmethod(math2.sqrt) | |
exp = staticmethod(math2.exp) | |
ln = log = staticmethod(math2.log) | |
cos = staticmethod(math2.cos) | |
sin = staticmethod(math2.sin) | |
tan = staticmethod(math2.tan) | |
cos_sin = staticmethod(math2.cos_sin) | |
acos = staticmethod(math2.acos) | |
asin = staticmethod(math2.asin) | |
atan = staticmethod(math2.atan) | |
cosh = staticmethod(math2.cosh) | |
sinh = staticmethod(math2.sinh) | |
tanh = staticmethod(math2.tanh) | |
gamma = staticmethod(math2.gamma) | |
rgamma = staticmethod(math2.rgamma) | |
fac = factorial = staticmethod(math2.factorial) | |
floor = staticmethod(math2.floor) | |
ceil = staticmethod(math2.ceil) | |
cospi = staticmethod(math2.cospi) | |
sinpi = staticmethod(math2.sinpi) | |
cbrt = staticmethod(math2.cbrt) | |
_nthroot = staticmethod(math2.nthroot) | |
_ei = staticmethod(math2.ei) | |
_e1 = staticmethod(math2.e1) | |
_zeta = _zeta_int = staticmethod(math2.zeta) | |
# XXX: math2 | |
def arg(ctx, z): | |
z = complex(z) | |
return math.atan2(z.imag, z.real) | |
def expj(ctx, x): | |
return ctx.exp(ctx.j*x) | |
def expjpi(ctx, x): | |
return ctx.exp(ctx.j*ctx.pi*x) | |
ldexp = math.ldexp | |
frexp = math.frexp | |
def mag(ctx, z): | |
if z: | |
return ctx.frexp(abs(z))[1] | |
return ctx.ninf | |
def isint(ctx, z): | |
if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5 | |
if z.imag: | |
return False | |
z = z.real | |
try: | |
return z == int(z) | |
except: | |
return False | |
def nint_distance(ctx, z): | |
if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5 | |
n = round(z.real) | |
else: | |
n = round(z) | |
if n == z: | |
return n, ctx.ninf | |
return n, ctx.mag(abs(z-n)) | |
def _convert_param(ctx, z): | |
if type(z) is tuple: | |
p, q = z | |
return ctx.mpf(p) / q, 'R' | |
if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5 | |
intz = int(z.real) | |
else: | |
intz = int(z) | |
if z == intz: | |
return intz, 'Z' | |
return z, 'R' | |
def _is_real_type(ctx, z): | |
return isinstance(z, float) or isinstance(z, int_types) | |
def _is_complex_type(ctx, z): | |
return isinstance(z, complex) | |
def hypsum(ctx, p, q, types, coeffs, z, maxterms=6000, **kwargs): | |
coeffs = list(coeffs) | |
num = range(p) | |
den = range(p,p+q) | |
tol = ctx.eps | |
s = t = 1.0 | |
k = 0 | |
while 1: | |
for i in num: t *= (coeffs[i]+k) | |
for i in den: t /= (coeffs[i]+k) | |
k += 1; t /= k; t *= z; s += t | |
if abs(t) < tol: | |
return s | |
if k > maxterms: | |
raise ctx.NoConvergence | |
def atan2(ctx, x, y): | |
return math.atan2(x, y) | |
def psi(ctx, m, z): | |
m = int(m) | |
if m == 0: | |
return ctx.digamma(z) | |
return (-1)**(m+1) * ctx.fac(m) * ctx.zeta(m+1, z) | |
digamma = staticmethod(math2.digamma) | |
def harmonic(ctx, x): | |
x = ctx.convert(x) | |
if x == 0 or x == 1: | |
return x | |
return ctx.digamma(x+1) + ctx.euler | |
nstr = str | |
def to_fixed(ctx, x, prec): | |
return int(math.ldexp(x, prec)) | |
def rand(ctx): | |
import random | |
return random.random() | |
_erf = staticmethod(math2.erf) | |
_erfc = staticmethod(math2.erfc) | |
def sum_accurately(ctx, terms, check_step=1): | |
s = ctx.zero | |
k = 0 | |
for term in terms(): | |
s += term | |
if (not k % check_step) and term: | |
if abs(term) <= 1e-18*abs(s): | |
break | |
k += 1 | |
return s | |