shomez commited on
Commit
101cd2b
·
verified ·
1 Parent(s): 7060677

Upload ctx_mp.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. ctx_mp.py +1339 -0
ctx_mp.py ADDED
@@ -0,0 +1,1339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This module defines the mpf, mpc classes, and standard functions for
3
+ operating with them.
4
+ """
5
+ __docformat__ = 'plaintext'
6
+
7
+ import functools
8
+
9
+ import re
10
+
11
+ from .ctx_base import StandardBaseContext
12
+
13
+ from .libmp.backend import basestring, BACKEND
14
+
15
+ from . import libmp
16
+
17
+ from .libmp import (MPZ, MPZ_ZERO, MPZ_ONE, int_types, repr_dps,
18
+ round_floor, round_ceiling, dps_to_prec, round_nearest, prec_to_dps,
19
+ ComplexResult, to_pickable, from_pickable, normalize,
20
+ from_int, from_float, from_str, to_int, to_float, to_str,
21
+ from_rational, from_man_exp,
22
+ fone, fzero, finf, fninf, fnan,
23
+ mpf_abs, mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul, mpf_mul_int,
24
+ mpf_div, mpf_rdiv_int, mpf_pow_int, mpf_mod,
25
+ mpf_eq, mpf_cmp, mpf_lt, mpf_gt, mpf_le, mpf_ge,
26
+ mpf_hash, mpf_rand,
27
+ mpf_sum,
28
+ bitcount, to_fixed,
29
+ mpc_to_str,
30
+ mpc_to_complex, mpc_hash, mpc_pos, mpc_is_nonzero, mpc_neg, mpc_conjugate,
31
+ mpc_abs, mpc_add, mpc_add_mpf, mpc_sub, mpc_sub_mpf, mpc_mul, mpc_mul_mpf,
32
+ mpc_mul_int, mpc_div, mpc_div_mpf, mpc_pow, mpc_pow_mpf, mpc_pow_int,
33
+ mpc_mpf_div,
34
+ mpf_pow,
35
+ mpf_pi, mpf_degree, mpf_e, mpf_phi, mpf_ln2, mpf_ln10,
36
+ mpf_euler, mpf_catalan, mpf_apery, mpf_khinchin,
37
+ mpf_glaisher, mpf_twinprime, mpf_mertens,
38
+ int_types)
39
+
40
+ from . import function_docs
41
+ from . import rational
42
+
43
+ new = object.__new__
44
+
45
+ get_complex = re.compile(r'^\(?(?P<re>[\+\-]?\d*(\.\d*)?(e[\+\-]?\d+)?)??'
46
+ r'(?P<im>[\+\-]?\d*(\.\d*)?(e[\+\-]?\d+)?j)?\)?$')
47
+
48
+ if BACKEND == 'sage':
49
+ from sage.libs.mpmath.ext_main import Context as BaseMPContext
50
+ # pickle hack
51
+ import sage.libs.mpmath.ext_main as _mpf_module
52
+ else:
53
+ from .ctx_mp_python import PythonMPContext as BaseMPContext
54
+ from . import ctx_mp_python as _mpf_module
55
+
56
+ from .ctx_mp_python import _mpf, _mpc, mpnumeric
57
+
58
+ class MPContext(BaseMPContext, StandardBaseContext):
59
+ """
60
+ Context for multiprecision arithmetic with a global precision.
61
+ """
62
+
63
+ def __init__(ctx):
64
+ BaseMPContext.__init__(ctx)
65
+ ctx.trap_complex = False
66
+ ctx.pretty = False
67
+ ctx.types = [ctx.mpf, ctx.mpc, ctx.constant]
68
+ ctx._mpq = rational.mpq
69
+ ctx.default()
70
+ StandardBaseContext.__init__(ctx)
71
+
72
+ ctx.mpq = rational.mpq
73
+ ctx.init_builtins()
74
+
75
+ ctx.hyp_summators = {}
76
+
77
+ ctx._init_aliases()
78
+
79
+ # XXX: automate
80
+ try:
81
+ ctx.bernoulli.im_func.func_doc = function_docs.bernoulli
82
+ ctx.primepi.im_func.func_doc = function_docs.primepi
83
+ ctx.psi.im_func.func_doc = function_docs.psi
84
+ ctx.atan2.im_func.func_doc = function_docs.atan2
85
+ except AttributeError:
86
+ # python 3
87
+ ctx.bernoulli.__func__.func_doc = function_docs.bernoulli
88
+ ctx.primepi.__func__.func_doc = function_docs.primepi
89
+ ctx.psi.__func__.func_doc = function_docs.psi
90
+ ctx.atan2.__func__.func_doc = function_docs.atan2
91
+
92
+ ctx.digamma.func_doc = function_docs.digamma
93
+ ctx.cospi.func_doc = function_docs.cospi
94
+ ctx.sinpi.func_doc = function_docs.sinpi
95
+
96
+ def init_builtins(ctx):
97
+
98
+ mpf = ctx.mpf
99
+ mpc = ctx.mpc
100
+
101
+ # Exact constants
102
+ ctx.one = ctx.make_mpf(fone)
103
+ ctx.zero = ctx.make_mpf(fzero)
104
+ ctx.j = ctx.make_mpc((fzero,fone))
105
+ ctx.inf = ctx.make_mpf(finf)
106
+ ctx.ninf = ctx.make_mpf(fninf)
107
+ ctx.nan = ctx.make_mpf(fnan)
108
+
109
+ eps = ctx.constant(lambda prec, rnd: (0, MPZ_ONE, 1-prec, 1),
110
+ "epsilon of working precision", "eps")
111
+ ctx.eps = eps
112
+
113
+ # Approximate constants
114
+ ctx.pi = ctx.constant(mpf_pi, "pi", "pi")
115
+ ctx.ln2 = ctx.constant(mpf_ln2, "ln(2)", "ln2")
116
+ ctx.ln10 = ctx.constant(mpf_ln10, "ln(10)", "ln10")
117
+ ctx.phi = ctx.constant(mpf_phi, "Golden ratio phi", "phi")
118
+ ctx.e = ctx.constant(mpf_e, "e = exp(1)", "e")
119
+ ctx.euler = ctx.constant(mpf_euler, "Euler's constant", "euler")
120
+ ctx.catalan = ctx.constant(mpf_catalan, "Catalan's constant", "catalan")
121
+ ctx.khinchin = ctx.constant(mpf_khinchin, "Khinchin's constant", "khinchin")
122
+ ctx.glaisher = ctx.constant(mpf_glaisher, "Glaisher's constant", "glaisher")
123
+ ctx.apery = ctx.constant(mpf_apery, "Apery's constant", "apery")
124
+ ctx.degree = ctx.constant(mpf_degree, "1 deg = pi / 180", "degree")
125
+ ctx.twinprime = ctx.constant(mpf_twinprime, "Twin prime constant", "twinprime")
126
+ ctx.mertens = ctx.constant(mpf_mertens, "Mertens' constant", "mertens")
127
+
128
+ # Standard functions
129
+ ctx.sqrt = ctx._wrap_libmp_function(libmp.mpf_sqrt, libmp.mpc_sqrt)
130
+ ctx.cbrt = ctx._wrap_libmp_function(libmp.mpf_cbrt, libmp.mpc_cbrt)
131
+ ctx.ln = ctx._wrap_libmp_function(libmp.mpf_log, libmp.mpc_log)
132
+ ctx.atan = ctx._wrap_libmp_function(libmp.mpf_atan, libmp.mpc_atan)
133
+ ctx.exp = ctx._wrap_libmp_function(libmp.mpf_exp, libmp.mpc_exp)
134
+ ctx.expj = ctx._wrap_libmp_function(libmp.mpf_expj, libmp.mpc_expj)
135
+ ctx.expjpi = ctx._wrap_libmp_function(libmp.mpf_expjpi, libmp.mpc_expjpi)
136
+ ctx.sin = ctx._wrap_libmp_function(libmp.mpf_sin, libmp.mpc_sin)
137
+ ctx.cos = ctx._wrap_libmp_function(libmp.mpf_cos, libmp.mpc_cos)
138
+ ctx.tan = ctx._wrap_libmp_function(libmp.mpf_tan, libmp.mpc_tan)
139
+ ctx.sinh = ctx._wrap_libmp_function(libmp.mpf_sinh, libmp.mpc_sinh)
140
+ ctx.cosh = ctx._wrap_libmp_function(libmp.mpf_cosh, libmp.mpc_cosh)
141
+ ctx.tanh = ctx._wrap_libmp_function(libmp.mpf_tanh, libmp.mpc_tanh)
142
+ ctx.asin = ctx._wrap_libmp_function(libmp.mpf_asin, libmp.mpc_asin)
143
+ ctx.acos = ctx._wrap_libmp_function(libmp.mpf_acos, libmp.mpc_acos)
144
+ ctx.atan = ctx._wrap_libmp_function(libmp.mpf_atan, libmp.mpc_atan)
145
+ ctx.asinh = ctx._wrap_libmp_function(libmp.mpf_asinh, libmp.mpc_asinh)
146
+ ctx.acosh = ctx._wrap_libmp_function(libmp.mpf_acosh, libmp.mpc_acosh)
147
+ ctx.atanh = ctx._wrap_libmp_function(libmp.mpf_atanh, libmp.mpc_atanh)
148
+ ctx.sinpi = ctx._wrap_libmp_function(libmp.mpf_sin_pi, libmp.mpc_sin_pi)
149
+ ctx.cospi = ctx._wrap_libmp_function(libmp.mpf_cos_pi, libmp.mpc_cos_pi)
150
+ ctx.floor = ctx._wrap_libmp_function(libmp.mpf_floor, libmp.mpc_floor)
151
+ ctx.ceil = ctx._wrap_libmp_function(libmp.mpf_ceil, libmp.mpc_ceil)
152
+ ctx.nint = ctx._wrap_libmp_function(libmp.mpf_nint, libmp.mpc_nint)
153
+ ctx.frac = ctx._wrap_libmp_function(libmp.mpf_frac, libmp.mpc_frac)
154
+ ctx.fib = ctx.fibonacci = ctx._wrap_libmp_function(libmp.mpf_fibonacci, libmp.mpc_fibonacci)
155
+
156
+ ctx.gamma = ctx._wrap_libmp_function(libmp.mpf_gamma, libmp.mpc_gamma)
157
+ ctx.rgamma = ctx._wrap_libmp_function(libmp.mpf_rgamma, libmp.mpc_rgamma)
158
+ ctx.loggamma = ctx._wrap_libmp_function(libmp.mpf_loggamma, libmp.mpc_loggamma)
159
+ ctx.fac = ctx.factorial = ctx._wrap_libmp_function(libmp.mpf_factorial, libmp.mpc_factorial)
160
+
161
+ ctx.digamma = ctx._wrap_libmp_function(libmp.mpf_psi0, libmp.mpc_psi0)
162
+ ctx.harmonic = ctx._wrap_libmp_function(libmp.mpf_harmonic, libmp.mpc_harmonic)
163
+ ctx.ei = ctx._wrap_libmp_function(libmp.mpf_ei, libmp.mpc_ei)
164
+ ctx.e1 = ctx._wrap_libmp_function(libmp.mpf_e1, libmp.mpc_e1)
165
+ ctx._ci = ctx._wrap_libmp_function(libmp.mpf_ci, libmp.mpc_ci)
166
+ ctx._si = ctx._wrap_libmp_function(libmp.mpf_si, libmp.mpc_si)
167
+ ctx.ellipk = ctx._wrap_libmp_function(libmp.mpf_ellipk, libmp.mpc_ellipk)
168
+ ctx._ellipe = ctx._wrap_libmp_function(libmp.mpf_ellipe, libmp.mpc_ellipe)
169
+ ctx.agm1 = ctx._wrap_libmp_function(libmp.mpf_agm1, libmp.mpc_agm1)
170
+ ctx._erf = ctx._wrap_libmp_function(libmp.mpf_erf, None)
171
+ ctx._erfc = ctx._wrap_libmp_function(libmp.mpf_erfc, None)
172
+ ctx._zeta = ctx._wrap_libmp_function(libmp.mpf_zeta, libmp.mpc_zeta)
173
+ ctx._altzeta = ctx._wrap_libmp_function(libmp.mpf_altzeta, libmp.mpc_altzeta)
174
+
175
+ # Faster versions
176
+ ctx.sqrt = getattr(ctx, "_sage_sqrt", ctx.sqrt)
177
+ ctx.exp = getattr(ctx, "_sage_exp", ctx.exp)
178
+ ctx.ln = getattr(ctx, "_sage_ln", ctx.ln)
179
+ ctx.cos = getattr(ctx, "_sage_cos", ctx.cos)
180
+ ctx.sin = getattr(ctx, "_sage_sin", ctx.sin)
181
+
182
+ def to_fixed(ctx, x, prec):
183
+ return x.to_fixed(prec)
184
+
185
+ def hypot(ctx, x, y):
186
+ r"""
187
+ Computes the Euclidean norm of the vector `(x, y)`, equal
188
+ to `\sqrt{x^2 + y^2}`. Both `x` and `y` must be real."""
189
+ x = ctx.convert(x)
190
+ y = ctx.convert(y)
191
+ return ctx.make_mpf(libmp.mpf_hypot(x._mpf_, y._mpf_, *ctx._prec_rounding))
192
+
193
+ def _gamma_upper_int(ctx, n, z):
194
+ n = int(ctx._re(n))
195
+ if n == 0:
196
+ return ctx.e1(z)
197
+ if not hasattr(z, '_mpf_'):
198
+ raise NotImplementedError
199
+ prec, rounding = ctx._prec_rounding
200
+ real, imag = libmp.mpf_expint(n, z._mpf_, prec, rounding, gamma=True)
201
+ if imag is None:
202
+ return ctx.make_mpf(real)
203
+ else:
204
+ return ctx.make_mpc((real, imag))
205
+
206
+ def _expint_int(ctx, n, z):
207
+ n = int(n)
208
+ if n == 1:
209
+ return ctx.e1(z)
210
+ if not hasattr(z, '_mpf_'):
211
+ raise NotImplementedError
212
+ prec, rounding = ctx._prec_rounding
213
+ real, imag = libmp.mpf_expint(n, z._mpf_, prec, rounding)
214
+ if imag is None:
215
+ return ctx.make_mpf(real)
216
+ else:
217
+ return ctx.make_mpc((real, imag))
218
+
219
+ def _nthroot(ctx, x, n):
220
+ if hasattr(x, '_mpf_'):
221
+ try:
222
+ return ctx.make_mpf(libmp.mpf_nthroot(x._mpf_, n, *ctx._prec_rounding))
223
+ except ComplexResult:
224
+ if ctx.trap_complex:
225
+ raise
226
+ x = (x._mpf_, libmp.fzero)
227
+ else:
228
+ x = x._mpc_
229
+ return ctx.make_mpc(libmp.mpc_nthroot(x, n, *ctx._prec_rounding))
230
+
231
+ def _besselj(ctx, n, z):
232
+ prec, rounding = ctx._prec_rounding
233
+ if hasattr(z, '_mpf_'):
234
+ return ctx.make_mpf(libmp.mpf_besseljn(n, z._mpf_, prec, rounding))
235
+ elif hasattr(z, '_mpc_'):
236
+ return ctx.make_mpc(libmp.mpc_besseljn(n, z._mpc_, prec, rounding))
237
+
238
+ def _agm(ctx, a, b=1):
239
+ prec, rounding = ctx._prec_rounding
240
+ if hasattr(a, '_mpf_') and hasattr(b, '_mpf_'):
241
+ try:
242
+ v = libmp.mpf_agm(a._mpf_, b._mpf_, prec, rounding)
243
+ return ctx.make_mpf(v)
244
+ except ComplexResult:
245
+ pass
246
+ if hasattr(a, '_mpf_'): a = (a._mpf_, libmp.fzero)
247
+ else: a = a._mpc_
248
+ if hasattr(b, '_mpf_'): b = (b._mpf_, libmp.fzero)
249
+ else: b = b._mpc_
250
+ return ctx.make_mpc(libmp.mpc_agm(a, b, prec, rounding))
251
+
252
+ def bernoulli(ctx, n):
253
+ return ctx.make_mpf(libmp.mpf_bernoulli(int(n), *ctx._prec_rounding))
254
+
255
+ def _zeta_int(ctx, n):
256
+ return ctx.make_mpf(libmp.mpf_zeta_int(int(n), *ctx._prec_rounding))
257
+
258
+ def atan2(ctx, y, x):
259
+ x = ctx.convert(x)
260
+ y = ctx.convert(y)
261
+ return ctx.make_mpf(libmp.mpf_atan2(y._mpf_, x._mpf_, *ctx._prec_rounding))
262
+
263
+ def psi(ctx, m, z):
264
+ z = ctx.convert(z)
265
+ m = int(m)
266
+ if ctx._is_real_type(z):
267
+ return ctx.make_mpf(libmp.mpf_psi(m, z._mpf_, *ctx._prec_rounding))
268
+ else:
269
+ return ctx.make_mpc(libmp.mpc_psi(m, z._mpc_, *ctx._prec_rounding))
270
+
271
+ def cos_sin(ctx, x, **kwargs):
272
+ if type(x) not in ctx.types:
273
+ x = ctx.convert(x)
274
+ prec, rounding = ctx._parse_prec(kwargs)
275
+ if hasattr(x, '_mpf_'):
276
+ c, s = libmp.mpf_cos_sin(x._mpf_, prec, rounding)
277
+ return ctx.make_mpf(c), ctx.make_mpf(s)
278
+ elif hasattr(x, '_mpc_'):
279
+ c, s = libmp.mpc_cos_sin(x._mpc_, prec, rounding)
280
+ return ctx.make_mpc(c), ctx.make_mpc(s)
281
+ else:
282
+ return ctx.cos(x, **kwargs), ctx.sin(x, **kwargs)
283
+
284
+ def cospi_sinpi(ctx, x, **kwargs):
285
+ if type(x) not in ctx.types:
286
+ x = ctx.convert(x)
287
+ prec, rounding = ctx._parse_prec(kwargs)
288
+ if hasattr(x, '_mpf_'):
289
+ c, s = libmp.mpf_cos_sin_pi(x._mpf_, prec, rounding)
290
+ return ctx.make_mpf(c), ctx.make_mpf(s)
291
+ elif hasattr(x, '_mpc_'):
292
+ c, s = libmp.mpc_cos_sin_pi(x._mpc_, prec, rounding)
293
+ return ctx.make_mpc(c), ctx.make_mpc(s)
294
+ else:
295
+ return ctx.cos(x, **kwargs), ctx.sin(x, **kwargs)
296
+
297
+ def clone(ctx):
298
+ """
299
+ Create a copy of the context, with the same working precision.
300
+ """
301
+ a = ctx.__class__()
302
+ a.prec = ctx.prec
303
+ return a
304
+
305
+ # Several helper methods
306
+ # TODO: add more of these, make consistent, write docstrings, ...
307
+
308
+ def _is_real_type(ctx, x):
309
+ if hasattr(x, '_mpc_') or type(x) is complex:
310
+ return False
311
+ return True
312
+
313
+ def _is_complex_type(ctx, x):
314
+ if hasattr(x, '_mpc_') or type(x) is complex:
315
+ return True
316
+ return False
317
+
318
+ def isnan(ctx, x):
319
+ """
320
+ Return *True* if *x* is a NaN (not-a-number), or for a complex
321
+ number, whether either the real or complex part is NaN;
322
+ otherwise return *False*::
323
+
324
+ >>> from mpmath import *
325
+ >>> isnan(3.14)
326
+ False
327
+ >>> isnan(nan)
328
+ True
329
+ >>> isnan(mpc(3.14,2.72))
330
+ False
331
+ >>> isnan(mpc(3.14,nan))
332
+ True
333
+
334
+ """
335
+ if hasattr(x, "_mpf_"):
336
+ return x._mpf_ == fnan
337
+ if hasattr(x, "_mpc_"):
338
+ return fnan in x._mpc_
339
+ if isinstance(x, int_types) or isinstance(x, rational.mpq):
340
+ return False
341
+ x = ctx.convert(x)
342
+ if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
343
+ return ctx.isnan(x)
344
+ raise TypeError("isnan() needs a number as input")
345
+
346
+ def isfinite(ctx, x):
347
+ """
348
+ Return *True* if *x* is a finite number, i.e. neither
349
+ an infinity or a NaN.
350
+
351
+ >>> from mpmath import *
352
+ >>> isfinite(inf)
353
+ False
354
+ >>> isfinite(-inf)
355
+ False
356
+ >>> isfinite(3)
357
+ True
358
+ >>> isfinite(nan)
359
+ False
360
+ >>> isfinite(3+4j)
361
+ True
362
+ >>> isfinite(mpc(3,inf))
363
+ False
364
+ >>> isfinite(mpc(nan,3))
365
+ False
366
+
367
+ """
368
+ if ctx.isinf(x) or ctx.isnan(x):
369
+ return False
370
+ return True
371
+
372
+ def isnpint(ctx, x):
373
+ """
374
+ Determine if *x* is a nonpositive integer.
375
+ """
376
+ if not x:
377
+ return True
378
+ if hasattr(x, '_mpf_'):
379
+ sign, man, exp, bc = x._mpf_
380
+ return sign and exp >= 0
381
+ if hasattr(x, '_mpc_'):
382
+ return not x.imag and ctx.isnpint(x.real)
383
+ if type(x) in int_types:
384
+ return x <= 0
385
+ if isinstance(x, ctx.mpq):
386
+ p, q = x._mpq_
387
+ if not p:
388
+ return True
389
+ return q == 1 and p <= 0
390
+ return ctx.isnpint(ctx.convert(x))
391
+
392
+ def __str__(ctx):
393
+ lines = ["Mpmath settings:",
394
+ (" mp.prec = %s" % ctx.prec).ljust(30) + "[default: 53]",
395
+ (" mp.dps = %s" % ctx.dps).ljust(30) + "[default: 15]",
396
+ (" mp.trap_complex = %s" % ctx.trap_complex).ljust(30) + "[default: False]",
397
+ ]
398
+ return "\n".join(lines)
399
+
400
+ @property
401
+ def _repr_digits(ctx):
402
+ return repr_dps(ctx._prec)
403
+
404
+ @property
405
+ def _str_digits(ctx):
406
+ return ctx._dps
407
+
408
+ def extraprec(ctx, n, normalize_output=False):
409
+ """
410
+ The block
411
+
412
+ with extraprec(n):
413
+ <code>
414
+
415
+ increases the precision n bits, executes <code>, and then
416
+ restores the precision.
417
+
418
+ extraprec(n)(f) returns a decorated version of the function f
419
+ that increases the working precision by n bits before execution,
420
+ and restores the parent precision afterwards. With
421
+ normalize_output=True, it rounds the return value to the parent
422
+ precision.
423
+ """
424
+ return PrecisionManager(ctx, lambda p: p + n, None, normalize_output)
425
+
426
+ def extradps(ctx, n, normalize_output=False):
427
+ """
428
+ This function is analogous to extraprec (see documentation)
429
+ but changes the decimal precision instead of the number of bits.
430
+ """
431
+ return PrecisionManager(ctx, None, lambda d: d + n, normalize_output)
432
+
433
+ def workprec(ctx, n, normalize_output=False):
434
+ """
435
+ The block
436
+
437
+ with workprec(n):
438
+ <code>
439
+
440
+ sets the precision to n bits, executes <code>, and then restores
441
+ the precision.
442
+
443
+ workprec(n)(f) returns a decorated version of the function f
444
+ that sets the precision to n bits before execution,
445
+ and restores the precision afterwards. With normalize_output=True,
446
+ it rounds the return value to the parent precision.
447
+ """
448
+ return PrecisionManager(ctx, lambda p: n, None, normalize_output)
449
+
450
+ def workdps(ctx, n, normalize_output=False):
451
+ """
452
+ This function is analogous to workprec (see documentation)
453
+ but changes the decimal precision instead of the number of bits.
454
+ """
455
+ return PrecisionManager(ctx, None, lambda d: n, normalize_output)
456
+
457
+ def autoprec(ctx, f, maxprec=None, catch=(), verbose=False):
458
+ r"""
459
+ Return a wrapped copy of *f* that repeatedly evaluates *f*
460
+ with increasing precision until the result converges to the
461
+ full precision used at the point of the call.
462
+
463
+ This heuristically protects against rounding errors, at the cost of
464
+ roughly a 2x slowdown compared to manually setting the optimal
465
+ precision. This method can, however, easily be fooled if the results
466
+ from *f* depend "discontinuously" on the precision, for instance
467
+ if catastrophic cancellation can occur. Therefore, :func:`~mpmath.autoprec`
468
+ should be used judiciously.
469
+
470
+ **Examples**
471
+
472
+ Many functions are sensitive to perturbations of the input arguments.
473
+ If the arguments are decimal numbers, they may have to be converted
474
+ to binary at a much higher precision. If the amount of required
475
+ extra precision is unknown, :func:`~mpmath.autoprec` is convenient::
476
+
477
+ >>> from mpmath import *
478
+ >>> mp.dps = 15
479
+ >>> mp.pretty = True
480
+ >>> besselj(5, 125 * 10**28) # Exact input
481
+ -8.03284785591801e-17
482
+ >>> besselj(5, '1.25e30') # Bad
483
+ 7.12954868316652e-16
484
+ >>> autoprec(besselj)(5, '1.25e30') # Good
485
+ -8.03284785591801e-17
486
+
487
+ The following fails to converge because `\sin(\pi) = 0` whereas all
488
+ finite-precision approximations of `\pi` give nonzero values::
489
+
490
+ >>> autoprec(sin)(pi) # doctest: +IGNORE_EXCEPTION_DETAIL
491
+ Traceback (most recent call last):
492
+ ...
493
+ NoConvergence: autoprec: prec increased to 2910 without convergence
494
+
495
+ As the following example shows, :func:`~mpmath.autoprec` can protect against
496
+ cancellation, but is fooled by too severe cancellation::
497
+
498
+ >>> x = 1e-10
499
+ >>> exp(x)-1; expm1(x); autoprec(lambda t: exp(t)-1)(x)
500
+ 1.00000008274037e-10
501
+ 1.00000000005e-10
502
+ 1.00000000005e-10
503
+ >>> x = 1e-50
504
+ >>> exp(x)-1; expm1(x); autoprec(lambda t: exp(t)-1)(x)
505
+ 0.0
506
+ 1.0e-50
507
+ 0.0
508
+
509
+ With *catch*, an exception or list of exceptions to intercept
510
+ may be specified. The raised exception is interpreted
511
+ as signaling insufficient precision. This permits, for example,
512
+ evaluating a function where a too low precision results in a
513
+ division by zero::
514
+
515
+ >>> f = lambda x: 1/(exp(x)-1)
516
+ >>> f(1e-30)
517
+ Traceback (most recent call last):
518
+ ...
519
+ ZeroDivisionError
520
+ >>> autoprec(f, catch=ZeroDivisionError)(1e-30)
521
+ 1.0e+30
522
+
523
+
524
+ """
525
+ def f_autoprec_wrapped(*args, **kwargs):
526
+ prec = ctx.prec
527
+ if maxprec is None:
528
+ maxprec2 = ctx._default_hyper_maxprec(prec)
529
+ else:
530
+ maxprec2 = maxprec
531
+ try:
532
+ ctx.prec = prec + 10
533
+ try:
534
+ v1 = f(*args, **kwargs)
535
+ except catch:
536
+ v1 = ctx.nan
537
+ prec2 = prec + 20
538
+ while 1:
539
+ ctx.prec = prec2
540
+ try:
541
+ v2 = f(*args, **kwargs)
542
+ except catch:
543
+ v2 = ctx.nan
544
+ if v1 == v2:
545
+ break
546
+ err = ctx.mag(v2-v1) - ctx.mag(v2)
547
+ if err < (-prec):
548
+ break
549
+ if verbose:
550
+ print("autoprec: target=%s, prec=%s, accuracy=%s" \
551
+ % (prec, prec2, -err))
552
+ v1 = v2
553
+ if prec2 >= maxprec2:
554
+ raise ctx.NoConvergence(\
555
+ "autoprec: prec increased to %i without convergence"\
556
+ % prec2)
557
+ prec2 += int(prec2*2)
558
+ prec2 = min(prec2, maxprec2)
559
+ finally:
560
+ ctx.prec = prec
561
+ return +v2
562
+ return f_autoprec_wrapped
563
+
564
+ def nstr(ctx, x, n=6, **kwargs):
565
+ """
566
+ Convert an ``mpf`` or ``mpc`` to a decimal string literal with *n*
567
+ significant digits. The small default value for *n* is chosen to
568
+ make this function useful for printing collections of numbers
569
+ (lists, matrices, etc).
570
+
571
+ If *x* is a list or tuple, :func:`~mpmath.nstr` is applied recursively
572
+ to each element. For unrecognized classes, :func:`~mpmath.nstr`
573
+ simply returns ``str(x)``.
574
+
575
+ The companion function :func:`~mpmath.nprint` prints the result
576
+ instead of returning it.
577
+
578
+ The keyword arguments *strip_zeros*, *min_fixed*, *max_fixed*
579
+ and *show_zero_exponent* are forwarded to :func:`~mpmath.libmp.to_str`.
580
+
581
+ The number will be printed in fixed-point format if the position
582
+ of the leading digit is strictly between min_fixed
583
+ (default = min(-dps/3,-5)) and max_fixed (default = dps).
584
+
585
+ To force fixed-point format always, set min_fixed = -inf,
586
+ max_fixed = +inf. To force floating-point format, set
587
+ min_fixed >= max_fixed.
588
+
589
+ >>> from mpmath import *
590
+ >>> nstr([+pi, ldexp(1,-500)])
591
+ '[3.14159, 3.05494e-151]'
592
+ >>> nprint([+pi, ldexp(1,-500)])
593
+ [3.14159, 3.05494e-151]
594
+ >>> nstr(mpf("5e-10"), 5)
595
+ '5.0e-10'
596
+ >>> nstr(mpf("5e-10"), 5, strip_zeros=False)
597
+ '5.0000e-10'
598
+ >>> nstr(mpf("5e-10"), 5, strip_zeros=False, min_fixed=-11)
599
+ '0.00000000050000'
600
+ >>> nstr(mpf(0), 5, show_zero_exponent=True)
601
+ '0.0e+0'
602
+
603
+ """
604
+ if isinstance(x, list):
605
+ return "[%s]" % (", ".join(ctx.nstr(c, n, **kwargs) for c in x))
606
+ if isinstance(x, tuple):
607
+ return "(%s)" % (", ".join(ctx.nstr(c, n, **kwargs) for c in x))
608
+ if hasattr(x, '_mpf_'):
609
+ return to_str(x._mpf_, n, **kwargs)
610
+ if hasattr(x, '_mpc_'):
611
+ return "(" + mpc_to_str(x._mpc_, n, **kwargs) + ")"
612
+ if isinstance(x, basestring):
613
+ return repr(x)
614
+ if isinstance(x, ctx.matrix):
615
+ return x.__nstr__(n, **kwargs)
616
+ return str(x)
617
+
618
+ def _convert_fallback(ctx, x, strings):
619
+ if strings and isinstance(x, basestring):
620
+ if 'j' in x.lower():
621
+ x = x.lower().replace(' ', '')
622
+ match = get_complex.match(x)
623
+ re = match.group('re')
624
+ if not re:
625
+ re = 0
626
+ im = match.group('im').rstrip('j')
627
+ return ctx.mpc(ctx.convert(re), ctx.convert(im))
628
+ if hasattr(x, "_mpi_"):
629
+ a, b = x._mpi_
630
+ if a == b:
631
+ return ctx.make_mpf(a)
632
+ else:
633
+ raise ValueError("can only create mpf from zero-width interval")
634
+ raise TypeError("cannot create mpf from " + repr(x))
635
+
636
+ def mpmathify(ctx, *args, **kwargs):
637
+ return ctx.convert(*args, **kwargs)
638
+
639
+ def _parse_prec(ctx, kwargs):
640
+ if kwargs:
641
+ if kwargs.get('exact'):
642
+ return 0, 'f'
643
+ prec, rounding = ctx._prec_rounding
644
+ if 'rounding' in kwargs:
645
+ rounding = kwargs['rounding']
646
+ if 'prec' in kwargs:
647
+ prec = kwargs['prec']
648
+ if prec == ctx.inf:
649
+ return 0, 'f'
650
+ else:
651
+ prec = int(prec)
652
+ elif 'dps' in kwargs:
653
+ dps = kwargs['dps']
654
+ if dps == ctx.inf:
655
+ return 0, 'f'
656
+ prec = dps_to_prec(dps)
657
+ return prec, rounding
658
+ return ctx._prec_rounding
659
+
660
+ _exact_overflow_msg = "the exact result does not fit in memory"
661
+
662
+ _hypsum_msg = """hypsum() failed to converge to the requested %i bits of accuracy
663
+ using a working precision of %i bits. Try with a higher maxprec,
664
+ maxterms, or set zeroprec."""
665
+
666
+ def hypsum(ctx, p, q, flags, coeffs, z, accurate_small=True, **kwargs):
667
+ if hasattr(z, "_mpf_"):
668
+ key = p, q, flags, 'R'
669
+ v = z._mpf_
670
+ elif hasattr(z, "_mpc_"):
671
+ key = p, q, flags, 'C'
672
+ v = z._mpc_
673
+ if key not in ctx.hyp_summators:
674
+ ctx.hyp_summators[key] = libmp.make_hyp_summator(key)[1]
675
+ summator = ctx.hyp_summators[key]
676
+ prec = ctx.prec
677
+ maxprec = kwargs.get('maxprec', ctx._default_hyper_maxprec(prec))
678
+ extraprec = 50
679
+ epsshift = 25
680
+ # Jumps in magnitude occur when parameters are close to negative
681
+ # integers. We must ensure that these terms are included in
682
+ # the sum and added accurately
683
+ magnitude_check = {}
684
+ max_total_jump = 0
685
+ for i, c in enumerate(coeffs):
686
+ if flags[i] == 'Z':
687
+ if i >= p and c <= 0:
688
+ ok = False
689
+ for ii, cc in enumerate(coeffs[:p]):
690
+ # Note: c <= cc or c < cc, depending on convention
691
+ if flags[ii] == 'Z' and cc <= 0 and c <= cc:
692
+ ok = True
693
+ if not ok:
694
+ raise ZeroDivisionError("pole in hypergeometric series")
695
+ continue
696
+ n, d = ctx.nint_distance(c)
697
+ n = -int(n)
698
+ d = -d
699
+ if i >= p and n >= 0 and d > 4:
700
+ if n in magnitude_check:
701
+ magnitude_check[n] += d
702
+ else:
703
+ magnitude_check[n] = d
704
+ extraprec = max(extraprec, d - prec + 60)
705
+ max_total_jump += abs(d)
706
+ while 1:
707
+ if extraprec > maxprec:
708
+ raise ValueError(ctx._hypsum_msg % (prec, prec+extraprec))
709
+ wp = prec + extraprec
710
+ if magnitude_check:
711
+ mag_dict = dict((n,None) for n in magnitude_check)
712
+ else:
713
+ mag_dict = {}
714
+ zv, have_complex, magnitude = summator(coeffs, v, prec, wp, \
715
+ epsshift, mag_dict, **kwargs)
716
+ cancel = -magnitude
717
+ jumps_resolved = True
718
+ if extraprec < max_total_jump:
719
+ for n in mag_dict.values():
720
+ if (n is None) or (n < prec):
721
+ jumps_resolved = False
722
+ break
723
+ accurate = (cancel < extraprec-25-5 or not accurate_small)
724
+ if jumps_resolved:
725
+ if accurate:
726
+ break
727
+ # zero?
728
+ zeroprec = kwargs.get('zeroprec')
729
+ if zeroprec is not None:
730
+ if cancel > zeroprec:
731
+ if have_complex:
732
+ return ctx.mpc(0)
733
+ else:
734
+ return ctx.zero
735
+
736
+ # Some near-singularities were not included, so increase
737
+ # precision and repeat until they are
738
+ extraprec *= 2
739
+ # Possible workaround for bad roundoff in fixed-point arithmetic
740
+ epsshift += 5
741
+ extraprec += 5
742
+
743
+ if type(zv) is tuple:
744
+ if have_complex:
745
+ return ctx.make_mpc(zv)
746
+ else:
747
+ return ctx.make_mpf(zv)
748
+ else:
749
+ return zv
750
+
751
+ def ldexp(ctx, x, n):
752
+ r"""
753
+ Computes `x 2^n` efficiently. No rounding is performed.
754
+ The argument `x` must be a real floating-point number (or
755
+ possible to convert into one) and `n` must be a Python ``int``.
756
+
757
+ >>> from mpmath import *
758
+ >>> mp.dps = 15; mp.pretty = False
759
+ >>> ldexp(1, 10)
760
+ mpf('1024.0')
761
+ >>> ldexp(1, -3)
762
+ mpf('0.125')
763
+
764
+ """
765
+ x = ctx.convert(x)
766
+ return ctx.make_mpf(libmp.mpf_shift(x._mpf_, n))
767
+
768
+ def frexp(ctx, x):
769
+ r"""
770
+ Given a real number `x`, returns `(y, n)` with `y \in [0.5, 1)`,
771
+ `n` a Python integer, and such that `x = y 2^n`. No rounding is
772
+ performed.
773
+
774
+ >>> from mpmath import *
775
+ >>> mp.dps = 15; mp.pretty = False
776
+ >>> frexp(7.5)
777
+ (mpf('0.9375'), 3)
778
+
779
+ """
780
+ x = ctx.convert(x)
781
+ y, n = libmp.mpf_frexp(x._mpf_)
782
+ return ctx.make_mpf(y), n
783
+
784
+ def fneg(ctx, x, **kwargs):
785
+ """
786
+ Negates the number *x*, giving a floating-point result, optionally
787
+ using a custom precision and rounding mode.
788
+
789
+ See the documentation of :func:`~mpmath.fadd` for a detailed description
790
+ of how to specify precision and rounding.
791
+
792
+ **Examples**
793
+
794
+ An mpmath number is returned::
795
+
796
+ >>> from mpmath import *
797
+ >>> mp.dps = 15; mp.pretty = False
798
+ >>> fneg(2.5)
799
+ mpf('-2.5')
800
+ >>> fneg(-5+2j)
801
+ mpc(real='5.0', imag='-2.0')
802
+
803
+ Precise control over rounding is possible::
804
+
805
+ >>> x = fadd(2, 1e-100, exact=True)
806
+ >>> fneg(x)
807
+ mpf('-2.0')
808
+ >>> fneg(x, rounding='f')
809
+ mpf('-2.0000000000000004')
810
+
811
+ Negating with and without roundoff::
812
+
813
+ >>> n = 200000000000000000000001
814
+ >>> print(int(-mpf(n)))
815
+ -200000000000000016777216
816
+ >>> print(int(fneg(n)))
817
+ -200000000000000016777216
818
+ >>> print(int(fneg(n, prec=log(n,2)+1)))
819
+ -200000000000000000000001
820
+ >>> print(int(fneg(n, dps=log(n,10)+1)))
821
+ -200000000000000000000001
822
+ >>> print(int(fneg(n, prec=inf)))
823
+ -200000000000000000000001
824
+ >>> print(int(fneg(n, dps=inf)))
825
+ -200000000000000000000001
826
+ >>> print(int(fneg(n, exact=True)))
827
+ -200000000000000000000001
828
+
829
+ """
830
+ prec, rounding = ctx._parse_prec(kwargs)
831
+ x = ctx.convert(x)
832
+ if hasattr(x, '_mpf_'):
833
+ return ctx.make_mpf(mpf_neg(x._mpf_, prec, rounding))
834
+ if hasattr(x, '_mpc_'):
835
+ return ctx.make_mpc(mpc_neg(x._mpc_, prec, rounding))
836
+ raise ValueError("Arguments need to be mpf or mpc compatible numbers")
837
+
838
+ def fadd(ctx, x, y, **kwargs):
839
+ """
840
+ Adds the numbers *x* and *y*, giving a floating-point result,
841
+ optionally using a custom precision and rounding mode.
842
+
843
+ The default precision is the working precision of the context.
844
+ You can specify a custom precision in bits by passing the *prec* keyword
845
+ argument, or by providing an equivalent decimal precision with the *dps*
846
+ keyword argument. If the precision is set to ``+inf``, or if the flag
847
+ *exact=True* is passed, an exact addition with no rounding is performed.
848
+
849
+ When the precision is finite, the optional *rounding* keyword argument
850
+ specifies the direction of rounding. Valid options are ``'n'`` for
851
+ nearest (default), ``'f'`` for floor, ``'c'`` for ceiling, ``'d'``
852
+ for down, ``'u'`` for up.
853
+
854
+ **Examples**
855
+
856
+ Using :func:`~mpmath.fadd` with precision and rounding control::
857
+
858
+ >>> from mpmath import *
859
+ >>> mp.dps = 15; mp.pretty = False
860
+ >>> fadd(2, 1e-20)
861
+ mpf('2.0')
862
+ >>> fadd(2, 1e-20, rounding='u')
863
+ mpf('2.0000000000000004')
864
+ >>> nprint(fadd(2, 1e-20, prec=100), 25)
865
+ 2.00000000000000000001
866
+ >>> nprint(fadd(2, 1e-20, dps=15), 25)
867
+ 2.0
868
+ >>> nprint(fadd(2, 1e-20, dps=25), 25)
869
+ 2.00000000000000000001
870
+ >>> nprint(fadd(2, 1e-20, exact=True), 25)
871
+ 2.00000000000000000001
872
+
873
+ Exact addition avoids cancellation errors, enforcing familiar laws
874
+ of numbers such as `x+y-x = y`, which don't hold in floating-point
875
+ arithmetic with finite precision::
876
+
877
+ >>> x, y = mpf(2), mpf('1e-1000')
878
+ >>> print(x + y - x)
879
+ 0.0
880
+ >>> print(fadd(x, y, prec=inf) - x)
881
+ 1.0e-1000
882
+ >>> print(fadd(x, y, exact=True) - x)
883
+ 1.0e-1000
884
+
885
+ Exact addition can be inefficient and may be impossible to perform
886
+ with large magnitude differences::
887
+
888
+ >>> fadd(1, '1e-100000000000000000000', prec=inf)
889
+ Traceback (most recent call last):
890
+ ...
891
+ OverflowError: the exact result does not fit in memory
892
+
893
+ """
894
+ prec, rounding = ctx._parse_prec(kwargs)
895
+ x = ctx.convert(x)
896
+ y = ctx.convert(y)
897
+ try:
898
+ if hasattr(x, '_mpf_'):
899
+ if hasattr(y, '_mpf_'):
900
+ return ctx.make_mpf(mpf_add(x._mpf_, y._mpf_, prec, rounding))
901
+ if hasattr(y, '_mpc_'):
902
+ return ctx.make_mpc(mpc_add_mpf(y._mpc_, x._mpf_, prec, rounding))
903
+ if hasattr(x, '_mpc_'):
904
+ if hasattr(y, '_mpf_'):
905
+ return ctx.make_mpc(mpc_add_mpf(x._mpc_, y._mpf_, prec, rounding))
906
+ if hasattr(y, '_mpc_'):
907
+ return ctx.make_mpc(mpc_add(x._mpc_, y._mpc_, prec, rounding))
908
+ except (ValueError, OverflowError):
909
+ raise OverflowError(ctx._exact_overflow_msg)
910
+ raise ValueError("Arguments need to be mpf or mpc compatible numbers")
911
+
912
+ def fsub(ctx, x, y, **kwargs):
913
+ """
914
+ Subtracts the numbers *x* and *y*, giving a floating-point result,
915
+ optionally using a custom precision and rounding mode.
916
+
917
+ See the documentation of :func:`~mpmath.fadd` for a detailed description
918
+ of how to specify precision and rounding.
919
+
920
+ **Examples**
921
+
922
+ Using :func:`~mpmath.fsub` with precision and rounding control::
923
+
924
+ >>> from mpmath import *
925
+ >>> mp.dps = 15; mp.pretty = False
926
+ >>> fsub(2, 1e-20)
927
+ mpf('2.0')
928
+ >>> fsub(2, 1e-20, rounding='d')
929
+ mpf('1.9999999999999998')
930
+ >>> nprint(fsub(2, 1e-20, prec=100), 25)
931
+ 1.99999999999999999999
932
+ >>> nprint(fsub(2, 1e-20, dps=15), 25)
933
+ 2.0
934
+ >>> nprint(fsub(2, 1e-20, dps=25), 25)
935
+ 1.99999999999999999999
936
+ >>> nprint(fsub(2, 1e-20, exact=True), 25)
937
+ 1.99999999999999999999
938
+
939
+ Exact subtraction avoids cancellation errors, enforcing familiar laws
940
+ of numbers such as `x-y+y = x`, which don't hold in floating-point
941
+ arithmetic with finite precision::
942
+
943
+ >>> x, y = mpf(2), mpf('1e1000')
944
+ >>> print(x - y + y)
945
+ 0.0
946
+ >>> print(fsub(x, y, prec=inf) + y)
947
+ 2.0
948
+ >>> print(fsub(x, y, exact=True) + y)
949
+ 2.0
950
+
951
+ Exact addition can be inefficient and may be impossible to perform
952
+ with large magnitude differences::
953
+
954
+ >>> fsub(1, '1e-100000000000000000000', prec=inf)
955
+ Traceback (most recent call last):
956
+ ...
957
+ OverflowError: the exact result does not fit in memory
958
+
959
+ """
960
+ prec, rounding = ctx._parse_prec(kwargs)
961
+ x = ctx.convert(x)
962
+ y = ctx.convert(y)
963
+ try:
964
+ if hasattr(x, '_mpf_'):
965
+ if hasattr(y, '_mpf_'):
966
+ return ctx.make_mpf(mpf_sub(x._mpf_, y._mpf_, prec, rounding))
967
+ if hasattr(y, '_mpc_'):
968
+ return ctx.make_mpc(mpc_sub((x._mpf_, fzero), y._mpc_, prec, rounding))
969
+ if hasattr(x, '_mpc_'):
970
+ if hasattr(y, '_mpf_'):
971
+ return ctx.make_mpc(mpc_sub_mpf(x._mpc_, y._mpf_, prec, rounding))
972
+ if hasattr(y, '_mpc_'):
973
+ return ctx.make_mpc(mpc_sub(x._mpc_, y._mpc_, prec, rounding))
974
+ except (ValueError, OverflowError):
975
+ raise OverflowError(ctx._exact_overflow_msg)
976
+ raise ValueError("Arguments need to be mpf or mpc compatible numbers")
977
+
978
+ def fmul(ctx, x, y, **kwargs):
979
+ """
980
+ Multiplies the numbers *x* and *y*, giving a floating-point result,
981
+ optionally using a custom precision and rounding mode.
982
+
983
+ See the documentation of :func:`~mpmath.fadd` for a detailed description
984
+ of how to specify precision and rounding.
985
+
986
+ **Examples**
987
+
988
+ The result is an mpmath number::
989
+
990
+ >>> from mpmath import *
991
+ >>> mp.dps = 15; mp.pretty = False
992
+ >>> fmul(2, 5.0)
993
+ mpf('10.0')
994
+ >>> fmul(0.5j, 0.5)
995
+ mpc(real='0.0', imag='0.25')
996
+
997
+ Avoiding roundoff::
998
+
999
+ >>> x, y = 10**10+1, 10**15+1
1000
+ >>> print(x*y)
1001
+ 10000000001000010000000001
1002
+ >>> print(mpf(x) * mpf(y))
1003
+ 1.0000000001e+25
1004
+ >>> print(int(mpf(x) * mpf(y)))
1005
+ 10000000001000011026399232
1006
+ >>> print(int(fmul(x, y)))
1007
+ 10000000001000011026399232
1008
+ >>> print(int(fmul(x, y, dps=25)))
1009
+ 10000000001000010000000001
1010
+ >>> print(int(fmul(x, y, exact=True)))
1011
+ 10000000001000010000000001
1012
+
1013
+ Exact multiplication with complex numbers can be inefficient and may
1014
+ be impossible to perform with large magnitude differences between
1015
+ real and imaginary parts::
1016
+
1017
+ >>> x = 1+2j
1018
+ >>> y = mpc(2, '1e-100000000000000000000')
1019
+ >>> fmul(x, y)
1020
+ mpc(real='2.0', imag='4.0')
1021
+ >>> fmul(x, y, rounding='u')
1022
+ mpc(real='2.0', imag='4.0000000000000009')
1023
+ >>> fmul(x, y, exact=True)
1024
+ Traceback (most recent call last):
1025
+ ...
1026
+ OverflowError: the exact result does not fit in memory
1027
+
1028
+ """
1029
+ prec, rounding = ctx._parse_prec(kwargs)
1030
+ x = ctx.convert(x)
1031
+ y = ctx.convert(y)
1032
+ try:
1033
+ if hasattr(x, '_mpf_'):
1034
+ if hasattr(y, '_mpf_'):
1035
+ return ctx.make_mpf(mpf_mul(x._mpf_, y._mpf_, prec, rounding))
1036
+ if hasattr(y, '_mpc_'):
1037
+ return ctx.make_mpc(mpc_mul_mpf(y._mpc_, x._mpf_, prec, rounding))
1038
+ if hasattr(x, '_mpc_'):
1039
+ if hasattr(y, '_mpf_'):
1040
+ return ctx.make_mpc(mpc_mul_mpf(x._mpc_, y._mpf_, prec, rounding))
1041
+ if hasattr(y, '_mpc_'):
1042
+ return ctx.make_mpc(mpc_mul(x._mpc_, y._mpc_, prec, rounding))
1043
+ except (ValueError, OverflowError):
1044
+ raise OverflowError(ctx._exact_overflow_msg)
1045
+ raise ValueError("Arguments need to be mpf or mpc compatible numbers")
1046
+
1047
+ def fdiv(ctx, x, y, **kwargs):
1048
+ """
1049
+ Divides the numbers *x* and *y*, giving a floating-point result,
1050
+ optionally using a custom precision and rounding mode.
1051
+
1052
+ See the documentation of :func:`~mpmath.fadd` for a detailed description
1053
+ of how to specify precision and rounding.
1054
+
1055
+ **Examples**
1056
+
1057
+ The result is an mpmath number::
1058
+
1059
+ >>> from mpmath import *
1060
+ >>> mp.dps = 15; mp.pretty = False
1061
+ >>> fdiv(3, 2)
1062
+ mpf('1.5')
1063
+ >>> fdiv(2, 3)
1064
+ mpf('0.66666666666666663')
1065
+ >>> fdiv(2+4j, 0.5)
1066
+ mpc(real='4.0', imag='8.0')
1067
+
1068
+ The rounding direction and precision can be controlled::
1069
+
1070
+ >>> fdiv(2, 3, dps=3) # Should be accurate to at least 3 digits
1071
+ mpf('0.6666259765625')
1072
+ >>> fdiv(2, 3, rounding='d')
1073
+ mpf('0.66666666666666663')
1074
+ >>> fdiv(2, 3, prec=60)
1075
+ mpf('0.66666666666666667')
1076
+ >>> fdiv(2, 3, rounding='u')
1077
+ mpf('0.66666666666666674')
1078
+
1079
+ Checking the error of a division by performing it at higher precision::
1080
+
1081
+ >>> fdiv(2, 3) - fdiv(2, 3, prec=100)
1082
+ mpf('-3.7007434154172148e-17')
1083
+
1084
+ Unlike :func:`~mpmath.fadd`, :func:`~mpmath.fmul`, etc., exact division is not
1085
+ allowed since the quotient of two floating-point numbers generally
1086
+ does not have an exact floating-point representation. (In the
1087
+ future this might be changed to allow the case where the division
1088
+ is actually exact.)
1089
+
1090
+ >>> fdiv(2, 3, exact=True)
1091
+ Traceback (most recent call last):
1092
+ ...
1093
+ ValueError: division is not an exact operation
1094
+
1095
+ """
1096
+ prec, rounding = ctx._parse_prec(kwargs)
1097
+ if not prec:
1098
+ raise ValueError("division is not an exact operation")
1099
+ x = ctx.convert(x)
1100
+ y = ctx.convert(y)
1101
+ if hasattr(x, '_mpf_'):
1102
+ if hasattr(y, '_mpf_'):
1103
+ return ctx.make_mpf(mpf_div(x._mpf_, y._mpf_, prec, rounding))
1104
+ if hasattr(y, '_mpc_'):
1105
+ return ctx.make_mpc(mpc_div((x._mpf_, fzero), y._mpc_, prec, rounding))
1106
+ if hasattr(x, '_mpc_'):
1107
+ if hasattr(y, '_mpf_'):
1108
+ return ctx.make_mpc(mpc_div_mpf(x._mpc_, y._mpf_, prec, rounding))
1109
+ if hasattr(y, '_mpc_'):
1110
+ return ctx.make_mpc(mpc_div(x._mpc_, y._mpc_, prec, rounding))
1111
+ raise ValueError("Arguments need to be mpf or mpc compatible numbers")
1112
+
1113
+ def nint_distance(ctx, x):
1114
+ r"""
1115
+ Return `(n,d)` where `n` is the nearest integer to `x` and `d` is
1116
+ an estimate of `\log_2(|x-n|)`. If `d < 0`, `-d` gives the precision
1117
+ (measured in bits) lost to cancellation when computing `x-n`.
1118
+
1119
+ >>> from mpmath import *
1120
+ >>> n, d = nint_distance(5)
1121
+ >>> print(n); print(d)
1122
+ 5
1123
+ -inf
1124
+ >>> n, d = nint_distance(mpf(5))
1125
+ >>> print(n); print(d)
1126
+ 5
1127
+ -inf
1128
+ >>> n, d = nint_distance(mpf(5.00000001))
1129
+ >>> print(n); print(d)
1130
+ 5
1131
+ -26
1132
+ >>> n, d = nint_distance(mpf(4.99999999))
1133
+ >>> print(n); print(d)
1134
+ 5
1135
+ -26
1136
+ >>> n, d = nint_distance(mpc(5,10))
1137
+ >>> print(n); print(d)
1138
+ 5
1139
+ 4
1140
+ >>> n, d = nint_distance(mpc(5,0.000001))
1141
+ >>> print(n); print(d)
1142
+ 5
1143
+ -19
1144
+
1145
+ """
1146
+ typx = type(x)
1147
+ if typx in int_types:
1148
+ return int(x), ctx.ninf
1149
+ elif typx is rational.mpq:
1150
+ p, q = x._mpq_
1151
+ n, r = divmod(p, q)
1152
+ if 2*r >= q:
1153
+ n += 1
1154
+ elif not r:
1155
+ return n, ctx.ninf
1156
+ # log(p/q-n) = log((p-nq)/q) = log(p-nq) - log(q)
1157
+ d = bitcount(abs(p-n*q)) - bitcount(q)
1158
+ return n, d
1159
+ if hasattr(x, "_mpf_"):
1160
+ re = x._mpf_
1161
+ im_dist = ctx.ninf
1162
+ elif hasattr(x, "_mpc_"):
1163
+ re, im = x._mpc_
1164
+ isign, iman, iexp, ibc = im
1165
+ if iman:
1166
+ im_dist = iexp + ibc
1167
+ elif im == fzero:
1168
+ im_dist = ctx.ninf
1169
+ else:
1170
+ raise ValueError("requires a finite number")
1171
+ else:
1172
+ x = ctx.convert(x)
1173
+ if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"):
1174
+ return ctx.nint_distance(x)
1175
+ else:
1176
+ raise TypeError("requires an mpf/mpc")
1177
+ sign, man, exp, bc = re
1178
+ mag = exp+bc
1179
+ # |x| < 0.5
1180
+ if mag < 0:
1181
+ n = 0
1182
+ re_dist = mag
1183
+ elif man:
1184
+ # exact integer
1185
+ if exp >= 0:
1186
+ n = man << exp
1187
+ re_dist = ctx.ninf
1188
+ # exact half-integer
1189
+ elif exp == -1:
1190
+ n = (man>>1)+1
1191
+ re_dist = 0
1192
+ else:
1193
+ d = (-exp-1)
1194
+ t = man >> d
1195
+ if t & 1:
1196
+ t += 1
1197
+ man = (t<<d) - man
1198
+ else:
1199
+ man -= (t<<d)
1200
+ n = t>>1 # int(t)>>1
1201
+ re_dist = exp+bitcount(man)
1202
+ if sign:
1203
+ n = -n
1204
+ elif re == fzero:
1205
+ re_dist = ctx.ninf
1206
+ n = 0
1207
+ else:
1208
+ raise ValueError("requires a finite number")
1209
+ return n, max(re_dist, im_dist)
1210
+
1211
+ def fprod(ctx, factors):
1212
+ r"""
1213
+ Calculates a product containing a finite number of factors (for
1214
+ infinite products, see :func:`~mpmath.nprod`). The factors will be
1215
+ converted to mpmath numbers.
1216
+
1217
+ >>> from mpmath import *
1218
+ >>> mp.dps = 15; mp.pretty = False
1219
+ >>> fprod([1, 2, 0.5, 7])
1220
+ mpf('7.0')
1221
+
1222
+ """
1223
+ orig = ctx.prec
1224
+ try:
1225
+ v = ctx.one
1226
+ for p in factors:
1227
+ v *= p
1228
+ finally:
1229
+ ctx.prec = orig
1230
+ return +v
1231
+
1232
+ def rand(ctx):
1233
+ """
1234
+ Returns an ``mpf`` with value chosen randomly from `[0, 1)`.
1235
+ The number of randomly generated bits in the mantissa is equal
1236
+ to the working precision.
1237
+ """
1238
+ return ctx.make_mpf(mpf_rand(ctx._prec))
1239
+
1240
+ def fraction(ctx, p, q):
1241
+ """
1242
+ Given Python integers `(p, q)`, returns a lazy ``mpf`` representing
1243
+ the fraction `p/q`. The value is updated with the precision.
1244
+
1245
+ >>> from mpmath import *
1246
+ >>> mp.dps = 15
1247
+ >>> a = fraction(1,100)
1248
+ >>> b = mpf(1)/100
1249
+ >>> print(a); print(b)
1250
+ 0.01
1251
+ 0.01
1252
+ >>> mp.dps = 30
1253
+ >>> print(a); print(b) # a will be accurate
1254
+ 0.01
1255
+ 0.0100000000000000002081668171172
1256
+ >>> mp.dps = 15
1257
+ """
1258
+ return ctx.constant(lambda prec, rnd: from_rational(p, q, prec, rnd),
1259
+ '%s/%s' % (p, q))
1260
+
1261
+ def absmin(ctx, x):
1262
+ return abs(ctx.convert(x))
1263
+
1264
+ def absmax(ctx, x):
1265
+ return abs(ctx.convert(x))
1266
+
1267
+ def _as_points(ctx, x):
1268
+ # XXX: remove this?
1269
+ if hasattr(x, '_mpi_'):
1270
+ a, b = x._mpi_
1271
+ return [ctx.make_mpf(a), ctx.make_mpf(b)]
1272
+ return x
1273
+
1274
+ '''
1275
+ def _zetasum(ctx, s, a, b):
1276
+ """
1277
+ Computes sum of k^(-s) for k = a, a+1, ..., b with a, b both small
1278
+ integers.
1279
+ """
1280
+ a = int(a)
1281
+ b = int(b)
1282
+ s = ctx.convert(s)
1283
+ prec, rounding = ctx._prec_rounding
1284
+ if hasattr(s, '_mpf_'):
1285
+ v = ctx.make_mpf(libmp.mpf_zetasum(s._mpf_, a, b, prec))
1286
+ elif hasattr(s, '_mpc_'):
1287
+ v = ctx.make_mpc(libmp.mpc_zetasum(s._mpc_, a, b, prec))
1288
+ return v
1289
+ '''
1290
+
1291
+ def _zetasum_fast(ctx, s, a, n, derivatives=[0], reflect=False):
1292
+ if not (ctx.isint(a) and hasattr(s, "_mpc_")):
1293
+ raise NotImplementedError
1294
+ a = int(a)
1295
+ prec = ctx._prec
1296
+ xs, ys = libmp.mpc_zetasum(s._mpc_, a, n, derivatives, reflect, prec)
1297
+ xs = [ctx.make_mpc(x) for x in xs]
1298
+ ys = [ctx.make_mpc(y) for y in ys]
1299
+ return xs, ys
1300
+
1301
+ class PrecisionManager:
1302
+ def __init__(self, ctx, precfun, dpsfun, normalize_output=False):
1303
+ self.ctx = ctx
1304
+ self.precfun = precfun
1305
+ self.dpsfun = dpsfun
1306
+ self.normalize_output = normalize_output
1307
+ def __call__(self, f):
1308
+ @functools.wraps(f)
1309
+ def g(*args, **kwargs):
1310
+ orig = self.ctx.prec
1311
+ try:
1312
+ if self.precfun:
1313
+ self.ctx.prec = self.precfun(self.ctx.prec)
1314
+ else:
1315
+ self.ctx.dps = self.dpsfun(self.ctx.dps)
1316
+ if self.normalize_output:
1317
+ v = f(*args, **kwargs)
1318
+ if type(v) is tuple:
1319
+ return tuple([+a for a in v])
1320
+ return +v
1321
+ else:
1322
+ return f(*args, **kwargs)
1323
+ finally:
1324
+ self.ctx.prec = orig
1325
+ return g
1326
+ def __enter__(self):
1327
+ self.origp = self.ctx.prec
1328
+ if self.precfun:
1329
+ self.ctx.prec = self.precfun(self.ctx.prec)
1330
+ else:
1331
+ self.ctx.dps = self.dpsfun(self.ctx.dps)
1332
+ def __exit__(self, exc_type, exc_val, exc_tb):
1333
+ self.ctx.prec = self.origp
1334
+ return False
1335
+
1336
+
1337
+ if __name__ == '__main__':
1338
+ import doctest
1339
+ doctest.testmod()