Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/libs/mpmath/ext_impl.pyx
4045 views
1
"""
2
This module provides the core implementation of multiprecision
3
floating-point arithmetic. Operations are done in-place.
4
"""
5
6
include '../../ext/interrupt.pxi'
7
include "../../ext/stdsage.pxi"
8
include "../../ext/python_int.pxi"
9
include "../../ext/python_long.pxi"
10
include "../../ext/python_float.pxi"
11
include "../../ext/python_complex.pxi"
12
include "../../ext/python_number.pxi"
13
14
cdef extern from "math.h":
15
cdef double fpow "pow" (double, double)
16
cdef double fsqrt "sqrt" (double)
17
cdef double frexp "frexp" (double, int*)
18
19
from sage.libs.gmp.all cimport *
20
from sage.libs.mpfr cimport *
21
from sage.rings.integer cimport Integer
22
23
cdef extern from "mpz_pylong.h":
24
cdef mpz_get_pylong(mpz_t src)
25
cdef mpz_get_pyintlong(mpz_t src)
26
cdef int mpz_set_pylong(mpz_t dst, src) except -1
27
cdef long mpz_pythonhash(mpz_t src)
28
29
cdef mpz_set_integer(mpz_t v, x):
30
if PyInt_Check(x):
31
mpz_set_si(v, PyInt_AS_LONG(x))
32
elif PyLong_Check(x):
33
mpz_set_pylong(v, x)
34
elif PY_TYPE_CHECK(x, Integer):
35
mpz_set(v, (<Integer>x).value)
36
else:
37
raise TypeError("cannot convert %s to an integer" % x)
38
39
cdef inline void mpz_add_si(mpz_t a, mpz_t b, long x):
40
if x >= 0:
41
mpz_add_ui(a, b, x)
42
else:
43
# careful: overflow when negating INT_MIN
44
mpz_sub_ui(a, b, <unsigned long>(-x))
45
46
cdef inline mpzi(mpz_t n):
47
return mpz_get_pyintlong(n)
48
49
cdef inline mpzl(mpz_t n):
50
return mpz_get_pylong(n)
51
52
# This should be done better
53
cdef int mpz_tstbit_abs(mpz_t z, unsigned long bit_index):
54
cdef int res
55
if mpz_sgn(z) < 0:
56
mpz_neg(z, z)
57
res = mpz_tstbit(z, bit_index)
58
mpz_neg(z, z)
59
else:
60
res = mpz_tstbit(z, bit_index)
61
return res
62
63
cdef void mpz_set_fixed(mpz_t t, MPF *x, int prec, bint abs=False):
64
"""
65
Set t = x, or t = |x|, as a fixed-point number with prec bits.
66
"""
67
cdef int offset
68
offset = mpz_get_si(x.exp) + prec
69
if offset >= 0:
70
mpz_mul_2exp(t, x.man, offset)
71
else:
72
mpz_tdiv_q_2exp(t, x.man, -offset)
73
if abs:
74
mpz_abs(t, t)
75
76
cdef unsigned long mpz_bitcount(mpz_t z):
77
if mpz_sgn(z) == 0:
78
return 0
79
return mpz_sizeinbase(z, 2)
80
81
# The following limits allowed exponent shifts. We could use mpz_fits_slong_p,
82
# but then (-LONG_MIN) wraps around; we may also not be able to add large
83
# shifts safely. A higher limit could be used on 64-bit systems, but
84
# it is unlikely that anyone will run into this (adding numbers
85
# that differ by 2^(2^30), at precisions of 2^30 bits).
86
87
# Note: MPFR's emax is 1073741823
88
DEF MAX_SHIFT = 536870912 # 2^29
89
90
cdef int mpz_reasonable_shift(mpz_t z):
91
if mpz_sgn(z) > 0:
92
return mpz_cmp_ui(z, MAX_SHIFT) < 0
93
else:
94
return mpz_cmp_si(z, -MAX_SHIFT) > 0
95
96
DEF ROUND_N = 0
97
DEF ROUND_F = 1
98
DEF ROUND_C = 2
99
DEF ROUND_D = 3
100
DEF ROUND_U = 4
101
102
DEF S_NORMAL = 0
103
DEF S_ZERO = 1
104
DEF S_NZERO = 2
105
DEF S_INF = 3
106
DEF S_NINF = 4
107
DEF S_NAN = 5
108
109
cdef inline str rndmode_to_python(int rnd):
110
if rnd == ROUND_N: return 'n'
111
if rnd == ROUND_F: return 'f'
112
if rnd == ROUND_C: return 'c'
113
if rnd == ROUND_D: return 'd'
114
if rnd == ROUND_U: return 'u'
115
116
cdef inline rndmode_from_python(str rnd):
117
if rnd == 'n': return ROUND_N
118
if rnd == 'f': return ROUND_F
119
if rnd == 'c': return ROUND_C
120
if rnd == 'd': return ROUND_D
121
if rnd == 'u': return ROUND_U
122
123
cdef inline mpfr_rnd_t rndmode_to_mpfr(int rnd, int sign):
124
if rnd == ROUND_N: return GMP_RNDN
125
if rnd == ROUND_F: return GMP_RNDD
126
if rnd == ROUND_C: return GMP_RNDU
127
if rnd == ROUND_D: return GMP_RNDZ
128
if rnd == ROUND_U:
129
# return GMP_RNDA (unsupported)
130
if sign >= 0:
131
return GMP_RNDU
132
else:
133
return GMP_RNDD
134
135
cdef inline int reciprocal_rnd(int rnd):
136
if rnd == ROUND_N: return ROUND_N
137
if rnd == ROUND_D: return ROUND_U
138
if rnd == ROUND_U: return ROUND_D
139
if rnd == ROUND_C: return ROUND_F
140
if rnd == ROUND_F: return ROUND_C
141
142
cdef MPopts opts_exact
143
cdef MPopts opts_double_precision
144
cdef MPopts opts_mini_prec
145
146
opts_exact.prec = 0
147
opts_exact.rounding = ROUND_N
148
opts_double_precision.prec = 53
149
opts_double_precision.rounding = ROUND_N
150
opts_mini_prec.prec = 5
151
opts_mini_prec.rounding = ROUND_D
152
153
cdef double _double_inf = float("1e300") * float("1e300")
154
cdef double _double_ninf = -_double_inf
155
cdef double _double_nan = _double_inf - _double_inf
156
157
cdef inline void MPF_init(MPF *x):
158
"""Allocate space and set value to zero.
159
Must be called exactly once when creating a new MPF."""
160
x.special = S_ZERO
161
mpz_init(x.man)
162
mpz_init(x.exp)
163
164
cdef inline void MPF_clear(MPF *x):
165
"""Deallocate space. Must be called exactly once when finished with an MPF."""
166
mpz_clear(x.man)
167
mpz_clear(x.exp)
168
169
cdef inline void MPF_set(MPF *dest, MPF *src):
170
"""Clone MPF value. Assumes source value is already normalized."""
171
if src is dest:
172
return
173
dest.special = src.special
174
mpz_set(dest.man, src.man)
175
mpz_set(dest.exp, src.exp)
176
177
cdef inline void MPF_set_zero(MPF *x):
178
"""Set value to 0."""
179
x.special = S_ZERO
180
181
cdef inline void MPF_set_one(MPF *x):
182
"""Set value to 1."""
183
x.special = S_NORMAL
184
mpz_set_ui(x.man, 1)
185
mpz_set_ui(x.exp, 0)
186
187
cdef inline void MPF_set_nan(MPF *x):
188
"""Set value to NaN (not a number)."""
189
x.special = S_NAN
190
191
cdef inline void MPF_set_inf(MPF *x):
192
"""Set value to +infinity."""
193
x.special = S_INF
194
195
cdef inline void MPF_set_ninf(MPF *x):
196
"""Set value to -infinity."""
197
x.special = S_NINF
198
199
cdef MPF_set_si(MPF *x, long n):
200
"""Set value to that of a given C (long) integer."""
201
if n:
202
x.special = S_NORMAL
203
mpz_set_si(x.man, n)
204
mpz_set_ui(x.exp, 0)
205
MPF_normalize(x, opts_exact)
206
else:
207
MPF_set_zero(x)
208
209
cdef MPF_set_int(MPF *x, n):
210
"""Set value to that of a given Python integer."""
211
x.special = S_NORMAL
212
mpz_set_integer(x.man, n)
213
if mpz_sgn(x.man):
214
mpz_set_ui(x.exp, 0)
215
MPF_normalize(x, opts_exact)
216
else:
217
MPF_set_zero(x)
218
219
cdef MPF_set_man_exp(MPF *x, man, exp):
220
"""
221
Set value to man*2^exp where man, exp may be of any appropriate
222
Python integer types.
223
"""
224
x.special = S_NORMAL
225
mpz_set_integer(x.man, man)
226
mpz_set_integer(x.exp, exp)
227
MPF_normalize(x, opts_exact)
228
229
230
# Temporary variables. Note: not thread-safe.
231
# Used by MPF_add/MPF_sub/MPF_div
232
cdef mpz_t tmp_exponent
233
mpz_init(tmp_exponent)
234
cdef MPF tmp0
235
MPF_init(&tmp0)
236
237
# Used by MPF_hypot and MPF_cmp, which may call MPF_add/MPF_sub
238
cdef MPF tmp1
239
MPF_init(&tmp1)
240
cdef MPF tmp2
241
MPF_init(&tmp2)
242
243
244
# Constants needed in a few places
245
cdef MPF MPF_C_1
246
MPF_init(&MPF_C_1)
247
MPF_set_si(&MPF_C_1, 1)
248
cdef Integer MPZ_ZERO = Integer(0)
249
cdef tuple _mpf_fzero = (0, MPZ_ZERO, 0, 0)
250
cdef tuple _mpf_fnan = (0, MPZ_ZERO, -123, -1)
251
cdef tuple _mpf_finf = (0, MPZ_ZERO, -456, -2)
252
cdef tuple _mpf_fninf = (1, MPZ_ZERO, -789, -3)
253
254
cdef MPF_set_tuple(MPF *x, tuple value):
255
"""
256
Set value of an MPF to that of a normalized (sign, man, exp, bc) tuple
257
in the format used by mpmath.libmp.
258
"""
259
#cdef int sign
260
cdef Integer man
261
sign, _man, exp, bc = value
262
if PY_TYPE_CHECK(_man, Integer):
263
man = <Integer>_man
264
else:
265
# This is actually very unlikely; it should never happen
266
# in internal code that man isn't an Integer. Maybe the check
267
# can be avoided by doing checks in e.g. MPF_set_any?
268
man = Integer(_man)
269
if mpz_sgn(man.value):
270
MPF_set_man_exp(x, man, exp)
271
if sign:
272
mpz_neg(x.man, x.man)
273
return
274
if value == _mpf_fzero:
275
MPF_set_zero(x)
276
elif value == _mpf_finf:
277
MPF_set_inf(x)
278
elif value == _mpf_fninf:
279
MPF_set_ninf(x)
280
else:
281
MPF_set_nan(x)
282
283
cdef MPF_to_tuple(MPF *x):
284
"""Convert MPF value to (sign, man, exp, bc) tuple."""
285
cdef Integer man
286
if x.special:
287
if x.special == S_ZERO: return _mpf_fzero
288
#if x.special == S_NZERO: return _mpf_fnzero
289
if x.special == S_INF: return _mpf_finf
290
if x.special == S_NINF: return _mpf_fninf
291
return _mpf_fnan
292
man = PY_NEW(Integer)
293
if mpz_sgn(x.man) < 0:
294
mpz_neg(man.value, x.man)
295
sign = 1
296
else:
297
mpz_set(man.value, x.man)
298
sign = 0
299
exp = mpz_get_pyintlong(x.exp)
300
bc = mpz_sizeinbase(x.man, 2)
301
return (sign, man, exp, bc)
302
303
cdef MPF_set_double(MPF *r, double x):
304
"""
305
Set r to the value of a C double x.
306
"""
307
cdef int exp
308
cdef double man
309
if x != x:
310
MPF_set_nan(r)
311
return
312
if x == _double_inf:
313
MPF_set_inf(r)
314
return
315
if x == _double_ninf:
316
MPF_set_ninf(r)
317
return
318
man = frexp(x, &exp)
319
man *= 9007199254740992.0
320
mpz_set_d(r.man, man)
321
mpz_set_si(r.exp, exp-53)
322
r.special = S_NORMAL
323
MPF_normalize(r, opts_exact)
324
325
import math as pymath
326
327
# TODO: implement this function safely without using the Python math module
328
cdef double MPF_to_double(MPF *x, bint strict):
329
"""Convert MPF value to a Python float."""
330
if x.special == S_NORMAL:
331
man = mpzi(x.man)
332
exp = mpzi(x.exp)
333
bc = mpz_sizeinbase(x.man, 2)
334
try:
335
if bc < 100:
336
return pymath.ldexp(man, exp)
337
# Try resizing the mantissa. Overflow may still happen here.
338
n = bc - 53
339
m = man >> n
340
return pymath.ldexp(m, exp + n)
341
except OverflowError:
342
if strict:
343
raise
344
# Overflow to infinity
345
if exp + bc > 0:
346
if man < 0:
347
return _double_ninf
348
else:
349
return _double_inf
350
# Underflow to zero
351
return 0.0
352
if x.special == S_ZERO:
353
return 0.0
354
if x.special == S_INF:
355
return _double_inf
356
if x.special == S_NINF:
357
return _double_ninf
358
return _double_nan
359
360
cdef MPF_to_fixed(mpz_t r, MPF *x, long prec, bint truncate):
361
"""
362
Set r = x, r being in the format of a fixed-point number with prec bits.
363
Floor division is used unless truncate=True in which case
364
truncating division is used.
365
"""
366
cdef long shift
367
if x.special:
368
if x.special == S_ZERO or x.special == S_NZERO:
369
mpz_set_ui(r, 0)
370
return
371
raise ValueError("cannot create fixed-point number from special value")
372
if mpz_reasonable_shift(x.exp):
373
# XXX: signed integer overflow
374
shift = mpz_get_si(x.exp) + prec
375
if shift >= 0:
376
mpz_mul_2exp(r, x.man, shift)
377
else:
378
if truncate:
379
mpz_tdiv_q_2exp(r, x.man, -shift)
380
else:
381
mpz_fdiv_q_2exp(r, x.man, -shift)
382
return
383
# Underflow
384
if mpz_sgn(x.exp) < 0:
385
mpz_set_ui(r, 0)
386
return
387
raise OverflowError("cannot convert huge number to fixed-point format")
388
389
cdef int MPF_sgn(MPF *x):
390
"""
391
Gives the sign of an MPF (-1, 0, or 1).
392
"""
393
if x.special:
394
if x.special == S_INF:
395
return 1
396
if x.special == S_NINF:
397
return -1
398
return 0
399
return mpz_sgn(x.man)
400
401
cdef void MPF_neg(MPF *r, MPF *s):
402
"""
403
Sets r = -s. MPF_neg(x, x) negates in place.
404
"""
405
if s.special:
406
if s.special == S_ZERO: r.special = S_ZERO #r.special = S_NZERO
407
elif s.special == S_NZERO: r.special = S_ZERO
408
elif s.special == S_INF: r.special = S_NINF
409
elif s.special == S_NINF: r.special = S_INF
410
else: r.special = s.special
411
return
412
r.special = s.special
413
mpz_neg(r.man, s.man)
414
if r is not s:
415
mpz_set(r.exp, s.exp)
416
417
cdef void MPF_abs(MPF *r, MPF *s):
418
"""
419
Sets r = abs(s). MPF_abs(r, r) sets the absolute value in place.
420
"""
421
if s.special:
422
if s.special == S_NINF: r.special = S_INF
423
else: r.special = s.special
424
return
425
r.special = s.special
426
mpz_abs(r.man, s.man)
427
if r is not s:
428
mpz_set(r.exp, s.exp)
429
430
cdef MPF_normalize(MPF *x, MPopts opts):
431
"""
432
Normalize.
433
434
With prec = 0, trailing zero bits are stripped but no rounding
435
is performed.
436
"""
437
cdef int sign
438
cdef long trail, bc, shift
439
if x.special != S_NORMAL:
440
return
441
sign = mpz_sgn(x.man)
442
if sign == 0:
443
x.special = S_ZERO
444
mpz_set_ui(x.exp, 0)
445
return
446
bc = mpz_sizeinbase(x.man, 2)
447
shift = bc - opts.prec
448
# Ok if mantissa small and no trailing zero bits
449
if (shift <= 0 or not opts.prec) and mpz_odd_p(x.man):
450
return
451
# Mantissa is too large, so divide by appropriate power of 2
452
# Need to be careful about rounding
453
if shift > 0 and opts.prec:
454
if opts.rounding == ROUND_N:
455
if mpz_tstbit_abs(&x.man, shift-1):
456
if mpz_tstbit_abs(&x.man, shift) or mpz_scan1(x.man, 0) < (shift-1):
457
if sign < 0:
458
mpz_fdiv_q_2exp(x.man, x.man, shift)
459
else:
460
mpz_cdiv_q_2exp(x.man, x.man, shift)
461
else:
462
mpz_tdiv_q_2exp(x.man, x.man, shift)
463
else:
464
mpz_tdiv_q_2exp(x.man, x.man, shift)
465
elif opts.rounding == ROUND_D:
466
mpz_tdiv_q_2exp(x.man, x.man, shift)
467
elif opts.rounding == ROUND_F:
468
mpz_fdiv_q_2exp(x.man, x.man, shift)
469
elif opts.rounding == ROUND_C:
470
mpz_cdiv_q_2exp(x.man, x.man, shift)
471
elif opts.rounding == ROUND_U:
472
if sign < 0:
473
mpz_fdiv_q_2exp(x.man, x.man, shift)
474
else:
475
mpz_cdiv_q_2exp(x.man, x.man, shift)
476
else:
477
raise ValueError("bad rounding mode")
478
else:
479
shift = 0
480
# Strip trailing bits
481
trail = mpz_scan1(x.man, 0)
482
if 0 < trail < bc:
483
mpz_tdiv_q_2exp(x.man, x.man, trail)
484
shift += trail
485
mpz_add_si(x.exp, x.exp, shift)
486
487
cdef void MPF_pos(MPF *x, MPF *y, MPopts opts):
488
"""
489
Set x = +y (i.e. copy the value, and round if the
490
working precision is smaller than the width
491
of the mantissa of y).
492
"""
493
MPF_set(x, y)
494
MPF_normalize(x, opts)
495
496
cdef void _add_special(MPF *r, MPF *s, MPF *t):
497
if s.special == S_ZERO:
498
# (+0) + (-0) = +0
499
if t.special == S_NZERO:
500
MPF_set(r, s)
501
# (+0) + x = x
502
else:
503
MPF_set(r, t)
504
elif t.special == S_ZERO:
505
# (-0) + (+0) = +0
506
if s.special == S_NZERO:
507
MPF_set(r, t)
508
# x + (+0) = x
509
else:
510
MPF_set(r, s)
511
# (+/- 0) + x = x
512
elif s.special == S_NZERO:
513
MPF_set(r, t)
514
elif t.special == S_NZERO:
515
MPF_set(r, s)
516
# (+/- inf) + (-/+ inf) = nan
517
elif ((s.special == S_INF and t.special == S_NINF) or
518
(s.special == S_NINF and t.special == S_INF)):
519
MPF_set_nan(r)
520
# nan or +/- inf trumps any finite number
521
elif s.special == S_NAN or t.special == S_NAN:
522
MPF_set_nan(r)
523
elif s.special:
524
MPF_set(r, s)
525
else:
526
MPF_set(r, t)
527
return
528
529
cdef void _sub_special(MPF *r, MPF *s, MPF *t):
530
if s.special == S_ZERO:
531
# (+0) - (+/-0) = (+0)
532
if t.special == S_NZERO:
533
MPF_set(r, s)
534
else:
535
# (+0) - x = (-x)
536
MPF_neg(r, t)
537
elif t.special == S_ZERO:
538
# x - (+0) = x; also covers (-0) - (+0) = (-0)
539
MPF_set(r, s)
540
# (-0) - x = x
541
elif s.special == S_NZERO:
542
# (-0) - (-0) = (+0)
543
if t.special == S_NZERO:
544
MPF_set_zero(r)
545
# (-0) - x = -x
546
else:
547
MPF_neg(r, t)
548
elif t.special == S_NZERO:
549
# x - (-0) = x
550
MPF_set(r, s)
551
# (+/- inf) - (+/- inf) = nan
552
elif ((s.special == S_INF and t.special == S_INF) or
553
(s.special == S_NINF and t.special == S_NINF)):
554
MPF_set_nan(r)
555
elif s.special == S_NAN or t.special == S_NAN:
556
MPF_set_nan(r)
557
# nan - x or (+/-inf) - x = l.h.s
558
elif s.special:
559
MPF_set(r, s)
560
# x - nan or x - (+/-inf) = (- r.h.s)
561
else:
562
MPF_neg(r, t)
563
564
cdef void _mul_special(MPF *r, MPF *s, MPF *t):
565
if s.special == S_ZERO:
566
if t.special == S_NORMAL or t.special == S_ZERO:
567
MPF_set(r, s)
568
elif t.special == S_NZERO:
569
MPF_set(r, t)
570
else:
571
MPF_set_nan(r)
572
elif t.special == S_ZERO:
573
if s.special == S_NORMAL:
574
MPF_set(r, t)
575
elif s.special == S_NZERO:
576
MPF_set(r, s)
577
else:
578
MPF_set_nan(r)
579
elif s.special == S_NZERO:
580
if t.special == S_NORMAL:
581
if mpz_sgn(t.man) < 0:
582
MPF_set_zero(r)
583
else:
584
MPF_set(r, s)
585
else:
586
MPF_set_nan(r)
587
elif t.special == S_NZERO:
588
if s.special == S_NORMAL:
589
if mpz_sgn(s.man) < 0:
590
MPF_set_zero(r)
591
else:
592
MPF_set(r, t)
593
else:
594
MPF_set_nan(r)
595
elif s.special == S_NAN or t.special == S_NAN:
596
MPF_set_nan(r)
597
else:
598
if MPF_sgn(s) == MPF_sgn(t):
599
MPF_set_inf(r)
600
else:
601
MPF_set_ninf(r)
602
603
cdef _div_special(MPF *r, MPF *s, MPF *t):
604
# TODO: handle signed zeros correctly
605
if s.special == S_NAN or t.special == S_NAN:
606
MPF_set_nan(r)
607
elif t.special == S_ZERO or t.special == S_NZERO:
608
raise ZeroDivisionError
609
elif s.special == S_ZERO or s.special == S_NZERO:
610
MPF_set_zero(r)
611
elif s.special == S_NORMAL:
612
MPF_set_zero(r)
613
elif s.special == S_INF or s.special == S_NINF:
614
if t.special == S_INF or t.special == S_NINF:
615
MPF_set_nan(r)
616
elif MPF_sgn(s) == MPF_sgn(t):
617
MPF_set_inf(r)
618
else:
619
MPF_set_ninf(r)
620
# else:
621
elif t.special == S_INF or t.special == S_NINF:
622
MPF_set_zero(r)
623
624
cdef _add_perturbation(MPF *r, MPF *s, int sign, MPopts opts):
625
cdef long shift
626
if opts.rounding == ROUND_N:
627
MPF_set(r, s)
628
else:
629
shift = opts.prec - mpz_sizeinbase(s, 2) + 8
630
if shift < 0:
631
shift = 8
632
mpz_mul_2exp(r.man, s.man, shift)
633
mpz_add_si(r.man, r.man, sign)
634
mpz_sub_ui(r.exp, s.exp, shift)
635
MPF_normalize(r, opts)
636
637
cdef MPF_add(MPF *r, MPF *s, MPF *t, MPopts opts):
638
"""
639
Set r = s + t, with exact rounding.
640
641
With prec = 0, the addition is performed exactly. Note that this
642
may cause overflow if the exponents are huge.
643
"""
644
cdef long shift, sbc, tbc
645
#assert (r is not s) and (r is not t)
646
if s.special or t.special:
647
_add_special(r, s, t)
648
return
649
r.special = S_NORMAL
650
# Difference between exponents
651
mpz_sub(tmp_exponent, s.exp, t.exp)
652
if mpz_reasonable_shift(tmp_exponent):
653
shift = mpz_get_si(tmp_exponent)
654
if shift >= 0:
655
# |s| >> |t|
656
if shift > 2*opts.prec and opts.prec:
657
sbc = mpz_sizeinbase(s,2)
658
tbc = mpz_sizeinbase(t,2)
659
if shift + sbc - tbc > opts.prec+8:
660
_add_perturbation(r, s, mpz_sgn(t.man), opts)
661
return
662
# |s| > |t|
663
mpz_mul_2exp(tmp0.man, s.man, shift)
664
mpz_add(r.man, tmp0.man, t.man)
665
mpz_set(r.exp, t.exp)
666
MPF_normalize(r, opts)
667
elif shift < 0:
668
shift = -shift
669
# |s| << |t|
670
if shift > 2*opts.prec and opts.prec:
671
sbc = mpz_sizeinbase(s,2)
672
tbc = mpz_sizeinbase(t,2)
673
if shift + tbc - sbc > opts.prec+8:
674
_add_perturbation(r, t, mpz_sgn(s.man), opts)
675
return
676
# |s| < |t|
677
mpz_mul_2exp(tmp0.man, t.man, shift)
678
mpz_add(r.man, tmp0.man, s.man)
679
mpz_set(r.exp, s.exp)
680
MPF_normalize(r, opts)
681
else:
682
if not opts.prec:
683
raise OverflowError("the exact result does not fit in memory")
684
# |s| >>> |t|
685
if mpz_sgn(tmp_exponent) > 0:
686
_add_perturbation(r, s, mpz_sgn(t.man), opts)
687
# |s| <<< |t|
688
else:
689
_add_perturbation(r, t, mpz_sgn(s.man), opts)
690
691
cdef MPF_sub(MPF *r, MPF *s, MPF *t, MPopts opts):
692
"""
693
Set r = s - t, with exact rounding.
694
695
With prec = 0, the addition is performed exactly. Note that this
696
may cause overflow if the exponents are huge.
697
"""
698
cdef long shift, sbc, tbc
699
#assert (r is not s) and (r is not t)
700
if s.special or t.special:
701
_sub_special(r, s, t)
702
return
703
r.special = S_NORMAL
704
# Difference between exponents
705
mpz_sub(tmp_exponent, s.exp, t.exp)
706
if mpz_reasonable_shift(tmp_exponent):
707
shift = mpz_get_si(tmp_exponent)
708
if shift >= 0:
709
# |s| >> |t|
710
if shift > 2*opts.prec and opts.prec:
711
sbc = mpz_sizeinbase(s,2)
712
tbc = mpz_sizeinbase(t,2)
713
if shift + sbc - tbc > opts.prec+8:
714
_add_perturbation(r, s, -mpz_sgn(t.man), opts)
715
return
716
# |s| > |t|
717
mpz_mul_2exp(tmp0.man, s.man, shift)
718
mpz_sub(r.man, tmp0.man, t.man)
719
mpz_set(r.exp, t.exp)
720
MPF_normalize(r, opts)
721
elif shift < 0:
722
shift = -shift
723
# |s| << |t|
724
if shift > 2*opts.prec and opts.prec:
725
sbc = mpz_sizeinbase(s,2)
726
tbc = mpz_sizeinbase(t,2)
727
if shift + tbc - sbc > opts.prec+8:
728
_add_perturbation(r, t, -mpz_sgn(s.man), opts)
729
MPF_neg(r, r)
730
return
731
# |s| < |t|
732
mpz_mul_2exp(tmp0.man, t.man, shift)
733
mpz_sub(r.man, s.man, tmp0.man)
734
mpz_set(r.exp, s.exp)
735
MPF_normalize(r, opts)
736
else:
737
if not opts.prec:
738
raise OverflowError("the exact result does not fit in memory")
739
# |s| >>> |t|
740
if mpz_sgn(tmp_exponent) > 0:
741
_add_perturbation(r, s, -mpz_sgn(t.man), opts)
742
# |s| <<< |t|
743
else:
744
_add_perturbation(r, t, -mpz_sgn(s.man), opts)
745
MPF_neg(r, r)
746
747
cdef bint MPF_eq(MPF *s, MPF *t):
748
"""
749
Evaluates s == t.
750
"""
751
if s.special == S_NAN or t.special == S_NAN:
752
return False
753
if s.special == t.special:
754
if s.special == S_NORMAL:
755
return (mpz_cmp(s.man, t.man) == 0) and (mpz_cmp(s.exp, t.exp) == 0)
756
else:
757
return True
758
return False
759
760
cdef bint MPF_ne(MPF *s, MPF *t):
761
"""
762
Evaluates s != t.
763
"""
764
if s.special == S_NAN or t.special == S_NAN:
765
return True
766
if s.special == S_NORMAL and t.special == S_NORMAL:
767
return (mpz_cmp(s.man, t.man) != 0) or (mpz_cmp(s.exp, t.exp) != 0)
768
return s.special != t.special
769
770
cdef int MPF_cmp(MPF *s, MPF *t):
771
"""
772
Evaluates cmp(s,t). Conventions for nan follow those
773
of the mpmath.libmp function.
774
"""
775
cdef long sbc, tbc
776
cdef int cm
777
if MPF_eq(s, t):
778
return 0
779
if s.special != S_NORMAL or t.special != S_NORMAL:
780
if s.special == S_ZERO: return -MPF_sgn(t)
781
if t.special == S_ZERO: return MPF_sgn(s)
782
if t.special == S_NAN: return 1
783
if s.special == S_INF: return 1
784
if t.special == S_NINF: return 1
785
return -1
786
if mpz_sgn(s.man) != mpz_sgn(t.man):
787
if mpz_sgn(s.man) < 0:
788
return -1
789
else:
790
return 1
791
if not mpz_cmp(s.exp, t.exp):
792
return mpz_cmp(s.man, t.man)
793
mpz_add_ui(tmp1.exp, s.exp, mpz_sizeinbase(s.man, 2))
794
mpz_add_ui(tmp2.exp, t.exp, mpz_sizeinbase(t.man, 2))
795
cm = mpz_cmp(tmp1.exp, tmp2.exp)
796
if mpz_sgn(s.man) < 0:
797
if cm < 0: return 1
798
if cm > 0: return -1
799
else:
800
if cm < 0: return -1
801
if cm > 0: return 1
802
MPF_sub(&tmp1, s, t, opts_mini_prec)
803
return MPF_sgn(&tmp1)
804
805
cdef bint MPF_lt(MPF *s, MPF *t):
806
"""
807
Evaluates s < t.
808
"""
809
if s.special == S_NAN or t.special == S_NAN:
810
return False
811
return MPF_cmp(s, t) < 0
812
813
cdef bint MPF_le(MPF *s, MPF *t):
814
"""
815
Evaluates s <= t.
816
"""
817
if s.special == S_NAN or t.special == S_NAN:
818
return False
819
return MPF_cmp(s, t) <= 0
820
821
cdef bint MPF_gt(MPF *s, MPF *t):
822
"""
823
Evaluates s > t.
824
"""
825
if s.special == S_NAN or t.special == S_NAN:
826
return False
827
return MPF_cmp(s, t) > 0
828
829
cdef bint MPF_ge(MPF *s, MPF *t):
830
"""
831
Evaluates s >= t.
832
"""
833
if s.special == S_NAN or t.special == S_NAN:
834
return False
835
return MPF_cmp(s, t) >= 0
836
837
cdef MPF_mul(MPF *r, MPF *s, MPF *t, MPopts opts):
838
"""
839
Set r = s * t, with correct rounding.
840
841
With prec = 0, the multiplication is performed exactly,
842
i.e. no rounding is performed.
843
"""
844
if s.special or t.special:
845
_mul_special(r, s, t)
846
else:
847
r.special = S_NORMAL
848
mpz_mul(r.man, s.man, t.man)
849
mpz_add(r.exp, s.exp, t.exp)
850
if opts.prec:
851
MPF_normalize(r, opts)
852
853
cdef MPF_div(MPF *r, MPF *s, MPF *t, MPopts opts):
854
"""
855
Set r = s / t, with correct rounding.
856
"""
857
cdef int sign
858
cdef long sbc, tbc, extra
859
cdef mpz_t rem
860
#assert (r is not s) and (r is not t)
861
if s.special or t.special:
862
_div_special(r, s, t)
863
return
864
r.special = S_NORMAL
865
# Division by a power of two <=> shift exponents
866
if mpz_cmp_si(t.man, 1) == 0:
867
MPF_set(&tmp0, s)
868
mpz_sub(tmp0.exp, tmp0.exp, t.exp)
869
MPF_normalize(&tmp0, opts)
870
MPF_set(r, &tmp0)
871
return
872
elif mpz_cmp_si(t.man, -1) == 0:
873
MPF_neg(&tmp0, s)
874
mpz_sub(tmp0.exp, tmp0.exp, t.exp)
875
MPF_normalize(&tmp0, opts)
876
MPF_set(r, &tmp0)
877
return
878
sign = mpz_sgn(s.man) != mpz_sgn(t.man)
879
# Same strategy as for addition: if there is a remainder, perturb
880
# the result a few bits outside the precision range before rounding
881
extra = opts.prec - mpz_sizeinbase(s.man,2) + mpz_sizeinbase(t.man,2) + 5
882
if extra < 5:
883
extra = 5
884
mpz_init(rem)
885
mpz_mul_2exp(tmp0.man, s.man, extra)
886
mpz_tdiv_qr(r.man, rem, tmp0.man, t.man)
887
if mpz_sgn(rem):
888
mpz_mul_2exp(r.man, r.man, 1)
889
if sign:
890
mpz_sub_ui(r.man, r.man, 1)
891
else:
892
mpz_add_ui(r.man, r.man, 1)
893
extra += 1
894
mpz_clear(rem)
895
mpz_sub(r.exp, s.exp, t.exp)
896
mpz_sub_ui(r.exp, r.exp, extra)
897
MPF_normalize(r, opts)
898
899
cdef int MPF_sqrt(MPF *r, MPF *s, MPopts opts):
900
"""
901
Set r = sqrt(s), with correct rounding.
902
"""
903
cdef long shift
904
cdef mpz_t rem
905
#assert r is not s
906
if s.special:
907
if s.special == S_ZERO or s.special == S_INF:
908
MPF_set(r, s)
909
else:
910
MPF_set_nan(r)
911
return 0
912
if mpz_sgn(s.man) < 0:
913
MPF_set_nan(r)
914
return 1
915
r.special = S_NORMAL
916
if mpz_odd_p(s.exp):
917
mpz_sub_ui(r.exp, s.exp, 1)
918
mpz_mul_2exp(r.man, s.man, 1)
919
elif mpz_cmp_ui(s.man, 1) == 0:
920
# Square of a power of two
921
mpz_set_ui(r.man, 1)
922
mpz_tdiv_q_2exp(r.exp, s.exp, 1)
923
MPF_normalize(r, opts)
924
return 0
925
else:
926
mpz_set(r.man, s.man)
927
mpz_set(r.exp, s.exp)
928
shift = 2*opts.prec - mpz_sizeinbase(r.man,2) + 4
929
if shift < 4:
930
shift = 4
931
shift += shift & 1
932
mpz_mul_2exp(r.man, r.man, shift)
933
if opts.rounding == ROUND_F or opts.rounding == ROUND_D:
934
mpz_sqrt(r.man, r.man)
935
else:
936
mpz_init(rem)
937
mpz_sqrtrem(r.man, rem, r.man)
938
if mpz_sgn(rem):
939
mpz_mul_2exp(r.man, r.man, 1)
940
mpz_add_ui(r.man, r.man, 1)
941
shift += 2
942
mpz_clear(rem)
943
mpz_add_si(r.exp, r.exp, -shift)
944
mpz_tdiv_q_2exp(r.exp, r.exp, 1)
945
MPF_normalize(r, opts)
946
return 0
947
948
cdef MPF_hypot(MPF *r, MPF *a, MPF *b, MPopts opts):
949
"""
950
Set r = sqrt(a^2 + b^2)
951
"""
952
cdef MPopts tmp_opts
953
if a.special == S_ZERO:
954
MPF_abs(r, b)
955
MPF_normalize(r, opts)
956
return
957
if b.special == S_ZERO:
958
MPF_abs(r, a)
959
MPF_normalize(r, opts)
960
return
961
tmp_opts = opts
962
tmp_opts.prec += 30
963
MPF_mul(&tmp1, a, a, opts_exact)
964
MPF_mul(&tmp2, b, b, opts_exact)
965
MPF_add(r, &tmp1, &tmp2, tmp_opts)
966
MPF_sqrt(r, r, opts)
967
968
cdef MPF_pow_int(MPF *r, MPF *x, mpz_t n, MPopts opts):
969
"""
970
Set r = x ** n. Currently falls back to mpmath.libmp
971
unless n is tiny.
972
"""
973
cdef long m, absm
974
cdef unsigned long bc
975
cdef int nsign
976
if x.special != S_NORMAL:
977
nsign = mpz_sgn(n)
978
if x.special == S_ZERO:
979
if nsign < 0:
980
raise ZeroDivisionError
981
elif nsign == 0:
982
MPF_set(r, &MPF_C_1)
983
else:
984
MPF_set_zero(r)
985
elif x.special == S_INF:
986
if nsign > 0:
987
MPF_set(r, x)
988
elif nsign == 0:
989
MPF_set_nan(r)
990
else:
991
MPF_set_zero(r)
992
elif x.special == S_NINF:
993
if nsign > 0:
994
if mpz_odd_p(n):
995
MPF_set(r, x)
996
else:
997
MPF_neg(r, x)
998
elif nsign == 0:
999
MPF_set_nan(r)
1000
else:
1001
MPF_set_zero(r)
1002
else:
1003
MPF_set_nan(r)
1004
return
1005
bc = mpz_sizeinbase(r.man,2)
1006
r.special = S_NORMAL
1007
if mpz_reasonable_shift(n):
1008
m = mpz_get_si(n)
1009
if m == 0:
1010
MPF_set(r, &MPF_C_1)
1011
return
1012
if m == 1:
1013
MPF_set(r, x)
1014
MPF_normalize(r, opts)
1015
return
1016
if m == 2:
1017
MPF_mul(r, x, x, opts)
1018
return
1019
if m == -1:
1020
MPF_div(r, &MPF_C_1, x, opts)
1021
return
1022
if m == -2:
1023
MPF_mul(r, x, x, opts_exact)
1024
MPF_div(r, &MPF_C_1, r, opts)
1025
return
1026
absm = abs(m)
1027
if bc * absm < 10000:
1028
mpz_pow_ui(r.man, x.man, absm)
1029
mpz_mul_ui(r.exp, x.exp, absm)
1030
if m < 0:
1031
MPF_div(r, &MPF_C_1, r, opts)
1032
else:
1033
MPF_normalize(r, opts)
1034
return
1035
r.special = S_NORMAL
1036
# (2^p)^n
1037
if mpz_cmp_si(x.man, 1) == 0:
1038
mpz_set(r.man, x.man)
1039
mpz_mul(r.exp, x.exp, n)
1040
return
1041
# (-2^p)^n
1042
if mpz_cmp_si(x.man, -1) == 0:
1043
if mpz_odd_p(n):
1044
mpz_set(r.man, x.man)
1045
else:
1046
mpz_neg(r.man, x.man)
1047
mpz_mul(r.exp, x.exp, n)
1048
return
1049
# TODO: implement efficiently here
1050
import mpmath.libmp
1051
MPF_set_tuple(r,
1052
mpmath.libmp.mpf_pow_int(MPF_to_tuple(x), mpzi(n),
1053
opts.prec, rndmode_to_python(opts.rounding)))
1054
1055
cdef mpz_t _pi_value
1056
cdef int _pi_prec = -1
1057
1058
cdef mpz_t _ln2_value
1059
cdef int _ln2_prec = -1
1060
1061
cdef mpz_set_pi(mpz_t x, int prec):
1062
"""
1063
Set x = pi as a fixed-point number.
1064
"""
1065
global _pi_value
1066
global _pi_prec
1067
if prec <= _pi_prec:
1068
mpz_tdiv_q_2exp(x, _pi_value, _pi_prec-prec)
1069
else:
1070
from mpmath.libmp import pi_fixed
1071
if _pi_prec < 0:
1072
mpz_init(_pi_value)
1073
mpz_set_integer(_pi_value, pi_fixed(prec))
1074
mpz_set(x, _pi_value)
1075
_pi_prec = prec
1076
1077
cdef mpz_set_ln2(mpz_t x, int prec):
1078
"""
1079
Set x = ln(2) as a fixed-point number.
1080
"""
1081
global _ln2_value
1082
global _ln2_prec
1083
if prec <= _ln2_prec:
1084
mpz_tdiv_q_2exp(x, _ln2_value, _ln2_prec-prec)
1085
else:
1086
from mpmath.libmp import ln2_fixed
1087
if _ln2_prec < 0:
1088
mpz_init(_ln2_value)
1089
mpz_set_integer(_ln2_value, ln2_fixed(prec))
1090
mpz_set(x, _ln2_value)
1091
_ln2_prec = prec
1092
1093
cdef void _cy_exp_mpfr(mpz_t y, mpz_t x, int prec):
1094
"""
1095
Computes y = exp(x) for fixed-point numbers y and x using MPFR,
1096
assuming that no overflow will occur.
1097
"""
1098
cdef mpfr_t yf, xf
1099
mpfr_init2(xf, mpz_bitcount(x)+2)
1100
mpfr_init2(yf, prec+2)
1101
mpfr_set_z(xf, x, GMP_RNDN)
1102
mpfr_div_2exp(xf, xf, prec, GMP_RNDN)
1103
mpfr_exp(yf, xf, GMP_RNDN)
1104
mpfr_mul_2exp(yf, yf, prec, GMP_RNDN)
1105
mpfr_get_z(y, yf, GMP_RNDN)
1106
mpfr_clear(yf)
1107
mpfr_clear(xf)
1108
1109
cdef cy_exp_basecase(mpz_t y, mpz_t x, int prec):
1110
"""
1111
Computes y = exp(x) for fixed-point numbers y and x, assuming
1112
that x is small (|x| ~< 1). At small precisions, this function
1113
is equivalent to the exp_basecase function in
1114
mpmath.libmp.exp_fixed.
1115
"""
1116
cdef int k, r, u
1117
cdef mpz_t s0, s1, x2, a
1118
# TODO: could use custom implementation here; for now switch to MPFR
1119
if prec > 2000:
1120
_cy_exp_mpfr(y, x, prec)
1121
return
1122
mpz_init(s0)
1123
mpz_init(s1)
1124
mpz_init(x2)
1125
mpz_init(a)
1126
r = <int>fsqrt(prec)
1127
prec += r
1128
mpz_set_ui(s0, 1)
1129
mpz_mul_2exp(s0, s0, prec)
1130
mpz_set(s1, s0)
1131
k = 2
1132
mpz_mul(x2, x, x)
1133
mpz_fdiv_q_2exp(x2, x2, prec)
1134
mpz_set(a, x2)
1135
while mpz_sgn(a):
1136
mpz_fdiv_q_ui(a, a, k)
1137
mpz_add(s0, s0, a)
1138
k += 1
1139
mpz_fdiv_q_ui(a, a, k)
1140
mpz_add(s1, s1, a)
1141
k += 1
1142
mpz_mul(a, a, x2)
1143
mpz_fdiv_q_2exp(a, a, prec)
1144
mpz_mul(s1, s1, x)
1145
mpz_fdiv_q_2exp(s1, s1, prec)
1146
mpz_add(s0, s0, s1)
1147
u = r
1148
while r:
1149
mpz_mul(s0, s0, s0)
1150
mpz_fdiv_q_2exp(s0, s0, prec)
1151
r -= 1
1152
mpz_fdiv_q_2exp(y, s0, u)
1153
mpz_clear(s0)
1154
mpz_clear(s1)
1155
mpz_clear(x2)
1156
mpz_clear(a)
1157
1158
1159
cdef MPF_exp(MPF *y, MPF *x, MPopts opts):
1160
"""
1161
Set y = exp(x).
1162
"""
1163
cdef bint sign, is_int
1164
cdef long wp, wpmod, offset, mag
1165
cdef mpz_t t, u
1166
cdef tuple w
1167
if x.special:
1168
if x.special == S_ZERO: MPF_set_si(y, 1)
1169
elif x.special == S_NINF: MPF_set_zero(y)
1170
elif x.special == S_INF: MPF_set_inf(y)
1171
else: MPF_set_nan(y)
1172
return
1173
wp = opts.prec + 14
1174
sign = mpz_sgn(x.man) < 0
1175
is_int = mpz_sgn(x.exp) >= 0
1176
# note: bogus if not reasonable shift
1177
mag = mpz_bitcount(x.man) + mpz_get_si(x.exp)
1178
if (not mpz_reasonable_shift(x.exp)) or mag < -wp:
1179
if mpz_sgn(x.exp) <= 0:
1180
# perturb
1181
MPF_set_one(y)
1182
if opts.rounding != ROUND_N:
1183
mpz_mul_2exp(y.man, y.man, wp)
1184
if sign:
1185
mpz_sub_ui(y.man, y.man, 1)
1186
else:
1187
mpz_add_ui(y.man, y.man, 1)
1188
mpz_set_si(y.exp, -wp)
1189
MPF_normalize(y, opts)
1190
return
1191
else:
1192
raise OverflowError("exp of a huge number")
1193
#offset = mpz_get_si(x.exp) + wp
1194
mpz_init(t)
1195
if mag > 1:
1196
wpmod = wp + mag
1197
mpz_set_fixed(t, x, wpmod, False)
1198
mpz_init(u)
1199
mpz_set_ln2(u, wpmod)
1200
# y.exp, t = divmod(t, ln2)
1201
mpz_fdiv_qr(y.exp,t,t,u)
1202
mpz_clear(u)
1203
mpz_fdiv_q_2exp(t, t, mag)
1204
else:
1205
mpz_set_fixed(t, x, wp, False)
1206
mpz_set_ui(y.exp, 0)
1207
cy_exp_basecase(y.man, t, wp)
1208
mpz_add_si(y.exp, y.exp, -wp)
1209
y.special = S_NORMAL
1210
mpz_clear(t)
1211
MPF_normalize(y, opts)
1212
1213
1214
cdef MPF_complex_sqrt(MPF *c, MPF *d, MPF *a, MPF *b, MPopts opts):
1215
"""
1216
Set c+di = sqrt(a+bi).
1217
1218
c, a and d, b may be the same objects.
1219
"""
1220
cdef int apos, bneg
1221
cdef MPF t, u, v
1222
cdef MPopts wpopts
1223
if b.special == S_ZERO:
1224
if a.special == S_ZERO:
1225
MPF_set_zero(c)
1226
MPF_set_zero(d)
1227
# a+bi, a < 0, b = 0
1228
elif MPF_sgn(a) < 0:
1229
MPF_abs(d, a)
1230
MPF_sqrt(d, d, opts)
1231
MPF_set_zero(c)
1232
# a > 0
1233
else:
1234
MPF_sqrt(c, a, opts)
1235
MPF_set_zero(d)
1236
return
1237
wpopts.prec = opts.prec + 20
1238
wpopts.rounding = ROUND_D
1239
MPF_init(&t)
1240
MPF_init(&u)
1241
MPF_init(&v)
1242
apos = MPF_sgn(a) >= 0
1243
bneg = MPF_sgn(b) <= 0
1244
if apos:
1245
# real part
1246
MPF_hypot(&t, a, b, wpopts) #t = abs(a+bi) + a
1247
MPF_add(&t, &t, a, wpopts)
1248
MPF_set(&u, &t)
1249
mpz_sub_ui(u.exp, u.exp, 1) # u = t / 2
1250
MPF_sqrt(c, &u, opts) # re = sqrt(u)
1251
# imag part
1252
mpz_add_ui(t.exp, t.exp, 1) # t = 2*t
1253
MPF_sqrt(&u, &t, wpopts) # u = sqrt(t)
1254
MPF_div(d, b, &u, opts) # im = b / u
1255
else:
1256
MPF_set(&v, b)
1257
MPF_hypot(&t, a, b, wpopts) # t = abs(a+bi) - a
1258
MPF_sub(&t, &t, a, wpopts)
1259
MPF_set(&u, &t)
1260
mpz_sub_ui(u.exp, u.exp, 1) # u = t / 2
1261
MPF_sqrt(d, &u, opts) # im = sqrt(u)
1262
mpz_add_ui(t.exp, t.exp, 1) # t = 2*t
1263
MPF_sqrt(&u, &t, wpopts) # u = sqrt(t)
1264
MPF_div(c, &v, &u, opts) # re = b / u
1265
if bneg:
1266
MPF_neg(c, c)
1267
MPF_neg(d, d)
1268
MPF_clear(&t)
1269
MPF_clear(&u)
1270
MPF_clear(&v)
1271
1272
cdef int MPF_get_mpfr_overflow(mpfr_t y, MPF *x):
1273
"""
1274
Store the mpmath number x exactly in the MPFR variable y. The precision
1275
of y will be adjusted if necessary. If the exponent overflows, only
1276
the mantissa is stored and 1 is returned; if no overflow occurs,
1277
the function returns 0.
1278
"""
1279
cdef long prec, exp
1280
if x.special != S_NORMAL:
1281
if x.special == S_ZERO:
1282
mpfr_set_ui(y, 0, GMP_RNDN)
1283
elif x.special == S_INF:
1284
mpfr_set_inf(y, 1)
1285
elif x.special == S_NINF:
1286
mpfr_set_inf(y, -1)
1287
else:
1288
mpfr_set_nan(y)
1289
return 0
1290
prec = mpz_bitcount(x.man)
1291
# Minimum precision for MPFR
1292
if prec < 2:
1293
prec = 2
1294
mpfr_set_prec(y, prec)
1295
mpfr_set_z(y, x.man, GMP_RNDN)
1296
if mpz_reasonable_shift(x.exp):
1297
exp = mpz_get_si(x.exp)
1298
if exp >= 0:
1299
mpfr_mul_2exp(y, y, exp, GMP_RNDN)
1300
else:
1301
mpfr_div_2exp(y, y, -exp, GMP_RNDN)
1302
return 0
1303
else:
1304
return 1
1305
1306
cdef MPF_set_mpfr(MPF *y, mpfr_t x, MPopts opts):
1307
"""
1308
Convert the MPFR number x to a normalized MPF y.
1309
inf/nan and zero are handled.
1310
"""
1311
cdef long exp
1312
# TODO: use mpfr_regular_p with MPFR 3
1313
if mpfr_nan_p(x):
1314
MPF_set_nan(y)
1315
return
1316
if mpfr_inf_p(x):
1317
if mpfr_sgn(x) > 0:
1318
MPF_set_inf(y)
1319
else:
1320
MPF_set_ninf(y)
1321
return
1322
if mpfr_zero_p(x):
1323
MPF_set_zero(y)
1324
return
1325
exp = mpfr_get_z_exp(y.man, x)
1326
mpz_set_si(y.exp, exp)
1327
y.special = S_NORMAL
1328
MPF_normalize(y, opts)
1329
1330
cdef int MPF_log(MPF *y, MPF *x, MPopts opts):
1331
"""
1332
Set y = log(|x|). Returns 1 if x is negative.
1333
"""
1334
cdef MPF t
1335
cdef bint negative, overflow
1336
cdef mpfr_rnd_t rndmode
1337
cdef mpfr_t yy, xx
1338
if x.special != S_NORMAL:
1339
if x.special == S_ZERO:
1340
MPF_set_ninf(y)
1341
return 0
1342
if x.special == S_INF:
1343
MPF_set_inf(y)
1344
return 0
1345
if x.special == S_NAN:
1346
MPF_set_nan(y)
1347
return 0
1348
if x.special == S_NINF:
1349
MPF_set_inf(y)
1350
return 1
1351
1352
negative = MPF_sgn(x) < 0
1353
mpfr_init2(xx, opts.prec)
1354
mpfr_init2(yy, opts.prec)
1355
1356
overflow = MPF_get_mpfr_overflow(xx, x)
1357
rndmode = rndmode_to_mpfr(opts.rounding, mpfr_cmp_ui(xx, 1))
1358
1359
if overflow:
1360
MPF_init(&t)
1361
# Copy x exponent in case x and y are aliased
1362
mpz_set(t.exp, x.exp)
1363
1364
# log(m * 2^e) = log(m) + e*log(2)
1365
mpfr_abs(xx, xx, GMP_RNDN)
1366
mpfr_log(yy, xx, rndmode)
1367
MPF_set_mpfr(y, yy, opts)
1368
1369
mpz_set_ln2(t.man, opts.prec+20)
1370
mpz_mul(t.man, t.man, t.exp)
1371
mpz_set_si(t.exp, -(opts.prec+20))
1372
t.special = S_NORMAL
1373
1374
MPF_add(y, y, &t, opts)
1375
MPF_clear(&t)
1376
else:
1377
mpfr_abs(xx, xx, GMP_RNDN)
1378
mpfr_log(yy, xx, rndmode)
1379
MPF_set_mpfr(y, yy, opts)
1380
1381
mpfr_clear(xx)
1382
mpfr_clear(yy)
1383
return negative
1384
1385
cdef MPF_set_pi(MPF *x, MPopts opts):
1386
"""
1387
Set x = pi.
1388
"""
1389
x.special = S_NORMAL
1390
mpz_set_pi(x.man, (opts.prec+20))
1391
mpz_set_si(x.exp, -(opts.prec+20))
1392
MPF_normalize(x, opts)
1393
1394
cdef MPF_set_ln2(MPF *x, MPopts opts):
1395
"""
1396
Set x = ln(2).
1397
"""
1398
x.special = S_NORMAL
1399
mpz_set_ln2(x.man, (opts.prec+20))
1400
mpz_set_si(x.exp, -(opts.prec+20))
1401
MPF_normalize(x, opts)
1402
1403
1404
def exp_fixed(Integer x, int prec, ln2=None):
1405
"""
1406
Returns a fixed-point approximation of exp(x) where x is a fixed-point
1407
number.
1408
1409
EXAMPLES::
1410
1411
sage: from sage.libs.mpmath.ext_impl import exp_fixed
1412
sage: y = exp_fixed(1<<53, 53)
1413
sage: float(y) / 2^53
1414
2.718281828459044
1415
1416
"""
1417
cdef Integer v
1418
cdef mpz_t n, t
1419
cdef long nn
1420
mpz_init(n)
1421
mpz_init(t)
1422
if ln2 is None:
1423
mpz_set_ln2(t, prec)
1424
mpz_fdiv_qr(n, t, x.value, t)
1425
else:
1426
mpz_fdiv_qr(n, t, x.value, (<Integer>ln2).value)
1427
nn = mpz_get_si(n)
1428
v = PY_NEW(Integer)
1429
cy_exp_basecase(v.value, t, prec)
1430
if nn >= 0:
1431
mpz_mul_2exp(v.value, v.value, nn)
1432
else:
1433
mpz_fdiv_q_2exp(v.value, v.value, -nn)
1434
mpz_clear(t)
1435
mpz_clear(n)
1436
return v
1437
1438
def cos_sin_fixed(Integer x, int prec, pi2=None):
1439
"""
1440
Returns fixed-point approximations of cos(x), sin(x) where
1441
x is a fixed-point number.
1442
1443
EXAMPLES::
1444
1445
sage: from sage.libs.mpmath.ext_impl import cos_sin_fixed
1446
sage: c, s = cos_sin_fixed(1<<53, 53)
1447
sage: print float(c) / 2^53
1448
0.540302305868
1449
sage: print float(s) / 2^53
1450
0.841470984808
1451
1452
"""
1453
cdef Integer cv, sv
1454
cdef mpfr_t t, cf, sf
1455
mpfr_init2(t, mpz_bitcount(x.value)+2)
1456
mpfr_init2(cf, prec)
1457
mpfr_init2(sf, prec)
1458
mpfr_set_z(t, x.value, GMP_RNDN)
1459
mpfr_div_2exp(t, t, prec, GMP_RNDN)
1460
mpfr_sin_cos(sf, cf, t, GMP_RNDN)
1461
mpfr_mul_2exp(cf, cf, prec, GMP_RNDN)
1462
mpfr_mul_2exp(sf, sf, prec, GMP_RNDN)
1463
cv = PY_NEW(Integer)
1464
sv = PY_NEW(Integer)
1465
mpfr_get_z(cv.value, cf, GMP_RNDN)
1466
mpfr_get_z(sv.value, sf, GMP_RNDN)
1467
mpfr_clear(t)
1468
mpfr_clear(cf)
1469
mpfr_clear(sf)
1470
return cv, sv
1471
1472
DEF MAX_LOG_INT_CACHE = 2000
1473
1474
cdef mpz_t log_int_cache[MAX_LOG_INT_CACHE+1]
1475
cdef long log_int_cache_prec[MAX_LOG_INT_CACHE+1]
1476
cdef bint log_int_cache_initialized = 0
1477
1478
cdef mpz_log_int(mpz_t v, mpz_t n, int prec):
1479
"""
1480
Set v = log(n) where n is an integer and v is a fixed-point number
1481
with the specified precision.
1482
"""
1483
cdef mpfr_t f
1484
mpfr_init2(f, prec+15)
1485
mpfr_set_z(f, n, GMP_RNDN)
1486
mpfr_log(f, f, GMP_RNDN)
1487
mpfr_mul_2exp(f, f, prec, GMP_RNDN)
1488
mpfr_get_z(v, f, GMP_RNDN)
1489
mpfr_clear(f)
1490
1491
def log_int_fixed(n, long prec, ln2=None):
1492
"""
1493
Returns fixed-point approximation of log(n).
1494
1495
EXAMPLES::
1496
1497
sage: from sage.libs.mpmath.ext_impl import log_int_fixed
1498
sage: print float(log_int_fixed(5, 53)) / 2^53
1499
1.60943791243
1500
sage: print float(log_int_fixed(5, 53)) / 2^53 # exercise cache
1501
1.60943791243
1502
1503
"""
1504
global log_int_cache_initialized
1505
cdef Integer t
1506
cdef int i
1507
t = PY_NEW(Integer)
1508
mpz_set_integer(t.value, n)
1509
if mpz_sgn(t.value) <= 0:
1510
mpz_set_ui(t.value, 0)
1511
elif mpz_cmp_ui(t.value, MAX_LOG_INT_CACHE) <= 0:
1512
if not log_int_cache_initialized:
1513
for i in range(MAX_LOG_INT_CACHE+1):
1514
mpz_init(log_int_cache[i])
1515
log_int_cache_prec[i] = 0
1516
log_int_cache_initialized = 1
1517
i = mpz_get_si(t.value)
1518
if log_int_cache_prec[i] < prec:
1519
mpz_log_int(log_int_cache[i], t.value, prec+64)
1520
log_int_cache_prec[i] = prec+64
1521
mpz_tdiv_q_2exp(t.value, log_int_cache[i], log_int_cache_prec[i]-prec)
1522
1523
else:
1524
mpz_log_int(t.value, t.value, prec)
1525
return t
1526
1527
1528
cdef _MPF_cos_python(MPF *c, MPF *x, MPopts opts):
1529
"""
1530
Computes c = cos(x) by calling the mpmath.libmp Python implementation.
1531
"""
1532
from mpmath.libmp.libelefun import mpf_cos_sin
1533
ct = mpf_cos_sin(MPF_to_tuple(x), opts.prec,
1534
rndmode_to_python(opts.rounding), 1, False)
1535
MPF_set_tuple(c, ct)
1536
1537
cdef _MPF_sin_python(MPF *s, MPF *x, MPopts opts):
1538
"""
1539
Computes s = sin(x) by calling the mpmath.libmp Python implementation.
1540
"""
1541
from mpmath.libmp.libelefun import mpf_cos_sin
1542
st = mpf_cos_sin(MPF_to_tuple(x), opts.prec,
1543
rndmode_to_python(opts.rounding), 2, False)
1544
MPF_set_tuple(s, st)
1545
1546
1547
cdef MPF_cos(MPF *c, MPF *x, MPopts opts):
1548
"""
1549
Set c = cos(x)
1550
"""
1551
cdef mpfr_t cf, xf
1552
cdef bint overflow
1553
if x.special != S_NORMAL:
1554
if x.special == S_ZERO:
1555
MPF_set_one(c)
1556
else:
1557
MPF_set_nan(c)
1558
return
1559
mpfr_init(xf)
1560
mpfr_init2(cf, opts.prec)
1561
overflow = MPF_get_mpfr_overflow(xf, x)
1562
if overflow or opts.rounding == ROUND_U:
1563
_MPF_cos_python(c, x, opts)
1564
else:
1565
mpfr_cos(cf, xf, rndmode_to_mpfr(opts.rounding, 1))
1566
MPF_set_mpfr(c, cf, opts)
1567
mpfr_clear(xf)
1568
mpfr_clear(cf)
1569
1570
cdef MPF_sin(MPF *s, MPF *x, MPopts opts):
1571
"""
1572
Set s = sin(x)
1573
"""
1574
cdef mpfr_t sf, xf
1575
cdef bint overflow
1576
if x.special != S_NORMAL:
1577
if x.special == S_ZERO:
1578
MPF_set_zero(s)
1579
else:
1580
MPF_set_nan(s)
1581
return
1582
mpfr_init(xf)
1583
mpfr_init2(sf, opts.prec)
1584
overflow = MPF_get_mpfr_overflow(xf, x)
1585
if overflow or opts.rounding == ROUND_U:
1586
_MPF_sin_python(s, x, opts)
1587
else:
1588
mpfr_sin(sf, xf, rndmode_to_mpfr(opts.rounding, 1))
1589
MPF_set_mpfr(s, sf, opts)
1590
mpfr_clear(xf)
1591
mpfr_clear(sf)
1592
1593
cdef MPF_cos_sin(MPF *c, MPF *s, MPF *x, MPopts opts):
1594
"""
1595
Set c = cos(x), s = sin(x)
1596
"""
1597
cdef mpfr_t cf, sf, xf
1598
cdef bint overflow
1599
if x.special != S_NORMAL:
1600
if x.special == S_ZERO:
1601
MPF_set_one(c)
1602
MPF_set_zero(s)
1603
else:
1604
MPF_set_nan(c)
1605
MPF_set_nan(s)
1606
return
1607
mpfr_init(xf)
1608
mpfr_init2(sf, opts.prec)
1609
mpfr_init2(cf, opts.prec)
1610
overflow = MPF_get_mpfr_overflow(xf, x)
1611
if overflow or opts.rounding == ROUND_U:
1612
_MPF_cos_python(c, x, opts)
1613
_MPF_sin_python(s, x, opts)
1614
else:
1615
mpfr_sin_cos(sf, cf, xf, rndmode_to_mpfr(opts.rounding, 1))
1616
MPF_set_mpfr(s, sf, opts)
1617
MPF_set_mpfr(c, cf, opts)
1618
mpfr_clear(xf)
1619
mpfr_clear(cf)
1620
mpfr_clear(sf)
1621
1622
1623
cdef MPF_complex_exp(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts):
1624
"""
1625
Set re+im*i = exp(a+bi)
1626
"""
1627
cdef MPF mag, c, s
1628
cdef MPopts wopts
1629
if a.special == S_ZERO:
1630
MPF_cos_sin(re, im, b, opts)
1631
return
1632
if b.special == S_ZERO:
1633
MPF_exp(re, a, opts)
1634
MPF_set_zero(im)
1635
return
1636
MPF_init(&mag)
1637
MPF_init(&c)
1638
MPF_init(&s)
1639
wopts = opts
1640
wopts.prec += 4
1641
MPF_exp(&mag, a, wopts)
1642
MPF_cos_sin(&c, &s, b, wopts)
1643
MPF_mul(re, &mag, &c, opts)
1644
MPF_mul(im, &mag, &s, opts)
1645
MPF_clear(&mag)
1646
MPF_clear(&c)
1647
MPF_clear(&s)
1648
1649
cdef int MPF_pow(MPF *z, MPF *x, MPF *y, MPopts opts):
1650
"""
1651
Set z = x^y for real x and y and returns 0 if the result is real-valued.
1652
If the result is complex, does nothing and returns 1.
1653
"""
1654
cdef MPopts wopts
1655
cdef mpz_t t
1656
cdef MPF w
1657
cdef int xsign, ysign
1658
cdef mpz_t tm
1659
1660
# Integer exponentiation, if reasonable
1661
if y.special == S_NORMAL and mpz_sgn(y.exp) >= 0:
1662
mpz_init(tm)
1663
# check if size is reasonable
1664
mpz_add_ui(tm, y.exp, mpz_bitcount(y.man))
1665
mpz_abs(tm, tm)
1666
if mpz_cmp_ui(tm, 10000) < 0:
1667
# man * 2^exp
1668
mpz_mul_2exp(tm, y.man, mpz_get_ui(y.exp))
1669
MPF_pow_int(z, x, tm, opts)
1670
mpz_clear(tm)
1671
return 0
1672
mpz_clear(tm)
1673
1674
# x ^ 0
1675
if y.special == S_ZERO:
1676
if x.special == S_NORMAL or x.special == S_ZERO:
1677
MPF_set_one(z)
1678
else:
1679
MPF_set_nan(z)
1680
return 0
1681
1682
xsign = MPF_sgn(x)
1683
ysign = MPF_sgn(y)
1684
1685
if xsign < 0:
1686
return 1
1687
1688
# Square root or integer power thereof
1689
if y.special == S_NORMAL and mpz_cmp_si(y.exp, -1) == 0:
1690
# x^(1/2)
1691
if mpz_cmp_ui(y.man, 1) == 0:
1692
MPF_sqrt(z, x, opts)
1693
return 0
1694
# x^(-1/2)
1695
if mpz_cmp_si(y.man, -1) == 0:
1696
wopts = opts
1697
wopts.prec += 10
1698
wopts.rounding = reciprocal_rnd(wopts.rounding)
1699
MPF_sqrt(z, x, wopts)
1700
MPF_div(z, &MPF_C_1, z, opts)
1701
return 0
1702
# x^(n/2)
1703
wopts = opts
1704
wopts.prec += 10
1705
if mpz_sgn(y.man) < 0:
1706
wopts.rounding = reciprocal_rnd(wopts.rounding)
1707
mpz_init_set(t, y.man)
1708
MPF_sqrt(z, x, wopts)
1709
MPF_pow_int(z, z, t, opts)
1710
mpz_clear(t)
1711
return 0
1712
1713
if x.special != S_NORMAL or y.special != S_NORMAL:
1714
if x.special == S_NAN or y.special == S_NAN:
1715
MPF_set_nan(z)
1716
return 0
1717
if y.special == S_ZERO:
1718
if x.special == S_NORMAL or x.special == S_ZERO:
1719
MPF_set_one(z)
1720
else:
1721
MPF_set_nan(z)
1722
return 0
1723
if x.special == S_ZERO and y.special == S_NORMAL:
1724
if mpz_sgn(y.man) > 0:
1725
MPF_set_zero(z)
1726
return 0
1727
1728
wopts = opts
1729
wopts.prec += 10
1730
MPF_init(&w)
1731
MPF_log(&w, x, wopts)
1732
MPF_mul(&w, &w, y, opts_exact)
1733
MPF_exp(z, &w, opts)
1734
MPF_clear(&w)
1735
return 0
1736
1737
cdef MPF_complex_square(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts):
1738
"""
1739
Set re+im*i = (a+bi)^2 = a^2-b^2, 2ab*i.
1740
"""
1741
cdef MPF t, u
1742
MPF_init(&t)
1743
MPF_init(&u)
1744
MPF_mul(&t,a,a,opts_exact)
1745
MPF_mul(&u,b,b,opts_exact)
1746
MPF_sub(re, &t, &u, opts)
1747
MPF_mul(im, a, b, opts)
1748
if im.special == S_NORMAL:
1749
mpz_add_ui(im.exp, im.exp, 1)
1750
MPF_clear(&t)
1751
MPF_clear(&u)
1752
1753
1754
cdef MPF_complex_reciprocal(MPF *re, MPF *im, MPF *a, MPF *b, MPopts opts):
1755
"""
1756
Set re+im*i = 1/(a+bi), i.e. compute the reciprocal of
1757
a complex number.
1758
"""
1759
cdef MPopts wopts
1760
cdef MPF t, u, m
1761
wopts = opts
1762
wopts.prec += 10
1763
MPF_init(&t)
1764
MPF_init(&u)
1765
MPF_init(&m)
1766
MPF_mul(&t, a, a,opts_exact)
1767
MPF_mul(&u, b, b,opts_exact)
1768
MPF_add(&m, &t, &u,wopts)
1769
MPF_div(&t, a, &m, opts)
1770
MPF_div(&u, b, &m, opts)
1771
MPF_set(re, &t)
1772
MPF_neg(im, &u)
1773
MPF_clear(&t)
1774
MPF_clear(&u)
1775
MPF_clear(&m)
1776
1777
1778
cdef MPF_complex_pow_int(MPF *zre, MPF *zim, MPF *xre, MPF *xim, mpz_t n, MPopts opts):
1779
"""
1780
Set zre+zim*i = (xre+xim) ^ n, i.e. raise a complex number to an integer power.
1781
"""
1782
cdef MPopts wopts
1783
cdef long m
1784
1785
if xim.special == S_ZERO:
1786
MPF_pow_int(zre, xre, n, opts)
1787
MPF_set_zero(zim)
1788
return
1789
1790
if xre.special == S_ZERO:
1791
# n % 4
1792
m = mpz_get_si(n) % 4
1793
if m == 0:
1794
MPF_pow_int(zre, xim, n, opts)
1795
MPF_set_zero(zim)
1796
return
1797
if m == 1:
1798
MPF_set_zero(zre)
1799
MPF_pow_int(zim, xim, n, opts)
1800
return
1801
if m == 2:
1802
MPF_pow_int(zre, xim, n, opts)
1803
MPF_neg(zre, zre)
1804
MPF_set_zero(zim)
1805
return
1806
if m == 3:
1807
MPF_set_zero(zre)
1808
MPF_pow_int(zim, xim, n, opts)
1809
MPF_neg(zim, zim)
1810
return
1811
1812
if mpz_reasonable_shift(n):
1813
m = mpz_get_si(n)
1814
if m == 0:
1815
MPF_set_one(zre)
1816
MPF_set_zero(zim)
1817
return
1818
if m == 1:
1819
MPF_pos(zre, xre, opts)
1820
MPF_pos(zim, xim, opts)
1821
return
1822
if m == 2:
1823
MPF_complex_square(zre, zim, xre, xim, opts)
1824
return
1825
if m == -1:
1826
MPF_complex_reciprocal(zre, zim, xre, xim, opts)
1827
return
1828
if m == -2:
1829
wopts = opts
1830
wopts.prec += 10
1831
MPF_complex_square(zre, zim, xre, xim, wopts)
1832
MPF_complex_reciprocal(zre, zim, zre, zim, opts)
1833
return
1834
1835
xret = MPF_to_tuple(xre)
1836
ximt = MPF_to_tuple(xim)
1837
from mpmath.libmp import mpc_pow_int
1838
vr, vi = mpc_pow_int((xret, ximt), mpzi(n), \
1839
opts.prec, rndmode_to_python(opts.rounding))
1840
MPF_set_tuple(zre, vr)
1841
MPF_set_tuple(zim, vi)
1842
1843
1844
cdef MPF_complex_pow_re(MPF *zre, MPF *zim, MPF *xre, MPF *xim, MPF *y, MPopts opts):
1845
"""
1846
Set (zre+zim*i) = (xre+xim*i) ^ y, i.e. raise a complex number
1847
to a real power.
1848
"""
1849
1850
cdef mpz_t tm
1851
cdef MPopts wopts
1852
1853
if y.special == S_ZERO:
1854
if xre.special == S_NORMAL and xim.special == S_NORMAL:
1855
# x ^ 0
1856
MPF_set_one(zre)
1857
MPF_set_zero(zim)
1858
return
1859
1860
wopts = opts
1861
wopts.prec += 10
1862
1863
if y.special == S_NORMAL:
1864
# Integer
1865
if mpz_cmp_ui(y.exp, 0) >= 0 and mpz_reasonable_shift(y.exp):
1866
mpz_init_set(tm, y.man)
1867
mpz_mul_2exp(tm, tm, mpz_get_ui(y.exp))
1868
MPF_complex_pow_int(zre, zim, xre, xim, tm, opts)
1869
mpz_clear(tm)
1870
return
1871
# x ^ (n/2)
1872
if mpz_cmp_si(y.exp, -1) == 0:
1873
mpz_init_set(tm, y.man)
1874
MPF_complex_sqrt(zre, zim, xre, xim, wopts)
1875
MPF_complex_pow_int(zre, zim, zre, zim, tm, opts)
1876
mpz_clear(tm)
1877
return
1878
1879
xret = MPF_to_tuple(xre)
1880
ximt = MPF_to_tuple(xim)
1881
yret = MPF_to_tuple(y)
1882
from mpmath.libmp import mpc_pow_mpf, fzero
1883
vr, vi = mpc_pow_mpf((xret, ximt), yret, \
1884
opts.prec, rndmode_to_python(opts.rounding))
1885
MPF_set_tuple(zre, vr)
1886
MPF_set_tuple(zim, vi)
1887
1888
1889
cdef MPF_complex_pow(MPF *zre, MPF *zim, MPF *xre, MPF *xim, MPF *yre, MPF *yim, MPopts opts):
1890
"""
1891
Set (zre + zim*i) = (xre+xim*i) ^ (yre+yim*i).
1892
"""
1893
if yim.special == S_ZERO:
1894
MPF_complex_pow_re(zre, zim, xre, xim, yre, opts)
1895
return
1896
xret = MPF_to_tuple(xre)
1897
ximt = MPF_to_tuple(xim)
1898
yret = MPF_to_tuple(yre)
1899
yimt = MPF_to_tuple(yim)
1900
from mpmath.libmp import mpc_pow
1901
vr, vi = mpc_pow((xret,ximt), (yret,yimt), \
1902
opts.prec, rndmode_to_python(opts.rounding))
1903
MPF_set_tuple(zre, vr)
1904
MPF_set_tuple(zim, vi)
1905
1906
1907
cdef mpz_set_tuple_fixed(mpz_t x, tuple t, long prec):
1908
"""
1909
Set the integer x to a fixed-point number with specified precision
1910
and the value of t = (sign,man,exp,bc). Truncating division is used
1911
if the value cannot be represented exactly.
1912
"""
1913
cdef long offset
1914
sign, man, exp, bc = t
1915
mpz_set_integer(x, man)
1916
if sign:
1917
mpz_neg(x, x)
1918
offset = exp + prec
1919
if offset >= 0:
1920
mpz_mul_2exp(x, x, offset)
1921
else:
1922
mpz_tdiv_q_2exp(x, x, -offset)
1923
1924
cdef mpz_set_complex_tuple_fixed(mpz_t x, mpz_t y, tuple t, long prec):
1925
"""
1926
Set the integers (x,y) to fixed-point numbers with the values of
1927
the mpf pair t = ((xsign,xman,xexp,xbc), (ysign,yman,yexp,ybc)).
1928
"""
1929
mpz_set_tuple_fixed(x, t[0], prec)
1930
mpz_set_tuple_fixed(y, t[1], prec)
1931
1932
cdef MPF_set_fixed(MPF *x, mpz_t man, long wp, long prec, int rnd):
1933
"""
1934
Set value of an MPF given a fixed-point mantissa of precision wp,
1935
rounding to the given precision and rounding mode.
1936
"""
1937
cdef MPopts opts
1938
opts.prec = prec
1939
opts.rounding = rnd
1940
x.special = S_NORMAL
1941
mpz_set(x.man, man)
1942
mpz_set_si(x.exp, -wp)
1943
MPF_normalize(x, opts)
1944
1945
# TODO: we should allocate these dynamically
1946
DEF MAX_PARAMS = 128
1947
cdef mpz_t AINT[MAX_PARAMS]
1948
cdef mpz_t BINT[MAX_PARAMS]
1949
cdef mpz_t AP[MAX_PARAMS]
1950
cdef mpz_t AQ[MAX_PARAMS]
1951
cdef mpz_t BP[MAX_PARAMS]
1952
cdef mpz_t BQ[MAX_PARAMS]
1953
cdef mpz_t AREAL[MAX_PARAMS]
1954
cdef mpz_t BREAL[MAX_PARAMS]
1955
cdef mpz_t ACRE[MAX_PARAMS]
1956
cdef mpz_t ACIM[MAX_PARAMS]
1957
cdef mpz_t BCRE[MAX_PARAMS]
1958
cdef mpz_t BCIM[MAX_PARAMS]
1959
1960
1961
1962
cdef MPF_hypsum(MPF *a, MPF *b, int p, int q, param_types, str ztype, coeffs, z,
1963
long prec, long wp, long epsshift, dict magnitude_check, kwargs):
1964
"""
1965
Evaluates a+bi = pFq(..., z) by summing the hypergeometric
1966
series in fixed-point arithmetic.
1967
1968
This basically a Cython version of
1969
mpmath.libmp.libhyper.make_hyp_summator(). It should produce identical
1970
results (the calculations are exactly the same, and the same rounding
1971
is used for divisions).
1972
1973
This function is not intended to be called directly; it is wrapped
1974
by the hypsum_internal function in ext_main.pyx.
1975
1976
"""
1977
cdef long i, j, k, n, p_mag, cancellable_real, MAX, magn
1978
cdef int have_complex_param, have_complex_arg, have_complex
1979
1980
cdef mpz_t SRE, SIM, PRE, PIM, ZRE, ZIM, TRE, TIM, URE, UIM, MUL, DIV, HIGH, LOW, one
1981
# Count number of parameters
1982
cdef int aint, bint, arat, brat, areal, breal, acomplex, bcomplex
1983
cdef int have_multiplier
1984
1985
if p >= MAX_PARAMS or q >= MAX_PARAMS:
1986
raise NotImplementedError("too many hypergeometric function parameters")
1987
1988
have_complex_param = 'C' in param_types
1989
have_complex_arg = ztype == 'C'
1990
have_complex = have_complex_param or have_complex_arg
1991
1992
mpz_init(one)
1993
mpz_init(SRE)
1994
mpz_init(SIM)
1995
mpz_init(PRE)
1996
mpz_init(PIM)
1997
mpz_init(ZRE)
1998
mpz_init(ZIM)
1999
mpz_init(MUL)
2000
mpz_init(DIV)
2001
mpz_init(HIGH)
2002
mpz_init(LOW)
2003
mpz_init(TRE)
2004
mpz_init(TIM)
2005
mpz_init(URE)
2006
mpz_init(UIM)
2007
2008
aint = bint = arat = brat = areal = breal = acomplex = bcomplex = 0
2009
2010
MAX = kwargs.get('maxterms', wp*100)
2011
mpz_set_ui(HIGH, 1)
2012
mpz_mul_2exp(HIGH, HIGH, epsshift)
2013
mpz_neg(LOW, HIGH)
2014
2015
mpz_set_ui(one, 1)
2016
mpz_mul_2exp(one, one, wp)
2017
mpz_set(SRE, one)
2018
mpz_set(PRE, one)
2019
2020
# Copy input data to mpzs
2021
if have_complex_arg:
2022
mpz_set_complex_tuple_fixed(ZRE, ZIM, z, wp)
2023
else:
2024
mpz_set_tuple_fixed(ZRE, z, wp)
2025
for i in range(0,p):
2026
if param_types[i] == 'Z':
2027
mpz_init(AINT[aint])
2028
mpz_set_integer(AINT[aint], coeffs[i])
2029
aint += 1
2030
elif param_types[i] == 'Q':
2031
mpz_init(AP[arat])
2032
mpz_init(AQ[arat])
2033
__p, __q = coeffs[i]._mpq_
2034
mpz_set_integer(AP[arat], __p)
2035
mpz_set_integer(AQ[arat], __q)
2036
arat += 1
2037
elif param_types[i] == 'R':
2038
mpz_init(AREAL[areal])
2039
mpz_set_tuple_fixed(AREAL[areal], coeffs[i]._mpf_, wp)
2040
areal += 1
2041
elif param_types[i] == 'C':
2042
mpz_init(ACRE[acomplex])
2043
mpz_init(ACIM[acomplex])
2044
mpz_set_complex_tuple_fixed(ACRE[acomplex], ACIM[acomplex], coeffs[i]._mpc_, wp)
2045
acomplex += 1
2046
else:
2047
raise ValueError
2048
for i in range(p,p+q):
2049
if param_types[i] == 'Z':
2050
mpz_init(BINT[bint])
2051
mpz_set_integer(BINT[bint], coeffs[i])
2052
bint += 1
2053
elif param_types[i] == 'Q':
2054
mpz_init(BP[brat])
2055
mpz_init(BQ[brat])
2056
__p, __q = coeffs[i]._mpq_
2057
mpz_set_integer(BP[brat], __p)
2058
mpz_set_integer(BQ[brat], __q)
2059
brat += 1
2060
elif param_types[i] == 'R':
2061
mpz_init(BREAL[breal])
2062
mpz_set_tuple_fixed(BREAL[breal], coeffs[i]._mpf_, wp)
2063
breal += 1
2064
elif param_types[i] == 'C':
2065
mpz_init(BCRE[bcomplex])
2066
mpz_init(BCIM[bcomplex])
2067
mpz_set_complex_tuple_fixed(BCRE[bcomplex], BCIM[bcomplex], coeffs[i]._mpc_, wp)
2068
bcomplex += 1
2069
else:
2070
raise ValueError
2071
2072
cancellable_real = min(areal, breal)
2073
2074
# Main loop
2075
for n in range(1, 10**8):
2076
2077
if n in magnitude_check:
2078
p_mag = mpz_bitcount(PRE)
2079
if have_complex:
2080
p_mag = max(p_mag, mpz_bitcount(PIM))
2081
magnitude_check[n] = wp - p_mag
2082
2083
# Update rational part of product
2084
mpz_set_ui(MUL, 1)
2085
mpz_set_ui(DIV, n)
2086
2087
for i in range(aint): mpz_mul(MUL, MUL, AINT[i])
2088
for i in range(arat): mpz_mul(MUL, MUL, AP[i])
2089
for i in range(brat): mpz_mul(MUL, MUL, BQ[i])
2090
for i in range(bint): mpz_mul(DIV, DIV, BINT[i])
2091
for i in range(brat): mpz_mul(DIV, DIV, BP[i])
2092
for i in range(arat): mpz_mul(DIV, DIV, AQ[i])
2093
2094
# Check for singular terms
2095
if mpz_sgn(DIV) == 0:
2096
if mpz_sgn(MUL) == 0:
2097
break
2098
raise ZeroDivisionError
2099
2100
# Multiply real factors
2101
for k in range(0, cancellable_real):
2102
mpz_mul(PRE, PRE, AREAL[k])
2103
mpz_fdiv_q(PRE, PRE, BREAL[k])
2104
for k in range(cancellable_real, areal):
2105
mpz_mul(PRE, PRE, AREAL[k])
2106
mpz_fdiv_q_2exp(PRE, PRE, wp)
2107
for k in range(cancellable_real, breal):
2108
mpz_mul_2exp(PRE, PRE, wp)
2109
mpz_fdiv_q(PRE, PRE, BREAL[k])
2110
if have_complex:
2111
for k in range(0, cancellable_real):
2112
mpz_mul(PIM, PIM, AREAL[k])
2113
mpz_fdiv_q(PIM, PIM, BREAL[k])
2114
for k in range(cancellable_real, areal):
2115
mpz_mul(PIM, PIM, AREAL[k])
2116
mpz_fdiv_q_2exp(PIM, PIM, wp)
2117
for k in range(cancellable_real, breal):
2118
mpz_mul_2exp(PIM, PIM, wp)
2119
mpz_fdiv_q(PIM, PIM, BREAL[k])
2120
2121
# Update product
2122
if have_complex:
2123
if have_complex_arg:
2124
# PRE = ((mul*(PRE*ZRE-PIM*ZIM))//div)>>wp
2125
# PIM = ((mul*(PIM*ZRE+PRE*ZIM))//div)>>wp
2126
mpz_mul(TRE, PRE, ZRE)
2127
mpz_submul(TRE, PIM, ZIM)
2128
mpz_mul(TRE, TRE, MUL)
2129
2130
mpz_mul(TIM, PIM, ZRE)
2131
mpz_addmul(TIM, PRE, ZIM)
2132
mpz_mul(TIM, TIM, MUL)
2133
2134
mpz_fdiv_q(PRE, TRE, DIV)
2135
mpz_fdiv_q_2exp(PRE, PRE, wp)
2136
2137
mpz_fdiv_q(PIM, TIM, DIV)
2138
mpz_fdiv_q_2exp(PIM, PIM, wp)
2139
else:
2140
mpz_mul(PRE, PRE, MUL)
2141
mpz_mul(PRE, PRE, ZRE)
2142
mpz_fdiv_q_2exp(PRE, PRE, wp)
2143
mpz_fdiv_q(PRE, PRE, DIV)
2144
2145
mpz_mul(PIM, PIM, MUL)
2146
mpz_mul(PIM, PIM, ZRE)
2147
mpz_fdiv_q_2exp(PIM, PIM, wp)
2148
mpz_fdiv_q(PIM, PIM, DIV)
2149
2150
for i in range(acomplex):
2151
mpz_mul(TRE, PRE, ACRE[i])
2152
mpz_submul(TRE, PIM, ACIM[i])
2153
mpz_mul(TIM, PIM, ACRE[i])
2154
mpz_addmul(TIM, PRE, ACIM[i])
2155
mpz_fdiv_q_2exp(PRE, TRE, wp)
2156
mpz_fdiv_q_2exp(PIM, TIM, wp)
2157
2158
for i in range(bcomplex):
2159
mpz_mul(URE, BCRE[i], BCRE[i])
2160
mpz_addmul(URE, BCIM[i], BCIM[i])
2161
mpz_mul(TRE, PRE, BCRE[i])
2162
mpz_addmul(TRE, PIM, BCIM[i])
2163
mpz_mul(TIM, PIM, BCRE[i])
2164
mpz_submul(TIM, PRE, BCIM[i])
2165
mpz_mul_2exp(PRE, TRE, wp)
2166
mpz_fdiv_q(PRE, PRE, URE)
2167
mpz_mul_2exp(PIM, TIM, wp)
2168
mpz_fdiv_q(PIM, PIM, URE)
2169
else:
2170
mpz_mul(PRE, PRE, MUL)
2171
mpz_mul(PRE, PRE, ZRE)
2172
mpz_fdiv_q_2exp(PRE, PRE, wp)
2173
mpz_fdiv_q(PRE, PRE, DIV)
2174
2175
# Add product to sum
2176
if have_complex:
2177
mpz_add(SRE, SRE, PRE)
2178
mpz_add(SIM, SIM, PIM)
2179
if mpz_cmpabs(PRE, HIGH) < 0 and mpz_cmpabs(PIM, HIGH) < 0:
2180
break
2181
else:
2182
mpz_add(SRE, SRE, PRE)
2183
if mpz_cmpabs(PRE, HIGH) < 0:
2184
break
2185
2186
if n > MAX:
2187
from mpmath.libmp import NoConvergence
2188
raise NoConvergence('Hypergeometric series converges too slowly. Try increasing maxterms.')
2189
2190
# +1 all parameters for next iteration
2191
for i in range(aint): mpz_add_ui(AINT[i], AINT[i], 1)
2192
for i in range(bint): mpz_add_ui(BINT[i], BINT[i], 1)
2193
for i in range(arat): mpz_add(AP[i], AP[i], AQ[i])
2194
for i in range(brat): mpz_add(BP[i], BP[i], BQ[i])
2195
for i in range(areal): mpz_add(AREAL[i], AREAL[i], one)
2196
for i in range(breal): mpz_add(BREAL[i], BREAL[i], one)
2197
for i in range(acomplex): mpz_add(ACRE[i], ACRE[i], one)
2198
for i in range(bcomplex): mpz_add(BCRE[i], BCRE[i], one)
2199
2200
# Done
2201
if have_complex:
2202
MPF_set_fixed(a, SRE, wp, prec, ROUND_N)
2203
MPF_set_fixed(b, SIM, wp, prec, ROUND_N)
2204
if mpz_sgn(SRE):
2205
if mpz_sgn(SIM):
2206
magn = max(mpz_get_si(a.exp) + <long>mpz_bitcount(a.man),
2207
mpz_get_si(b.exp) + <long>mpz_bitcount(b.man))
2208
else:
2209
magn = mpz_get_si(a.exp) + <long>mpz_bitcount(a.man)
2210
elif mpz_sgn(SIM):
2211
magn = mpz_get_si(b.exp) + <long>mpz_bitcount(b.man)
2212
else:
2213
magn = -wp
2214
else:
2215
MPF_set_fixed(a, SRE, wp, prec, ROUND_N)
2216
if mpz_sgn(SRE):
2217
magn = mpz_get_si(a.exp) + <long>mpz_bitcount(a.man)
2218
else:
2219
magn = -wp
2220
2221
mpz_clear(one)
2222
mpz_clear(SRE)
2223
mpz_clear(SIM)
2224
mpz_clear(PRE)
2225
mpz_clear(PIM)
2226
mpz_clear(ZRE)
2227
mpz_clear(ZIM)
2228
mpz_clear(MUL)
2229
mpz_clear(DIV)
2230
mpz_clear(HIGH)
2231
mpz_clear(LOW)
2232
mpz_clear(TRE)
2233
mpz_clear(TIM)
2234
mpz_clear(URE)
2235
mpz_clear(UIM)
2236
2237
for i in range(aint): mpz_clear(AINT[i])
2238
for i in range(bint): mpz_clear(BINT[i])
2239
for i in range(arat):
2240
mpz_clear(AP[i])
2241
mpz_clear(AQ[i])
2242
for i in range(brat):
2243
mpz_clear(BP[i])
2244
mpz_clear(BQ[i])
2245
for i in range(areal): mpz_clear(AREAL[i])
2246
for i in range(breal): mpz_clear(BREAL[i])
2247
for i in range(acomplex):
2248
mpz_clear(ACRE[i])
2249
mpz_clear(ACIM[i])
2250
for i in range(bcomplex):
2251
mpz_clear(BCRE[i])
2252
mpz_clear(BCIM[i])
2253
2254
return have_complex, magn
2255
2256