mpmath 0.2__zip → 0.4__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mpmath-0.4/CHANGES +52 -0
- {mpmath-0.2 → mpmath-0.4}/PKG-INFO +1 -1
- {mpmath-0.2 → mpmath-0.4}/README +58 -8
- {mpmath-0.2 → mpmath-0.4}/demo/pidigits.py +10 -16
- mpmath-0.4/mpmath/__init__.py +3 -0
- mpmath-0.4/mpmath/functions2.py +384 -0
- mpmath-0.4/mpmath/lib/__init__.py +7 -0
- mpmath-0.4/mpmath/lib/complexop.py +181 -0
- mpmath-0.4/mpmath/lib/constants.py +212 -0
- mpmath-0.4/mpmath/lib/convert.py +233 -0
- mpmath-0.4/mpmath/lib/floatop.py +252 -0
- mpmath-0.4/mpmath/lib/functions.py +350 -0
- mpmath-0.4/mpmath/lib/squareroot.py +199 -0
- mpmath-0.4/mpmath/lib/util.py +268 -0
- mpmath-0.4/mpmath/mpmath.py +739 -0
- {mpmath-0.2 → mpmath-0.4}/setup.py +2 -2
- mpmath-0.4/tests/benchmark.py +139 -0
- mpmath-0.4/tests/runtests.py +5 -0
- mpmath-0.4/tests/test_bitwise.py +110 -0
- mpmath-0.4/tests/test_compatibility.py +51 -0
- mpmath-0.4/tests/test_convert.py +62 -0
- mpmath-0.4/tests/test_division.py +126 -0
- mpmath-0.4/tests/test_functions2.py +68 -0
- mpmath-0.4/tests/test_hp.py +199 -0
- {mpmath-0.2 → mpmath-0.4}/tests/test_mpmath.py +137 -166
- mpmath-0.2/CHANGES +0 -23
- mpmath-0.2/mpmath/__init__.py +0 -2
- mpmath-0.2/mpmath/lib.py +0 -1122
- mpmath-0.2/mpmath/mpmath.py +0 -515
- {mpmath-0.2 → mpmath-0.4}/LICENSE +0 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Arithmetic operations and functions on complex numbers, represented on
|
|
3
|
+
rectangular form as tuples of real floating-point numbers.
|
|
4
|
+
|
|
5
|
+
This module is quite compact, since most of the dirty work can be
|
|
6
|
+
delegated to functions that work on real numbers.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from util import *
|
|
10
|
+
from floatop import *
|
|
11
|
+
from functions import *
|
|
12
|
+
from squareroot import *
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Use fastest rounding mode for intermediate calculations
|
|
16
|
+
RF = ROUND_FLOOR
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
#----------------------------------------------------------------------
|
|
20
|
+
# Complex parts
|
|
21
|
+
#
|
|
22
|
+
|
|
23
|
+
def fcabs(a, b, prec, rounding):
|
|
24
|
+
"""
|
|
25
|
+
Absolute value of a complex number, |a+bi|. Returns a single
|
|
26
|
+
real number.
|
|
27
|
+
"""
|
|
28
|
+
return fhypot(a, b, prec, rounding)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
#----------------------------------------------------------------------
|
|
32
|
+
# Arithmetic
|
|
33
|
+
#
|
|
34
|
+
|
|
35
|
+
def fcmul(a, b, c, d, prec, rounding):
|
|
36
|
+
"""
|
|
37
|
+
Complex multiplication.
|
|
38
|
+
|
|
39
|
+
Returns the real and imaginary part of (a+bi)*(c+di), rounded to
|
|
40
|
+
the specified precision. The rounding mode applies to the real and
|
|
41
|
+
imaginary parts separately.
|
|
42
|
+
|
|
43
|
+
Implemented the straightforward way. TODO: use a more stable
|
|
44
|
+
algorithm to avoid cancellation.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
# All-real case
|
|
48
|
+
if b == d == fzero:
|
|
49
|
+
return fmul(a, c, prec, rounding), fzero
|
|
50
|
+
|
|
51
|
+
ep = prec + 10
|
|
52
|
+
|
|
53
|
+
re = fsub(fmul(a,c, ep, RF), fmul(b,d, ep, RF), prec, rounding)
|
|
54
|
+
im = fadd(fmul(a,d, ep, RF), fmul(b,c, ep, RF), prec, rounding)
|
|
55
|
+
return re, im
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
#----------------------------------------------------------------------
|
|
59
|
+
# Square root
|
|
60
|
+
#
|
|
61
|
+
|
|
62
|
+
def fcsqrt(a, b, prec, rounding):
|
|
63
|
+
"""
|
|
64
|
+
Complex square root (principal branch).
|
|
65
|
+
|
|
66
|
+
We have sqrt(a+bi) = sqrt((r+a)/2) + b/sqrt(2*(r+a))*i where
|
|
67
|
+
r = abs(a+bi), when a+bi is not a negative real number.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
if a == b == fzero:
|
|
71
|
+
return (a, b)
|
|
72
|
+
|
|
73
|
+
# When a+bi is a negative real number, we get a real sqrt times i
|
|
74
|
+
if a[0] < 0 and b == fzero:
|
|
75
|
+
im = fsqrt(fneg_exact(a), prec, rounding)
|
|
76
|
+
return (fzero, im)
|
|
77
|
+
|
|
78
|
+
ep = prec+20
|
|
79
|
+
|
|
80
|
+
t = fadd(fcabs(a, b, ep, RF), a, ep, RF) # t = abs(a+bi) + a
|
|
81
|
+
u = fmul(t, fhalf, ep, RF) # u = t / 2
|
|
82
|
+
re = fsqrt(u, prec, rounding) # re = sqrt(u)
|
|
83
|
+
v = fmul(t, ftwo, ep, RF) # v = t * 2
|
|
84
|
+
w = fsqrt(v, ep, RF) # w = sqrt(v)
|
|
85
|
+
im = fdiv(b, w, prec, rounding) # im = b / w
|
|
86
|
+
|
|
87
|
+
return re, im
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
#----------------------------------------------------------------------
|
|
91
|
+
# Exp and log
|
|
92
|
+
#
|
|
93
|
+
|
|
94
|
+
def fcexp(a, b, prec, rounding):
|
|
95
|
+
"""
|
|
96
|
+
Complex exponential function.
|
|
97
|
+
|
|
98
|
+
We use the direct formula exp(a+bi) = exp(a) * (cos(b) + sin(b)*i)
|
|
99
|
+
for the computation. This formula is very nice because it is
|
|
100
|
+
perfectly stable; since we just do real multiplications, the only
|
|
101
|
+
numerical errors that can creep in are single-ulp rounding errors.
|
|
102
|
+
|
|
103
|
+
The formula is efficient since mpmath's real exp is quite fast and
|
|
104
|
+
since we can compute cos and sin simultaneously.
|
|
105
|
+
|
|
106
|
+
It is no problem if a and b are large; if the implementations of
|
|
107
|
+
exp/cos/sin are accurate and efficient for all real numbers, then
|
|
108
|
+
so is this function for all complex numbers.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
mag = fexp(a, prec+4, rounding)
|
|
112
|
+
|
|
113
|
+
c, s = cos_sin(b, prec+4, rounding)
|
|
114
|
+
|
|
115
|
+
re = fmul(mag, c, prec, rounding)
|
|
116
|
+
im = fmul(mag, s, prec, rounding)
|
|
117
|
+
return re, im
|
|
118
|
+
|
|
119
|
+
# TODO: log
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
#----------------------------------------------------------------------
|
|
123
|
+
# Trigonometric functions
|
|
124
|
+
#
|
|
125
|
+
|
|
126
|
+
def fccos(a, b, prec, rounding):
|
|
127
|
+
"""
|
|
128
|
+
Complex cosine.
|
|
129
|
+
|
|
130
|
+
The formula used is cos(a+bi) = cos(a)*cosh(b) - sin(a)*sinh(b)*i.
|
|
131
|
+
|
|
132
|
+
The same comments apply as for the complex exp: only real
|
|
133
|
+
multiplications are performed, so no cancellation errors are
|
|
134
|
+
possible. The formula is also efficient since we can compute both
|
|
135
|
+
pairs (cos, sin) and (cosh, sinh) in single steps.
|
|
136
|
+
"""
|
|
137
|
+
ep = prec + 6
|
|
138
|
+
|
|
139
|
+
c, s = cos_sin(a, ep, RF)
|
|
140
|
+
ch, sh = cosh_sinh(b, ep, RF)
|
|
141
|
+
|
|
142
|
+
re = fmul(c, ch, prec, rounding)
|
|
143
|
+
im = fmul(s, sh, prec, rounding)
|
|
144
|
+
|
|
145
|
+
return re, fneg_exact(im)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def fcsin(a, b, prec, rounding):
|
|
149
|
+
"""
|
|
150
|
+
Complex sine.
|
|
151
|
+
|
|
152
|
+
We have sin(a+bi) = sin(a)*cosh(b) + cos(a)*sinh(b)*i.
|
|
153
|
+
See the docstring for fccos for additional comments.
|
|
154
|
+
"""
|
|
155
|
+
ep = prec + 6
|
|
156
|
+
|
|
157
|
+
c, s = cos_sin(a, ep, RF)
|
|
158
|
+
ch, sh = cosh_sinh(b, ep, RF)
|
|
159
|
+
|
|
160
|
+
re = fmul(s, ch, prec, rounding)
|
|
161
|
+
im = fmul(c, sh, prec, rounding)
|
|
162
|
+
|
|
163
|
+
return re, im
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# TODO: complex tan
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
#----------------------------------------------------------------------
|
|
170
|
+
# Hyperbolic functions
|
|
171
|
+
#
|
|
172
|
+
|
|
173
|
+
def fccosh(a, b, prec, rounding):
|
|
174
|
+
"""Complex hyperbolic cosine. Computed as cosh(z) = cos(z*i)."""
|
|
175
|
+
return fccos(b, fneg_exact(a), prec, rounding)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def fcsinh(a, b, prec, rounding):
|
|
179
|
+
"""Complex hyperbolic sine. Computed as sinh(z) = -i*sin(z*i)."""
|
|
180
|
+
b, a = fcsin(b, a, prec, rounding)
|
|
181
|
+
return a, b
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Mathematical constants
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import math
|
|
7
|
+
|
|
8
|
+
from util import *
|
|
9
|
+
from floatop import *
|
|
10
|
+
from squareroot import *
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def constant_memo(f):
|
|
14
|
+
"""
|
|
15
|
+
Memoization for calculation of constants using fixed-point
|
|
16
|
+
arithmetic. Only store the value computed with highest precision;
|
|
17
|
+
if a lower or equal precision is requested later, the result can
|
|
18
|
+
be generated directly through downshifting the cached value.
|
|
19
|
+
"""
|
|
20
|
+
f.memo_prec = -1
|
|
21
|
+
f.memo_val = None
|
|
22
|
+
|
|
23
|
+
def g(prec):
|
|
24
|
+
if prec == f.memo_prec:
|
|
25
|
+
return f.memo_val
|
|
26
|
+
if prec < f.memo_prec:
|
|
27
|
+
return f.memo_val >> (f.memo_prec-prec)
|
|
28
|
+
f.memo_val = f(prec)
|
|
29
|
+
f.memo_prec = prec
|
|
30
|
+
return f.memo_val
|
|
31
|
+
|
|
32
|
+
g.__name__ = f.__name__
|
|
33
|
+
g.__doc__ = f.__doc__
|
|
34
|
+
return g
|
|
35
|
+
|
|
36
|
+
def acot(n, prec, hyperbolic):
|
|
37
|
+
"""
|
|
38
|
+
Compute acot of an integer using fixed-point arithmetic. With
|
|
39
|
+
hyperbolic=True, compute acoth. We use the series expansion
|
|
40
|
+
|
|
41
|
+
1 1 1
|
|
42
|
+
acot(n) = --- - ---- + ---- - ...,
|
|
43
|
+
3 5
|
|
44
|
+
n 3 n 5 n
|
|
45
|
+
|
|
46
|
+
optimized for integer arguments. In the hyperbolic case, all
|
|
47
|
+
negative terms are changed to positive ones.
|
|
48
|
+
"""
|
|
49
|
+
s = t = (1 << prec) // n # 1 / n
|
|
50
|
+
k = 3
|
|
51
|
+
while 1:
|
|
52
|
+
# Repeatedly divide by k * n**2, and add
|
|
53
|
+
t //= (n*n)
|
|
54
|
+
term = t // k
|
|
55
|
+
if not term:
|
|
56
|
+
break
|
|
57
|
+
# Alternate signs
|
|
58
|
+
if hyperbolic or not k & 2:
|
|
59
|
+
s += term
|
|
60
|
+
else:
|
|
61
|
+
s -= term
|
|
62
|
+
k += 2
|
|
63
|
+
return s
|
|
64
|
+
|
|
65
|
+
def machin(coefs, prec, hyperbolic=False):
|
|
66
|
+
"""
|
|
67
|
+
Evaluate a Machin-like formula, i.e., a linear combination of
|
|
68
|
+
acot(n) or acoth(n) for specific integer values of n, using fixed-
|
|
69
|
+
point arithmetic.
|
|
70
|
+
|
|
71
|
+
The input should be a list [(c, n), ...], giving c*acot[h](n) + ...
|
|
72
|
+
"""
|
|
73
|
+
extraprec = 10
|
|
74
|
+
s = 0
|
|
75
|
+
for a, b in coefs:
|
|
76
|
+
s += a * acot(b, prec+extraprec, hyperbolic)
|
|
77
|
+
return (s >> extraprec)
|
|
78
|
+
|
|
79
|
+
def agm_status(prec, step, adiff, verbose_base):
|
|
80
|
+
logdiff = math.log(max(1, adiff), verbose_base)
|
|
81
|
+
digits = int(prec/math.log(verbose_base,2) - logdiff)
|
|
82
|
+
print " iteration", step, ("(accuracy ~= %i base-%i digits)" % \
|
|
83
|
+
(digits, verbose_base))
|
|
84
|
+
|
|
85
|
+
def pi_agm(prec, verbose=False, verbose_base=10):
|
|
86
|
+
"""
|
|
87
|
+
Compute floor(pi * 2**prec) as a big integer using the Brent-
|
|
88
|
+
Salamin algorithm based on the arithmetic-geometric mean.
|
|
89
|
+
|
|
90
|
+
See for example Wikipedia (http://en.wikipedia.org/wiki/Brent-
|
|
91
|
+
Salamin_algorithm) or "Pi and the AGM" by Jonathan and Peter
|
|
92
|
+
Borwein (Wiley, 1987). The algorithm (as stated in the Wikipedia
|
|
93
|
+
article) consists of setting
|
|
94
|
+
|
|
95
|
+
a_0 = 1
|
|
96
|
+
b_0 = 1/sqrt(2)
|
|
97
|
+
t_0 = 1/4
|
|
98
|
+
p_0 = 1
|
|
99
|
+
|
|
100
|
+
and computing
|
|
101
|
+
|
|
102
|
+
a_{n+1} = (a_n + b_n)/2
|
|
103
|
+
b_{n+1} = sqrt(a_n * b_n)
|
|
104
|
+
t_{n+1} = t_n - p_n*(a_n - a_{n+1})**2
|
|
105
|
+
p_{n+1} = 2*p_n
|
|
106
|
+
|
|
107
|
+
for n = 0, 1, 2, 3, ..., after which the approximation is given by
|
|
108
|
+
pi ~= (a_n + b_n)**2 / (4*t_n). Each step roughly doubles the
|
|
109
|
+
number of correct digits.
|
|
110
|
+
"""
|
|
111
|
+
extraprec = 50
|
|
112
|
+
prec += extraprec
|
|
113
|
+
|
|
114
|
+
# Initialial values. a, b and t are fixed-point numbers
|
|
115
|
+
a = 1 << prec
|
|
116
|
+
b = sqrt_fixed2(a >> 1, prec)
|
|
117
|
+
t = a >> 2
|
|
118
|
+
p = 1
|
|
119
|
+
|
|
120
|
+
step = 1
|
|
121
|
+
while 1:
|
|
122
|
+
an = (a + b) >> 1
|
|
123
|
+
adiff = a - an
|
|
124
|
+
if verbose:
|
|
125
|
+
agm_status(prec, step, adiff, verbose_base)
|
|
126
|
+
# No change in a
|
|
127
|
+
if p > 16 and abs(adiff) < 1000:
|
|
128
|
+
break
|
|
129
|
+
prod = (a * b) >> prec
|
|
130
|
+
b = sqrt_fixed2(prod, prec)
|
|
131
|
+
t = t - p*((adiff**2) >> prec)
|
|
132
|
+
p = 2*p
|
|
133
|
+
a = an
|
|
134
|
+
step += 1
|
|
135
|
+
if verbose:
|
|
136
|
+
print " final division"
|
|
137
|
+
pi = ((((a+b)**2) >> 2) // t)
|
|
138
|
+
return pi >> extraprec
|
|
139
|
+
|
|
140
|
+
@constant_memo
|
|
141
|
+
def pi_fixed(prec):
|
|
142
|
+
"""
|
|
143
|
+
Compute floor(pi * 2**prec) as a big integer.
|
|
144
|
+
|
|
145
|
+
For low precisions, Machin's formula pi = 16*acot(5)-4*acot(239)
|
|
146
|
+
is used. For high precisions, the more efficient arithmetic-
|
|
147
|
+
geometric mean iteration is used.
|
|
148
|
+
"""
|
|
149
|
+
if prec < 10000:
|
|
150
|
+
return machin([(16, 5), (-4, 239)], prec)
|
|
151
|
+
else:
|
|
152
|
+
return pi_agm(prec)
|
|
153
|
+
|
|
154
|
+
def fpi(prec, rounding):
|
|
155
|
+
"""Compute a floating-point approximation of pi"""
|
|
156
|
+
return normalize(pi_fixed(prec+5), -prec-5, prec, rounding)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# Logarithms of integers can be computed easily using
|
|
160
|
+
# Machin-like formulas
|
|
161
|
+
|
|
162
|
+
@constant_memo
|
|
163
|
+
def log2_fixed(prec):
|
|
164
|
+
return machin([(18, 26), (-2, 4801), (8, 8749)], prec, True)
|
|
165
|
+
|
|
166
|
+
def flog2(prec, rounding):
|
|
167
|
+
return normalize(log2_fixed(prec+5), -prec-5, prec, rounding)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@constant_memo
|
|
171
|
+
def log10_fixed(prec):
|
|
172
|
+
return machin([(46, 31), (34, 49), (20, 161)], prec, True)
|
|
173
|
+
|
|
174
|
+
def flog10(prec, rounding):
|
|
175
|
+
return normalize(log10_fixed(prec+5), -prec-5, prec, rounding)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
"""
|
|
179
|
+
Euler's constant (gamma) is computed using the Brent-McMillan formula,
|
|
180
|
+
gamma ~= A(n)/B(n) - log(n), where
|
|
181
|
+
|
|
182
|
+
A(n) = sum_{k=0,1,2,...} (n**k / k!)**2 * H(k)
|
|
183
|
+
B(n) = sum_{k=0,1,2,...} (n**k / k!)**2
|
|
184
|
+
H(k) = 1 + 1/2 + 1/3 + ... + 1/k
|
|
185
|
+
|
|
186
|
+
The error is bounded by O(exp(-4n)). Choosing n to be a power
|
|
187
|
+
of two, 2**p, the logarithm becomes particularly easy to calculate.
|
|
188
|
+
|
|
189
|
+
Reference:
|
|
190
|
+
Xavier Gourdon & Pascal Sebah, The Euler constant: gamma
|
|
191
|
+
http://numbers.computation.free.fr/Constants/Gamma/gamma.pdf
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
@constant_memo
|
|
195
|
+
def gamma_fixed(prec):
|
|
196
|
+
prec += 30
|
|
197
|
+
# choose p such that exp(-4*(2**p)) < 2**-n
|
|
198
|
+
p = int(math.log((prec/4) * math.log(2), 2)) + 1
|
|
199
|
+
n = 1<<p
|
|
200
|
+
r = one = 1<<prec
|
|
201
|
+
H, A, B, npow, k, d = 0, 0, 0, 1, 1, 1
|
|
202
|
+
while r:
|
|
203
|
+
A += (r * H) >> prec
|
|
204
|
+
B += r
|
|
205
|
+
r = r * (n*n) // (k*k)
|
|
206
|
+
H += one // k
|
|
207
|
+
k += 1
|
|
208
|
+
S = ((A<<prec) // B) - p*log2_fixed(prec)
|
|
209
|
+
return S >> 30
|
|
210
|
+
|
|
211
|
+
def fgamma(prec, rounding):
|
|
212
|
+
return normalize(gamma_fixed(prec+5), -prec-5, prec, rounding)
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Functions for converting between raw mpmath floating-point numbers and
|
|
3
|
+
other types and number representations (int, float, str...).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from util import *
|
|
7
|
+
from floatop import *
|
|
8
|
+
from constants import flog2, flog10
|
|
9
|
+
import math
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
#----------------------------------------------------------------------
|
|
13
|
+
# Strings
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
def to_digits_exp(s, dps):
|
|
17
|
+
"""
|
|
18
|
+
Helper function for representing the floating-point number s as a
|
|
19
|
+
decimal with dps places. Returns (sign, string, exponent)
|
|
20
|
+
containing '' or '-', the decimal digits as a string, and an
|
|
21
|
+
integer for the decimal exponent.
|
|
22
|
+
|
|
23
|
+
If inexact, the decimal representation is rounded toward zero.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
# Extract sign so it doesn't mess up the string digit count
|
|
27
|
+
sign = ''
|
|
28
|
+
if s[0] < 0:
|
|
29
|
+
sign = '-'
|
|
30
|
+
s = fabs(s, s[2], ROUND_FLOOR)
|
|
31
|
+
man, exp, bc = s
|
|
32
|
+
|
|
33
|
+
if not man:
|
|
34
|
+
return '', '0', 0
|
|
35
|
+
|
|
36
|
+
bitprec = int(dps * math.log(10,2)) + 10
|
|
37
|
+
|
|
38
|
+
# Cut down to size
|
|
39
|
+
# TODO: account for precision when doing this
|
|
40
|
+
exp_from_1 = exp + bc
|
|
41
|
+
if abs(exp) > 500:
|
|
42
|
+
# Set b = int(exp * log(2)/log(10))
|
|
43
|
+
# If exp is huge, we must use high-precision arithmetic to
|
|
44
|
+
# find the nearest power of ten
|
|
45
|
+
expprec = bitcount(exp) + 5
|
|
46
|
+
RF = ROUND_FLOOR
|
|
47
|
+
tmp = from_int(exp, expprec, RF)
|
|
48
|
+
tmp = fmul(tmp, flog2(expprec, RF), expprec, RF)
|
|
49
|
+
tmp = fdiv(tmp, flog10(expprec, RF), expprec, RF)
|
|
50
|
+
b = to_int(tmp)
|
|
51
|
+
s = fdiv(s, fpow(ften, b, bitprec, RF), bitprec, RF)
|
|
52
|
+
man, exp, bc = s
|
|
53
|
+
exponent = b
|
|
54
|
+
else:
|
|
55
|
+
exponent = 0
|
|
56
|
+
|
|
57
|
+
# First, calculate mantissa digits by converting to a binary
|
|
58
|
+
# fixed-point number and then converting that number to
|
|
59
|
+
# a decimal fixed-point number.
|
|
60
|
+
fixprec = max(bitprec - exp, 0)
|
|
61
|
+
fixdps = int(fixprec / math.log(10,2) + 0.5)
|
|
62
|
+
sf = make_fixed(s, fixprec)
|
|
63
|
+
sd = bin_to_radix(sf, fixprec, 10, fixdps)
|
|
64
|
+
digits = numeral(sd, base=10, size=dps)
|
|
65
|
+
|
|
66
|
+
exponent += len(digits) - fixdps - 1
|
|
67
|
+
return sign, digits, exponent
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def to_str(s, dps):
|
|
71
|
+
"""Convert a raw mpf to a decimal floating-point literal with at
|
|
72
|
+
most `dps` decimal digits in the mantissa (not counting extra zeros
|
|
73
|
+
that may be inserted for visual purposes).
|
|
74
|
+
|
|
75
|
+
The literal is formatted so that it can be parsed back to a number
|
|
76
|
+
by to_str, float() or Decimal()."""
|
|
77
|
+
|
|
78
|
+
# to_digits_exp rounds to floor.
|
|
79
|
+
# This sometimes kills some instances of "...00001"
|
|
80
|
+
sign, digits, exponent = to_digits_exp(s, dps+3)
|
|
81
|
+
|
|
82
|
+
# Rounding up kills some instances of "...99999"
|
|
83
|
+
if len(digits) > dps and digits[dps] in '56789':
|
|
84
|
+
digits2 = str(int(digits[:dps]) + 1)
|
|
85
|
+
if len(digits2) > dps:
|
|
86
|
+
digits2 = digits2[:dps]
|
|
87
|
+
exponent += 1
|
|
88
|
+
digits = digits2
|
|
89
|
+
else:
|
|
90
|
+
digits = digits[:dps]
|
|
91
|
+
|
|
92
|
+
# Prettify numbers close to unit magnitude
|
|
93
|
+
if -(dps//3) < exponent < dps:
|
|
94
|
+
if exponent < 0:
|
|
95
|
+
digits = ("0"*(-exponent)) + digits
|
|
96
|
+
split = 1
|
|
97
|
+
else:
|
|
98
|
+
split = exponent + 1
|
|
99
|
+
exponent = 0
|
|
100
|
+
else:
|
|
101
|
+
split = 1
|
|
102
|
+
|
|
103
|
+
digits = (digits[:split] + "." + digits[split:])
|
|
104
|
+
|
|
105
|
+
# Clean up trailing zeros
|
|
106
|
+
digits = digits.rstrip('0')
|
|
107
|
+
if digits[-1] == ".":
|
|
108
|
+
digits += "0"
|
|
109
|
+
|
|
110
|
+
if exponent == 0: return sign + digits
|
|
111
|
+
if exponent > 0: return sign + digits + "e+" + str(exponent)
|
|
112
|
+
if exponent < 0: return sign + digits + "e" + str(exponent)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def str_to_man_exp(x, base=10):
|
|
116
|
+
# Verify that the input is a valid float literal
|
|
117
|
+
float(x)
|
|
118
|
+
# Split into mantissa, exponent
|
|
119
|
+
x = x.lower()
|
|
120
|
+
parts = x.split('e')
|
|
121
|
+
if len(parts) == 1:
|
|
122
|
+
exp = 0
|
|
123
|
+
else: # == 2
|
|
124
|
+
x = parts[0]
|
|
125
|
+
exp = int(parts[1])
|
|
126
|
+
# Look for radix point in mantissa
|
|
127
|
+
parts = x.split('.')
|
|
128
|
+
if len(parts) == 2:
|
|
129
|
+
a, b = parts[0], parts[1].rstrip('0')
|
|
130
|
+
exp -= len(b)
|
|
131
|
+
x = a + b
|
|
132
|
+
x = int(x, base)
|
|
133
|
+
return x, exp
|
|
134
|
+
|
|
135
|
+
def from_str(x, prec, rounding):
|
|
136
|
+
"""Create a raw mpf from a decimal literal, rounding in the
|
|
137
|
+
specified direction if the input number cannot be represented
|
|
138
|
+
exactly as a binary floating-point number with the given number of
|
|
139
|
+
bits. The literal syntax accepted is the same as for Python
|
|
140
|
+
floats.
|
|
141
|
+
|
|
142
|
+
TODO: the rounding does not work properly for large exponents.
|
|
143
|
+
"""
|
|
144
|
+
man, exp = str_to_man_exp(x, base=10)
|
|
145
|
+
|
|
146
|
+
# XXX: appropriate cutoffs & track direction
|
|
147
|
+
# note no factors of 5
|
|
148
|
+
if abs(exp) > 400:
|
|
149
|
+
s = from_int(man, prec+10, ROUND_FLOOR)
|
|
150
|
+
s = fmul(s, fpow(ften, exp, prec+10, ROUND_FLOOR), prec, rounding)
|
|
151
|
+
else:
|
|
152
|
+
if exp >= 0:
|
|
153
|
+
s = from_int(man * 10**exp, prec, rounding)
|
|
154
|
+
else:
|
|
155
|
+
s = from_rational(man, 10**-exp, prec, rounding)
|
|
156
|
+
return s
|
|
157
|
+
|
|
158
|
+
# Binary string conversion. These are currently mainly used for debugging
|
|
159
|
+
# and could use some improvement in the future
|
|
160
|
+
|
|
161
|
+
def from_bstr(x):
|
|
162
|
+
man, exp = str_to_man_exp(x, base=2)
|
|
163
|
+
return normalize(man, exp, bitcount(man), ROUND_FLOOR)
|
|
164
|
+
|
|
165
|
+
def to_bstr(x):
|
|
166
|
+
man, exp, bc = x
|
|
167
|
+
return numeral(man, size=bitcount(man), base=2) + ("e%i" % exp)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
#----------------------------------------------------------------------
|
|
171
|
+
# Integers
|
|
172
|
+
#
|
|
173
|
+
|
|
174
|
+
def from_int(n, prec, rounding):
|
|
175
|
+
"""Create a raw mpf from an integer, rounding if necessary."""
|
|
176
|
+
return normalize(n, 0, prec, rounding)
|
|
177
|
+
|
|
178
|
+
def from_int_exact(n):
|
|
179
|
+
"""Create a raw mpf from an integer, automatically choosing the
|
|
180
|
+
precision high enough to represent the integer exactly."""
|
|
181
|
+
t = trailing_zeros(n)
|
|
182
|
+
n >>= t
|
|
183
|
+
return (n, t, bitcount(n))
|
|
184
|
+
|
|
185
|
+
def to_int(s):
|
|
186
|
+
"""Convert a raw mpf to the nearest int, rounding down."""
|
|
187
|
+
man, exp, bc = s
|
|
188
|
+
return rshift(man, -exp, ROUND_DOWN)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
#----------------------------------------------------------------------
|
|
192
|
+
# Regular python floats
|
|
193
|
+
#
|
|
194
|
+
|
|
195
|
+
def from_float(x, prec, rounding):
|
|
196
|
+
"""Create a raw mpf from a Python float, rounding if necessary.
|
|
197
|
+
If prec >= 53, the result is guaranteed to represent exactly the
|
|
198
|
+
same number as the input."""
|
|
199
|
+
m, e = math.frexp(x)
|
|
200
|
+
return normalize(int(m*(1<<53)), e-53, prec, rounding)
|
|
201
|
+
|
|
202
|
+
def to_float(s):
|
|
203
|
+
"""Convert a raw mpf to a Python float. The result is exact if the
|
|
204
|
+
bitcount of s is <= 53 and no underflow/overflow occurs. An
|
|
205
|
+
OverflowError is raised if the number is too large to be
|
|
206
|
+
represented as a regular float."""
|
|
207
|
+
man, exp, bc = s
|
|
208
|
+
try:
|
|
209
|
+
return math.ldexp(man, exp)
|
|
210
|
+
except OverflowError:
|
|
211
|
+
# Try resizing the mantissa. Overflow may still happen here.
|
|
212
|
+
n = bc - 53
|
|
213
|
+
m = man >> n
|
|
214
|
+
return math.ldexp(m, exp + n)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
#----------------------------------------------------------------------
|
|
218
|
+
# Rational numbers (for use by other libraries)
|
|
219
|
+
#
|
|
220
|
+
|
|
221
|
+
def from_rational(p, q, prec, rounding):
|
|
222
|
+
"""Create a raw mpf from a rational number p/q, rounding if
|
|
223
|
+
necessary."""
|
|
224
|
+
return fdiv(from_int_exact(p), from_int_exact(q), prec, rounding)
|
|
225
|
+
|
|
226
|
+
def to_rational(s):
|
|
227
|
+
"""Convert a raw mpf to a rational number. Return integers (p, q)
|
|
228
|
+
such that s = p/q exactly. p and q are not reduced to lowest terms."""
|
|
229
|
+
man, exp, bc = s
|
|
230
|
+
if exp > 0:
|
|
231
|
+
return man * 2**exp, 1
|
|
232
|
+
else:
|
|
233
|
+
return man, 2**-exp
|