Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/libs/mpmath/ext_main.pyx
4048 views
1
"""
2
Implements mpf and mpc types, with binary operations and support
3
for interaction with other types. Also implements the main
4
context class, and related utilities.
5
"""
6
7
include '../../ext/interrupt.pxi'
8
include "../../ext/stdsage.pxi"
9
include "../../ext/python_int.pxi"
10
include "../../ext/python_long.pxi"
11
include "../../ext/python_float.pxi"
12
include "../../ext/python_complex.pxi"
13
include "../../ext/python_number.pxi"
14
15
from sage.libs.gmp.all cimport *
16
from sage.rings.integer cimport Integer
17
18
cdef extern from "mpz_pylong.h":
19
cdef mpz_get_pylong(mpz_t src)
20
cdef mpz_get_pyintlong(mpz_t src)
21
cdef int mpz_set_pylong(mpz_t dst, src) except -1
22
cdef long mpz_pythonhash(mpz_t src)
23
24
DEF ROUND_N = 0
25
DEF ROUND_F = 1
26
DEF ROUND_C = 2
27
DEF ROUND_D = 3
28
DEF ROUND_U = 4
29
DEF S_NORMAL = 0
30
DEF S_ZERO = 1
31
DEF S_NZERO = 2
32
DEF S_INF = 3
33
DEF S_NINF = 4
34
DEF S_NAN = 5
35
36
from ext_impl cimport *
37
38
import mpmath.rational as rationallib
39
import mpmath.libmp as libmp
40
import mpmath.function_docs as function_docs
41
from mpmath.libmp import to_str
42
from mpmath.libmp import repr_dps, prec_to_dps, dps_to_prec
43
44
DEF OP_ADD = 0
45
DEF OP_SUB = 1
46
DEF OP_MUL = 2
47
DEF OP_DIV = 3
48
DEF OP_POW = 4
49
DEF OP_MOD = 5
50
DEF OP_RICHCMP = 6
51
DEF OP_EQ = (OP_RICHCMP + 2)
52
DEF OP_NE = (OP_RICHCMP + 3)
53
DEF OP_LT = (OP_RICHCMP + 0)
54
DEF OP_GT = (OP_RICHCMP + 4)
55
DEF OP_LE = (OP_RICHCMP + 1)
56
DEF OP_GE = (OP_RICHCMP + 5)
57
58
cdef MPopts opts_exact
59
cdef MPopts opts_double_precision
60
cdef MPopts opts_mini_prec
61
62
opts_exact.prec = 0
63
opts_exact.rounding = ROUND_N
64
opts_double_precision.prec = 53
65
opts_double_precision.rounding = ROUND_N
66
opts_mini_prec.prec = 5
67
opts_mini_prec.rounding = ROUND_D
68
69
cdef MPF MPF_C_0
70
cdef MPF MPF_C_1
71
cdef MPF MPF_C_2
72
73
MPF_init(&MPF_C_0); MPF_set_zero(&MPF_C_0);
74
MPF_init(&MPF_C_1); MPF_set_si(&MPF_C_1, 1);
75
MPF_init(&MPF_C_2); MPF_set_si(&MPF_C_2, 2);
76
77
# Temporaries used for operands in binary operations
78
cdef mpz_t tmp_mpz
79
mpz_init(tmp_mpz)
80
81
cdef MPF tmp1
82
cdef MPF tmp2
83
cdef MPF tmp_opx_re
84
cdef MPF tmp_opx_im
85
cdef MPF tmp_opy_re
86
cdef MPF tmp_opy_im
87
88
MPF_init(&tmp1)
89
MPF_init(&tmp2)
90
MPF_init(&tmp_opx_re)
91
MPF_init(&tmp_opx_im)
92
MPF_init(&tmp_opy_re)
93
MPF_init(&tmp_opy_im)
94
95
cdef class Context
96
cdef class mpnumber
97
cdef class mpf_base
98
cdef class mpf
99
cdef class mpc
100
cdef class constant
101
cdef class wrapped_libmp_function
102
cdef class wrapped_specfun
103
104
cdef __isint(MPF *v):
105
return v.special == S_ZERO or (v.special == S_NORMAL and mpz_sgn(v.exp) >= 0)
106
107
cdef int MPF_set_any(MPF *re, MPF *im, x, MPopts opts, bint str_tuple_ok) except -1:
108
"""
109
Sets re + im*i = x, where x is any Python number.
110
111
Returns 0 if unable to coerce x; 1 if x is real and re was set;
112
2 if x is complex and both re and im were set.
113
114
If str_tuple_ok=True, strings and tuples are accepted and converted
115
(useful for parsing arguments, but not for arithmetic operands).
116
"""
117
if PY_TYPE_CHECK(x, mpf):
118
MPF_set(re, &(<mpf>x).value)
119
return 1
120
if PY_TYPE_CHECK(x, mpc):
121
MPF_set(re, &(<mpc>x).re)
122
MPF_set(im, &(<mpc>x).im)
123
return 2
124
if PyInt_Check(x) or PyLong_Check(x) or PY_TYPE_CHECK(x, Integer):
125
MPF_set_int(re, x)
126
return 1
127
if PyFloat_Check(x):
128
MPF_set_double(re, x)
129
return 1
130
if PyComplex_Check(x):
131
MPF_set_double(re, x.real)
132
MPF_set_double(im, x.imag)
133
return 2
134
if PY_TYPE_CHECK(x, constant):
135
MPF_set_tuple(re, x.func(opts.prec, rndmode_to_python(opts.rounding)))
136
return 1
137
if hasattr(x, "_mpf_"):
138
MPF_set_tuple(re, x._mpf_)
139
return 1
140
if hasattr(x, "_mpc_"):
141
r, i = x._mpc_
142
MPF_set_tuple(re, r)
143
MPF_set_tuple(im, i)
144
return 2
145
if hasattr(x, "_mpmath_"):
146
return MPF_set_any(re, im, x._mpmath_(opts.prec,
147
rndmode_to_python(opts.rounding)), opts, False)
148
if PY_TYPE_CHECK(x, rationallib.mpq):
149
p, q = x._mpq_
150
MPF_set_int(re, p)
151
MPF_set_int(im, q)
152
MPF_div(re, re, im, opts)
153
#MPF_set_tuple(re, libmp.from_rational(p, q, opts.prec,
154
# rndmode_to_python(opts.rounding)))
155
return 1
156
if hasattr(x, '_mpi_'):
157
a, b = x._mpi_
158
if a == b:
159
MPF_set_tuple(re, a)
160
return 1
161
raise ValueError("can only create mpf from zero-width interval")
162
if str_tuple_ok:
163
if PY_TYPE_CHECK(x, tuple):
164
if len(x) == 2:
165
MPF_set_man_exp(re, x[0], x[1])
166
return 1
167
elif len(x) == 4:
168
MPF_set_tuple(re, x)
169
return 1
170
if isinstance(x, basestring):
171
try:
172
st = libmp.from_str(x, opts.prec,
173
rndmode_to_python(opts.rounding))
174
except ValueError:
175
return 0
176
MPF_set_tuple(re, st)
177
return 1
178
return 0
179
180
cdef binop(int op, x, y, MPopts opts):
181
cdef int typx
182
cdef int typy
183
cdef MPF xre, xim, yre, yim
184
cdef mpf rr
185
cdef mpc rc
186
cdef MPopts altopts
187
188
if PY_TYPE_CHECK(x, mpf):
189
xre = (<mpf>x).value
190
typx = 1
191
elif PY_TYPE_CHECK(x, mpc):
192
xre = (<mpc>x).re
193
xim = (<mpc>x).im
194
typx = 2
195
else:
196
typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, False)
197
if typx == 0:
198
return NotImplemented
199
xre = tmp_opx_re
200
xim = tmp_opx_im
201
202
if PY_TYPE_CHECK(y, mpf):
203
yre = (<mpf>y).value
204
typy = 1
205
elif PY_TYPE_CHECK(y, mpc):
206
yre = (<mpc>y).re
207
yim = (<mpc>y).im
208
typy = 2
209
else:
210
typy = MPF_set_any(&tmp_opy_re, &tmp_opy_im, y, opts, False)
211
if typy == 0:
212
return NotImplemented
213
yre = tmp_opy_re
214
yim = tmp_opy_im
215
216
if op == OP_ADD:
217
if typx == 1 and typy == 1:
218
# Real result
219
rr = PY_NEW(mpf)
220
MPF_add(&rr.value, &xre, &yre, opts)
221
return rr
222
else:
223
# Complex result
224
rc = PY_NEW(mpc)
225
MPF_add(&rc.re, &xre, &yre, opts)
226
if typx == 1:
227
MPF_set(&rc.im, &yim)
228
#MPF_normalize(&rc.im, opts)
229
elif typy == 1:
230
MPF_set(&rc.im, &xim)
231
#MPF_normalize(&rc.im, opts)
232
else:
233
MPF_add(&rc.im, &xim, &yim, opts)
234
return rc
235
236
elif op == OP_SUB:
237
if typx == 1 and typy == 1:
238
# Real result
239
rr = PY_NEW(mpf)
240
MPF_sub(&rr.value, &xre, &yre, opts)
241
return rr
242
else:
243
# Complex result
244
rc = PY_NEW(mpc)
245
MPF_sub(&rc.re, &xre, &yre, opts)
246
if typx == 1:
247
MPF_neg(&rc.im, &yim)
248
MPF_normalize(&rc.im, opts)
249
elif typy == 1:
250
MPF_set(&rc.im, &xim)
251
MPF_normalize(&rc.im, opts)
252
else:
253
MPF_sub(&rc.im, &xim, &yim, opts)
254
return rc
255
256
elif op == OP_MUL:
257
if typx == 1 and typy == 1:
258
# Real result
259
rr = PY_NEW(mpf)
260
MPF_mul(&rr.value, &xre, &yre, opts)
261
return rr
262
else:
263
# Complex result
264
rc = PY_NEW(mpc)
265
if typx == 1:
266
MPF_mul(&rc.re, &yre, &xre, opts)
267
MPF_mul(&rc.im, &yim, &xre, opts)
268
elif typy == 1:
269
MPF_mul(&rc.re, &xre, &yre, opts)
270
MPF_mul(&rc.im, &xim, &yre, opts)
271
else:
272
# a*c - b*d
273
MPF_mul(&rc.re, &xre, &yre, opts_exact)
274
MPF_mul(&tmp1, &xim, &yim, opts_exact)
275
MPF_sub(&rc.re, &rc.re, &tmp1, opts)
276
# a*d + b*c
277
MPF_mul(&rc.im, &xre, &yim, opts_exact)
278
MPF_mul(&tmp1, &xim, &yre, opts_exact)
279
MPF_add(&rc.im, &rc.im, &tmp1, opts)
280
return rc
281
282
283
elif op == OP_DIV:
284
if typx == 1 and typy == 1:
285
# Real result
286
rr = PY_NEW(mpf)
287
MPF_div(&rr.value, &xre, &yre, opts)
288
return rr
289
else:
290
rc = PY_NEW(mpc)
291
if typy == 1:
292
MPF_div(&rc.re, &xre, &yre, opts)
293
MPF_div(&rc.im, &xim, &yre, opts)
294
else:
295
if typx == 1:
296
xim = MPF_C_0
297
altopts = opts
298
altopts.prec += 10
299
# m = c*c + d*d
300
MPF_mul(&tmp1, &yre, &yre, opts_exact)
301
MPF_mul(&tmp2, &yim, &yim, opts_exact)
302
MPF_add(&tmp1, &tmp1, &tmp2, altopts)
303
# (a*c+b*d)/m
304
MPF_mul(&rc.re, &xre, &yre, opts_exact)
305
MPF_mul(&tmp2, &xim, &yim, opts_exact)
306
MPF_add(&rc.re, &rc.re, &tmp2, altopts)
307
MPF_div(&rc.re, &rc.re, &tmp1, opts)
308
# (b*c-a*d)/m
309
MPF_mul(&rc.im, &xim, &yre, opts_exact)
310
MPF_mul(&tmp2, &xre, &yim, opts_exact)
311
MPF_sub(&rc.im, &rc.im, &tmp2, altopts)
312
MPF_div(&rc.im, &rc.im, &tmp1, opts)
313
return rc
314
315
elif op == OP_POW:
316
if typx == 1 and typy == 1:
317
rr = PY_NEW(mpf)
318
if not MPF_pow(&rr.value, &xre, &yre, opts):
319
return rr
320
if typx == 1: xim = MPF_C_0
321
if typy == 1: yim = MPF_C_0
322
rc = PY_NEW(mpc)
323
MPF_complex_pow(&rc.re, &rc.im, &xre, &xim, &yre, &yim, opts)
324
return rc
325
326
elif op == OP_MOD:
327
if typx != 1 or typx != 1:
328
raise TypeError("mod for complex numbers")
329
xret = MPF_to_tuple(&xre)
330
yret = MPF_to_tuple(&yre)
331
v = libmp.mpf_mod(xret, yret, opts.prec, rndmode_to_python(opts.rounding))
332
rr = PY_NEW(mpf)
333
MPF_set_tuple(&rr.value, v)
334
return rr
335
336
elif op == OP_EQ:
337
if typx == 1 and typy == 1:
338
return MPF_eq(&xre, &yre)
339
if typx == 1:
340
return MPF_eq(&xre, &yre) and MPF_eq(&yim, &MPF_C_0)
341
if typy == 1:
342
return MPF_eq(&xre, &yre) and MPF_eq(&xim, &MPF_C_0)
343
return MPF_eq(&xre, &yre) and MPF_eq(&xim, &yim)
344
345
elif op == OP_NE:
346
if typx == 1 and typy == 1:
347
return MPF_ne(&xre, &yre)
348
if typx == 1:
349
return MPF_ne(&xre, &yre) or MPF_ne(&yim, &MPF_C_0)
350
if typy == 1:
351
return MPF_ne(&xre, &yre) or MPF_ne(&xim, &MPF_C_0)
352
return MPF_ne(&xre, &yre) or MPF_ne(&xim, &yim)
353
354
elif op == OP_LT:
355
if typx != 1 or typy != 1:
356
raise ValueError("cannot compare complex numbers")
357
return MPF_lt(&xre, &yre)
358
359
elif op == OP_GT:
360
if typx != 1 or typy != 1:
361
raise ValueError("cannot compare complex numbers")
362
return MPF_gt(&xre, &yre)
363
364
elif op == OP_LE:
365
if typx != 1 or typy != 1:
366
raise ValueError("cannot compare complex numbers")
367
return MPF_le(&xre, &yre)
368
369
elif op == OP_GE:
370
if typx != 1 or typy != 1:
371
raise ValueError("cannot compare complex numbers")
372
return MPF_ge(&xre, &yre)
373
374
return NotImplemented
375
376
377
cdef MPopts global_opts
378
379
global_context = None
380
381
cdef class Context:
382
cdef public mpf, mpc, constant #, def_mp_function
383
cdef public trap_complex
384
cdef public pretty
385
386
def __cinit__(ctx):
387
"""
388
At present, only a single global context should exist ::
389
390
sage: from mpmath import mp
391
sage: type(mp)
392
<class 'mpmath.ctx_mp.MPContext'>
393
"""
394
global global_opts, global_context
395
global_opts = opts_double_precision
396
global_context = ctx
397
ctx.mpf = mpf
398
ctx.mpc = mpc
399
ctx.constant = constant
400
#ctx.def_mp_function = def_mp_function
401
ctx._mpq = rationallib.mpq
402
403
def default(ctx):
404
"""
405
Sets defaults.
406
407
TESTS ::
408
409
sage: import mpmath
410
sage: mpmath.mp.prec = 100
411
sage: mpmath.mp.default()
412
sage: mpmath.mp.prec
413
53
414
"""
415
global global_opts
416
global_opts = opts_double_precision
417
ctx.trap_complex = False
418
ctx.pretty = False
419
420
def _get_prec(ctx):
421
"""
422
Controls the working precision in bits ::
423
424
sage: from mpmath import mp
425
sage: mp.prec = 100
426
sage: mp.prec
427
100
428
sage: mp.dps
429
29
430
sage: mp.prec = 53
431
"""
432
return global_opts.prec
433
434
def _set_prec(ctx, prec):
435
"""
436
Controls the working precision in bits ::
437
438
sage: from mpmath import mp
439
sage: mp.prec = 100
440
sage: mp.prec
441
100
442
sage: mp.dps
443
29
444
sage: mp.prec = 53
445
"""
446
global_opts.prec = prec
447
448
def _set_dps(ctx, n):
449
"""
450
Controls the working precision in decimal digits ::
451
452
sage: from mpmath import mp
453
sage: mp.dps = 100
454
sage: mp.prec
455
336
456
sage: mp.dps
457
100
458
sage: mp.prec = 53
459
"""
460
global_opts.prec = dps_to_prec(int(n))
461
462
def _get_dps(ctx):
463
"""
464
Controls the working precision in decimal digits ::
465
466
sage: from mpmath import mp
467
sage: mp.dps = 100
468
sage: mp.prec
469
336
470
sage: mp.dps
471
100
472
sage: mp.prec = 53
473
"""
474
return libmp.prec_to_dps(global_opts.prec)
475
476
dps = property(_get_dps, _set_dps, doc=_get_dps.__doc__)
477
prec = property(_get_prec, _set_prec, doc=_get_dps.__doc__)
478
_dps = property(_get_dps, _set_dps, doc=_get_dps.__doc__)
479
_prec = property(_get_prec, _set_prec, doc=_get_dps.__doc__)
480
481
def _get_prec_rounding(ctx):
482
"""
483
Returns the precision and rounding mode ::
484
485
sage: from mpmath import mp
486
sage: mp._get_prec_rounding()
487
(53, 'n')
488
"""
489
return global_opts.prec, rndmode_to_python(global_opts.rounding)
490
491
_prec_rounding = property(_get_prec_rounding)
492
493
cpdef mpf make_mpf(ctx, tuple v):
494
"""
495
Creates an mpf from tuple data ::
496
497
sage: import mpmath
498
sage: float(mpmath.mp.make_mpf((0,1,-1,1)))
499
0.5
500
"""
501
cdef mpf x
502
x = PY_NEW(mpf)
503
MPF_set_tuple(&x.value, v)
504
return x
505
506
cpdef mpc make_mpc(ctx, tuple v):
507
"""
508
Creates an mpc from tuple data ::
509
510
sage: import mpmath
511
>>> complex(mpmath.mp.make_mpc(((0,1,-1,1), (1,1,-2,1))))
512
(0.5-0.25j)
513
"""
514
cdef mpc x
515
x = PY_NEW(mpc)
516
MPF_set_tuple(&x.re, v[0])
517
MPF_set_tuple(&x.im, v[1])
518
return x
519
520
def convert(ctx, x, strings=True):
521
"""
522
Converts *x* to an ``mpf``, ``mpc`` or ``mpi``. If *x* is of type ``mpf``,
523
``mpc``, ``int``, ``float``, ``complex``, the conversion
524
will be performed losslessly.
525
526
If *x* is a string, the result will be rounded to the present
527
working precision. Strings representing fractions or complex
528
numbers are permitted.
529
530
TESTS ::
531
532
sage: from mpmath import mp, convert
533
sage: mp.dps = 15; mp.pretty = False
534
sage: convert(3.5)
535
mpf('3.5')
536
sage: convert('2.1')
537
mpf('2.1000000000000001')
538
sage: convert('3/4')
539
mpf('0.75')
540
sage: convert('2+3j')
541
mpc(real='2.0', imag='3.0')
542
543
"""
544
cdef mpf rr
545
cdef mpc rc
546
if PY_TYPE_CHECK(x, mpnumber):
547
return x
548
typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, strings)
549
if typx == 1:
550
rr = PY_NEW(mpf)
551
MPF_set(&rr.value, &tmp_opx_re)
552
return rr
553
if typx == 2:
554
rc = PY_NEW(mpc)
555
MPF_set(&rc.re, &tmp_opx_re)
556
MPF_set(&rc.im, &tmp_opx_im)
557
return rc
558
return ctx._convert_fallback(x, strings)
559
560
def isnan(ctx, x):
561
"""
562
For an ``mpf`` *x*, determines whether *x* is not-a-number (nan)::
563
564
TESTS ::
565
566
sage: from mpmath import isnan, nan
567
sage: isnan(nan), isnan(3)
568
(True, False)
569
"""
570
cdef int s, t, typ
571
if PY_TYPE_CHECK(x, mpf):
572
return (<mpf>x).value.special == S_NAN
573
if PY_TYPE_CHECK(x, mpc):
574
s = (<mpc>x).re.special
575
t = (<mpc>x).im.special
576
return s == S_NAN or t == S_NAN
577
if PyInt_CheckExact(x) or PyLong_CheckExact(x) or PY_TYPE_CHECK(x, Integer) \
578
or PY_TYPE_CHECK(x, rationallib.mpq):
579
return False
580
typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 0)
581
if typ == 1:
582
s = tmp_opx_re.special
583
return s == S_NAN
584
if typ == 2:
585
s = tmp_opx_re.special
586
t = tmp_opx_im.special
587
return s == S_NAN or t == S_NAN
588
raise TypeError("isnan() needs a number as input")
589
590
def isinf(ctx, x):
591
"""
592
Return *True* if the absolute value of *x* is infinite;
593
otherwise return *False*::
594
595
TESTS ::
596
597
sage: from mpmath import isinf, inf, mpc
598
sage: isinf(inf)
599
True
600
sage: isinf(-inf)
601
True
602
sage: isinf(3)
603
False
604
sage: isinf(3+4j)
605
False
606
sage: isinf(mpc(3,inf))
607
True
608
sage: isinf(mpc(inf,3))
609
True
610
611
"""
612
cdef int s, t, typ
613
if PY_TYPE_CHECK(x, mpf):
614
s = (<mpf>x).value.special
615
return s == S_INF or s == S_NINF
616
if PY_TYPE_CHECK(x, mpc):
617
s = (<mpc>x).re.special
618
t = (<mpc>x).im.special
619
return s == S_INF or s == S_NINF or t == S_INF or t == S_NINF
620
if PyInt_CheckExact(x) or PyLong_CheckExact(x) or PY_TYPE_CHECK(x, Integer) \
621
or PY_TYPE_CHECK(x, rationallib.mpq):
622
return False
623
typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 0)
624
if typ == 1:
625
s = tmp_opx_re.special
626
return s == S_INF or s == S_NINF
627
if typ == 2:
628
s = tmp_opx_re.special
629
t = tmp_opx_im.special
630
return s == S_INF or s == S_NINF or t == S_INF or t == S_NINF
631
raise TypeError("isinf() needs a number as input")
632
633
def isnormal(ctx, x):
634
"""
635
Determine whether *x* is "normal" in the sense of floating-point
636
representation; that is, return *False* if *x* is zero, an
637
infinity or NaN; otherwise return *True*. By extension, a
638
complex number *x* is considered "normal" if its magnitude is
639
normal.
640
641
TESTS ::
642
643
sage: from mpmath import isnormal, inf, nan, mpc
644
sage: isnormal(3)
645
True
646
sage: isnormal(0)
647
False
648
sage: isnormal(inf); isnormal(-inf); isnormal(nan)
649
False
650
False
651
False
652
sage: isnormal(0+0j)
653
False
654
sage: isnormal(0+3j)
655
True
656
sage: isnormal(mpc(2,nan))
657
False
658
"""
659
# TODO: optimize this
660
if hasattr(x, "_mpf_"):
661
return bool(x._mpf_[1])
662
if hasattr(x, "_mpc_"):
663
re, im = x._mpc_
664
re_normal = bool(re[1])
665
im_normal = bool(im[1])
666
if re == libmp.fzero: return im_normal
667
if im == libmp.fzero: return re_normal
668
return re_normal and im_normal
669
if PyInt_CheckExact(x) or PyLong_CheckExact(x) or PY_TYPE_CHECK(x, Integer) \
670
or PY_TYPE_CHECK(x, rationallib.mpq):
671
return bool(x)
672
x = ctx.convert(x)
673
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
674
return ctx.isnormal(x)
675
raise TypeError("isnormal() needs a number as input")
676
677
def isint(ctx, x, gaussian=False):
678
"""
679
Return *True* if *x* is integer-valued; otherwise return
680
*False*.
681
682
TESTS ::
683
684
sage: from mpmath import isint, mpf, inf
685
sage: isint(3)
686
True
687
sage: isint(mpf(3))
688
True
689
sage: isint(3.2)
690
False
691
sage: isint(inf)
692
False
693
694
Optionally, Gaussian integers can be checked for::
695
696
sage: isint(3+0j)
697
True
698
sage: isint(3+2j)
699
False
700
sage: isint(3+2j, gaussian=True)
701
True
702
703
"""
704
cdef MPF v
705
cdef MPF w
706
cdef int typ
707
if PyInt_CheckExact(x) or PyLong_CheckExact(x) or PY_TYPE_CHECK(x, Integer):
708
return True
709
if PY_TYPE_CHECK(x, mpf):
710
v = (<mpf>x).value
711
return __isint(&v)
712
if PY_TYPE_CHECK(x, mpc):
713
v = (<mpc>x).re
714
w = (<mpc>x).im
715
if gaussian:
716
return __isint(&v) and __isint(&w)
717
return (w.special == S_ZERO) and __isint(&v)
718
if PY_TYPE_CHECK(x, rationallib.mpq):
719
p, q = x._mpq_
720
return not (p % q)
721
typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 0)
722
if typ == 1:
723
return __isint(&tmp_opx_re)
724
if typ == 2:
725
v = tmp_opx_re
726
w = tmp_opx_im
727
if gaussian:
728
return __isint(&v) and __isint(&w)
729
return (w.special == S_ZERO) and __isint(&v)
730
raise TypeError("isint() needs a number as input")
731
732
def fsum(ctx, terms, bint absolute=False, bint squared=False):
733
"""
734
Calculates a sum containing a finite number of terms (for infinite
735
series, see :func:`nsum`). The terms will be converted to
736
mpmath numbers. For len(terms) > 2, this function is generally
737
faster and produces more accurate results than the builtin
738
Python function :func:`sum`.
739
740
TESTS ::
741
742
sage: from mpmath import mp, fsum
743
sage: mp.dps = 15; mp.pretty = False
744
sage: fsum([1, 2, 0.5, 7])
745
mpf('10.5')
746
747
With squared=True each term is squared, and with absolute=True
748
the absolute value of each term is used.
749
"""
750
cdef MPF sre, sim, tre, tim, tmp
751
cdef mpf rr
752
cdef mpc rc
753
cdef MPopts workopts
754
cdef int styp, ttyp
755
workopts = global_opts
756
workopts.prec = workopts.prec * 2 + 50
757
workopts.rounding = ROUND_D
758
unknown = global_context.zero
759
try: # Way down, there is a ``finally`` with sig_off()
760
sig_on()
761
MPF_init(&sre)
762
MPF_init(&sim)
763
MPF_init(&tre)
764
MPF_init(&tim)
765
MPF_init(&tmp)
766
styp = 1
767
for term in terms:
768
ttyp = MPF_set_any(&tre, &tim, term, workopts, 0)
769
if ttyp == 0:
770
if absolute: term = ctx.absmax(term)
771
if squared: term = term**2
772
unknown += term
773
continue
774
if absolute:
775
if squared:
776
if ttyp == 1:
777
MPF_mul(&tre, &tre, &tre, opts_exact)
778
MPF_add(&sre, &sre, &tre, workopts)
779
elif ttyp == 2:
780
# |(a+bi)^2| = a^2+b^2
781
MPF_mul(&tre, &tre, &tre, opts_exact)
782
MPF_add(&sre, &sre, &tre, workopts)
783
MPF_mul(&tim, &tim, &tim, opts_exact)
784
MPF_add(&sre, &sre, &tim, workopts)
785
else:
786
if ttyp == 1:
787
MPF_abs(&tre, &tre)
788
MPF_add(&sre, &sre, &tre, workopts)
789
elif ttyp == 2:
790
# |a+bi| = sqrt(a^2+b^2)
791
MPF_mul(&tre, &tre, &tre, opts_exact)
792
MPF_mul(&tim, &tim, &tim, opts_exact)
793
MPF_add(&tre, &tre, &tim, workopts)
794
MPF_sqrt(&tre, &tre, workopts)
795
MPF_add(&sre, &sre, &tre, workopts)
796
elif squared:
797
if ttyp == 1:
798
MPF_mul(&tre, &tre, &tre, opts_exact)
799
MPF_add(&sre, &sre, &tre, workopts)
800
elif ttyp == 2:
801
# (a+bi)^2 = a^2-b^2 + 2i*ab
802
MPF_mul(&tmp, &tre, &tim, opts_exact)
803
MPF_mul(&tmp, &tmp, &MPF_C_2, opts_exact)
804
MPF_add(&sim, &sim, &tmp, workopts)
805
MPF_mul(&tre, &tre, &tre, opts_exact)
806
MPF_add(&sre, &sre, &tre, workopts)
807
MPF_mul(&tim, &tim, &tim, opts_exact)
808
MPF_sub(&sre, &sre, &tim, workopts)
809
styp = 2
810
else:
811
if ttyp == 1:
812
MPF_add(&sre, &sre, &tre, workopts)
813
elif ttyp == 2:
814
MPF_add(&sre, &sre, &tre, workopts)
815
MPF_add(&sim, &sim, &tim, workopts)
816
styp = 2
817
MPF_clear(&tre)
818
MPF_clear(&tim)
819
if styp == 1:
820
rr = PY_NEW(mpf)
821
MPF_set(&rr.value, &sre)
822
MPF_clear(&sre)
823
MPF_clear(&sim)
824
MPF_normalize(&rr.value, global_opts)
825
if unknown is not global_context.zero:
826
return ctx._stupid_add(rr, unknown)
827
return rr
828
elif styp == 2:
829
rc = PY_NEW(mpc)
830
MPF_set(&rc.re, &sre)
831
MPF_set(&rc.im, &sim)
832
MPF_clear(&sre)
833
MPF_clear(&sim)
834
MPF_normalize(&rc.re, global_opts)
835
MPF_normalize(&rc.im, global_opts)
836
if unknown is not global_context.zero:
837
return ctx._stupid_add(rc, unknown)
838
return rc
839
else:
840
MPF_clear(&sre)
841
MPF_clear(&sim)
842
return +unknown
843
finally:
844
sig_off()
845
846
def fdot(ctx, A, B=None, bint conjugate=False):
847
r"""
848
Computes the dot product of the iterables `A` and `B`,
849
850
.. math ::
851
852
\sum_{k=0} A_k B_k.
853
854
Alternatively, :func:`fdot` accepts a single iterable of pairs.
855
In other words, ``fdot(A,B)`` and ``fdot(zip(A,B))`` are equivalent.
856
857
The elements are automatically converted to mpmath numbers.
858
859
TESTS ::
860
861
sage: from mpmath import mp, fdot
862
sage: mp.dps = 15; mp.pretty = False
863
sage: A = [2, 1.5r, 3]
864
sage: B = [1, -1, 2]
865
sage: fdot(A, B)
866
mpf('6.5')
867
sage: zip(A, B)
868
[(2, 1), (1.5, -1), (3, 2)]
869
sage: fdot(_)
870
mpf('6.5')
871
"""
872
if B:
873
A = zip(A, B)
874
cdef MPF sre, sim, tre, tim, ure, uim, tmp
875
cdef mpf rr
876
cdef mpc rc
877
cdef MPopts workopts
878
cdef int styp, ttyp, utyp
879
MPF_init(&sre)
880
MPF_init(&sim)
881
MPF_init(&tre)
882
MPF_init(&tim)
883
MPF_init(&ure)
884
MPF_init(&uim)
885
MPF_init(&tmp)
886
workopts = global_opts
887
workopts.prec = workopts.prec * 2 + 50
888
workopts.rounding = ROUND_D
889
unknown = global_context.zero
890
styp = 1
891
for a, b in A:
892
ttyp = MPF_set_any(&tre, &tim, a, workopts, 0)
893
utyp = MPF_set_any(&ure, &uim, b, workopts, 0)
894
if utyp == 2 and conjugate:
895
MPF_neg(&uim, &uim);
896
if ttyp == 0 or utyp == 0:
897
if conjugate:
898
b = b.conj()
899
unknown += a * b
900
continue
901
styp = max(styp, ttyp)
902
styp = max(styp, utyp)
903
if ttyp == 1:
904
if utyp == 1:
905
MPF_mul(&tre, &tre, &ure, opts_exact)
906
MPF_add(&sre, &sre, &tre, workopts)
907
elif utyp == 2:
908
MPF_mul(&ure, &ure, &tre, opts_exact)
909
MPF_mul(&uim, &uim, &tre, opts_exact)
910
MPF_add(&sre, &sre, &ure, workopts)
911
MPF_add(&sim, &sim, &uim, workopts)
912
styp = 2
913
elif ttyp == 2:
914
styp = 2
915
if utyp == 1:
916
MPF_mul(&tre, &tre, &ure, opts_exact)
917
MPF_mul(&tim, &tim, &ure, opts_exact)
918
MPF_add(&sre, &sre, &tre, workopts)
919
MPF_add(&sim, &sim, &tim, workopts)
920
elif utyp == 2:
921
MPF_mul(&tmp, &tre, &ure, opts_exact)
922
MPF_add(&sre, &sre, &tmp, workopts)
923
MPF_mul(&tmp, &tim, &uim, opts_exact)
924
MPF_sub(&sre, &sre, &tmp, workopts)
925
MPF_mul(&tmp, &tim, &ure, opts_exact)
926
MPF_add(&sim, &sim, &tmp, workopts)
927
MPF_mul(&tmp, &tre, &uim, opts_exact)
928
MPF_add(&sim, &sim, &tmp, workopts)
929
MPF_clear(&tre)
930
MPF_clear(&tim)
931
MPF_clear(&ure)
932
MPF_clear(&uim)
933
MPF_clear(&tmp)
934
if styp == 1:
935
rr = PY_NEW(mpf)
936
MPF_set(&rr.value, &sre)
937
MPF_clear(&sre)
938
MPF_clear(&sim)
939
MPF_normalize(&rr.value, global_opts)
940
if unknown is not global_context.zero:
941
return ctx._stupid_add(rr, unknown)
942
return rr
943
elif styp == 2:
944
rc = PY_NEW(mpc)
945
MPF_set(&rc.re, &sre)
946
MPF_set(&rc.im, &sim)
947
MPF_clear(&sre)
948
MPF_clear(&sim)
949
MPF_normalize(&rc.re, global_opts)
950
MPF_normalize(&rc.im, global_opts)
951
if unknown is not global_context.zero:
952
return ctx._stupid_add(rc, unknown)
953
return rc
954
else:
955
MPF_clear(&sre)
956
MPF_clear(&sim)
957
return +unknown
958
959
# Doing a+b directly doesn't work with mpi, presumably due to
960
# Cython trying to be clever with the operation resolution
961
cdef _stupid_add(ctx, a, b):
962
return a + b
963
964
def _convert_param(ctx, x):
965
"""
966
Internal function for parsing a hypergeometric function parameter.
967
Retrurns (T, x) where T = 'Z', 'Q', 'R', 'C' depending on the
968
type of the parameter, and with x converted to the canonical
969
mpmath type.
970
971
TESTS ::
972
973
sage: from mpmath import mp
974
sage: mp.pretty = True
975
sage: (x, T) = mp._convert_param(3)
976
sage: (x, type(x).__name__, T)
977
(3, 'int', 'Z')
978
sage: (x, T) = mp._convert_param(2.5)
979
sage: (x, type(x).__name__, T)
980
(mpq(5,2), 'mpq', 'Q')
981
sage: (x, T) = mp._convert_param(2.3)
982
sage: (x, type(x).__name__, T)
983
(2.3, 'mpf', 'R')
984
sage: (x, T) = mp._convert_param(2+3j)
985
sage: (x, type(x).__name__, T)
986
((2.0 + 3.0j), 'mpc', 'C')
987
sage: mp.pretty = False
988
989
"""
990
cdef MPF v
991
cdef bint ismpf, ismpc
992
if PyInt_Check(x) or PyLong_Check(x) or PY_TYPE_CHECK(x, Integer):
993
return int(x), 'Z'
994
if PY_TYPE_CHECK(x, tuple):
995
p, q = x
996
p = int(p)
997
q = int(q)
998
if not p % q:
999
return p // q, 'Z'
1000
return rationallib.mpq((p,q)), 'Q'
1001
if PY_TYPE_CHECK(x, basestring) and '/' in x:
1002
p, q = x.split('/')
1003
p = int(p)
1004
q = int(q)
1005
if not p % q:
1006
return p // q, 'Z'
1007
return rationallib.mpq((p,q)), 'Q'
1008
if PY_TYPE_CHECK(x, constant):
1009
return x, 'R'
1010
ismpf = PY_TYPE_CHECK(x, mpf)
1011
ismpc = PY_TYPE_CHECK(x, mpc)
1012
if not (ismpf or ismpc):
1013
x = global_context.convert(x)
1014
ismpf = PY_TYPE_CHECK(x, mpf)
1015
ismpc = PY_TYPE_CHECK(x, mpc)
1016
if not (ismpf or ismpc):
1017
return x, 'U'
1018
if ismpf:
1019
v = (<mpf>x).value
1020
elif ismpc:
1021
if (<mpc>x).im.special != S_ZERO:
1022
return x, 'C'
1023
x = (<mpc>x).real
1024
v = (<mpc>x).re
1025
# A real number
1026
if v.special == S_ZERO:
1027
return 0, 'Z'
1028
if v.special != S_NORMAL:
1029
return x, 'U'
1030
if mpz_sgn(v.exp) >= 0:
1031
return (mpzi(v.man) << mpzi(v.exp)), 'Z'
1032
if mpz_cmp_si(v.exp, -4) > 0:
1033
p = mpzi(v.man)
1034
q = 1 << (-mpzi(v.exp))
1035
return rationallib.mpq((p,q)), 'Q'
1036
return x, 'R'
1037
1038
def mag(ctx, x):
1039
"""
1040
Quick logarithmic magnitude estimate of a number. Returns an
1041
integer or infinity `m` such that `|x| <= 2^m`. It is not
1042
guaranteed that `m` is an optimal bound, but it will never
1043
be too large by more than 2 (and probably not more than 1).
1044
1045
TESTS::
1046
1047
sage: from mpmath import *
1048
sage: mp.pretty = True
1049
sage: mag(10), mag(10.0), mag(mpf(10)), int(ceil(log(10,2)))
1050
(4, 4, 4, 4)
1051
sage: mag(10j), mag(10+10j)
1052
(4, 5)
1053
sage: mag(0.01), int(ceil(log(0.01,2)))
1054
(-6, -6)
1055
sage: mag(0), mag(inf), mag(-inf), mag(nan)
1056
(-inf, +inf, +inf, nan)
1057
1058
::
1059
1060
sage: class MyInt(int):
1061
... pass
1062
sage: class MyLong(long):
1063
... pass
1064
sage: class MyFloat(float):
1065
... pass
1066
sage: mag(MyInt(10)), mag(MyLong(10))
1067
(4, 4)
1068
1069
"""
1070
cdef int typ
1071
if PyInt_Check(x) or PyLong_Check(x) or PY_TYPE_CHECK(x, Integer):
1072
mpz_set_integer(tmp_opx_re.man, x)
1073
if mpz_sgn(tmp_opx_re.man) == 0:
1074
return global_context.ninf
1075
else:
1076
return mpz_sizeinbase(tmp_opx_re.man,2)
1077
if PY_TYPE_CHECK(x, rationallib.mpq):
1078
p, q = x._mpq_
1079
mpz_set_integer(tmp_opx_re.man, int(p))
1080
if mpz_sgn(tmp_opx_re.man) == 0:
1081
return global_context.ninf
1082
mpz_set_integer(tmp_opx_re.exp, int(q))
1083
return 1 + mpz_sizeinbase(tmp_opx_re.man,2) + mpz_sizeinbase(tmp_opx_re.exp,2)
1084
typ = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, False)
1085
if typ == 1:
1086
if tmp_opx_re.special == S_ZERO:
1087
return global_context.ninf
1088
if tmp_opx_re.special == S_INF or tmp_opx_re.special == S_NINF:
1089
return global_context.inf
1090
if tmp_opx_re.special != S_NORMAL:
1091
return global_context.nan
1092
mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, mpz_sizeinbase(tmp_opx_re.man, 2))
1093
return mpzi(tmp_opx_re.exp)
1094
if typ == 2:
1095
if tmp_opx_re.special == S_NAN or tmp_opx_im.special == S_NAN:
1096
return global_context.nan
1097
if tmp_opx_re.special == S_INF or tmp_opx_im.special == S_NINF or \
1098
tmp_opx_im.special == S_INF or tmp_opx_im.special == S_NINF:
1099
return global_context.inf
1100
if tmp_opx_re.special == S_ZERO:
1101
if tmp_opx_im.special == S_ZERO:
1102
return global_context.ninf
1103
else:
1104
mpz_add_ui(tmp_opx_im.exp, tmp_opx_im.exp, mpz_sizeinbase(tmp_opx_im.man, 2))
1105
return mpzi(tmp_opx_im.exp)
1106
elif tmp_opx_im.special == S_ZERO:
1107
mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, mpz_sizeinbase(tmp_opx_re.man, 2))
1108
return mpzi(tmp_opx_re.exp)
1109
mpz_add_ui(tmp_opx_im.exp, tmp_opx_im.exp, mpz_sizeinbase(tmp_opx_im.man, 2))
1110
mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, mpz_sizeinbase(tmp_opx_re.man, 2))
1111
if mpz_cmp(tmp_opx_re.exp, tmp_opx_im.exp) >= 0:
1112
mpz_add_ui(tmp_opx_re.exp, tmp_opx_re.exp, 1)
1113
return mpzi(tmp_opx_re.exp)
1114
else:
1115
mpz_add_ui(tmp_opx_im.exp, tmp_opx_im.exp, 1)
1116
return mpzi(tmp_opx_im.exp)
1117
raise TypeError("requires an mpf/mpc")
1118
1119
def _wrap_libmp_function(ctx, mpf_f, mpc_f=None, mpi_f=None, doc="<no doc>"):
1120
"""
1121
Create a high-level mpmath function from base functions working
1122
on mpf, mpc and mpi tuple data.
1123
1124
TESTS ::
1125
1126
sage: from mpmath import mp
1127
sage: mp.pretty = False
1128
sage: f = lambda x, prec, rnd: x
1129
sage: g = mp._wrap_libmp_function(f)
1130
sage: g(mp.mpf(2))
1131
mpf('2.0')
1132
1133
"""
1134
name = mpf_f.__name__[4:]
1135
doc = function_docs.__dict__.get(name, "Computes the %s of x" % doc)
1136
# workaround lack of closures in Cython
1137
f_cls = type(name, (wrapped_libmp_function,), {'__doc__':doc})
1138
f = f_cls(mpf_f, mpc_f, mpi_f, doc)
1139
return f
1140
1141
@classmethod
1142
def _wrap_specfun(cls, name, f, wrap):
1143
"""
1144
Adds the given function as a method to the context object,
1145
optionally wrapping it to do automatic conversions and
1146
allocating a small number of guard bits to suppress
1147
typical roundoff error.
1148
1149
TESTS ::
1150
1151
sage: from mpmath import mp
1152
sage: mp._wrap_specfun("foo", lambda ctx, x: ctx.prec + x, True)
1153
sage: mp.pretty = False; mp.prec = 53
1154
sage: mp.foo(5) # 53 + 10 guard bits + 5
1155
mpf('68.0')
1156
1157
"""
1158
doc = function_docs.__dict__.get(name, getattr(f, '__doc__', '<no doc>'))
1159
if wrap:
1160
# workaround lack of closures in Cython
1161
f_wrapped_cls = type(name, (wrapped_specfun,), {'__doc__':doc})
1162
f_wrapped = f_wrapped_cls(name, f)
1163
else:
1164
f_wrapped = f
1165
f_wrapped.__doc__ = doc
1166
setattr(cls, name, f_wrapped)
1167
1168
cdef MPopts _fun_get_opts(ctx, kwargs):
1169
"""
1170
Helper function that extracts precision and rounding information
1171
from kwargs, or returns the global working precision and rounding
1172
if no options are specified.
1173
"""
1174
cdef MPopts opts
1175
opts.prec = global_opts.prec
1176
opts.rounding = global_opts.rounding
1177
if kwargs:
1178
if 'prec' in kwargs:
1179
opts.prec = int(kwargs['prec'])
1180
if 'dps' in kwargs:
1181
opts.prec = libmp.dps_to_prec(int(kwargs['dps']))
1182
if 'rounding' in kwargs:
1183
opts.rounding = rndmode_from_python(kwargs['rounding'])
1184
return opts
1185
1186
def _sage_sqrt(ctx, x, **kwargs):
1187
"""
1188
Square root of an mpmath number x, using the Sage mpmath backend.
1189
1190
TESTS ::
1191
1192
sage: from mpmath import mp
1193
sage: mp.dps = 15
1194
sage: print mp.sqrt(2) # indirect doctest
1195
1.4142135623731
1196
sage: print mp.sqrt(-2)
1197
(0.0 + 1.4142135623731j)
1198
sage: print mp.sqrt(2+2j)
1199
(1.55377397403004 + 0.643594252905583j)
1200
1201
"""
1202
cdef MPopts opts
1203
cdef int typx
1204
cdef mpf rr
1205
cdef mpc rc
1206
cdef tuple rev, imv
1207
opts = ctx._fun_get_opts(kwargs)
1208
typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, 1)
1209
if typx == 1:
1210
rr = PY_NEW(mpf)
1211
if MPF_sqrt(&rr.value, &tmp_opx_re, opts):
1212
rc = PY_NEW(mpc)
1213
MPF_complex_sqrt(&rc.re, &rc.im, &tmp_opx_re, &MPF_C_0, opts)
1214
return rc
1215
return rr
1216
elif typx == 2:
1217
rc = PY_NEW(mpc)
1218
MPF_complex_sqrt(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts)
1219
return rc
1220
else:
1221
raise NotImplementedError("unknown argument")
1222
1223
def _sage_exp(ctx, x, **kwargs):
1224
"""
1225
Exponential function of an mpmath number x, using the Sage
1226
mpmath backend.
1227
1228
EXAMPLES::
1229
1230
sage: from mpmath import mp
1231
sage: mp.dps = 15
1232
sage: print mp.exp(2) # indirect doctest
1233
7.38905609893065
1234
sage: print mp.exp(2+2j)
1235
(-3.07493232063936 + 6.71884969742825j)
1236
1237
"""
1238
cdef MPopts opts
1239
cdef int typx
1240
cdef mpf rr
1241
cdef mpc rc
1242
cdef tuple rev, imv
1243
opts = ctx._fun_get_opts(kwargs)
1244
typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, opts, 1)
1245
if typx == 1:
1246
rr = PY_NEW(mpf)
1247
MPF_exp(&rr.value, &tmp_opx_re, opts)
1248
return rr
1249
elif typx == 2:
1250
rc = PY_NEW(mpc)
1251
MPF_complex_exp(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts)
1252
return rc
1253
else:
1254
raise NotImplementedError("unknown argument")
1255
1256
def _sage_cos(ctx, x, **kwargs):
1257
"""
1258
Cosine of an mpmath number x, using the Sage mpmath backend.
1259
1260
EXAMPLES::
1261
1262
sage: from mpmath import mp
1263
sage: mp.dps = 15
1264
sage: print mp.cos(2) # indirect doctest
1265
-0.416146836547142
1266
sage: print mp.cos(2+2j)
1267
(-1.56562583531574 - 3.29789483631124j)
1268
1269
"""
1270
cdef MPopts opts
1271
cdef int typx
1272
cdef mpf rr
1273
cdef mpc rc
1274
cdef tuple rev, imv
1275
opts = ctx._fun_get_opts(kwargs)
1276
typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1)
1277
if typx == 1:
1278
rr = PY_NEW(mpf)
1279
MPF_cos(&rr.value, &tmp_opx_re, opts)
1280
return rr
1281
elif typx == 2:
1282
rev = MPF_to_tuple(&tmp_opx_re)
1283
imv = MPF_to_tuple(&tmp_opx_im)
1284
cxu = libmp.mpc_cos((rev, imv), opts.prec,
1285
rndmode_to_python(opts.rounding))
1286
rc = PY_NEW(mpc)
1287
MPF_set_tuple(&rc.re, cxu[0])
1288
MPF_set_tuple(&rc.im, cxu[1])
1289
return rc
1290
else:
1291
raise NotImplementedError("unknown argument")
1292
1293
def _sage_sin(ctx, x, **kwargs):
1294
"""
1295
Sine of an mpmath number x, using the Sage mpmath backend.
1296
1297
EXAMPLES::
1298
1299
sage: from mpmath import mp
1300
sage: mp.dps = 15
1301
sage: print mp.sin(2) # indirect doctest
1302
0.909297426825682
1303
sage: print mp.sin(2+2j)
1304
(3.42095486111701 - 1.50930648532362j)
1305
1306
"""
1307
cdef MPopts opts
1308
cdef int typx
1309
cdef mpf rr
1310
cdef mpc rc
1311
cdef tuple rev, imv
1312
opts = ctx._fun_get_opts(kwargs)
1313
typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1)
1314
if typx == 1:
1315
rr = PY_NEW(mpf)
1316
MPF_sin(&rr.value, &tmp_opx_re, opts)
1317
return rr
1318
elif typx == 2:
1319
rev = MPF_to_tuple(&tmp_opx_re)
1320
imv = MPF_to_tuple(&tmp_opx_im)
1321
cxu = libmp.mpc_sin((rev, imv), opts.prec,
1322
rndmode_to_python(opts.rounding))
1323
rc = PY_NEW(mpc)
1324
MPF_set_tuple(&rc.re, cxu[0])
1325
MPF_set_tuple(&rc.im, cxu[1])
1326
return rc
1327
else:
1328
raise NotImplementedError("unknown argument")
1329
1330
def _sage_ln(ctx, x, **kwargs):
1331
"""
1332
Natural logarithm of an mpmath number x, using the Sage mpmath backend.
1333
1334
EXAMPLES::
1335
1336
sage: from mpmath import mp
1337
sage: print mp.ln(2) # indirect doctest
1338
0.693147180559945
1339
sage: print mp.ln(-2)
1340
(0.693147180559945 + 3.14159265358979j)
1341
sage: print mp.ln(2+2j)
1342
(1.03972077083992 + 0.785398163397448j)
1343
1344
"""
1345
cdef MPopts opts
1346
cdef int typx
1347
cdef mpf rr
1348
cdef mpc rc
1349
cdef tuple rev, imv
1350
typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1)
1351
prec = global_opts.prec
1352
rounding = rndmode_to_python(global_opts.rounding)
1353
opts.prec = global_opts.prec
1354
opts.rounding = global_opts.rounding
1355
if kwargs:
1356
if 'prec' in kwargs: opts.prec = int(kwargs['prec'])
1357
if 'dps' in kwargs: opts.prec = libmp.dps_to_prec(int(kwargs['dps']))
1358
if 'rounding' in kwargs: opts.rounding = rndmode_from_python(kwargs['rounding'])
1359
if typx == 1:
1360
if MPF_sgn(&tmp_opx_re) < 0:
1361
rc = PY_NEW(mpc)
1362
MPF_log(&rc.re, &tmp_opx_re, opts)
1363
MPF_set_pi(&rc.im, opts)
1364
return rc
1365
else:
1366
rr = PY_NEW(mpf)
1367
MPF_log(&rr.value, &tmp_opx_re, opts)
1368
return rr
1369
elif typx == 2:
1370
rev = MPF_to_tuple(&tmp_opx_re)
1371
imv = MPF_to_tuple(&tmp_opx_im)
1372
cxu = libmp.mpc_log((rev, imv), opts.prec, rndmode_to_python(opts.rounding))
1373
rc = PY_NEW(mpc)
1374
MPF_set_tuple(&rc.re, cxu[0])
1375
MPF_set_tuple(&rc.im, cxu[1])
1376
return rc
1377
1378
#rc = PY_NEW(mpc)
1379
#MPF_complex_log(&rc.re, &rc.im, &tmp_opx_re, &tmp_opx_im, opts)
1380
#return rc
1381
else:
1382
raise NotImplementedError("unknown argument")
1383
1384
1385
cdef class wrapped_libmp_function:
1386
1387
cdef public mpf_f, mpc_f, mpi_f, name, __name__, __doc__
1388
1389
def __init__(self, mpf_f, mpc_f=None, mpi_f=None, doc="<no doc>"):
1390
"""
1391
Create a high-level mpmath function from base functions working
1392
on mpf, mpc and mpi tuple data.
1393
1394
TESTS ::
1395
1396
sage: from sage.libs.mpmath.ext_main import wrapped_libmp_function
1397
sage: from mpmath import mp
1398
sage: from mpmath.libmp import mpf_exp, mpf_sqrt
1399
sage: f = lambda x, prec, rnd: mpf_exp(mpf_sqrt(x, prec, rnd), prec, rnd)
1400
sage: g = wrapped_libmp_function(f)
1401
sage: g(mp.mpf(3))
1402
mpf('5.6522336740340915')
1403
sage: mp.exp(mp.sqrt(3))
1404
mpf('5.6522336740340915')
1405
sage: g(mp.mpf(3), prec=10)
1406
mpf('5.65625')
1407
sage: g(mp.mpf(3), prec=10, rounding='u')
1408
mpf('5.65625')
1409
sage: g(mp.mpf(3), prec=10, rounding='d')
1410
mpf('5.640625')
1411
"""
1412
self.mpf_f = mpf_f
1413
self.mpc_f = mpc_f
1414
self.mpi_f = mpi_f
1415
self.name = self.__name__ = mpf_f.__name__[4:]
1416
self.__doc__ = function_docs.__dict__.get(self.name, "Computes the %s of x" % doc)
1417
1418
def __call__(self, x, **kwargs):
1419
"""
1420
A wrapped mpmath library function performs automatic
1421
conversions and uses the default working precision
1422
unless overridden ::
1423
1424
sage: from mpmath import mp
1425
sage: mp.sinh(2)
1426
mpf('3.6268604078470186')
1427
sage: mp.sinh(2, prec=10)
1428
mpf('3.625')
1429
sage: mp.sinh(2, prec=10, rounding='d')
1430
mpf('3.625')
1431
sage: mp.sinh(2, prec=10, rounding='u')
1432
mpf('3.62890625')
1433
"""
1434
cdef int typx
1435
cdef tuple rev, imv, reu, cxu
1436
cdef mpf rr
1437
cdef mpc rc
1438
prec = global_opts.prec
1439
rounding = rndmode_to_python(global_opts.rounding)
1440
if kwargs:
1441
if 'prec' in kwargs: prec = int(kwargs['prec'])
1442
if 'dps' in kwargs: prec = libmp.dps_to_prec(int(kwargs['dps']))
1443
if 'rounding' in kwargs: rounding = kwargs['rounding']
1444
typx = MPF_set_any(&tmp_opx_re, &tmp_opx_im, x, global_opts, 1)
1445
if typx == 1:
1446
rev = MPF_to_tuple(&tmp_opx_re)
1447
try:
1448
reu = self.mpf_f(rev, prec, rounding)
1449
rr = PY_NEW(mpf)
1450
MPF_set_tuple(&rr.value, reu)
1451
return rr
1452
except libmp.ComplexResult:
1453
if global_context.trap_complex:
1454
raise
1455
cxu = self.mpc_f((rev, libmp.fzero), prec, rounding)
1456
rc = PY_NEW(mpc)
1457
MPF_set_tuple(&rc.re, cxu[0])
1458
MPF_set_tuple(&rc.im, cxu[1])
1459
return rc
1460
if typx == 2:
1461
rev = MPF_to_tuple(&tmp_opx_re)
1462
imv = MPF_to_tuple(&tmp_opx_im)
1463
cxu = self.mpc_f((rev, imv), prec, rounding)
1464
rc = PY_NEW(mpc)
1465
MPF_set_tuple(&rc.re, cxu[0])
1466
MPF_set_tuple(&rc.im, cxu[1])
1467
return rc
1468
x = global_context.convert(x)
1469
if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"):
1470
return self.__call__(x, **kwargs)
1471
#if hasattr(x, "_mpi_"):
1472
# if self.mpi_f:
1473
# return global_context.make_mpi(self.mpi_f(x._mpi_, prec))
1474
raise NotImplementedError("%s of a %s" % (self.name, type(x)))
1475
1476
1477
1478
cdef class wrapped_specfun:
1479
cdef public f, name, __name__, __doc__
1480
1481
def __init__(self, name, f):
1482
"""
1483
Creates an object holding a wrapped mpmath function
1484
along with metadata (name and documentation).
1485
1486
TESTS ::
1487
1488
sage: import mpmath
1489
sage: from sage.libs.mpmath.ext_main import wrapped_specfun
1490
sage: f = wrapped_specfun("f", lambda ctx, x: x)
1491
sage: f.name
1492
'f'
1493
"""
1494
self.name = self.__name__ = name
1495
self.f = f
1496
self.__doc__ = function_docs.__dict__.get(name, "<no doc>")
1497
1498
def __call__(self, *args, **kwargs):
1499
"""
1500
Call wrapped mpmath function. Arguments are automatically converted
1501
to mpmath number, and the internal working precision is increased
1502
by a few bits to suppress typical rounding errors ::
1503
1504
sage: from mpmath import mp
1505
sage: from sage.libs.mpmath.ext_main import wrapped_specfun
1506
sage: f = wrapped_specfun("f", lambda ctx, x: x + ctx.prec)
1507
sage: f("1") # 53 + 10 guard bits + 1
1508
mpf('64.0')
1509
1510
"""
1511
cdef int origprec
1512
args = [global_context.convert(a) for a in args]
1513
origprec = global_opts.prec
1514
global_opts.prec += 10
1515
try:
1516
retval = self.f(global_context, *args, **kwargs)
1517
finally:
1518
global_opts.prec = origprec
1519
return +retval
1520
1521
1522
cdef class mpnumber:
1523
1524
def __richcmp__(self, other, int op):
1525
"""
1526
Comparison of mpmath numbers. Compatible numerical types
1527
are automatically converted to mpmath numbers ::
1528
1529
sage: from mpmath import mpf, mpc
1530
sage: mpf(3) == mpc(3)
1531
True
1532
sage: mpf(3) == mpc(4)
1533
False
1534
sage: mpf(3) == float(3)
1535
True
1536
sage: mpf(3) < float(2.5)
1537
False
1538
sage: mpc(3) < mpc(4)
1539
Traceback (most recent call last):
1540
...
1541
ValueError: cannot compare complex numbers
1542
1543
"""
1544
return binop(OP_RICHCMP+op, self, other, global_opts)
1545
1546
def __add__(self, other):
1547
"""
1548
Addition of mpmath numbers. Compatible numerical types
1549
are automatically converted to mpmath numbers ::
1550
1551
sage: from mpmath import mpf, mpc
1552
sage: mpf(3) + mpc(3)
1553
mpc(real='6.0', imag='0.0')
1554
sage: float(4) + mpf(3)
1555
mpf('7.0')
1556
"""
1557
return binop(OP_ADD, self, other, global_opts)
1558
1559
def __sub__(self, other):
1560
"""
1561
Subtraction of mpmath numbers. Compatible numerical types
1562
are automatically converted to mpmath numbers ::
1563
1564
sage: from mpmath import mpf, mpc
1565
sage: mpf(5) - mpc(3)
1566
mpc(real='2.0', imag='0.0')
1567
sage: float(4) - mpf(3)
1568
mpf('1.0')
1569
"""
1570
return binop(OP_SUB, self, other, global_opts)
1571
1572
def __mul__(self, other):
1573
"""
1574
Multiplication of mpmath numbers. Compatible numerical types
1575
are automatically converted to mpmath numbers ::
1576
1577
sage: from mpmath import mpf, mpc
1578
sage: mpf(5) * mpc(3)
1579
mpc(real='15.0', imag='0.0')
1580
sage: float(4) * mpf(3)
1581
mpf('12.0')
1582
"""
1583
return binop(OP_MUL, self, other, global_opts)
1584
1585
def __div__(self, other):
1586
"""
1587
Division of mpmath numbers. Compatible numerical types
1588
are automatically converted to mpmath numbers ::
1589
1590
sage: from mpmath import mpf, mpc
1591
sage: mpf(10) / mpc(5)
1592
mpc(real='2.0', imag='0.0')
1593
sage: float(9) / mpf(3)
1594
mpf('3.0')
1595
"""
1596
return binop(OP_DIV, self, other, global_opts)
1597
1598
def __truediv__(self, other):
1599
"""
1600
Division of mpmath numbers. Compatible numerical types
1601
are automatically converted to mpmath numbers ::
1602
1603
sage: from mpmath import mpf, mpc
1604
sage: mpf(10) / mpc(5)
1605
mpc(real='2.0', imag='0.0')
1606
sage: float(9) / mpf(3)
1607
mpf('3.0')
1608
"""
1609
return binop(OP_DIV, self, other, global_opts)
1610
1611
def __mod__(self, other):
1612
"""
1613
Remainder of mpmath numbers. Compatible numerical types
1614
are automatically converted to mpmath numbers ::
1615
1616
sage: from mpmath import mpf
1617
sage: mpf(12) % float(7)
1618
mpf('5.0')
1619
"""
1620
return binop(OP_MOD, self, other, global_opts)
1621
1622
def __pow__(self, other, mod):
1623
"""
1624
Exponentiation of mpmath numbers. Compatible numerical types
1625
are automatically converted to mpmath numbers ::
1626
1627
sage: from mpmath import mpf, mpc
1628
sage: mpf(10) ** mpc(3)
1629
mpc(real='1000.0', imag='0.0')
1630
sage: mpf(3) ** float(2)
1631
mpf('9.0')
1632
"""
1633
if mod is not None:
1634
raise ValueError("three-argument pow not supported")
1635
return binop(OP_POW, self, other, global_opts)
1636
1637
def ae(s, t, rel_eps=None, abs_eps=None):
1638
"""
1639
Check if two numbers are approximately equal to within the specified
1640
tolerance (see mp.almosteq for documentation) ::
1641
1642
sage: from mpmath import mpf, mpc
1643
sage: mpf(3).ae(mpc(3,1e-10))
1644
False
1645
sage: mpf(3).ae(mpc(3,1e-10), rel_eps=1e-5)
1646
True
1647
"""
1648
return global_context.almosteq(s, t, rel_eps, abs_eps)
1649
1650
cdef class mpf_base(mpnumber):
1651
1652
# Shared methods for mpf, constant. However, somehow some methods
1653
# (hash?, __richcmp__?) aren't inerited, so they have to
1654
# be defined multiple times. TODO: fix this.
1655
1656
def __hash__(self):
1657
"""
1658
Support hashing of derived classes ::
1659
1660
sage: from mpmath import mpf
1661
sage: from sage.libs.mpmath.ext_main import mpf_base
1662
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1663
sage: hash(X()) == hash(float(X()))
1664
True
1665
"""
1666
return libmp.mpf_hash(self._mpf_)
1667
1668
def __repr__(self):
1669
"""
1670
Support repr() of derived classes ::
1671
1672
sage: from mpmath import mpf
1673
sage: from sage.libs.mpmath.ext_main import mpf_base
1674
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1675
sage: repr(X())
1676
"mpf('3.25')"
1677
"""
1678
if global_context.pretty:
1679
return self.__str__()
1680
n = repr_dps(global_opts.prec)
1681
return "mpf('%s')" % to_str(self._mpf_, n)
1682
1683
def __str__(self):
1684
"""
1685
Support str() of derived classes ::
1686
1687
sage: from mpmath import mpf
1688
sage: from sage.libs.mpmath.ext_main import mpf_base
1689
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1690
sage: str(X())
1691
'3.25'
1692
"""
1693
return to_str(self._mpf_, global_context._str_digits)
1694
1695
@property
1696
def real(self):
1697
"""
1698
Support real part of derived classes ::
1699
1700
sage: from mpmath import mpf
1701
sage: from sage.libs.mpmath.ext_main import mpf_base
1702
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1703
sage: X().real
1704
mpf('3.25')
1705
"""
1706
return self
1707
1708
@property
1709
def imag(self):
1710
"""
1711
Support imaginary part of derived classes ::
1712
1713
sage: from mpmath import mpf
1714
sage: from sage.libs.mpmath.ext_main import mpf_base
1715
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1716
sage: X().imag
1717
mpf('0.0')
1718
"""
1719
return global_context.zero
1720
1721
def conjugate(self):
1722
"""
1723
Support complex conjugate of derived classes ::
1724
1725
sage: from mpmath import mpf
1726
sage: from sage.libs.mpmath.ext_main import mpf_base
1727
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1728
sage: X().conjugate()
1729
mpf('3.25')
1730
"""
1731
return self
1732
1733
@property
1734
def man(self):
1735
"""
1736
Support mantissa extraction of derived classes ::
1737
1738
sage: from mpmath import mpf
1739
sage: from sage.libs.mpmath.ext_main import mpf_base
1740
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1741
sage: X().man
1742
13
1743
"""
1744
return self._mpf_[1]
1745
1746
@property
1747
def exp(self):
1748
"""
1749
Support exponent extraction of derived classes ::
1750
1751
sage: from mpmath import mpf
1752
sage: from sage.libs.mpmath.ext_main import mpf_base
1753
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1754
sage: X().exp
1755
-2
1756
"""
1757
return self._mpf_[2]
1758
1759
@property
1760
def bc(self):
1761
"""
1762
Support bitcount extraction of derived classes ::
1763
1764
sage: from mpmath import mpf
1765
sage: from sage.libs.mpmath.ext_main import mpf_base
1766
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1767
sage: X().bc
1768
4
1769
"""
1770
return self._mpf_[3]
1771
1772
# XXX: optimize
1773
def __int__(self):
1774
"""
1775
Support integer conversion for derived classes ::
1776
1777
sage: from mpmath import mpf
1778
sage: from sage.libs.mpmath.ext_main import mpf_base
1779
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1780
sage: int(X())
1781
3
1782
"""
1783
return int(libmp.to_int(self._mpf_))
1784
1785
def __long__(self):
1786
"""
1787
Support long conversion for derived classes ::
1788
1789
sage: from mpmath import mpf
1790
sage: from sage.libs.mpmath.ext_main import mpf_base
1791
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1792
sage: long(X())
1793
3L
1794
"""
1795
return long(self.__int__())
1796
1797
def __float__(self):
1798
"""
1799
Support float conversion for derived classes ::
1800
1801
sage: from mpmath import mpf
1802
sage: from sage.libs.mpmath.ext_main import mpf_base
1803
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1804
sage: float(X())
1805
3.25
1806
"""
1807
return libmp.to_float(self._mpf_)
1808
1809
def __complex__(self):
1810
"""
1811
Support complex conversion for derived classes ::
1812
1813
sage: from mpmath import mpf
1814
sage: from sage.libs.mpmath.ext_main import mpf_base
1815
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1816
sage: complex(X())
1817
(3.25+0j)
1818
"""
1819
return complex(float(self))
1820
1821
def to_fixed(self, prec):
1822
"""
1823
Support conversion to a fixed-point integer for derived classes ::
1824
1825
sage: from mpmath import mpf
1826
sage: from sage.libs.mpmath.ext_main import mpf_base
1827
sage: class X(mpf_base): _mpf_ = mpf(3.25)._mpf_
1828
sage: X().to_fixed(30)
1829
3489660928
1830
"""
1831
return libmp.to_fixed(self._mpf_, prec)
1832
1833
def __getstate__(self):
1834
return libmp.to_pickable(self._mpf_)
1835
1836
def __setstate__(self, val):
1837
self._mpf_ = libmp.from_pickable(val)
1838
1839
1840
cdef class mpf(mpf_base):
1841
"""
1842
An mpf instance holds a real-valued floating-point number. mpf:s
1843
work analogously to Python floats, but support arbitrary-precision
1844
arithmetic.
1845
"""
1846
1847
cdef MPF value
1848
1849
def __init__(self, x=0, **kwargs):
1850
"""
1851
Create an mpf from a recognized type, optionally rounding
1852
to a precision and in a direction different from the default.
1853
1854
TESTS ::
1855
1856
sage: from mpmath import mpf
1857
sage: mpf()
1858
mpf('0.0')
1859
sage: mpf(5)
1860
mpf('5.0')
1861
sage: mpf('inf')
1862
mpf('+inf')
1863
sage: mpf('nan')
1864
mpf('nan')
1865
sage: mpf(float(2.5))
1866
mpf('2.5')
1867
sage: mpf("2.5")
1868
mpf('2.5')
1869
sage: mpf("0.3")
1870
mpf('0.29999999999999999')
1871
sage: mpf("0.3", prec=10)
1872
mpf('0.2998046875')
1873
sage: mpf("0.3", prec=10, rounding='u')
1874
mpf('0.30029296875')
1875
1876
"""
1877
cdef MPopts opts
1878
opts = global_opts
1879
if kwargs:
1880
if 'prec' in kwargs: opts.prec = int(kwargs['prec'])
1881
if 'dps' in kwargs: opts.prec = libmp.dps_to_prec(int(kwargs['dps']))
1882
if 'rounding' in kwargs: opts.rounding = rndmode_from_python(kwargs['rounding'])
1883
if MPF_set_any(&self.value, &self.value, x, opts, 1) != 1:
1884
raise TypeError
1885
1886
def __reduce__(self):
1887
"""
1888
Support pickling ::
1889
1890
sage: from mpmath import mpf
1891
sage: loads(dumps(mpf(0.5))) == mpf(0.5)
1892
True
1893
"""
1894
return (mpf, (), self._mpf_)
1895
1896
def _get_mpf(self):
1897
"""
1898
Returns internal representation of self as a tuple
1899
of (sign bit, mantissa, exponent, bitcount) ::
1900
1901
sage: from mpmath import mp
1902
sage: mp.mpf(-3)._mpf_
1903
(1, 3, 0, 2)
1904
"""
1905
return MPF_to_tuple(&self.value)
1906
1907
def _set_mpf(self, v):
1908
"""
1909
Sets tuple value of self (warning: unsafe) ::
1910
1911
sage: from mpmath import mp
1912
sage: x = mp.mpf(-3)
1913
sage: x._mpf_ = (1, 3, -1, 2)
1914
sage: x
1915
mpf('-1.5')
1916
"""
1917
MPF_set_tuple(&self.value, v)
1918
1919
_mpf_ = property(_get_mpf, _set_mpf, doc=_get_mpf.__doc__)
1920
1921
def __nonzero__(self):
1922
"""
1923
Returns whether the number is nonzero ::
1924
1925
sage: from mpmath import mpf
1926
sage: bool(mpf(3.5))
1927
True
1928
sage: bool(mpf(0.0))
1929
False
1930
"""
1931
return self.value.special != S_ZERO
1932
1933
def __hash__(self):
1934
"""
1935
Hash values are compatible with builtin Python floats
1936
when the precision is small enough ::
1937
1938
sage: from mpmath import mpf
1939
sage: hash(mpf(2.5)) == hash(float(2.5))
1940
True
1941
sage: hash(mpf('inf')) == hash(float(Infinity))
1942
True
1943
"""
1944
return libmp.mpf_hash(self._mpf_)
1945
1946
@property
1947
def real(self):
1948
"""
1949
Real part, leaves self unchanged ::
1950
1951
sage: from mpmath import mpf
1952
sage: mpf(2.5).real
1953
mpf('2.5')
1954
"""
1955
return self
1956
1957
@property
1958
def imag(self):
1959
"""
1960
Imaginary part, equal to zero ::
1961
1962
sage: from mpmath import mpf
1963
sage: mpf(2.5).imag
1964
mpf('0.0')
1965
"""
1966
return global_context.zero
1967
1968
def conjugate(self):
1969
"""
1970
Complex conjugate, leaves self unchanged ::
1971
1972
sage: from mpmath import mpf
1973
sage: mpf(2.5).conjugate()
1974
mpf('2.5')
1975
"""
1976
return self
1977
1978
@property
1979
def man(self):
1980
"""
1981
Returns the binary mantissa of self. The result is a Sage
1982
integer ::
1983
1984
sage: from mpmath import mpf
1985
sage: mpf(-500.5).man
1986
1001
1987
sage: type(_)
1988
<type 'sage.rings.integer.Integer'>
1989
"""
1990
return self._mpf_[1]
1991
1992
@property
1993
def exp(self):
1994
"""
1995
Returns the binary exponent of self ::
1996
1997
sage: from mpmath import mpf
1998
sage: mpf(1/64.).exp
1999
-6
2000
"""
2001
return self._mpf_[2]
2002
2003
@property
2004
def bc(self):
2005
"""
2006
Returns the number of bits in the mantissa of self ::
2007
2008
sage: from mpmath import mpf
2009
sage: mpf(-256).bc
2010
1
2011
sage: mpf(-255).bc
2012
8
2013
"""
2014
return self._mpf_[3]
2015
2016
def to_fixed(self, long prec):
2017
"""
2018
Convert to a fixed-point integer of the given precision ::
2019
2020
sage: from mpmath import mpf
2021
sage: mpf(7.25).to_fixed(30)
2022
7784628224
2023
sage: ZZ(7.25 * 2**30)
2024
7784628224
2025
"""
2026
# return libmp.to_fixed(self._mpf_, prec)
2027
MPF_to_fixed(tmp_mpz, &self.value, prec, False)
2028
cdef Integer r
2029
r = PY_NEW(Integer)
2030
mpz_set(r.value, tmp_mpz)
2031
return r
2032
2033
def __int__(self):
2034
"""
2035
Convert to a Python integer (truncating if necessary) ::
2036
2037
sage: from mpmath import mpf
2038
sage: int(mpf(2.5))
2039
2
2040
sage: type(_)
2041
<type 'int'>
2042
"""
2043
MPF_to_fixed(tmp_mpz, &self.value, 0, True)
2044
return mpzi(tmp_mpz)
2045
2046
def __long__(self):
2047
r"""
2048
Convert this mpf value to a long.
2049
2050
(Due to http://bugs.python.org/issue9869, to allow NZMATH to use
2051
this Sage-modified version of mpmath, it is vital that we
2052
return a long, not an int.)
2053
2054
TESTS::
2055
2056
sage: import mpmath
2057
sage: v = mpmath.mpf(2)
2058
sage: class MyLong(long):
2059
... pass
2060
sage: MyLong(v)
2061
2L
2062
"""
2063
MPF_to_fixed(tmp_mpz, &self.value, 0, True)
2064
return mpzl(tmp_mpz)
2065
2066
def __float__(self):
2067
"""
2068
Convert to a double-precision Python float ::
2069
2070
sage: from mpmath import mpf
2071
sage: float(mpf(2.5))
2072
2.5
2073
sage: type(_)
2074
<type 'float'>
2075
"""
2076
return MPF_to_double(&self.value, False)
2077
2078
def __getstate__(self):
2079
"""
2080
Support pickling ::
2081
2082
sage: from mpmath import mpf
2083
sage: loads(dumps(mpf(3))) == mpf(3)
2084
True
2085
"""
2086
return libmp.to_pickable(self._mpf_)
2087
2088
def __setstate__(self, val):
2089
"""
2090
Support pickling ::
2091
2092
sage: from mpmath import mpf
2093
sage: loads(dumps(mpf(3))) == mpf(3)
2094
True
2095
"""
2096
self._mpf_ = libmp.from_pickable(val)
2097
2098
def __cinit__(self):
2099
"""
2100
Create a new mpf ::
2101
2102
sage: from mpmath import mpf
2103
sage: x = mpf()
2104
2105
"""
2106
MPF_init(&self.value)
2107
2108
def __dealloc__(self):
2109
MPF_clear(&self.value)
2110
2111
def __neg__(s):
2112
"""
2113
Negates self, rounded to the current working precision ::
2114
2115
sage: from mpmath import mpf
2116
sage: -mpf(2)
2117
mpf('-2.0')
2118
"""
2119
cdef mpf r = PY_NEW(mpf)
2120
MPF_neg(&r.value, &s.value)
2121
MPF_normalize(&r.value, global_opts)
2122
return r
2123
2124
def __pos__(s):
2125
"""
2126
Rounds the number to the current working precision ::
2127
2128
sage: from mpmath import mp, mpf
2129
sage: mp.prec = 200
2130
sage: x = mpf(1) / 3
2131
sage: x.man
2132
1071292029505993517027974728227441735014801995855195223534251
2133
sage: mp.prec = 53
2134
sage: (+x).man
2135
6004799503160661
2136
sage: print +x
2137
0.333333333333333
2138
"""
2139
cdef mpf r = PY_NEW(mpf)
2140
MPF_set(&r.value, &s.value)
2141
MPF_normalize(&r.value, global_opts)
2142
return r
2143
2144
def __abs__(s):
2145
"""
2146
Computes the absolute value, rounded to the current
2147
working precision ::
2148
2149
sage: from mpmath import mpf
2150
sage: abs(mpf(-2))
2151
mpf('2.0')
2152
"""
2153
cdef mpf r = PY_NEW(mpf)
2154
MPF_abs(&r.value, &s.value)
2155
MPF_normalize(&r.value, global_opts)
2156
return r
2157
2158
def sqrt(s):
2159
"""
2160
Computes the square root, rounded to the current
2161
working precision ::
2162
2163
sage: from mpmath import mpf
2164
sage: mpf(2).sqrt()
2165
mpf('1.4142135623730951')
2166
"""
2167
cdef mpf r = PY_NEW(mpf)
2168
MPF_sqrt(&r.value, &s.value, global_opts)
2169
return r
2170
2171
def __richcmp__(self, other, int op):
2172
"""
2173
Compares numbers ::
2174
2175
sage: from mpmath import mpf
2176
sage: mpf(3) > 2
2177
True
2178
sage: mpf(3) == 3
2179
True
2180
sage: mpf(3) == 4
2181
False
2182
"""
2183
return binop(OP_RICHCMP+op, self, other, global_opts)
2184
2185
2186
2187
cdef class constant(mpf_base):
2188
"""
2189
Represents a mathematical constant with dynamic precision.
2190
When printed or used in an arithmetic operation, a constant
2191
is converted to a regular mpf at the working precision. A
2192
regular mpf can also be obtained using the operation +x.
2193
"""
2194
2195
cdef public name, func, __doc__
2196
2197
def __init__(self, func, name, docname=''):
2198
"""
2199
Creates a constant from a function computing an mpf
2200
tuple value ::
2201
2202
sage: from mpmath import mp, mpf
2203
sage: q = mp.constant(lambda prec, rnd: mpf(0.25)._mpf_, "quarter", "q")
2204
sage: q
2205
<quarter: 0.25~>
2206
sage: q + 1
2207
mpf('1.25')
2208
2209
"""
2210
self.name = name
2211
self.func = func
2212
self.__doc__ = getattr(function_docs, docname, '')
2213
2214
def __call__(self, prec=None, dps=None, rounding=None):
2215
"""
2216
Calling a constant is equivalent to rounding it. A
2217
custom precision and rounding direction can also be passed ::
2218
2219
sage: from mpmath import pi
2220
sage: print pi(dps=5, rounding='d')
2221
3.1415901184082
2222
sage: print pi(dps=5, rounding='u')
2223
3.14159393310547
2224
2225
"""
2226
prec2 = global_opts.prec
2227
rounding2 = rndmode_to_python(global_opts.rounding)
2228
if not prec: prec = prec2
2229
if not rounding: rounding = rounding2
2230
if dps: prec = dps_to_prec(dps)
2231
return global_context.make_mpf(self.func(prec, rounding))
2232
2233
@property
2234
def _mpf_(self):
2235
"""
2236
Returns the tuple value of the constant as if rounded
2237
to an mpf at the present working precision ::
2238
2239
sage: from mpmath import pi
2240
sage: pi._mpf_
2241
(0, 884279719003555, -48, 50)
2242
sage: 884279719003555 / 2.0**48
2243
3.14159265358979
2244
"""
2245
prec = global_opts.prec
2246
rounding = rndmode_to_python(global_opts.rounding)
2247
return self.func(prec, rounding)
2248
2249
def __repr__(self):
2250
"""
2251
Represents self as a string. With mp.pretty=False, the
2252
representation differs from that of an ordinary mpf ::
2253
2254
sage: from mpmath import mp, pi
2255
sage: mp.pretty = True
2256
sage: repr(pi)
2257
'3.14159265358979'
2258
sage: mp.pretty = False
2259
sage: repr(pi)
2260
'<pi: 3.14159~>'
2261
2262
"""
2263
if global_context.pretty:
2264
return self.__str__()
2265
return "<%s: %s~>" % (self.name, global_context.nstr(self))
2266
2267
def __nonzero__(self):
2268
"""
2269
Returns whether the constant is nonzero ::
2270
2271
sage: from mpmath import pi
2272
sage: bool(pi)
2273
True
2274
"""
2275
return self._mpf_ != libmp.fzero
2276
2277
def __neg__(self):
2278
"""
2279
Negates the constant ::
2280
2281
sage: from mpmath import pi
2282
sage: -pi
2283
mpf('-3.1415926535897931')
2284
"""
2285
return -mpf(self)
2286
2287
def __pos__(self):
2288
"""
2289
Instantiates the constant as an mpf ::
2290
2291
sage: from mpmath import pi
2292
sage: +pi
2293
mpf('3.1415926535897931')
2294
"""
2295
return mpf(self)
2296
2297
def __abs__(self):
2298
"""
2299
Computes the absolute value of the constant ::
2300
2301
sage: from mpmath import pi
2302
sage: abs(pi)
2303
mpf('3.1415926535897931')
2304
"""
2305
return abs(mpf(self))
2306
2307
def sqrt(self):
2308
"""
2309
Computes the square root of the constant ::
2310
2311
sage: from mpmath import pi
2312
sage: print pi.sqrt()
2313
1.77245385090552
2314
"""
2315
return mpf(self).sqrt()
2316
2317
# XXX: optimize
2318
def to_fixed(self, prec):
2319
"""
2320
Convert to a fixed-point integer ::
2321
2322
sage: from mpmath import pi
2323
sage: print float(pi.to_fixed(10) / 2.0**10)
2324
3.140625
2325
"""
2326
return libmp.to_fixed(self._mpf_, prec)
2327
2328
def __getstate__(self):
2329
return libmp.to_pickable(self._mpf_)
2330
2331
def __setstate__(self, val):
2332
self._mpf_ = libmp.from_pickable(val)
2333
2334
# WHY is this method not inherited from the base class by Cython?
2335
def __hash__(self):
2336
"""
2337
A constant hashes as if instantiated to a number ::
2338
2339
sage: from mpmath import pi
2340
sage: hash(pi) == hash(+pi)
2341
True
2342
"""
2343
return libmp.mpf_hash(self._mpf_)
2344
2345
def __richcmp__(self, other, int op):
2346
"""
2347
A constant hashes as if instantiated to a number ::
2348
2349
sage: from mpmath import pi
2350
sage: pi == pi
2351
True
2352
sage: pi > 3.14
2353
True
2354
sage: pi < 3.14
2355
False
2356
"""
2357
return binop(OP_RICHCMP+op, self, other, global_opts)
2358
2359
2360
cdef class mpc(mpnumber):
2361
"""
2362
An mpc represents a complex number using a pair of mpf:s (one
2363
for the real part and another for the imaginary part.) The mpc
2364
class behaves fairly similarly to Python's complex type.
2365
"""
2366
2367
cdef MPF re
2368
cdef MPF im
2369
2370
def __init__(self, real=0, imag=0):
2371
"""
2372
Creates a new mpc::
2373
2374
sage: from mpmath import mpc
2375
sage: mpc() == mpc(0,0) == mpc(1,0)-1 == 0
2376
True
2377
2378
"""
2379
cdef int typx, typy
2380
typx = MPF_set_any(&self.re, &self.im, real, global_opts, 1)
2381
if typx == 2:
2382
typy = 1
2383
else:
2384
typy = MPF_set_any(&self.im, &self.im, imag, global_opts, 1)
2385
if typx == 0 or typy != 1:
2386
raise TypeError
2387
2388
def __cinit__(self):
2389
"""
2390
Create a new mpc ::
2391
2392
sage: from mpmath import mpc
2393
sage: x = mpc()
2394
2395
"""
2396
MPF_init(&self.re)
2397
MPF_init(&self.im)
2398
2399
def __dealloc__(self):
2400
MPF_clear(&self.re)
2401
MPF_clear(&self.im)
2402
2403
def __reduce__(self):
2404
"""
2405
Support pickling ::
2406
2407
sage: from mpmath import mpc
2408
sage: loads(dumps(mpc(1,3))) == mpc(1,3)
2409
True
2410
"""
2411
return (mpc, (), self._mpc_)
2412
2413
def __setstate__(self, val):
2414
"""
2415
Support pickling ::
2416
2417
sage: from mpmath import mpc
2418
sage: loads(dumps(mpc(1,3))) == mpc(1,3)
2419
True
2420
"""
2421
self._mpc_ = val[0], val[1]
2422
2423
def __repr__(self):
2424
"""
2425
TESTS ::
2426
2427
sage: from mpmath import mp
2428
sage: mp.pretty = True
2429
sage: repr(mp.mpc(2,3))
2430
'(2.0 + 3.0j)'
2431
sage: mp.pretty = False
2432
sage: repr(mp.mpc(2,3))
2433
"mpc(real='2.0', imag='3.0')"
2434
"""
2435
if global_context.pretty:
2436
return self.__str__()
2437
re, im = self._mpc_
2438
n = repr_dps(global_opts.prec)
2439
return "mpc(real='%s', imag='%s')" % (to_str(re, n), to_str(im, n))
2440
2441
def __str__(s):
2442
"""
2443
TESTS ::
2444
2445
sage: from mpmath import mp
2446
sage: str(mp.mpc(2,3))
2447
'(2.0 + 3.0j)'
2448
"""
2449
return "(%s)" % libmp.mpc_to_str(s._mpc_, global_context._str_digits)
2450
2451
def __nonzero__(self):
2452
"""
2453
TESTS ::
2454
2455
sage: from mpmath import mp
2456
sage: bool(mp.mpc(0,1))
2457
True
2458
sage: bool(mp.mpc(1,0))
2459
True
2460
sage: bool(mp.mpc(0,0))
2461
False
2462
"""
2463
return self.re.special != S_ZERO or self.im.special != S_ZERO
2464
2465
#def __complex__(self):
2466
# a, b = self._mpc_
2467
# return complex(libmp.to_float(a), libmp.to_float(b))
2468
2469
def __complex__(self):
2470
"""
2471
TESTS ::
2472
2473
sage: from mpmath import mp
2474
sage: complex(mp.mpc(1,2)) == complex(1,2)
2475
True
2476
"""
2477
return complex(MPF_to_double(&self.re, False), MPF_to_double(&self.im, False))
2478
2479
def _get_mpc(self):
2480
"""
2481
Returns tuple value of self ::
2482
2483
sage: from mpmath import mp
2484
sage: mp.mpc(2,3)._mpc_
2485
((0, 1, 1, 1), (0, 3, 0, 2))
2486
"""
2487
return MPF_to_tuple(&self.re), MPF_to_tuple(&self.im)
2488
2489
def _set_mpc(self, tuple v):
2490
"""
2491
Sets tuple value of self (warning: unsafe) ::
2492
2493
sage: from mpmath import mp
2494
sage: x = mp.mpc(2,3)
2495
sage: x._mpc_ = (x._mpc_[1], x._mpc_[0])
2496
sage: x
2497
mpc(real='3.0', imag='2.0')
2498
"""
2499
MPF_set_tuple(&self.re, v[0])
2500
MPF_set_tuple(&self.im, v[1])
2501
2502
_mpc_ = property(_get_mpc, _set_mpc, doc=_get_mpc.__doc__)
2503
2504
@property
2505
def real(self):
2506
"""
2507
Returns the real part of self as an mpf ::
2508
2509
sage: from mpmath import mp
2510
sage: mp.mpc(1,2).real
2511
mpf('1.0')
2512
"""
2513
cdef mpf r = PY_NEW(mpf)
2514
MPF_set(&r.value, &self.re)
2515
return r
2516
2517
@property
2518
def imag(self):
2519
"""
2520
Returns the imaginary part of self as an mpf ::
2521
2522
sage: from mpmath import mp
2523
sage: mp.mpc(1,2).imag
2524
mpf('2.0')
2525
"""
2526
cdef mpf r = PY_NEW(mpf)
2527
MPF_set(&r.value, &self.im)
2528
return r
2529
2530
def __hash__(self):
2531
"""
2532
Returns the hash value of self ::
2533
2534
sage: from mpmath import mp
2535
sage: hash(mp.mpc(2,3)) == hash(complex(2,3))
2536
True
2537
"""
2538
return libmp.mpc_hash(self._mpc_)
2539
2540
def __neg__(s):
2541
"""
2542
Negates the number ::
2543
2544
sage: from mpmath import mpc
2545
sage: -mpc(1,2)
2546
mpc(real='-1.0', imag='-2.0')
2547
"""
2548
cdef mpc r = PY_NEW(mpc)
2549
MPF_neg(&r.re, &s.re)
2550
MPF_neg(&r.im, &s.im)
2551
MPF_normalize(&r.re, global_opts)
2552
MPF_normalize(&r.im, global_opts)
2553
return r
2554
2555
def conjugate(s):
2556
"""
2557
Returns the complex conjugate ::
2558
2559
sage: from mpmath import mpc
2560
sage: mpc(1,2).conjugate()
2561
mpc(real='1.0', imag='-2.0')
2562
"""
2563
cdef mpc r = PY_NEW(mpc)
2564
MPF_set(&r.re, &s.re)
2565
MPF_neg(&r.im, &s.im)
2566
MPF_normalize(&r.re, global_opts)
2567
MPF_normalize(&r.im, global_opts)
2568
return r
2569
2570
def __pos__(s):
2571
"""
2572
Rounds the number to the current working precision ::
2573
2574
sage: from mpmath import mp
2575
sage: mp.prec = 200
2576
sage: x = mp.mpc(1) / 3
2577
sage: x.real.man
2578
1071292029505993517027974728227441735014801995855195223534251
2579
sage: mp.prec = 53
2580
sage: +x
2581
mpc(real='0.33333333333333331', imag='0.0')
2582
sage: (+x).real.man
2583
6004799503160661
2584
"""
2585
cdef mpc r = PY_NEW(mpc)
2586
MPF_set(&r.re, &s.re)
2587
MPF_set(&r.im, &s.im)
2588
MPF_normalize(&r.re, global_opts)
2589
MPF_normalize(&r.im, global_opts)
2590
return r
2591
2592
def __abs__(s):
2593
"""
2594
Returns the absolute value of self ::
2595
2596
sage: from mpmath import mpc
2597
sage: abs(mpc(3,4))
2598
mpf('5.0')
2599
"""
2600
cdef mpf r = PY_NEW(mpf)
2601
MPF_hypot(&r.value, &s.re, &s.im, global_opts)
2602
return r
2603
2604
def __richcmp__(self, other, int op):
2605
"""
2606
Complex numbers can be compared for equality ::
2607
2608
sage: from mpmath import mpc
2609
sage: mpc(2,3) == complex(2,3)
2610
True
2611
sage: mpc(-2,3) == complex(2,3)
2612
False
2613
sage: mpc(-2,3) != complex(2,3)
2614
True
2615
"""
2616
return binop(OP_RICHCMP+op, self, other, global_opts)
2617
2618
2619
def hypsum_internal(int p, int q, param_types, str ztype, coeffs, z,
2620
long prec, long wp, long epsshift, dict magnitude_check, kwargs):
2621
"""
2622
Internal summation routine for hypergeometric series (wraps
2623
extension function MPF_hypsum to handle mpf/mpc types).
2624
2625
EXAMPLES::
2626
2627
sage: from mpmath import mp # indirect doctest
2628
sage: mp.dps = 15
2629
sage: print mp.hyp1f1(1,2,3)
2630
6.36184564106256
2631
2632
TODO: convert mpf/mpc parameters to fixed-point numbers here
2633
instead of converting to tuples within MPF_hypsum.
2634
"""
2635
cdef mpf f
2636
cdef mpc c
2637
c = PY_NEW(mpc)
2638
have_complex, magn = MPF_hypsum(&c.re, &c.im, p, q, param_types, \
2639
ztype, coeffs, z, prec, wp, epsshift, magnitude_check, kwargs)
2640
if have_complex:
2641
v = c
2642
else:
2643
f = PY_NEW(mpf)
2644
MPF_set(&f.value, &c.re)
2645
v = f
2646
return v, have_complex, magn
2647
2648